How do we define a Quantity and which parts does it have?
from astropy import units as u
# Define a quantity length
length = 26.2 * u.meter
# print it
print(length) # length is a quantity
26.2 m
# Type of quantity
type(length)
astropy.units.quantity.Quantity
# Type of unit
type(u.meter)
astropy.units.core.IrreducibleUnit
# Quantity
length
# value
length.value
26.2
# unit
length.unit
# information
length.info
dtype = float64 unit = m class = Quantity n_bad = 0
Quantities can be converted to other units systems or factors by using to()
# Convert it to: km, lyr
print(length.to(u.km))
print(length.to(u.lightyear))
0.0262 km 2.76934218514e-15 lyr
We can do arithmetic operations when the quantities have the compatible units:
# arithmetic with distances
distance_start = 10 * u.mm
distance_end = 23 * u.km
length = distance_end - distance_start
print(length)
22.99999 km
Quantities can also be combined, for example to measure speed
# calculate a speed
time = 15 * u.minute
speed = length / time
print(speed)
1.53333266667 km / min
# decompose it
print(speed.decompose())
print(speed.si)
25.5555444444 m / s 25.5555444444 m / s
from astropy.units import imperial
Something strange? Check what deffinition of pint astropy is using.
#1
from astropy.units import imperial
print(speed.to(imperial.mile/u.hour))
57.166124831 mi / h
#2
imperial.pint > 0.5 * u.l
# A liquid pint in US is 473 ml; in UK is 568 ml
False
#3
rectangle_area = 3 * u.km * 5 * u.m
print(rectangle_area)
print(rectangle_area.decompose())
print(rectangle_area.to(imperial.yard ** 2))
15.0 km m 15000.0 m2 17939.8506945 yd2
Many units are compositions of others, for example, one could create new combinationes for ease of use:
# create a composite unit
cms = u.cm / u.s
speed.to(cms)
# and in the imperial system
mph = imperial.mile / u.hour
speed.to(mph)
and others are already a composition:
# what can be converted from s-1?
(u.s ** -1).compose()
[Unit("Hz"), Unit("Bq"), Unit("3.7e+10 Ci")]
# or Jules?
(u.joule).compose()
[Unit("J"), Unit("1e+07 erg"), Unit("4.58742e+17 Ry"), Unit("6.24151e+18 eV")]
# Unity of R
(13.605692 * u.eV).to(u.Ry)
Sometime we get no units quantitites
# no units
nounits = 20. * u.cm / (1. * u.m)
nounits
What happen if we add a number to this?
# arithmetic with no units
nounits + 3
# final value of a no unit quantity
nounits.decompose() # It's a unitless quantity
Some conversions are not done by a conversion factor as between miles and kilometers, for example converting between wavelength and frequency.
# converting spectral quantities
(656.281 * u.nm).to(u.Hz) # Fails because they are not compatible
--------------------------------------------------------------------------- UnitConversionError Traceback (most recent call last) <ipython-input-24-1d7f56a8e756> in <module>() 1 # converting spectral quantities ----> 2 (656.281 * u.nm).to(u.Hz) # Fails because they are not compatible /home/dvd/.conda/envs/swc/lib/python2.7/site-packages/astropy/units/quantity.pyc in to(self, unit, equivalencies) 631 unit = Unit(unit) 632 new_val = self.unit.to(unit, self.view(np.ndarray), --> 633 equivalencies=equivalencies) 634 return self._new_view(new_val, unit) 635 /home/dvd/.conda/envs/swc/lib/python2.7/site-packages/astropy/units/core.pyc in to(self, other, value, equivalencies) 966 If units are inconsistent 967 """ --> 968 return self._get_converter(other, equivalencies=equivalencies)(value) 969 970 def in_units(self, other, value=1.0, equivalencies=[]): /home/dvd/.conda/envs/swc/lib/python2.7/site-packages/astropy/units/core.pyc in _get_converter(self, other, equivalencies) 867 except UnitsError: 868 return self._apply_equivalencies( --> 869 self, other, self._normalize_equivalencies(equivalencies)) 870 return lambda val: scale * _condition_arg(val) 871 /home/dvd/.conda/envs/swc/lib/python2.7/site-packages/astropy/units/core.pyc in _apply_equivalencies(self, unit, other, equivalencies) 858 raise UnitConversionError( 859 "{0} and {1} are not convertible".format( --> 860 unit_str, other_str)) 861 862 def _get_converter(self, other, equivalencies=[]): UnitConversionError: 'nm' (length) and 'Hz' (frequency) are not convertible
# but doing it right
(656.281 * u.nm).to(u.Hz, equivalencies=u.spectral())
Other built-in equivalencies are:
parallax()
dopplr_radio
, doppler_optical
, doppler_relativistic
)# finding the equivalencies
u.Hz.find_equivalent_units()
Primary name | Unit definition | Aliases [ Bq | 1 / s | becquerel , Ci | 2.7027e-11 / s | curie , Hz | 1 / s | Hertz, hertz , ]
# but also using other systems
u.Hz.find_equivalent_units(equivalencies=u.spectral())
Primary name | Unit definition | Aliases [ AU | 1.49598e+11 m | au, astronomical_unit , Angstrom | 1e-10 m | AA, angstrom , Bq | 1 / s | becquerel , Ci | 2.7027e-11 / s | curie , Hz | 1 / s | Hertz, hertz , J | kg m2 / s2 | Joule, joule , Ry | 2.17987e-18 kg m2 / s2 | rydberg , cm | 0.01 m | centimeter , eV | 1.60218e-19 kg m2 / s2 | electronvolt , erg | 1e-07 kg m2 / s2 | , k | 100 / m | Kayser, kayser , lyr | 9.46073e+15 m | lightyear , m | irreducible | meter , micron | 1e-06 m | , pc | 3.08568e+16 m | parsec , solRad | 6.95508e+08 m | R_sun, Rsun , ]
# Printing values with different formats
print("{0.value:0.03f} {0.unit:FITS}".format(speed))
print("{0.value:0.03f} {0.unit:latex_inline}".format(speed))
1.533 km min-1 1.533 $\mathrm{km\,min^{-1}}$
Quantities can also be applied to arrays
# different ways of defining a quantity for a single value
length = 44 * u.m
time = u.Quantity(23, u.s)
speed = length / time
speed
# now with lists
length_list = [1, 2, 3] * u.m
# and arrays
import numpy as np
time_array = np.array([1, 2, 3]) * u.s
# and its arithmetics
length_list / time_array
# angles are smart!
angle = u.Quantity(np.arange(180), u.deg)
print(angle[[0, -1]])
print(np.sin(angle[[0, -1]]))
[ 0. 179.] deg [ 0. 0.01745241]
To work nicely with matplotlib we need to do as follows:
# allowing for plotting
from astropy.visualization import quantity_support
quantity_support()
# loading matplotlib
%matplotlib inline
from matplotlib import pyplot as plt
# Ploting the previous array
plt.plot(angle, np.sin(angle))
[<matplotlib.lines.Line2D at 0x7f5ec58923d0>]
We want to have functions that contain the information of the untis, and with them we can be sure that we will be always have the right result.
# Create a function for the Kinetic energy
@u.quantity_input(mass=u.kg, speed=u.m/u.s)
def kinetic(mass, speed):
return (mass * speed ** 2 / 2.).to(u.joule)
# run with and without units
kinetic(5, 10) # Fails! it doesn't specify the units.
kinetic(5 * u.kg, 100 * cms)
#4
@u.quantity_input(mass=u.kg, height=u.m, g=u.m / u.s ** 2)
def potential(mass, height, g=9.8 * u.m / u.s **2):
return (0.5 * mass * g * height).to(u.joule)
# run it for some values
potential(5 * u.kg, 30 *u.cm)
# on Mars:
potential(5 * u.kg, 1 * u.m, g=3.75 * u.m/u.s**2)
Some times we want to create our own units:
# Create units for a laugh scale
titter = u.def_unit('titter')
chuckle = u.def_unit('chuckle', 5 * titter)
laugh = u.def_unit('laugh', 4 * chuckle)
guffaw = u.def_unit('guffaw', 3 * laugh)
rofl = u.def_unit('rofl', 4 * guffaw)
death_by_laughing = u.def_unit('death_by_laughing', 10 * rofl)
print((1 * rofl).to(titter))
240.0 titter
#5
ares = u.def_unit('ares', (10 * u.m)**2)
hectar = u.def_unit('hectares', 100 * ares)
print(rectangle_area.to(hectar))
1.5 hectares