Skip to content

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.plot and out.analysis on a Struphy Output: whole-run plots and diagnostics.
  • array.plasma.plot, .analysis and .data on every xarray.DataArray, e.g. a product from out.evaluate("em_fields/phi").
  • dataset.plasma.plot, .analysis and .data on 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

NameDescription
PlasmaAccessorStruphy diagnostics of one array: array.plasma.plot, .analysis and .data.
SkippedPlotWhat a plot returns on MPI ranks other than 0, where nothing is drawn.

Functions

NameDescription
figureCompose several plots into one figure, drawn with Matplotlib, or as one Plotly or TikZ figure.
from_descEvaluate DESC quantities on a grid, as a Dataset in plasma-plots' conventions.
from_gvecReturn GVEC evaluations in plasma-plots' conventions; see plasma_plots.gvec.
get_backendReturn the backend of plots that do not pass backend= themselves.
is_plotting_rankTell whether this process draws plots and writes their files.
mpi_rankReturn this process' rank in MPI_COMM_WORLD, without initializing MPI.
save_figureSave a figure in several formats at once, as <name>.<format>.
set_backendSet 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#

class 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#

class 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

NameTypeDescription
namestrThe skipped plot function, shown by repr.
rankintThe rank that skipped it.

Examples

>>> skipped = SkippedPlot("plot_slice", rank=1)
>>> skipped.save("slice.png").fig is skipped # nothing is written
True
>>> list(skipped), bool(skipped)
([], False)

figurefunction#

def 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) -> Figure

Compose 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

NameTypeDefaultDescription
nrowsint1The number of rows of panels. Default: 1.
ncolsint1The 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.
sharexbool or {'row', 'col', 'all'}FalseShare the horizontal axes (and their zoom, in Plotly), as for matplotlib.pyplot.subplots. Default: False.
shareybool or {'row', 'col', 'all'}FalseShare the vertical axes. Default: False.
figsize(float, float)NoneThe size in inches. Default: from the number of panels.
titlestrNoneA 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].rate

from_descfunction#

def 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.Dataset

Evaluate DESC quantities on a grid, as a Dataset in plasma-plots’ conventions.

See plasma_plots.desc for what the Dataset contains.

Parameters

NameTypeDefaultDescription
eqdesc.equilibrium.EquilibriumrequiredThe equilibrium, e.g. desc.io.load("eq.h5") or desc.examples.get("W7-X").
namesstr or sequence of strrequiredDESC’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.
rhoint, float or sequence of float11The flux surfaces: an integer as that many points from 0 to 1, a float or a sequence as the values. Default: 11 points.
thetaint, float or sequence of float32The poloidal angles (PEST angles with sfl="pest"): an integer as that many points over [0, 2π), else the values. Default: 32 points.
zetaint, float or sequence of float24The 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 (or theta_P) and zeta, vectors along component, with the coordinates X, Y, Z, labels, units, the angles’ period and the nfp attribute.

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#

def from_gvec(data: xr.DataArray | xr.Dataset, *, nfp: int | None = None) -> xr.DataArray | xr.Dataset

Return 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

NameTypeDefaultDescription
dataxarray.Dataset or xarray.DataArrayrequiredA Dataset from state.evaluate(...), state.evaluate_sfl(...) or gvec.Evaluations (also after to_netcdf and open_dataset), or one of its variables.
nfpintNoneThe 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_B and component, the coordinates X, Y, Z (from pos), X1, X2, labels from the symbol attributes, the angles’ period and the nfp attribute.

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#

def get_backend() -> str

Return the backend of plots that do not pass backend= themselves.

Returns

str
"matplotlib" (the default), "plotly" or "tikz".

is_plotting_rankfunction#

def is_plotting_rank() -> bool

Tell whether this process draws plots and writes their files.

Returns

bool
True on rank 0 of an MPI job and in any process outside one.

mpi_rankfunction#

def mpi_rank() -> int

Return 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 run
0

save_figurefunction#

def 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

NameTypeDefaultDescription
figure(PlotResult, Figure, plotly.graph_objects.Figure or matplotlib.figure.Figure)requiredWhat 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.
namestr or pathlib.PathrequiredThe files’ path without the format, e.g. "maxwell-wave" or "figures/energy".
formatssequence 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").
showboolFalseShow the figure first. Default: False.
frameintNoneFor 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.
stillplotly.graph_objects.FigureNoneA 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.
widthint1100Width of an image of a Plotly figure, in layout pixels. Default: 1100.
heightint650Height of an image of a Plotly figure, in layout pixels. Default: 650.
scalefloat2.0Resolution 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#

def set_backend(backend: str) -> str

Set the backend of every plot that does not pass backend= itself.

Parameters

NameTypeDefaultDescription
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 backend is 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)