%matplotlib inline


# Quantities, Units, and Constants#

The purpose of this demo is to demonstrate the capabilities of astropy astropy.units.Unit, astropy.units.Quantity, and astropy.units.Constant.

The astropy astropy.units.Quantity object handles defining, converting between, and performing arithmetic with physical quantities, such as meters, seconds, Hz, etc.

from astropy import units as u
import numpy as np


You can define a astropy.units.Quantity (a number with a unit) in a number of different ways.

42.0 * u.meter
[1., 2., 3.] * u.s
np.arange(10) * u.Hz

$[0,~1,~2,~3,~4,~5,~6,~7,~8,~9] \; \mathrm{Hz}$

These objects work as you would expect with most Python operators or numpy functions

np.power(2 * u.s, 3)
(2 * u.s) ** 2

$4 \; \mathrm{s^{2}}$

If needed you can get the value as well as the unit

q = 42.0 * u.meter
print("The value is {0} and the unit is {1}".format(q.value, q.unit))

The value is 42.0 and the unit is m


Using the astropy.units.Quantity.to function we can easily converted to another unit.

print(q.to('parsec'))

1.3611273015666334e-15 pc


and imperial units as also supported

from astropy.units import imperial
print(q.to(imperial.mile))

0.026097590073968023 mi


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

u.m / u.m

$\mathrm{}$

More complex conversions are also supported using astropy.units.equivalencies. For example, we can convert the GOES wavelength range to Hz or keV easily using the astropy.units.equivalencies.spectral.

print(([0.5, 4.0] * u.angstrom).to('Hz', u.spectral()))

print(([0.5, 4.0] * u.angstrom).to('keV', u.spectral()))

[5.99584916e+18 7.49481145e+17] Hz
[24.79683969  3.09960496] keV


Astropy provides a number of reference constants

from astropy import constants as astropy_const


SunPy also provides a number of relevant solar reference constants.

from sunpy.sun import constants as sunpy_const


astropy.units.Constant are simply quantities but they also provide an uncertainty and a reference

M_earth = astropy_const.M_earth
print("The mass of the Earth is {0} +/- {1} {2} [ref {3}].".format(M_earth.value, M_earth.uncertainty, M_earth.unit, M_earth.reference))

The mass of the Earth is 5.972167867791379e+24 +/- 1.3422009501651213e+20 kg [ref IAU 2015 Resolution B 3 + CODATA 2018].


The light travel time in minutes from the Sun to the Earth can be calculated

print((sunpy_const.au / astropy_const.c).to('min'))

8.316746397269274 min


Let’s define a function to calculate the plasma beta, with quantities we don’t have to worry about much beyond getting the equation correct

def plasma_beta(n, T, B):
return (2 * n * astropy_const.k_B * T) / (B ** 2 / (2 * astropy_const.mu0))


The plasma beta for the solar corona using appropriate parameters is given by the following. The decompose function works to simplify the units.

print(plasma_beta(1e9 * u.cm**-3, 3e6 * u.Kelvin, 10 * u.Gauss).decompose())

0.2081969643814698


If the input is given in the wrong units then an error may occur but a better way is to inforce the units on input. Let’s consider a simpler example here to calculate velocity. We use a function annotation to specify the units (this is a Python 3.5+ feature, see the quantity_input documentation for more details and Python 2 instructions):

@u.quantity_input
def speed(length: u.m, time: u.s):
return length / time