分隔、偏移、目录匹配和相关功能#
astropy.coordinates
包含用于比较或匹配坐标对象的常用工具。特别重要的是那些用来确定坐标之间的分隔的那些,以及那些用于将一个(或多个)坐标与目录相匹配的那些。这些主要是在坐标对象上实现的方法。
在下面的示例中,我们将假设已经执行了以下导入:
>>> import astropy.units as u
>>> from astropy.coordinates import SkyCoord
分居#
天空中的距离可以用以下公式计算 separation()
,它计算大圆距离( not 小角度近似):
>>> c1 = SkyCoord('5h23m34.5s', '-69d45m22s', frame='icrs')
>>> c2 = SkyCoord('0h52m44.8s', '-72d49m43s', frame='fk5')
>>> sep = c1.separation(c2)
>>> sep
<Angle 20.74611448 deg>
返回的对象是 Angle
例如,因此可以使用几个等效角度单位中的任意一个来访问角度:
>>> sep.radian
0.36208800460262563
>>> sep.hour
1.3830742984029318
>>> sep.arcminute
1244.7668685626384
>>> sep.arcsecond
74686.0121137583
还请注意,两个输入坐标不在同一帧中-一个被自动转换为与另一个相匹配,以确保即使它们在不同的帧中,也能一致地确定间隔。
除了上面描述的空中分离之外, separation_3d()
将确定具有以下条件的两个坐标之间的3D距离 distance
定义::
>>> c1 = SkyCoord('5h23m34.5s', '-69d45m22s', distance=70*u.kpc, frame='icrs')
>>> c2 = SkyCoord('0h52m44.8s', '-72d49m43s', distance=80*u.kpc, frame='icrs')
>>> sep = c1.separation_3d(c2)
>>> sep
<Distance 28.74398816 kpc>
偏移#
与角度分离密切相关的是坐标之间的偏移。偏移的关键区别通常是“从”和“到”坐标的概念,而不是分离的单个标量角度偏移量。 coordinates
包含计算天文学中遇到的一些常见偏移的便利性。
这类功能的第一部分是 position_angle()
方法。此方法计算一个 SkyCoord
实例和遵循天文学约定的另一个(作为参数传递的)(北以东的正角度):
>>> c1 = SkyCoord(1*u.deg, 1*u.deg, frame='icrs')
>>> c2 = SkyCoord(2*u.deg, 2*u.deg, frame='icrs')
>>> c1.position_angle(c2).to(u.deg)
<Angle 44.97818294 deg>
这两种技术的结合 separation()
和 position_angle()
从而给出一组方向偏移量。要执行相反的操作--在给定间隔和位置角度的情况下确定新的“目标”坐标-- directional_offset_by()
提供了方法::
>>> c1 = SkyCoord(1*u.deg, 1*u.deg, frame='icrs')
>>> position_angle = 45 * u.deg
>>> separation = 1.414 * u.deg
>>> c1.directional_offset_by(position_angle, separation)
<SkyCoord (ICRS): (ra, dec) in deg
(2.0004075, 1.99964588)>
这种技术对于计算两个坐标之间的中点(或实际上任何点)也很有用,这种方法可以解释球面几何(即,而不是分别平均RAs/dec):
>>> coord1 = SkyCoord(0*u.deg, 0*u.deg, frame='icrs')
>>> coord2 = SkyCoord(1*u.deg, 1*u.deg, frame='icrs')
>>> pa = coord1.position_angle(coord2)
>>> sep = coord1.separation(coord2)
>>> coord1.directional_offset_by(pa, sep/2)
<SkyCoord (ICRS): (ra, dec) in deg
(0.49996192, 0.50001904)>
还有一个 spherical_offsets_to()
计算角度偏移的方法(例如,像你给望远镜操作员的小位移,使他们从明亮的恒星移动到较暗的目标):
>>> bright_star = SkyCoord('8h50m59.75s', '+11d39m22.15s', frame='icrs')
>>> faint_galaxy = SkyCoord('8h50m47.92s', '+11d39m32.74s', frame='icrs')
>>> dra, ddec = bright_star.spherical_offsets_to(faint_galaxy)
>>> dra.to(u.arcsec)
<Angle -173.78873354 arcsec>
>>> ddec.to(u.arcsec)
<Angle 10.60510342 arcsec>
概念上的反面 spherical_offsets_to()
也可以作为方法在任何 SkyCoord
对象: spherical_offsets_by()
,它接受两个角度偏移量(经度和纬度),并返回偏移位置的坐标:
>>> target_star = SkyCoord(86.75309*u.deg, -31.5633*u.deg, frame='icrs')
>>> target_star.spherical_offsets_by(1.3*u.arcmin, -0.7*u.arcmin)
<SkyCoord (ICRS): (ra, dec) in deg
(86.77852168, -31.57496415)>
“天空偏移”帧#
为了扩展球面偏移量的概念, coordinates
有一个Frame类 SkyOffsetFrame
这会创建以特定点为中心的不同帧。这些帧称为“天空偏移帧”,因为它们是创建以天空中任意位置为中心的帧的便捷方法,适用于计算位置偏移(例如,用于天文测量):
>>> from astropy.coordinates import SkyOffsetFrame, ICRS
>>> center = ICRS(10*u.deg, 45*u.deg)
>>> center.transform_to(SkyOffsetFrame(origin=center))
<SkyOffsetICRS Coordinate (rotation=0.0 deg, origin=<ICRS Coordinate: (ra, dec) in deg
(10., 45.)>): (lon, lat) in deg
(0., 0.)>
>>> target = ICRS(11*u.deg, 46*u.deg)
>>> target.transform_to(SkyOffsetFrame(origin=center))
<SkyOffsetICRS Coordinate (rotation=0.0 deg, origin=<ICRS Coordinate: (ra, dec) in deg
(10., 45.)>): (lon, lat) in deg
(0.69474685, 1.00428706)>
或者,方便法 skyoffset_frame()
用于从现有的天空偏移帧创建天空偏移帧 SkyCoord
::
>>> center = SkyCoord(10*u.deg, 45*u.deg)
>>> aframe = center.skyoffset_frame()
>>> target.transform_to(aframe)
<SkyOffsetICRS Coordinate (rotation=0.0 deg, origin=<ICRS Coordinate: (ra, dec) in deg
(10., 45.)>): (lon, lat) in deg
(0.69474685, 1.00428706)>
>>> other = SkyCoord(9*u.deg, 44*u.deg, frame='fk5')
>>> other.transform_to(aframe)
<SkyCoord (SkyOffsetICRS: rotation=0.0 deg, origin=<ICRS Coordinate: (ra, dec) in deg
(10., 45.)>): (lon, lat) in deg
(-0.71943945, -0.99556216)>
备注
而天空偏移帧 出现 所有的类都是一样的,但情况并非如此:天空偏移帧用于每种不同类型的帧 origin
实际上是一个不同的类。例如。, SkyOffsetFrame(origin=ICRS(...))
生成类的对象 SkyOffsetICRS
, not SkyOffsetFrame
. 虽然这对于这个类的大多数使用并不重要,但是对于类型检查之类的事情来说却很重要,因为 SkyOffsetFrame(origin=ICRS(...)).__class__ is SkyOffsetFrame
将 not 是 True
,就像大多数课程一样。
同样的框架也可以作为一种工具,用于定义与特定的已知对象相关的帧,这些对象对于像星系群这样的分层物理系统很有用。例如,M31周围的对象有时显示在与标准ICRA RA/Dec对齐的坐标系中,但在M31上:
>>> m31 = SkyCoord(10.6847083*u.deg, 41.26875*u.deg, frame='icrs')
>>> ngc147 = SkyCoord(8.3005*u.deg, 48.5087389*u.deg, frame='icrs')
>>> ngc147_inm31 = ngc147.transform_to(m31.skyoffset_frame())
>>> xi, eta = ngc147_inm31.lon, ngc147_inm31.lat
>>> xi
<Longitude -1.59206948 deg>
>>> eta
<Latitude 7.26183757 deg>
备注
目前,距离信息在 origin
一种 SkyOffsetFrame
不用于计算变换的任何部分。这个 origin
仅用于天空中的旋转。然而,这种情况在未来可能会改变。
匹配目录#
coordinates
利用坐标框架,可以在目录中找到与所需的其他坐标集最近的坐标。例如,假设 ra1
/dec1
和 ra2
/dec2
是否从某个文件加载NumPy数组:
>>> c = SkyCoord(ra=ra1*u.degree, dec=dec1*u.degree)
>>> catalog = SkyCoord(ra=ra2*u.degree, dec=dec2*u.degree)
>>> idx, d2d, d3d = c.match_to_catalog_sky(catalog)
返回的距离 d3d
是三维距离。除非两个来源 (c
)和目录 (catalog
)坐标具有关联的距离,此数量假定所有源的距离为1(无量纲)。
您还可以找到最近的三维匹配,与上面显示的仅当坐标初始化为 distance
:
>>> c = SkyCoord(ra=ra1*u.degree, dec=dec1*u.degree, distance=distance1*u.kpc)
>>> catalog = SkyCoord(ra=ra2*u.degree, dec=dec2*u.degree, distance=distance2*u.kpc)
>>> idx, d2d, d3d = c.match_to_catalog_3d(catalog)
现在 idx
是指 catalog
它们是距离中每个坐标最近的对象 c
, d2d
是它们之间的空中距离 d3d
是三维距离。对象支持坐标索引,因为, idx
允许轻松访问目录中的匹配坐标集:
>>> matches = catalog[idx]
>>> (matches.separation_3d(c) == d3d).all()
True
>>> dra, ddec = c.spherical_offsets_to(matches)
此功能也可以从 match_coordinates_sky()
和 match_coordinates_3d()
功能。这些都可以在以下两种情况下运行 SkyCoord
对象 or 较低级别的框架类:
>>> from astropy.coordinates import match_coordinates_sky
>>> idx, d2d, d3d = match_coordinates_sky(c, catalog)
>>> idx, d2d, d3d = match_coordinates_sky(c.frame, catalog.frame)
可以通过创建布尔掩码来施加分离约束(例如,将最大分离视为匹配) d2d
或 d3d
. 例如:
>>> max_sep = 1.0 * u.arcsec
>>> idx, d2d, d3d = c.match_to_catalog_3d(catalog)
>>> sep_constraint = d2d < max_sep
>>> c_matches = c[sep_constraint]
>>> catalog_matches = catalog[idx[sep_constraint]]
现在, c_matches
和 catalog_matches
匹配的源在吗 c
和 catalog
,它们之间的间隔小于1弧秒。
搜索坐标#
密切相关的功能可用于搜索 all 在另一组坐标的某一距离(三维距离或天空)内的坐标。这个 search_around_*
方法(和函数)提供此功能,接口与 match_coordinates_*
:
>>> import numpy as np
>>> idxc, idxcatalog, d2d, d3d = catalog.search_around_sky(c, 1*u.deg)
>>> np.all(d2d < 1*u.deg)
True
>>> idxc, idxcatalog, d2d, d3d = catalog.search_around_3d(c, 1*u.kpc)
>>> np.all(d3d < 1*u.kpc)
True
这些方法的关键不同之处在于, catalog
在任何地点周围 c
。因此,索引到这两个 c
和 catalog
而不只是将索引返回到 catalog
。然后,可以将这些索引重新编入两个 SkyCoord
对象,或具有相同顺序的任何数组:
>>> np.all(c[idxc].separation(catalog[idxcatalog]) == d2d)
True
>>> np.all(c[idxc].separation_3d(catalog[idxcatalog]) == d3d)
True
>>> print(catalog_objectnames[idxcatalog])
['NGC 1234' 'NGC 4567' ...]
但是请注意,这种双重索引意味着 search_around_*
如果其中一个坐标是标量,则无法正常工作,因为返回的索引对于标量没有意义:
>>> scalarc = SkyCoord(ra=1*u.deg, dec=2*u.deg, distance=distance1*u.kpc)
>>> idxscalarc, idxcatalog, d2d, d3d = catalog.search_around_sky(scalarc, 1*u.deg)
ValueError: One of the inputs to search_around_sky is a scalar.
结果(因为 search_around_*
算法在标量情况下效率低下),对于这种情况,最好的方法是使用 separation*
方法:
>>> d2d = scalarc.separation(catalog)
>>> catalogmsk = d2d < 1*u.deg
>>> d3d = scalarc.separation_3d(catalog)
>>> catalog3dmsk = d3d < 1*u.kpc
结果 catalogmsk
或 catalog3dmsk
变量是布尔数组而不是索引数组,但实际上它们通常可以用与 idxcatalog
从上面的例子。如果确实需要索引而不是布尔掩码,可以执行以下操作:
>>> idxcatalog = np.where(catalogmsk)[0]
>>> idxcatalog3d = np.where(catalog3dmsk)[0]