使用 CFITSIO 库从 FITS table 读取可变长度数组

Reading variable-length arrays from a FITS table using the CFITSIO library

我很难使用 CFITSIO 库从 FITS table 的条目中读取可变长度数组(由于我正在开发的另一个软件,我必须使用它们)。

现在,我尝试阅读的 FITS table 看起来像这样:

如您所见,最后三列的单元格中没有标量值,而是包含可变长度数组。

CFITSIO 文档对这种特殊情况不是很有帮助:大多数基本例程被认为是通过直接读取常规列来生成数组(在它们的单元格中带有标量,请参阅 [=18 的第 2 节) =]). fits_read_col 不适用于此数据结构。

现在建议在读取变量列时使用fits_read_descript例程。问题在于此函数 returns 低级信息,特别是存储数组的堆中的起始偏移量(请参阅 https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/node82.html 的第 7 节)。 因此,即使我获得了包含多个数组的单元格的低级信息,也不清楚如何使用它来获取数值!

CFITSIO Iterators略有帮助,没有这么复杂的数据结构的例子。

以前有人做过吗?是否有人能够使用 CFITSIO 生成片段来读取可变长度数组?这将非常有帮助。

可以找到我截图的FITS文件here

这里是打开文件并检查列和行的暂定片段,对可变长度列应用建议的 fits_read_descript 函数。我不知道如何进一步进行,因为我不知道如何利用返回的参数来获取 table.

中的实际数值
#include "fitsio.h"
#include <iostream>

int main(){

    fitsfile *fp = 0; // pointer to fitsfile type provided in CFITSIO library
    int status = 0; // variable passed down to different CFITSIO functions 

    // open the fits file, go to the Header Data Unit 1 containing the table 
    // with variable-length arrays
    fits_open_file(&fp, "rmf_obs5029747.fits[1]", READONLY, &status);

    // read HDU type
    int hdutype;
    fits_get_hdu_type(fp, &hdutype, &status);
    std::cout << "found type " << hdutype << " HDU type." << "\n";

    // read number of rows and columns
    long nTableRows;
    int  nTableCols;
    fits_get_num_rows(fp, &nTableRows, &status);
    fits_get_num_cols(fp, &nTableCols, &status);
    std::cout << "the table has " << nTableRows << " rows" << "\n";
    std::cout << "the table has " << nTableCols << " columns" << "\n";

    // loop through the columns and consider only those with a negative typecode
    // indicating that they contain a variable-length array
    // https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/node29.html
    int typecode;
    long repeat;
    long width; 
    long offset;

    for (int colnum = 0; colnum < nTableCols; ++colnum) {
        fits_get_coltype(fp, colnum+1, &typecode, &repeat, &width, &status);
        if (typecode < 1) {
            std::cout << "->column " << colnum << " contains a variable-length array" << "\n"; 
            std::cout << "->examining its rows..." << "\n";
            // loop through the rows
            for (int rownum = 0; rownum < nTableRows; ++rownum)
                fits_read_descript(fp, colnum, rownum, &repeat, &offset, &status);
        }
    }
}

只是想一想,您可能已经 this/thought 看到了这方面的内容,但以防万一您还没有看到。

fits_get_col_display_width() = 了解可用字符数

如果fits_read_descript()给出了数组中的元素个数和起始偏移量,是否可以将总字节数读入字符串并用分隔符“,”分词得到数字?

FITS中有很多奇怪的特例,你找到了其中的一个。

我已经成功使用了这个。

  1. 调用 fits_read_descript{s}{ll}() 以确定相关行的重复和偏移量。您还可以使用 descripts 变体一次确定多行的重复和偏移量。
  2. 调用fits_read_col{null}()读取数据,一次一行。元素的数量是您从步骤 1 中找到的重复计数,或者如果您想要一个子集,则更少。像往常一样设置列、行号和第一个元素。使用 null 变体效果很好。

重要的是你一次只能读取一行这样的可变长度数据,但它省去了你做所有字节解码和堆索引的麻烦。即使您使用 fits_read_descripts() 变体来确定一次函数调用中的多次重复计数,您仍然必须为您感兴趣的每个 table 行调用一次 fits_read_col()。

阅读可变长度字符串或位数组本身就是一种有趣的消遣,但您看起来只是想阅读 X 射线响应矩阵数据(浮点数),所以这应该可以回答您的问题。

感谢@lorenz 和@CraigM 的建议。

其实我在ROOT class interfacing with the CFITSIO library找到了解决方案并实现了,所以如果其他人有同样的问题可以复制解决方案或者直接ROOT。 我介绍的在ROOT中读取一个变长单元格的函数是: TFITSHDU::GetTabVarLengthVectorCell()

我一年前做过,忘了 post 这里的答案:)

您可以找到解决方案的代码 here

我实际上使用了你提出的@CraigM 方案,即结合 fits_read_descriptfits_read_col