Structured Units¶
Numpy arrays can be structured arrays, where
each element consists of multiple fields. These can be used with Quantity
using a StructuredUnit
, which provides a UnitBase
for each field. For example,
this allows constructing a single Quantity
object with position and velocity
fields that have different units, but are contained within the same object
(as is needed to support units in the PyERFA wrappers around the ERFA
routines that use position-velocity arrays).
Creating Structured Quantities¶
You can create structured quantities either directly or by multiplication with
a StructuredUnit
, with the latter in turn either created directly, or
through Unit
.
Example¶
To create a structured quantity containing a position and velocity:
>>> import astropy.units as u, numpy as np
>>> pv_values = np.array([([1., 0., 0.], [0., 0.125, 0.]),
... ([0., 1., 0.], [-0.125, 0., 0.])],
... dtype=[('p', '(3,)f8'), ('v', '(3,)f8')])
>>> pv = u.Quantity(pv_values, u.StructuredUnit((u.km, u.km/u.s)))
>>> pv
<Quantity [([1., 0., 0.], [ 0. , 0.125, 0. ]),
([0., 1., 0.], [-0.125, 0. , 0. ])] (km, km / s)>
>>> pv_values * u.Unit('AU, AU/day')
<Quantity [([1., 0., 0.], [ 0. , 0.125, 0. ]),
([0., 1., 0.], [-0.125, 0. , 0. ])] (AU, AU / d)>
As for normal Quantity
objects, you can access the value and the unit with the
value
and unit
attribute,
respectively. In addition, you can index any given field using its name:
>>> pv = pv_values * u.Unit('km, km/s')
>>> pv.value
array([([1., 0., 0.], [ 0. , 0.125, 0. ]),
([0., 1., 0.], [-0.125, 0. , 0. ])],
dtype=[('p', '<f8', (3,)), ('v', '<f8', (3,))])
>>> pv.unit
Unit("(km, km / s)")
>>> pv['v']
<Quantity [[ 0. , 0.125, 0. ],
[-0.125, 0. , 0. ]] km / s>
Structures can be nested, as in this example taken from an PyERFA test case
for erfa.ldn()
:
>>> ldbody = [
... (0.00028574, 3e-10, ([-7.81014427, -5.60956681, -1.98079819],
... [0.0030723249, -0.00406995477, -0.00181335842])),
... (0.00095435, 3e-9, ([0.738098796, 4.63658692, 1.9693136],
... [-0.00755816922, 0.00126913722, 0.000727999001])),
... (1.0, 6e-6, ([-0.000712174377, -0.00230478303, -0.00105865966],
... [6.29235213e-6, -3.30888387e-7, -2.96486623e-7]))
... ] * u.Unit('Msun,radian,(AU,AU/day)')
>>> ldbody
<Quantity [(2.8574e-04, 3.e-10, ([-7.81014427e+00, -5.60956681e+00, -1.98079819e+00], [ 3.07232490e-03, -4.06995477e-03, -1.81335842e-03])),
(9.5435e-04, 3.e-09, ([ 7.38098796e-01, 4.63658692e+00, 1.96931360e+00], [-7.55816922e-03, 1.26913722e-03, 7.27999001e-04])),
(1.0000e+00, 6.e-06, ([-7.12174377e-04, -2.30478303e-03, -1.05865966e-03], [ 6.29235213e-06, -3.30888387e-07, -2.96486623e-07]))] (solMass, rad, (AU, AU / d))>
Converting to Different Units¶
Like regular Quantity
objects, structured quantities can be converted to
different units, as long as they have the same structure and each unit is
equivalent.
Example¶
To convert a structured quantity to a different unit:
>>> pv.to((u.m, u.m / u.s))
<Quantity [([1000., 0., 0.], [ 0., 125., 0.]),
([ 0., 1000., 0.], [-125., 0., 0.])] (m, m / s)>
>>> pv.cgs
<Quantity [([100000., 0., 0.], [ 0., 12500., 0.]),
([ 0., 100000., 0.], [-12500., 0., 0.])] (cm, cm / s)>
Use with ERFA¶
The ERFA C routines make use of structured types, and these are exposed in the PyERFA interface.
Warning
Not all PyERFA routines are wrapped yet. Help with adding wrappers will be appreciated.
Example¶
To use a position-velocity structured array with PyERFA:
>>> import erfa
>>> pv_values = np.array([([1., 0., 0.], [0., 0.125, 0.]),
... ([0., 1., 0.], [-0.125, 0., 0.])],
... dtype=erfa.dt_pv)
>>> pv = pv_values << u.Unit('AU,AU/day')
>>> erfa.pvu(86400*u.s, pv)
<Quantity [([ 1. , 0.125, 0. ], [ 0. , 0.125, 0. ]),
([-0.125, 1. , 0. ], [-0.125, 0. , 0. ])] (AU, AU / d)>
>>> erfa.pv2s(pv)
(<Quantity [0. , 1.57079633] rad>,
<Quantity [0., 0.] rad>,
<Quantity [1., 1.] AU>,
<Quantity [0.125, 0.125] rad / d>,
<Quantity [0., 0.] rad / d>,
<Quantity [0., 0.] AU / d>)
>>> z_axis = np.array(([0, 0, 1], [0, 0, 0]), erfa.dt_pv) * u.Unit('1,1/s')
>>> erfa.pvxpv(pv, z_axis)
<Quantity [([ 0., -1., 0.], [0.125, 0. , 0. ]),
([ 1., 0., 0.], [0. , 0.125, 0. ])] (AU, AU / d)>