File: format.rst

package info (click to toggle)
astropy 7.0.1-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 35,328 kB
  • sloc: python: 233,437; ansic: 55,264; javascript: 17,680; lex: 8,621; sh: 3,317; xml: 2,287; makefile: 191
file content (372 lines) | stat: -rw-r--r-- 14,416 bytes parent folder | download
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
.. _astropy-units-format:

String Representations of Units and Quantities
**********************************************

Converting to Strings
=====================

You can control the way that |Quantity| and |Unit| objects are rendered as
strings using the `Python Format String Syntax
<https://docs.python.org/3/library/string.html#format-string-syntax>`_
(demonstrated below using `f-strings
<https://www.python.org/dev/peps/pep-0498/>`_).

For a |Quantity|, format specifiers that are names of `Built-In Formats`_ are
applied to the |Quantity| unit, and if possible also to the value. Format
specifiers for numerical values, like ``.3f``, will be applied to the
|Quantity| value, without affecting the unit. Finally, specifiers like
``^20s``, which would apply to a string, will be applied to the string
representation of the |Quantity| as a whole. Format specifiers that apply to
the unit part of a |Quantity| are also applicable to a |Unit| instance.

Examples
--------

.. EXAMPLE START: Converting Units to String Representations

To render |Quantity| or |Unit| objects as strings::

    >>> from astropy import units as u
    >>> q = 10.5 * u.km
    >>> q
    <Quantity  10.5 km>
    >>> f"{q}"
    '10.5 km'
    >>> f"{q:latex}"
    '$10.5 \\; \\mathrm{km}$'
    >>> f"{q:+.3f}"
    '+10.500 km'
    >>> f"{q:^20}"
    '        10.5         km'
    >>> f"{q:^20s}"
    '     10.5 km        '

To format both the value and the unit separately, you can access the |Quantity|
attributes within format strings::

    >>> q = 10.5 * u.km
    >>> q
    <Quantity  10.5 km>
    >>> f"{q.value:.3f} in {q.unit}"
    '10.500 in km'

This might not work well with LaTeX strings, in which case it would be better
to use the `Quantity.to_string() <astropy.units.Quantity.to_string()>` method.
Just like how `table.Column() <astropy.table.Column()>` takes a format specifier
or callable for formatting, you can also optionally specify a format via the
``formatter`` parameter with either type or additionally with a dictionary, the
added benefit being a more flexible or tighter LaTeX output. It relies on
:func:`numpy.array2string()` for directly handling the ``formatter``, which will
effectively override the default LaTeX formatting for the scientific and complex
notations provided by `Quantity.to_string() <astropy.units.Quantity.to_string()>`
unless the ``formatter`` is simply just a format specifier string or `None`
(by default)::

    >>> q = 1.2478e12 * u.pc/u.Myr
    >>> f"{q:latex}"  # Might not have the number of digits we would like
    '$1.2478 \\times 10^{12} \\; \\mathrm{\\frac{pc}{Myr}}$'
    >>> f"{q.value:.3e} {q.unit:latex}"  # The value is not in LaTeX
    '1.248e+12 $\\mathrm{\\frac{pc}{Myr}}$'
    >>> q.to_string(format="latex", precision=4)  # Right number of LaTeX digits
    '$1.248 \\times 10^{12} \\; \\mathrm{\\frac{pc}{Myr}}$'
    >>> q.to_string(format="latex", formatter=".2e")  # Specifying format_spec
    '$1.25 \\times 10^{12} \\; \\mathrm{\\frac{pc}{Myr}}$'
    >>> q.to_string(format="latex", formatter=lambda x: f"\\approx {float(x):.2e}")  # Custom formatting (overwrites)
    '$\\approx 1.25e+12 \\; \\mathrm{\\frac{pc}{Myr}}$'

