r'''
A collection of small utilities to interface with ``pyfits``.
'''
import pyfits
[docs]def read_header(fits_name):
r'''
Read only the header in FITS file ``fits_name``.
**Parameters**
fits_name: string
File name from which to read the header.
**Returns**
A pyfits.Header instance.
**Raises**
OSError: If ``fits_name`` cannot be opened.
**Example**
>>> print(read_header('testdata/Q_Fthinsource.fits')
SIMPLE = T / Written by IDL: Tue Sep 28 22:42:54 2010
BITPIX = -32 / Number of bits per data pixel
NAXIS = 3 / Number of data axes
NAXIS1 = 100 /
NAXIS2 = 100 /
NAXIS3 = 100 /
DATE = '2010-09-28' / Creation UTC (CCCC-MM-DD) date of FITS header
COMMENT FITS (Flexible Image Transport System) format is defined in 'Astronomy
COMMENT and Astrophysics', volume 376, page 359; bibcode 2001A&A...376..359H
CTYPE1 = 'X ' /
CRVAL1 = 0 /
CDELT1 = 1.30000E+06 /
CRPIX1 = 0 /
CUNIT1 = 'Hz ' /
CTYPE2 = 'Y ' /
CRVAL2 = 0 /
CRVAL3 = 1.10000E+08 /
POL = 'Q ' /
>>> print(read_header('testdata/non-existent.fits')
ERROR: An unexpected error occurred while tokenizing input
The following traceback may be corrupted or invalid
The error message is: ('EOF in multi-line statement', (11, 0))
ERROR: An unexpected error occurred while tokenizing input
The following traceback may be corrupted or invalid
The error message is: ('EOF in multi-line statement', (285, 0))
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
...
IOError: [Errno 2] No such file or directory: 'testdata/non-existent.fits'
'''
hdulist = pyfits.open(fits_name)
header = hdulist[0].header
hdulist.close()
return header
[docs]def get_fits_data_start_and_size(fits_name):
"""
Return the first byte of the data of the first HDU in the file,
followed by the length of the data block, including padding, in
bytes.
"""
hdulist = pyfits.open(fits_name)
info = hdulist.fileinfo(0)
hdulist.close()
return info['datLoc'], info['datSpan']
[docs]def get_fits_header_data(fits_name):
"""
Return a (header, data) tuple of the first Header Data Unit (HDU)
of the FITS file with name *fits_name*. May raise an OSError if the
file cannot be opened.
"""
hdulist = pyfits.open(fits_name)
header = hdulist[0].header
data = hdulist[0].data
hdulist.close()
return header, data
[docs]def fits_image_frames(fits_name):
"""
An iterator over a FITS image cube:
for frame in fits_image_frames('example.fits'):
print frame.shape, frame.max()
"""
header = get_fits_header(fits_name)
dtype = pyfits.hdu.PrimaryHDU.NumCode[header['BITPIX']]
shape = (header['NAXIS2'], header['NAXIS1'])
frame_size = product(shape)*abs(header['BITPIX']/8)
data_start, data_length = get_fits_data_start_and_size(fits_name)
file_stream = open(fits_name, mode='rb')
file_stream.seek(data_start)
try:
while file_stream.tell() +frame_size < data_start + data_length:
frame = fromfile(file_stream,
count = product(shape),
dtype = dtype).reshape(shape)
if sys.byteorder == 'little':
yield frame.byteswap()
else:
yield frame
finally:
file_stream.close()
[docs]def fits_write_header(fits_name, fits_header, force_overwrite):
r'''
Write only the header (including padding) to file ``fits_name``
'''
header_lines = [str(card) for card in fits_header.ascardlist()]
padding = 'END'+' '*77+' '*80*(36 - ((len(header_lines) + 1) % 36))
if force_overwrite or not os.path.exists(fits_name):
out_file = open(fits_name, 'w')
for line in header_lines:
out_file.write(line)
out_file.write(padding)
return out_file
[docs]def fits_write_partial_cube(file_stream, cube):
r'''
'''
if sys.byteorder == 'little':
cube.byteswap().tofile(file_stream)
else:
cube.tofile(file_stream)
[docs]def fits_padding(shape, bytes_per_sample):
r'''
'''
last_chunk = (product(shape)*bytes_per_sample) % 2880
if last_chunk == 0:
return zeros((0), dtype = uint8)
else:
return zeros((2880 - last_chunk), dtype = uint8)