sdf-xarray 0.2.4__tar.gz → 0.2.6__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.

Potentially problematic release.


This version of sdf-xarray might be problematic. Click here for more details.

Files changed (117) hide show
  1. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/.github/workflows/build_publish.yml +1 -1
  2. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/CONTRIBUTING.md +6 -0
  3. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/PKG-INFO +8 -35
  4. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/index.rst +1 -0
  5. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/key_functionality.rst +6 -0
  6. sdf_xarray-0.2.6/docs/known_issues.rst +9 -0
  7. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/pyproject.toml +7 -10
  8. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/src/sdf_xarray/__init__.py +59 -7
  9. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/src/sdf_xarray/_version.py +16 -3
  10. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/src/sdf_xarray/plotting.py +2 -2
  11. sdf_xarray-0.2.6/tests/example_two_probes_2D/0000.sdf +0 -0
  12. sdf_xarray-0.2.6/tests/example_two_probes_2D/0001.sdf +0 -0
  13. sdf_xarray-0.2.6/tests/example_two_probes_2D/0002.sdf +0 -0
  14. sdf_xarray-0.2.6/tests/example_two_probes_2D/input.deck +188 -0
  15. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/test_basic.py +71 -0
  16. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/uv.lock +999 -1041
  17. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/.github/workflows/black.yml +0 -0
  18. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/.github/workflows/lint.yml +0 -0
  19. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/.github/workflows/tests.yml +0 -0
  20. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/.gitignore +0 -0
  21. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/.gitmodules +0 -0
  22. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/.readthedocs.yaml +0 -0
  23. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/BEAM.png +0 -0
  24. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/CITATION.cff +0 -0
  25. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/CMakeLists.txt +0 -0
  26. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/LICENCE +0 -0
  27. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/PlasmaFAIR.svg +0 -0
  28. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/README.md +0 -0
  29. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/.gitignore +0 -0
  30. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/_templates/custom-class-template.rst +0 -0
  31. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/_templates/custom-module-template.rst +0 -0
  32. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/api.rst +0 -0
  33. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/conf.py +0 -0
  34. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/contributing.rst +0 -0
  35. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/getting_started.rst +0 -0
  36. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/make.bat +0 -0
  37. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0000.sdf +0 -0
  38. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0001.sdf +0 -0
  39. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0002.sdf +0 -0
  40. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0003.sdf +0 -0
  41. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0004.sdf +0 -0
  42. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0005.sdf +0 -0
  43. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0006.sdf +0 -0
  44. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0007.sdf +0 -0
  45. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0008.sdf +0 -0
  46. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0009.sdf +0 -0
  47. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0010.sdf +0 -0
  48. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0011.sdf +0 -0
  49. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0012.sdf +0 -0
  50. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0013.sdf +0 -0
  51. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0014.sdf +0 -0
  52. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0015.sdf +0 -0
  53. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0016.sdf +0 -0
  54. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0017.sdf +0 -0
  55. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0018.sdf +0 -0
  56. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0019.sdf +0 -0
  57. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0020.sdf +0 -0
  58. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0021.sdf +0 -0
  59. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0022.sdf +0 -0
  60. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0023.sdf +0 -0
  61. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0024.sdf +0 -0
  62. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0025.sdf +0 -0
  63. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0026.sdf +0 -0
  64. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0027.sdf +0 -0
  65. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0028.sdf +0 -0
  66. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0029.sdf +0 -0
  67. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0030.sdf +0 -0
  68. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0031.sdf +0 -0
  69. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0032.sdf +0 -0
  70. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0033.sdf +0 -0
  71. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0034.sdf +0 -0
  72. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0035.sdf +0 -0
  73. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0036.sdf +0 -0
  74. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0037.sdf +0 -0
  75. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0038.sdf +0 -0
  76. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0039.sdf +0 -0
  77. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/0040.sdf +0 -0
  78. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/deck.status +0 -0
  79. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/epoch1d.dat +0 -0
  80. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/input.deck +0 -0
  81. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/normal.visit +0 -0
  82. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/tutorial_dataset_1d/restart.visit +0 -0
  83. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/docs/unit_conversion.rst +0 -0
  84. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/src/sdf_xarray/csdf.pxd +0 -0
  85. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/src/sdf_xarray/sdf_interface.pyx +0 -0
  86. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_array_no_grids/0000.sdf +0 -0
  87. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_array_no_grids/0001.sdf +0 -0
  88. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_array_no_grids/README.md +0 -0
  89. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_array_no_grids/input.deck +0 -0
  90. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_dist_fn/0000.sdf +0 -0
  91. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_dist_fn/0001.sdf +0 -0
  92. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_dist_fn/0002.sdf +0 -0
  93. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_dist_fn/input.deck +0 -0
  94. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0000.sdf +0 -0
  95. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0001.sdf +0 -0
  96. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0002.sdf +0 -0
  97. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0003.sdf +0 -0
  98. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0004.sdf +0 -0
  99. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0005.sdf +0 -0
  100. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0006.sdf +0 -0
  101. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0007.sdf +0 -0
  102. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0008.sdf +0 -0
  103. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0009.sdf +0 -0
  104. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/0010.sdf +0 -0
  105. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/README.md +0 -0
  106. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_1D/input.deck +0 -0
  107. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_2D_moving_window/0000.sdf +0 -0
  108. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_2D_moving_window/0001.sdf +0 -0
  109. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_2D_moving_window/0002.sdf +0 -0
  110. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_2D_moving_window/0003.sdf +0 -0
  111. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_2D_moving_window/0004.sdf +0 -0
  112. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_files_2D_moving_window/input.deck +0 -0
  113. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_mismatched_files/0000.sdf +0 -0
  114. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_mismatched_files/0001.sdf +0 -0
  115. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/example_mismatched_files/0002.sdf +0 -0
  116. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/test_cython.py +0 -0
  117. {sdf_xarray-0.2.4 → sdf_xarray-0.2.6}/tests/test_epoch_accessor.py +0 -0
