Unit Conversion

Documentation

For more information about the features presented below, you can read the astropy.units docs.

Representing units and quantities

Astropy includes a powerful framework for units that allows users to attach units to scalars and arrays, and manipulate/combine these, keeping track of the units.

Since we may want to use a number of units in expressions, it is easiest and most concise to import the units module with:

In [1]:
from astropy import units as u

though note that this will conflict with any variable called u.

Units can then be accessed with:

In [2]:
u.m
Out[2]:
$\mathrm{m}$

They all have a docstring defining them:

In [3]:
u.m.__doc__
Out[3]:
u'meter: base unit of length in SI'
In [4]:
u.m.physical_type
Out[4]:
u'length'
In [5]:
u.pc
Out[5]:
$\mathrm{pc}$
In [6]:
u.pc.__doc__
Out[6]:
u'parsec: approximately 3.26 light-years.'
In [7]:
u.s
Out[7]:
$\mathrm{s}$
In [8]:
u.kg
Out[8]:
$\mathrm{kg}$

The full list of available units is available here.

We can create composite units:

In [9]:
u.m / u.kg / u.s**2
Out[9]:
$\mathrm{\frac{m}{kg\,s^{2}}}$
In [10]:
repr(u.m / u.kg / u.s**2)
Out[10]:
'Unit("m / (kg s2)")'

The most useful feature about the units is the ability to attach them to scalars or arrays, creating Quantity objects:

In [11]:
3. * u.m
Out[11]:
$3 \; \mathrm{m}$
In [12]:
import numpy as np
In [13]:
np.array([1.2, 2.2, 1.7]) * u.pc / u.year
Out[13]:
<Quantity [ 1.2, 2.2, 1.7] pc / yr>

Combining and converting units

Quantities can then be combined:

In [14]:
q1 = 3. * u.m
In [15]:
q2 = 5. * u.cm / u.s / u.g**2
In [16]:
q1 * q2
Out[16]:
$15 \; \mathrm{\frac{cm\,m}{s\,g^{2}}}$

and converted to different units:

In [17]:
(q1 * q2).to(u.m**2 / u.kg**2 / u.s)
Out[17]:
$150000 \; \mathrm{\frac{m^{2}}{s\,kg^{2}}}$

The units and value of a quantity can be accessed separately via the value and unit attributes:

In [18]:
q = 5. * u.pc
In [19]:
q.value
Out[19]:
5.0
In [20]:
q.unit
Out[20]:
$\mathrm{pc}$

Advanced features

The units of a quantity can be decomposed into a set of base units using the decompose() method. By default, units will be decomposed to S.I.:

In [21]:
(3. * u.cm * u.pc / u.g / u.year**2).decompose()
Out[21]:
$929.531 \; \mathrm{\frac{m^{2}}{kg\,s^{2}}}$

To compose into c.g.s. bases:

In [22]:
u.cgs.bases
Out[22]:
{Unit("mol"),
 Unit("rad"),
 Unit("cd"),
 Unit("cm"),
 Unit("g"),
 Unit("s"),
 Unit("C"),
 Unit("K")}
In [23]:
(3. * u.cm * u.pc / u.g / u.year**2).decompose(u.cgs.bases)
Out[23]:
$9295.31 \; \mathrm{\frac{cm^{2}}{g\,s^{2}}}$

To decompose and recompose into the highest-level c.g.s. units, one can do:

In [24]:
(3. * u.cm * u.pc / u.g / u.year**2).cgs
Out[24]:
$9295.31 \; \mathrm{\frac{erg}{g^{2}}}$

Using physical constants

The astropy.constants module contains physical constants relevant for Astronomy, and these are defined with units attached to them using the astropy.units framework.

If we want to compute the Gravitational force felt by a 100. * u.kg space probe by the Sun, at a distance of 3.2au, we can do:

In [25]:
from astropy.constants import G
In [26]:
F = (G * 1. * u.M_sun * 100. * u.kg) / (3.2 * u.au)**2
In [27]:
F
Out[27]:
$6.51742\times 10^{-10} \; \mathrm{\frac{m^{3}\,M_{\odot}}{AU^{2}\,s^{2}}}$
In [28]:
F.to(u.N)
Out[28]:
$0.0579271 \; \mathrm{N}$

