Units in Python

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

Astropy has a lot of built-in units. A complete list can be found here.


In [ ]:
import numpy as np

import pandas as pd
from astropy.table import QTable

from astropy import units as u
from astropy import constants as const
from astropy.units import imperial
imperial.enable()

Note: because we imported the units package as u, you cannot use u as a variable name.

You can use the units by themselves:


In [ ]:
u.m    # The unit of meters

In [ ]:
u.s    # The unit of seconds

In [ ]:
u.m / u.s    # combine them into a composite unit

For any unit you can find all of the built-in units that are equivalent:


In [ ]:
u.m.find_equivalent_units()

The units package is much more useful when you combine it with scalars or arrays to create Quantities


In [ ]:
time_1 = 0.25 * u.s

time_1

In [ ]:
position = np.arange(1,6,1) * u.m    # np.arange(x,y,z) - create an array of numbers between x and y in steps z

position

In [ ]:
velocity = position / time_1

velocity

You can access the number and unit part of the Quantity separately:


In [ ]:
velocity.value

In [ ]:
velocity.unit

This is useful in formatting output:


In [ ]:
"The velocity of the first particle is {0:.1f}".format(velocity[0])

In [ ]:
"The velocity of the first particle is {0.value:.1f} in the units of {0.unit:s}.".format(velocity[0])

At example problem: How long would it take to go 100 km at velocities in velocity?


In [ ]:
distance = 100 * u.km

time_2 = distance / velocity

time_2

Notice that the units are a bit strange. We can simplify this using .decompose()


In [ ]:
time_2.decompose()

Unit conversion is really easy!


In [ ]:
time_2.to(u.h)

In [ ]:
velocity.to(u.cm / u.h)

In [ ]:
velocity.to(imperial.mi / u.h)

In [ ]:
velocity.si                     # quick conversion to SI units

In [ ]:
velocity.cgs                    # quick conversion to CGS units

In [ ]:
density = 3000 * (u.kg / u.m**3)     # From last week's homework

density.to(u.kg / u.km**3)

Units make math with Time easy!


In [ ]:
u.s.find_equivalent_units()

In [ ]:
time_3 = 29 * u.day + 7 * u.h + 56 * u.min + 12 * u.s
time_4 = 2 * u.fortnight + 1.33 * u.day

In [ ]:
time_3 - time_4

In [ ]:
(time_3 - time_4).to(u.min)

You can define your own units


In [ ]:
ringo = u.def_unit('Ringos', 3.712 * imperial.yd)

In [ ]:
position.to(ringo)

In [ ]:
velocity.to(ringo / u.s)

Dimentionless Units


In [ ]:
dimless_y = (1 * u.m) / (1 * u.km)

dimless_y

In [ ]:
dimless_y.unit

In [ ]:
dimless_y.decompose()   # returns the scale of the dimentionless quanity

Some math functions only make sense with dimentionless quanities


In [ ]:
np.log(2 * u.m)

In [ ]:
np.log((2 * u.km) / (1 * u.m))

In [ ]:
np.log10((2 * u.km) / (1 * u.m))

Or they expect the correct type of unit!


In [ ]:
np.sin(2 * u.m)

In [ ]:
np.sin(2 * u.deg)

Using units can save you headaches.

  • All of the trig functions expect all angles to be in radians.
  • If you forget this, it can lead to problems that are hard to debug

In [ ]:
np.sin(90)               # not really what I expected

In [ ]:
np.sin(90 * u.deg)       # better

QTables vs. DataFrames

  • Astropy tables are constructed to use units.
  • The units of the column will be saved with the table

Part II - Advantage Astropy


In [ ]:
planet_table = QTable.read('Planets.csv', format='ascii.csv')

In [ ]:
planet_table[0:3]

In [ ]:
planet_table['a'].unit = u.AU
planet_table[0:3]

The unit is now part of the structure of the table, and will be saved when the table is saved.


In [ ]:
planet_table['a'].to(u.km)

In [ ]:
planet_table['a'].to(u.km)[2]

You can use pandas to read in tables and then convert them to QTables


In [ ]:
planet_table2 = pd.read_csv('Planets.csv')

In [ ]:
planet_table2[0:3]

In [ ]:
planet_table3 = QTable.from_pandas(planet_table2)

In [ ]:
planet_table3['a'].unit = u.AU

In [ ]:
planet_table3[0:3]

In [ ]:
planet_table3['a']

In [ ]:
planet_table3['a'].to(u.km)

Constants

The Astropy package also includes a whole bunch of built-in constants to make your life easier.

A complete list of the built-in constants can be found here.


In [ ]:
const.G

In [ ]:
const.M_sun

An Example: The velocity of an object in circular orbit around the Sun is

$$ v=\sqrt{GM_{\odot}\over d} $$

In [ ]:
distance = planet_table['a'][0:3]  # Mercury, Venus, Earth

In [ ]:
orbit_v = np.sqrt(const.G * const.M_sun / distance)

orbit_v

In [ ]:
orbit_v.decompose()

In [ ]:
orbit_v.to(u.km/u.s)

In [ ]:
orbit_v.to(ringo/u.ms)

Functions and Units - (Last week's homework)


In [ ]:
def find_diameter(H,A):
    result = (1329 / np.sqrt(A)) * (10 ** (-0.2 * H))
    return result * u.km

In [ ]:
H = 3.34
A = 0.09

asteroid_diameter = find_diameter(H,A)
asteroid_diameter

In [ ]:
def find_mass(D):
    p = 3000 * (u.kg / u.m**3)
    result = p * (1/6) * np.pi * D**3
    return result

In [ ]:
asteroid_mass = find_mass(asteroid_diameter)
asteroid_mass

In [ ]:
asteroid_mass.decompose()

In [ ]:
moon_mass = u.def_unit('Lunar\ Masses', 7.34767309e22 * u.kg)

In [ ]:
asteroid_mass.to(moon_mass)

In [ ]: