数量

这个 Quantity 对象表示一个值,该值具有与该数字相关的单位。

创建数量实例

Quantity 对象通常是通过与相乘来创建的 Unit 物体。

实例

创建一个 Quantity 代表15 m/s:

>>> import astropy.units as u
>>> 15 * u.m / u.s  
<Quantity 15. m / s>

这可以按单位进行除法,或者使用 numpy 数组或Python序列:

>>> 1.25 / u.s
<Quantity 1.25 1 / s>
>>> [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 构造函数,通过指定值和单位:

>>> u.Quantity(15, u.m / u.s)  
<Quantity 15. m / s>

构造函数提供了更多的选项。特别是,它允许您合并 Quantity 对象(只要它们的所有单元都是等效的),以及解析简单字符串(这可能有助于,例如,解析配置文件等):

>>> qlst = [60 * u.s, 1 * u.min]
>>> u.Quantity(qlst, u.minute)  
<Quantity [1.,  1.] min>
>>> u.Quantity('15 m/s')  
<Quantity 15. m / s>

可以通过访问当前单位和值 unitvalue 属性:

>>> q = 2.5 * u.m / u.s
>>> q.unit
Unit("m / s")
>>> q.value
2.5

备注

Quantity 默认情况下,对象将转换为浮点。此外,传入的任何数据都会被复制,这对于大型数组来说可能不是最佳的。如前所述 further below ,您可以改为获得 view 旁路 copy=FalseQuantity 或者使用 << 操作员。

转换为不同单位

Quantity 对象可以使用 to() 方法。

实例

转换 Quantity 不同单位的对象:

>>> q = 2.3 * u.m / u.s
>>> q.to(u.km / u.h)  
<Quantity 8.28 km / h>

为了方便起见, sicgs 属性可用于转换 Quantity 对于SI或CGS单位:

>>> q = 2.4 * u.m / u.s
>>> q.si  
<Quantity 2.4 m / s>
>>> q.cgs  
<Quantity 240. cm / s>

如果您想在不同的单位中显示数量的值,可以使用 to_value() 作为快捷方式:

>>> q = 2.5 * u.m
>>> q.to_value(u.cm)
250.0

备注

你可以得到价值 cm 同时使用 q.to(u.cm).value . 区别在于 to_value() 如果单位已经是正确的,则不进行转换,而是返回 view() 数据(就像你做的一样 q.value ). 相反, to() 总是返回一个副本(这也意味着在不需要转换的情况下,它会比较慢)。如前所述 further below ,如果单位已经正确,则可以使用 << 操作员。

比较数量

Quantity 对象可以进行如下比较:

>>> from astropy import units as u
>>> u.allclose([1, 2] * u.m, [100, 200] * u.cm)
True
>>> u.isclose([1, 2] * u.m, [100, 20] * u.cm)  
array([ True, False])

绘制数量

Quantity 使用matplotlib可以方便地绘制对象-请参见 绘制数量 了解更多详细信息。

算术

加减法

加减法 Quantity 如果对象的单位相等,则支持这些对象。

实例

当单位相等时,生成的对象具有相同的单位:

>>> 11 * u.s + 30 * u.s  
<Quantity 41. s>
>>> 30 * u.s - 11 * u.s  
<Quantity 19. s>

如果单位相等,但不相等(例如公里和米),则结果对象 在左边有对象的单位

>>> 1100.1 * u.m + 13.5 * u.km
<Quantity 14600.1 m>
>>> 13.5 * u.km + 1100.1 * u.m  
<Quantity 14.6001 km>
>>> 1100.1 * u.m - 13.5 * u.km
<Quantity -12399.9 m>
>>> 13.5 * u.km - 1100.1 * u.m  
<Quantity 12.3999 km>

之间不支持加法和减法 Quantity 对象和基本数字类型:

>>> 13.5 * u.km + 19.412  
Traceback (most recent call last):
  ...
UnitConversionError: Can only apply 'add' function to dimensionless
quantities when other argument is not a quantity (unless the
latter is all zero/infinity/nan)

无量纲数量除外(参见 Dimensionless Quantities

乘除

支持乘法和除法 Quantity 具有任意单位和数字类型的对象。对于具有等效单位的对象之间的这些操作 结果对象具有复合单位 .

实例

执行这些操作 Quantity 物体:

>>> 1.1 * u.m * 140.3 * u.cm  
<Quantity 154.33 cm m>
>>> 140.3 * u.cm * 1.1 * u.m  
<Quantity 154.33 cm m>
>>> 1. * u.m / (20. * u.cm)  
<Quantity 0.05 m / cm>
>>> 20. * u.cm / (1. * u.m)  
<Quantity 20. cm / m>

对于乘法,可以通过使用 to() 方法:

>>> (1.1 * u.m * 140.3 * u.cm).to(u.m**2)  
<Quantity 1.5433 m2>
>>> (1.1 * u.m * 140.3 * u.cm).to(u.cm**2)  
<Quantity 15433. cm2>

对于分割,如果单位相等,则可能需要通过减少单位使生成的对象无量纲。为此,请使用 decompose() 方法:

>>> (20. * u.cm / (1. * u.m)).decompose()  
<Quantity 0.2>

此方法也适用于更复杂的运算:

>>> 15. * u.kg * 32. * u.cm * 15 * u.m / (11. * u.s * 1914.15 * u.ms)  
<Quantity 0.34195097 cm kg m / (ms s)>
>>> (15. * u.kg * 32. * u.cm * 15 * u.m / (11. * u.s * 1914.15 * u.ms)).decompose()  
<Quantity 3.41950973 kg m2 / s2>

NumPy函数

Quantity 对象实际上已满 numpy 数组(的 Quantity 类继承自并扩展 numpy.ndarray )我们努力确保 numpy 函数的行为与量有关:

>>> q = np.array([1., 2., 3., 4.]) * u.m / u.s
>>> np.mean(q)
<Quantity 2.5 m / s>
>>> np.std(q)  
<Quantity 1.11803399 m / s>

这包括只接受特定单位的函数,例如角度:

>>> q = 30. * u.deg
>>> np.sin(q)  
<Quantity 0.5>

或无量纲量:

>>> from astropy.constants import h, k_B
>>> nu = 3 * u.GHz
>>> T = 30 * u.K
>>> np.exp(-h * nu / (k_B * T))  
<Quantity 0.99521225>

Dimensionless Quantities 详情请参见下文。

备注

numpy 版本早于1.17,许多非算术函数都有 known issues ,或者忽略单元(例如。, np.dot )或者没有正确初始化(例如。, np.hstack ). 这会传播到更复杂的函数,例如 np.linalg.norm .

支持其他包中的函数,例如 scipy ,是更不完整的(欢迎对此进行改进的贡献!)。

无量纲量

无量纲量的特点是,如果它们是从Python标量或无量纲中加或减的 ndarray ,或者如果它们传递给 numpy 函数采用无量纲量,单位被简化,使量无量纲和无标度。例如:

>>> 1. + 1. * u.m / u.km  
<Quantity 1.001>

不同于:

>>> 1. + (1. * u.m / u.km).value
2.0

在后一种情况下,结果是 2.0 因为 (1. * u.m / u.km) 默认情况下不可缩放:

>>> q = (1. * u.m / u.km)
>>> q.unit
Unit("m / km")
>>> q.unit.decompose()
Unit(dimensionless with a scale of 0.001)

但是,当与不是 Quantity ,将单元自动分解为无标度,得到了预期的结果。

当将无量纲量传递给采用无量纲量的函数时,也会发生这种情况:

>>> nu = 3 * u.GHz
>>> T = 30 * u.K
>>> np.exp(- h * nu / (k_B * T))  
<Quantity 0.99521225>

结果与指定不同数量的单位无关:

>>> nu = 3.e9 * u.Hz
>>> T = 30 * u.K
>>> np.exp(- h * nu / (k_B * T))  
<Quantity 0.99521225>

转换为纯Python标量

转换 Quantity 对象不适用于无量纲数量:

>>> float(3. * u.m)
Traceback (most recent call last):
  ...
TypeError: only dimensionless scalar quantities can be converted
to Python scalars

相反,只有无量纲值可以转换为纯Python标量:

>>> float(3. * u.m / (4. * u.m))
0.75
>>> float(3. * u.km / (4. * u.m))
750.0
>>> int(6. * u.km / (2. * u.m))
3000

接受数量的函数

对函数的数量参数进行验证会导致同一检查代码多次重复。提供了一个修饰符,用于验证函数的某些参数是否 Quantity 对象,并且这些单位与所需的单位或物理类型兼容。

decorator不会将输入量转换为所需的单位,例如在下面的示例中,它只是检查这种转换是否可行,从而验证 Quantity 参数可用于计算。

装饰工 quantity_input 接受关键字参数,以指定应验证哪些参数以及它们与哪个单元兼容。

实例

验证 Quantity 参数可用于计算:

>>> @u.quantity_input(myarg=u.deg)
... def myfunction(myarg):
...     return myarg.unit
>>> myfunction(100*u.arcsec)
Unit("arcsec")

也可以指定所需单元的物理类型:

>>> @u.quantity_input(myarg='angle')
... def myfunction(myarg):
...     return myarg.unit
>>> myfunction(100*u.arcsec)
Unit("arcsec")

或者, None 还支持关键字参数;对于这种情况,只有当值不是 None 通过:

>>> @u.quantity_input(a='length', b='angle')
... def myfunction(a, b=None):
...     return a, b
>>> myfunction(1.*u.km)  
(<Quantity 1. km>, None)
>>> myfunction(1.*u.km, 1*u.deg)  
(<Quantity 1. km>, <Quantity 1. deg>)

或者,可以使用注释语法提供单位:

>>> @u.quantity_input  
... def myfunction(myarg: u.arcsec):
...     return myarg.unit
>>> myfunction(100*u.arcsec)  
Unit("arcsec")

您还可以为非单元期望参数中的不同类型添加注释:

>>> @u.quantity_input  
... def myfunction(myarg: u.arcsec, nice_string: str):
...     return myarg.unit, nice_string
>>> myfunction(100*u.arcsec, "a nice string")  
(Unit("arcsec"), 'a nice string')

可以定义返回装饰,返回值将转换为该装饰,例如:

>>> @u.quantity_input  
... def myfunction(myarg: u.arcsec) -> u.deg:
...     return myarg*1000

>>> myfunction(100*u.arcsec)  
<Quantity 27.77777778 deg>

这将检查函数的返回值是否与期望值一致,并使函数结果的显示更简洁。

decorator还支持为应接受多个有效单元的输入的函数指定有效等效单元或物理类型的列表:

>>> @u.quantity_input(a=['length', 'speed'])
... def myfunction(a):
...     return a.unit
>>> myfunction(1.*u.km)
Unit("km")
>>> myfunction(1.*u.km/u.s)
Unit("km / s")

用单位表示向量

Quantity 对象可以,比如 numpy 数组,通过指定特定的维数来表示坐标或矩阵元素来表示向量或矩阵,但这意味着要仔细跟踪这些维度。对于向量,可以使用坐标基础的表示法,这样可以使用笛卡尔坐标以外的表示法(如球面或柱面),也可以使用简单的矢量算法。有关详细信息,请参阅 使用和设计坐标表示法 .

创建和转换无副本的数量

创建一个 Quantity 使用与单位相乘的方法,生成底层数据的副本。这可以通过传递来避免 copy=False 在初始值设定项中。

实例

避免重复使用 copy=False ::

>>> a = np.arange(5.)
>>> q = u.Quantity(a, u.m, copy=False)
>>> q  
<Quantity [0., 1., 2., 3., 4.] m>
>>> np.may_share_memory(a, q)
True
>>> a[0] = -1.
>>> q  
<Quantity [-1.,  1.,  2.,  3.,  4.] m>

这在不更改输入的函数中尤其有用;它还可以确保如果用户传入 Quantity 以长度为单位,将转换为米。

作为快捷方式,您可以使用 << 操作员:

>>> q = a << u.m
>>> np.may_share_memory(a, q)
True
>>> q  
<Quantity [-1.,  1.,  2.,  3.,  4.] m>

运算符的工作方式与初始化相同 copy=False 如上所述:

>>> q << u.cm  
<Quantity [-100.,  100.,  200.,  300.,  400.] cm>

也可用于就地转换:

>>> q <<= u.cm
>>> q  
<Quantity [-100.,  100.,  200.,  300.,  400.] cm>
>>> a  
array([-100.,  100.,  200.,  300.,  400.])

子类量

子类 Quantity ,通常会像子类化时那样继续 ndarray (即,您通常需要覆盖 __new__ 而不是 __init__ ,并使用 numpy.ndarray.__array_finalize__ 方法更新属性)。有关详细信息,请参见 NumPy documentation on subclassing . 要想了解其中的含义,请看一看 Quantity 它本身,例如 astropy.units.Quantity.__array_finalize__ 方法传递 unit ,在 Angle ,其中字符串在 astropy.coordinates.Angle.__new__ 方法和at Longitude 那里 astropy.coordinates.Longitude.__array_finalize__ 方法用于传递经度缠绕的角度。

另一个要被子类重写的方法,特定于 Quantityastropy.units.Quantity.__quantity_subclass__ . 调用此函数是为了根据 Quantity 那将被创造出来。例如,它用于 Angle 归还 Quantity 如果计算返回的单位不是角度单位。这是通过 SpecificTypeQuantity ,这通常允许用户构造 Quantity 子类的方法只对特定的物理类型有用。