diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b26da3d3..b2405792 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,6 +10,10 @@ repos: rev: stable hooks: - id: black + - repo: https://github.com/keewis/blackdoc + rev: stable + hooks: + - id: blackdoc - repo: https://gitlab.com/pycqa/flake8 rev: 3.8.1 hooks: diff --git a/docs/conf.py b/docs/conf.py index b0235b56..4a83889b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,6 +29,7 @@ project = "pint-xarray" author = f"{project} developers" copyright = f"{year}, {author}" +github_url = "https://github.com/xarray-contrib/pint-xarray" # -- General configuration --------------------------------------------------- @@ -38,10 +39,13 @@ # ones. extensions = [ "sphinx.ext.intersphinx", + "sphinx.ext.extlinks", "sphinx.ext.autosummary", "sphinx.ext.autodoc", "sphinx.ext.napoleon", "sphinx_autosummary_accessors", + "IPython.sphinxext.ipython_directive", + "IPython.sphinxext.ipython_console_highlighting", ] # Add any paths that contain templates here, relative to this directory. @@ -68,13 +72,38 @@ # -- Extension configuration ------------------------------------------------- +# extlinks +extlinks = { + "issue": (f"{github_url}/issues/%s", "GH"), + "pull": (f"{github_url}/pull/%s", "PR"), +} + +# autosummary autosummary_generate = True + +# autodoc autodoc_typehints = "none" -napoleon_use_param = True +# napoleon +napoleon_use_param = False napoleon_use_rtype = True +napoleon_preprocess_types = True +napoleon_type_aliases = { + "dict-like": ":term:`dict-like `", + "mapping": ":term:`mapping`", + "hashable": ":term:`hashable`", + # xarray + "Dataset": "~xarray.Dataset", + "DataArray": "~xarray.DataArray", + # pint / pint-xarray + "unit-like": ":term:`unit-like`", +} + # -- Options for intersphinx extension --------------------------------------- -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {"https://docs.python.org/3/": None} +intersphinx_mapping = { + "python": ("https://docs.python.org/3/", None), + "xarray": ("https://xarray.pydata.org/en/stable", None), + "pint": ("https://pint.readthedocs.io/en/stable", None), +} diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 00000000..8d2bf6c5 --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1,12 @@ +Contributing +============ +``pint-xarray`` is developed on `github `_. + +Linters / Autoformatters +------------------------ +In order to keep code consistent, we use + +- `Black `_ for standardized code formatting +- `blackdoc `_ for standardized code formatting in documentation +- `Flake8 `_ for general code quality +- `isort `_ for standardized order in imports. See also `flake8-isort `_. diff --git a/docs/conversion.rst b/docs/conversion.rst new file mode 100644 index 00000000..292c3a50 --- /dev/null +++ b/docs/conversion.rst @@ -0,0 +1,30 @@ +.. currentmodule:: xarray + +Converting units +================ +.. ipython:: python + :suppress: + + import xarray as xr + +When working with :py:class:`Dataset` or :py:class:`DataArray` objects with +units, we frequently might want to convert the units. Suppose we have: + +.. ipython:: + + In [1]: ds = xr.Dataset( + ...: {"a": ("x", [4, 8, 12, 16])}, coords={"u": ("x", [10, 20, 30, 40])} + ...: ).pint.quantify({"a": "m", "u": "s"}) + ...: ds + + In [2]: da = ds.a + ...: da + +To convert the data to different units, we can use the +:py:meth:`Dataset.pint.to` and :py:meth:`DataArray.pint.to` methods: + +.. ipython:: + + In [3]: ds.pint.to(a="feet", u="ks") + + In [4]: da.pint.to({da.name: "nautical_mile", "u": "ms"}) diff --git a/docs/creation.rst b/docs/creation.rst new file mode 100644 index 00000000..ecf6c29e --- /dev/null +++ b/docs/creation.rst @@ -0,0 +1,97 @@ +.. currentmodule:: xarray + +Creating and saving objects with units +====================================== + +Attaching units +--------------- +.. ipython:: python + :suppress: + + import xarray as xr + +Usually, when loading data from disk we get a :py:class:`Dataset` or +:py:class:`DataArray` with units in attributes: + +.. ipython:: + + In [1]: ds = xr.Dataset( + ...: { + ...: "a": (("lon", "lat"), [[11.84, 3.12, 9.7], [7.8, 9.3, 14.72]]), + ...: "b": (("lon", "lat"), [[13, 2, 7], [5, 4, 9]], {"units": "m"}), + ...: }, + ...: coords={"lat": [10, 20, 30], "lon": [74, 76]}, + ...: ) + ...: ds + + In [2]: da = ds.b + ...: da + +In order to get :py:class:`pint.Quantity` instances, we can use the +:py:meth:`Dataset.pint.quantify` or :py:meth:`DataArray.pint.quantify` methods: + +.. ipython:: + + In [3]: ds.pint.quantify() + +We can also override the units of a variable: + +.. ipython:: + + In [4]: ds.pint.quantify(b="km") + + In [5]: da.pint.quantify({"b": "degree"}) + +Overriding works, even if there is no ``units`` attribute, so we could use this +to attach units to a normal :py:class:`Dataset`: + +.. ipython:: + + In [6]: temporary_ds = xr.Dataset({"a": ("x", [0, 5, 10])}, coords={"x": [1, 2, 3]}) + ...: temporary_ds.pint.quantify({"a": "m"}) + +Of course, we could use :py:class:`pint.Unit` instances instead of strings to +specify units, too. + +If we wanted to change the units of the data of a :py:class:`DataArray`, we +could do so using the :py:attr:`DataArray.name` attribute: + +.. ipython:: + + In [7]: da.pint.quantify({da.name: "J", "lat": "degree", "lon": "degree"}) + +However, `xarray`_ currently doesn't support `units in indexes`_, so the new units were set +as attributes. To really observe the changes the ``quantify`` methods make, we +have to first swap the dimensions: + +.. ipython:: + + In [8]: ds_with_units = ds.swap_dims({"lon": "x", "lat": "y"}).pint.quantify( + ...: {"lat": "degree", "lon": "degree"} + ...: ) + ...: ds_with_units + + In [9]: da_with_units = da.swap_dims({"lon": "x", "lat": "y"}).pint.quantify( + ...: {"lat": "degree", "lon": "degree"} + ...: ) + ...: da_with_units + +Saving with units +----------------- +In order to not lose the units when saving to disk, we first have to call the +:py:meth:`Dataset.pint.dequantify` and :py:meth:`DataArray.pint.dequantify` +methods: + +.. ipython:: + + In [10]: ds_with_units.pint.dequantify() + + In [11]: da_with_units.pint.dequantify() + +This will get the string representation of a :py:class:`pint.Unit` instance and +attach it as a ``units`` attribute. The data of the variable will now be +whatever `pint`_ wrapped. + +.. _pint: https://pint.readthedocs.org/en/stable +.. _xarray: https://xarray.pydata.org/en/stable +.. _units in indexes: https://github.com/pydata/xarray/issues/1603 diff --git a/docs/examples.rst b/docs/examples.rst new file mode 100644 index 00000000..76c315ca --- /dev/null +++ b/docs/examples.rst @@ -0,0 +1,3 @@ +Examples +======== +There are no examples yet. diff --git a/docs/index.rst b/docs/index.rst index b526353b..b7bf628c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,13 +1,53 @@ -.. accessors documentation master file, created by - sphinx-quickstart on Thu Jul 2 01:49:50 2020. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +pint-xarray +=========== +A convenience wrapper for using `pint`_ in `xarray`_ objects. -Welcome to accessors's documentation! -===================================== +.. _pint: https://pint.readthedocs.io/en/stable +.. _xarray: https://xarray.pydata.org/en/stable + +Documentation +------------- + +**Getting Started**: + +- :doc:`installation` +- :doc:`examples` + +.. toctree:: + :maxdepth: 1 + :caption: Getting Started + :hidden: + + installation + examples + +**User Guide**: + +- :doc:`terminology` +- :doc:`creation` +- :doc:`conversion` + +.. toctree:: + :maxdepth: 1 + :caption: User Guide + :hidden: + + terminology + creation + conversion + + +**Help & Reference**: + +- :doc:`whats-new` +- :doc:`api` +- :doc:`contributing` .. toctree:: - :maxdepth: 2 - :caption: Contents: + :maxdepth: 1 + :caption: Help & Reference + :hidden: + whats-new api + contributing diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 00000000..e454fe57 --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,26 @@ +Installation +------------ +Install from ``conda-forge``: + +.. code:: sh + + conda install -c conda-forge pint-xarray + +or from ``PyPI``: + +.. code:: sh + + python -m pip install pint-xarray + +or from source, either directly from github: + +.. code:: sh + + python -m pip install git+https://github.com/xarray-contrib/pint-xarray + +or from a local copy: + +.. code:: sh + + git clone https://github.com/xarray-contrib/pint-xarray + python -m pip install ./pint-xarray diff --git a/docs/requirements.txt b/docs/requirements.txt index 1b181900..6a0cf8f9 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,8 @@ -pint>=0.13 -xarray>=0.15.1 -sphinx>=3.0 +pint>=0.14 +xarray>=0.16.0 +netCDF4 +sphinx>=3.2 sphinx_rtd_theme +ipython nbsphinx sphinx-autosummary-accessors diff --git a/docs/terminology.rst b/docs/terminology.rst new file mode 100644 index 00000000..4fe6534d --- /dev/null +++ b/docs/terminology.rst @@ -0,0 +1,10 @@ +Terminology +=========== + +.. glossary:: + + unit-like + A `pint`_ unit definition, as accepted by :py:class:`pint.Unit`. + May be either a :py:class:`str` or a :py:class:`pint.Unit` instance. + +.. _pint: https://pint.readthedocs.io/en/stable diff --git a/docs/whats-new.rst b/docs/whats-new.rst new file mode 100644 index 00000000..190ca2dc --- /dev/null +++ b/docs/whats-new.rst @@ -0,0 +1,6 @@ +What's new +========== + +0.1 (*unreleased*) +------------------ +- add documentation (:pull:`20`) diff --git a/pint_xarray/accessors.py b/pint_xarray/accessors.py index e86fcd13..47c76cb4 100644 --- a/pint_xarray/accessors.py +++ b/pint_xarray/accessors.py @@ -148,7 +148,7 @@ def quantify( Parameters ---------- - units : pint.Unit or str or mapping of hashable to pint.Unit or str, optional + units : unit-like or mapping of hashable to unit-like, optional Physical units to use for this DataArray. If a str or pint.Unit, will be used as the DataArray's units. If a dict-like, it should map a variable name to the desired @@ -275,7 +275,7 @@ def to(self, units=None, **unit_kwargs): Parameters ---------- - units : str or pint.Unit or mapping of hashable to str or pint.Unit, optional + units : unit-like or mapping of hashable to unit-like, optional The units to convert to. If a unit name or ``pint.Unit`` object, convert the DataArray's data. If a dict-like, it has to map a variable name to a unit name or ``pint.Unit`` @@ -440,7 +440,7 @@ def quantify( Parameters ---------- - units : mapping of hashable to pint.Unit or str, optional + units : mapping of hashable to unit-like, optional Physical units to use for particular DataArrays in this Dataset. It should map variable names to units (unit names or ``pint.Unit`` objects). If not provided, will try to @@ -532,7 +532,7 @@ def to(self, units=None, **unit_kwargs): Parameters ---------- - units : mapping of hashable to str or pint.Unit, optional + units : mapping of hashable to unit-like, optional Maps variable names to the unit to convert to. **unit_kwargs The kwargs form of ``units``. Can only be used for