VTD 如何读取射电源先验星表

· 预计阅读 12 分钟

射电源先验星表为 VTD 计算理论时延提供源坐标。对于一次实验,VTD 需要从星表中找出本次观测的源,并读取它们的先验坐标。VTD 读取射电源先验星表的核心程序是 VTD_LOAD_SOUCOO(vtd/src/vtd_load_soucoo.f)。它根据文件首行的标识判断格式,再按固定列位置读取源名、赤经和赤纬。这里记录其读取过程

一、VTD 如何读取星表

  1. 调用程序先用 VTD_INIT 初始化 VTD,再用 VTD_CONF 读取控制文件。控制文件最多可以指定 4 份先验星表,下面的例子使用了其中两份。
SOURCE_COORDINATES:      /path/to/main_catalogue.txt
SOURCE_COORDINATES_2ND:  /path/to/supplement_catalogue.txt
SOURCE_COORDINATES_3RD:  NONE
SOURCE_COORDINATES_4TH:  NONE

它们依次写入 VTD%CONF%FINAM_SOUCOO(1:4)。后三项可以使用 NONE;第一项直接检查文件是否存在,没有相同的 NONE 处理。

  1. 调用者向 VTD_LOAD 提供本次实验的源数 L_SOU 和源名列表 C_SOU。以 pSolve 为例,这两项分别来自当前实验 GVF 数据库中的 NUMB_SOU 和 SRCNAMES。这样,实验数据库决定要查哪些源,控制文件决定去哪些星表查。通常,VTD_LOAD 接着调用 VTD_LOAD_SOUCOO 读取源坐标。VTD__BYPS 表示跳过装载,当 VTD%STATUS_SOU == VTD__BYPS 时,VTD_LOAD 跳过这一步。

  2. VTD_LOAD_SOUCOO 调用 RD_TEXT 依次读取各份星表,根据每个文件的首行识别格式,再用数据行中的源名匹配 C_SOU。只装入本次实验需要的源。对于同一个普通射电源,后读到的坐标覆盖先前的坐标。因此,第 4 份星表优先于第 3 份,依此类推,同一文件中也是后面的记录优先。如果读完所有星表仍未找到某个请求的普通射电源,程序报告错误。

  3. 将射电源表中的坐标转为弧度,保存到 VTD%SOU。赤经通过 HR_TAT 从时、分、秒转换为弧度,赤纬通过 GR_TAT 从度、角分、角秒转换为弧度,并计算空固系中的方向单位向量:

\(\boldsymbol{s} = \begin{pmatrix} \cos\delta\cos\alpha\\ \cos\delta\sin\alpha\\ \sin\delta \end{pmatrix}.\) 赤经、赤纬和方向单位向量分别保存在 ALPHA、DELTA 和 S_CRS(1:3) 中,供后续时延计算使用。

二、VTD 支持的七种先验源表格式

在上述读取过程中,源名、赤经和赤纬各占哪些列,取决于文件首行的标识。VTD_LOAD_SOUCOO 识别下表中的 7 种标识,表中编号就是源码中 I_FMT 的值。

编号 文件第一行的标识 用途
1 # VLBI SOURCE POSITION CATALOGUE Format version of 2004.01.21 射电源位置星表
2 $$ SOU-MODFILE Format pre-2000 旧式射电源位置文件
3 # Catalogue of source positions and velocities. Format version of 2005.12.29 此读取分支提取目标名称、类型及轨道目标名称
4 # SOURCE-NAMES v 2.0 2005.09.06 源名、别名及先验位置
5 # Source position file format 1.0 of 2019.08.08 射电源先验位置文件
6 # VLBI SOURCE POSITION CATALOGUE Format version of 2024.10.14 较新的射电源位置星表
7 # SOURCE-NAMES v 3.0 2025.09.06 包含普通射电源和轨道目标的分支

程序直接检查首行,因此标识中的大小写和内部空格应保留,前面也不要添加空行或缩进。识别格式后,程序按相应的固定列读取数据。下表列出普通射电源的源名和坐标列位,适用于格式 1、2、4、5、6,以及格式 7 的普通源记录。格式 3 用于关联观测源名与轨道目标名,格式 7 也可以指定轨道文件或目录,这两类记录在各自的示例中说明。

