sdf-xarray 0.8.0__tar.gz → 0.10.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.
Files changed (71) hide show
  1. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/.github/workflows/build_publish.yml +1 -1
  2. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/.github/workflows/tests.yml +1 -1
  3. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/PKG-INFO +1 -1
  4. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/animation.md +16 -20
  5. sdf_xarray-0.10.0/docs/figures/voxel_plot_high_res.png +0 -0
  6. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/index.md +1 -0
  7. sdf_xarray-0.10.0/docs/known_issues.md +8 -0
  8. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/loading_data.md +32 -17
  9. sdf_xarray-0.10.0/docs/plotting.md +95 -0
  10. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/understanding_datasets.md +51 -18
  11. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/why_sdf_xarray.md +1 -1
  12. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/pyproject.toml +8 -2
  13. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/src/sdf_xarray/__init__.py +138 -43
  14. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/src/sdf_xarray/_version.py +3 -3
  15. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/src/sdf_xarray/csdf.pxd +2 -0
  16. sdf_xarray-0.10.0/src/sdf_xarray/dataarray_accessor.py +226 -0
  17. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/src/sdf_xarray/download.py +18 -11
  18. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/src/sdf_xarray/plotting.py +247 -10
  19. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/src/sdf_xarray/sdf_interface.pyx +110 -14
  20. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/tests/test_cython.py +46 -0
  21. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/tests/test_dataset.py +87 -0
  22. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/tests/test_epoch_dataarray_accessor.py +252 -29
  23. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/uv.lock +141 -0
  24. sdf_xarray-0.8.0/docs/known_issues.md +0 -15
  25. sdf_xarray-0.8.0/src/sdf_xarray/dataarray_accessor.py +0 -74
  26. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/.github/workflows/lint.yml +0 -0
  27. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/.gitignore +0 -0
  28. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/.gitmodules +0 -0
  29. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/.readthedocs.yaml +0 -0
  30. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/CITATION.cff +0 -0
  31. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/CMakeLists.txt +0 -0
  32. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/CONTRIBUTING.md +0 -0
  33. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/LICENCE +0 -0
  34. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/README.md +0 -0
  35. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/.gitignore +0 -0
  36. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/_static/BEAM.png +0 -0
  37. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/_static/PlasmaFAIR.svg +0 -0
  38. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/_static/force_render_dark_xarray_objects.css +0 -0
  39. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/_static/sdf-xarray-logo-dark.svg +0 -0
  40. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/_static/sdf-xarray-logo-light.svg +0 -0
  41. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/_templates/custom-class-template.rst +0 -0
  42. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/_templates/custom-module-template.rst +0 -0
  43. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/api.md +0 -0
  44. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/conf.py +0 -0
  45. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/contributing.md +0 -0
  46. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/animating/animate_1D_density.py +0 -0
  47. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/animating/animate_1D_poynting_flux.py +0 -0
  48. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/animating/animate_2D_dist_fn_multispecies.py +0 -0
  49. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/animating/animate_2D_dist_fn_multispecies_alternative.py +0 -0
  50. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/animating/animate_2D_poynting_flux.py +0 -0
  51. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/animations.md +0 -0
  52. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/histograms/plot_hist_ke.py +0 -0
  53. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/histograms/plot_hist_ke_probe.py +0 -0
  54. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/histograms/plot_hist_px.py +0 -0
  55. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/histograms.md +0 -0
  56. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/live_demo.ipynb +0 -0
  57. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/plots.md +0 -0
  58. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/plotting/plot_1D_density.py +0 -0
  59. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/plotting/plot_1D_poynting_flux.py +0 -0
  60. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/plotting/plot_2D_density.py +0 -0
  61. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/plotting/plot_2D_dist_fn_multispecies.py +0 -0
  62. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/plotting/plot_2D_poynting_flux.py +0 -0
  63. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/plotting/plot_time_temperature.py +0 -0
  64. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/plotting/plot_x_px_scatter.py +0 -0
  65. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/epoch_workshop_2026/workshop_details.md +0 -0
  66. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/installation.md +0 -0
  67. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/make.bat +0 -0
  68. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/docs/unit_conversion.md +0 -0
  69. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/src/sdf_xarray/dataset_accessor.py +0 -0
  70. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/tests/test_datatree.py +0 -0
  71. {sdf_xarray-0.8.0 → sdf_xarray-0.10.0}/tests/test_epoch_dataset_accessor.py +0 -0
@@ -20,7 +20,7 @@ jobs:
20
20
  submodules: "recursive"
21
21
 
22
22
  - name: Cache Zenodo datasets
23
- uses: actions/cache@v4
23
+ uses: actions/cache@v6
24
24
  with:
25
25
  enableCrossOsArchive: true
26
26
  path: ~/.cache/sdf_datasets
@@ -31,7 +31,7 @@ jobs:
31
31
  uv sync --python ${{ matrix.python-version }} --frozen
32
32
 
33
33
  - name: Cache Zenodo datasets
34
- uses: actions/cache@v4
34
+ uses: actions/cache@v6
35
35
  with:
36
36
  path: ~/.cache/sdf_datasets
37
37
  key: sdf-datasets-17991042
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sdf-xarray
3
- Version: 0.8.0
3
+ Version: 0.10.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
@@ -12,7 +12,6 @@ mimic <inv:#xarray.DataArray.plot>.
12
12
 
13
13
  ```{code-cell} ipython3
14
14
  import sdf_xarray as sdfxr
15
- import xarray as xr
16
15
  import matplotlib.pyplot as plt
17
16
  from matplotlib.animation import FuncAnimation
18
17
  from IPython.display import HTML
@@ -35,9 +34,10 @@ resolved data has 2 dimensions.
35
34
 
36
35
  | Dimensions | Plotting function | Notes |
37
36
  | ---------- | ----------------------------- | --------------------- |
38
- | `2` | <inv:#xarray.plot.line> | |
39
- | `3` | <inv:#xarray.plot.pcolormesh> | |
40
- | `>3` | <inv:#xarray.plot.hist> | Not fully implemented |
37
+ | 2 | <inv:#xarray.plot.line> | |
38
+ | 3 | <inv:#xarray.plot.pcolormesh> | |
39
+ | 4 | <inv:#mpl_toolkits.mplot3d.axes3d.Axes3D.voxels>| WIP |
40
+ | >4 | <inv:#xarray.plot.hist> | Not fully implemented |
41
41
 
42
42
 
43
43
  ### 1D simulation
@@ -103,6 +103,10 @@ anim.show()
103
103
 
104
104
  ### 3D simulation
105
105
 
106
+ ```{warning}
107
+ [Voxel](./plotting.md#voxel-plots) animations are not currently implemented.
108
+ ```
109
+
106
110
  Opening a 3D simulation as a multi-file dataset and plotting it will
107
111
  return a <inv:#xarray.plot.hist>. However, this may not be
108
112
  desirable. We can plot a 3D simulation along a certain plane in the
@@ -134,31 +138,23 @@ EPOCH allows for simulations that have a moving simulation window
134
138
  `move_window` and change the x-axis limits accordingly.
135
139
 
136
140
  ```{warning}
137
- <project:#sdf_xarray.open_mfdataset> does not currently function with moving window data.
138
- You must use <inv:#xarray.open_mfdataset> and specify arguments in the following way.
141
+ Importing some datasets with moving windows can cause vertical banding
142
+ in the <inv:#xarray.Dataset>, which will affect the animation. Each output stores
143
+ its own x grid, and the same position can differ by floating point rounding between
144
+ outputs. Both values are then kept on the combined x axis, so each time step has
145
+ nan values in some columns. Setting `join = "override"` in
146
+ <inv:#xarray.open_mfdataset> does not fix this for moving window data, as it
147
+ relabels every time step with the first output's x grid.
139
148
  ```
140
149
 
141
150
  ```{code-cell} ipython3
142
- ds = xr.open_mfdataset(
143
- "tutorial_dataset_2d_moving_window/*.sdf",
144
- preprocess = sdfxr.SDFPreprocess(),
145
- combine = "nested",
146
- join = "outer",
147
- compat="no_conflicts",
148
- concat_dim="time",
149
- )
151
+ ds = sdfxr.open_mfdataset("tutorial_dataset_2d_moving_window/*.sdf")
150
152
 
151
153
  da = ds["Derived_Number_Density_Beam_Electrons"]
152
154
  anim = da.epoch.animate(move_window = True, fps = 5)
153
155
  anim.show()
154
156
  ```
155
157
 
156
- ```{warning}
157
- Importing some datasets with moving windows can cause vertical banding
158
- in the <inv:#xarray.Dataset>, which will affect the animation. The cause for
159
- this is unknown but can be circumvented by setting `join = "override"`.
160
- ```
161
-
162
158
  ## Customisation
163
159
 
164
160
  The animation can be customised in much the same way as <inv:#xarray.DataArray.plot>,
@@ -21,6 +21,7 @@ why_sdf_xarray.md
21
21
  loading_data.md
22
22
  understanding_datasets.md
23
23
  unit_conversion.md
24
+ plotting.md
24
25
  animation.md
25
26
  ```
26
27
 
@@ -0,0 +1,8 @@
1
+ # Known Issues
2
+
3
+ These are the known 'quirks' in `sdf_xarray`:
4
+
5
+ - [Issue #112](https://github.com/epochpic/sdf-xarray/issues/112) Due to the
6
+ way [cylindrical EPOCH](https://github.com/epochpic/cylindrical_epoch) sets up
7
+ grids we can't currently load it's SDF files. If there is enough interest in this
8
+ we will attempt to find a solution otherwise it shall remain low priority.
@@ -85,7 +85,11 @@ is by using the <project:#sdf_xarray.open_mfdataset>.
85
85
  ```{tip}
86
86
  If your simulation includes multiple `output` blocks that specify different variables
87
87
  for output at various time steps, variables not present at a specific step will default
88
- to a nan value. To remove these nan values we suggest using the <inv:#xarray.DataArray.dropna>
88
+ to a nan value. This includes distribution functions and particle data that are only
89
+ output at some time steps. Grids that change between outputs (such as a moving window,
90
+ or a distribution function with an automatic range) are combined onto the union of
91
+ every output's grid points, with nan values outside the part of the grid each output
92
+ covers. To remove these nan values we suggest using the <inv:#xarray.DataArray.dropna>
89
93
  function or following our implmentation in [](#loading-sparse-data).
90
94
  ```
91
95
 
@@ -98,13 +102,20 @@ sdfxr.open_mfdataset("tutorial_dataset_1d/*.sdf")
98
102
  Alternatively, files can be loaded using <inv:#xarray.open_mfdataset>. However, when loading in
99
103
  all the files we have do some processing of the data so that we can correctly align it along
100
104
  the time dimension; This is done via the `preprocess` parameter utilising the
101
- <project:#sdf_xarray.SDFPreprocess> function.
105
+ <project:#sdf_xarray.SDFPreprocess> function. Passing `combine="nested"` and
106
+ `concat_dim="time"` makes sure the files are only joined along time. Otherwise
107
+ <inv:#xarray> treats any coordinate that differs between files (such as a moving
108
+ window's x grid) as another dimension to concatenate along, which can fail or request
109
+ far more memory than needed. Unlike <project:#sdf_xarray.open_mfdataset>, this does
110
+ not handle particle positions that are missing from some files.
102
111
 
103
112
  ```{code-cell} ipython3
104
113
  import xarray as xr
105
114
 
106
115
  xr.open_mfdataset(
107
116
  "tutorial_dataset_1d/*.sdf",
117
+ combine="nested",
118
+ concat_dim="time",
108
119
  join="outer",
109
120
  compat="no_conflicts",
110
121
  preprocess=sdfxr.SDFPreprocess()
@@ -123,6 +134,9 @@ sdfxr.open_mfdatatree("tutorial_dataset_1d/*.sdf")
123
134
 
124
135
  ## Loading sparse data
125
136
 
137
+ By default, <project:#sdf_xarray.open_mfdataset> puts every variable on a single
138
+ time dimension, and a variable missing from an output (including distribution
139
+ functions and particle data) is filled with nan values at that time step.
126
140
  When dealing with sparse data (where different variables are saved at different,
127
141
  non-overlapping time steps) you can optimize memory usage by loading the data with
128
142
  <project:#sdf_xarray.open_mfdataset> using the parameter `separate_times=True`. This
@@ -140,12 +154,17 @@ sdfxr.open_mfdataset("tutorial_dataset_1d/*.sdf", separate_times=True)
140
154
  ## Loading particle data
141
155
 
142
156
  ```{warning}
143
- It is **not recommended** to use <inv:#xarray.open_mfdataset> or
144
- <project:#sdf_xarray.open_mfdataset> to load particle data from multiple
145
- SDF outputs. The number of particles often varies between outputs,
146
- which can lead to inconsistent array shapes that these functions
147
- cannot handle. Instead, consider loading each file individually and
148
- then concatenating them manually.
157
+ <project:#sdf_xarray.open_mfdataset> can load particle data from multiple
158
+ SDF outputs, and outputs that don't include particles are filled with nan
159
+ values. However, every output that does include a species must contain the
160
+ same number of particles of that species. The number of particles often
161
+ varies between outputs (for example with particle injection, losses or probes),
162
+ in which case loading fails with a conflicting dimension sizes error, and you
163
+ should load each file individually instead.
164
+
165
+ The `ID_<species>` dimension is the position in each output's particle array,
166
+ not a particle identity, so the same index at two time steps is not
167
+ necessarily the same particle.
149
168
  ```
150
169
 
151
170
  ```{note}
@@ -157,7 +176,7 @@ Failing to do so will result in dimension name conflicts.
157
176
 
158
177
  By default, particle data isn't kept as it takes up a lot of space.
159
178
  Pass `keep_particles=True` as a keyword argument to
160
- <inv:#xarray.open_dataset> (for single files) or <inv:#xarray.open_mfdataset> (for
179
+ <project:#sdf_xarray.open_dataset> (for single files) or <project:#sdf_xarray.open_mfdataset> (for
161
180
  multiple files).
162
181
 
163
182
  ```{code-cell} ipython3
@@ -168,14 +187,10 @@ sdfxr.open_dataset("tutorial_dataset_1d/0010.sdf", keep_particles=True)
168
187
 
169
188
  ## Loading specific variables
170
189
 
171
- When loading datasets containing several (`>10`) coordinates/dimensions
172
- using <project:#sdf_xarray.open_mfdataset>, <inv:#xarray> may struggle to locate
173
- the necessary RAM to concatenate all of the data (as seen in
174
- [Issue #57](https://github.com/epochpic/sdf-xarray/issues/57)).
175
- In this instance, you can optimize memory usage by loading only the data
176
- you need using the keyword argument `data_vars` and passing one or more
177
- variables. This creates a dataset consisting only of the given variable(s)
178
- and the relevant coordinates/dimensions, significantly reducing memory
190
+ If you only need some of the variables, you can load just those using the
191
+ keyword argument `data_vars` and passing one or more variables to
192
+ <project:#sdf_xarray.open_mfdataset>. This creates a dataset consisting only of
193
+ the given variable(s) and the relevant coordinates/dimensions, reducing memory
179
194
  consumption.
180
195
 
181
196
  ```{code-cell} ipython3
@@ -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
+ ![voxel_plot_high_res](./figures/voxel_plot_high_res.png)
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
- ## Plotting
32
+ ## Visualisation
33
33
 
34
- You can plot datasets using
35
- [`xarray.DataArray.epoch.plot`](project:#sdf_xarray.dataarray_accessor.EpochAccessor.plot).
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 passsing the index to the `time` parameter (e.g., `time=0` for
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 intead of an index.
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
@@ -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:understanding_datasets.md#plotting) - You can easily plot variables across several dimensions including time using built in <inv:#matplotlib> support.
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"]
@@ -80,6 +81,7 @@ test = [
80
81
  "tqdm",
81
82
  "pint",
82
83
  "pint-xarray",
84
+ "scipy",
83
85
  ]
84
86
 
85
87
  [project.entry-points."xarray.backends"]
@@ -133,6 +135,10 @@ ignore = [
133
135
  "PLR2004", # magic-comparison
134
136
  "B9", # flake8-bugbear opinionated warnings
135
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
136
140
  ]
137
- exclude = ["**/_version.py"]
138
- # Auto-generated file
141
+ exclude = ["**/_version.py"] # Auto-generated file
142
+
143
+ [tool.pytest.ini_options]
144
+ filterwarnings = ['ignore::UserWarning']