SEP | 3 |
---|---|
title | Physical Units in SunPy |
author(s) | Steven Christe |
contact email | [email protected] |
date-creation | 2014-04-22 |
type | standard |
discussion | #7 |
status | accepted |
Using quantities with units is a great idea because it less likely that mistakes will be made and units can be easily converted as needed. This SEP defines how physical quantities should be dealt with in SunPy.
All user-facing function/object arguments which accept physical quantities as input MUST accept astropy quantities. The same standards should be followed for functions whose output is a physical quantity, they should output an astropy quantity. For the sake of consistency, functions/objects should strive to not convert the units given by the user meaning that if a users hands a length in meters than the output should also use meters regardless of how complex the resulting quantity might be (e.g. flux).
Use of astropy quantities throughout code is also expected. In cases where performance may be significantly impacted by the use of quantities, private (i.e. non-user-facing) wrapper functions may be used which accept physical quantities in the form of pure numbers. However in these cases, variable name used for both input and output should strive to carry the name of the unit (e.g. x_arcsec, length_meters, photons_flux) and the excepted input and output units must be declared in the doc string.
def get_area_of_square(side_length):
"""Compute the area of a square.
Parameters
----------
side_length : `~astropy.units.quantity.Quantity`
Side length of the square
Returns
-------
area : `~astropy.units.quantity.Quantity`
Area of the square.
"""
if not isinstance(a, Quantity):
raise TypeError("Expecting Quantity")
return (side_length ** 2)
In this example, a function (other_function
) is needed in some_function
which does not play
well with quantities. In this case, a private function (_private_wrapper_function
) is defined (see below) to wrap other_function
. The quantity is converted to a dimensional number with a known unit and passed to the _private_wrapper_function
. Afterwards the result (whose units should be known) is then converted back to a quantity to be returned by some_function
.
def some_function(length):
"""Does something useful.
Parameters
----------
length : `~astropy.units.quantity.Quantity`
A length.
Returns
-------
length : `~astropy.units.quantity.Quantity`
Another length
"""
if not isinstance(a, Quantity):
raise TypeError("Expecting Quantity")
# the following function either
# a] does not accept Quantities
# b] is slow if using Quantities
result_meters = _private_wrapper_function(length.convert('meters').value)
# now convert back to a quantity
result = Quantity(result_meters, 'meters')
return result
In the following example, the function is itself not quantity-friendly either because it is expected to deal with millions of quantities or for some other appropriate reason.
def _private_wrapper_function(length_meters):
"""Does something else useful.
Parameters
----------
many_lengths_meters : `numpy.ndarray`
Lengths in ``m``.
Returns
-------
other_length_meters : `numpy.ndarray`
Lengths in ``m``
"""
# do something with length_meters
result = other_function(length_meters)
return result_meters
- Astropy Quantities documentation
- Discussion of usage of quantities on Astropy mailing list
- An example of docs of a function using Quantities
This SEP was accepted unanimously by the SunPy board on 9-Jun-2014 because everyone knows that units are important except for computer code...until now!