字段 格式 1 格式 2 格式 4 格式 5 格式 6,以及格式 7 的普通源分支
主要匹配源名 1:8 5:12 1:8 4:11 17:24
J2000 名称 10:19 不读取,设为 ?????????? 11:20 14:23 5:14
赤经:时 22:23 15:16 46:47 26:27 27:28
赤经:分 25:26 18:19 49:50 29:30 30:31
赤经:秒 28:36 21:31 52:58 32:40 33:41
赤纬:符号及度 38:40 35:37 60:62 43:45 43:45
赤纬:角分 42:43 39:40 64:65 47:48 47:48
赤纬:角秒 45:52 42:51 67:72 50:57 50:57

表中的列号从 1 起算,起止列都包括在内。各格式对这些字段的读法略有不同。

  • 格式 1、2 分别截取三个坐标分量,再用 _ 拼接后解析。
  • 格式 4 直接解析 46:58 和 60:72,典型写法是 12_34_56.1234、+12_34_56.123。
  • 格式 5 直接解析 26:40 和 43:57,典型写法是 12:34:56.123456、+12:34:56.12345。
  • 格式 6 会将第 29、32、46、49 列改成冒号,然后解析坐标。因此,原始记录可以采用时、分、秒之间用空格分隔的形式。
  • 程序用“主要匹配源名”一栏所列的字段查找 C_SOU 中的源。格式 4 还会尝试别名。各格式中的 J2000 名称字段用于保存名称,不参与这里的匹配。
  • 星表中的位置误差、相关系数、流量密度等附加字段,没有被这个坐标读取程序读入。

1. 2004年版 VLBI 射电源位置星表

第一行标明版本 2004.01.21。以 3C273B 为例,把坐标按格式 1 重排,就可以将上表中的列位与实际数据行逐项对照。

# VLBI SOURCE POSITION CATALOGUE  Format version of 2004.01.21
3C273B   J1229+0203  12 29 06.699755 +02 03 08.59830
字段 源码读取的列 示例值
IVS 名称,用于匹配 C_SOU 1:8 3C273B
J2000 名称 10:19 J1229+0203
赤经的时、分、秒 22:23、25:26、28:36 12 29 06.699755
赤纬的符号及度、角分、角秒 38:40、42:43、45:52 +02 03 08.59830

程序分别截取赤经、赤纬的三个分量,用下划线拼起来,再转换为弧度。

2. SOU-MODFILE

这是 VTD 为兼容旧文件保留的格式。下面是格式说明中的原始示例,数据行开头有 4 个空格。

$$  SOU-MODFILE Format pre-2000
    2357-326  00 00 20.399945     -32 21 01.23327     0.60  ! J0000-3221
字段 源码读取的列 示例值
IVS 名称,用于匹配 C_SOU 5:12 2357-326
赤经的时、分、秒 15:16、18:19、21:31 00 00 20.399945
赤纬的符号及度、角分、角秒 35:37、39:40、42:51 -32 21 01.23327

值得注意的是,行末虽然写着 ! J0000-3221,但这是注释。这个分支把 J2000_NAME 直接设成 ??????????,也不读取 0.60 这个位置误差值。

3. 2005年版 VLBI 射电源位置与速度星表

源代码中的 vtd/share/titan_apr.src 使用这种格式。下面是它的第一条数据记录,HYIGENS 保留文件中的实际拼写。

# Catalogue of source positions and velocities. Format version of 2005.12.29
2005.01.14_10:00:00.0000000000  TAI  S  S_000001  HYIGENS
字段 列位置 示例值 VTD_LOAD_SOUCOO 的处理
日期及时间尺度 1:30、33:35 2005.01.14_10:00:00.0000000000、TAI 本分支不解析这两个字段
目标类型 38 S 写入 OBJ_TYPE,这里表示太阳系内的近场目标
观测源名 41:48 S_000001 与 C_SOU 匹配,写入 IVS_NAME
轨道目标名 51:58 HYIGENS 写入 NZO_NAME,用于关联轨道数据

这条记录的含义是:实验中的 S_000001 对应轨道目标 HYIGENS。下一条记录又把 S_000002 指向同一个 HYIGENS。尽管格式名称里有“位置和速度”,这个读取分支实际只取目标类型和两个名称。

4. SOURCE-NAMES v2.0

这是源代码中 vtd/share/source.names 使用的格式。一条记录同时给出同一个射电源的多个名称和一组先验坐标。下面是 3C273B 的原始记录。

