Skip to main content
`Ctrl`+`K`

# Units and Quantities (`astropy.units`)

## Introduction

`astropy.units` handles defining, converting between, and performing arithmetic with physical quantities, such as meters, seconds, Hz, etc. It also handles logarithmic units such as magnitude and decibel.

`astropy.units` does not know spherical geometry or sexagesimal (hours, min, sec): if you want to deal with celestial coordinates, see the `astropy.coordinates` package.

## Getting Started

Most users of the `astropy.units` package will work with Quantity objects: the combination of a value and a unit. The most convenient way to create a |Quantity| is to multiply or divide a value by one of the built-in units. It works with scalars, sequences, and `numpy` arrays.

### Examples

To create a |Quantity| object:

    >>> from astropy import units as u
    >>> 42.0 * u.meter
    <Quantity  42. m>
    >>> [1., 2., 3.] * u.m
    <Quantity [1., 2., 3.] m>
    >>> import numpy as np
    >>> np.array([1., 2., 3.]) * u.m
    <Quantity [1., 2., 3.] m>

You can get the unit and value from a |Quantity| using the unit and value members:

    >>> q = 42.0 * u.meter
    >>> q.value
    np.float64(42.0)
    >>> q.unit
    Unit("m")

From this basic building block, it is possible to start combining quantities with different units:

    >>> 15.1 * u.meter / (32.0 * u.second)
    <Quantity 0.471875 m / s>
    >>> 3.0 * u.kilometer / (130.51 * u.meter / u.second)
    <Quantity 0.022986744310780783 km s / m>
    >>> (3.0 * u.kilometer / (130.51 * u.meter / u.second)).decompose()
    <Quantity 22.986744310780782 s>

Unit conversion is done using the `to()` method, which returns a new |Quantity| in the given unit:

    >>> x = 1.0 * u.parsec
    >>> x.to(u.km)
    <Quantity 30856775814671.914 km>

It is also possible to work directly with units at a lower level, for example, to create custom units:

    >>> from astropy.units import imperial

    >>> cms = u.cm / u.s
    >>> # ...and then use some imperial units
    >>> mph = imperial.mile / u.hour

    >>> # And do some conversions
    >>> q = 42.0 * cms
    >>> q.to(mph)
    <Quantity 0.939513242662849 mi / h>

Units that “cancel out” become a special unit called the “dimensionless unit”:

    >>> u.m / u.m
    Unit(dimensionless)

To create a basic dimensionless quantity, multiply a value by the unscaled dimensionless unit:

    >>> q = 1.0 * u.dimensionless_unscaled
    >>> q.unit
    Unit(dimensionless)

`astropy.units` is able to match compound units against the units it already knows about:

    >>> (u.s ** -1).compose()
    [Unit("Bq"), Unit("Hz"), Unit("2.7027e-11 Ci")]

And it can convert between unit systems, such as SI or CGS:

    >>> (1.0 * u.Pa).cgs
    <Quantity 10. Ba>

The units `mag`, `dex`, and `dB` are special, being logarithmic units, for which a value is the logarithm of a physical quantity in a given unit. These can be used with a physical unit in parentheses to create a corresponding logarithmic quantity:

    >>> -2.5 * u.mag(u.ct / u.s)
    <Magnitude -2.5 mag(ct / s)>
    >>> from astropy import constants as c
    >>> u.Dex((c.G * u.M_sun / u.R_sun**2).cgs)
    <Dex 4.438067627303133 dex(cm / s2)>

`astropy.units` also handles equivalencies, such as that between wavelength and frequency. To use that feature, equivalence objects are passed to the `to()` conversion method. For instance, a conversion from wavelength to frequency does not normally work:

    >>> (1000 * u.nm).to(u.Hz)
    Traceback (most recent call last):
      ...
    UnitConversionError: 'nm' (length) and 'Hz' (frequency) are not convertible

But by passing an equivalency list, in this case `spectral()`, it does:

    >>> (1000 * u.nm).to(u.Hz, equivalencies=u.spectral())
    <Quantity  2.99792458e+14 Hz>

Quantities and units can be printed nicely to strings using the Format String Syntax. Format specifiers (like `0.03f`) in strings will be used to format the quantity value:

    >>> q = 15.1 * u.meter / (32.0 * u.second)
    >>> q
    <Quantity 0.471875 m / s>
    >>> f"{q:0.03f}"
    '0.472 m / s'

The value and unit can also be formatted separately. Format specifiers for units can be used to choose the unit formatter:

    >>> q = 15.1 * u.meter / (32.0 * u.second)
    >>> q
    <Quantity 0.471875 m / s>
    >>> f"{q.value:0.03f} {q.unit:FITS}"
    '0.472 m s-1'

