out.plot and out.analysis
Plots and diagnostics of a whole run, on a Struphy Output object. out.plot() on its own draws the scalar overview.
out.plot
Section titled “out.plot”Plots of a whole run, as out.plot.<kind>(...), constructed as OutputPlots(out).
scalars
Section titled “scalars”scalarsmethod#
def scalars(names=None, *, relative_to: str | None = None, logy: bool = False, backend: Backend | None = None)Overview of the scalar time series in one axes.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
names | list of str | None | Scalars to show; all by default. |
relative_to | str | None | Show every scalar divided by this one. |
logy | bool | False | Logarithmic value axis. |
backend | ('matplotlib', 'plotly', 'tikz') | "matplotlib" | Draw with Matplotlib, as an interactive Plotly figure, or as TikZ/pgfplots code for
LaTeX (in result.fig; needs plotly or maxplotlib, see
plasma_plots.plotly_backend and plasma_plots.tikz_backend). Default:
the one set with plasma_plots.set_backend(), "matplotlib" unless changed. |
Returns
PlotResult- The figure, the axes and the drawn lines, titled with the run’s label.
Examples
>>> out.plot.scalars()>>> out.plot.scalars(["en_U", "en_B"], logy=True)energies
Section titled “energies”energiesmethod#
def energies(parts=None, total: str | None = 'en_tot', groups: dict | None = None, logy: bool = False, backend: Backend | None = None)Plot the run’s energy budget from its energy scalars (en_* or *_energy).
Shows the energy scalars, the relative drift of total, and, with groups
(e.g. {"wave": ["en_U", "en_B", "en_p"], "energetic ions": ["en_fv", "en_fB"]}), the
energy exchanged between them.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
parts | sequence of str | None | The energies drawn in the first panel. Default: the scalars [energy_names()][energy_names]
finds (en_* and *_energy), except total. |
total | str or None | 'en_tot' | The total energy; the second panel is left out if it is None or not among the
scalars. Default: "en_tot", or "total_energy" for a run that names its
energies that way. |
groups | dict of str to list of str | None | A label to the names it sums, e.g.
{"wave": ["en_U", "en_B", "en_p"], "energetic ions": ["en_fv", "en_fB"]}. Default:
no exchange panel. |
logy | bool | False | Use a logarithmic value axis in the first panel. Default: False. |
backend | ('matplotlib', 'plotly', 'tikz') | "matplotlib" | Draw with Matplotlib, as an interactive Plotly figure, or as TikZ/pgfplots code for
LaTeX (in result.fig; needs plotly or maxplotlib, see
plasma_plots.plotly_backend and plasma_plots.tikz_backend). Default:
the one set with plasma_plots.set_backend(), "matplotlib" unless changed. |
Returns
PlotResult- The figure, the axes and the drawn lines, titled with the run’s label.
Examples
>>> out.plot.energies()>>> out.plot.energies(... groups={... "wave": ["en_U", "en_B", "en_p"],... "energetic ions": ["en_fv", "en_fB"],... }... )equilibrium
Section titled “equilibrium”equilibriummethod#
def equilibrium(ax=None, *, backend: Backend | None = None)Plot radial profiles of this run’s fluid equilibrium (out.equil, out.domain).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
ax | matplotlib.axes.Axes | None | The axes to draw into. Default: a new figure. |
backend | ('matplotlib', 'plotly', 'tikz') | "matplotlib" | Draw with Matplotlib, as an interactive Plotly figure, or as TikZ/pgfplots code for
LaTeX (in result.fig; needs plotly or maxplotlib, see
plasma_plots.plotly_backend and plasma_plots.tikz_backend). Default:
the one set with plasma_plots.set_backend(), "matplotlib" unless changed. |
Returns
PlotResult- The figure, the axes and the drawn lines.
Examples
>>> out.plot.equilibrium()equilibrium_3d
Section titled “equilibrium_3d”equilibrium_3dmethod#
def equilibrium_3d(scalars: str = 'p0', cmap='viridis')Create a PyVista view of this run’s fluid equilibrium; call .show() on the returned plotter.
Parameters
Returns
pyvista.Plotter- The scene, not yet shown.
Examples
>>> out.plot.equilibrium_3d(scalars="p0").show()domain_3d
Section titled “domain_3d”domain_3dmethod#
def domain_3d(n1: int = 8, n2: int = 32, n3: int = 32, surface: bool = True)Draw a PyVista wireframe of this run’s mapping (out.domain); call .show() on it.
Parameters
Returns
pyvista.Plotter- The scene, not yet shown.
Examples
>>> out.plot.domain_3d().show()>>> out.plot.domain_3d(n3=1).show()profile
Section titled “profile”profileproperty#
profile: 'ProfilePlots'Plots of this run’s timing regions, e.g. out.plot.profile.gantt().
Needs the optional scope-profiler extra (pip install "plasma-plots[profiling]")
and a run recorded with sim.run(profiling_activated=True).
Returns
ProfilePlots- The profiling plots of this run.
out.plot.profile
Section titled “out.plot.profile”Plots of one run’s timing regions (out.profile.results), as out.plot.profile.<kind>(...).
ganttmethod#
def gantt(return_fig: bool = True, verbose: bool = False, **kwargs)A timeline of every recorded region, one row per rank.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
return_fig | bool | True | Return the rendered figure (scope-profiler’s own default is to return None).
Default: True. |
verbose | bool | False | Let scope-profiler print progress information. Default: False. |
**kwargs | {} | Passed on to scope-profiler’s plot_gantt
(ranks, include/exclude, backend, filepath, min_duration, …). |
Returns
Examples
>>> out.plot.profile.gantt()flamemethod#
def flame(return_fig: bool = True, verbose: bool = False, **kwargs)A flame chart reconstructing the call stack from region timings.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
return_fig | bool | True | Return the rendered figure (scope-profiler’s own default is to return None).
Default: True. |
verbose | bool | False | Let scope-profiler print progress information. Default: False. |
**kwargs | {} | Passed on to scope-profiler’s plot_flame
(ranks, include/exclude, backend, filepath, …). |
Returns
Examples
>>> out.plot.profile.flame()callgraph
Section titled “callgraph”callgraphmethod#
def callgraph(return_fig: bool = True, verbose: bool = False, **kwargs)The explicit call graph (which region calls which), without timings.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
return_fig | bool | True | Return the rendered figure (scope-profiler’s own default is to return None).
Default: True. |
verbose | bool | False | Let scope-profiler print progress information. Default: False. |
**kwargs | {} | Passed on to scope-profiler’s plot_callgraph
(rank, include/exclude, backend, compact, fluid, …). |
Returns
Examples
>>> out.plot.profile.callgraph()out.analysis
Section titled “out.analysis”Spectral diagnostics of a run’s products, as out.analysis.<kind>(product, ...).
fftmethod#
def fft(product, *, dim: str, detrend: bool = False, window: str | None = None)Compute two-sided Fourier coefficients of a product along dim.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
product | str or xarray.DataArray | required | A product name (e.g. "mhd/velocity"), evaluated with out.evaluate, or an
already selected array. |
dim | str | required | The dimension to transform. |
detrend | bool | False | Subtract the mean along dim first. Default: False. |
window | (None, 'hann') | None | Multiply by a periodic Hann window (see [hann()][hann]) first. Default: None (boxcar). |
Returns
xarray.DataArray- Complex coefficients, with
dimreplaced byomega(time) ork_<dim>.
Examples
>>> out.analysis.fft(phi.isel(t=-1, eta2=0, eta3=0), dim="eta1")time_fft
Section titled “time_fft”time_fftmethod#
def time_fft(product, *, detrend: bool = False, window: str | None = None)Compute one-sided temporal Fourier coefficients and per-bin power of a product.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
product | str or xarray.DataArray | required | A product name (e.g. "mhd/velocity"), evaluated with out.evaluate, or an
already selected array. |
detrend | bool | False | Subtract the temporal mean first. Default: False. |
window | (None, 'hann') | None | Multiply by a periodic Hann window (see [hann()][hann]) first. Default: None (boxcar). |
Returns
xarray.Dataset- The complex coefficients and the power over
omega.
Examples
>>> out.analysis.time_fft(phi.isel(eta1=0.5, eta2=0, eta3=0), window="hann")filter_time
Section titled “filter_time”filter_timemethod#
def filter_time(product, *, dims=None, omega_min: float = 1e-08, pad_bins: int = 0)Reconstruct the dominant temporal frequency band of a product.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
product | str or xarray.DataArray | required | A product name (e.g. "mhd/velocity"), evaluated with out.evaluate, or an
already selected array. |
dims | str or sequence of str | None | Non-time dimensions to sum the power over before choosing the band. Default: all
dimensions except t and component. Pass dims=() for independent filtering at
each point. |
omega_min | float | 1e-08 | Finite, positive lowest frequency considered, which excludes DC. Default: 1e-8. |
pad_bins | int | 0 | Nonnegative number of extra bins on each side of the band. Default: 0. |
Returns
TimeFilterResult- The filtered field and the reduced spectrum with the selected band.
Examples
>>> result = out.analysis.filter_time(phi)>>> result.filtered.plasma.plot.slice(t=-1, eta3=0)linear_mhd_energies
Section titled “linear_mhd_energies”linear_mhd_energiesmethod#
def linear_mhd_energies(velocity='mhd/velocity', b_field='em_fields/b_field', pressure='mhd/pressure', gamma: float = 5 / 3)Compute LinearMHD’s energy scalars from fields, as a Dataset of time series.
The scalars are en_U, en_B, en_thermal, en_p and
en_tot = en_U + en_B + en_thermal. Same definitions as the scalars saved during the run
(en_U = 1/2 u^T M2n u, …),
with the run’s domain and equilibrium (n0, p0), but evaluated by quadrature
on the post-processing grid, so they also work for fields that were never simulated:
pass a filtered array (e.g. filter_time(...).filtered) to get the energy in one mode.
Each argument is a raw field name (evaluated at the Gauss points of
quadrature_grid(), in its FEEC space’s own representation), an array in that
representation (on the Gauss grid its weights are exact; elsewhere see
quadrature_weights()), or None to skip it: 2-form
components for velocity and b_field (out.evaluate("mhd/velocity", representation="2")), a 3-form for pressure (representation="3"). The default
post-processing products are in other representations ("norm", "0") and would
give wrong energies. Points where p0 vanishes are left out of en_thermal.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
velocity | (str, xarray.DataArray or None) | 'mhd/velocity' | The velocity as 2-form components (en_U, weighted by n0).
Default: "mhd/velocity". |
b_field | (str, xarray.DataArray or None) | 'em_fields/b_field' | The magnetic field as 2-form components (en_B). Default: "em_fields/b_field". |
pressure | (str, xarray.DataArray or None) | 'mhd/pressure' | The pressure as a 3-form (en_thermal, weighted by 1/p0, and en_p).
Default: "mhd/pressure". |
gamma | float | 5 / 3 | The adiabatic index: en_thermal is normalized by 1/gamma and
en_p = ∫ p / (gamma - 1). Default: 5/3. |
Returns
xarray.Dataset- One time series per computed scalar (only those whose fields were given), plus
en_tot.
Raises
ValueError- If
velocity,b_fieldandpressureare allNone.
Examples
>>> energies = out.analysis.linear_mhd_energies()>>> filtered = out.analysis.filter_time(... out.evaluate("mhd/velocity", representation="2")... ).filtered>>> out.analysis.linear_mhd_energies(... velocity=filtered, b_field=None, pressure=None... )quadrature_grid
Section titled “quadrature_grid”quadrature_gridmethod#
def quadrature_grid()Return the run’s Gauss-Legendre quadrature points and weights in each logical direction.
The points (spline degree + 1 per element) and their weights for each of eta1,
eta2, eta3 form the grid on which spline fields squared integrate exactly.
Evaluate a field there (out.evaluate(name, eta1=etas["eta1"], ..., representation="2")), filter it, and linear_mhd_energies or field_energy(..., quadrature=weights) give its energy as the run’s own scalars would.
Returns
etasdict of str to numpy.ndarray- The points in
[0, 1]for"eta1","eta2","eta3". weightsdict of str to numpy.ndarray- The matching quadrature weights, summing to 1 in each direction.
Examples
>>> etas, weights = out.analysis.quadrature_grid()>>> b = out.evaluate(... "em_fields/b_field",... eta1=etas["eta1"],... eta2=etas["eta2"],... eta3=etas["eta3"],... representation="2",... )mode_spectrum
Section titled “mode_spectrum”mode_spectrummethod#
def mode_spectrum(product, *, dims=('eta2', 'eta3'), names=('m', 'n'), periods=1.0)Compute complex amplitudes of a product over poloidal/toroidal mode numbers.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
product | str or xarray.DataArray | required | A product name (e.g. "mhd/velocity"), evaluated with out.evaluate, or an
already selected array. |
dims | str or sequence of str | ('eta2', 'eta3') | The periodic dimensions to transform. Default: the two angles of the logical dimensions
(see plasma_plots.arrays.logical_dims()), ("eta2", "eta3") for Struphy. |
names | str or sequence of str | ('m', 'n') | The name of the mode number of each dimension, one per dimension.
Default: ("m", "n"). |
periods | float or sequence of float | 1.0 | Each direction’s period in its coordinate: one number for all, or one per dimension.
Default: the coordinate’s period attribute (see
plasma_plots.arrays.angle_period()), else 1.0. |
Returns
xarray.DataArray- Complex amplitudes over the mode numbers
namesand every remaining dimension.
Examples
>>> out.analysis.mode_spectrum("em_fields/phi_log")>>> out.analysis.mode_spectrum(phi.isel(t=-1), dims="eta3", names="n")