diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..12cd93c --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,33 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-20.04 + tools: + python: "3.12" + + # You can also specify other tool versions: + # nodejs: "16" + # rust: "1.55" + # golang: "1.17" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Optionally build your docs in additional formats such as PDF +# formats: +# - pdf + +# Optionally declare the Python requirements required to build your docs +python: + install: + - method: pip + path: . + extra_requirements: + - docs diff --git a/docs/_templates/custom-class-template.rst b/docs/_templates/custom-class-template.rst new file mode 100644 index 0000000..4a2889e --- /dev/null +++ b/docs/_templates/custom-class-template.rst @@ -0,0 +1,32 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :members: + :undoc-members: + :show-inheritance: + + {% block methods %} + .. automethod:: __init__ + + {% if methods %} + .. rubric:: {{ _('Methods') }} + + .. autosummary:: + {% for item in methods %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/docs/_templates/custom-module-template.rst b/docs/_templates/custom-module-template.rst new file mode 100644 index 0000000..f46f9f6 --- /dev/null +++ b/docs/_templates/custom-module-template.rst @@ -0,0 +1,66 @@ +{{ fullname | escape | underline}} + +.. automodule:: {{ fullname }} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Module Attributes') }} + + .. autosummary:: + :toctree: + {% for item in attributes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block functions %} + {% if functions %} + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + :toctree: + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block classes %} + {% if classes %} + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block exceptions %} + {% if exceptions %} + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + :toctree: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + +{% block modules %} +{% if modules %} +.. rubric:: Modules + +.. autosummary:: + :toctree: + :template: custom-module-template.rst + :recursive: +{% for item in modules %} + {{ item }} +{%- endfor %} +{% endif %} +{% endblock %} diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 0000000..2fc966d --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,10 @@ +=============== + API Reference +=============== + +.. autosummary:: + :toctree: generated + :template: custom-module-template.rst + :recursive: + + sdf_xarray diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..20d8c0e --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,108 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +from importlib.metadata import version as get_version + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'sdf-xarray' +copyright = '2024, Peter Hill, Joel Adams' +author = 'Peter Hill, Joel Adams' + +# The full version, including alpha/beta/rc tags +release = get_version("sdf_xarray") +# Major.minor version +version = ".".join(release.split(".")[:2]) + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + "sphinx.ext.napoleon", + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.viewcode", + "sphinx.ext.coverage", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx_autodoc_typehints", +] + +autosummary_generate = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +# Numpy-doc config +napoleon_google_docstring = False +napoleon_numpy_docstring = True +napoleon_attr_annotations = True +napoleon_preprocess_types = True + +# Enable numbered references +numfig = True + +autodoc_type_aliases = { + "ArrayLike": "numpy.typing.ArrayLike", +} + +autodoc_default_options = { + 'ignore-module-all': True +} +autodoc_typehints = "description" +autodoc_class_signature = "mixed" + +# The default role for text marked up `like this` +default_role = "any" + +# Tell sphinx what the primary language being documented is. +primary_domain = "py" + +# Tell sphinx what the pygments highlight language should be. +highlight_language = "python" + +# Include "todo" directives in output +todo_include_todos = True + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_book_theme" + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = ["_static"] +html_static_path = [] + +html_theme_options = { + "repository_url": "https://github.com/PlasmaFAIR/sdf-xarray", + "repository_branch": "main", + "path_to_docs": "docs", + "use_edit_page_button": True, + "use_repository_button": True, + "use_issues_button": True, + "home_page_in_toc": False, +} + +pygments_style = "sphinx" + +# -- Options for intersphinx extension --------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#configuration + +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "numpy": ("https://numpy.org/doc/stable", None), + "scipy": ("https://docs.scipy.org/doc/scipy", None), + "xarray": ("https://docs.xarray.dev/en/latest", None), +} diff --git a/docs/generated/sdf_xarray.SDFBackendArray.rst b/docs/generated/sdf_xarray.SDFBackendArray.rst new file mode 100644 index 0000000..151c1f0 --- /dev/null +++ b/docs/generated/sdf_xarray.SDFBackendArray.rst @@ -0,0 +1,38 @@ +sdf\_xarray.SDFBackendArray +=========================== + +.. currentmodule:: sdf_xarray + +.. autoclass:: SDFBackendArray + :members: + :undoc-members: + :show-inheritance: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~SDFBackendArray.__init__ + ~SDFBackendArray.get_array + ~SDFBackendArray.get_duck_array + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~SDFBackendArray.datastore + ~SDFBackendArray.dtype + ~SDFBackendArray.shape + ~SDFBackendArray.variable_name + ~SDFBackendArray.ndim + ~SDFBackendArray.size + + \ No newline at end of file diff --git a/docs/generated/sdf_xarray.SDFDataStore.rst b/docs/generated/sdf_xarray.SDFDataStore.rst new file mode 100644 index 0000000..4e3001c --- /dev/null +++ b/docs/generated/sdf_xarray.SDFDataStore.rst @@ -0,0 +1,42 @@ +sdf\_xarray.SDFDataStore +======================== + +.. currentmodule:: sdf_xarray + +.. autoclass:: SDFDataStore + :members: + :undoc-members: + :show-inheritance: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~SDFDataStore.__init__ + ~SDFDataStore.acquire_context + ~SDFDataStore.close + ~SDFDataStore.get_attrs + ~SDFDataStore.get_dimensions + ~SDFDataStore.get_encoding + ~SDFDataStore.get_variables + ~SDFDataStore.load + ~SDFDataStore.open + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~SDFDataStore.lock + ~SDFDataStore.drop_variables + ~SDFDataStore.keep_particles + ~SDFDataStore.ds + + \ No newline at end of file diff --git a/docs/generated/sdf_xarray.SDFEntrypoint.rst b/docs/generated/sdf_xarray.SDFEntrypoint.rst new file mode 100644 index 0000000..caf701a --- /dev/null +++ b/docs/generated/sdf_xarray.SDFEntrypoint.rst @@ -0,0 +1,37 @@ +sdf\_xarray.SDFEntrypoint +========================= + +.. currentmodule:: sdf_xarray + +.. autoclass:: SDFEntrypoint + :members: + :undoc-members: + :show-inheritance: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~SDFEntrypoint.__init__ + ~SDFEntrypoint.guess_can_open + ~SDFEntrypoint.open_dataset + ~SDFEntrypoint.open_datatree + ~SDFEntrypoint.open_groups_as_dict + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~SDFEntrypoint.description + ~SDFEntrypoint.open_dataset_parameters + ~SDFEntrypoint.url + + \ No newline at end of file diff --git a/docs/generated/sdf_xarray.SDFPreprocess.rst b/docs/generated/sdf_xarray.SDFPreprocess.rst new file mode 100644 index 0000000..428f543 --- /dev/null +++ b/docs/generated/sdf_xarray.SDFPreprocess.rst @@ -0,0 +1,25 @@ +sdf\_xarray.SDFPreprocess +========================= + +.. currentmodule:: sdf_xarray + +.. autoclass:: SDFPreprocess + :members: + :undoc-members: + :show-inheritance: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~SDFPreprocess.__init__ + + + + + + \ No newline at end of file diff --git a/docs/generated/sdf_xarray.combine_datasets.rst b/docs/generated/sdf_xarray.combine_datasets.rst new file mode 100644 index 0000000..cdca587 --- /dev/null +++ b/docs/generated/sdf_xarray.combine_datasets.rst @@ -0,0 +1,6 @@ +sdf\_xarray.combine\_datasets +============================= + +.. currentmodule:: sdf_xarray + +.. autofunction:: combine_datasets \ No newline at end of file diff --git a/docs/generated/sdf_xarray.make_time_dims.rst b/docs/generated/sdf_xarray.make_time_dims.rst new file mode 100644 index 0000000..d8e1913 --- /dev/null +++ b/docs/generated/sdf_xarray.make_time_dims.rst @@ -0,0 +1,6 @@ +sdf\_xarray.make\_time\_dims +============================ + +.. currentmodule:: sdf_xarray + +.. autofunction:: make_time_dims \ No newline at end of file diff --git a/docs/generated/sdf_xarray.open_mfdataset.rst b/docs/generated/sdf_xarray.open_mfdataset.rst new file mode 100644 index 0000000..69fc18c --- /dev/null +++ b/docs/generated/sdf_xarray.open_mfdataset.rst @@ -0,0 +1,6 @@ +sdf\_xarray.open\_mfdataset +=========================== + +.. currentmodule:: sdf_xarray + +.. autofunction:: open_mfdataset \ No newline at end of file diff --git a/docs/generated/sdf_xarray.rst b/docs/generated/sdf_xarray.rst new file mode 100644 index 0000000..28ffaa8 --- /dev/null +++ b/docs/generated/sdf_xarray.rst @@ -0,0 +1,52 @@ +sdf\_xarray +=========== + +.. automodule:: sdf_xarray + + + + + + + + .. rubric:: Functions + + .. autosummary:: + :toctree: + + combine_datasets + make_time_dims + open_mfdataset + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + + SDFBackendArray + SDFDataStore + SDFEntrypoint + SDFPreprocess + + + + + + + + + +.. rubric:: Modules + +.. autosummary:: + :toctree: + :template: custom-module-template.rst + :recursive: + + sdf_interface + diff --git a/docs/generated/sdf_xarray.sdf_interface.Block.rst b/docs/generated/sdf_xarray.sdf_interface.Block.rst new file mode 100644 index 0000000..3a91eb8 --- /dev/null +++ b/docs/generated/sdf_xarray.sdf_interface.Block.rst @@ -0,0 +1,35 @@ +sdf\_xarray.sdf\_interface.Block +================================ + +.. currentmodule:: sdf_xarray.sdf_interface + +.. autoclass:: Block + :members: + :undoc-members: + :show-inheritance: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~Block.__init__ + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~Block.dtype + ~Block.is_point_data + ~Block.name + ~Block.sdffile + ~Block.shape + + \ No newline at end of file diff --git a/docs/generated/sdf_xarray.sdf_interface.Constant.rst b/docs/generated/sdf_xarray.sdf_interface.Constant.rst new file mode 100644 index 0000000..047bb67 --- /dev/null +++ b/docs/generated/sdf_xarray.sdf_interface.Constant.rst @@ -0,0 +1,34 @@ +sdf\_xarray.sdf\_interface.Constant +=================================== + +.. currentmodule:: sdf_xarray.sdf_interface + +.. autoclass:: Constant + :members: + :undoc-members: + :show-inheritance: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~Constant.__init__ + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~Constant.data + ~Constant.is_point_data + ~Constant.name + ~Constant.units + + \ No newline at end of file diff --git a/docs/generated/sdf_xarray.sdf_interface.Mesh.rst b/docs/generated/sdf_xarray.sdf_interface.Mesh.rst new file mode 100644 index 0000000..427ecc9 --- /dev/null +++ b/docs/generated/sdf_xarray.sdf_interface.Mesh.rst @@ -0,0 +1,40 @@ +sdf\_xarray.sdf\_interface.Mesh +=============================== + +.. currentmodule:: sdf_xarray.sdf_interface + +.. autoclass:: Mesh + :members: + :undoc-members: + :show-inheritance: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~Mesh.__init__ + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~Mesh.data + ~Mesh.dtype + ~Mesh.is_point_data + ~Mesh.labels + ~Mesh.mults + ~Mesh.name + ~Mesh.parent + ~Mesh.sdffile + ~Mesh.shape + ~Mesh.units + + \ No newline at end of file diff --git a/docs/generated/sdf_xarray.sdf_interface.SDFFile.rst b/docs/generated/sdf_xarray.sdf_interface.SDFFile.rst new file mode 100644 index 0000000..3b941d8 --- /dev/null +++ b/docs/generated/sdf_xarray.sdf_interface.SDFFile.rst @@ -0,0 +1,37 @@ +sdf\_xarray.sdf\_interface.SDFFile +================================== + +.. currentmodule:: sdf_xarray.sdf_interface + +.. autoclass:: SDFFile + :members: + :undoc-members: + :show-inheritance: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~SDFFile.__init__ + ~SDFFile.close + ~SDFFile.read + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~SDFFile.filename + ~SDFFile.grids + ~SDFFile.header + ~SDFFile.run_info + ~SDFFile.variables + + \ No newline at end of file diff --git a/docs/generated/sdf_xarray.sdf_interface.Variable.rst b/docs/generated/sdf_xarray.sdf_interface.Variable.rst new file mode 100644 index 0000000..15e0019 --- /dev/null +++ b/docs/generated/sdf_xarray.sdf_interface.Variable.rst @@ -0,0 +1,40 @@ +sdf\_xarray.sdf\_interface.Variable +=================================== + +.. currentmodule:: sdf_xarray.sdf_interface + +.. autoclass:: Variable + :members: + :undoc-members: + :show-inheritance: + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~Variable.__init__ + + + + + + .. rubric:: Attributes + + .. autosummary:: + + ~Variable.data + ~Variable.dtype + ~Variable.grid + ~Variable.grid_mid + ~Variable.is_point_data + ~Variable.mult + ~Variable.name + ~Variable.sdffile + ~Variable.shape + ~Variable.units + + \ No newline at end of file diff --git a/docs/generated/sdf_xarray.sdf_interface.rst b/docs/generated/sdf_xarray.sdf_interface.rst new file mode 100644 index 0000000..6b7c7fe --- /dev/null +++ b/docs/generated/sdf_xarray.sdf_interface.rst @@ -0,0 +1,35 @@ +sdf\_xarray.sdf\_interface +========================== + +.. automodule:: sdf_xarray.sdf_interface + + + + + + + + + + + + .. rubric:: Classes + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + + Block + Constant + Mesh + SDFFile + Variable + + + + + + + + + diff --git a/docs/getting_started.rst b/docs/getting_started.rst new file mode 100644 index 0000000..3f8a179 --- /dev/null +++ b/docs/getting_started.rst @@ -0,0 +1,115 @@ +.. _sec-getting-started: + +================= + Getting Started +================= + +Installation +------------ + +Install sdf-xarray from PyPI with: + +.. code:: console + + $ pip install sdf-xarray + +or from a local checkout: + +.. code:: console + + $ git clone https://github.com/PlasmaFAIR/sdf-xarray.git + $ cd sdf-xarray + $ pip install . + +Usage +----- + +``sdf-xarray`` is a backend for xarray, and so is usable directly from +`xarray`. + +Single file loading +~~~~~~~~~~~~~~~~~~~ + +Basic usage:: + + import xarray as xr + + df = xr.open_dataset("0010.sdf") + + print(df["Electric_Field_Ex"]) + + # Size: 128B + # [16 values with dtype=float64] + # Coordinates: + # * X_x_px_deltaf_electron_beam (X_x_px_deltaf_electron_beam) float64 128B 1... + # Attributes: + # units: V/m + # full_name: "Electric Field/Ex" + +Multi file loading +~~~~~~~~~~~~~~~~~~ + +To open a whole simulation at once, pass ``preprocess=sdf_xarray.SDFPreprocess()`` +to `xarray.open_mfdataset`:: + + import xarray as xr + from sdf_xarray import SDFPreprocess + + with xr.open_mfdataset("*.sdf", preprocess=SDFPreprocess()) as ds: + print(ds) + + # Dimensions: + # time: 301, X_Grid_mid: 128, ... + # Coordinates: (9) ... + # Data variables: (18) ... + # Indexes: (9) ... + # Attributes: (22) ... + +`SDFPreprocess` checks that all the files are from the same simulation, and +ensures there's a ``time`` dimension so the files are correctly concatenated. + +If your simulation has multiple ``output`` blocks so that not all variables are +output at every time step, then those variables will have ``NaN`` values at the +corresponding time points. + +Alternatively, we can create a separate time dimensions for each ``output`` block +(essentially) using `sdf_xarray.open_mfdataset` with ``separate_times=True``:: + + from sdf_xarray import open_mfdataset + + with open_mfdataset("*.sdf", separate_times=True) as ds: + print(ds) + + # Dimensions: + # time0: 301, time1: 31, time2: 61, X_Grid_mid: 128, ... + # Coordinates: (12) ... + # Data variables: (18) ... + # Indexes: (9) ... + # Attributes: (22) ... + +This is better for memory consumption, at the cost of perhaps slightly less +friendly comparisons between variables on different time coordinates. + +Reading particle data +~~~~~~~~~~~~~~~~~~~~~ + +By default, particle data isn't kept as it takes up a lot of space. Pass +``keep_particles=True`` as a keyword argument to `open_dataset` (for single files) +or `open_mfdataset` (for multiple files):: + + df = xr.open_dataset("0010.sdf", keep_particles=True) + + ### Loading SDF files directly + + For debugging, sometimes it's useful to see the raw SDF files:: + + from sdf_xarray import SDFFile + + with SDFFile("0010.sdf") as sdf_file: + print(sdf_file.variables["Electric Field/Ex"]) + + # Variable(_id='ex', name='Electric Field/Ex', dtype=dtype('float64'), ... + + print(sdf_file.variables["Electric Field/Ex"].data) + + # [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... -4.44992788e+12 1.91704994e+13 0.00000000e+00] diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..c2311e7 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,28 @@ +sdf-xarray +=========== + +``sdf-xarray`` provides a backend for `xarray `_ to +read SDF files as created by the `EPOCH `_ +plasma PIC code. + +``sdf-xarray`` uses the `SDF-C `_ library. + + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + Getting Started + +.. toctree:: + :maxdepth: 2 + :caption: Reference + + API Reference + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..32bb245 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd