xarray-units


Namexarray-units JSON
Version 0.5.0 PyPI version JSON
download
home_pagehttps://github.com/astropenguin/xarray-units/
Summaryxarray extension for handling units
upload_time2024-02-03 18:55:16
maintainer
docs_urlNone
authorAkio Taniguchi
requires_python>=3.9,<3.13
licenseMIT
keywords xarray xarray-accessor xarray-extension units
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # xarray-units

[![Release](https://img.shields.io/pypi/v/xarray-units?label=Release&color=cornflowerblue&style=flat-square)](https://pypi.org/project/xarray-units/)
[![Python](https://img.shields.io/pypi/pyversions/xarray-units?label=Python&color=cornflowerblue&style=flat-square)](https://pypi.org/project/xarray-units/)
[![Downloads](https://img.shields.io/pypi/dm/xarray-units?label=Downloads&color=cornflowerblue&style=flat-square)](https://pepy.tech/project/xarray-units)
[![DOI](https://img.shields.io/badge/DOI-10.5281/zenodo.10354517-cornflowerblue?style=flat-square)](https://doi.org/10.5281/zenodo.10354517)
[![Tests](https://img.shields.io/github/actions/workflow/status/astropenguin/xarray-units/tests.yaml?label=Tests&style=flat-square)](https://github.com/astropenguin/xarray-units/actions)

xarray extension for handling units

## Overview

xarray-units is an import-only package that provides a [xarray](https://xarray.dev) DataArray accessor `.units` for handling units such as converting units and numeric operations considering units.
[Astropy](https://www.astropy.org) is used as a backend.
Unlike similar implementations, xarray-units does not use a special data type to handle units, but uses the original data type in a DataArray.
This allows to continue to use powerful features such as parallel and lazy processing with [Dask](https://www.dask.org) and/or user-defined DataArray subclasses.

## Installation

```shell
pip install xarray-units==0.5.0
```

## Basic usages

Suppose the following imports will be commonly used in the examples:

```python
import xarray as xr
import xarray_units
```

### Setting and unsetting units

xarray-units sets units in DataArray attributes (`.attrs`) with the name `"units"`:

```python
da_km = xr.DataArray([1, 2, 3]).units.set("km")
print(da_km)
```

```
<xarray.DataArray (dim_0: 3)>
array([1, 2, 3])
Dimensions without coordinates: dim_0
Attributes:
    units:    km
```

And the units can also be unset (deleted):

```python
da = da_km.units.unset()
print(da)
```

```
<xarray.DataArray (dim_0: 3)>
array([1, 2, 3])
Dimensions without coordinates: dim_0
```

> [!NOTE]
> These are equivalent to manually un/setting the units in the DataArray attributes, but the `units` accessor also check that the units are valid when setting.

### Converting units to others

xarray-units converts a DataArray with units to other units:

```python
da_km = xr.DataArray([1, 2, 3]).units.set("km")
da_m = da_km.units.to("m")
print(da_m)
```

```
<xarray.DataArray (dim_0: 3)>
array([1000., 2000., 3000.])
Dimensions without coordinates: dim_0
Attributes:
    units:    m
```

Astropy [equivalencies](https://docs.astropy.org/en/stable/units/equivalencies.html) can also be used for equivalences between different units:

```python
from astropy.units import spectral

da_mm = xr.DataArray([1, 2, 3]).units.set("mm")
da_GHz = da_mm.units.to("GHz", spectral())
print(da_GHz)
```

```
<xarray.DataArray (dim_1: 3)>
array([299.792458  , 149.896229  ,  99.93081933])
Dimensions without coordinates: dim_0
Attributes:
    units:    GHz
```

> [!TIP]
> There exist other accessor methods (e.g. `decompose`, `like`) for converting units.
> See [the package guide](https://astropenguin.github.io/xarray-units/_apidoc/xarray_units.accessor.html) for more details.

### Numeric operations considering units

xarray-units performs numerical operations considering units when the `units` accessor is attached to the DataArray on the left side of the operator:

```python
da_m = xr.DataArray([1000, 2000, 3000]).units.set("m")
da_km = xr.DataArray([1, 2, 3]).units.set("km")

da_sum_m = da_m.units + da_km
da_sum_km = da_km.units + da_m

print(da_sum_m)
print(da_sum_km)
```

```
<xarray.DataArray (dim_0: 3)>
array([2000., 4000., 6000.])
Dimensions without coordinates: dim_0
Attributes:
    units:    m

<xarray.DataArray (dim_0: 3)>
array([2., 4., 6.])
Dimensions without coordinates: dim_0
Attributes:
    units:    km
```

The units of the DataArray after the operation follows those of the DataArray with the `units` accessor.
The resulting data values will be therefore different depending on the order of the operation.
They are, of course, equal when considering units:

```python
da_eq = (da_sum_m.units == da_sum_km)
print(da_eq)
```

```
<xarray.DataArray (dim_0: 3)>
array([ True,  True,  True])
Dimensions without coordinates: dim_0
```

> [!IMPORTANT]
> Because this feature is accessor-based, units are only considered for the operation right after the `units` accessor.
> See [method and operation chains](#method-and-operation-chains) for performing multiple operations at once.

> [!TIP]
> There exist accessor methods corresponding to each operator (e.g. `add` → `+`, `eq` → `==`).
> See [the package guide](https://astropenguin.github.io/xarray-units/_apidoc/xarray_units.accessor.html) for more details.

### Formatting units

xarray-units converts units to [various string formats](https://docs.astropy.org/en/stable/units/format.html):

```python
da = xr.DataArray([1, 2, 3]).units.set("m / s^2")

da_console = da.units.format("console")
da_latex = da.units.format("latex")

print(da_console)
print(da_latex)
```

```
<xarray.DataArray (dim_0: 3)>
array([1, 2, 3])
Dimensions without coordinates: dim_0
Attributes:
    units:    m s^-2

<xarray.DataArray (dim_0: 3)>
array([1, 2, 3])
Dimensions without coordinates: dim_0
Attributes:
    units:    $\mathrm{\frac{m}{s^{2}}}$
```

This is useful, for example, when plotting a DataArray:

```python
da.units.format("latex").plot()
```

> [!NOTE]
> By default, the units of the DataArray coordinates will also be formatted.

## Advanced usages

### Handling units of coordinates

The `units` accessor has an option for handling units of DataArray coordinates.
For example, the following code will create a DataArray with `x` and `y` coordinates in units of meters:

```python
da_m = xr.DataArray([[1, 2], [3, 4]], dims=["x", "y"]).units.set("deg_C")
da_m = da_m.assign_coords(
    x=xr.DataArray([1000, 2000], dims="x").units.set("m"),
    y=xr.DataArray([3000, 4000], dims="y").units.set("m"),
)
print(da_m.x)
print(da_m.y)
```

```
<xarray.DataArray 'x' (x: 2)>
array([1000, 2000])
Coordinates:
  * x        (x) int64 1000 2000
Attributes:
    units:    m

<xarray.DataArray 'y' (y: 2)>
array([3000, 4000])
Coordinates:
  * y        (y) int64 3000 4000
Attributes:
    units:    m
```

To handling the units of the DataArray coordinates, use an option `of` for specifying them:

```python
da_km = da_m.units(of=["x", "y"]).to("km")
print(da_km.x)
print(da_km.y)
```

```
<xarray.DataArray 'x' (x: 2)>
array([1., 2.])
Coordinates:
  * x        (x) float64 1.0 2.0
Attributes:
    units:    km

<xarray.DataArray 'y' (y: 2)>
array([3., 4.])
Coordinates:
  * y        (y) float64 3.0 4.0
Attributes:
    units:    km
```

where `of` accepts the name(s) of the coordinate(s).

### Method and operation chains

The `units` accessor has an option `chain` for chaining methods or operations while considering units:

```python
da_m = xr.DataArray([1, 2, 3]).units.set("m")
da_s = xr.DataArray([1, 2, 3]).units.set("s")
da_a = da_m.units(chain=2) / da_s / da_s
print(da_a)
```

```
<xarray.DataArray (dim_0: 3)>
array([1.        , 0.5       , 0.33333333])
Dimensions without coordinates: dim_0
Attributes:
    units:    m / s2
```

where `chain` is the number of chained methods or operations.
This is equivalent to nesting the `units` accessors:

```python
(da_m.units / da_s).units / da_s
```

### Use with static type checking

xarray-units provides a special type hint `xarray_units.DataArray` with which type checkers can statically handle the `units ` accessor and its methods:

```python
from xarray_units import DataArray

da: DataArray = xr.DataArray([1, 2, 3]).units.set("km")
```

> [!TIP]
> `xarray_units.DataArray` will be replaced by `xarray.DataArray` at runtime, so it can also be used for creating and subclassing `DataArray`.

### Use without the units accessor

xarray-units provides a function `xarray_units.units` that returns the `units` accessor of a DataArray.
The following two codes are therefore equivalent:

```python
xr.DataArray([1, 2, 3]).units.set("km")
```

```python
from xarray_units import units

units(xr.DataArray([1, 2, 3])).set("km")
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/astropenguin/xarray-units/",
    "name": "xarray-units",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9,<3.13",
    "maintainer_email": "",
    "keywords": "xarray,xarray-accessor,xarray-extension,units",
    "author": "Akio Taniguchi",
    "author_email": "taniguchi@a.phys.nagoya-u.ac.jp",
    "download_url": "https://files.pythonhosted.org/packages/06/e3/226f29cc3d8ce5c24393e04ee560245b0155b92b11e1360e0fc97b3daa27/xarray_units-0.5.0.tar.gz",
    "platform": null,
    "description": "# xarray-units\n\n[![Release](https://img.shields.io/pypi/v/xarray-units?label=Release&color=cornflowerblue&style=flat-square)](https://pypi.org/project/xarray-units/)\n[![Python](https://img.shields.io/pypi/pyversions/xarray-units?label=Python&color=cornflowerblue&style=flat-square)](https://pypi.org/project/xarray-units/)\n[![Downloads](https://img.shields.io/pypi/dm/xarray-units?label=Downloads&color=cornflowerblue&style=flat-square)](https://pepy.tech/project/xarray-units)\n[![DOI](https://img.shields.io/badge/DOI-10.5281/zenodo.10354517-cornflowerblue?style=flat-square)](https://doi.org/10.5281/zenodo.10354517)\n[![Tests](https://img.shields.io/github/actions/workflow/status/astropenguin/xarray-units/tests.yaml?label=Tests&style=flat-square)](https://github.com/astropenguin/xarray-units/actions)\n\nxarray extension for handling units\n\n## Overview\n\nxarray-units is an import-only package that provides a [xarray](https://xarray.dev) DataArray accessor `.units` for handling units such as converting units and numeric operations considering units.\n[Astropy](https://www.astropy.org) is used as a backend.\nUnlike similar implementations, xarray-units does not use a special data type to handle units, but uses the original data type in a DataArray.\nThis allows to continue to use powerful features such as parallel and lazy processing with [Dask](https://www.dask.org) and/or user-defined DataArray subclasses.\n\n## Installation\n\n```shell\npip install xarray-units==0.5.0\n```\n\n## Basic usages\n\nSuppose the following imports will be commonly used in the examples:\n\n```python\nimport xarray as xr\nimport xarray_units\n```\n\n### Setting and unsetting units\n\nxarray-units sets units in DataArray attributes (`.attrs`) with the name `\"units\"`:\n\n```python\nda_km = xr.DataArray([1, 2, 3]).units.set(\"km\")\nprint(da_km)\n```\n\n```\n<xarray.DataArray (dim_0: 3)>\narray([1, 2, 3])\nDimensions without coordinates: dim_0\nAttributes:\n    units:    km\n```\n\nAnd the units can also be unset (deleted):\n\n```python\nda = da_km.units.unset()\nprint(da)\n```\n\n```\n<xarray.DataArray (dim_0: 3)>\narray([1, 2, 3])\nDimensions without coordinates: dim_0\n```\n\n> [!NOTE]\n> These are equivalent to manually un/setting the units in the DataArray attributes, but the `units` accessor also check that the units are valid when setting.\n\n### Converting units to others\n\nxarray-units converts a DataArray with units to other units:\n\n```python\nda_km = xr.DataArray([1, 2, 3]).units.set(\"km\")\nda_m = da_km.units.to(\"m\")\nprint(da_m)\n```\n\n```\n<xarray.DataArray (dim_0: 3)>\narray([1000., 2000., 3000.])\nDimensions without coordinates: dim_0\nAttributes:\n    units:    m\n```\n\nAstropy [equivalencies](https://docs.astropy.org/en/stable/units/equivalencies.html) can also be used for equivalences between different units:\n\n```python\nfrom astropy.units import spectral\n\nda_mm = xr.DataArray([1, 2, 3]).units.set(\"mm\")\nda_GHz = da_mm.units.to(\"GHz\", spectral())\nprint(da_GHz)\n```\n\n```\n<xarray.DataArray (dim_1: 3)>\narray([299.792458  , 149.896229  ,  99.93081933])\nDimensions without coordinates: dim_0\nAttributes:\n    units:    GHz\n```\n\n> [!TIP]\n> There exist other accessor methods (e.g. `decompose`, `like`) for converting units.\n> See [the package guide](https://astropenguin.github.io/xarray-units/_apidoc/xarray_units.accessor.html) for more details.\n\n### Numeric operations considering units\n\nxarray-units performs numerical operations considering units when the `units` accessor is attached to the DataArray on the left side of the operator:\n\n```python\nda_m = xr.DataArray([1000, 2000, 3000]).units.set(\"m\")\nda_km = xr.DataArray([1, 2, 3]).units.set(\"km\")\n\nda_sum_m = da_m.units + da_km\nda_sum_km = da_km.units + da_m\n\nprint(da_sum_m)\nprint(da_sum_km)\n```\n\n```\n<xarray.DataArray (dim_0: 3)>\narray([2000., 4000., 6000.])\nDimensions without coordinates: dim_0\nAttributes:\n    units:    m\n\n<xarray.DataArray (dim_0: 3)>\narray([2., 4., 6.])\nDimensions without coordinates: dim_0\nAttributes:\n    units:    km\n```\n\nThe units of the DataArray after the operation follows those of the DataArray with the `units` accessor.\nThe resulting data values will be therefore different depending on the order of the operation.\nThey are, of course, equal when considering units:\n\n```python\nda_eq = (da_sum_m.units == da_sum_km)\nprint(da_eq)\n```\n\n```\n<xarray.DataArray (dim_0: 3)>\narray([ True,  True,  True])\nDimensions without coordinates: dim_0\n```\n\n> [!IMPORTANT]\n> Because this feature is accessor-based, units are only considered for the operation right after the `units` accessor.\n> See [method and operation chains](#method-and-operation-chains) for performing multiple operations at once.\n\n> [!TIP]\n> There exist accessor methods corresponding to each operator (e.g. `add` \u2192 `+`, `eq` \u2192 `==`).\n> See [the package guide](https://astropenguin.github.io/xarray-units/_apidoc/xarray_units.accessor.html) for more details.\n\n### Formatting units\n\nxarray-units converts units to [various string formats](https://docs.astropy.org/en/stable/units/format.html):\n\n```python\nda = xr.DataArray([1, 2, 3]).units.set(\"m / s^2\")\n\nda_console = da.units.format(\"console\")\nda_latex = da.units.format(\"latex\")\n\nprint(da_console)\nprint(da_latex)\n```\n\n```\n<xarray.DataArray (dim_0: 3)>\narray([1, 2, 3])\nDimensions without coordinates: dim_0\nAttributes:\n    units:    m s^-2\n\n<xarray.DataArray (dim_0: 3)>\narray([1, 2, 3])\nDimensions without coordinates: dim_0\nAttributes:\n    units:    $\\mathrm{\\frac{m}{s^{2}}}$\n```\n\nThis is useful, for example, when plotting a DataArray:\n\n```python\nda.units.format(\"latex\").plot()\n```\n\n> [!NOTE]\n> By default, the units of the DataArray coordinates will also be formatted.\n\n## Advanced usages\n\n### Handling units of coordinates\n\nThe `units` accessor has an option for handling units of DataArray coordinates.\nFor example, the following code will create a DataArray with `x` and `y` coordinates in units of meters:\n\n```python\nda_m = xr.DataArray([[1, 2], [3, 4]], dims=[\"x\", \"y\"]).units.set(\"deg_C\")\nda_m = da_m.assign_coords(\n    x=xr.DataArray([1000, 2000], dims=\"x\").units.set(\"m\"),\n    y=xr.DataArray([3000, 4000], dims=\"y\").units.set(\"m\"),\n)\nprint(da_m.x)\nprint(da_m.y)\n```\n\n```\n<xarray.DataArray 'x' (x: 2)>\narray([1000, 2000])\nCoordinates:\n  * x        (x) int64 1000 2000\nAttributes:\n    units:    m\n\n<xarray.DataArray 'y' (y: 2)>\narray([3000, 4000])\nCoordinates:\n  * y        (y) int64 3000 4000\nAttributes:\n    units:    m\n```\n\nTo handling the units of the DataArray coordinates, use an option `of` for specifying them:\n\n```python\nda_km = da_m.units(of=[\"x\", \"y\"]).to(\"km\")\nprint(da_km.x)\nprint(da_km.y)\n```\n\n```\n<xarray.DataArray 'x' (x: 2)>\narray([1., 2.])\nCoordinates:\n  * x        (x) float64 1.0 2.0\nAttributes:\n    units:    km\n\n<xarray.DataArray 'y' (y: 2)>\narray([3., 4.])\nCoordinates:\n  * y        (y) float64 3.0 4.0\nAttributes:\n    units:    km\n```\n\nwhere `of` accepts the name(s) of the coordinate(s).\n\n### Method and operation chains\n\nThe `units` accessor has an option `chain` for chaining methods or operations while considering units:\n\n```python\nda_m = xr.DataArray([1, 2, 3]).units.set(\"m\")\nda_s = xr.DataArray([1, 2, 3]).units.set(\"s\")\nda_a = da_m.units(chain=2) / da_s / da_s\nprint(da_a)\n```\n\n```\n<xarray.DataArray (dim_0: 3)>\narray([1.        , 0.5       , 0.33333333])\nDimensions without coordinates: dim_0\nAttributes:\n    units:    m / s2\n```\n\nwhere `chain` is the number of chained methods or operations.\nThis is equivalent to nesting the `units` accessors:\n\n```python\n(da_m.units / da_s).units / da_s\n```\n\n### Use with static type checking\n\nxarray-units provides a special type hint `xarray_units.DataArray` with which type checkers can statically handle the `units ` accessor and its methods:\n\n```python\nfrom xarray_units import DataArray\n\nda: DataArray = xr.DataArray([1, 2, 3]).units.set(\"km\")\n```\n\n> [!TIP]\n> `xarray_units.DataArray` will be replaced by `xarray.DataArray` at runtime, so it can also be used for creating and subclassing `DataArray`.\n\n### Use without the units accessor\n\nxarray-units provides a function `xarray_units.units` that returns the `units` accessor of a DataArray.\nThe following two codes are therefore equivalent:\n\n```python\nxr.DataArray([1, 2, 3]).units.set(\"km\")\n```\n\n```python\nfrom xarray_units import units\n\nunits(xr.DataArray([1, 2, 3])).set(\"km\")\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "xarray extension for handling units",
    "version": "0.5.0",
    "project_urls": {
        "Documentation": "https://astropenguin.github.io/xarray-units/",
        "Homepage": "https://github.com/astropenguin/xarray-units/"
    },
    "split_keywords": [
        "xarray",
        "xarray-accessor",
        "xarray-extension",
        "units"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d1f47cbd6bf2372e725b1ad07ef9ab6b0fba9d4670cdb14fe65bbab94c8d2235",
                "md5": "e4a9520020404039d9797233529bcdfc",
                "sha256": "655179f97171f593449901ed7695253234899c4d2e4637ed9ed30765bfe02cd0"
            },
            "downloads": -1,
            "filename": "xarray_units-0.5.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e4a9520020404039d9797233529bcdfc",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9,<3.13",
            "size": 10926,
            "upload_time": "2024-02-03T18:55:15",
            "upload_time_iso_8601": "2024-02-03T18:55:15.049370Z",
            "url": "https://files.pythonhosted.org/packages/d1/f4/7cbd6bf2372e725b1ad07ef9ab6b0fba9d4670cdb14fe65bbab94c8d2235/xarray_units-0.5.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "06e3226f29cc3d8ce5c24393e04ee560245b0155b92b11e1360e0fc97b3daa27",
                "md5": "03aabfa67385e0aa322d490c0cc93ef2",
                "sha256": "b1d3d95eb7438dc0c8e64c07c6fae6790a9d7e4ecced75b6d5492d48e4c20ffd"
            },
            "downloads": -1,
            "filename": "xarray_units-0.5.0.tar.gz",
            "has_sig": false,
            "md5_digest": "03aabfa67385e0aa322d490c0cc93ef2",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9,<3.13",
            "size": 11147,
            "upload_time": "2024-02-03T18:55:16",
            "upload_time_iso_8601": "2024-02-03T18:55:16.707019Z",
            "url": "https://files.pythonhosted.org/packages/06/e3/226f29cc3d8ce5c24393e04ee560245b0155b92b11e1360e0fc97b3daa27/xarray_units-0.5.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-02-03 18:55:16",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "astropenguin",
    "github_project": "xarray-units",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "xarray-units"
}
        
Elapsed time: 0.29833s