适合页眉#
在接下来的三章中,我们将分别解释处理FITS头、图像/数组数据和表数据的更详细信息,包括示例。
HDU的标头#
每个报头数据单元(HDU)通常有两个组件:报头和数据。在 astropy
这两个组件通过HDU的两个属性访问, hdu.header
和 hdu.data
.
而HDU可能有空数据(即 .data
属性是 None
),任何HDU都将始终具有标头。使用构造函数创建HDU时(例如。, hdu = PrimaryHDU(data, header)
),用户可以从现有HDU的报头提供报头值,并从 numpy
数组。如果使用默认值(无),则新的HDU将具有该类型HDU所需的最少关键字:
>>> from astropy.io import fits
>>> hdu = fits.PrimaryHDU()
>>> hdu.header # show the all of the header cards
SIMPLE = T / conforms to FITS standard
BITPIX = 8 / array data type
NAXIS = 0 / number of array dimensions
EXTEND = T
用户可以使用任何头和任何数据来构造新的HDU。 astropy
将删除所有描述数据结构的关键字,只留下信息性关键字。稍后,它将重新添加所需的结构关键字,以便与新的HDU和添加到其中的任何数据兼容。因此,用户可以使用表HDU的头来构造图像HDU,反之亦然。构造函数还将确保头中的数据类型和维度信息与数据一致。
Header属性#
价值访问、更新和创建#
如图所示 Getting Started 教程中,关键字值可以通过HDU头属性的关键字名称或索引访问。您也可以使用通配符 *
以获取与搜索字符串匹配的关键字-值对。下面是一个简短的总结:
>>> fits_image_filename = fits.util.get_testdata_filepath('test0.fits')
>>> hdul = fits.open(fits_image_filename) # open a FITS file
>>> hdr = hdul[0].header # the primary HDU header
>>> print(hdr[34]) # get the 2nd keyword's value
96
>>> hdr[34] = 20 # change its value
>>> hdr['DARKCORR'] # get the value of the keyword 'darkcorr'
'OMIT'
>>> hdr['DARKCOR*'] # get keyword values using wildcard matching
DARKCORR= 'OMIT ' / Do dark correction: PERFORM, OMIT, COMPLETE
>>> hdr['darkcorr'] = 'PERFORM' # change darkcorr's value
关键字名称不区分大小写,但在一些特殊情况下除外(请参阅有关层次卡和记录值卡的部分)。因此, hdr['abc']
, hdr['ABC']
或 hdr['aBc']
都是等价的。
和Python的一样 dict
类型,也可以使用赋值语法将新关键字添加到标头中:
>>> hdr = hdul[1].header
>>> 'DARKCORR' in hdr # Check for existence
False
>>> hdr['DARKCORR'] = 'OMIT' # Add a new DARKCORR keyword
也可以添加新值 and 通过将它们指定为元组进行注释::
>>> hdr['DARKCORR'] = ('OMIT', 'Dark Image Subtraction')
备注
在向标题中添加新关键字时,需要注意的一点是,默认情况下不会附加关键字 立即 直到文件的结尾。相反,它们被附加到最后一个非注释关键字之后。这是为了支持始终将所有历史关键字组合在一起的常见用例。一个新的非注释关键字将添加到现有关键字的末尾,但在标题末尾的任何历史/注释关键字之前。
有几种方法可以覆盖此功能:
使用
Header.append()
方法与end=True
论点:>>> hdr.append(('DARKCORR', 'OMIT', 'Dark Image Subtraction'), end=True)
这将强制在标头的实际结尾添加新关键字。
这个
Header.insert()
方法将始终在您要求的位置插入新关键字:>>> del hdr['DARKCORR'] # Delete previous insertion for doctest >>> hdr.insert(20, ('DARKCORR', 'OMIT', 'Dark Image Subtraction'))
这将在头中的第20个关键字之前插入DARKCORR关键字,而不管它是什么。
可以使用相同的索引/名称语法删除关键字(及其对应的卡片):
>>> del hdr[3] # delete the 2nd keyword
>>> del hdr['DARKCORR'] # delete the value of the keyword 'DARKCORR'
注意,与常规Python列表一样,索引在每次删除后都会更新,因此如果 del hdr[3]
连续执行两次时,第四个和第五个关键字将从原始标题中删除。同样, del hdr[-1]
将删除页眉中的最后一张卡。
也可以使用slice语法删除整个卡片范围:
>>> del hdr[3:5]
方法 Header.set()
是更新与现有关键字关联的值或注释或创建新关键字的另一种方法。它的大部分功能可以用上面所示的dict类语法复制。但在某些情况下,情况可能会更清楚。它还有一个优点,允许用户在标题中移动卡片,或者指定新卡片相对于现有卡片的位置:
>>> hdr.set('target', 'NGC1234', 'target name')
>>> # place the next new keyword before the 'TARGET' keyword
>>> hdr.set('newkey', 666, before='TARGET') # comment is optional
>>> # place the next new keyword after the 21st keyword
>>> hdr.set('newkey2', 42.0, 'another new key', after=20)
在FITS标题中,每个关键字也可能有一个与之相关联的注释来解释其用途。与每个关键字关联的注释通过 comments
属性:
>>> hdr['NAXIS']
2
>>> hdr.comments['NAXIS']
'number of data axes'
>>> hdr.comments['NAXIS'] = 'The number of image axes' # Update
>>> hdul.close() # close the HDUList again
可以通过与访问值相同的所有方式访问注释,无论是通过关键字名称还是卡片索引。切片也是可能的。唯一的区别是你要经历 hdr.comments
与其只是 hdr
单打独斗。
未定义的值#
FITS头可以有未定义的值,这些值在Python中用特殊值表示 None
. None
在将值赋给 Header
或 Card
.
>>> hdr = fits.Header()
>>> hdr['UNDEF'] = None
>>> hdr['UNDEF'] is None
True
>>> repr(hdr)
'UNDEF = '
>>> hdr.append('UNDEF2')
>>> hdr['UNDEF2'] is None
True
>>> hdr.append(('UNDEF3', None, 'Undefined value'))
>>> str(hdr.cards[-1])
'UNDEF3 = / Undefined value '
卡片图像#
FITS标题由卡片图像组成。
FITS标题中的卡片图像由关键字名称、值和可选的注释组成。从物理上讲,在FITS文件的存储格式中,它需要80列(字节)-不带回车符。在 astropy
,每个卡片图像都由 Card
对象。还有一些特殊种类的卡片:评论卡片(见上文)和卡片图像,它可以拍摄超过一张80列的卡片图像。后者将在稍后讨论。
大多数时候处理卡片的细节是由 Header
对象,而不必直接操作卡片。事实上,大多数 Header
接受 (keyword, value)
或 (keyword, value, comment)
元组作为参数也可以使用 Card
对象作为参数。 Card
对象只是围绕这样的元组的包装器,这些元组提供解析和格式化头中单个卡的逻辑。手动使用 Card
对象,但在实际将卡添加到标头之前检查它在标头中的显示方式。
创建一个新的Card对象 Card
构造函数: Card(key, value, comment)
.
例子#
要创建新的卡片对象:
>>> c1 = fits.Card('TEMP', 80.0, 'temperature, floating value')
>>> c2 = fits.Card('DETECTOR', 1) # comment is optional
>>> c3 = fits.Card('MIR_REVR', True,
... 'mirror reversed? Boolean value')
>>> c4 = fits.Card('ABC', 2+3j, 'complex value')
>>> c5 = fits.Card('OBSERVER', 'Hubble', 'string value')
>>> print(c1); print(c2); print(c3); print(c4); print(c5) # show the cards
TEMP = 80.0 / temperature, floating value
DETECTOR= 1
MIR_REVR= T / mirror reversed? Boolean value
ABC = (2.0, 3.0) / complex value
OBSERVER= 'Hubble ' / string value
卡片有属性 .keyword
, .value
和 .comment
.两者都是 .value
和 .comment
可以改变但不能改变 .keyword
属性。换句话说,一旦创建了一张卡,它就为一个特定的、不可变的关键字创建。
这个 Card()
构造器将检查给定的参数是否符合FITS标准并且具有固定的卡片图像格式。如果用户想要创建一个自定义格式的卡,甚至是一个不符合FITS标准的卡(例如,出于测试目的),则 Card.fromstring()
可以使用类方法。
卡片可以用 Card.verify()
. 非标准卡片 c2
在下面的例子中,通过这样的验证来标记。有关验证的详细信息 astropy
将在后面的章节中讨论。
>>> c1 = fits.Card.fromstring('ABC = 3.456D023')
>>> c2 = fits.Card.fromstring("P.I. ='Hubble'")
>>> print(c1)
ABC = 3.456D023
>>> print(c2)
P.I. ='Hubble'
>>> c2.verify()
Output verification result:
Unfixable error: Illegal keyword name 'P.I.'
一份清单 Card
对象 Header
对象可以通过 Header.cards
属性。不应该仅仅是为了观察而被操纵。事实上,它只是一个拷贝-对它的修改不会影响它来自的头。使用 Header
改为类。
连续卡片#
事实上,FITS标准只允许最多8个字符作为关键字名称,80个字符可以包含关键字、值和注释,这对某些应用程序是有限制的。为了允许关键字使用长字符串值,提出了一个建议:
在包含关键字的常规80列之后使用CONTINUE关键字。 astropy
支持此约定,这是自4.0版以来的FITS标准的一部分。
实例#
下面的示例显示,对于长字符串值,CONTINUE是自动使用的:
>>> hdr = fits.Header()
>>> hdr['abc'] = 'abcdefg' * 20
>>> hdr
ABC = 'abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcd&'
CONTINUE 'efgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefga&'
CONTINUE 'bcdefg'
>>> hdr['abc']
'abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg'
>>> # both value and comments are long
>>> hdr['abc'] = ('abcdefg' * 10, 'abcdefg' * 10)
>>> hdr
ABC = 'abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcd&'
CONTINUE 'efg&'
CONTINUE '&' / abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefga
CONTINUE '' / bcdefg
请注意,当使用CONTINUE卡时,在每个80个字符的卡片图像的末尾,会出现一个与号。和号不是字符串值的一部分。此外,在CONTINUE之后的第九列没有“=”。在第一个示例中,整个240个字符由 astropy
作为一张卡片。因此,如果它是标题中的第n张卡片,(n+1)第张卡片指的是下一个关键字,而不是下一张CONTINUE卡片。因此,CONTINUE卡由 astropy
作为一个单一的逻辑卡,一般不必担心格式的细节。可以像常规关键字一样访问和更新解析为一组CONTINUE卡片的关键字。
等级卡#
对于长度超过8个字符的关键字,欧洲南方天文台(ESO)制定了一个惯例,以便于使用。它使用一个特殊的关键字层次结构,后面是实际的长关键字。 astropy
也支持这项公约。
如果关键字包含八个以上的字符 astropy
将自动使用分层卡,但也会发出警告,以防出错。但是,您可以通过在关键字前面加上“HIERARCH”来显式地请求层次结构卡(就像它将出现在标题中一样)。例如, hdr['HIERARCH abcdefghi']
将创建关键字 abcdefghi
没有显示警告。创建后,可以像访问其他关键字一样访问层次结构关键字: hdr['abcdefghi']
,而不在关键字前面添加“HIERARCH”。
实例#
astropy
当关键字包含超过八个字符时,将使用分层卡并发出警告:
>>> # this will result in a Warning because a HIERARCH card is implicitly created
>>> c = fits.Card('abcdefghi', 10)
>>> print(c)
HIERARCH abcdefghi = 10
>>> c = fits.Card('hierarch abcdefghi', 10)
>>> print(c)
HIERARCH abcdefghi = 10
>>> hdu = fits.PrimaryHDU()
>>> hdu.header['hierarch abcdefghi'] = 99
>>> hdu.header['abcdefghi']
99
>>> hdu.header['abcdefghi'] = 10
>>> hdu.header['abcdefghi']
10
>>> hdu.header
SIMPLE = T / conforms to FITS standard
BITPIX = 8 / array data type
NAXIS = 0 / number of array dimensions
EXTEND = T
HIERARCH abcdefghi = 10
备注
关于 Header
类的大部分设计都是为了抽象出有关FITS格式的怪癖。这就是为什么,例如,它会自动创建CONTINUE和HIERARCH卡。头只是一个数据结构,作为用户,您不必担心它最终如何被序列化为FITS文件中的头。
尽管有些地方几乎不可能隐藏FITS格式的怪癖, astropy
试着让你尽量少去想它。如果有任何地方是模糊的或难以理解的头部是如何构造的,请让我们知道,因为可能有一些领域可以改进,甚至更多。
注释、历史记录和空白关键字#
FITS标题中的大多数关键字都有唯一的名称。如果有两个以上的卡共享同一个名称,则当按名称引用时,它是第一个被访问的卡。副本只能通过数字索引访问。
有三个特殊的关键字(它们的关联卡片有时被称为评论卡片),它们通常会出现在FITS标题中多次。它们是(1)空白关键字,(2)历史,(3)注释。与其他关键字不同,当访问这些关键字时,它们以列表形式返回:
这些列表可以像其他列表一样进行切片。例如,要只显示最后一个历史条目,请使用
hdr['history'][-1]
. 现有的评论卡也可以通过使用该卡的适当索引号进行更新。通过使用dict-like关键字赋值语法,或使用
Header.set()
我是说。但是,与其他关键字不同,新的评论卡总是添加并附加到最后一个注释卡中,该卡片具有相同的关键字,而不是在标题的末尾。例子#
添加新的评论卡:
修改后的标题中的部分变为:
用户还可以使用
Header.insert()
方法。备注
讽刺的是,评论卡中没有注释,只有字符串值。