如何调整 astropy.io.fits BinTableHDU 中列的大小

How to resize a column in a astropy.io.fits BinTableHDU

我试图在创建 FITS BinTableHDU 列后调整列的大小,但我似乎无法在 astropy 文档中找到执行此操作的方法。

例如,假设使用包含长度为 3 的单列的 BinTableHDU 创建了一个简单的拟合文件:

from astropy.io import fits
from astropy.table import Table
import numpy as np

hdul = fits.HDUList()
hdul.append(fits.PrimaryHDU())
data = Table({'test':[42,42,42]})
hdul.append(fits.BinTableHDU(data))

hdul.writeto('test.fits', overwrite=True)

稍后,我想重新打开文件,更改列并将其保存到新文件中:

hdul = fits.open('test.fits')
hdul[1].data['test'] = np.array([27, 27])
hdul.writeto('new_test.fits', overwrite=True)

我希望通过用新的 numpy 数组实例替换该列,它会覆盖旧的。但是我收到以下错误:

ValueError: could not broadcast input array from shape (2,) into shape (3,)

考虑到尺寸差异,这个错误并不奇怪,但我正在寻找一种方法来完全替换该列,或者以其他方式改变其形状。

注意事项,该列的类型为numpy.ndarray:

col_data = hdul[1].data['test']
print(type(col_data))
print(col_data)

显示:

<class 'numpy.ndarray'>
[42 42 42]

但是,调整数组大小的常用方法似乎不起作用:

hdul[1].data['test'].resize((2,))

投掷:

ValueError: cannot resize this array: it does not own its data

其他奇怪的行为。如果我尝试用单个元素数组替换它,而不是抛出错误,它会用标量替换每个元素:

hdul[1].data['test'] = np.array([27])
print(col_data)

显示:

[27 27 27]

我意识到有人可能会指出我应该在创建列时更改其原始尺寸。但在我的特定用例中,我需要在创建 BinTableHDU 后对其进行修改。这就是我要在这里完成的。

更新 FITS 文件中不同大小的二进制 table 数据的简便方法

在问题示例中,只有一个 table 列需要更新,并且大小不同。 Table class 有一个 replace_column 函数来帮助解决这个问题。

hdul = fits.open('test.fits')
table = Table(hdul[1].data)
table.replace_column('test', [27, 27])
hdul[1] = fits.BinTableHDU(table)
hdul.writeto('new_test.fits', overwrite=True)

但是,如果涉及到多列,这就有点复杂了。在 astropy 实现的标准 BinTableHDU 中,所有列的大小必须相同。为了使用可变长度的列,必须使用特殊的特殊关键字。请参阅 astropy 教程 here。也就是说,只要用相同大小的数组替换列,上面的代码就可以了。

当用单个元素数组替换元素时,它不会抛出错误,而是用标量替换每个元素。

上面说到astropy支持的FITSBinaryTable的标准类型是non-variable长度。因此,为方便起见,astropy 实现了一种行为,即向数组广播标量。虽然广播对于单个列 table 来说似乎不是正确的行为,但我的猜测是这种行为会覆盖预期的行为。请参阅 quick overview 中的 table 个示例。 “可以使用向字典添加 key-value 对等语法将单个列添加到 table。右侧的值可以是列表或 numpy.ndarray 的正确大小,或将被广播的标量值