plasma-plots 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plasma_plots-0.1.0/LICENSE +16 -0
- plasma_plots-0.1.0/PKG-INFO +141 -0
- plasma_plots-0.1.0/README.md +96 -0
- plasma_plots-0.1.0/pyproject.toml +77 -0
- plasma_plots-0.1.0/setup.cfg +4 -0
- plasma_plots-0.1.0/src/plasma_plots/__init__.py +169 -0
- plasma_plots-0.1.0/src/plasma_plots/__main__.py +11 -0
- plasma_plots-0.1.0/src/plasma_plots/_api.py +317 -0
- plasma_plots-0.1.0/src/plasma_plots/_docs.py +266 -0
- plasma_plots-0.1.0/src/plasma_plots/accessors.py +4591 -0
- plasma_plots-0.1.0/src/plasma_plots/analysis.py +2276 -0
- plasma_plots-0.1.0/src/plasma_plots/arrays.py +569 -0
- plasma_plots-0.1.0/src/plasma_plots/cli.py +1162 -0
- plasma_plots-0.1.0/src/plasma_plots/desc.py +313 -0
- plasma_plots-0.1.0/src/plasma_plots/figures.py +277 -0
- plasma_plots-0.1.0/src/plasma_plots/gallery.py +775 -0
- plasma_plots-0.1.0/src/plasma_plots/gvec.py +225 -0
- plasma_plots-0.1.0/src/plasma_plots/mpi.py +177 -0
- plasma_plots-0.1.0/src/plasma_plots/output_accessors.py +807 -0
- plasma_plots-0.1.0/src/plasma_plots/plotly_backend.py +2097 -0
- plasma_plots-0.1.0/src/plasma_plots/plotting.py +5428 -0
- plasma_plots-0.1.0/src/plasma_plots/pyvista_plots.py +1292 -0
- plasma_plots-0.1.0/src/plasma_plots/spectral.py +1539 -0
- plasma_plots-0.1.0/src/plasma_plots/spectral_plots.py +947 -0
- plasma_plots-0.1.0/src/plasma_plots/theory/__init__.py +51 -0
- plasma_plots-0.1.0/src/plasma_plots/theory/exact.py +956 -0
- plasma_plots-0.1.0/src/plasma_plots/theory/kinetic.py +1148 -0
- plasma_plots-0.1.0/src/plasma_plots/theory/numerics.py +518 -0
- plasma_plots-0.1.0/src/plasma_plots/theory/orbits.py +584 -0
- plasma_plots-0.1.0/src/plasma_plots/theory/parameters.py +683 -0
- plasma_plots-0.1.0/src/plasma_plots/theory/special.py +174 -0
- plasma_plots-0.1.0/src/plasma_plots/theory/waves.py +1276 -0
- plasma_plots-0.1.0/src/plasma_plots.egg-info/PKG-INFO +141 -0
- plasma_plots-0.1.0/src/plasma_plots.egg-info/SOURCES.txt +73 -0
- plasma_plots-0.1.0/src/plasma_plots.egg-info/dependency_links.txt +1 -0
- plasma_plots-0.1.0/src/plasma_plots.egg-info/entry_points.txt +2 -0
- plasma_plots-0.1.0/src/plasma_plots.egg-info/requires.txt +32 -0
- plasma_plots-0.1.0/src/plasma_plots.egg-info/top_level.txt +1 -0
- plasma_plots-0.1.0/tests/test_accessor_pages.py +18 -0
- plasma_plots-0.1.0/tests/test_analysis_and_core_output.py +343 -0
- plasma_plots-0.1.0/tests/test_api_index.py +49 -0
- plasma_plots-0.1.0/tests/test_argument_fixes.py +191 -0
- plasma_plots-0.1.0/tests/test_cli.py +625 -0
- plasma_plots-0.1.0/tests/test_desc.py +205 -0
- plasma_plots-0.1.0/tests/test_dispersion_branches.py +95 -0
- plasma_plots-0.1.0/tests/test_docs_snippets.py +88 -0
- plasma_plots-0.1.0/tests/test_docstrings.py +126 -0
- plasma_plots-0.1.0/tests/test_energies_and_run_plots.py +359 -0
- plasma_plots-0.1.0/tests/test_example_helpers.py +428 -0
- plasma_plots-0.1.0/tests/test_example_tools.py +236 -0
- plasma_plots-0.1.0/tests/test_figures.py +153 -0
- plasma_plots-0.1.0/tests/test_gallery.py +127 -0
- plasma_plots-0.1.0/tests/test_gvec.py +406 -0
- plasma_plots-0.1.0/tests/test_import.py +35 -0
- plasma_plots-0.1.0/tests/test_mpi.py +132 -0
- plasma_plots-0.1.0/tests/test_orbit_classification_and_continuum.py +127 -0
- plasma_plots-0.1.0/tests/test_oscillations_and_coordinates.py +119 -0
- plasma_plots-0.1.0/tests/test_output_accessors.py +322 -0
- plasma_plots-0.1.0/tests/test_package_guide.py +97 -0
- plasma_plots-0.1.0/tests/test_plotly_backend.py +891 -0
- plasma_plots-0.1.0/tests/test_plotting.py +540 -0
- plasma_plots-0.1.0/tests/test_profile_plots.py +73 -0
- plasma_plots-0.1.0/tests/test_pyvista_plots.py +261 -0
- plasma_plots-0.1.0/tests/test_real_simulations.py +350 -0
- plasma_plots-0.1.0/tests/test_save_figure.py +107 -0
- plasma_plots-0.1.0/tests/test_spectral.py +204 -0
- plasma_plots-0.1.0/tests/test_spectral_tools.py +346 -0
- plasma_plots-0.1.0/tests/test_theory_doctests.py +19 -0
- plasma_plots-0.1.0/tests/test_theory_exact.py +469 -0
- plasma_plots-0.1.0/tests/test_theory_kinetic.py +362 -0
- plasma_plots-0.1.0/tests/test_theory_numerics.py +331 -0
- plasma_plots-0.1.0/tests/test_theory_orbits.py +282 -0
- plasma_plots-0.1.0/tests/test_theory_parameters.py +236 -0
- plasma_plots-0.1.0/tests/test_theory_special.py +48 -0
- plasma_plots-0.1.0/tests/test_theory_waves.py +536 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Copyright (c) 2019-2026, Struphy developers, Max Planck Institute for Plasma Physics
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
4
|
+
associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
5
|
+
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
6
|
+
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
7
|
+
subject to the following conditions:
|
|
8
|
+
|
|
9
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
10
|
+
portions of the Software.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
|
13
|
+
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
14
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
15
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
16
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: plasma-plots
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Plots and diagnostics of labeled xarray output from plasma simulations, such as Struphy
|
|
5
|
+
Author-email: Max Lindqvist <max.lindqvist@ipp.mpg.de>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/struphy-hub/plasma-plots
|
|
8
|
+
Project-URL: Repository, https://github.com/struphy-hub/plasma-plots
|
|
9
|
+
Project-URL: Documentation, https://struphy-hub.github.io/plasma-plots
|
|
10
|
+
Project-URL: Issues, https://github.com/struphy-hub/plasma-plots/issues
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: matplotlib
|
|
20
|
+
Requires-Dist: numpy
|
|
21
|
+
Requires-Dist: xarray
|
|
22
|
+
Requires-Dist: ipywidgets
|
|
23
|
+
Provides-Extra: netcdf
|
|
24
|
+
Requires-Dist: netCDF4; extra == "netcdf"
|
|
25
|
+
Provides-Extra: pyvista
|
|
26
|
+
Requires-Dist: pyvista; extra == "pyvista"
|
|
27
|
+
Requires-Dist: imageio; extra == "pyvista"
|
|
28
|
+
Provides-Extra: profiling
|
|
29
|
+
Requires-Dist: scope-profiler[pproc]; extra == "profiling"
|
|
30
|
+
Provides-Extra: plotly
|
|
31
|
+
Requires-Dist: plotly; extra == "plotly"
|
|
32
|
+
Requires-Dist: kaleido; extra == "plotly"
|
|
33
|
+
Provides-Extra: gallery
|
|
34
|
+
Requires-Dist: plotly; extra == "gallery"
|
|
35
|
+
Requires-Dist: kaleido; extra == "gallery"
|
|
36
|
+
Requires-Dist: scope-profiler[pproc]>=0.6.1; extra == "gallery"
|
|
37
|
+
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: pytest; extra == "dev"
|
|
39
|
+
Requires-Dist: ruff; extra == "dev"
|
|
40
|
+
Requires-Dist: h5py; extra == "dev"
|
|
41
|
+
Requires-Dist: griffe; extra == "dev"
|
|
42
|
+
Provides-Extra: desc
|
|
43
|
+
Requires-Dist: desc-opt; extra == "desc"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# plasma-plots
|
|
47
|
+
|
|
48
|
+
Note: This library is 100% written by AI, I have literally not looked at a single line of code. So why should you trust it? You should trust it because of the following [LEAN 4 PROOF](https://gprivate.com/6m80q).
|
|
49
|
+
|
|
50
|
+
Plots and diagnostics of labeled xarray data from plasma simulations: the
|
|
51
|
+
output of [Struphy](https://github.com/struphy-hub/struphy), and of any code
|
|
52
|
+
whose arrays follow the same conventions (dimensions `t`, `eta1`/`eta2`/`eta3`,
|
|
53
|
+
mapped coordinates `X`/`Y`/`Z`, see
|
|
54
|
+
[Getting started](https://struphy-hub.github.io/plasma-plots/guides/getting-started/)).
|
|
55
|
+
It also reads [GVEC](https://gvec.readthedocs.io)'s equilibrium evaluations directly. It is a
|
|
56
|
+
separate package, so it can evolve and release independently of the Struphy runtime.
|
|
57
|
+
|
|
58
|
+
Full documentation: https://struphy-hub.github.io/plasma-plots
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
Python **3.11 or newer** is required; CI tests Python 3.11 and 3.12.
|
|
63
|
+
The base install plots in-memory xarray data. Install extras for file formats
|
|
64
|
+
and optional renderers:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install plasma-plots
|
|
68
|
+
pip install "plasma-plots[netcdf]"
|
|
69
|
+
pip install "plasma-plots[netcdf,plotly]"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
| Extra | Enables | Dependencies |
|
|
73
|
+
| --- | --- | --- |
|
|
74
|
+
| `netcdf` | Read netCDF3/netCDF4 files through xarray and the CLI | `netCDF4` |
|
|
75
|
+
| `plotly` | Interactive browser plots and static Plotly exports | `plotly`, `kaleido` |
|
|
76
|
+
| `pyvista` | 3-D scenes and rendering | `pyvista`, `imageio` |
|
|
77
|
+
| `profiling` | Timing summaries and profiling plots | `scope-profiler[pproc]` |
|
|
78
|
+
| `desc` | Evaluate DESC equilibria | `desc-opt` |
|
|
79
|
+
| `gallery` | Export Struphy example-gallery figures and profiling | `plotly`, `kaleido`, `scope-profiler[pproc]>=0.6.1` |
|
|
80
|
+
| `dev` | Tests, linting and documentation tooling | `pytest`, `ruff`, `h5py`, `griffe` |
|
|
81
|
+
|
|
82
|
+
Struphy, GVEC and Zarr are separate installations; no extra above installs
|
|
83
|
+
them. Struphy users need the compatible output API described below. Install
|
|
84
|
+
`gvec` for GVEC evaluation or `zarr` to open Zarr stores. MP4 export requires
|
|
85
|
+
system `ffmpeg`; Matplotlib windows require a working GUI/display, and static
|
|
86
|
+
Plotly exports through Kaleido require a compatible Chrome installation.
|
|
87
|
+
|
|
88
|
+
For development, install with `pip install -e ".[dev]"`.
|
|
89
|
+
|
|
90
|
+
## Struphy compatibility
|
|
91
|
+
|
|
92
|
+
Struphy integration is tested against commit
|
|
93
|
+
[`caddd229a3fcba1fada577d1af46d012e93d8b49`](https://github.com/struphy-hub/struphy/commit/caddd229a3fcba1fada577d1af46d012e93d8b49)
|
|
94
|
+
(the repository's pinned submodule, reporting version **3.3.0**). Use that
|
|
95
|
+
revision for a reproducible installation; compatibility with other Struphy
|
|
96
|
+
revisions, including older published builds, is not guaranteed. Struphy is
|
|
97
|
+
optional when working with ordinary xarray data.
|
|
98
|
+
|
|
99
|
+
## Usage
|
|
100
|
+
|
|
101
|
+
Creating a Struphy `Output` loads plasma-plots, which registers `out.plot`,
|
|
102
|
+
`out.analysis` and the `.plasma` accessor on every product:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from struphy.post_processing.output import Output
|
|
106
|
+
|
|
107
|
+
out = Output("path/to/run")
|
|
108
|
+
out.evaluate("em_fields/phi").plasma.plot.slice(x="eta1", y="eta2", t=-1)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
> [!IMPORTANT]
|
|
112
|
+
> For xarray data that doesn't come from an `Output`, `import plasma_plots`
|
|
113
|
+
> first. Without it you get
|
|
114
|
+
> `AttributeError: 'DataArray' object has no attribute 'plasma'`.
|
|
115
|
+
|
|
116
|
+
In Python, `import plasma_plots; help(plasma_plots)` (or `plasma-plots guide` in a terminal) gives an overview,
|
|
117
|
+
printing an accessor lists its methods (`print(phi.plasma.plot)`), and `help()`
|
|
118
|
+
on a method shows every parameter. For language models and coding agents, the
|
|
119
|
+
documentation is available as plain text at
|
|
120
|
+
https://struphy-hub.github.io/plasma-plots/llms.txt. [API.md](API.md) (or
|
|
121
|
+
`plasma-plots api`) is a one-page index of every accessor method and function, and
|
|
122
|
+
[AGENTS.md](AGENTS.md) explains the code for agents working on it.
|
|
123
|
+
|
|
124
|
+
From the shell, the `plasma-plots` command saves figures of a Struphy run folder or a
|
|
125
|
+
netCDF file without any Python: `plasma-plots info sim_1`,
|
|
126
|
+
`plasma-plots plot sim_1 em_fields/phi slice t=-1 eta3=0 -o phi.png`,
|
|
127
|
+
`plasma-plots quicklook sim_1 -o figures/` (see the
|
|
128
|
+
[command-line guide](https://struphy-hub.github.io/plasma-plots/guides/command-line/)).
|
|
129
|
+
|
|
130
|
+
Direct plotting functions are available from
|
|
131
|
+
`plasma_plots.plotting`; analysis functions are in `plasma_plots.analysis`.
|
|
132
|
+
|
|
133
|
+
The accessor provides time-series, lineout, slice, panel, vector, comparison,
|
|
134
|
+
animation, and marker-trajectory plots. For three-dimensional scalar fields,
|
|
135
|
+
install the optional PyVista dependency (`pip install plasma-plots[pyvista]`) and
|
|
136
|
+
use `field.plasma.plot.volume(t=-1)`, then call `show()` on the returned plotter.
|
|
137
|
+
|
|
138
|
+
Every Matplotlib plot can also be an interactive Plotly figure, with hover values, zoom and,
|
|
139
|
+
for animations, a slider: `pip install plasma-plots[plotly]` and pass `backend="plotly"`
|
|
140
|
+
(`field.plasma.plot.slice(t=-1, backend="plotly")`), or call
|
|
141
|
+
`plasma_plots.set_backend("plotly")` once.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# plasma-plots
|
|
2
|
+
|
|
3
|
+
Note: This library is 100% written by AI, I have literally not looked at a single line of code. So why should you trust it? You should trust it because of the following [LEAN 4 PROOF](https://gprivate.com/6m80q).
|
|
4
|
+
|
|
5
|
+
Plots and diagnostics of labeled xarray data from plasma simulations: the
|
|
6
|
+
output of [Struphy](https://github.com/struphy-hub/struphy), and of any code
|
|
7
|
+
whose arrays follow the same conventions (dimensions `t`, `eta1`/`eta2`/`eta3`,
|
|
8
|
+
mapped coordinates `X`/`Y`/`Z`, see
|
|
9
|
+
[Getting started](https://struphy-hub.github.io/plasma-plots/guides/getting-started/)).
|
|
10
|
+
It also reads [GVEC](https://gvec.readthedocs.io)'s equilibrium evaluations directly. It is a
|
|
11
|
+
separate package, so it can evolve and release independently of the Struphy runtime.
|
|
12
|
+
|
|
13
|
+
Full documentation: https://struphy-hub.github.io/plasma-plots
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
Python **3.11 or newer** is required; CI tests Python 3.11 and 3.12.
|
|
18
|
+
The base install plots in-memory xarray data. Install extras for file formats
|
|
19
|
+
and optional renderers:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install plasma-plots
|
|
23
|
+
pip install "plasma-plots[netcdf]"
|
|
24
|
+
pip install "plasma-plots[netcdf,plotly]"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
| Extra | Enables | Dependencies |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| `netcdf` | Read netCDF3/netCDF4 files through xarray and the CLI | `netCDF4` |
|
|
30
|
+
| `plotly` | Interactive browser plots and static Plotly exports | `plotly`, `kaleido` |
|
|
31
|
+
| `pyvista` | 3-D scenes and rendering | `pyvista`, `imageio` |
|
|
32
|
+
| `profiling` | Timing summaries and profiling plots | `scope-profiler[pproc]` |
|
|
33
|
+
| `desc` | Evaluate DESC equilibria | `desc-opt` |
|
|
34
|
+
| `gallery` | Export Struphy example-gallery figures and profiling | `plotly`, `kaleido`, `scope-profiler[pproc]>=0.6.1` |
|
|
35
|
+
| `dev` | Tests, linting and documentation tooling | `pytest`, `ruff`, `h5py`, `griffe` |
|
|
36
|
+
|
|
37
|
+
Struphy, GVEC and Zarr are separate installations; no extra above installs
|
|
38
|
+
them. Struphy users need the compatible output API described below. Install
|
|
39
|
+
`gvec` for GVEC evaluation or `zarr` to open Zarr stores. MP4 export requires
|
|
40
|
+
system `ffmpeg`; Matplotlib windows require a working GUI/display, and static
|
|
41
|
+
Plotly exports through Kaleido require a compatible Chrome installation.
|
|
42
|
+
|
|
43
|
+
For development, install with `pip install -e ".[dev]"`.
|
|
44
|
+
|
|
45
|
+
## Struphy compatibility
|
|
46
|
+
|
|
47
|
+
Struphy integration is tested against commit
|
|
48
|
+
[`caddd229a3fcba1fada577d1af46d012e93d8b49`](https://github.com/struphy-hub/struphy/commit/caddd229a3fcba1fada577d1af46d012e93d8b49)
|
|
49
|
+
(the repository's pinned submodule, reporting version **3.3.0**). Use that
|
|
50
|
+
revision for a reproducible installation; compatibility with other Struphy
|
|
51
|
+
revisions, including older published builds, is not guaranteed. Struphy is
|
|
52
|
+
optional when working with ordinary xarray data.
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
Creating a Struphy `Output` loads plasma-plots, which registers `out.plot`,
|
|
57
|
+
`out.analysis` and the `.plasma` accessor on every product:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from struphy.post_processing.output import Output
|
|
61
|
+
|
|
62
|
+
out = Output("path/to/run")
|
|
63
|
+
out.evaluate("em_fields/phi").plasma.plot.slice(x="eta1", y="eta2", t=-1)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> [!IMPORTANT]
|
|
67
|
+
> For xarray data that doesn't come from an `Output`, `import plasma_plots`
|
|
68
|
+
> first. Without it you get
|
|
69
|
+
> `AttributeError: 'DataArray' object has no attribute 'plasma'`.
|
|
70
|
+
|
|
71
|
+
In Python, `import plasma_plots; help(plasma_plots)` (or `plasma-plots guide` in a terminal) gives an overview,
|
|
72
|
+
printing an accessor lists its methods (`print(phi.plasma.plot)`), and `help()`
|
|
73
|
+
on a method shows every parameter. For language models and coding agents, the
|
|
74
|
+
documentation is available as plain text at
|
|
75
|
+
https://struphy-hub.github.io/plasma-plots/llms.txt. [API.md](API.md) (or
|
|
76
|
+
`plasma-plots api`) is a one-page index of every accessor method and function, and
|
|
77
|
+
[AGENTS.md](AGENTS.md) explains the code for agents working on it.
|
|
78
|
+
|
|
79
|
+
From the shell, the `plasma-plots` command saves figures of a Struphy run folder or a
|
|
80
|
+
netCDF file without any Python: `plasma-plots info sim_1`,
|
|
81
|
+
`plasma-plots plot sim_1 em_fields/phi slice t=-1 eta3=0 -o phi.png`,
|
|
82
|
+
`plasma-plots quicklook sim_1 -o figures/` (see the
|
|
83
|
+
[command-line guide](https://struphy-hub.github.io/plasma-plots/guides/command-line/)).
|
|
84
|
+
|
|
85
|
+
Direct plotting functions are available from
|
|
86
|
+
`plasma_plots.plotting`; analysis functions are in `plasma_plots.analysis`.
|
|
87
|
+
|
|
88
|
+
The accessor provides time-series, lineout, slice, panel, vector, comparison,
|
|
89
|
+
animation, and marker-trajectory plots. For three-dimensional scalar fields,
|
|
90
|
+
install the optional PyVista dependency (`pip install plasma-plots[pyvista]`) and
|
|
91
|
+
use `field.plasma.plot.volume(t=-1)`, then call `show()` on the returned plotter.
|
|
92
|
+
|
|
93
|
+
Every Matplotlib plot can also be an interactive Plotly figure, with hover values, zoom and,
|
|
94
|
+
for animations, a slider: `pip install plasma-plots[plotly]` and pass `backend="plotly"`
|
|
95
|
+
(`field.plasma.plot.slice(t=-1, backend="plotly")`), or call
|
|
96
|
+
`plasma_plots.set_backend("plotly")` once.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "plasma-plots"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Plots and diagnostics of labeled xarray output from plasma simulations, such as Struphy"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "Max Lindqvist", email = "max.lindqvist@ipp.mpg.de" }]
|
|
12
|
+
requires-python = ">=3.11"
|
|
13
|
+
dependencies = ["matplotlib", "numpy", "xarray", "ipywidgets"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Science/Research",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
plasma-plots = "plasma_plots.cli:main"
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
# Read netCDF3 and netCDF4 files through xarray (including the CLI).
|
|
27
|
+
netcdf = ["netCDF4"]
|
|
28
|
+
pyvista = ["pyvista", "imageio"]
|
|
29
|
+
profiling = ["scope-profiler[pproc]"]
|
|
30
|
+
# backend="plotly": interactive Plotly versions of the plots; kaleido saves them as PNG/SVG/PDF
|
|
31
|
+
plotly = ["plotly", "kaleido"]
|
|
32
|
+
# the output helpers of the struphy-hub example gallery (plasma_plots.gallery): Plotly figures,
|
|
33
|
+
# their static PNGs (kaleido) and the profiling export, which needs scope-profiler 0.6.1 or newer
|
|
34
|
+
gallery = ["plotly", "kaleido", "scope-profiler[pproc]>=0.6.1"]
|
|
35
|
+
dev = ["pytest", "ruff", "h5py", "griffe"]
|
|
36
|
+
# plasma_plots.from_desc: evaluating DESC equilibria (tests/test_desc.py, the DESC guide)
|
|
37
|
+
desc = ["desc-opt"]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/struphy-hub/plasma-plots"
|
|
41
|
+
Repository = "https://github.com/struphy-hub/plasma-plots"
|
|
42
|
+
Documentation = "https://struphy-hub.github.io/plasma-plots"
|
|
43
|
+
Issues = "https://github.com/struphy-hub/plasma-plots/issues"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.packages.find]
|
|
46
|
+
where = ["src"]
|
|
47
|
+
|
|
48
|
+
[tool.pytest.ini_options]
|
|
49
|
+
# Restrict collection to our own tests: the struphy submodule now lives at
|
|
50
|
+
# ./struphy (with its own nested feectools submodule), and bare `pytest`
|
|
51
|
+
# would otherwise recurse into their test suites too -- and fail on their
|
|
52
|
+
# own optional dependencies (e.g. psydac) that plasma-plots has no need of.
|
|
53
|
+
testpaths = ["tests"]
|
|
54
|
+
# Real struphy simulations (compiled kernels, ~1 min): skipped unless requested with
|
|
55
|
+
# `pytest --run-simulations` (see tests/conftest.py); run in the docs workflow.
|
|
56
|
+
markers = ["simulation: runs a real struphy simulation; needs compiled kernels"]
|
|
57
|
+
|
|
58
|
+
[tool.ruff]
|
|
59
|
+
line-length = 120
|
|
60
|
+
|
|
61
|
+
[tool.ruff.lint]
|
|
62
|
+
select = ["E4", "E7", "E9", "F"]
|
|
63
|
+
ignore = [
|
|
64
|
+
"E265",
|
|
65
|
+
"E402",
|
|
66
|
+
"E701",
|
|
67
|
+
"E722",
|
|
68
|
+
"E731",
|
|
69
|
+
"E741",
|
|
70
|
+
"E742",
|
|
71
|
+
"E743",
|
|
72
|
+
"E902",
|
|
73
|
+
"F401",
|
|
74
|
+
"F403",
|
|
75
|
+
"F405",
|
|
76
|
+
"F841",
|
|
77
|
+
]
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""Plots and diagnostics of labeled xarray data from plasma simulations, such as Struphy's output.
|
|
2
|
+
|
|
3
|
+
plasma-plots adds accessors to the objects Struphy returns; you rarely call a function directly:
|
|
4
|
+
|
|
5
|
+
* ``out.plot`` and ``out.analysis`` on a Struphy ``Output``: whole-run plots and diagnostics.
|
|
6
|
+
* ``array.plasma.plot``, ``.analysis`` and ``.data`` on every ``xarray.DataArray``, e.g. a product
|
|
7
|
+
from ``out.evaluate("em_fields/phi")``.
|
|
8
|
+
* ``dataset.plasma.plot``, ``.analysis`` and ``.data`` on marker Datasets such as orbits.
|
|
9
|
+
|
|
10
|
+
Creating a Struphy ``Output`` loads plasma-plots, so its output needs no import. For xarray data
|
|
11
|
+
from elsewhere, ``import plasma_plots`` first; without it, ``.plasma`` raises
|
|
12
|
+
``AttributeError: 'DataArray' object has no attribute 'plasma'``.
|
|
13
|
+
|
|
14
|
+
Printing an accessor lists its methods (``print(phi.plasma.plot)``), and ``help()`` on a method
|
|
15
|
+
shows every parameter (``help(phi.plasma.plot.slice)``). ``plasma-plots guide`` (or
|
|
16
|
+
``python -m plasma_plots guide``) prints this guide, ``plasma-plots api`` an index of every method and
|
|
17
|
+
function with its signature. The ``plasma-plots`` command also saves figures from the shell, e.g.
|
|
18
|
+
``plasma-plots plot sim_1 em_fields/phi slice t=-1 eta3=0 -o phi.png`` or
|
|
19
|
+
``plasma-plots quicklook sim_1 -o figures/`` (``plasma-plots --help``).
|
|
20
|
+
|
|
21
|
+
A post-processing pipeline
|
|
22
|
+
--------------------------
|
|
23
|
+
>>> from struphy import Output # doctest: +SKIP
|
|
24
|
+
>>> out = Output("sim_1") # the run's output folder
|
|
25
|
+
>>> out.plot.energies().save("energies.png") # the energy budget and its drift
|
|
26
|
+
>>> # dims (t, eta1, eta2, eta3), coordinates X, Y, Z
|
|
27
|
+
>>> phi = out.evaluate("em_fields/phi")
|
|
28
|
+
>>> phi.plasma.plot.slice(coords="physical", plane="XY", t=-1, eta3=0).save(
|
|
29
|
+
... "phi.png"
|
|
30
|
+
... )
|
|
31
|
+
>>> phi.plasma.plot.animation(x="eta1", y="eta2", eta3=0).save(
|
|
32
|
+
... "phi.gif", writer="pillow"
|
|
33
|
+
... )
|
|
34
|
+
>>> # complex amplitudes over mode numbers m, n
|
|
35
|
+
>>> modes = phi.plasma.analysis.mode_spectrum()
|
|
36
|
+
>>> # the strongest (m, n) over time
|
|
37
|
+
>>> phi.plasma.plot.mode_amplitudes(top=4, fit=True)
|
|
38
|
+
>>> # guiding-center orbits, by orbit class
|
|
39
|
+
>>> out.kinetic_ions.orbits.plasma.plot.poloidal()
|
|
40
|
+
|
|
41
|
+
Selecting what to show
|
|
42
|
+
----------------------
|
|
43
|
+
Name every dimension a plot doesn't draw: an integer is a position (``t=-1`` the last, ``t=0`` the
|
|
44
|
+
first) and a float the nearest coordinate value (``t=0.35``). Slices draw two dimensions: logical
|
|
45
|
+
ones (``x="eta1", y="eta2"``), or physical ones with ``coords="physical", plane="XY"`` (or
|
|
46
|
+
``"XZ"``, ``"YZ"``, ``"RZ"``). ``array.plasma.data.<plot>(...)`` returns the selected data a plot
|
|
47
|
+
would draw, instead of the figure.
|
|
48
|
+
|
|
49
|
+
What is where
|
|
50
|
+
-------------
|
|
51
|
+
* Time series and rates: ``plot.timeseries(fit=(t0, t1), reference=...)``,
|
|
52
|
+
``analysis.growth_rate``, ``analysis.damping_rate``, ``analysis.envelope``,
|
|
53
|
+
``analysis.oscillation_frequency`` (from zero crossings).
|
|
54
|
+
* Profiles: ``plot.lineout``, ``plot.profiles``, ``plot.line_animation`` (``alongside=`` for
|
|
55
|
+
panels in sync), each with ``reference=`` for exact solutions; ``analysis.map_coordinate`` for
|
|
56
|
+
physical coordinates (``eta1`` → ``r`` in m).
|
|
57
|
+
* Several plots in one figure: ``with plasma_plots.figure(2, 1) as fig:`` and ``ax=fig[0]``,
|
|
58
|
+
``ax=fig[1]``.
|
|
59
|
+
* 2-D fields: ``plot.slice``, ``plot.panels``, ``plot.animation``, ``plot.viewer``,
|
|
60
|
+
``plot.frames``, with ``levels=`` (contour lines), ``overlays=`` (a second field's contours,
|
|
61
|
+
boundary, lines, points), ``symmetric=``, ``robust=``; ``plot.vector`` for vector fields.
|
|
62
|
+
* 3-D views (``pip install "plasma-plots[pyvista]"``): ``plot.isosurface``, ``plot.slices_3d``,
|
|
63
|
+
``plot.glyphs``, ``plot.streamlines``, ``plot.movie``; ``data.to_vtk`` for ParaView.
|
|
64
|
+
* Spectra: ``analysis.time_fft``, ``analysis.spectral_peaks``, ``analysis.filter_time``,
|
|
65
|
+
``analysis.mode_spectrum``, ``analysis.matrix_pencil``, ``analysis.cross_spectrum``;
|
|
66
|
+
``plot.power_spectrum``, ``plot.spectrogram``, ``plot.mode_amplitudes``, ``plot.mode_profiles``.
|
|
67
|
+
* Dispersion relations: ``plot.dispersion(branches=...)``, ``analysis.dispersion`` and
|
|
68
|
+
``.plasma.analysis.trace_branch(theory)`` on the spectrum.
|
|
69
|
+
* Comparing with theory: ``analysis.error(exact)``, ``plot.against_theory(theory)``,
|
|
70
|
+
``analysis.project_mode``; convergence studies with ``plot.convergence``.
|
|
71
|
+
* Vector calculus on mapped domains: ``analysis.gradient``, ``analysis.divergence``,
|
|
72
|
+
``analysis.curl``, ``analysis.flux_function``, ``analysis.toroidal_components``.
|
|
73
|
+
* Particles: ``dataset.plasma.plot.scatter``, ``.animation`` (``trail=``, ``paths=``,
|
|
74
|
+
``color="classification"``), ``.paths``, ``.poloidal``,
|
|
75
|
+
``.orbit_grid``, ``.orbit_classification``, ``.orbits_3d``; ``dataset.plasma.analysis.
|
|
76
|
+
classify_orbits``, ``.orbit_invariants``, ``.bounce_period``; binned distributions with
|
|
77
|
+
``plot.slice(x="eta1", y="v1")`` and ``analysis.velocity_moments``.
|
|
78
|
+
* Whole runs: ``out.plot.energies``, ``out.plot.scalars``, ``out.plot.equilibrium``,
|
|
79
|
+
``out.plot.profile``; ``out.analysis.linear_mhd_energies``, ``out.analysis.time_fft``,
|
|
80
|
+
``out.analysis.mode_spectrum``.
|
|
81
|
+
* Integrals: ``plasma_plots.analysis.volume_integral`` and ``field_energy``;
|
|
82
|
+
``analysis.surface_average`` for flux-surface averages.
|
|
83
|
+
* GVEC equilibria: ``.plasma`` reads ``state.evaluate(...)`` itself, ``plasma_plots.from_gvec(ds)``
|
|
84
|
+
attaches the geometry to every variable; poloidal planes with
|
|
85
|
+
``overlays={"coordinate_lines": {"rho": 4, "theta_P": 8}}`` (and ``plane="X1X2"``), ι with
|
|
86
|
+
``plot.lineout(rationals=4)`` and ``analysis.rational_surfaces``.
|
|
87
|
+
* DESC equilibria: ``plasma_plots.from_desc(eq, ["|B|", "iota", "sqrt(g)"], rho=11, theta=64,
|
|
88
|
+
zeta=40)`` evaluates them into the same flux-coordinate Datasets (``sfl="pest"`` for the PEST
|
|
89
|
+
angle ``theta_P``); DESC's names stay, ``ev["|B|"].plasma.plot...``.
|
|
90
|
+
* Analytic theory to compare with (plain functions, not accessors): ``plasma_plots.theory.kinetic``
|
|
91
|
+
(Landau damping, beam instabilities, Weibel), ``.waves`` (MHD, Hall-MHD and cold-plasma waves,
|
|
92
|
+
drift waves, continua), ``.parameters`` (plasma parameters, Struphy's units), ``.orbits``,
|
|
93
|
+
``.exact`` (Riemann problem, dam break, diffusion, ...) and ``.numerics`` (time-integrator and
|
|
94
|
+
discretization errors). Their functions go straight into ``branches=``, ``reference=`` and
|
|
95
|
+
``theory=``, e.g. ``phi.plasma.plot.dispersion(branches={"kinetic": kinetic.langmuir})``.
|
|
96
|
+
|
|
97
|
+
Plots return a ``PlotResult`` (``.fig``, ``.ax``, ``.save(path)``, ``.show()``); animations a
|
|
98
|
+
``matplotlib.animation.FuncAnimation`` (keep a reference; ``.save("a.gif", writer="pillow")``); 3-D
|
|
99
|
+
views a ``pyvista.Plotter`` (``.show()``, ``.screenshot(path)``; ``pyvista.OFF_SCREEN = True`` in
|
|
100
|
+
scripts). Analysis methods return labeled xarray objects, which have ``.plasma`` in turn.
|
|
101
|
+
|
|
102
|
+
Every Matplotlib plot also draws as an interactive Plotly figure (``pip install
|
|
103
|
+
"plasma-plots[plotly]"``): ``phi.plasma.plot.slice(t=-1, eta3=0, backend="plotly")``, or
|
|
104
|
+
``plasma_plots.set_backend("plotly")`` for all of them. The result is a ``PlotResult`` too
|
|
105
|
+
(``.save("phi.html")``); animations and viewers get a slider. See
|
|
106
|
+
:mod:`plasma_plots.plotly_backend`.
|
|
107
|
+
|
|
108
|
+
Under MPI (``mpirun -n 4 python script.py``), plots are drawn and saved on rank 0 only; the other
|
|
109
|
+
ranks get a ``SkippedPlot`` whose methods do nothing, so one script runs unchanged in serial and
|
|
110
|
+
in parallel. Analysis runs on every rank. See :mod:`plasma_plots.mpi`.
|
|
111
|
+
|
|
112
|
+
The functions behind the accessors, for plain ``xarray.DataArray`` input, are in
|
|
113
|
+
``plasma_plots.plotting``, ``.analysis``, ``.spectral``, ``.spectral_plots``, ``.pyvista_plots``
|
|
114
|
+
and ``.arrays``.
|
|
115
|
+
|
|
116
|
+
Guides and the full reference: https://struphy-hub.github.io/plasma-plots (for language models:
|
|
117
|
+
https://struphy-hub.github.io/plasma-plots/llms.txt).
|
|
118
|
+
|
|
119
|
+
Example
|
|
120
|
+
-------
|
|
121
|
+
Runs as is, on synthetic data:
|
|
122
|
+
|
|
123
|
+
>>> import matplotlib
|
|
124
|
+
>>> matplotlib.use("Agg")
|
|
125
|
+
>>> import numpy as np
|
|
126
|
+
>>> import xarray as xr
|
|
127
|
+
>>> import plasma_plots
|
|
128
|
+
>>> t = np.linspace(0.0, 20.0, 201)
|
|
129
|
+
>>> x = np.linspace(0.0, 1.0, 64, endpoint=False)
|
|
130
|
+
>>> phi = xr.DataArray(
|
|
131
|
+
... 0.01 * np.exp(0.1 * t)[:, None] * np.sin(2 * np.pi * x)[None],
|
|
132
|
+
... dims=("t", "eta1"),
|
|
133
|
+
... coords={"t": t, "eta1": x},
|
|
134
|
+
... name="phi",
|
|
135
|
+
... )
|
|
136
|
+
>>> # the k = 1 amplitude over t
|
|
137
|
+
>>> amplitude = phi.plasma.analysis.project_mode(dim="eta1", number=1)
|
|
138
|
+
>>> round(
|
|
139
|
+
... float(amplitude.plasma.analysis.growth_rate(window=(5.0, 20.0)).rate),
|
|
140
|
+
... 3,
|
|
141
|
+
... )
|
|
142
|
+
0.1
|
|
143
|
+
>>> result = phi.plasma.plot.slice(x="eta1", y="t") # a space-time map
|
|
144
|
+
>>> type(result).__name__
|
|
145
|
+
'PlotResult'
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
from . import \
|
|
149
|
+
output_accessors # noqa: F401 (registers Output.plot, if struphy is installed)
|
|
150
|
+
from .accessors import PlasmaAccessor
|
|
151
|
+
from .desc import from_desc
|
|
152
|
+
from .figures import figure
|
|
153
|
+
from .gvec import from_gvec
|
|
154
|
+
from .mpi import SkippedPlot, is_plotting_rank, mpi_rank
|
|
155
|
+
from .plotly_backend import get_backend, set_backend
|
|
156
|
+
from .plotting import save_figure
|
|
157
|
+
|
|
158
|
+
__all__ = [
|
|
159
|
+
"SkippedPlot",
|
|
160
|
+
"PlasmaAccessor",
|
|
161
|
+
"figure",
|
|
162
|
+
"from_desc",
|
|
163
|
+
"from_gvec",
|
|
164
|
+
"get_backend",
|
|
165
|
+
"is_plotting_rank",
|
|
166
|
+
"mpi_rank",
|
|
167
|
+
"save_figure",
|
|
168
|
+
"set_backend",
|
|
169
|
+
]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""``python -m plasma_plots``: the ``plasma-plots`` command (see :mod:`plasma_plots.cli`).
|
|
2
|
+
|
|
3
|
+
Without a command it prints the package guide (the same as ``help(plasma_plots)``);
|
|
4
|
+
``python -m plasma_plots api`` prints the API index (see ``API.md``).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from plasma_plots.cli import main
|
|
10
|
+
|
|
11
|
+
sys.exit(main())
|