File: structured_units.rst

package info (click to toggle)
astropy 7.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 34,156 kB
  • sloc: python: 240,839; ansic: 55,852; lex: 8,621; sh: 3,318; xml: 2,399; makefile: 149
file content (132 lines) | stat: -rw-r--r-- 5,292 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
.. _structured_units:

Structured Units
****************

Numpy arrays can be :doc:`structured arrays <numpy:user/basics.rec>`, 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 `~astropy.units.Unit`.

Example
-------

.. EXAMPLE START: Creating Structured Quantities

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
`~astropy.units.Quantity.value` and `~astropy.units.Quantity.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 :func:`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  # doctest: +FLOAT_CMP
  <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))>

.. EXAMPLE END

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

.. EXAMPLE START: Converting Structured Quantities to Different Units

To convert a structured quantity to a different unit::

  >>> pv.to((u.m, u.m / u.s))  # doctest: +FLOAT_CMP
  <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)>

.. EXAMPLE END

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

.. EXAMPLE START: Using Structured Quantities with ERFA

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)  # doctest: +FLOAT_CMP
  (<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)>

.. EXAMPLE END