sdf-xarray 0.2.2__tar.gz → 0.2.4__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 (114) hide show
  1. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/CITATION.cff +1 -0
  2. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/PKG-INFO +16 -3
  3. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/README.md +6 -1
  4. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/getting_started.rst +8 -1
  5. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/key_functionality.rst +8 -5
  6. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/pyproject.toml +13 -2
  7. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/src/sdf_xarray/__init__.py +2 -0
  8. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/src/sdf_xarray/_version.py +2 -2
  9. sdf_xarray-0.2.4/src/sdf_xarray/plotting.py +205 -0
  10. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/src/sdf_xarray/sdf_interface.pyx +1 -1
  11. sdf_xarray-0.2.4/tests/example_dist_fn/0000.sdf +0 -0
  12. sdf_xarray-0.2.4/tests/example_dist_fn/0001.sdf +0 -0
  13. sdf_xarray-0.2.4/tests/example_dist_fn/0002.sdf +0 -0
  14. sdf_xarray-0.2.4/tests/example_dist_fn/input.deck +154 -0
  15. sdf_xarray-0.2.4/tests/example_files_2D_moving_window/0000.sdf +0 -0
  16. sdf_xarray-0.2.4/tests/example_files_2D_moving_window/0001.sdf +0 -0
  17. sdf_xarray-0.2.4/tests/example_files_2D_moving_window/0002.sdf +0 -0
  18. sdf_xarray-0.2.4/tests/example_files_2D_moving_window/0003.sdf +0 -0
  19. sdf_xarray-0.2.4/tests/example_files_2D_moving_window/0004.sdf +0 -0
  20. sdf_xarray-0.2.4/tests/example_files_2D_moving_window/input.deck +63 -0
  21. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/tests/test_basic.py +8 -1
  22. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/tests/test_cython.py +1 -1
  23. sdf_xarray-0.2.4/tests/test_epoch_accessor.py +183 -0
  24. sdf_xarray-0.2.2/src/sdf_xarray/plotting.py +0 -184
  25. sdf_xarray-0.2.2/tests/test_epoch_accessor.py +0 -39
  26. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/.github/workflows/black.yml +0 -0
  27. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/.github/workflows/build_publish.yml +0 -0
  28. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/.github/workflows/lint.yml +0 -0
  29. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/.github/workflows/tests.yml +0 -0
  30. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/.gitignore +0 -0
  31. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/.gitmodules +0 -0
  32. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/.readthedocs.yaml +0 -0
  33. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/BEAM.png +0 -0
  34. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/CMakeLists.txt +0 -0
  35. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/CONTRIBUTING.md +0 -0
  36. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/LICENCE +0 -0
  37. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/PlasmaFAIR.svg +0 -0
  38. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/.gitignore +0 -0
  39. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/_templates/custom-class-template.rst +0 -0
  40. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/_templates/custom-module-template.rst +0 -0
  41. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/api.rst +0 -0
  42. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/conf.py +0 -0
  43. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/contributing.rst +0 -0
  44. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/index.rst +0 -0
  45. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/make.bat +0 -0
  46. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0000.sdf +0 -0
  47. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0001.sdf +0 -0
  48. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0002.sdf +0 -0
  49. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0003.sdf +0 -0
  50. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0004.sdf +0 -0
  51. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0005.sdf +0 -0
  52. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0006.sdf +0 -0
  53. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0007.sdf +0 -0
  54. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0008.sdf +0 -0
  55. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0009.sdf +0 -0
  56. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0010.sdf +0 -0
  57. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0011.sdf +0 -0
  58. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0012.sdf +0 -0
  59. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0013.sdf +0 -0
  60. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0014.sdf +0 -0
  61. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0015.sdf +0 -0
  62. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0016.sdf +0 -0
  63. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0017.sdf +0 -0
  64. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0018.sdf +0 -0
  65. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0019.sdf +0 -0
  66. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0020.sdf +0 -0
  67. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0021.sdf +0 -0
  68. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0022.sdf +0 -0
  69. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0023.sdf +0 -0
  70. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0024.sdf +0 -0
  71. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0025.sdf +0 -0
  72. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0026.sdf +0 -0
  73. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0027.sdf +0 -0
  74. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0028.sdf +0 -0
  75. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0029.sdf +0 -0
  76. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0030.sdf +0 -0
  77. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0031.sdf +0 -0
  78. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0032.sdf +0 -0
  79. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0033.sdf +0 -0
  80. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0034.sdf +0 -0
  81. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0035.sdf +0 -0
  82. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0036.sdf +0 -0
  83. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0037.sdf +0 -0
  84. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0038.sdf +0 -0
  85. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0039.sdf +0 -0
  86. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/0040.sdf +0 -0
  87. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/deck.status +0 -0
  88. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/epoch1d.dat +0 -0
  89. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/input.deck +0 -0
  90. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/normal.visit +0 -0
  91. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/tutorial_dataset_1d/restart.visit +0 -0
  92. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/docs/unit_conversion.rst +0 -0
  93. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/src/sdf_xarray/csdf.pxd +0 -0
  94. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/tests/example_array_no_grids/0000.sdf +0 -0
  95. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/tests/example_array_no_grids/0001.sdf +0 -0
  96. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/tests/example_array_no_grids/README.md +0 -0
  97. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/tests/example_array_no_grids/input.deck +0 -0
  98. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0000.sdf +0 -0
  99. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0001.sdf +0 -0
  100. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0002.sdf +0 -0
  101. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0003.sdf +0 -0
  102. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0004.sdf +0 -0
  103. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0005.sdf +0 -0
  104. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0006.sdf +0 -0
  105. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0007.sdf +0 -0
  106. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0008.sdf +0 -0
  107. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0009.sdf +0 -0
  108. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/0010.sdf +0 -0
  109. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/README.md +0 -0
  110. {sdf_xarray-0.2.2/tests/example_files → sdf_xarray-0.2.4/tests/example_files_1D}/input.deck +0 -0
  111. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/tests/example_mismatched_files/0000.sdf +0 -0
  112. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/tests/example_mismatched_files/0001.sdf +0 -0
  113. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/tests/example_mismatched_files/0002.sdf +0 -0
  114. {sdf_xarray-0.2.2 → sdf_xarray-0.2.4}/uv.lock +0 -0