The full list of available physical constants is shown here (and additions are welcome!).

Equivalencies

Equivalencies can be used to convert quantities that are not strictly the same physical type:

In [29]:
(450. * u.nm).to(u.GHz)
---------------------------------------------------------------------------
UnitsError                                Traceback (most recent call last)
<ipython-input-29-e4fbcb033257> in <module>()
----> 1 (450. * u.nm).to(u.GHz)

/Users/tom/Library/Python/2.7/lib/python/site-packages/astropy/units/quantity.pyc in to(self, unit, equivalencies)
    566         unit = Unit(unit)
    567         new_val = np.asarray(
--> 568             self.unit.to(unit, self.value, equivalencies=equivalencies))
    569         return self._new_view(new_val, unit)
    570 

/Users/tom/Library/Python/2.7/lib/python/site-packages/astropy/units/core.pyc in to(self, other, value, equivalencies)
    910             If units are inconsistent
    911         """
--> 912         return self.get_converter(other, equivalencies=equivalencies)(value)
    913 
    914     def in_units(self, other, value=1.0, equivalencies=[]):

/Users/tom/Library/Python/2.7/lib/python/site-packages/astropy/units/core.pyc in get_converter(self, other, equivalencies)
    846         except UnitsError:
    847             return self._apply_equivalences(
--> 848                 self, other, self._normalize_equivalencies(equivalencies))
    849         return lambda val: scale * _condition_arg(val)
    850 

/Users/tom/Library/Python/2.7/lib/python/site-packages/astropy/units/core.pyc in _apply_equivalences(self, unit, other, equivalencies)
    809         raise UnitsError(
    810             "{0} and {1} are not convertible".format(
--> 811                 unit_str, other_str))
    812 
    813     def get_converter(self, other, equivalencies=[]):

UnitsError: 'nm' (length) and 'GHz' (frequency) are not convertible
In [30]:
(450. * u.nm).to(u.GHz, equivalencies=u.spectral())
Out[30]:
$666205 \; \mathrm{GHz}$
In [31]:
(450. * u.eV).to(u.nm, equivalencies=u.spectral())
Out[31]:
$2.7552 \; \mathrm{nm}$
In [32]:
q = (1e-18 * u.erg / u.cm**2 / u.s / u.AA)
q.to(u.Jy, equivalencies=u.spectral_density(u.mm, 1))
Out[32]:
$3.33564 \; \mathrm{Jy}$

Integration with Numpy ufuncs

Most of the Numpy functions understand Quantity objects:

In [33]:
np.sin(30 * u.degree)
Out[33]:
$0.5 \; \mathrm{}$
In [34]:
np.sqrt(100 * u.km*u.km)
Out[34]:
$10 \; \mathrm{km}$
In [35]:
np.exp(3 * u.m/ (3 * u.km))
Out[35]:
$1.001 \; \mathrm{}$

Care needs to be taken with dimensionless units. Passing raw values to an inverse trig function, there will be no units in the result:

In [36]:
np.arcsin(1.0)
Out[36]:
1.5707963267948966

However, u.dimensionless_unscaled creates a Quantity "with the dimensionless unit" from a value, and therefore we do units in the output:

In [37]:
np.arcsin(1.0 * u.dimensionless_unscaled)
Out[37]:
$1.5708 \; \mathrm{rad}$
In [38]:
np.arcsin(1.0 * u.dimensionless_unscaled).to(u.degree)
Out[38]:
$90 \; \mathrm{{}^{\circ}}$

Practical Exercises

Level 1

What is 1 barn megaparsecs in teaspoons? Note that teaspoons are not part of the standard set of units, but it can be found in:

In [39]:
from astropy.units import imperial
imperial.tsp  
Out[39]:
$\mathrm{tsp}$

Level 2

What is \(3 \mathrm{nm}^2 \mathrm{Mpc} / \mathrm{m}^3\) in dimensionless units?

Level 3

Try and use equivalencies to find the doppler shifted wavelength of a line at \(454.4\mathrm{nm}\) if the object is moving at a velocity of \(510\mathrm{km}/\mathrm{s}\). You will need to read up more about the available equivalencies here