@@ -32,7 +32,7 @@ jobs:
32
32
  uv sync --python 3.12 --extra test --extra build --frozen
33
33
 
34
34
  - name: Build
35
- uses: pypa/cibuildwheel@v2.21.3
35
+ uses: pypa/cibuildwheel@v3.1.3
36
36
  env:
37
37
  CIBW_ARCHS_LINUX: auto
38
38
  CIBW_ARCHS_MACOS: x86_64 arm64
@@ -68,6 +68,12 @@ pip install "sdf-xarray[docs]"
68
68
  cd docs
69
69
  make html
70
70
  ```
71
+
72
+ The documentation can be updated by changing any of the `*.rst` files located
73
+ in the main `docs` directory. The existing documentation hopefully includes most
74
+ of the snippets you'd need to write or update it, however if you are stuck
75
+ please don't hesitate to reach out.
76
+
71
77
  Every time you make changes to the documentation or add a new page, you must
72
78
  re-run the `make html` command to regenerate the HTML files.
73
79
 
@@ -1,47 +1,20 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: sdf-xarray
3
- Version: 0.2.4
3
+ Version: 0.2.6
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>
6
- License: Copyright 2024, Peter Hill, Joel Adams, epochpic team
7
-
8
- Redistribution and use in source and binary forms, with or without
9
- modification, are permitted provided that the following conditions are
10
- met:
11
-
12
- 1. Redistributions of source code must retain the above copyright
13
- notice, this list of conditions and the following disclaimer.
14
-
15
- 2. Redistributions in binary form must reproduce the above copyright
16
- notice, this list of conditions and the following disclaimer in the
17
- documentation and/or other materials provided with the distribution.
18
-
19
- 3. Neither the name of the copyright holder nor the names of its
20
- contributors may be used to endorse or promote products derived from
21
- this software without specific prior written permission.
22
-
23
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
- “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
-
6
+ License-Expression: BSD-3-Clause
7
+ Classifier: Development Status :: 5 - Production/Stable
8
+ Classifier: Intended Audience :: Science/Research
9
+ Classifier: Topic :: Scientific/Engineering
10
+ Classifier: Operating System :: OS Independent
35
11
  Classifier: Programming Language :: Python
36
12
  Classifier: Programming Language :: Python :: 3
37
13
  Classifier: Programming Language :: Python :: 3.10
38
14
  Classifier: Programming Language :: Python :: 3.11
39
15
  Classifier: Programming Language :: Python :: 3.12
40
16
  Classifier: Programming Language :: Python :: 3.13
41
- Classifier: Intended Audience :: Science/Research
42
- Classifier: Topic :: Scientific/Engineering
43
- Classifier: Operating System :: OS Independent
44
- Requires-Python: >=3.10
17
+ Requires-Python: <3.14,>=3.10
45
18
  Requires-Dist: numpy>=2.0.0
46
19
  Requires-Dist: xarray>=2024.1.0
47
20
  Requires-Dist: dask>=2024.7.1
@@ -15,6 +15,7 @@ plasma PIC code.
15
15
  Getting Started <getting_started>
16
16
  Key Functionality <key_functionality>
17
17
  Unit Conversion <unit_conversion>
18
+ Known Issues <known_issues>
18
19
  Contributing <contributing>
19
20
 
20
21
  .. toctree::
@@ -51,6 +51,12 @@ done via the ``preprocess`` parameter.
51
51
  Reading particle data
52
52
  ~~~~~~~~~~~~~~~~~~~~~
53
53
 
54
+ .. warning::
55
+ It is **not recommended** to use :func:`xarray.open_mfdataset` or :func:`open_mfdataset` to load particle data from multiple SDF outputs. The number of particles often varies between outputs, which can lead to inconsistent array shapes that these functions cannot handle. Instead, consider loading each file individually and then concatenating them manually.
56
+
57
+ .. note::
58
+ When loading multiple probes from a single SDF file, you **must** use the `probe_names` parameter to assign a unique name to each. For example, use `probe_names=["Front_Electron_Probe", "Back_Electron_Probe"]`. Failing to do so will result in dimension name conflicts.
59
+
54
60
  By default, particle data isn't kept as it takes up a lot of space.
55
61
  Pass ``keep_particles=True`` as a keyword argument to
56
62
  :func:`xarray.open_dataset` (for single files) or :func:`xarray.open_mfdataset` (for
@@ -0,0 +1,9 @@
1
+ .. _sec-known-issues:
2
+
3
+ ============
4
+ Known Issues
5
+ ============
6
+
7
+ There are a couple of known 'quirks' in sdf-xarray:
8
+
9
+ - `Issue #57 <https://github.com/epochpic/sdf-xarray/issues/57>`_ Loading multiple SDF files with `open_mfdataset` can lead to out-of-memory errors. The issue is believed to stem from how the underlying `xarray` library handles coordinates, causing it to infer an excessively large array shape that requests far more memory than is needed. Due to the significant architectural changes required for a fix, the maintainers do not plan to resolve this. The recommended solution is to load the files individually or in smaller batches.
@@ -10,30 +10,27 @@ build-backend = "scikit_build_core.build"
10
10
  [project]
11
11
  name = "sdf-xarray"
12
12
  dynamic = ["version"]
13
- license = { file = "LICENCE" }
13
+ license = "BSD-3-Clause"
14
14
  readme = "README.md"
15
15
  authors = [
16
16
  { name = "Peter Hill", email = "peter.hill@york.ac.uk" },
17
17
  { name = "Joel Adams", email = "joel.adams@york.ac.uk" },
18
18
  { name = "Shaun Doherty", email = "shaun.doherty@york.ac.uk" },
19
19
  ]
20
- requires-python = ">=3.10"
21
- dependencies = [
22
- "numpy>=2.0.0",
23
- "xarray>=2024.1.0",
24
- "dask>=2024.7.1",
25
- ]
20
+ requires-python = ">=3.10,<3.14"
21
+ dependencies = ["numpy>=2.0.0", "xarray>=2024.1.0", "dask>=2024.7.1"]
26
22
  description = "Provides a backend for xarray to read SDF files as created by the EPOCH plasma PIC code."
27
23
  classifiers = [
24
+ "Development Status :: 5 - Production/Stable",
25
+ "Intended Audience :: Science/Research",
26
+ "Topic :: Scientific/Engineering",
27
+ "Operating System :: OS Independent",
28
28
  "Programming Language :: Python",
29
29
  "Programming Language :: Python :: 3",
30
30
  "Programming Language :: Python :: 3.10",
31
31
  "Programming Language :: Python :: 3.11",
32
32
  "Programming Language :: Python :: 3.12",
33
33
  "Programming Language :: Python :: 3.13",
34
- "Intended Audience :: Science/Research",
35
- "Topic :: Scientific/Engineering",
36
- "Operating System :: OS Independent",
37
34
  ]
