sdf-xarray 0.7.4__tar.gz → 0.9.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.
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/.github/workflows/build_publish.yml +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/.github/workflows/tests.yml +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/PKG-INFO +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/animation.md +10 -5
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/animating/animate_1D_density.py +2 -2
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/animating/animate_1D_poynting_flux.py +2 -2
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/animating/animate_2D_dist_fn_multispecies.py +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/animating/animate_2D_dist_fn_multispecies_alternative.py +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/animating/animate_2D_poynting_flux.py +2 -2
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/live_demo.ipynb +2 -2
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_1D_density.py +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_1D_poynting_flux.py +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_2D_density.py +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_2D_dist_fn_multispecies.py +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_2D_poynting_flux.py +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_time_temperature.py +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_x_px_scatter.py +1 -1
- sdf_xarray-0.9.0/docs/epoch_workshop_2026/workshop_details.md +7 -0
- sdf_xarray-0.9.0/docs/figures/voxel_plot_high_res.png +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/index.md +1 -0
- sdf_xarray-0.9.0/docs/plotting.md +95 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/understanding_datasets.md +51 -18
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/unit_conversion.md +4 -4
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/why_sdf_xarray.md +1 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/pyproject.toml +10 -2
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/src/sdf_xarray/_version.py +3 -3
- sdf_xarray-0.9.0/src/sdf_xarray/dataarray_accessor.py +226 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/src/sdf_xarray/dataset_accessor.py +30 -18
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/src/sdf_xarray/plotting.py +247 -10
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/tests/test_epoch_dataarray_accessor.py +252 -29
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/tests/test_epoch_dataset_accessor.py +43 -1
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/uv.lock +141 -0
- sdf_xarray-0.7.4/docs/epoch_workshop_2026/workshop_details.md +0 -7
- sdf_xarray-0.7.4/src/sdf_xarray/dataarray_accessor.py +0 -74
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/.github/workflows/lint.yml +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/.gitignore +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/.gitmodules +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/.readthedocs.yaml +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/CITATION.cff +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/CMakeLists.txt +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/CONTRIBUTING.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/LICENCE +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/README.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/.gitignore +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/_static/BEAM.png +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/_static/PlasmaFAIR.svg +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/_static/force_render_dark_xarray_objects.css +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/_static/sdf-xarray-logo-dark.svg +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/_static/sdf-xarray-logo-light.svg +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/_templates/custom-class-template.rst +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/_templates/custom-module-template.rst +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/api.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/conf.py +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/contributing.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/animations.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/histograms/plot_hist_ke.py +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/histograms/plot_hist_ke_probe.py +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/histograms/plot_hist_px.py +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/histograms.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plots.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/installation.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/known_issues.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/loading_data.md +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/make.bat +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/src/sdf_xarray/__init__.py +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/src/sdf_xarray/csdf.pxd +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/src/sdf_xarray/download.py +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/src/sdf_xarray/sdf_interface.pyx +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/tests/test_cython.py +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/tests/test_dataset.py +0 -0
- {sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/tests/test_datatree.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sdf-xarray
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Provides a backend for xarray to read SDF files as created by the EPOCH plasma PIC code.
|
|
5
5
|
Author-Email: Peter Hill <peter.hill@york.ac.uk>, Joel Adams <joel.adams@york.ac.uk>, Shaun Doherty <shaun.doherty@york.ac.uk>, Chris Herdman <chris.herdman@york.ac.uk>, Liam Pattinson <liam.pattinson@york.ac.uk>, Sviatoslav Shekhanov <sviatoslav.shekhanov@york.ac.uk>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -35,9 +35,10 @@ resolved data has 2 dimensions.
|
|
|
35
35
|
|
|
36
36
|
| Dimensions | Plotting function | Notes |
|
|
37
37
|
| ---------- | ----------------------------- | --------------------- |
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
38
|
+
| 2 | <inv:#xarray.plot.line> | |
|
|
39
|
+
| 3 | <inv:#xarray.plot.pcolormesh> | |
|
|
40
|
+
| 4 | <inv:#mpl_toolkits.mplot3d.axes3d.Axes3D.voxels>| WIP |
|
|
41
|
+
| >4 | <inv:#xarray.plot.hist> | Not fully implemented |
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
### 1D simulation
|
|
@@ -103,6 +104,10 @@ anim.show()
|
|
|
103
104
|
|
|
104
105
|
### 3D simulation
|
|
105
106
|
|
|
107
|
+
```{warning}
|
|
108
|
+
[Voxel](./plotting.md#voxel-plots) animations are not currently implemented.
|
|
109
|
+
```
|
|
110
|
+
|
|
106
111
|
Opening a 3D simulation as a multi-file dataset and plotting it will
|
|
107
112
|
return a <inv:#xarray.plot.hist>. However, this may not be
|
|
108
113
|
desirable. We can plot a 3D simulation along a certain plane in the
|
|
@@ -170,8 +175,8 @@ Some functionality such as `aspect` and `size` are not fully implemented yet.
|
|
|
170
175
|
ds = sdfxr.open_mfdataset("tutorial_dataset_2d/*.sdf")
|
|
171
176
|
|
|
172
177
|
# Change the units of the coordinates
|
|
173
|
-
ds = ds.epoch.rescale_coords(
|
|
174
|
-
ds = ds.epoch.rescale_coords(
|
|
178
|
+
ds = ds.epoch.rescale_coords("µm", ["X_Grid_mid", "Y_Grid_mid"])
|
|
179
|
+
ds = ds.epoch.rescale_coords("fs", ["time"])
|
|
175
180
|
ds["time"].attrs["long_name"] = "t"
|
|
176
181
|
|
|
177
182
|
# Change units and name of the variable
|
{sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/animating/animate_1D_density.py
RENAMED
|
@@ -6,9 +6,9 @@ input_dir = Path("datasets/1_1_drifting_bunch")
|
|
|
6
6
|
ds = sdfxr.open_mfdataset(input_dir)
|
|
7
7
|
|
|
8
8
|
# Convert the time to femtoseconds
|
|
9
|
-
ds = ds.epoch.rescale_coords(
|
|
9
|
+
ds = ds.epoch.rescale_coords("fs", "time", 1e15)
|
|
10
10
|
# Convert the x and y coords to microns
|
|
11
|
-
ds = ds.epoch.rescale_coords(
|
|
11
|
+
ds = ds.epoch.rescale_coords("µm", ["X_Grid_mid"], 1e6)
|
|
12
12
|
|
|
13
13
|
anim = ds["Derived_Number_Density"].epoch.animate()
|
|
14
14
|
|
{sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/animating/animate_1D_poynting_flux.py
RENAMED
|
@@ -8,9 +8,9 @@ input_dir = Path("datasets/3_3_Gaussian_1d_laser")
|
|
|
8
8
|
ds = sdfxr.open_mfdataset(input_dir)
|
|
9
9
|
|
|
10
10
|
# Convert the time to femtoseconds
|
|
11
|
-
ds = ds.epoch.rescale_coords(
|
|
11
|
+
ds = ds.epoch.rescale_coords("fs", "time", 1e15)
|
|
12
12
|
# Convert the x and y coords to microns
|
|
13
|
-
ds = ds.epoch.rescale_coords(
|
|
13
|
+
ds = ds.epoch.rescale_coords("µm", ["X_Grid_mid"], 1e6)
|
|
14
14
|
|
|
15
15
|
# Calculate Poynting flux magnitude
|
|
16
16
|
flux_magnitude = np.sqrt(
|
|
@@ -8,7 +8,7 @@ ds = sdfxr.open_mfdataset(
|
|
|
8
8
|
)
|
|
9
9
|
|
|
10
10
|
# Rescale coords to account for kilometers
|
|
11
|
-
ds = ds.epoch.rescale_coords(
|
|
11
|
+
ds = ds.epoch.rescale_coords("km", ["X_x_px_Left"], 1e-3)
|
|
12
12
|
|
|
13
13
|
# Sum phase-space of species "Left" and "Right" in "x_px" distribution function
|
|
14
14
|
# NOTE: We only use the values from the right distribution function as if we inherit
|
|
@@ -11,7 +11,7 @@ ds = sdfxr.open_mfdataset(
|
|
|
11
11
|
)
|
|
12
12
|
|
|
13
13
|
# Rescale coords to account for kilometers
|
|
14
|
-
ds = ds.epoch.rescale_coords(
|
|
14
|
+
ds = ds.epoch.rescale_coords("km", ["X_x_px_Left"], 1e-3)
|
|
15
15
|
|
|
16
16
|
# Sum phase-space of species "Left" and "Right" in "x_px" distribution function
|
|
17
17
|
# NOTE: We only use the values from the right distribution function as if we inherit
|
{sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/animating/animate_2D_poynting_flux.py
RENAMED
|
@@ -8,9 +8,9 @@ input_dir = Path("datasets/3_5_Gaussian_beam")
|
|
|
8
8
|
ds = sdfxr.open_mfdataset(input_dir)
|
|
9
9
|
|
|
10
10
|
# Convert the time to femtoseconds
|
|
11
|
-
ds = ds.epoch.rescale_coords(
|
|
11
|
+
ds = ds.epoch.rescale_coords("fs", "time", 1e15)
|
|
12
12
|
# Convert the x and y coords to microns
|
|
13
|
-
ds = ds.epoch.rescale_coords(
|
|
13
|
+
ds = ds.epoch.rescale_coords("µm", ["X_Grid_mid", "Y_Grid_mid"], 1e6)
|
|
14
14
|
|
|
15
15
|
# Calculate Poynting flux magnitude
|
|
16
16
|
flux_magnitude = np.sqrt(
|
|
@@ -3800,7 +3800,7 @@
|
|
|
3800
3800
|
},
|
|
3801
3801
|
{
|
|
3802
3802
|
"cell_type": "code",
|
|
3803
|
-
"execution_count":
|
|
3803
|
+
"execution_count": null,
|
|
3804
3804
|
"id": "2ef27498",
|
|
3805
3805
|
"metadata": {
|
|
3806
3806
|
"colab": {
|
|
@@ -3833,7 +3833,7 @@
|
|
|
3833
3833
|
}
|
|
3834
3834
|
],
|
|
3835
3835
|
"source": [
|
|
3836
|
-
"ds = ds.epoch.rescale_coords(
|
|
3836
|
+
"ds = ds.epoch.rescale_coords(\"µm\", [\"X_Grid_mid\", \"Y_Grid_mid\"], 1e6)\n",
|
|
3837
3837
|
"ds[\"Derived_Number_Density_Electron\"].isel(time=0).epoch.plot()"
|
|
3838
3838
|
]
|
|
3839
3839
|
},
|
|
@@ -8,7 +8,7 @@ import sdf_xarray as sdfxr
|
|
|
8
8
|
input_dir = Path("datasets/1_1_drifting_bunch")
|
|
9
9
|
|
|
10
10
|
ds = sdfxr.open_dataset(input_dir / "0000.sdf")
|
|
11
|
-
ds = ds.epoch.rescale_coords(
|
|
11
|
+
ds = ds.epoch.rescale_coords("µm", ["X_Grid_mid"], 1e6)
|
|
12
12
|
|
|
13
13
|
ds["Derived_Number_Density"].epoch.plot()
|
|
14
14
|
plt.tight_layout()
|
{sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_1D_poynting_flux.py
RENAMED
|
@@ -10,7 +10,7 @@ input_dir = Path("datasets/3_3_Gaussian_1d_laser")
|
|
|
10
10
|
ds = sdfxr.open_dataset(input_dir / "0020.sdf")
|
|
11
11
|
|
|
12
12
|
# Convert the x and y coords to microns
|
|
13
|
-
ds = ds.epoch.rescale_coords(
|
|
13
|
+
ds = ds.epoch.rescale_coords("µm", ["X_Grid_mid"], 1e6)
|
|
14
14
|
|
|
15
15
|
# Calculate Poynting flux magnitude
|
|
16
16
|
flux_magnitude = np.sqrt(
|
|
@@ -8,7 +8,7 @@ import sdf_xarray as sdfxr
|
|
|
8
8
|
input_dir = Path("datasets/4_3_basic_target")
|
|
9
9
|
|
|
10
10
|
ds = sdfxr.open_dataset(input_dir / "0000.sdf")
|
|
11
|
-
ds = ds.epoch.rescale_coords(
|
|
11
|
+
ds = ds.epoch.rescale_coords("µm", ["X_Grid_mid", "Y_Grid_mid"], 1e6)
|
|
12
12
|
|
|
13
13
|
ds["Derived_Number_Density"].epoch.plot()
|
|
14
14
|
plt.tight_layout()
|
|
@@ -8,7 +8,7 @@ import sdf_xarray as sdfxr
|
|
|
8
8
|
input_dir = Path("datasets/2_1_two_stream_instability")
|
|
9
9
|
ds = sdfxr.open_dataset(input_dir / "0000.sdf")
|
|
10
10
|
|
|
11
|
-
ds = ds.epoch.rescale_coords(
|
|
11
|
+
ds = ds.epoch.rescale_coords("km", ["X_x_px_Left"], 1e-3)
|
|
12
12
|
|
|
13
13
|
# Sum phase-space of species "Left" and "Right" in "x_px" distribution function
|
|
14
14
|
# NOTE: We only use the values from the right distribution function as if we inherit
|
{sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_2D_poynting_flux.py
RENAMED
|
@@ -10,7 +10,7 @@ input_dir = Path("datasets/3_5_Gaussian_beam")
|
|
|
10
10
|
ds = sdfxr.open_dataset(input_dir / "0001.sdf")
|
|
11
11
|
|
|
12
12
|
# Convert the x and y coords to microns
|
|
13
|
-
ds = ds.epoch.rescale_coords(
|
|
13
|
+
ds = ds.epoch.rescale_coords("µm", ["X_Grid_mid", "Y_Grid_mid"], 1e6)
|
|
14
14
|
|
|
15
15
|
# Calculate Poynting flux magnitude
|
|
16
16
|
flux_magnitude = np.sqrt(
|
{sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_time_temperature.py
RENAMED
|
@@ -13,7 +13,7 @@ input_dir = Path("datasets/4_2_self_heating")
|
|
|
13
13
|
ds = sdfxr.open_mfdataset(input_dir)
|
|
14
14
|
|
|
15
15
|
# Convert the time to femtoseconds
|
|
16
|
-
ds = ds.epoch.rescale_coords(
|
|
16
|
+
ds = ds.epoch.rescale_coords("fs", "time", 1e15)
|
|
17
17
|
|
|
18
18
|
# Averate temperature over all spatial cells at each time-step
|
|
19
19
|
kB = 1.380649e-23
|
{sdf_xarray-0.7.4 → sdf_xarray-0.9.0}/docs/epoch_workshop_2026/plotting/plot_x_px_scatter.py
RENAMED
|
@@ -9,7 +9,7 @@ input_dir = Path("datasets/5_2_subsets")
|
|
|
9
9
|
ds = sdfxr.open_dataset(input_dir / "0000.sdf", keep_particles=True)
|
|
10
10
|
|
|
11
11
|
ds = ds.epoch.rescale_coords(
|
|
12
|
-
|
|
12
|
+
"µm", ["X_Particles_subset_Refluxers_Electron", "Y_Target_mid"], 1e6
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
x = ds["X_Particles_subset_Refluxers_Electron"]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Workshop Details
|
|
2
|
+
|
|
3
|
+
The workshop consisted of a series of talks and practical sessions delivered at the University of York over the course of 2 days (23-24 April). It covered setting up both `EPOCH` and `sdf-xarray` along with delving into the details of how PIC codes work. The timetable is located [here](https://epochpic.github.io/quickstart/epoch_workshop_2026.html) and recordings of the presentations can be found on [YouTube](https://youtube.com/playlist?list=PLXfw-OhAIheRtwRqrGZvMqFuQ2GrIBLVl).
|
|
4
|
+
|
|
5
|
+
## Live Demo
|
|
6
|
+
|
|
7
|
+
As part of the start of the workshop a live demo covering the key features of `sdf-xarray` was performed. You can download this jupyter notebook in order to follow along <path:live_demo.ipynb>. Alternatively, if you have a Google account you can use the online [Google Colab notebook](https://colab.research.google.com/drive/1FTKj6gUizKjcL1ZSK4sNKlWKs5mzrD2g?usp=sharing).
|
|
Binary file
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
file_format: mystnb
|
|
3
|
+
kernelspec:
|
|
4
|
+
name: python3
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Plotting
|
|
8
|
+
|
|
9
|
+
You can plot datasets using
|
|
10
|
+
[`xarray.DataArray.epoch.plot`](project:#sdf_xarray.dataarray_accessor.EpochAccessor.plot).
|
|
11
|
+
This is a custom <project:#sdf_xarray> plotting routine that builds on top of
|
|
12
|
+
<inv:#xarray.DataArray.plot>, so you keep the familiar <inv:#xarray> plotting
|
|
13
|
+
behaviour while using <project:#sdf_xarray> conveniences (see
|
|
14
|
+
[here](project:#sdf_xarray.dataarray_accessor.EpochAccessor.plot) for details).
|
|
15
|
+
Under the hood, plotting is still handled by <inv:#matplotlib>, which means you
|
|
16
|
+
can use the full <inv:#matplotlib> API to customise your figure.
|
|
17
|
+
|
|
18
|
+
| Dimensions | Base plotting function | Notes |
|
|
19
|
+
| ---------- | ----------------------------- | --------------------- |
|
|
20
|
+
| 1 | <inv:#xarray.plot.line> | |
|
|
21
|
+
| 2 | <inv:#xarray.plot.pcolormesh> | |
|
|
22
|
+
| 3 | <inv:#mpl_toolkits.mplot3d.axes3d.Axes3D.voxels>| Custom functionality built for <project:#sdf_xarray> |
|
|
23
|
+
| >3 | <inv:#xarray.plot.hist> | Not fully implemented |
|
|
24
|
+
|
|
25
|
+
## Line plots
|
|
26
|
+
|
|
27
|
+
One dimensional data will be plotted as a line. Multiple lines can be easily
|
|
28
|
+
plotted at the same time.
|
|
29
|
+
|
|
30
|
+
```{code-cell} ipython3
|
|
31
|
+
import sdf_xarray as sdfxr
|
|
32
|
+
import matplotlib.pyplot as plt
|
|
33
|
+
ds = sdfxr.open_dataset("tutorial_dataset_1d/0010.sdf")
|
|
34
|
+
da_1 = ds["Derived_Number_Density_Electron"]
|
|
35
|
+
da_2 = ds["Derived_Number_Density_Ion"]
|
|
36
|
+
da_1.epoch.plot(label = "Electron")
|
|
37
|
+
da_2.epoch.plot(label = "Ion")
|
|
38
|
+
plt.legend()
|
|
39
|
+
plt.show()
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Mesh plots
|
|
43
|
+
|
|
44
|
+
Two dimensional data will be plotted as a mesh.
|
|
45
|
+
|
|
46
|
+
```{code-cell} ipython3
|
|
47
|
+
ds = sdfxr.open_dataset("tutorial_dataset_2d/0010.sdf")
|
|
48
|
+
da = ds["Derived_Number_Density_Electron"]
|
|
49
|
+
da.epoch.plot()
|
|
50
|
+
plt.show()
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Voxel plots
|
|
54
|
+
|
|
55
|
+
Three dimensional data will be plotted using voxels. This behaviour is not native
|
|
56
|
+
to <inv:#xarray>, it has been custom built specifically for this package.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
ds = sdfxr.open_dataset("tutorial_dataset_3d/0000.sdf")
|
|
60
|
+
da = ds["Derived_Number_Density"]
|
|
61
|
+
da.epoch.plot(vmin = 1e27)
|
|
62
|
+
plt.show()
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+

|
|
66
|
+
|
|
67
|
+
```{warning}
|
|
68
|
+
Voxel plots can be extremely computationally expensive and may take longer than
|
|
69
|
+
expected to plot.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Because voxel plots are very expensive, even with relatively small data arrays,
|
|
73
|
+
plotting can be sped up by using [`xarray.DataArray.epoch.resize`](project:#sdf_xarray.dataarray_accessor.EpochAccessor.resize),
|
|
74
|
+
which uses interpolation to reduce the resolution.
|
|
75
|
+
|
|
76
|
+
```{code-cell} ipython3
|
|
77
|
+
ds = sdfxr.open_dataset("tutorial_dataset_3d/0005.sdf")
|
|
78
|
+
da = ds["Derived_Number_Density"]
|
|
79
|
+
da_resized = da.epoch.resize((20, 20, 20))
|
|
80
|
+
da_resized.epoch.plot(vmin = 1e27)
|
|
81
|
+
plt.show()
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Histograms
|
|
85
|
+
|
|
86
|
+
When the data array has four or more dimensions (or is specified by the user), it will
|
|
87
|
+
be plotted as a histogram.
|
|
88
|
+
|
|
89
|
+
```{code-cell} ipython3
|
|
90
|
+
ds = sdfxr.open_dataset("tutorial_dataset_3d/0005.sdf")
|
|
91
|
+
da = ds["Derived_Number_Density"]
|
|
92
|
+
|
|
93
|
+
da.epoch.plot(hist = True)
|
|
94
|
+
plt.show()
|
|
95
|
+
```
|
|
@@ -29,23 +29,10 @@ ds = sdfxr.open_mfdataset("tutorial_dataset_1d/*.sdf")
|
|
|
29
29
|
ds["Electric_Field_Ex"]
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Visualisation
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
[
|
|
36
|
-
This is a custom <project:#sdf_xarray> plotting routine that builds on top of
|
|
37
|
-
<inv:#xarray.DataArray.plot>, so you keep the familiar <inv:#xarray> plotting
|
|
38
|
-
behaviour while using <project:#sdf_xarray> conveniences (see
|
|
39
|
-
[here](project:#sdf_xarray.dataarray_accessor.EpochAccessor.plot) for details).
|
|
40
|
-
Under the hood, plotting is still handled by <inv:#matplotlib>, which means you
|
|
41
|
-
can use the full <inv:#matplotlib> API to customise your figure.
|
|
42
|
-
|
|
43
|
-
```{code-cell} ipython3
|
|
44
|
-
# This is discretized in both space and time
|
|
45
|
-
ds["Electric_Field_Ex"].epoch.plot()
|
|
46
|
-
plt.title("Electric field along the x-axis")
|
|
47
|
-
plt.show()
|
|
48
|
-
```
|
|
34
|
+
`sdf-xarray` has built-in plotting and animation functionality, more details can
|
|
35
|
+
be found on [](./plotting.md) and [](./animation.md).
|
|
49
36
|
|
|
50
37
|
## Dimension slicing
|
|
51
38
|
|
|
@@ -56,6 +43,7 @@ for easy indexing. To quickly determine the number of time steps available,
|
|
|
56
43
|
you can check the size of the time dimension.
|
|
57
44
|
|
|
58
45
|
```{code-cell} ipython3
|
|
46
|
+
ds = sdfxr.open_mfdataset("tutorial_dataset_1d/*.sdf")
|
|
59
47
|
# This corresponds to the number of individual SDF files loaded
|
|
60
48
|
print(f"There are a total of {ds['time'].size} time steps")
|
|
61
49
|
|
|
@@ -66,7 +54,7 @@ print(f"The time at the 20th simulation step is {sim_time:.2e} s")
|
|
|
66
54
|
|
|
67
55
|
You can select and extract a single simulation snapshot using the integer
|
|
68
56
|
index of the time step with the <inv:#xarray.Dataset.isel> function. This can be
|
|
69
|
-
done by
|
|
57
|
+
done by passing the index to the `time` parameter (e.g., `time=0` for
|
|
70
58
|
the first snapshot).
|
|
71
59
|
|
|
72
60
|
```{code-cell} ipython3
|
|
@@ -74,7 +62,7 @@ ds["Electric_Field_Ex"].isel(time=20)
|
|
|
74
62
|
```
|
|
75
63
|
|
|
76
64
|
We can also use the <inv:#xarray.Dataset.sel> function if you wish to pass a
|
|
77
|
-
value
|
|
65
|
+
value instead of an index.
|
|
78
66
|
|
|
79
67
|
```{tip}
|
|
80
68
|
If you know roughly what time you wish to select but not the exact value
|
|
@@ -122,6 +110,51 @@ print(f"Total particle energy absorbed: {ds["Total_Particle_Energy_in_Simulation
|
|
|
122
110
|
print(f"The laser absorption fraction: {ds["Laser_Absorption_Fraction_in_Simulation"][-1].values:.1f} %")
|
|
123
111
|
```
|
|
124
112
|
|
|
113
|
+
## Limit
|
|
114
|
+
|
|
115
|
+
The `.epoch` accessor has the ability to "limit" data arrays. This is a helper
|
|
116
|
+
function which applies <inv:#xarray.DataArray.where> to the upper and lower bounds
|
|
117
|
+
of each dimension. You can use `None` to preserve the existing limit.
|
|
118
|
+
|
|
119
|
+
```{code-cell} ipython3
|
|
120
|
+
ds = sdfxr.open_dataset("tutorial_dataset_2d/0020.sdf")
|
|
121
|
+
da = ds["Derived_Number_Density_Electron"]
|
|
122
|
+
da.epoch.plot()
|
|
123
|
+
print(f"Orignal shape: {da.shape}")
|
|
124
|
+
plt.show()
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
```{code-cell} ipython3
|
|
128
|
+
da_limit = da.epoch.limit(((-2e-6, 2e-6), (None, 0)))
|
|
129
|
+
da_limit.epoch.plot()
|
|
130
|
+
print(f"New shape: {da_limit.shape}")
|
|
131
|
+
plt.show()
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Resize
|
|
135
|
+
|
|
136
|
+
The data arrays can be interpolated with <project:#sdf_xarray.dataarray_accessor.EpochAccessor.resize>
|
|
137
|
+
to either increase or decrease the resolution while mantaining the general structure.
|
|
138
|
+
Decreasing the size may be useful to download large data from HPCs to local machines
|
|
139
|
+
or ploting with [](./plotting.md#voxel-plots). Be aware that the original
|
|
140
|
+
data will not be preserved.
|
|
141
|
+
|
|
142
|
+
```{code-cell} ipython3
|
|
143
|
+
ds = sdfxr.open_dataset("tutorial_dataset_2d/0020.sdf")
|
|
144
|
+
da = ds["Derived_Number_Density_Electron"]
|
|
145
|
+
|
|
146
|
+
da.epoch.plot()
|
|
147
|
+
print(f"Orignal shape: {da.shape}")
|
|
148
|
+
plt.show()
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```{code-cell} ipython3
|
|
152
|
+
da_resized = da.epoch.resize((50, 50))
|
|
153
|
+
da_resized.epoch.plot()
|
|
154
|
+
print(f"New shape: {da_resized.shape}")
|
|
155
|
+
plt.show()
|
|
156
|
+
```
|
|
157
|
+
|
|
125
158
|
## Visualisation on HPC Machines
|
|
126
159
|
|
|
127
160
|
In many cases you will be running EPOCH simulations via a HPC cluster and your
|
|
@@ -30,7 +30,7 @@ plt.rcParams.update({
|
|
|
30
30
|
For simple scaling and unit relabelling of coordinates (e.g., converting meters to microns),
|
|
31
31
|
the most straightforward approach is to use the [`xarray.Dataset.epoch.rescale_coords`](project:#sdf_xarray.dataset_accessor.EpochAccessor.rescale_coords) dataset accessor.
|
|
32
32
|
This function scales the coordinate values by a given multiplier and updates the
|
|
33
|
-
`"units"` attribute in one step.
|
|
33
|
+
`"units"` attribute in one step. If the multiplier is not specified then the conversion parameter is inferred from the units and converted automatically using `pint` (see [](#unit-conversion-with-pint-xarray) for details).
|
|
34
34
|
|
|
35
35
|
### Rescaling grid coordinates
|
|
36
36
|
|
|
@@ -41,7 +41,7 @@ We can use the [`xarray.Dataset.epoch.rescale_coords`](project:#sdf_xarray.datas
|
|
|
41
41
|
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))
|
|
42
42
|
|
|
43
43
|
ds = sdfxr.open_mfdataset("tutorial_dataset_2d/*.sdf")
|
|
44
|
-
ds_in_microns = ds.epoch.rescale_coords(
|
|
44
|
+
ds_in_microns = ds.epoch.rescale_coords("µm", ["X_Grid_mid", "Y_Grid_mid"], 1e6)
|
|
45
45
|
|
|
46
46
|
ds["Derived_Number_Density_Electron"].isel(time=0).epoch.plot(ax=ax1)
|
|
47
47
|
ax1.set_title("Original X Coordinate (m)")
|
|
@@ -55,7 +55,7 @@ fig.tight_layout()
|
|
|
55
55
|
### Rescaling time coordinate
|
|
56
56
|
|
|
57
57
|
We can also use the [`xarray.Dataset.epoch.rescale_coords`](project:#sdf_xarray.dataset_accessor.EpochAccessor.rescale_coords) method to convert the time coordinate from
|
|
58
|
-
seconds (`s`) to femto-seconds (`fs`)
|
|
58
|
+
seconds (`s`) to femto-seconds (`fs`).
|
|
59
59
|
|
|
60
60
|
```{code-cell} ipython3
|
|
61
61
|
ds = sdfxr.open_mfdataset("tutorial_dataset_2d/*.sdf")
|
|
@@ -63,7 +63,7 @@ ds["time"]
|
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
```{code-cell} ipython3
|
|
66
|
-
ds = ds.epoch.rescale_coords(
|
|
66
|
+
ds = ds.epoch.rescale_coords("fs", "time")
|
|
67
67
|
ds["time"]
|
|
68
68
|
```
|
|
69
69
|
|
|
@@ -7,7 +7,7 @@ There are several benefits to using this package over the [`sdf_helper`](https:/
|
|
|
7
7
|
- [data to numpy and pandas](https://docs.xarray.dev/en/stable/user-guide/pandas.html) - Data can be easily converted to [numpy](https://www.numpy.org/) or [pandas](https://pandas.pydata.org/) if you prefer to work with raw data.
|
|
8
8
|
- [data labelling](project:understanding_datasets.md) - All SDF files come with a bunch of information about them such as the `dimensions`, `units` and `name` of the variable. In <inv:#xarray> these are added to each variable making it much easier to read.
|
|
9
9
|
- [lazy/partial loading](https://docs.xarray.dev/en/stable/internals/internal-design.html#lazy-loading) - This reduces the RAM requirements when loading large SDF files as we only load the actual array values when they are needed.
|
|
10
|
-
- [plotting](project:
|
|
10
|
+
- [plotting](project:plotting.md) - You can easily plot variables across several dimensions including time using built in <inv:#matplotlib> support.
|
|
11
11
|
- [animating](project:animation.md) - Visualise your data across time or slice through another dimension and make beautiful GIFs for your presentations.
|
|
12
12
|
- [deck loading](loading-input-deck) - <project:#sdf_xarray> automatically loads in the associated `input.deck` utilised when creating the simulation so that you can access setup variables.
|
|
13
13
|
- [easier unit conversion](project:unit_conversion.md) - Convert dimensions and variable units to other types with the help of [`pint`](https://pint.readthedocs.io/en/stable).
|
|
@@ -69,6 +69,7 @@ docs = [
|
|
|
69
69
|
"sphinx-design>=0.7.0",
|
|
70
70
|
"pooch>=1.8.2",
|
|
71
71
|
"tqdm",
|
|
72
|
+
"scipy",
|
|
72
73
|
]
|
|
73
74
|
build = ["cibuildwheel[uv]"]
|
|
74
75
|
lint = ["ruff"]
|
|
@@ -78,6 +79,9 @@ test = [
|
|
|
78
79
|
"matplotlib",
|
|
79
80
|
"pooch>=1.8.2",
|
|
80
81
|
"tqdm",
|
|
82
|
+
"pint",
|
|
83
|
+
"pint-xarray",
|
|
84
|
+
"scipy",
|
|
81
85
|
]
|
|
82
86
|
|
|
83
87
|
[project.entry-points."xarray.backends"]
|
|
@@ -131,6 +135,10 @@ ignore = [
|
|
|
131
135
|
"PLR2004", # magic-comparison
|
|
132
136
|
"B9", # flake8-bugbear opinionated warnings
|
|
133
137
|
"PLR0913", # remove maximum number of arguments in a function
|
|
138
|
+
"PLR0917", # remove maximum number of positional arguments in a function
|
|
139
|
+
"BLE001", # allow capturing of base exception
|
|
134
140
|
]
|
|
135
|
-
exclude = ["**/_version.py"]
|
|
136
|
-
|
|
141
|
+
exclude = ["**/_version.py"] # Auto-generated file
|
|
142
|
+
|
|
143
|
+
[tool.pytest.ini_options]
|
|
144
|
+
filterwarnings = ['ignore::UserWarning']
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.
|
|
22
|
-
__version_tuple__ = version_tuple = (0,
|
|
21
|
+
__version__ = version = '0.9.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 9, 0)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g65bb865da'
|