Because |ndarray| does not accept most format specifiers, using specifiers like
``.3f`` will not work when applied to a |ndarray| or non-scalar |Quantity|. Use
:func:`numpy.array_str` instead. For instance::

    >>> import numpy as np
    >>> q = np.linspace(0,1,10) * u.m
    >>> f"{np.array_str(q.value, precision=1)} {q.unit}"  # doctest: +FLOAT_CMP
    '[0.  0.1 0.2 0.3 0.4 0.6 0.7 0.8 0.9 1. ] m'

Examine the NumPy documentation for more examples with :func:`numpy.array_str`.

.. EXAMPLE END

A |Unit|, or the unit part of a |Quantity|, can also be formatted in a number
of different styles. By default, the string format used is the "generic"
format, which is based on syntax of the `FITS standard
<https://fits.gsfc.nasa.gov/fits_standard.html>`_ format for representing
units, but supports all of the units defined within the :mod:`astropy.units`
framework, including user-defined units. The format specifier (and
`UnitBase.to_string() <astropy.units.core.UnitBase.to_string>`) functions also
take an optional parameter to select a different format::

    >>> q = 10 * u.km
    >>> f"{q:latex}"
    '$10 \\; \\mathrm{km}$'
    >>> fluxunit = u.erg / (u.cm ** 2 * u.s)
    >>> f"{fluxunit}"
    'erg / (s cm2)'
    >>> print(f"{fluxunit:unicode}")
    erg s⁻¹ cm⁻²
    >>> f"{fluxunit:latex}"
    '$\\mathrm{\\frac{erg}{s\\,cm^{2}}}$'
    >>> f"{fluxunit:>20s}"
    '       erg / (s cm2)'

The `UnitBase.to_string() <astropy.units.core.UnitBase.to_string>` method is an
alternative way to format units as strings, and is the underlying
implementation of the `format`-style usage::

    >>> fluxunit = u.erg / (u.cm ** 2 * u.s)
    >>> fluxunit.to_string('latex')
    '$\\mathrm{\\frac{erg}{s\\,cm^{2}}}$'

Converting from Strings
=======================

.. EXAMPLE START: Creating Units from Strings

Units can also be created from strings in a number of different
formats using the `~astropy.units.Unit` class::

  >>> u.Unit("m")
  Unit("m")
  >>> u.Unit("erg / (s cm2)")
  Unit("erg / (s cm2)")
  >>> u.Unit("erg.s-1.cm-2", format="cds")
  Unit("erg / (s cm2)")

It is also possible to create a scalar |Quantity| from a string::

    >>> u.Quantity("3m/s")
    <Quantity 3. m / s>

.. note::

   Converting from strings requires the use of a specialized parser for the
   unit language, which results in a performance penalty. It is much faster to
   use |Unit| objects directly (e.g., ``unit = u.degree / u.minute``) instead
   of via string parsing (``unit = u.Unit('deg/min')``). This parser is very
   useful, however, if your unit definitions are coming from a file format such
   as FITS or VOTable.

.. EXAMPLE END

Built-In Formats
================

`astropy.units` includes support for parsing and writing the following
formats:

  - ``"fits"``: This is the format defined in the Units section of the
    `FITS Standard <https://fits.gsfc.nasa.gov/fits_standard.html>`__.
    Unlike the "generic" string format, this will only accept or
    generate units defined in the FITS standard.

  - ``"vounit"``: The `Units in the VO 1.0
    <http://www.ivoa.net/documents/VOUnits/>`__ standard for
    representing units in the VO. Again, based on the FITS syntax,
    but the collection of supported units is different.

  - ``"cds"``: `Standards for astronomical catalogues from Centre de
    Données astronomiques de Strasbourg
    <https://vizier.unistra.fr/vizier/doc/catstd-3.2.htx>`_: This is the
    standard used by `Vizier tables <https://vizier.unistra.fr/>`__,
    as well as what is used by VOTable versions 1.3 and earlier.

  - ``"ogip"``: A standard for storing units as recommended by the
    `Office of Guest Investigator Programs (OGIP)
    <https://heasarc.gsfc.nasa.gov/docs/heasarc/ofwg/docs/general/ogip_93_001/>`_.