@@ -16,4 +16,5 @@ authors:
16
16
  given-names: Shaun
17
17
  orcid: 'https://orcid.org/0009-0005-0693-030X'
18
18
  affiliation: University of York
19
+ doi: 10.5281/zenodo.15351323
19
20
  date-released: '2024-07-25'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: sdf-xarray
3
- Version: 0.2.2
3
+ Version: 0.2.4
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
6
  License: Copyright 2024, Peter Hill, Joel Adams, epochpic team
@@ -32,11 +32,19 @@ License: Copyright 2024, Peter Hill, Joel Adams, epochpic team
32
32
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
33
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
34
 
35
+ Classifier: Programming Language :: Python
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.10
38
+ Classifier: Programming Language :: Python :: 3.11
39
+ Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Programming Language :: Python :: 3.13
41
+ Classifier: Intended Audience :: Science/Research
42
+ Classifier: Topic :: Scientific/Engineering
43
+ Classifier: Operating System :: OS Independent
35
44
  Requires-Python: >=3.10
36
45
  Requires-Dist: numpy>=2.0.0
37
46
  Requires-Dist: xarray>=2024.1.0
38
47
  Requires-Dist: dask>=2024.7.1
39
- Requires-Dist: cython>=3.0
40
48
  Provides-Extra: docs
41
49
  Requires-Dist: sphinx>=5.3; extra == "docs"
42
50
  Requires-Dist: sphinx_autodoc_typehints>=1.19; extra == "docs"
@@ -67,9 +75,14 @@ Description-Content-Type: text/markdown
67
75
 
68
76
  # sdf-xarray
