单位和数量 (astropy.units#

介绍#

astropy.units 处理用物理量(如米、秒、赫兹等)定义、转换和执行算术运算。它还处理对数单位,如幅值和分贝。

astropy.units 不知道球面几何或六边形(小时,分,秒):如果你想处理天体坐标,请参阅 astropy.coordinates 包裹。

入门#

的大多数用户 astropy.units 程序包将与 Quantity objects :值和单位的组合。创建 Quantity 将一个值乘以或除以一个内置单位。它适用于标量、序列和 numpy 数组。

实例#

创建一个 Quantity 对象:

>>> from astropy import units as u
>>> 42.0 * u.meter  
<Quantity  42. m>
>>> [1., 2., 3.] * u.m  
<Quantity [1., 2., 3.] m>
>>> import numpy as np
>>> np.array([1., 2., 3.]) * u.m  
<Quantity [1., 2., 3.] m>

您可以从 Quantity 使用单位和值成员:

>>> q = 42.0 * u.meter
>>> q.value
42.0
>>> q.unit
Unit("m")

从这个基本构建块开始,可以开始将不同单位的数量组合起来:

>>> 15.1 * u.meter / (32.0 * u.second)  
<Quantity 0.471875 m / s>
>>> 3.0 * u.kilometer / (130.51 * u.meter / u.second)  
<Quantity 0.022986744310780783 km s / m>
>>> (3.0 * u.kilometer / (130.51 * u.meter / u.second)).decompose()  
<Quantity 22.986744310780782 s>

单位转换是使用 to() 方法,它返回一个新的 Quantity 以给定的单位:

>>> x = 1.0 * u.parsec
>>> x.to(u.km)  
<Quantity 30856775814671.914 km>

也可以直接使用较低级别的单位,例如,创建自定义单位:

>>> from astropy.units import imperial

>>> cms = u.cm / u.s
>>> # ...and then use some imperial units
>>> mph = imperial.mile / u.hour

>>> # And do some conversions
>>> q = 42.0 * cms
>>> q.to(mph)  
<Quantity 0.939513242662849 mi / h>

“抵消”的单位成为称为“无量纲单位”的特殊单位:

>>> u.m / u.m
Unit(dimensionless)

创建基本 dimensionless quantity ,将值乘以未标度的无量纲单位:

>>> q = 1.0 * u.dimensionless_unscaled
>>> q.unit
Unit(dimensionless)

astropy.units 能够将复合单位与已知单位进行匹配:

>>> (u.s ** -1).compose()  
[Unit("Bq"), Unit("Hz"), Unit("2.7027e-11 Ci")]

它还可以在单位系统之间进行转换,例如 SICGS **

>>> (1.0 * u.Pa).cgs
<Quantity 10. P / s>

单位 magdexdB 是特别的,是 logarithmic units ,其中值是给定单位的物理量的对数。这些可以与括号中的物理单位一起使用,以创建相应的对数量:

>>> -2.5 * u.mag(u.ct / u.s)
<Magnitude -2.5 mag(ct / s)>
>>> from astropy import constants as c
>>> u.Dex((c.G * u.M_sun / u.R_sun**2).cgs)  
<Dex 4.438067627303133 dex(cm / s2)>

astropy.units 也可以处理 equivalencies 比如波长和频率之间的关系。为了使用该特性,等价对象被传递给 to() 转换方法。例如,从波长到频率的转换通常不起作用:

>>> (1000 * u.nm).to(u.Hz)  
Traceback (most recent call last):
  ...
UnitConversionError: 'nm' (length) and 'Hz' (frequency) are not convertible

而是通过传递等价列表,在本例中 spectral() ,它确实:

>>> (1000 * u.nm).to(u.Hz, equivalencies=u.spectral())  
<Quantity  2.99792458e+14 Hz>

数量和单位可以是 printed nicely to strings 使用 Format String Syntax . 格式说明符(如 0.03f )将使用字符串格式设置数量值:

>>> q = 15.1 * u.meter / (32.0 * u.second)
>>> q  
<Quantity 0.471875 m / s>
>>> f"{q:0.03f}"
'0.472 m / s'

值和单位也可以单独格式化。单位的格式说明符可用于选择单位格式化程序:

>>> q = 15.1 * u.meter / (32.0 * u.second)
>>> q  
<Quantity 0.471875 m / s>
>>> f"{q.value:0.03f} {q.unit:FITS}"
'0.472 m s-1'

使用 astropy.units#

致谢#

此代码最初基于 pynbody units模块由andrewpontzen编写,他已经授予Astropy项目使用BSD许可证下的代码的权限。

也见#

性能提示#

如果你要将单位附加到数组 Quantity 数组中的对象被复制的速度会减慢。此外,如果将一个数组乘以一个复合单位,则每次乘法都会复制该数组。因此,在以下情况下,将连续复制数组四次:

In [1]: import numpy as np

In [2]: from astropy import units as u

In [3]: rng = np.random.default_rng()

In [4]: array = rng.random(10000000)

In [5]: %timeit array * u.m / u.s / u.kg / u.sr
92.5 ms ± 2.52 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

有几种方法可以加快速度。首先,在使用复合单元时,请确保先对整个单元求值,然后将其附加到数组。您可以使用圆括号来执行此操作,就像对任何其他操作一样:

In [6]: %timeit array * (u.m / u.s / u.kg / u.sr)
21.5 ms ± 886 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

在本例中,这将速度提高了4倍。如果您在代码中多次使用复合单元,则可以为其定义一个变量:

In [7]: UNIT_MSKGSR = u.m / u.s / u.kg / u.sr

In [8]: %timeit array * UNIT_MSKGSR
22.2 ms ± 551 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

在本例中以及带括号的情况下,在创建 Quantity . 如果您想完全避免复制,可以使用 << 操作员将设备连接到阵列:

In [9]: %timeit array << u.m / u.s / u.kg / u.sr
47.1 µs ± 5.77 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

请注意,这些现在 微秒 ,所以这是2000倍的速度比原来的案件没有括号。请注意,使用时不需要括号 << since * and / have a higher precedence, so the unit will be evaluated first. When using `` <<```,请注意,由于未复制数据,更改原始数组也会更改 Quantity 对象。

请注意,对于复合单元,如果可以预先计算组合单元,您肯定会看到影响:

In [10]: %timeit array << UNIT_MSKGSR
6.51 µs ± 112 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

比原来的例子快了1000倍。看到了吗 创建和转换无副本的数量 有关 << 操作员。

参考/API#