坐标系的使用与设计#

在……里面 astropy.coordinates ,如 概述 astropy.coordinates 概念 、的子类 BaseCoordinateFrame (“框架类”)定义特定的坐标框架。他们可以(但不能 have 到)包含存储实际坐标数据的表示对象。实际的坐标转换被定义为在框架类之间转换表示法的函数。此方法用于分离高级用户功能(请参见 使用SkyCoord高级课程 )和实际如何存储坐标的详细信息(请参见 使用和设计坐标表示法 )来自帧的定义以及它们是如何变换的。

使用框架对象#

没有数据的帧#

帧对象有两个不同(但相关)的用途。第一种方法是存储唯一定义帧所需的信息(例如春分点、观测时间)。此信息作为(只读)Python属性存储在帧对象上,这些属性是在首次创建对象时设置的:

>>> from astropy.coordinates import ICRS, FK5
>>> FK5(equinox='J1975')
<FK5 Frame (equinox=J1975.000)>
>>> ICRS()  # has no attributes
<ICRS Frame>
>>> FK5()  # uses default equinox
<FK5 Frame (equinox=J2000.000)>

可用于特定帧的属性的特定名称可用作 frame_attributes 词典::

>>> FK5.frame_attributes.keys()
dict_keys(['equinox'])

帧属性的默认设置如下: get_frame_attr_defaults() **

>>> FK5.get_frame_attr_defaults()
{'equinox': <Time object: scale='tt' format='jyear_str' value=J2000.000>}

通过使用标准Python属性访问,可以访问帧上的任何属性。注意,对于像 equinox ,它们是时间输入,如果传入任何明确的时间字符串,则它将转换为 Time 对象(参见 推断输入格式 ):

>>> f = FK5(equinox='J1975')
>>> f.equinox
<Time object: scale='tt' format='jyear_str' value=J1975.000>
>>> f = FK5(equinox='2011-05-15T12:13:14')
>>> f.equinox
<Time object: scale='utc' format='isot' value=2011-05-15T12:13:14.000>

带数据的帧#

Frame对象的第二个用途是存储如上所述的帧的实际实现的坐标数据。在此用法中,它类似于 SkyCoord 类,事实上, SkyCoord 类在内部使用Frame类作为其实现。但是,Frame类具有较少的“便利”功能,从而简化了Frame类的实现。因此,它们的创建方式类似于 SkyCoord 物体。一种建议的方式是与适合于帧的关键字一起使用(例如, radec 对于赤道系统):

>>> from astropy import units as u
>>> ICRS(ra=1.1*u.deg, dec=2.2*u.deg)  
<ICRS Coordinate: (ra, dec) in deg
    (1.1, 2.2)>
>>> FK5(ra=1.1*u.deg, dec=2.2*u.deg, equinox='J1975')  
<FK5 Coordinate (equinox=J1975.000): (ra, dec) in deg
    (1.1, 2.2)>

这些属性可用于访问帧中的数据 Angle 对象(或 Angle 子类)::

>>> coo = ICRS(ra=1.1*u.deg, dec=2.2*u.deg)
>>> coo.ra  
<Longitude 1.1 deg>
>>> coo.ra.value  
1.1
>>> coo.ra.to(u.hourangle)  
<Longitude 0.07333333 hourangle>

你可以使用 representation_type 属性与 representation_component_names 属性来计算特定类对象接受哪些关键字。前者是表示系统的表示类(例如赤道帧的球形表示),后者是将该帧的名称映射到表示类上的属性名的字典:

>>> import astropy.units as u
>>> icrs = ICRS(1*u.deg, 2*u.deg)
>>> icrs.representation_type
<class 'astropy.coordinates...SphericalRepresentation'>
>>> icrs.representation_component_names
{'ra': 'lon', 'dec': 'lat', 'distance': 'distance'}

如果需要,可以使用不同的表示形式获取数据:

>>> icrs.represent_as('cartesian')  
<CartesianRepresentation (x, y, z) [dimensionless]
     (0.99923861, 0.01744177, 0.0348995)>

坐标对象的表示也可以直接更改,如下所示。确实如此 没有什么 存储坐标值的对象内部数据,但它以两种方式更改该数据的外部视图:(1)对象按照新表示打印自身;(2)可用属性更改以匹配新表示的属性(例如,从 ra, dec, distancex, y, z ). 设置 representation_type 从而改变了 属性 在不改变代表三维空间中一个点的固有对象本身的情况下(如何显示):

>>> from astropy.coordinates import CartesianRepresentation
>>> icrs.representation_type = CartesianRepresentation
>>> icrs  
<ICRS Coordinate: (x, y, z) [dimensionless]
    (0.99923861, 0.01744177, 0.0348995)>
>>> icrs.x  
<Quantity 0.99923861>

也可以在创建坐标时设置表示,并影响用于提供坐标数据的关键字集。例如,要使用笛卡尔数据创建坐标,请执行以下操作:

>>> ICRS(x=1*u.kpc, y=2*u.kpc, z=3*u.kpc, representation_type='cartesian')  
<ICRS Coordinate: (x, y, z) in kpc
    (1., 2., 3.)>

有关在坐标中使用表示的详细信息,请参见 陈述 部分,有关表示本身的详细信息,请参见 使用和设计坐标表示法 .

有两种方法可以创建带有坐标的框架类。可以在创建时直接传入表示类,以及所需的任何帧属性:

>>> from astropy.coordinates import SphericalRepresentation
>>> rep = SphericalRepresentation(lon=1.1*u.deg, lat=2.2*u.deg, distance=3.3*u.kpc)
>>> FK5(rep, equinox='J1975')  
<FK5 Coordinate (equinox=J1975.000): (ra, dec, distance) in (deg, deg, kpc)
    (1.1, 2.2, 3.3)>

最后一种方法是使用 realize_frame 方法。这将生成一个具有相同属性的帧,但新数据:

>>> f1 = FK5(equinox='J1975')
>>> f1
<FK5 Frame (equinox=J1975.000)>
>>> rep = SphericalRepresentation(lon=1.1*u.deg, lat=2.2*u.deg, distance=3.3*u.kpc)
>>> f1.realize_frame(rep)  
<FK5 Coordinate (equinox=J1975.000): (ra, dec, distance) in (deg, deg, kpc)
    (1.1, 2.2, 3.3)>

可以使用 has_data 属性,如果存在,则可以从 data 属性:

>>> ICRS().has_data
False
>>> cooi = ICRS(ra=1.1*u.deg, dec=2.2*u.deg)
>>> cooi.has_data
True
>>> cooi.data  
<UnitSphericalRepresentation (lon, lat) in deg
    (1.1, 2.2)>

以上所有方法也可以接受数组数据(以类的形式:数量,或其他Python序列)来创建坐标数组:

>>> ICRS(ra=[1.5, 2.5]*u.deg, dec=[3.5, 4.5]*u.deg)  
<ICRS Coordinate: (ra, dec) in deg
    [(1.5, 3.5), (2.5, 4.5)]>

如果传入混合数组和标量,数组将适当地通过标量广播:

>>> ICRS(ra=[1.5, 2.5]*u.deg, dec=[3.5, 4.5]*u.deg, distance=5*u.kpc)  
<ICRS Coordinate: (ra, dec, distance) in (deg, deg, kpc)
    [(1.5, 3.5, 5.), (2.5, 4.5, 5.)]>

如果你转换到另一帧,类似的广播也会发生。例如::

>>> import numpy as np
>>> from astropy.coordinates import EarthLocation, AltAz
>>> coo = ICRS(ra=180.*u.deg, dec=51.477811*u.deg)
>>> lf = AltAz(location=EarthLocation.of_site('greenwich'),
...            obstime=['2012-03-21T00:00:00', '2012-06-21T00:00:00'])
>>> lcoo = coo.transform_to(lf)  # this can load finals2000A.all 
>>> lcoo  
<AltAz Coordinate (obstime=['2012-03-21T00:00:00.000' '2012-06-21T00:00:00.000'], location=(3980608.9024681724, -102.47522910648239, 4966861.273100675) m, pressure=0.0 hPa, temperature=0.0 deg_C, relative_humidity=0.0, obswl=1.0 micron): (az, alt) in deg
    [( 94.71264993, 89.21424259), (307.69488825, 37.98077772)]>

上面是形状- () 对于 coo(2,) 对于 lf -互相广播。如果要确定一组坐标的位置,则需要确保形状允许:

>>> coo2 = ICRS(ra=[180., 225., 270.]*u.deg, dec=[51.5, 0., 51.5]*u.deg)
>>> coo2.transform_to(lf)
Traceback (most recent call last):
...
ValueError: operands could not be broadcast together...
>>> coo2.shape
(3,)
>>> lf.shape
(2,)
>>> lf2 = lf[:, np.newaxis]
>>> lf2.shape
(2, 1)
>>> coo2.transform_to(lf2)  
<AltAz Coordinate (obstime=[['2012-03-21T00:00:00.000' '2012-03-21T00:00:00.000'
  '2012-03-21T00:00:00.000']
 ['2012-06-21T00:00:00.000' '2012-06-21T00:00:00.000'
  '2012-06-21T00:00:00.000']], location=(3980608.90246817, -102.47522911, 4966861.27310068) m, pressure=0.0 hPa, temperature=0.0 deg_C, relative_humidity=0.0, obswl=1.0 micron): (az, alt) in deg
    [[( 93.09845155, 89.21613119), (126.85789646, 25.46600543),
      ( 51.37993224, 37.1853252 )],
     [(307.71713691, 37.99437664), (231.37407858, 26.36768334),
      ( 85.42187562, 89.6929799 )]]>

备注

没有数据的帧具有 shape 这是由它们的帧属性决定的。对于包含数据的帧 shape 始终是数据的属性;任何非标量属性都被广播为具有匹配的形状(可以看到 obstime 在上面最后一行)。

数组值帧对象中的坐标值可以就地修改(在astropy 4.1中添加)。这需要从其他帧对象设置新值,该对象在所有方面都是等效的,但实际坐标数据值除外。这样,不需要帧转换,并且项目设置操作非常健壮。

要修改坐标数组,请对numpy数组使用相同的语法:

>>> coo1 = ICRS([1, 2] * u.deg, [3, 4] * u.deg)
>>> coo2 = ICRS(10 * u.deg, 20 * u.deg)
>>> coo1[0] = coo2
>>> coo1
<ICRS Coordinate: (ra, dec) in deg
    [(10., 20.), ( 2.,  4.)]>

此方法相对较慢,因为它需要从现有帧对象进行设置,并且它执行广泛的验证以确保操作有效。对于某些应用程序,可能需要采用本节中描述的不同的较低级别方法 坐标的快速在位修改 .

警告

例如,您可能会尝试一种显而易见的方法,通过直接更新组件属性来就地修改框架对象 coo1.ra[1] = 40 * u.deg . 然而,虽然这会 出现 为了给出正确的结果,它实际上并不修改底层表示数据。这与基于性能的缓存的当前实现有关。当前的缓存实现同样无法处理对表示的就地更改 (.data )或帧属性,例如 .obstime .

在帧之间变换#

要将包含数据的帧对象转换为另一帧,请使用 transform_to 方法,并为其提供要转换到的帧。这个框架应该是一个框架对象(有或没有坐标数据)。如果希望使用所有默认帧属性,可以不带参数(即空括号)实例化frame类:

>>> cooi = ICRS(1.5*u.deg, 2.5*u.deg)
>>> cooi.transform_to(FK5())  
<FK5 Coordinate (equinox=J2000.000): (ra, dec) in deg
    (1.50000661, 2.50000238)>
>>> cooi.transform_to(FK5(equinox='J1975'))  
<FK5 Coordinate (equinox=J1975.000): (ra, dec) in deg
    (1.17960348, 2.36085321)>

这个 参考/API 包括内置的所有帧的列表 astropy.coordinates ,以及它们之间定义的转换。任何具有有效路径的变换,即使它通过其他帧,也可以变换。若要以编程方式检查或操作转换,请参见 TransformGraph 文档。

定义新框架#

实现连接到 astropy.coordinates 基础设施可以通过子类化来实现 BaseCoordinateFrame . 下面给出了一些指导和示例,但在的docstring中给出了创建新框架的详细说明 BaseCoordinateFrame .

所有结构件类必须至少通过定义 default_representation 类属性(请参见 使用和设计坐标表示法 有关支持的 Representation 对象)。

实例#

要创建一个默认情况下预期接收球坐标数据的新帧,我们将创建一个子类,如下所示:

>>> from astropy.coordinates import BaseCoordinateFrame
>>> import astropy.coordinates.representation as r
>>> class MyFrame1(BaseCoordinateFrame):
...     # Specify how coordinate values are represented when outputted
...     default_representation = r.SphericalRepresentation

这已经是一个有效的帧类::

>>> fr = MyFrame1(1*u.deg, 2*u.deg)
>>> fr 
<MyFrame1 Coordinate: (lon, lat) in deg
    (1., 2.)>
>>> fr.lon 
<Longitude 1. deg>