`astropy.units` is also able to write, but not read, units in the
following formats:

  - ``"latex"``: Writes units out using LaTeX math syntax using the
    `IAU Style Manual
    <https://www.iau.org/static/publications/stylemanual1989.pdf>`_
    recommendations for unit presentation. This format is
    automatically used when printing a unit in the |IPython| notebook::

        >>> f"{fluxunit:latex}"
        '$\\mathrm{\\frac{erg}{s\\,cm^{2}}}$'

    which renders as

    .. math::

       \mathrm{\frac{erg}{s\,cm^{2}}}

  - ``"latex_inline"``: Writes units out using LaTeX math syntax using the
    `IAU Style Manual
    <https://www.iau.org/static/publications/stylemanual1989.pdf>`_
    recommendations for unit presentation, using negative powers instead of
    fractions, as required by some journals (e.g., `Apj and AJ
    <https://journals.aas.org/manuscript-preparation/>`_).
    Best suited for unit representation inline with text::

        >>> fluxunit.to_string('latex_inline')
        '$\\mathrm{erg\\,s^{-1}\\,cm^{-2}}$'

    which renders as

    .. math::

       \mathrm{erg\,s^{-1}\,cm^{-2}}

  - ``"console"``: Writes a representation of the unit useful for
    display in a text console::

      >>> print(fluxunit.to_string('console'))
       erg s^-1 cm^-2

    It is also possible to use a fraction, either on a single line,

      >>> print(fluxunit.to_string('console', fraction='inline'))
      erg / (s cm^2)

    or using a multiline representation:

      >>> print(fluxunit.to_string('console', fraction='multiline'))
       erg
      ------
      s cm^2

  - ``"unicode"``: Same as ``"console"``, except uses Unicode
    characters::

      >>> print(u.Ry.decompose().to_string('unicode'))  # doctest: +FLOAT_CMP
      2.1798724×10⁻¹⁸ m² kg s⁻²
      >>> print(u.Ry.decompose().to_string('unicode', fraction=True))  # doctest: +FLOAT_CMP
      2.1798724×10⁻¹⁸ m² kg / s²
      >>> print(u.Ry.decompose().to_string('unicode', fraction='multiline'))  # doctest: +FLOAT_CMP
                      m² kg
      2.1798724×10⁻¹⁸ ─────

.. _astropy-units-format-unrecognized:

Dealing with Unrecognized Units
===============================

Since many files found in the wild have unit strings that do not correspond to
any given standard, :mod:`astropy.units` contains functionality for both
validating the strings, and for reading in datasets that contain invalid unit
strings.

By default, passing an unrecognized unit string raises an exception::

  >>> # The FITS standard uses 'angstrom', not 'Angstroem'
  >>> u.Unit("Angstroem", format="fits")
  Traceback (most recent call last):
    ...
  ValueError: 'Angstroem' did not parse as fits unit: At col 0, Unit
  'Angstroem' not supported by the FITS standard. Did you mean Angstrom
  or angstrom? If this is meant to be a custom unit, define it with
  'u.def_unit'. To have it recognized inside a file reader or other
  code, enable it with 'u.add_enabled_units'. For details, see
  https://docs.astropy.org/en/latest/units/combining_and_defining.html

However, the :class:`~astropy.units.Unit` constructor obeys the keyword
argument ``parse_strict`` that can take one of three values to control
this behavior:

  - ``'raise'``: (default) raise a :class:`ValueError`.

  - ``'warn'``: emit a :class:`~astropy.units.UnitParserWarning`, and return a
    unit.

  - ``'silent'``: return a unit without raising errors or emitting warnings.

