plasma_plots
Type part of a name or a dotted path
Plots and diagnostics of labeled xarray data from plasma simulations, such as Struphy’s output.
plasma-plots adds accessors to the objects Struphy returns; you rarely call a function directly:
out.plotandout.analysison a StruphyOutput: whole-run plots and diagnostics.array.plasma.plot,.analysisand.dataon everyxarray.DataArray, e.g. a product fromout.evaluate("em_fields/phi").dataset.plasma.plot,.analysisand.dataon marker Datasets such as orbits.
Creating a Struphy Output loads plasma-plots, so its output needs no import. For xarray data
from elsewhere, import plasma_plots first; without it, .plasma raises
AttributeError: 'DataArray' object has no attribute 'plasma'.
Printing an accessor lists its methods (print(phi.plasma.plot)), and help() on a method
shows every parameter (help(phi.plasma.plot.slice)). plasma-plots guide (or
python -m plasma_plots guide) prints this guide, plasma-plots api an index of every method and
function with its signature. The plasma-plots command also saves figures from the shell, e.g.
plasma-plots plot sim_1 em_fields/phi slice t=-1 eta3=0 -o phi.png or
plasma-plots quicklook sim_1 -o figures/ (plasma-plots --help).
Classes
| Name | Description |
|---|---|
PlasmaAccessor | Struphy diagnostics of one array: array.plasma.plot, .analysis and .data. |
SkippedPlot | What a plot returns on MPI ranks other than 0, where nothing is drawn. |
Functions
| Name | Description |
|---|---|
figure | Compose several plots into one figure, drawn with Matplotlib, or as one Plotly or TikZ figure. |
from_desc | Evaluate DESC quantities on a grid, as a Dataset in plasma-plots' conventions. |
from_gvec | Return GVEC evaluations in plasma-plots' conventions; see plasma_plots.gvec. |
get_backend | Return the backend of plots that do not pass backend= themselves. |
is_plotting_rank | Tell whether this process draws plots and writes their files. |
mpi_rank | Return this process' rank in MPI_COMM_WORLD, without initializing MPI. |
save_figure | Save a figure in several formats at once, as <name>.<format>. |
set_backend | Set the backend of every plot that does not pass backend= itself. |
Modules
accessorsThe .plasma accessor: plots, diagnostics and plot data of a single labeled array or dataset.analysisNumerical diagnostics returning values and labeled arrays, without rendering.arraysSmall xarray metadata helpers used by plasma_plots.cliThe plasma-plots command: quick looks at simulation output without writing Python.descEvaluate DESC equilibria into Datasets in plasma-plots' conventions.fieldline_plotsPlots of traced field lines, from plasma_plots.fieldlines.fieldlinesMagnetic field lines on the mapped grid, traced, cut, classified and sampled along.figuresSeveral plots in one figure, with any backend: plasma_plots.figure(...).galleryOutput helpers of the struphy-hub example gallery: figure files, profiling exports and metadata.gvecRead GVEC's evaluation Datasets in plasma-plots' conventions.mpiPlot on MPI rank 0 only.output_accessorsPlots and diagnostics of a whole run, as out.plot and out.analysis.plotly_backendInteractive Plotly versions of the plots: backend="plotly".plottingSmall, composable plotting functions for labeled Struphy output.pyvista_plotsThree-dimensional PyVista views of labeled Struphy output.spectralFourier and spectral diagnostics of labeled arrays, computed on demand.spectral_plotsPlots of the spectral diagnostics in plasma_plots.spectral.theoryAnalytic theory to compare Struphy runs against.tikz_backendLaTeX versions of the plots, as TikZ/pgfplots code: backend="tikz".
PlasmaAccessorclass#
plasma_plots.accessorsView sourceclass PlasmaAccessor(array: xr.DataArray)Struphy diagnostics of one array: array.plasma.plot, .analysis and .data.
Registered on every xarray.DataArray when plasma_plots is imported. A GVEC
evaluation is read in plasma-plots’ conventions first (see plasma_plots.gvec.from_gvec()).
Examples
>>> import plasma_plots>>> phi.plasma.plot.slice(x="eta1", y="eta2", t=-1)analysisproperty#
analysis: 'ArrayAnalysis'Diagnostics of this array, e.g. array.plasma.analysis.growth_rate().
dataproperty#
data: 'ArrayData'The data behind each plot, without rendering it.
E.g. for a different plotting library: array.plasma.data.slice(x="eta1", y="v1", t=-1).
plotproperty#
plot: 'ArrayPlots'Plots of this array, e.g. array.plasma.plot.slice(x="eta1", y="v1", t=-1).
SkippedPlotclass#
plasma_plots.mpiView sourceclass SkippedPlot(name: str, rank: int)What a plot returns on MPI ranks other than 0, where nothing is drawn.
Any public attribute or call returns the same object, so plot(...).save(path),
plotter.show() or animation.save(path) run on every rank but act only on rank 0. It is
false and iterates as empty, like the (empty) list of files it wrote.
Parameters
Examples
>>> skipped = SkippedPlot("plot_slice", rank=1)>>> skipped.save("slice.png").fig is skipped # nothing is writtenTrue>>> list(skipped), bool(skipped)([], False)figurefunction#
plasma_plots.figuresView sourcedef figure(nrows: int = 1, ncols: int = 1, *, backend: str | None = None, sharex: bool | str = False, sharey: bool | str = False, figsize=None, title: str | None = None, **options) -> FigureCompose several plots into one figure, drawn with Matplotlib, or as one Plotly or TikZ figure.
Use it as a with block: every plot method given ax=fig[i] draws into panel i;
at the end of the block the figure is finished, and with backend="plotly" or
backend="tikz" converted once.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
nrows | int | 1 | The number of rows of panels. Default: 1. |
ncols | int | 1 | The number of columns of panels. Default: 1. |
backend | ('matplotlib', 'plotly', 'tikz') | "matplotlib" | Finish the figure as a Matplotlib figure, as an interactive Plotly figure, or as a
TikZ/pgfplots figure for LaTeX. Default: the one set with plasma_plots.set_backend(),
"matplotlib" unless changed. |
sharex | bool or {'row', 'col', 'all'} | False | Share the horizontal axes (and their zoom, in Plotly), as for matplotlib.pyplot.subplots.
Default: False. |
sharey | bool or {'row', 'col', 'all'} | False | Share the vertical axes. Default: False. |
figsize | (float, float) | None | The size in inches. Default: from the number of panels. |
title | str | None | A title above all panels. Default: none. |
**options | {} | Passed on to matplotlib.pyplot.subplots, e.g. gridspec_kw={"height_ratios": [3, 1]}. |
Returns
Figure- The figure; index it for the panels’ axes, and save or show it after the block.
Examples
>>> with plasma_plots.figure(2, 1, sharex=True, backend="plotly") as fig:... energy.plasma.plot.timeseries(fit=(0.0, 5.0), ax=fig[0])... drift.plasma.plot.timeseries(logy=True, ax=fig[1])>>> fig.save("energies.html")>>> fig.results[0].fit_results[0].ratefrom_descfunction#
plasma_plots.descView sourcedef from_desc(eq, names: str | Sequence[str], *, rho: int | float | Sequence[float] = 11, theta: int | float | Sequence[float] = 32, zeta: int | float | Sequence[float] = 24, sfl: str | None = None) -> xr.DatasetEvaluate DESC quantities on a grid, as a Dataset in plasma-plots’ conventions.
See plasma_plots.desc for what the Dataset contains.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
eq | desc.equilibrium.Equilibrium | required | The equilibrium, e.g. desc.io.load("eq.h5") or desc.examples.get("W7-X"). |
names | str or sequence of str | required | DESC’s names of the quantities ("|B|", "iota", "sqrt(g)", "B", "J",
"p", "D_Mercier", "V", …; see DESC’s list of variables). "theta_PEST"
becomes the coordinate theta_P. Quantities that are not scalars, profiles, fields or
3-vectors (such as "grad(B)") are not supported, nor "x": the position is X,
Y, Z. |
rho | int, float or sequence of float | 11 | The flux surfaces: an integer as that many points from 0 to 1, a float or a sequence as the values. Default: 11 points. |
theta | int, float or sequence of float | 32 | The poloidal angles (PEST angles with sfl="pest"): an integer as that many points
over [0, 2π), else the values. Default: 32 points. |
zeta | int, float or sequence of float | 24 | The toroidal angles: an integer as that many points over one field period
[0, 2π/nfp), else the values, which may cover the whole torus. Default: 24 points. |
sfl | (None, 'pest') | None | "pest" for a grid in the straight-field-line PEST angle theta_P (DESC’s own
theta becomes a coordinate, found by eq.map_coordinates) rather than in DESC’s poloidal
angle. Default: None. |
Returns
xarray.Dataset- The quantities over
rho,theta(ortheta_P) andzeta, vectors alongcomponent, with the coordinatesX,Y,Z, labels, units, the angles’periodand thenfpattribute.
Raises
ValueError- For an unknown
sfl, a name DESC doesn’t know, a quantity of an unsupported shape or a coordinate triplet such as"x".
Examples
>>> ev = from_desc(eq, ["|B|", "iota", "sqrt(g)"], rho=11, theta=64, zeta=40)>>> ev["|B|"].plasma.plot.panels(... sweep="zeta", coords="physical", plane="RZ", nrows=1, ncols=3... )>>> pest = from_desc(eq, "|B|", rho=[0.5], theta=64, zeta=48, sfl="pest")>>> pest["|B|"].plasma.plot.slice(x="zeta", y="theta_P", rho=0.5)from_gvecfunction#
plasma_plots.gvecView sourcedef from_gvec(data: xr.DataArray | xr.Dataset, *, nfp: int | None = None) -> xr.DataArray | xr.DatasetReturn GVEC evaluations in plasma-plots’ conventions; see plasma_plots.gvec.
Data that is not in GVEC’s layout (see is_gvec()) comes back with only the steps that
apply, so calling it twice is harmless.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
data | xarray.Dataset or xarray.DataArray | required | A Dataset from state.evaluate(...), state.evaluate_sfl(...) or gvec.Evaluations
(also after to_netcdf and open_dataset), or one of its variables. |
nfp | int | None | The number of field periods. Default: the N_FP variable (evaluate "N_FP" with the
rest), else an nfp attribute, else from a toroidal grid that spans one field period
uniformly (GVEC’s default grid); without one, the toroidal angle gets no period. |
Returns
xarray.Dataset or xarray.DataArray- The same data, of the same type, with the dimensions
rho,theta/theta_B/theta_P,zeta/zeta_Bandcomponent, the coordinatesX,Y,Z(frompos),X1,X2, labels from thesymbolattributes, the angles’periodand thenfpattribute.
Examples
>>> ev = from_gvec(... state.evaluate("mod_B", "pos", "N_FP", rho=11, theta=32, zeta=24)... )>>> ev.mod_B.plasma.plot.panels(... sweep="zeta", coords="physical", plane="RZ", nrows=1, ncols=3... )>>> boozer = from_gvec(... state.evaluate_sfl(... "mod_B", "pos", rho=[0.5], theta=32, zeta=24, sfl="boozer"... )... )>>> boozer.mod_B.plasma.plot.slice(x="zeta_B", y="theta_B", rho=0.5)get_backendfunction#
plasma_plots.plotly_backendView sourcedef get_backend() -> strReturn the backend of plots that do not pass backend= themselves.
Returns
str"matplotlib"(the default),"plotly"or"tikz".
is_plotting_rankfunction#
plasma_plots.mpiView sourcedef is_plotting_rank() -> boolTell whether this process draws plots and writes their files.
Returns
boolTrueon rank 0 of an MPI job and in any process outside one.
mpi_rankfunction#
plasma_plots.mpiView sourcedef mpi_rank() -> intReturn this process’ rank in MPI_COMM_WORLD, without initializing MPI.
The rank comes from mpi4py if the application has already initialized MPI, otherwise from
the per-rank variables MPI launchers export. STRUPHY_MPI=0 makes every process rank 0.
Returns
int- The rank, or 0 outside an MPI job.
Examples
>>> mpi_rank() # in a serial run0save_figurefunction#
plasma_plots.plottingView sourcedef save_figure(figure, name, *, formats=('html', 'png', 'plotly.json'), show: bool = False, frame: int | None = None, still=None, width: int = 1100, height: int = 650, scale: float = 2.0) -> list[str]Save a figure in several formats at once, as <name>.<format>.
The defaults write an interactive page, an image and the figure JSON of a Plotly figure: the
three files a web page needs. Like PlotResult.save(), this does nothing on MPI ranks
other than 0.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
figure | (PlotResult, Figure, plotly.graph_objects.Figure or matplotlib.figure.Figure) | required | What to save: the result of a plot (e.g. with backend="plotly"), a figure of
plasma_plots.figure(), or a figure made some other way. |
name | str or pathlib.Path | required | The files’ path without the format, e.g. "maxwell-wave" or "figures/energy". |
formats | sequence of str | ('html', 'png', 'plotly.json') | The formats, each appended to name after a dot; the last extension picks how it is
written, as in PlotResult.save(). Default: ("html", "png", "plotly.json"). |
show | bool | False | Show the figure first. Default: False. |
frame | int | None | For the image of a Plotly animation: the frame it shows (e.g. -1 for the last). The
page and the JSON keep the whole animation. Default: the first frame. |
still | plotly.graph_objects.Figure | None | A figure that the image shows instead, e.g. a view of an animation that is none of its
frames. The page and the JSON keep figure. |
width | int | 1100 | Width of an image of a Plotly figure, in layout pixels. Default: 1100. |
height | int | 650 | Height of an image of a Plotly figure, in layout pixels. Default: 650. |
scale | float | 2.0 | Resolution factor of an image of a Plotly figure. Default: 2. |
Returns
list of str- The paths written; empty on MPI ranks other than 0.
Examples
>>> dispersion = spectrum.plasma.plot.dispersion(kmin=0, backend="plotly")>>> # maxwell-wave.html, .png, .plotly.json>>> save_figure(dispersion, "maxwell-wave", show=True)>>> save_figure(movie, "phase-space", frame=len(movie.fig.frames) // 2)>>> save_figure(... go.Figure(go.Scatter(x=t, y=energy)), "energy", formats=("html",)... )set_backendfunction#
plasma_plots.plotly_backendView sourcedef set_backend(backend: str) -> strSet the backend of every plot that does not pass backend= itself.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
backend | ('matplotlib', 'plotly', 'tikz') | "matplotlib" | The new default ("tikz": see plasma_plots.tikz_backend). |
Returns
str- The previous default, e.g. to restore it afterwards.
Raises
ValueError- If
backendis not"matplotlib","plotly"or"tikz".
Examples
>>> previous = plasma_plots.set_backend("plotly")>>> phi.plasma.plot.slice(t=-1, eta3=0) # a Plotly figure>>> plasma_plots.set_backend(previous)