69
77
 
70
- ![PyPI](https://img.shields.io/pypi/v/sdf-xarray?color=blue)
78
+ ![Dynamic TOML Badge](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2Fepochpic%2Fsdf-xarray%2Frefs%2Fheads%2Fmain%2Fpyproject.toml&query=%24.project.requires-python&label=python&logo=python)
79
+ [![Available on PyPI](https://img.shields.io/pypi/v/sdf-xarray?color=blue&logo=pypi)](https://pypi.org/project/sdf-xarray/)
80
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.15351323.svg)](https://doi.org/10.5281/zenodo.15351323)
71
81
  ![Build/Publish](https://github.com/epochpic/sdf-xarray/actions/workflows/build_publish.yml/badge.svg)
72
82
  ![Tests](https://github.com/epochpic/sdf-xarray/actions/workflows/tests.yml/badge.svg)
83
+ [![Read the Docs](https://img.shields.io/readthedocs/sdf-xarray?logo=readthedocs&link=https%3A%2F%2Fsdf-xarray.readthedocs.io%2F)](https://sdf-xarray.readthedocs.io)
84
+ [![Formatted with black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black)
85
+
73
86
 
74
87
  sdf-xarray provides a backend for [xarray](https://xarray.dev) to read SDF files as created by
75
88
  [EPOCH](https://epochpic.github.io) using the [SDF-C](https://github.com/epochpic/SDF_C) library.
@@ -1,8 +1,13 @@
1
1
  # sdf-xarray
2
2
 
3
- ![PyPI](https://img.shields.io/pypi/v/sdf-xarray?color=blue)
3
+ ![Dynamic TOML Badge](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2Fepochpic%2Fsdf-xarray%2Frefs%2Fheads%2Fmain%2Fpyproject.toml&query=%24.project.requires-python&label=python&logo=python)
4
+ [![Available on PyPI](https://img.shields.io/pypi/v/sdf-xarray?color=blue&logo=pypi)](https://pypi.org/project/sdf-xarray/)
5
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.15351323.svg)](https://doi.org/10.5281/zenodo.15351323)
4
6
  ![Build/Publish](https://github.com/epochpic/sdf-xarray/actions/workflows/build_publish.yml/badge.svg)
5
7
  ![Tests](https://github.com/epochpic/sdf-xarray/actions/workflows/tests.yml/badge.svg)
8
+ [![Read the Docs](https://img.shields.io/readthedocs/sdf-xarray?logo=readthedocs&link=https%3A%2F%2Fsdf-xarray.readthedocs.io%2F)](https://sdf-xarray.readthedocs.io)
9
+ [![Formatted with black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black)
10
+
6
11
 
7
12
  sdf-xarray provides a backend for [xarray](https://xarray.dev) to read SDF files as created by
8
13
  [EPOCH](https://epochpic.github.io) using the [SDF-C](https://github.com/epochpic/SDF_C) library.
@@ -25,7 +25,14 @@ Usage
25
25
  -----
26
26
 
27
27
  ``sdf-xarray`` is a backend for xarray, and so is usable directly from
28
- `xarray`.
28
+ `xarray`. There are several ways to load SDF files:
29
+
30
+ - To load a single file, use :func:`xarray.open_dataset`.
31
+ - To load multiple files, use :func:`xarray.open_mfdataset` or :func:`sdf_xarray.open_mfdataset`.
32
+ - To access the raw contents of a single SDF file, use :func:`sdf_xarray.sdf_interface.SDFFile`.
33
+
34
+ .. note::
35
+ When loading ``*.sdf`` files, variables related to ``boundaries``, ``cpu`` and ``output file`` are excluded as they are problematic.
29
36
 
30
37
  Single file loading
31
38
  ~~~~~~~~~~~~~~~~~~~
@@ -13,11 +13,14 @@ Key Functionality
13
13
 
14
14
  Loading SDF Files
15
15
  -----------------
16
- There are several ways to load in SDF files using ``sdf-xarray``.
17
- You can load in a single file using :func:`xarray.open_dataset`,
18
- load in multiple files using :func:`xarray.open_mfdataset` or
19
- :func:`sdf_xarray.open_mfdataset`, or load in a single raw SDF file
20
- using :func:`sdf_xarray.sdf_interface.SDFFile`.
16
+ There are several ways to load SDF files:
17
+
18
+ - To load a single file, use :func:`xarray.open_dataset`.
19
+ - To load multiple files, use :func:`xarray.open_mfdataset` or :func:`sdf_xarray.open_mfdataset`.
20
+ - To access the raw contents of a single SDF file, use :func:`sdf_xarray.sdf_interface.SDFFile`.
21
+
22
+ .. note::
23
+ When loading ``*.sdf`` files, variables related to ``boundaries``, ``cpu`` and ``output file`` are excluded as they are problematic.
21
24
 
22
25
  Loading a Single SDF File
23
26
  ~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -3,7 +3,7 @@ requires = [
3
3
  "scikit-build-core>=0.3",
4
4
  "setuptools_scm",
5
5
  "numpy>=2.0.0",
6
- "cython>=3.0",
6
+ "cython~=3.0",
7
7
  ]
8
8
  build-backend = "scikit_build_core.build"
9
9
 
@@ -22,9 +22,19 @@ dependencies = [
22
22
  "numpy>=2.0.0",
23
23
  "xarray>=2024.1.0",
24
24
  "dask>=2024.7.1",
25
- "cython>=3.0",
26
25
  ]
27
26
  description = "Provides a backend for xarray to read SDF files as created by the EPOCH plasma PIC code."
27
+ classifiers = [
28
+ "Programming Language :: Python",
29
+ "Programming Language :: Python :: 3",
30
+ "Programming Language :: Python :: 3.10",
31
+ "Programming Language :: Python :: 3.11",
32
+ "Programming Language :: Python :: 3.12",
33
+ "Programming Language :: Python :: 3.13",
34
+ "Intended Audience :: Science/Research",
35
+ "Topic :: Scientific/Engineering",
36
+ "Operating System :: OS Independent",
37
+ ]
28
38
 
29
39
  [project.optional-dependencies]
30
40
  docs = [
@@ -94,4 +104,5 @@ extend-select = [
94
104
  ignore = [
95
105
  "PLR2004", # magic-comparison
96
106
  "B9", # flake8-bugbear opinionated warnings
107
+ "PLR0913", # remove maximum number of arguments in a function
97
108
  ]
@@ -310,6 +310,8 @@ class SDFDataStore(AbstractDataStore):
310
310
  # Had some problems with these variables, so just ignore them for now
311
311
  if "cpu" in key.lower():
312
312
  continue
313
+ if "boundary" in key.lower():
314
+ continue
313
315
  if "output file" in key.lower():
314
316
  continue
315
317
 
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.2.2'
21
- __version_tuple__ = version_tuple = (0, 2, 2)
20
+ __version__ = version = '0.2.4'
21
+ __version_tuple__ = version_tuple = (0, 2, 4)
@@ -0,0 +1,205 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ import numpy as np
6
+ import xarray as xr
7
+
8
+ if TYPE_CHECKING:
9
+ import matplotlib.pyplot as plt
10
+ from matplotlib.animation import FuncAnimation
11
+
12
+
13
+ def get_frame_title(
14
+ data: xr.DataArray,
15
+ frame: int,
16
+ display_sdf_name: bool = False,
17
+ title_custom: str | None = None,
18
+ ) -> str:
19
+ """Generate the title for a frame"""
20
+ # Adds custom text to the start of the title, if specified
21
+ title_custom = "" if title_custom is None else f"{title_custom}, "
22
+ # Adds the time and associated units to the title
23
+ time = data["time"][frame].to_numpy()
24
+
25
+ time_units = data["time"].attrs.get("units", False)
26
+ time_units_formatted = f" [{time_units}]" if time_units else ""
27
+ title_time = f"time = {time:.2e}{time_units_formatted}"
28
+
29
+ # Adds sdf name to the title, if specifed
30
+ title_sdf = f", {frame:04d}.sdf" if display_sdf_name else ""
31
+ return f"{title_custom}{title_time}{title_sdf}"
32
+
33
+
34
+ def calculate_window_boundaries(
35
+ data: xr.DataArray, xlim: tuple[float, float] | False = False
36
+ ) -> np.ndarray:
37
+ """Calculate the bounderies a moving window frame. If the user specifies xlim, this will
38
+ be used as the initial bounderies and the window will move along acordingly.
39
+ """
40
+ x_grid = data["X_Grid_mid"].values
41
+ x_half_cell = (x_grid[1] - x_grid[0]) / 2
42
+ N_frames = data["time"].size
43
+
44
+ # Find the window bounderies by finding the first and last non-NaN values in the 0th lineout
45
+ # along the x-axis.
46
+ window_boundaries = np.zeros((N_frames, 2))
47
+ for i in range(N_frames):
48
+ # Check if data is 1D
49
+ if data.ndim == 2:
50
+ target_lineout = data[i].values
51
+ # Check if data is 2D
52
+ if data.ndim == 3:
53
+ target_lineout = data[i, :, 0].values
54
+ x_grid_non_nan = x_grid[~np.isnan(target_lineout)]
55
+ window_boundaries[i, 0] = x_grid_non_nan[0] - x_half_cell
56
+ window_boundaries[i, 1] = x_grid_non_nan[-1] + x_half_cell
57
+
58
+ # User's choice for initial window edge supercides the one calculated
59
+ if xlim:
60
+ window_boundaries = window_boundaries + xlim - window_boundaries[0]
61
+ return window_boundaries
62
+
63
+
64
+ def compute_global_limits(
65
+ data: xr.DataArray,
66
+ min_percentile: float = 0,
67
+ max_percentile: float = 100,
68
+ ) -> tuple[float, float]:
69
+ """Remove all NaN values from the target data to calculate the global minimum and maximum of the data.
70
+ User defined percentiles can remove extreme outliers.
71
+ """
72
+
73
+ # Removes NaN values, needed for moving windows
74
+ values_no_nan = data.values[~np.isnan(data.values)]
75
+
76
+ # Finds the global minimum and maximum of the plot, based on the percentile of the data
77
+ global_min = np.percentile(values_no_nan, min_percentile)
78
+ global_max = np.percentile(values_no_nan, max_percentile)
79
+ return global_min, global_max
80
+
81
+
82
+ def animate(
83
+ data: xr.DataArray,
84
+ fps: float = 10,
85
+ min_percentile: float = 0,
86
+ max_percentile: float = 100,
87
+ title: str | None = None,
88
+ display_sdf_name: bool = False,
89
+ ax: plt.Axes | None = None,
90
+ **kwargs,
91
+ ) -> FuncAnimation:
92
+ """Generate an animation
93
+
94
+ Parameters
95
+ ---------
96
+ data
97
+ The dataarray containing the target data
98
+ fps
99
+ Frames per second for the animation (default: 10)
100
+ min_percentile
101
+ Minimum percentile of the data (default: 0)
102
+ max_percentile
103
+ Maximum percentile of the data (default: 100)
104
+ title
105
+ Custom title to add to the plot.
106
+ display_sdf_name
107
+ Display the sdf file name in the animation title
108
+ ax
109
+ Matplotlib axes on which to plot.
110
+ kwargs
111
+ Keyword arguments to be passed to matplotlib.
112
+
113
+ Examples
114
+ --------
115
+ >>> dataset["Derived_Number_Density_Electron"].epoch.animate()
116
+ """
117
+ import matplotlib.pyplot as plt
118
+ from matplotlib.animation import FuncAnimation
119
+
120
+ kwargs_original = kwargs.copy()
121
+
122
+ if ax is None:
123
+ _, ax = plt.subplots()
124
+
125
+ N_frames = data["time"].size
126
+ global_min, global_max = compute_global_limits(data, min_percentile, max_percentile)
127
+
128
+ # Initialise plot and set y-limits for 1D data
129
+ if data.ndim == 2:
130
+ kwargs.setdefault("x", "X_Grid_mid")
131
+ plot = data.isel(time=0).plot(ax=ax, **kwargs)
132
+ ax.set_title(get_frame_title(data, 0, display_sdf_name, title))
133
+ ax.set_ylim(global_min, global_max)
134
+
135
+ # Initilise plot and set colour bar for 2D data
136
+ if data.ndim == 3:
137
+ kwargs["norm"] = plt.Normalize(vmin=global_min, vmax=global_max)
138
+ kwargs["add_colorbar"] = False
139
+ # Set default x and y coordinates for 2D data if not provided
140
+ kwargs.setdefault("x", "X_Grid_mid")
141
+ kwargs.setdefault("y", "Y_Grid_mid")
142
+
143
+ # Initialize the plot with the first timestep
144
+ plot = data.isel(time=0).plot(ax=ax, **kwargs)
145
+ ax.set_title(get_frame_title(data, 0, display_sdf_name, title))
146
+
147
+ # Add colorbar
148
+ if kwargs_original.get("add_colorbar", True):
149
+ long_name = data.attrs.get("long_name")
150
+ units = data.attrs.get("units")
151
+ plt.colorbar(plot, ax=ax, label=f"{long_name} [${units}$]")
152
+
153
+ # check if there is a moving window by finding NaNs in the data
154
+ move_window = np.isnan(np.sum(data.values))
155
+ if move_window:
156
+ window_boundaries = calculate_window_boundaries(data, kwargs.get("xlim", False))
157
+
158
+ def update(frame):
159
+ # Set the xlim for each frame in the case of a moving window
160
+ if move_window:
161
+ kwargs["xlim"] = window_boundaries[frame]
162
+
163
+ # Update plot for the new frame
164
+ ax.clear()
165
+
166
+ data.isel(time=frame).plot(ax=ax, **kwargs)
167
+ ax.set_title(get_frame_title(data, frame, display_sdf_name, title))
168
+
169
+ # Update y-limits for 1D data
170
+ if data.ndim == 2:
171
+ ax.set_ylim(global_min, global_max)
172
+
173
+ return FuncAnimation(
174
+ ax.get_figure(),
175
+ update,
176
+ frames=range(N_frames),
177
+ interval=1000 / fps,
178
+ repeat=True,
179
+ )
180
+
181
+
182
+ @xr.register_dataarray_accessor("epoch")
183
+ class EpochAccessor:
184
+ def __init__(self, xarray_obj):
185
+ self._obj = xarray_obj
186
+
187
+ def animate(self, *args, **kwargs) -> FuncAnimation:
188
+ """Generate animations of Epoch data.
189
+
190
+ Parameters
191
+ ----------
192
+ args
193
+ Positional arguments passed to :func:`generate_animation`.
194
+ kwargs
195
+ Keyword arguments passed to :func:`generate_animation`.
196
+
197
+ Examples
198
+ --------
199
+ >>> import xarray as xr
200
+ >>> from sdf_xarray import SDFPreprocess
201
+ >>> ds = xr.open_mfdataset("*.sdf", preprocess=SDFPreprocess())
202
+ >>> ani = ds["Electric_Field_Ey"].epoch.animate()
203
+ >>> ani.save("myfile.mp4")
204
+ """
205
+ return animate(self._obj, *args, **kwargs)
@@ -39,7 +39,7 @@ cdef class Block:
39
39
 
40
40
  @dataclasses.dataclass
41
41
  cdef class Variable(Block):
42
- units: tuple[str] | None
42
+ units: str | None
43
43
  mult: float | None
44
44
  grid: str | None
45
45
  grid_mid: str | None
@@ -0,0 +1,154 @@
1
+ begin:control
2
+
3
+ # global number of gridpoints
4
+ # Divide nx and ny by 2 from 40 to 20
5
+ nx = 16 # in x
6
+ ny = 8
7
+ nparticles = nx * ny * 4
8
+
9
+ # maximum number of iterations
10
+ # set to -1 to run until finished
11
+ nsteps = -1
12
+
13
+ # final time of simulation
14
+ t_end = 200e-15
15
+
16
+ # size of domain
17
+ x_min = 0e-6
18
+ x_max = 40e-6
19
+ y_min = -10e-6
20
+ y_max = -y_min
21
+
22
+ dt_multiplier = 0.8
23
+ dlb_threshold = 0.8
24
+
25
+ end:control
26
+
27
+ begin:laser
28
+
29
+ boundary = x_min
30
+ intensity_w_cm2 = 1.0e23
31
+ lambda = 1e-6
32
+ phase = 0.0
33
+ t_profile = gauss(time, 40.0e-15, 30.0e-15) # This profile means your laser pulse has a maximum intensity at t=40 fs, and the intensity will smoothly decrease as time moves away from this point, with a width parameter of 30 fs.
34
+ t_start = 0.0
35
+ t_end = end
36
+ end:laser
37
+
38
+ begin:collisions
39
+
40
+ use_collisions = T
41
+ coulomb_log = auto
42
+ collide = all
43
+
44
+ end:collisions
45
+
46
+
47
+ begin:boundaries
48
+
49
+ bc_x_min = simple_laser
50
+ bc_x_max = open
51
+ bc_y_min = periodic
52
+ bc_y_max = periodic
53
+
54
+ end:boundaries
55
+
56
+
57
+ begin:species
58
+
59
+ # electrons
60
+ name = Electron
61
+ fraction = 0.5
62
+ dump = T
63
+
64
+ temperature = 0
65
+ number_density = if ((x gt 10e-6) and (x lt 30e-6), 1e22, 0)
66
+ number_density_min = 1
67
+
68
+ identify:electron
69
+
70
+ end:species
71
+
72
+
73
+ begin:output_global
74
+
75
+ force_final_to_be_restartable = F
76
+
77
+ end:output_global
78
+
79
+
80
+ begin:output
81
+
82
+ name = normal
83
+
84
+ # If use_offset_grid is true then the code dumps a grid which displays
85
+ # positions relative to the left hand edge of the window
86
+ use_offset_grid = F
87
+
88
+ # number of timesteps between output dumps
89
+ dt_snapshot = 100.0e-15 # 100.0e-15 / 100.0
90
+
91
+ # Properties at particle positions
92
+ particles = never
93
+ px = never
94
+ py = never
95
+ pz = never
96
+ vx = never
97
+ vy = never
98
+ vz = never
99
+ charge = never
100
+ mass = never
101
+ particle_weight = never
102
+ species_id = never
103
+
104
+ # Properties on grid
105
+ grid = always
106
+ ex = never
107
+ ey = always
108
+ ez = never
109
+ bx = never
110
+ by = never
111
+ bz = never
112
+ jx = never
113
+ jy = never
114
+ jz = never
115
+ poynt_flux = always
116
+ average_particle_energy = never
117
+ mass_density = never
118
+ charge_density = never
119
+ number_density = never
120
+ temperature = never
121
+
122
+ # extended io
123
+ distribution_functions = always
124
+ particle_probes = never
125
+ absorption = never
126
+ total_energy_sum = never
127
+
128
+ end:output
129
+
130
+
131
+ begin:dist_fn
132
+
133
+ name = x_px_py
134
+ ndims = 3
135
+ dumpmask = always
136
+
137
+ direction1 = dir_x
138
+ direction2 = dir_px
139
+ direction3 = dir_py
140
+
141
+ # range is ignored for spatial coordinates
142
+ range1 = (1, 1)
143
+ range2 = (1.6e-20, 1.6e-19)
144
+ range3 = (1.6e-20, 1.6e-19)
145
+
146
+ # resolution is ignored for spatial coordinates
147
+ resolution1 = 1
148
+ resolution2 = 20
149
+ resolution3 = 20
150
+
151
+ #include_species:Photon
152
+ include_species:Electron
153
+
154
+ end:dist_fn
@@ -0,0 +1,63 @@
1
+ begin:control
2
+ nx = 100
3
+ ny = 100
4
+
5
+ # final time of simulation
6
+ t_end = 10e-9
7
+
8
+ # size of domain
9
+ x_min = 0
10
+ x_end = 1
11
+
12
+ y_min = 0
13
+ y_max = 1
14
+
15
+ stdout_frequency = 10
16
+ end:control
17
+
18
+
19
+ begin:boundaries
20
+ bc_x_min = simple_outflow
21
+ bc_x_max = simple_outflow
22
+ bc_y_min = periodic
23
+ bc_y_max = periodic
24
+ end:boundaries
25
+
26
+
27
+ begin:window
28
+ move_window = T
29
+ window_start_time = 0
30
+ bc_x_min_after_move = simple_outflow
31
+ bc_x_max_after_move = simple_outflow
32
+ window_v_x = 2e8
33
+ end:window
34
+
35
+ begin:constant
36
+ x0 = 1.31
37
+ y0 = 0.5
38
+ r0 = 0.4^2
39
+ r2 = (x - x0)^2 + (y - y0)^2
40
+ end:constant
41
+
42
+ begin:species
43
+ # electron
44
+ name = electron
45
+ charge = -1.0
46
+ mass = 1.0
47
+ nparticles_per_cell = 5
48
+
49
+ number_density = if(abs(x-x0) lt 0.3, 2, 1)
50
+ number_density = if(abs(y-y0) lt 0.2, number_density(electron), 1)
51
+
52
+ temperature_ev = 0
53
+ end:species
54
+
55
+
56
+ begin:output
57
+ name = normal
58
+ dt_snapshot = 10e-9/4
59
+
60
+ # Properties on grid
61
+ grid = always
62
+ number_density = always + species + no_sum
63
+ end:output
@@ -5,11 +5,12 @@ import xarray as xr
5
5
 
6
6
  from sdf_xarray import SDFPreprocess, _process_latex_name, open_mfdataset
7
7
 
8
- EXAMPLE_FILES_DIR = pathlib.Path(__file__).parent / "example_files"
8
+ EXAMPLE_FILES_DIR = pathlib.Path(__file__).parent / "example_files_1D"
9
9
  EXAMPLE_MISMATCHED_FILES_DIR = (
10
10
  pathlib.Path(__file__).parent / "example_mismatched_files"
11
11
  )
12
12
  EXAMPLE_ARRAYS_DIR = pathlib.Path(__file__).parent / "example_array_no_grids"
13
+ EXAMPLE_3D_DIST_FN = pathlib.Path(__file__).parent / "example_dist_fn"
13
14
 
14
15
 
15
16
  def test_basic():
@@ -178,3 +179,9 @@ def test_arrays_with_no_grids_multifile():
178
179
  random_states = "Random_States"
179
180
  assert random_states in df
180
181
  assert df[random_states].shape == (2, 8)
182
+
183
+
184
+ def test_3d_distribution_function():
185
+ with xr.open_dataset(EXAMPLE_3D_DIST_FN / "0000.sdf") as df:
186
+ distribution_function = "dist_fn_x_px_py_Electron"
187
+ assert df[distribution_function].shape == (16, 20, 20)
@@ -6,7 +6,7 @@ import pytest
6
6
 
7
7
  from sdf_xarray import SDFFile
8
8
 
9
- EXAMPLE_FILES_DIR = pathlib.Path(__file__).parent / "example_files"
9
+ EXAMPLE_FILES_DIR = pathlib.Path(__file__).parent / "example_files_1D"
10
10
 
11
11
 
12
12
  def test_sdffile():