## Using `astropy.units`

- Quantity
  - Creating Quantity Instances
  - Converting to Different Units
  - Comparing Quantities
  - Plotting Quantities
  - Arithmetic
  - NumPy Functions
  - Dimensionless Quantities
  - Converting to Plain Python Scalars
  - Functions that Accept Quantities
  - Representing Vectors with Units
  - Creating and Converting Quantities without Copies
  - The `numpy.dtype` of a Quantity
  - QTable
  - Subclassing Quantity
- Unit-Aware Type Annotations
  - Quantity Type Annotation
  - Multiple Annotations
- Type Annotations Module
- Standard Units
  - Prefixes
  - The Dimensionless Unit
  - Enabling Other Units
- Combining and Defining Units
  - Basic example
  - Fractional powers
  - Defining units
- Decomposing and Composing Units
  - Reducing a Unit to Its Irreducible Parts
  - Automatically Composing a Unit into More Complex Units
  - Converting Between Systems
- Magnitudes and Other Logarithmic Units
  - Creating Logarithmic Quantities
  - Converting to Different Units
  - Arithmetic and Photometric Applications
  - NumPy Functions
  - Dimensionless Logarithmic Quantities
- Structured Units
  - Creating Structured Quantities
  - Converting to Different Units
  - Use with ERFA
- String Representations of Units and Quantities
  - Converting to Strings
  - Converting from Strings
  - Built-In Formats
  - Dealing with Unrecognized Units
- Equivalencies
  - Built-In Equivalencies
  - Writing New Equivalencies
  - Displaying Available Equivalencies
  - Using Equivalencies in Larger Pieces of Code
- Physical Types
  - Accessing Physical Types
  - Using Physical Types
  - Dimensional Analysis
- Using Prior Versions of Constants
  - Example
- Low-Level Unit Conversion
  - Direct Conversion
  - Incompatible Conversions

## Acknowledgments

This code was originally based on the pynbody units module written by Andrew Pontzen, who has granted the Astropy Project permission to use the code under a BSD license.

## See Also

- FITS Standard for units in FITS.

- The Units in the VO 1.0 Standard for representing units in the VO.

- OGIP Units: A standard for storing units in OGIP FITS files.

- Standards for astronomical catalogues: units.

- IAU Style Manual.

- A table of astronomical unit equivalencies.

## Performance Tips

If you are attaching units to arrays to make |Quantity| objects, multiplying arrays by units will result in the array being copied in memory, which will slow things down. Furthermore, if you are multiplying an array by a composite unit, the array will be copied for each individual multiplication. Thus, in the following case, the array is copied four successive times:

    In [1]: import numpy as np

    In [2]: from astropy import units as u

    In [3]: rng = np.random.default_rng()

    In [4]: array = rng.random(10000000)

    In [5]: %timeit array * u.m / u.s / u.kg / u.sr
    92.5 ms ± 2.52 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

There are several ways to speed this up. First, when you are using composite units, ensure that the entire unit gets evaluated first, then attached to the array. You can do this by using parentheses as for any other operation:

    In [6]: %timeit array * (u.m / u.s / u.kg / u.sr)
    21.5 ms ± 886 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In this case, this has sped things up by a factor of 4. If you use a composite unit several times in your code then you can define a variable for it:

    In [7]: UNIT_MSKGSR = u.m / u.s / u.kg / u.sr

    In [8]: %timeit array * UNIT_MSKGSR
    22.2 ms ± 551 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In this case and the case with brackets, the array is still copied once when creating the |Quantity|. If you want to avoid any copies altogether, you can make use of the `<<` operator to attach the unit to the array:

    In [9]: %timeit array << u.m / u.s / u.kg / u.sr
    47.1 µs ± 5.77 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Note that these are now microseconds, so this is 2000x faster than the original case with no brackets. Note that brackets are not needed when using `<<` since `*` and `/` have a higher precedence, so the unit will be evaluated first. When using `<<`, be aware that because the data is not being copied, changing the original array will also change the |Quantity| object.

Note that for composite units, you will definitely see an impact if you can pre-compute the composite unit:

    In [10]: %timeit array << UNIT_MSKGSR
    6.51 µs ± 112 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Which is over 10000x faster than the original example. See Creating and Converting Quantities without Copies for more details about the `<<` operator.

## Reference/API

- Reference/API
  - astropy.units Package
  - astropy.units.si Module
  - astropy.units.cgs Module
  - astropy.units.astrophys Module
  - astropy.units.misc Module
  - astropy.units.function.units Module
  - astropy.units.photometric Module
  - astropy.units.imperial Module
  - astropy.units.cds Module
  - astropy.units.physical Module
  - astropy.units.format Package
  - astropy.units.required_by_vounit Module