单位和数量支持#
备注
这里介绍的功能是最近添加的。如果您遇到任何问题,请不要犹豫在 issue tracker .
这个 astropy.modeling
该软件包包括对模型参数、模型和拟合期间使用单位和数量的部分支持。在这个时候,只有一些内置的模型(如 Gaussian1D
)支持单位,但这将在将来扩展到所有适当的型号。
将参数设置为数量#
模型可以 Quantity
对象作为参数:
>>> from astropy import units as u
>>> from astropy.modeling.models import Gaussian1D
>>> g1 = Gaussian1D(mean=3 * u.m, stddev=2 * u.cm, amplitude=3 * u.Jy)
然后访问该参数将返回一个包含值和单位的参数对象:
>>> g1.mean
Parameter('mean', value=3.0, unit=m)
然后可以访问参数的各个属性:
>>> g1.mean.name
'mean'
>>> g1.mean.value
3.0
>>> g1.mean.unit
Unit("m")
如果参数已初始化为数量,则应始终将其设置为数量,但单位不必与初始单位兼容:
>>> g1.mean = 3 * u.s
>>> g1
<Gaussian1D(amplitude=3. Jy, mean=3. s, stddev=2. cm)>
要更改参数的值而不是单位,只需设置value属性:
>>> g1.mean.value = 2
>>> g1
<Gaussian1D(amplitude=3. Jy, mean=2. s, stddev=2. cm)>
将最初设置为数量的参数设置为标量不起作用,因为用户是想只更改值并保留单位,还是删除单位,这是不明确的:
>>> g1.mean = 2
Traceback (most recent call last):
...
UnitsError : The 'mean' parameter should be given as a Quantity because it
was originally initialized as a Quantity
另一方面,如果先前定义的没有单位的参数被赋予一个带有单位的数量,这是因为它是明确的:
>>> g2 = Gaussian1D(mean=3)
>>> g2.mean = 3 * u.m
换句话说,一旦单位被附加到一个参数上,它们就不能被删除,因为含义不明确。
用数量评估模型#
在评估期间可以将数量传递到模型:
>>> g3 = Gaussian1D(mean=3 * u.m, stddev=5 * u.cm)
>>> g3(2.9 * u.m)
<Quantity 0.1353352832366122>
>>> g3(2.9 * u.s)
Traceback (most recent call last):
...
UnitsError : Units of input 'x', s (time), could not be converted to
required input units of m (length)
在这种情况下,由于平均值和标准差都有单位,因此在评估过程中通过的值也需要单位:
>>> g3(3)
Traceback (most recent call last):
...
UnitsError : Units of input 'x', (dimensionless), could not be converted to
required input units of m (length)
等价物#
等价性需要特别注意——例如,在频率空间定义的高斯函数不是波长空间中的高斯函数。出于这个原因,我们不允许将等价性附加到参数本身。相反,我们采取了将输入数据转换为参数空间的方法,并且在计算时应将任何等价性应用于数据(而不是参数)。
让我们考虑一个波长空间中的高斯模型:
>>> g4 = Gaussian1D(mean=3 * u.micron, stddev=1 * u.micron, amplitude=3 * u.Jy)
默认情况下,传递频率将不起作用:
>>> g4(1e2 * u.THz)
Traceback (most recent call last):
...
UnitsError : Units of input 'x', THz (frequency), could not be converted to
required input units of micron (length)
但是,您可以将等效字典传递给equivalences参数(这需要是一个字典,因为有些模型可以包含多个输入):
>>> g4(110 * u.THz, equivalencies={'x': u.spectral()})
<Quantity 2.888986819525229 Jy>
字典的键应该是输入的名称,根据:
>>> g4.inputs
('x',)
也可以使用input_units_equivalences属性为输入参数设置默认等效值:
>>> g4.input_units_equivalencies = {'x': u.spectral()}
>>> g4(110 * u.THz)
<Quantity 2.888986819525229 Jy>
用单位拟合模型到数据#
如果模型支持使用单位拟合,那么将带单位的模型与带单位的数据拟合应该是无缝的。为了证明这一点,我们从生成合成数据开始:
import numpy as np
from astropy import units as u
import matplotlib.pyplot as plt
x = np.linspace(1, 5, 30) * u.micron
y = np.exp(-0.5 * (x - 2.5 * u.micron)**2 / (200 * u.nm)**2) * u.mJy
plt.plot(x, y, 'ko')
plt.xlabel('Wavelength (microns)')
plt.ylabel('Flux density (mJy)')

然后,我们定义拟合的初始猜测值,然后按照不使用任何单位的方式进行拟合:
from astropy.modeling import models, fitting
g5 = models.Gaussian1D(mean=3 * u.micron, stddev=1 * u.micron, amplitude=1 * u.Jy)
fitter = fitting.LevMarLSQFitter()
g5_fit = fitter(g5, x, y)
plt.plot(x, y, 'ko')
plt.plot(x, g5_fit(x), 'r-')
plt.xlabel('Wavelength (microns)')
plt.ylabel('Flux density (mJy)')

具有等效性#
现在让我们考虑这样一种情况:数据与参数不等价,但它们可以通过等价物进行转换。在这种情况下,等价性可以通过字典传递,如上面的求值示例所示:
g6 = models.Gaussian1D(mean=110 * u.THz, stddev=10 * u.THz, amplitude=1 * u.Jy)
g6_fit = fitter(g6, x, y, equivalencies={'x': u.spectral()})
plt.plot(x, g6_fit(x, equivalencies={'x': u.spectral()}), 'b-')
plt.xlabel('Wavelength (microns)')
plt.ylabel('Flux density (mJy)')

在这种情况下,拟合(蓝色)稍差,因为频率空间(蓝色)中的高斯不是波长空间中的高斯(红色)。如前所述,您还可以在模型本身上设置input_units_等效性,以避免将额外的参数传递给装配工:
g6.input_units_equivalencies = {'x': u.spectral()}
g6_fit = fitter(g6, x, y)
支持其他无单位模型中的单元#
有些模型,如多项式,在本质上不适用于单位。取而代之的是 coerce_units()
方法提供了一种向无单位模型添加输入和返回单位的方法,方法是用 UnitsMapping
. 在内部,输入在传递到模型之前从单元中剥离出来,如果 return_units
已指定。该方法返回一个新的复合模型:
>>> from astropy.modeling import models
>>> from astropy import units as u
>>> model = models.Polynomial1D(1, c0=1, c1=2)
>>> new_model = model.coerce_units(input_units={'x': u.Hz}, return_units={'y': u.s},
... input_units_equivalencies={'x':u.spectral()})
>>> new_model(10 * u.Hz)
<Quantity 21. s>