The type of unit returned when ``parse_strict`` is ``'warn'`` or ``'silent'``
depends on how serious the standard violation is.
In case of a minor standard violation, :class:`~astropy.units.Unit` can
sometimes nonetheless parse the unit.
The warning message (if ``parse_strict='warn'``) will then contain information
about how the invalid string was interpreted.
In case of more serious standard violations an
:class:`~astropy.units.UnrecognizedUnit` instance is returned instead.
In such cases, particularly in case of misspelt units, it might be helpful to
register additional unit aliases with
:func:`~astropy.units.set_enabled_aliases` (e.g., 'Angstroms' for 'Angstrom';
as demonstrated below), or to define new units via
:func:`~astropy.units.def_unit` and :func:`~astropy.units.add_enabled_units`,


Examples
--------

.. EXAMPLE START: Define Aliases for Units

To set unit aliases, pass :func:`~astropy.units.set_enabled_aliases` a
:class:`dict` mapping the misspelt string to an astropy unit. The following
code snippet shows how to set up Angstroem -> Angstrom::

    >>> u.set_enabled_aliases({"Angstroem": u.Angstrom})
    <astropy.units.core._UnitContext object at 0x...>
    >>> u.Unit("Angstroem")
    Unit("Angstrom")
    >>> u.Unit("Angstroem") == u.Angstrom
    True

You can also set multiple aliases up at once or add to existing ones::

    >>> u.set_enabled_aliases({"Angstroem": u.Angstrom, "Angstroms": u.Angstrom})
    <astropy.units.core._UnitContext object at 0x...>
    >>> u.add_enabled_aliases({"angstroem": u.Angstrom})
    <astropy.units.core._UnitContext object at 0x...>
    >>> u.Unit("Angstroem") == u.Unit("Angstroms") == u.Unit("angstroem") == u.Angstrom
    True

The aliases can be reset by passing an empty dictionary::

    >>> u.set_enabled_aliases({})
    <astropy.units.core._UnitContext object at 0x...>

You can use both :func:`~astropy.units.set_enabled_aliases` and
:func:`~astropy.units.add_enabled_aliases` as a `context manager
<https://docs.python.org/3/reference/datamodel.html#context-managers>`_,
limiting where a particular alias is used::

    >>> with u.add_enabled_aliases({"Angstroem": u.Angstrom}):
    ...     print(u.Unit("Angstroem") == u.Angstrom)
    True
    >>> u.Unit("Angstroem") == u.Angstrom
    Traceback (most recent call last):
      ...
    ValueError: 'Angstroem' did not parse as unit: At col 0, Angstroem is not
    a valid unit. Did you mean Angstrom, angstrom, mAngstrom or mangstrom? If
    this is meant to be a custom unit, define it with 'u.def_unit'. To have it
    recognized inside a file reader or other code, enable it with
    'u.add_enabled_units'. For details, see
    https://docs.astropy.org/en/latest/units/combining_and_defining.html

.. EXAMPLE END

.. EXAMPLE START: Using `~astropy.units.UnrecognizedUnit`

To pass an unrecognized unit string::

   >>> x = u.Unit("Angstroem", format="fits", parse_strict="warn")  # doctest: +SHOW_WARNINGS
   UnitsWarning: 'Angstroem' did not parse as fits unit: At col 0, Unit
   'Angstroem' not supported by the FITS standard. Did you mean Angstrom or
   angstrom? If this is meant to be a custom unit, define it with 'u.def_unit'.
   To have it recognized inside a file reader or other code, enable it with
   'u.add_enabled_units'. For details, see
   https://docs.astropy.org/en/latest/units/combining_and_defining.html

This `~astropy.units.UnrecognizedUnit` object remembers the
original string it was created with, so it can be written back out,
but any meaningful operations on it, such as converting to another
unit or composing with other units, will fail.

   >>> x.to_string()
   'Angstroem'
   >>> x.to(u.km)
   Traceback (most recent call last):
     ...
   ValueError: The unit 'Angstroem' is unrecognized.  It can not be
   converted to other units.
   >>> x / u.m
   Traceback (most recent call last):
     ...
   ValueError: The unit 'Angstroem' is unrecognized, so all arithmetic
   operations with it are invalid.

.. EXAMPLE END