Connect other Accounts

PyFITS: FITS files in Python

PyFITS: FITS files in Python

In this article, we provide examples of using the python module PyFITS for working with FITS data. We first go through a brief overview of the FITS standard, and then we describe ways for accessing information in FITS files, using convenience functions defined in PyFITS. PyFITS offers facilities that provide more advanced access to information in FITS files, but these will not be discussed here. Perhaps, a future article will discuss these.

These instructions are based on the PyFITS Handbook (link is to a PDF file), which has exhaustive information on the facilties provided by PyFITS.

A FITS file consists of one or more header and data units, referred to as HDUs. An HDU consists of a header, which describes the data contained in the HDU, followed by the data itself. The first HDU is called the Primary HDU. Other HDUs, if present, are referred to as extensions.

In a valid FITS file the data part of an HDU can be empty. The simplest valid FITS file is one with just the header of the Primary HDU. A FITS file with only the Primary HDU is refered to as a Basic FITS file or a Single Image FITS (SIF) file. A FITS file with extensions is referred to as a Multi-Extension FITS (MEF) file.

A header consists of records, also called card images, each having a maximum of 80 characters. A record contains a keyword with maximum length of 8 characters, an "=" sign at the 9th position, a space at the 10th position, followed by a value for the keyword. A "/" after the value of the keyword indicates the beginning of a commentfor the record and the characters from that point, through the 80th character becomes the comment. The only characters allowed in a header record are ASCII values 32 to 126. A record can be a blank record in which case the entire record will be filled with ASCII space character (ASCII 32). The special keywords HISTORY andCOMMENT, do not use "=" sign and simply uses positions 11 to 80, to store the value.

There is a set of standard keywords, some mandatory and others optional, defined in the FITS standard. Document describing the standard is available from the FITS Support Office. In addition to these there are many non-standard FITS keywords that are used quite frequently. The exact keywords included in an header depends on the type of the data in the data part of the HDU. A list of standard and, non-standard but frequently used, keywords is available athttp://fits.gsfc.nasa.gov/fits_dictionary.html. In addition, "World Coordinate System" (WCS) information is stored in keywords defined in appropriate standards, which are also linked to at the above url.

The value of a header keyword can be of the following types.

String; ascii characters enclosed in single quotes.

Logical; letter T or letter F.

Integers; signed decimal numbers.

Floating point numbers; similar to integers, with E or D denoting the exponent part.

Complex numbers; specified as (real, imag).

The data in an HDU can be an image, which is an array of dimensions 1 to 999, a binary table or an ASCII table. There is another type of data structure called random groups, which is used only in radio interferometry work.

Data can be 8-bit characters, integers (8-bit unsigned, and 16-bit, 32-bit and 64-bit signed integers) and floating point numbers (32-bit and 64-bit). The data type is indicated using the BITPIX keyword, with value set to the number of bits, e.g., 8 for characters and unsigned integers. The values -32 and -64 are used for 32-bit and 64-bit formats, respectively.

An important thing to keep in mind is that the value stored in a data array, the raw value, need not be the actual value representing the physical quantity. If this is so, then the keywords BSCALE and BZERO will have values other than 1.0 and 0.0, respectively. The actual quantity that is being conveyed can be calculated as

physical_value = raw_value * BSCALE + BZERO.

Note

PyFITS will automatically perform this conversion, when it reads in data from a FITS file. The BITPIX value will also be changed to reflect this.

For tables, the corresponding keywords are TSCALEn and TZEROn, where "n" denotes the field, i.e., table column, for which this value is applicable. So we have, 1 <= n <= TFIELDS, where TFIELDS is the number of columns in the table.

The number of "dimensions" for data arrays is specified using the keyword NAXIS. The length of each dimension is specified using the keyword NAXISn where 1 <= n <= NAXIS.

Tables can only appear in extensions and not in Primary HDU and the type of the table will be indicated in the XTENSION keyword of the header of the concerned HDU. If an extension contains image data, i.e., an array, then XTENSION = IMAGE.

For an ASCII table, i.e., XTENSION = TABLE, NAXIS will always be 2. NAXIS1 will be the total number of 8-bit characters in a row, and NAXIS2 will be the number of rows. In FITS a "column" is a position in a row, where as a "field" represents a column in the table. The number of columns in a table, is therefore, given by the value of the keyword TFIELDS.

Binary tables, i.e., XTENSION = BINTABLE, have the same interpretation for NAXIS and NAXIS2. In ASCII tables a value in a particular "cell" will be a scalar. But in a binary table this can be a vector. The value of NAXIS1 for a binary table will take this into account.

