FITS_rec和选择数据:屏蔽而不是"true"过滤?



可能与Ashley的帖子重复(但我还不能发表评论;)。

当我试图将列添加到我的初始FITS_rec的子选择/样本中时,我也遇到了同样的问题(基于numpyrecarray);所有的行都重新出现了(而且这个新列的填充似乎没有得到尊重…)。Vlas Sokolov提出的">hdu_sliced._get_raw_data()"是一个对我来说非常有效的解决方案,但我想知道:

1) Iguananaut提出了哪些"更好的方法"?我当然需要有人帮我搜索一下;新手我感觉被卡住了:$(需要住在FITS_rec)。

2) 这是意料之中的行为吗?意思是,我们真的想研究一个"屏蔽数组"吗?它是我们原始数组的副本?最让我担心的是新计算列中的值的"崩溃"。见下文:

# A nice FITS_rec
a1 = np.array(['NGC1001', 'NGC1002', 'NGC1003'])
a2 = np.array([11.1, 12.3, 15.2])
col1 = fits.Column(name='target', format='20A', array=a1)
col2 = fits.Column(name='V_mag', format='E', array=a2)
cols = fits.ColDefs([col1, col2])
hdu = fits.BinTableHDU.from_columns(cols)
ori_rec=hdu.data
ori_rec
`

FITS_rec([(‘NGC101’,11.1),(‘NGC102’,12.3),(’NGC103’,15.2)],dtype=(numpy.record,[('target','S20'),('V_mag','

# Sub-selection
bug=ori_rec[ori_rec["V_mag"]>12.]
bug

FITS_rec([(‘NGC102',12.3),(‘NGC103',15.2)],dtype=(numpy.record,[('target','S20'),('V_mag','

到目前为止还不错…

# Let's add a new column
col0=bug.columns
col1 =fits.ColDefs([fits.Column(name='new',format='D',array=bug.field("V_mag")+1.)])
newbug = fits.BinTableHDU.from_columns(col0 + col1).data

FITS_rec([(‘NGC101’,11.113.30000019),(‘NGC102’,12.316.20000076),('nc1003',15.2,0.)],dtype=(numpy.record,[('target','S20'),('V_mag','

…AND…NGC102和NGC103的新列的值是正确的,但分别在NGC101和NGC102的行中…:|

任何启示都将受到欢迎:)

这是一个令人困惑的问题,它源于astropy.io.fits中有许多层遗留类和数据结构(源于PyFITS的早期版本)。例如,在您的示例中,您可以看到hdu.data是一个FITS_rec对象,它类似于Numpy recarray(本身是一个软弃用的遗留类),但它也有.columns属性(正如您所指出的):

>>> bug.columns
ColDefs(
name = 'target'; format = '20A'
name = 'V_mag'; format = 'E'
)

这反过来实际上保留了对原始数组的引用,您从中描述了列。例如:

>>> bug.columns['target'].array
chararray(['NGC1001', 'NGC1002', 'NGC1003'],
dtype='|S20')

您可以在这里看到,即使bug是原始表的"切片",通过bug.columns引用的数组仍然包含原始的、未切片的数组数据。所以当你做一些像在你的原始后

>>> col0 = bug.columns
>>> col1 = fits.ColDefs([fits.Column(name='new',format='D',array=bug.field("V_mag")+1.)])

它在这里尽了最大努力来弄清楚意图,但这里的col0已经不知道bug是原始表的一部分了,它只有原始的"coldefs"和完整的列可以依赖。

这些类中的大多数,包括FITS_recColumn,尤其是ColDefs,几乎不再需要直接使用。不幸的是,并不是所有的文档都更新了以反映这一事实,还有很多旧的教程和示例代码显示了这些类的用法。没有一个具备必要专业知识的人能够花时间更新文档并澄清这一点。

有时,如果您已经在一个单独的数组中拥有每列的列数据,并且您希望从中构建一个表,并为表列提供一些特定的FITS属性,那么Column会很有用。但我已经重新设计了API的大部分内容,这样您就可以获得像Numpy数组这样的原生Python数据结构,并将它们保存到FITS文件中,而在许多情况下,不必担心FITS是如何实现的细节或像FITS数据格式代码这样令人讨厌的事情。

这项工作有点不完整,因为如果你想从一些列式数组中定义一个FITS表,你仍然需要使用Column类,并指定一个最小的FITS格式(但你永远不需要直接使用ColDefs):

>>> hdu = fits.BinTableHDU.from_columns([fits.Column(name='target', format='20A', array=a1), fits.Column(name='V_mag', format='E', array=a2)])
>>> hdu.data
FITS_rec([('NGC1001', 11.1), ('NGC1002', 12.3), ('NGC1003', 15.2)],
dtype=(numpy.record, [('target', 'S20'), ('V_mag', '<f4')]))

然而,你也可以直接使用Numpy结构化数组,我个人通常觉得这更简单,因为它可以让你忽略大多数FITS主义,只关注你的数据,对于那些微调FITS特定内容并不重要的情况。例如,要为数据定义一个结构化数组,有几种方法可以实现,但您可以尝试:

>>> nrows = 3
>>> data = np.empty(nrows, dtype=[('target', 'S20'), ('V_mag', np.float32)])
>>> data['target'] = a1
>>> data['V_mag'] = a2
>>> data
array([('NGC1001', 11.100000381469727), ('NGC1002', 12.300000190734863),
('NGC1003', 15.199999809265137)],
dtype=[('target', 'S20'), ('V_mag', '<f4')])

然后你可以直接从这个数组实例化一个BinTableHDU

>>> hdu = fits.BinTableHDU(data)
>>> hdu.data
FITS_rec([('NGC1001', 11.1), ('NGC1002', 12.3), ('NGC1003', 15.2)],
dtype=(numpy.record, [('target', 'S20'), ('V_mag', '<f4')]))
>>> hdu.header
XTENSION= 'BINTABLE'           / binary table extension
BITPIX  =                    8 / array data type
NAXIS   =                    2 / number of array dimensions
NAXIS1  =                   24 / length of dimension 1
NAXIS2  =                    3 / length of dimension 2
PCOUNT  =                    0 / number of group parameters
GCOUNT  =                    1 / number of groups
TFIELDS =                    2 / number of table fields
TTYPE1  = 'target  '
TFORM1  = '20A     '
TTYPE2  = 'V_mag   '
TFORM2  = 'E       '

同样,当涉及到屏蔽、切片和添加新列时,直接使用本地Numpy数据结构是最好的。

或者,正如其他问题的答案中所建议的那样,使用AstropyTableAPI,如果你能帮上忙的话,就不要搞低级别的FITS。因为正如我所讨论的,它包含了几层遗留接口,这些接口会让人感到困惑(长期的问题可能应该清理掉,但很难做到,因为以某种方式使用它们的代码是普遍的)。API表是从一开始就设计的,目的是使表操作(包括屏蔽行和添加列)相对容易。而旧的PyFITS API从未完全适用于许多简单的情况。

我希望这个答案是有启发性的——我知道它可能有点长,有点令人困惑。如果有什么具体的事情我可以澄清,请告诉我。

最新更新