Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
43 views
Kernel: Python 2

Astropy: Handling FITS files

%matplotlib inline import numpy as np import matplotlib.pyplot as plt

Documentation

For more information about the features presented below, you can read the astropy.io.fits docs.

Data

The data used in this page is a model of the gamma-ray sky background used for the LAT instrument on the Fermi telescope, as well as the Fermi/LAT point source catalog.

Reading FITS files and accessing data

Opening a FITS file is relatively straightforward. We can open the background model included in the tutorial files:

from astropy.io import fits
hdulist = fits.open('data/gll_iem_v02_P6_V11_DIFFUSE.fit')

The returned object, hdulist, behaves like a Python list, and each element maps to a Header-Data Unit (HDU) in the FITS file. You can view more information about the FITS file with:

hdulist.info()

As we can see, this file contains two HDUs. To access the primary HDU, which contains the main data, you can then do:

hdu = hdulist[0]

The hdu object then has two important attributes: data, which behaves like a Numpy array, can be used to access the data, and header, which behaves like a dictionary, can be used to access the header information. First, we can take a look at the data:

hdu.data.shape

This tells us that it is a 3-d cube. We can now take a peak at the header:

hdu.header

which shows that this is a Plate Carrée (-CAR) projection in Galactic Coordinates, and the third axis is photon energy. We can access individual header keywords using standard item notation:

hdu.header['TELESCOP']
hdu.header['INSTRUME']

Provided that we started up ipython with the --pylab flag, we can plot one of the slices in photon energy:

plt.imshow(hdu.data[0,:,:], origin='lower')

Note that this is just a plot of an array, so the coordinates are just pixel coordinates at this stage. The data is stored with longitude increasing to the right (the opposite of the normal convention), but the Level 3 problem at the bottom of this page shows how to correctly flip the image.

Modifying data or header information in a FITS file object is easy. We can update existing header keywords:

hdu.header['TELESCOP'] = "Fermi Gamma-ray Space Telescope"

or add new ones:

hdu.header['MODIFIED'] = '21 Nov 2013' # adds a new keyword

and we can also change the data, for example extracting only the first slice in photon energy:

hdu.data = hdu.data[0,:,:]

Note that this does not change the original FITS file, simply the FITS file object in memory. Since the data is now 2-dimensional, we can remove the WCS keywords for the third dimension:

hdu.header.remove('CRPIX3') hdu.header.remove('CRVAL3') hdu.header.remove('CDELT3') hdu.header.remove('CUNIT3') hdu.header.remove('CTYPE3')

You can write the FITS file object to a file with:

hdu.writeto('lat_background_model_slice.fits', clobber=True)

if you want to simply write out this HDU to a file, or:

hdulist.writeto('lat_background_model_slice_allhdus.fits', clobber=True)

if you want to write out all of the original HDUs, including the modified one, to a file.

Creating a FITS file from scratch

If you want to create a FITS file from scratch, you need to start off by creating an HDU object:

hdu = fits.PrimaryHDU()

and you can then populate the data and header attributes with whatever information you like:

import numpy as np
hdu.data = np.random.random((128,128))

Note that setting the data automatically populates the header with basic information:

hdu.header

and you should never have to set header keywords such as NAXIS, NAXIS1, and so on manually. We can then set additional header keywords:

hdu.header['telescop'] = 'Python Observatory'

and we can then write out the FITS file to disk:

hdu.writeto('random_array.fits', clobber=True)

Convenience functions

In cases where you just want to access the data or header in a specific HDU, you can use the following convenience functions:

data = fits.getdata('data/gll_iem_v02_P6_V11_DIFFUSE.fit') header = fits.getheader('data/gll_iem_v02_P6_V11_DIFFUSE.fit')

To get the data or header for an HDU other than the first, you can specify the extension name or index. The second HDU is called energies, so we can do:

data = fits.getdata('data/gll_iem_v02_P6_V11_DIFFUSE.fit', extname='energies')

or:

data = fits.getdata('data/gll_iem_v02_P6_V11_DIFFUSE.fit', ext=1)

and similarly for getheader.

Accessing Tabular Data

Tabular data behaves very similarly to image data such as that shown above, but the data array is a structured Numpy array which requires column access via the item notation:

from astropy.io import fits hdulist = fits.open('data/gll_psc_v08.fit')
hdulist[1].name
hdulist[1].data['RAJ2000']
hdulist[1].data['DEJ2000']

However, as we saw on the notes on the Table class, it is often easier to simply read in FITS tables using Table.read:

from astropy.table import Table t = Table.read('data/gll_psc_v08.fit')

Practical Exercises

Level 1

Try and read in one of your own FITS files using astropy.io.fits, and see if you can also plot the array values in Matplotlib. Also, examine the header, and try and extract individual values. You can even try and modify the data/header and write the data back out - but take care not to write over the original file!

Level 2

Read in the LAT Point Source Catalog (data/gll_psc_v08.fit) and make a scatter plot of the Galactic Coordinates of the sources (complete with axis labels). Bonus points if you can make the plot go between -180 and 180 instead of 0 and 360 degrees. Note that the Point Source Catalog contains the Galactic Coordinates, so no need to convert them.

Level 3

Using Matplotlib, make an all-sky plot of the LAT Background Model in the Plate Carée projection showing the LAT Point Source Catalog overlaid with markers, and with the correct coordinates on the axes. You should do this using only astropy.io.fits, Numpy, and Matplotlib (no WCS or coordinate conversion library). Hint: the -CAR projection is such that the x pixel position is proportional to longitude, and the y pixel position to latitude. Bonus points for a pretty colormap.