# SOURCE-NAMES  v 2.0 2005.09.06
3C273B    J1229+0203  1226+023  3C273     C  12_29_06.6997 +02_03_08.598    0.17 ! rfc_2024c
字段 源码读取的列 示例值 用途
IVS 名称 1:8 3C273B 第一个尝试匹配的名称,也是最终保存的 IVS_NAME
J2000 名称 11:20 J1229+0203 保存到 J2000_NAME,不参与这个分支的名称匹配
B1950 名称 23:30 1226+023 第二个尝试匹配的名称
其他名称,本例为 AIPS 名称 33:42 3C273 第三个尝试匹配的名称
赤经、赤纬 46:58、60:72 12_29_06.6997、+02_03_08.598 转换为弧度

需要注意,即使实验数据中给的是 1226+023,程序也能找到这一行,但保存的 IVS_NAME 仍是 3C273B。后续 VTD_SOU_INDEX 按 3C273B 查找这条记录。

5. 2019年版 VLBI 射电源位置星表

格式 4 把 3C273B 和 1226+023 放在同一行。再看使用格式 5 的 vtd/share/glo.src,这两个名称分别出现在相邻的两行中。数据行开头各有 3 个空格。

#  Source position file format  1.0  of 2019.08.08
   3C273B    J1229+0203  12:29:06.699755  +02:03:08.59830     0.170  1  ! rfc_2026a
   1226+023  J1229+0203  12:29:06.74      +02:03:08.3       999.999  0  !  apriori bc191

这个分支用 4:11 的名称匹配 C_SOU,从 14:23 保存 J2000 名称,从 26:40 和 43:57 分别读取赤经、赤纬。两行虽然共用 J1229+0203,VTD 却会根据实验名单选取不同的坐标。名单中给 3C273B 就匹配第一行,给 1226+023 就匹配第二行。

Leonid 经常使用这种格式。下面这份文件保留了表头,可以对照其中的字段说明和实际数据行。

#  Source position file format  1.0  of 2019.08.08
#
#  Generated with update_apr_cat /sol/rfc/rfc_2025b/rfc_2025b_apr.src /tmp/rfc_2025b_cat.txt rfc_2025b /sol/rfc/rfc_2025b/rfc_2025b_aposteriori.src nokeepICRFdef
#
#  EPOCH 2016.01.01
#
#  Last update: 2026.06.24_15:08:15
#
#  Modifications:
#
#  who       when        what
#  L. Petrov 2026.06.24  Upated according to rfc_2026b solution
#
#  Format description
#
#  Byte-by-byte description of file:
#  --------------------------------------------------------------------------------
#  Bytes Format Units    Label     Explanations
#  --------------------------------------------------------------------------------
#   4-11 A8     ---      Name      IVS source name in B1950 IAU notation
#  14-23 A10    ---      Name      RFC source ID   in J2000 IAU notation
#  26-27 I2     h        RAh       Hour of Right Ascension (J2000)
#  28-28 A1     ---      :         Delimiter: colon
#  29-30 I2     m        RAm       Minutes of Right Ascension (J2000)
#  32-41 F10.7  s        RAs       Second  of Right Ascension (J2000)
#  43-43 A1     ---      DE-       Sign of the Declination (J2000): either - or +
#  44-45 I2     deg      DEd       Degree of Declination (J2000)
#  46-46 A1     ---      :         Delimiter: colon
#  47-48 I2     arcmin   DEm       Arcminute  of Declination (J2000)
#  49-49 A1     ---      :         Delimiter: colon
#  50-58 F9.6   arcsec   DEs       Arcsecond  of Declination (J2000)
#  61-67 F7.3   arcsec   SigMaj    Semi-major error ellipse axis in mas
#  70-70 I1     ---      Class     Source class:
#                                                 0 -- non-detected source
#                                                 1 -- detected non-geodetic source
#                                                 2 -- geodetic source
#                                                 3 -- geodetic source candidate
#                                                 9 -- ghost source
#  73-73 A1     ---      !         Delimiter: exclamation sign
#  75-   A      ---      Comm      Comment
#
#  IVS name  RFC ID      Right ascension  Declination         Error  C  !
# -----------------------------------------------------------------------
#
   0000-000  0000-000    00:00:00.00       00:00:00.0       999.999  0  !  J0000-0000 filler
   NOFRINGE  NOFRINGE    00:00:00.00       00:00:00.0       999.999  0  !  NOFRINGE   filler
   GALCENTR  J1745-2900  17:45:40.0360    -29:00:28.167     999.999  0  !  Galactic center
