File: creation.rst

package info (click to toggle)
pint-xarray 0.5.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 456 kB
  • sloc: python: 4,477; sh: 10; makefile: 4
file content (135 lines) | stat: -rw-r--r-- 4,059 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
.. currentmodule:: xarray

Creating and saving objects with units
======================================

Attaching units
---------------
.. ipython:: python
    :suppress:

    import pint
    import pint_xarray
    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("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.

.. note::

    Unit objects tied to different registries cannot interact with each
    other. In order to avoid this, :py:meth:`DataArray.pint.quantify` and
    :py:meth:`Dataset.pint.quantify` will make sure only a single registry is
    used per ``xarray`` object.

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

By default, :py:meth:`Dataset.pint.quantify` and
:py:meth:`DataArray.pint.quantify` will use the unit registry at
:py:obj:`pint_xarray.unit_registry` (the
:py:func:`application registry <pint.get_application_registry>`). If we want a
different registry, we can either pass it as the ``unit_registry`` parameter:

.. ipython::

   In [10]: ureg = pint.UnitRegistry(force_ndarray_like=True)
       ...: # set up the registry

   In [11]: da.pint.quantify("degree", unit_registry=ureg)

or overwrite the default registry:

.. ipython::

   In [12]: pint_xarray.unit_registry = ureg

   In [13]: da.pint.quantify("degree")

.. note::

    To properly work with ``xarray``, the ``force_ndarray_like`` or
    ``force_ndarray`` options have to be enabled on the custom registry.

   Without it, python scalars wrapped by :py:class:`pint.Quantity` may raise errors or
   have their units stripped.

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.io/en/stable/
.. _xarray: https://docs.xarray.dev/en/stable/
.. _units in indexes: https://github.com/pydata/xarray/issues/1603