PyFITS provides several "convenience" functions that allow the user to work with FITS data, without having to deal with opening and closing files. As mentioned before, there are methods available that provide much finer control over accessing FITS data.

The output shows that the file has two HDUs. The header of the Primary HDU has 262 header records and the data part is a 4x200x200 array, i.e., 4 "pages", 200 rows and 200 columns, of 32 bit floating point numbers. The file has a table extension which has a header of 353 records and the data part has 4 rows and 49 columns. The data format in each column is also given. The total number of 8-bit bytes in one row is 747+49, i.e., 747 bytes indicated by the format strings and one 8-bit separator associated with each column.

Note that while using PyFITS we often refer to the Primary HDU as extension number 0 and the first FITS extension as extension number 1.

To get the header of the first extension we can give a number, indicating the extension, to the getheader function. Here, since the table is the first extension we give the number 1. To get the primary header we can either omit the number or give the number 0.

The shape parameter returns the shape of the array as a tuple of the format (NAXIS3, NAXIS2, NAXIS1) or in general (NAXISn, ..., NAXIS1), where n is the value of the keyword NAXIS. This means that NAXIS1 is the number of columns (x axis), NAXIS2 is the number of rows (y axis) and NAXIS3 is the number of pages (z-axes).

The following illustrates that the "data cube" behaves just like a regular array. Here, numdisplay is used to display the array on DS9. DS9 should be running before calling numdisplay.display.

If data in the HDU is a table then an object similar to a numpy record array is returned. As mentioned before, in FITS, what we call a "table column" is referred to as a "field". A "column" in FITS referes to an 8-bit byte in a row, i.e., a position in a row. Hence a "field" will span a range of "columns".

The methods, add_comment, add_history and add_blank can be used to insert COMMENT, HISTORY and blank keywords, while the get_comment andget_history methods will retrieve a list of COMMENT and HISTORY keywords in the header. One can use the syntax header['COMMENT'] to get the value of a comment, but since a FITS header can contain more than 1 COMMENT and HISTORY keywords, this will only return the first such keyword. The methods to add the above keywords also allow one to specify where the keywords must be inserted.

The code

>>> header_table.add_comment("A new comment", before="median")

will insert a COMMENT key, just before the key MEDIAN. There is a keyword parameter, after, to do the insertion after a specified keyword.

To create a new FITS file with some data and header information we can use the writeto function, providing it with a filename, some data and a header.

>>> pyfits.writeto(filename, data, header)

Example:

>>> pyfits.writeto("WFPC_copy_page_3.fits", data_copy_page_3)

Since a header was not provided, a minimal header will be inserted into the file.

The function append can be used to append an HDU to an already existing FITS file.

>>> pyfits.append(filename, data, header)

The data and header provided will be appended as an HDU extension to the FITS file represented by filename.

Note that in both writeto and append functions, the header is optional. If not given a minimal header will be inserted into the HDU extension.

Tags

To suggest a new feed to our aggregator, fill in the Contact Form on the right !

Contribute to AstroPython

Contributions and feedback from the community are strongly encouraged.If you find a bug or wish to suggest new features for the site , file an issue on Github. If you simply have a question or comment for the AstroPython team please fill in this form and we'll get back to you as soon as possible.
If you have a new resource, question, or any other content that you'd like to post to the web site then likewise fill in the creation form. If you wish to have elevated priveleges , you can use the form to contact us.

Feedback | Contribute | Contact

We would love to hear from you but please login to access the Contact Form !

About Us : Team AstroPython

Tom Aldcroft is a Science
Operations Team member and Flight Director for the Chandra X-ray Observatory and works at the Smithsonian Astrophysical
Observatory. He uses Python for Chandra
spacecraft operations analysis as well as research on several X-ray
survey projects. He is the author of the
asciitable,
cosmocalc, and
deproject
packages. He is also
interested in Python for the web and writes Django and Google App Engine applications
for presenting large multi-wavelength survey datasets. He has been the primary mentor for AstroPython

Thomas Robitaille is a Spitzer
postdoctoral fellow at the Harvard-Smithsonian Center for Astrophysics. He works on
studying Galactic star formation, mostly through mid-infrared to mm
wavelengths. This includes modeling multi-wavelength observations of young
stars and studying the global properties of star formation in the
Milky-Way. In his spare time he is a keen Python programmer and is one of
the co-developers of the APLpy and
ATpy packages. He also developed
the IDLSave package.He has been the secondary mentor for the project.

Aman Jhunjhunwala is an undergraduate Computer Science student with a passion for Big Data,Machine Learning and Web technologies. He has been the primary developer of this site as a part of Google Summer of Code-2015 programme under the AstroPy project.