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 |Unit| 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)>