38
35
 
39
36
  [project.optional-dependencies]
@@ -69,6 +69,7 @@ def open_mfdataset(
69
69
  *,
70
70
  separate_times: bool = False,
71
71
  keep_particles: bool = False,
72
+ probe_names: list[str] | None = None,
72
73
  ) -> xr.Dataset:
73
74
  """Open a set of EPOCH SDF files as one `xarray.Dataset`
74
75
 
@@ -98,6 +99,8 @@ def open_mfdataset(
98
99
  different output frequencies
99
100
  keep_particles :
100
101
  If ``True``, also load particle data (this may use a lot of memory!)
102
+ probe_names :
103
+ List of EPOCH probe names
101
104
  """
102
105
 
103
106
  # TODO: This is not very robust, look at how xarray.open_mfdataset does it
@@ -108,10 +111,15 @@ def open_mfdataset(
108
111
  path_glob = sorted(list(path_glob)) # noqa: C414
109
112
 
110
113
  if not separate_times:
111
- return combine_datasets(path_glob, keep_particles=keep_particles)
114
+ return combine_datasets(
115
+ path_glob, keep_particles=keep_particles, probe_names=probe_names
116
+ )
112
117
 
113
118
  time_dims, var_times_map = make_time_dims(path_glob)
114
- all_dfs = [xr.open_dataset(f, keep_particles=keep_particles) for f in path_glob]
119
+ all_dfs = [
120
+ xr.open_dataset(f, keep_particles=keep_particles, probe_names=probe_names)
121
+ for f in path_glob
122
+ ]
115
123
 
116
124
  for df in all_dfs:
117
125
  for da in df:
@@ -211,14 +219,23 @@ class SDFDataStore(AbstractDataStore):
211
219
  "drop_variables",
212
220
  "keep_particles",
213
221
  "lock",
222
+ "probe_names",
214
223
  )
215
224
 
216
- def __init__(self, manager, drop_variables=None, keep_particles=False, lock=None):
225
+ def __init__(
226
+ self,
227
+ manager,
228
+ drop_variables=None,
229
+ keep_particles=False,
230
+ lock=None,
231
+ probe_names=None,
232
+ ):
217
233
  self._manager = manager
218
234
  self._filename = self.ds.filename
219
235
  self.drop_variables = drop_variables
220
236
  self.keep_particles = keep_particles
221
237
  self.lock = ensure_lock(lock)
238
+ self.probe_names = probe_names
222
239
 
223
240
  @classmethod
224
241
  def open(
@@ -227,6 +244,7 @@ class SDFDataStore(AbstractDataStore):
227
244
  lock=None,
228
245
  drop_variables=None,
229
246
  keep_particles=False,
247
+ probe_names=None,
230
248
  ):
231
249
  if isinstance(filename, os.PathLike):
232
250
  filename = os.fspath(filename)
@@ -237,6 +255,7 @@ class SDFDataStore(AbstractDataStore):
237
255
  lock=lock,
238
256
  drop_variables=drop_variables,
239
257
  keep_particles=keep_particles,
258
+ probe_names=probe_names,
240
259
  )
241
260
 
242
261
  def _acquire(self, needs_lock=True):
@@ -253,9 +272,18 @@ class SDFDataStore(AbstractDataStore):
253
272
  def load(self): # noqa: PLR0912, PLR0915
254
273
  # Drop any requested variables
255
274
  if self.drop_variables:
275
+ # Build a mapping from underscored names to real variable names
276
+ name_map = {_rename_with_underscore(var): var for var in self.ds.variables}
277
+
256
278
  for variable in self.drop_variables:
257
- # TODO: nicer error handling
258
- self.ds.variables.pop(variable)
279
+ key = _rename_with_underscore(variable)
280
+ original_name = name_map.get(key)
281
+
282
+ if original_name is None:
283
+ raise KeyError(
284
+ f"Variable '{variable}' not found (interpreted as '{key}')."
285
+ )
286
+ self.ds.variables.pop(original_name)
259
287
 
260
288
  # These two dicts are global metadata about the run or file
261
289
  attrs = {**self.ds.header, **self.ds.run_info}
@@ -338,7 +366,28 @@ class SDFDataStore(AbstractDataStore):
338
366
 
339
367
  if value.is_point_data:
340
368
  # Point (particle) variables are 1D
341
- var_coords = (f"ID_{_process_grid_name(key, _grid_species_name)}",)
369
+
370
+ # Particle data does not maintain a fixed dimension size
371
+ # throughout the simulation. An example of a particle name comes
372
+ # in the form of `Particles/Px/Ion_H` which is then modified
373
+ # using `_process_grid_name()` into `Ion_H`. This is fine as the
374
+ # other components of the momentum (`Py`, `Pz`) will have the same
375
+ # size as they represent the same bunch of particles.
376
+
377
+ # Probes however have names in the form of `Electron_Front_Probe/Px`
378
+ # which are changed to just `Px`; this is fine when there is only one
379
+ # probe in the system but when there are multiple they will have
380
+ # conflicting sizes so we can't keep the names as simply `Px` so we
381
+ # instead set their dimension as the full name `Electron_Front_Probe_Px`.
382
+ is_probe_name_match = self.probe_names is not None and any(
383
+ name in key for name in self.probe_names
384
+ )
385
+ name_processor = (
386
+ _rename_with_underscore
387
+ if is_probe_name_match
388
+ else _grid_species_name
389
+ )
390
+ var_coords = (f"ID_{_process_grid_name(key, name_processor)}",)
342
391
  else:
343
392
  # These are DataArrays
344
393
 
@@ -405,6 +454,7 @@ class SDFEntrypoint(BackendEntrypoint):
405
454
  *,
406
455
  drop_variables=None,
407
456
  keep_particles=False,
457
+ probe_names=None,
408
458
  ):
409
459
  if isinstance(filename_or_obj, Path):
410
460
  # sdf library takes a filename only
@@ -415,6 +465,7 @@ class SDFEntrypoint(BackendEntrypoint):
415
465
  filename_or_obj,
416
466
  drop_variables=drop_variables,
417
467
  keep_particles=keep_particles,
468
+ probe_names=probe_names,
418
469
  )
419
470
  with close_on_error(store):
420
471
  return store.load()
@@ -423,6 +474,7 @@ class SDFEntrypoint(BackendEntrypoint):
423
474
  "filename_or_obj",
424
475
  "drop_variables",
425
476
  "keep_particles",
477
+ "probe_names",
426
478
  ]
427
479
 
428
480
  def guess_can_open(self, filename_or_obj):
@@ -434,7 +486,7 @@ class SDFEntrypoint(BackendEntrypoint):
434
486
 
435
487
  description = "Use .sdf files in Xarray"
436
488
 
437
- url = "https://epochpic.github.io/documentation/visualising_output/python.html"
489
+ url = "https://epochpic.github.io/documentation/visualising_output/python_beam.html"
438
490
 
439
491
 
440
492
  class SDFPreprocess:
@@ -1,7 +1,14 @@
1
1
  # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
3
 
4
- __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
5
12
 
6
13
  TYPE_CHECKING = False
7
14
  if TYPE_CHECKING:
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
9
16
  from typing import Union
10
17
 
11
18
  VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
12
20
  else:
13
21
  VERSION_TUPLE = object
22
+ COMMIT_ID = object
14
23
 
15
24
  version: str
16
25
  __version__: str
17
26
  __version_tuple__: VERSION_TUPLE
18
27
  version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
19
30
 
20
- __version__ = version = '0.2.4'
21
- __version_tuple__ = version_tuple = (0, 2, 4)
31
+ __version__ = version = '0.2.6'
32
+ __version_tuple__ = version_tuple = (0, 2, 6)
33
+
34
+ __commit_id__ = commit_id = 'g67411803b'
@@ -114,8 +114,8 @@ def animate(
114
114
  --------
115
115
  >>> dataset["Derived_Number_Density_Electron"].epoch.animate()
116
116
  """
117
- import matplotlib.pyplot as plt
118
- from matplotlib.animation import FuncAnimation
117
+ import matplotlib.pyplot as plt # noqa: PLC0415
118
+ from matplotlib.animation import FuncAnimation # noqa: PLC0415
119
119
 
120
120
  kwargs_original = kwargs.copy()
121
121
 
@@ -0,0 +1,188 @@
1
+
2
+ ### USER DEFINED CONSTANTS ###
3
+ begin:constant
4
+ # User input constants
5
+ n_elec = 6e+29 #average electron number density
6
+ I_peak = 1e+28 #peak intensity of the laser
7
+
8
+ scale_length = 0.5e-6 #scale length of the target
9
+ L_target_x = 1.5e-6 #length of the target
10
+ L_target_y = 10e-6 #width of the target
11
+
12
+ lambda_L = 800e-9 #wavelength of the laser
13
+ y_fwhm_L = 2e-6 #intensity fwhm in y
14
+ tau_fwhm_L = 16e-15 #intensity fwhm in t
15
+
16
+ mppc = 100 #macro particles per cell
17
+ end:constant
18
+
19
+ begin:control
20
+ nx = 150
21
+ ny = 200
22
+ nsteps = -1
23
+ t_end = 200e-15
24
+ x_min = -10e-06
25
+ x_max = 5e-06
26
+ y_min = -10e-06
27
+ y_max = -y_min
28
+ nparticles = nint(((L_target_x * L_target_y) / ((x_max - x_min) * (y_max - y_min))) * nx * ny * mppc)
29
+ dt_multiplier = 0.8
30
+ smooth_currents = T
31
+ dlb_threshold = 0.8
32
+ stdout_frequency = 100 # Print ETA
33
+ particle_tstart = 30e-15 # Time before the laser hits the target
34
+ end:control
35
+
36
+ ### CALCULATD CONSTANTS ###
37
+ begin:constant
38
+ w_t = tau_fwhm_L / (2*sqrt(loge(2))) # Beam waist in t
39
+ w_y = y_fwhm_L / (2*sqrt(loge(2))) # Beam waist in y
40
+ t_hw01m = 0.5 * tau_fwhm_L * sqrt(loge(10)/loge(2))
41
+
42
+ x_foc = -x_min # Boundary to focal point distance
43
+ k_L = 2.0 * pi / lambda_L # Laser wave number
44
+ x_Rr = pi * w_y^2 / lambda_L # Rayleigh range
45
+ omega_L = 2 * pi * c / lambda_L # Angular frequency of the laser
46
+
47
+ w_boundary = w_y * sqrt(1 + (x_foc/x_Rr)^2) # Waist on boundary
48
+ I_boundary = I_peak * (w_y / w_boundary)^2 # Intens. on boundary
49
+ r_curve = x_foc * (1 + (x_Rr/x_foc)^2) # Boundary curv. rad.
50
+ phase_Gouy = atan(-x_foc/r_curve) # Boundary Gouy shift
51
+ end:constant
52
+
53
+ begin:laser
54
+ boundary = x_min
55
+ intensity = I_boundary
56
+ omega = omega_L
57
+ phase = k_L * y^2 / (2 * r_curve) - phase_Gouy
58
+ profile = gauss(y, 0, w_boundary)
59
+ t_profile = gauss(time, t_hw01m, w_t)
60
+ t_start = 0.0
61
+ t_end = end
62
+ end:laser
63
+
64
+ begin:qed
65
+ use_qed = F
66
+ qed_start_time = 0
67
+ produce_photons = T
68
+ photon_energy_min = 1 * kev
69
+ produce_pairs = T
70
+ photon_dynamics = T
71
+ end:qed
72
+
73
+ begin:collisions
74
+ use_collisions = T
75
+ coulomb_log = auto
76
+ collide = all
77
+ end:collisions
78
+
79
+ begin:boundaries
80
+ bc_x_min_particle = simple_outflow
81
+ bc_x_max_particle = simple_outflow
82
+ bc_y_min_particle = reflect
83
+ bc_y_max_particle = reflect
84
+ bc_x_min_field = simple_laser
85
+ bc_x_max_field = conduct
86
+ bc_y_min_field = conduct
87
+ bc_y_max_field = conduct
88
+ end:boundaries
89
+
90
+ begin:species
91
+ name = Electron
92
+ frac = 0.5
93
+ dump = T
94
+ temperature = 300
95
+ number_density = if((abs(y) lt L_target_y/2), if((x lt 0) or (x gt L_target_x), 0, if((x gt 0) and (x lt scale_length), n_elec * (1-exp(x/scale_length))/(1-exp(1)), n_elec)), 0)
96
+ number_density_min = 1
97
+ identify:electron
98
+ end:species
99
+
100
+ begin:species
101
+ name = Ion_C
102
+ charge = 6
103
+ atomic_number = 12
104
+ mass = 1836.2 * 12
105
+ frac = 0.25
106
+ dump = T
107
+ number_density = number_density(Electron) * (6/7)
108
+ temperature = temperature_x(Electron)
109
+ number_density_min = 1
110
+ end:species
111
+
112
+ begin:species
113
+ name = Ion_H
114
+ charge = 1
115
+ atomic_number = 1
116
+ mass = 1836.2
117
+ fraction = 0.25
118
+ dump = T
119
+ number_density = number_density(Electron) / 7
120
+ temperature = temperature_x(Electron)
121
+ number_density_min = 1
122
+ identify:proton
123
+ end:species
124
+
125
+ begin:species
126
+ name = Photon
127
+ nparticles = 0
128
+ dump = T
129
+ identify:photon
130
+ end:species
131
+
132
+ begin:species
133
+ name = Positron
134
+ nparticles = 0
135
+ dump = T
136
+ identify:positron
137
+ end:species
138
+
139
+ ### THE MANY PARTICLE PROBES ###
140
+
141
+ #Electron#
142
+ begin:probe
143
+ name = Electron_Front_Probe
144
+ point = (x_min, 0)
145
+ normal = (-1.0, 0.0)
146
+ ek_min = 0.0
147
+ ek_max = -1.0
148
+ include_species : Electron
149
+ dumpmask = always
150
+ end:probe
151
+ begin:probe
152
+ name = Electron_Back_Probe
153
+ point = (x_max, 0)
154
+ normal = (1.0, 0.0)
155
+ ek_min = 0.0
156
+ ek_max = -1.0
157
+ include_species : Electron
158
+ dumpmask = always
159
+ end:probe
160
+
161
+ ################################
162
+
163
+ begin:output_global
164
+ force_final_to_be_restartable = F
165
+ end:output_global
166
+
167
+ begin:output
168
+ name = normal
169
+ grid = always
170
+ particle_probes = always
171
+ dt_snapshot = 15e-14
172
+ ex = always + single
173
+ ey = always + single
174
+ ez = always + single
175
+ bx = always + single
176
+ by = always + single
177
+ bz = always + single
178
+ particles = always
179
+ particle_weight = always
180
+ px = always + single
181
+ py = always + single
182
+ pz = always + single
183
+ average_particle_energy = always + species + no_sum + single
184
+ number_density = always + species + no_sum + single
185
+ absorption = always
186
+ total_energy_sum = always + species
187
+ end:output
188
+
@@ -11,6 +11,7 @@ EXAMPLE_MISMATCHED_FILES_DIR = (
11
11
  )
12
12
  EXAMPLE_ARRAYS_DIR = pathlib.Path(__file__).parent / "example_array_no_grids"
13
13
  EXAMPLE_3D_DIST_FN = pathlib.Path(__file__).parent / "example_dist_fn"
14
+ EXAMPLE_2D_PARTICLE_DATA = pathlib.Path(__file__).parent / "example_two_probes_2D"
14
15
 
15
16
 
16
17
  def test_basic():
@@ -185,3 +186,73 @@ def test_3d_distribution_function():
185
186
  with xr.open_dataset(EXAMPLE_3D_DIST_FN / "0000.sdf") as df:
186
187
  distribution_function = "dist_fn_x_px_py_Electron"
187
188
  assert df[distribution_function].shape == (16, 20, 20)
189
+
190
+
191
+ def test_drop_variables():
192
+ with xr.open_dataset(
193
+ EXAMPLE_FILES_DIR / "0000.sdf", drop_variables=["Electric_Field_Ex"]
194
+ ) as df:
195
+ assert "Electric_Field_Ex" not in df
196
+
197
+
198
+ def test_drop_variables_multiple():
199
+ with xr.open_dataset(
200
+ EXAMPLE_FILES_DIR / "0000.sdf",
201
+ drop_variables=["Electric_Field_Ex", "Electric_Field_Ey"],
202
+ ) as df:
203
+ assert "Electric_Field_Ex" not in df
204
+ assert "Electric_Field_Ey" not in df
205
+
206
+
207
+ def test_drop_variables_original():
208
+ with xr.open_dataset(
209
+ EXAMPLE_FILES_DIR / "0000.sdf",
210
+ drop_variables=["Electric_Field/Ex", "Electric_Field/Ey"],
211
+ ) as df:
212
+ assert "Electric_Field_Ex" not in df
213
+ assert "Electric_Field_Ey" not in df
214
+
215
+
216
+ def test_drop_variables_mixed():
217
+ with xr.open_dataset(
218
+ EXAMPLE_FILES_DIR / "0000.sdf",
219
+ drop_variables=["Electric_Field/Ex", "Electric_Field_Ey"],
220
+ ) as df:
221
+ assert "Electric_Field_Ex" not in df
222
+ assert "Electric_Field_Ey" not in df
223
+
224
+
225
+ def test_erroring_drop_variables():
226
+ with pytest.raises(KeyError):
227
+ xr.open_dataset(
228
+ EXAMPLE_FILES_DIR / "0000.sdf", drop_variables=["Electric_Field/E"]
229
+ )
230
+
231
+
232
+ def test_loading_multiple_probes():
233
+ with xr.open_dataset(
234
+ EXAMPLE_2D_PARTICLE_DATA / "0002.sdf",
235
+ keep_particles=True,
236
+ probe_names=["Electron_Front_Probe", "Electron_Back_Probe"],
237
+ ) as df:
238
+ assert "X_Probe_Electron_Front_Probe" in df.coords
239
+ assert "X_Probe_Electron_Back_Probe" in df.coords
240
+ assert "ID_Electron_Front_Probe_Px" in df.dims
241
+ assert "ID_Electron_Back_Probe_Px" in df.dims
242
+
243
+
244
+ def test_loading_one_probe_drop_second_probe():
245
+ with xr.open_dataset(
246
+ EXAMPLE_2D_PARTICLE_DATA / "0002.sdf",
247
+ keep_particles=True,
248
+ drop_variables=[
249
+ "Electron_Back_Probe_Px",
250
+ "Electron_Back_Probe_Py",
251
+ "Electron_Back_Probe_Pz",
252
+ "Electron_Back_Probe_weight",
253
+ ],
254
+ probe_names=["Electron_Front_Probe"],
255
+ ) as df:
256
+ assert "X_Probe_Electron_Front_Probe" in df.coords
257
+ assert "ID_Electron_Front_Probe_Px" in df.dims
258
+ assert "ID_Electron_Back_Probe_Px" not in df.dims