Testing a couple of different packages for handling units: astropy.units
, quantities
, and pint
.
astropy.units
¶Replicating the handy online tutorial.
import astropy.units as u
import numpy as np
--------------------------------------------------------------------------- ModuleNotFoundError Traceback (most recent call last) <ipython-input-1-26f5b13a62e6> in <module> ----> 1 import astropy.units as u 2 import numpy as np ModuleNotFoundError: No module named 'astropy'
42.0 * u.meter
[1., 2., 3.] * u.m
np.array([1., 2., 3.]) * u.m
w = 42.0 * u.kilogram
w.value
42.0
w.unit
dir(w)
['T', '__abs__', '__add__', '__and__', '__array__', '__array_finalize__', '__array_interface__', '__array_prepare__', '__array_priority__', '__array_struct__', '__array_wrap__', '__class__', '__contains__', '__copy__', '__deepcopy__', '__delattr__', '__delitem__', '__delslice__', '__dict__', '__dir__', '__div__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__', '__idiv__', '__ifloordiv__', '__ilshift__', '__imod__', '__imul__', '__index__', '__init__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__', '__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__', '__long__', '__lshift__', '__lt__', '__mod__', '__module__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__quantity_subclass__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__setitem__', '__setslice__', '__setstate__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__xor__', '_decompose', '_equivalencies', '_include_easy_conversion_members', '_new_view', '_repr_latex_', '_to_own_unit', '_unit', '_unitstr', '_wrap_function', 'all', 'any', 'argmax', 'argmin', 'argpartition', 'argsort', 'astype', 'base', 'byteswap', 'cgs', 'choose', 'clip', 'compress', 'conj', 'conjugate', 'copy', 'ctypes', 'cumprod', 'cumsum', 'data', 'decompose', 'diagonal', 'diff', 'dot', 'dtype', 'dump', 'dumps', 'ediff1d', 'equivalencies', 'fill', 'flags', 'flat', 'flatten', 'getfield', 'imag', 'insert', 'isscalar', 'item', 'itemset', 'itemsize', 'max', 'mean', 'min', 'nansum', 'nbytes', 'ndim', 'newbyteorder', 'nonzero', 'partition', 'prod', 'ptp', 'put', 'ravel', 'real', 'repeat', 'reshape', 'resize', 'round', 'searchsorted', 'setfield', 'setflags', 'shape', 'si', 'size', 'sort', 'squeeze', 'std', 'strides', 'sum', 'swapaxes', 'take', 'to', 'tobytes', 'tofile', 'tolist', 'tostring', 'trace', 'transpose', 'unit', 'value', 'var', 'view']
Variables and attributes:
d = 2300. * u.kg/u.m**3
d
d.unit
vp = 2500 * u.m/u.s
z = vp * d
z
z.unit
z.unit.compose()
[Unit("10 P / m")]
Convert velocity to ft/s:
from astropy.units import imperial
vp.to(imperial.foot/u.s)
# To put it another way:
vp * 3.28084 * (imperial.foot/u.m)
fps = imperial.foot/u.second
vp_imperial = vp.to(fps)
vp_imperial
vp.cgs
vp_imperial.si
I think we could define a unit system, oilfield
or oil
perhaps, that has feet, g/cm^3, seconds, degF, etc.
We would also have to define various units like barrel, boe, cubic foot, etc.
t = 245 * u.deg_C
t
u.equivalencies.temperature()
[(Unit("K"), Unit("deg_C"), <function astropy.units.equivalencies.<lambda>>, <function astropy.units.equivalencies.<lambda>>), (Unit("deg_C"), Unit("deg_F"), <function astropy.units.equivalencies.<lambda>>, <function astropy.units.equivalencies.<lambda>>), (Unit("K"), Unit("deg_F"), <function astropy.units.equivalencies.<lambda>>, <function astropy.units.equivalencies.<lambda>>)]
I do like how IPython plays so nicely with the formatting.
quantities
¶Potentially nice because it can also handle uncertainties. Following the tutorial...
import quantities as pq
vel = 2.5 * pq.km/pq.s
vel
array(2.5) * km/s
vel.units = pq.ft/pq.s
vel
array(8202.099737532808) * ft/s
I think I prefer having a to
method on the quantity object, rather than setting an attribute.
Uncertainties are quite cool, though, if rather deterministic...
den = pq.UncertainQuantity(2850., pq.kg/pq.m**3, 75.)
den
UncertainQuantity(array(2850.0), kg/m**3, array(75.0))
imp = vel * den
imp
UncertainQuantity(array(23375984.251968503), kg*ft/(m**3*s), array(615157.4803149606))
pint
¶from pint import UnitRegistry
ureg = UnitRegistry()
vs = 1200. * ureg.meter/ureg.second
vs
vs.units
<UnitsContainer({'meter': 1.0, 'second': -1.0})>
vs.magnitude
1200.0
vs.dimensionality
<UnitsContainer({'[length]': 1.0, '[time]': -1.0})>
zs = vs * d
zs
Not sure if this is good or bad, but pint
knows about aliases and alternate spellings:
vs.to(ureg.feet/ureg.s)
vs.to(ureg.foot/ureg.s)
5.0 * ureg.metres
As with astropy, we can define units:
ftps = ureg.foot/ureg.second
vs.to(ftps)
t = 2245.0 * ureg.rankine
t
t.to(ureg.degC)
p = 4500. * ureg.psi
p.to(ureg.MPa)
pint
with numpy
¶Need to see how the units respond to being differenced, convolved, etc.