但是,正如我们在上面定义的那样,(1)坐标组件的名称将与指定的 default_representation (在这种情况下, lonlatdistance 对于经度、纬度和距离,(2)此帧没有任何附加属性或元数据,(3)此帧不支持转换到任何其他坐标系,(4)此帧不支持速度数据。我们可以通过查看其他定制框架子类的方法来解决这些问题。

自定义结构件零部件名称#

首先,如第(1)点所述 above ,一些框架类对其组件有特殊的名称。例如 ICRS frame和其他赤道框架类通常用“赤经”或“RA”代替经度,用“赤纬”或“Dec”代替纬度。这些零部件名称将替代,从而更改从 Representation 类,通过指定一组 RepresentationMapping 实例(每个组件一个)作为在框架类上定义附加类属性的一部分: frame_specific_representation_info . 此属性必须是字典,并且键应该是 RepresentationDifferential 类(有关为velocity组件自定义行为的讨论,请参见下面的内容,该讨论使用 Differential 类)。使用上面实现的示例框架,我们可以对其进行自定义,以使用名称“R”和“D”,而不是“lon”和“lat”:

>>> from astropy.coordinates import RepresentationMapping
>>> class MyFrame2(BaseCoordinateFrame):
...     # Specify how coordinate values are represented when outputted
...     default_representation = r.SphericalRepresentation
...
...     # Override component names (e.g., "ra" instead of "lon")
...     frame_specific_representation_info = {
...         r.SphericalRepresentation: [RepresentationMapping('lon', 'R'),
...                                     RepresentationMapping('lat', 'D')]
...     }

有了这个框架,我们现在可以使用名称了 RD 访问帧数据:

>>> fr = MyFrame2(3*u.deg, 4*u.deg)
>>> fr 
<MyFrame2 Coordinate: (R, D) in deg
    (3., 4.)>
>>> fr.R 
<Longitude 3. deg>

我们可以为任何 Representation 班在 astropy.coordinates 更改默认零部件名称。例如 Galactic 当与a一起使用时,frame使用标准的经度和纬度名称“l”和“b” SphericalRepresentation ,但当表示形式更改为a时,使用组件名称“x”、“y”和“z” CartesianRepresentation . 在上面的例子中,我们可以添加一组额外的映射来覆盖笛卡尔组件名为“a”、“b”和“c”,而不是默认的“x”、“y”和“z”:

>>> class MyFrame3(BaseCoordinateFrame):
...     # Specify how coordinate values are represented when outputted
...     default_representation = r.SphericalRepresentation
...
...     # Override component names (e.g., "ra" instead of "lon")
...     frame_specific_representation_info = {
...         r.SphericalRepresentation: [RepresentationMapping('lon', 'R'),
...                                     RepresentationMapping('lat', 'D')],
...         r.CartesianRepresentation: [RepresentationMapping('x', 'a'),
...                                     RepresentationMapping('y', 'b'),
...                                     RepresentationMapping('z', 'c')]
...     }

对于任何 RepresentationMapping ,也可以通过设置 defaultunit 关键字参数。

定义帧属性#

第二,如 introduction above ,对于坐标帧,允许指定帧“属性”通常很有用,这些属性可以指定所需的附加数据或参数,以便完全指定给定帧与其他帧之间的转换。例如 FK5 frame allows specifying an equinox that helps define the transformation between FK5 and the ICRS frame. Frame attributes are defined by creating class attributes that are instances of Attribute or its subclasses (e.g., TimeAttribute, QuantityAttribute, etc.). If attributes are defined using these classes, there is often no need to define an ``_ _初始化函数,作为中的初始值设定项 BaseCoordinateFrame 可能会按照你想要的方式行事。现在让我们修改上面的toy frame类实现来添加两个frame属性:

>>> from astropy.coordinates import TimeAttribute, QuantityAttribute
>>> class MyFrame4(BaseCoordinateFrame):
...     # Specify how coordinate values are represented when outputted
...     default_representation = r.SphericalRepresentation
...
...     # Override component names (e.g., "ra" instead of "lon")
...     frame_specific_representation_info = {
...         r.SphericalRepresentation: [RepresentationMapping('lon', 'R'),
...                                     RepresentationMapping('lat', 'D')],
...         r.CartesianRepresentation: [RepresentationMapping('x', 'a'),
...                                     RepresentationMapping('y', 'b'),
...                                     RepresentationMapping('z', 'c')]
...     }
...
...     # Specify frame attributes required to fully specify the frame
...     time = TimeAttribute(default='B1950')
...     orientation = QuantityAttribute(default=42*u.deg)

在不指定初始值设定项的情况下,定义这些属性会告诉 BaseCoordinateFrame 在传递给我们的子类初始值设定项的附加参数方面,应该期待什么。例如,当用我们的子类定义一个框架实例时,我们现在可以选择为这些属性指定值:

>>> fr = MyFrame4(R=1*u.deg, D=2*u.deg, orientation=21*u.deg)
>>> fr 
<MyFrame4 Coordinate (time=B1950.000, orientation=21.0 deg): (R, D) in deg
    (1., 2.)>

注意,我们用默认值指定了两个frame属性,因此它们是框架初始值设定项的可选参数。另请注意,帧属性现在显示在 repr 上面的框架实例。作为奖励,对于大多数 Attribute 子类,即使没有定义初始值设定项,也将验证指定为参数的属性。例如,传入的参数 QuantityAttribute 将检查属性是否具有与预期属性单位有效且兼容的单位。使用上面的框架示例,它期望 orientation 对于角度单位,传入时间会导致错误:

>>> MyFrame4(R=1*u.deg, D=2*u.deg, orientation=55*u.microyear) 
Traceback (most recent call last):
...
UnitConversionError: 'uyr' (time) and 'deg' (angle) are not convertible

定义帧属性时,不必总是指定默认值,只要 Attribute 子类能够验证输入。例如,对于上面的框架,如果 orientation 不需要默认值,但我们仍然希望强制它具有角度单位,我们可以将其定义为:

orientation = QuantityAttribute(unit=u.deg)

在上述情况下,如果 orientation 在创建新框架实例时未指定,则其值将为 None :注意,由帧类和转换函数实现来定义如何处理 None 价值观。在大多数情况下 None 应该表示一种特殊情况,如“为此值使用不同的帧属性”或类似的情况。

自定义属性显示#

而违约 repr for coordinate frames is suitable for most cases, you may want to customize how frame attributes are displayed in certain cases. To do this you can define a method named ``_ 在你的框里有一个阿谀奉承的人。应该在设置为frame属性本身的对象上定义此方法, not 这个 Attribute 描述符。

例子#

作为一个例子 _astropy_repr_in_frame ,假设你有一个物体 Spam 作为帧的属性:

>>> class Spam:
...     def _astropy_repr_in_frame(self):
...         return "<A can of Spam>"

如果您的帧将此类作为属性::

>>> from astropy.coordinates import Attribute
>>> class Egg(BaseCoordinateFrame):
...     can = Attribute(default=Spam())

当它按帧显示时,它将使用 _astropy_repr_in_frame ::

>>> Egg()
<Egg Frame (can=<A can of Spam>)>

定义帧之间的变换#

如图中第(3)点所示 introduction above ,只有在框架类和其他坐标系类之间定义了转换之后,框架类本身可能不会很有用。在中定义转换的关键概念 astropy.coordinates 是“帧变换图”(在“图论”的意义上,而不是“图”),它存储了内置帧之间的所有变换,以及通过该图查找最短路径的工具,以便通过组合变换从任何帧转换到任何其他帧。此概念背后的强大功能也适用于用户创建的帧,这意味着一旦定义了从帧到图形中任何帧的一个变换,帧中定义的坐标就可以转换为 any 图中的其他帧。“帧变换图”的代码如下 astropy.coordinates.frame_transform_graph ,它是 TransformGraph 班级。

转换本身表示为 CoordinateTransform 对象或其子类。有用的转换子类/类型有:

  • FunctionTransform

    定义为接受一个帧类的帧对象并返回另一个类的对象的函数的一种转换。

  • AffineTransform

    一种包括线性矩阵运算和平移(向量偏移)的变换。这些变换由3x3矩阵和偏移量的3矢量定义(以笛卡尔表示形式提供)。该变换应用于一帧的笛卡尔表示,并转换为目标帧的笛卡尔表示。

  • StaticMatrixTransform

  • DynamicMatrixTransform

    矩阵变换是 AffineTransform 无平移的变换(即仅旋转)。静态版本适用于矩阵独立于帧属性的情况(例如,ICRS->FK5转换,因为ICRS没有帧属性)。动态情况适用于变换,其中变换矩阵依赖于to或from帧的帧属性。

一般来说,没有必要直接使用这些类。相反,请使用 frame_transform_graph 可以用作函数修饰符。定义进行实际转换的函数(对于 FunctionTransform ),或者计算必要的转换矩阵来进行转换。然后装饰函数以将这些变换注册到帧变换图中:

from astropy.coordinates import frame_transform_graph

@frame_transform_graph.transform(DynamicMatrixTransform, ICRS, FK5)
def icrs_to_fk5(icrscoord, fk5frame):
    ...

@frame_transform_graph.transform(DynamicMatrixTransform, FK5, ICRS)
def fk5_to_icrs(fk5coord, icrsframe):
    ...

如果到您感兴趣的坐标系的转换不能用矩阵运算表示,您也可以指定一个函数来执行实际的转换,并传递 FunctionTransform 类改为转换图形修饰符::

@frame_transform_graph.transform(FunctionTransform, FK4NoETerms, FK4)
def fk4_no_e_to_fk4(fk4noecoord, fk4frame):
    ...

而且, frame_transform_graph 在第一次尝试从一个帧转到另一帧之后,执行一些缓存和优化以加快转换速度,并在相关的地方缩短步骤(例如,将多个静态矩阵转换为单个矩阵)。因此,一般来说,最好是为用户定义的框架定义最自然的转换,而不是担心如何优化或缓存转换以加快过程。

有关如何定义同样适用于变换速度分量的变换函数的演示,请参见 用速度变换帧 .

帧内支持速度数据#

如第(4)点所述 introduction above ,我们在上面看到的示例主要处理为位置信息定制帧行为。(关于如何在 astropy.coordinates ,请阅读概述: 使用速度数据创建帧对象

定义框架类时,也可以设置 default_differential (类似于 default_representation ),以及自定义velocity数据组件的命名方式。在上面的自定义框架示例中,我们可以使用 RepresentationMapping 覆盖 Differential 组件名称。违约 Differential 组件通常以相应的 Representation 组件,前面有 d_ . 例如,经度 Differential 默认情况下, d_lon . 但是,也有一些缺陷需要注意。这里,如果我们设置默认值 Differential 类也可以是球形的,它将为速度组件mapping实现一组默认的“更好的”名称 pm_Rd_lonpm_Dd_latradial_velocityd_distance (使用先前覆盖的经度和纬度组件名称)::

>>> class MyFrame4WithVelocity(BaseCoordinateFrame):
...     # Specify how coordinate values are represented when outputted
...     default_representation = r.SphericalRepresentation
...     default_differential = r.SphericalDifferential
...
...     # Override component names (e.g., "ra" instead of "lon")
...     frame_specific_representation_info = {
...         r.SphericalRepresentation: [RepresentationMapping('lon', 'R'),
...                                     RepresentationMapping('lat', 'D')],
...         r.CartesianRepresentation: [RepresentationMapping('x', 'a'),
...                                     RepresentationMapping('y', 'b'),
...                                     RepresentationMapping('z', 'c')]
...     }
>>> fr = MyFrame4WithVelocity(R=1*u.deg, D=2*u.deg,
...                           pm_R=3*u.mas/u.yr, pm_D=4*u.mas/u.yr)
>>> fr 
<MyFrame4WithVelocity Coordinate: (R, D) in deg
    (1., 2.)
(pm_R, pm_D) in mas / yr
    (3., 4.)>

如果要重写默认的“更好”名称,可以在 frame_specific_representation_info 对于任何 Differential 类,例如:

>>> class MyFrame4WithVelocity2(BaseCoordinateFrame):
...     # Specify how coordinate values are represented when outputted
...     default_representation = r.SphericalRepresentation
...     default_differential = r.SphericalDifferential
...
...     # Override component names (e.g., "ra" instead of "lon")
...     frame_specific_representation_info = {
...         r.SphericalRepresentation: [RepresentationMapping('lon', 'R'),
...                                     RepresentationMapping('lat', 'D')],
...         r.CartesianRepresentation: [RepresentationMapping('x', 'a'),
...                                     RepresentationMapping('y', 'b'),
...                                     RepresentationMapping('z', 'c')],
...         r.SphericalDifferential: [RepresentationMapping('d_lon', 'pm1'),
...                                   RepresentationMapping('d_lat', 'pm2'),
...                                   RepresentationMapping('d_distance', 'rv')]
...     }
>>> fr = MyFrame4WithVelocity2(R=1*u.deg, D=2*u.deg,
...                           pm1=3*u.mas/u.yr, pm2=4*u.mas/u.yr)
>>> fr 
<MyFrame4WithVelocity2 Coordinate: (R, D) in deg
    (1., 2.)
(pm1, pm2) in mas / yr
    (3., 4.)>

最终笔记#

您还可以为希望框架具有该框架独有的任何附加功能定义任意方法。这些方法将在任何 SkyCoord 它是使用用户定义的框架创建的。

对于定义框架类的示例,首先要查看中包含的框架的源代码 astropy (可在 astropy.coordinates.builtin_frames ). 这些不是特殊情况,而是使用用户创建的框架可用的所有相同的API和特性。