#
   2357+67A  J0000+6810  00:00:01.536     +68:10:02.42      999.999  0  ! apriori BP252AL pri    41.0 mJy   1.5 arcsec
   2357-006  J0000-0021  00:00:01.659837  -00:22:10.02335     2.700  1  !  rfc_2026b

6. 2024年版 VLBI 射电源位置星表

与格式 1 相比,最明显的变化是两个名称的排列顺序反过来了。文件先写 RFC 标识,再写用于匹配的常用名。下面将 3C273B 的坐标按格式 6 重排,只保留 VTD 所需的部分。

# VLBI SOURCE POSITION CATALOGUE  Format version of 2024.10.14
RFC J1229+0203  3C273B    12 29 06.699755 +02 03 08.59830
字段 列位置 示例值
完整 RFC 标识 1:14 RFC J1229+0203
其中保存为 J2000_NAME 的部分 5:14 J1229+0203
常用名,用于匹配并保存为 IVS_NAME 17:24 3C273B
赤经 27:41 12 29 06.699755
赤纬 43:57 +02 03 08.59830

程序把第 29、32、46、49 列的分隔符改成冒号,再转换坐标。完整 RFC 记录后面还可以有位置误差、相关系数、观测数和流量密度等字段,这个读取分支只取名称和坐标。

7. SOURCE-NAMES v3.0

这个格式在同一个文件里允许两类记录。程序先读第 43 列:D 或 F 进入轨道目标分支,其他字符进入普通射电源分支。下面按源码实际读取的列位构造三条示例,后两行的轨道路径是示意路径。

# SOURCE-NAMES  v 3.0 2025.09.06
RFC J1229+0203  3C273B    12 29 06.699755 +02 03 08.59830
N_12345   12345                         E F  /example/orbits/12345.tle
N_23456   23456                         E D  /example/orbits/gnss

第一条是普通射电源。 第 43 列是赤纬的正号 +。程序按格式 6 的布局读取,用 17:24 的 3C273B 匹配源名,用 27:41、43:57 读取赤经、赤纬。这里有一处重要的文档差异:vtd_formats.txt 为 v3 普通源规定的是 1:8 的 IVS 名、46:58 的赤经和 60:72 的赤纬。按文档排出的普通源记录,当前源码可能找不到源,或者从错误的列读取坐标。把格式 4 的 source.names 只换成 v3 的首行,不能完成格式转换。

第二、三条是轨道目标。 它们按以下字段读取。

列位置 含义 第二条示例 第三条示例
1:8 与 C_SOU 匹配的目标名 N_12345 N_23456
11:15 NORAD 编号,空白时设为 0 12345 23456
41 目标类型 E E
43 轨道数据所在位置 F,指定文件 D,指定目录
46: 文件或目录路径 /example/orbits/12345.tle /example/orbits/gnss

对于轨道目标,第 41 列给出目标类型,允许值见下表。第 43 列决定如何检查路径。若为 D,指定的目录必须存在。若为 F,指定的文件必须存在,程序还会检查轨道文件格式。如果是 TLE 文件,程序会核对文件中的 NORAD 编号与星表第 11:15 列是否一致。

类型常量在 vtd_i.templ 中定义:

值 源码定义
S 太阳系内的近场目标
E 地球附近的近场目标
R 射电发射体

三、位置参考历元

前面各例说明了 VTD 怎样从数据行读取源名和坐标。坐标的参考历元则由注释行给出,如格式 5 示例中的 # EPOCH 2016.01.01。程序识别以下三种写法,均取第三个字段作为日期。

# EPOCH 2016.01.01
# EPOCH: 2016.01.01_00:00:00
# Reference_epoch: 2016.01.01_00:00:00

VTD_LOAD_SOUCOO 在开始处理各份星表之前,将参考历元设为 MJD_REF = 51544、TAI_REF = 0。遇到历元行时,程序调用 DATE_TO_TIME 将日期转换成新的 MJD_REF 和 TAI_REF,供后续源记录使用。进入下一份星表时,这两个变量不会重新初始化。因此,若主星表给出了 2016 年的参考历元,而补充星表没有自己的历元行,补充星表中的普通源也会沿用这一历元。组合多份星表时,最好在每份文件的数据行之前明确写出参考历元。普通源的位置记录给出坐标,历元行说明这些坐标对应的参考历元。自行和视差另有来源,由 VTD_LOAD_SOUPRL 读取控制文件中 SOURCE_PRLX_PRP_MOTION: 指定的文件。