In [ ]:
import numpy as np
# Set up matplotlib and use a nicer set of plot parameters
%config InlineBackend.rc = {}
import matplotlib
matplotlib.rc_file("matplotlibrc")
import matplotlib.pyplot as plt
%matplotlib inline
The following line is needed to download the example FITS files used here.
In [ ]:
from astropy.utils.data import download_file
In [ ]:
from astropy.io import fits
In [ ]:
image_file = download_file('http://data.astropy.org/tutorials/FITS-images/HorseHead.fits', cache=True )
I will open the FITS file and find out what it contains.
In [ ]:
hdu_list = fits.open(image_file)
hdu_list.info()
Generally the image information is located in the PRIMARY
block. The blocks are numbered and can be accessed by indexing hdu_list
.
In [ ]:
image_data = hdu_list[0].data
You data is now stored as a 2-D numpy array. Want to know the dimensions of the image? Just look at the shape
of the array.
In [ ]:
print(type(image_data))
print(image_data.shape)
At this point, we can just close the FITS file. We have stored everything we wanted to a variable.
In [ ]:
hdu_list.close()
If you don't need to examine the FITS header, you can call fits.getdata
to bypass the previous steps.
In [ ]:
image_data = fits.getdata(image_file)
print(type(image_data))
print(image_data.shape)
In [ ]:
plt.imshow(image_data, cmap='gray')
plt.colorbar()
# To see more color maps
# http://wiki.scipy.org/Cookbook/Matplotlib/Show_colormaps
Let's get some basic statistics about our image
In [ ]:
print('Min:', np.min(image_data))
print('Max:', np.max(image_data))
print('Mean:', np.mean(image_data))
print('Stdev:', np.std(image_data))
To make a histogram with matplotlib.pyplot.hist()
, I need to cast the data from a 2-D to array to something one dimensional.
In this case, I am using the iterable python object img_data.flat
.
In [ ]:
print(type(image_data.flat))
In [ ]:
NBINS = 1000
histogram = plt.hist(image_data.flat, NBINS)
Want to use a logarithmic color scale? To do so we need to load the LogNorm
object from matplotlib
.
In [ ]:
from matplotlib.colors import LogNorm
In [ ]:
plt.imshow(image_data, cmap='gray', norm=LogNorm())
# I chose the tick marks based on the histogram above
cbar = plt.colorbar(ticks=[5.e3,1.e4,2.e4])
cbar.ax.set_yticklabels(['5,000','10,000','20,000'])
You can perform math with the image data like any other numpy array. In this particular example, I will stack several images of M13 taken with a ~10'' telescope.
I open a series of FITS files and store the data in a list, which I've named image_concat
.
In [ ]:
image_list = [ download_file('http://data.astropy.org/tutorials/FITS-images/M13_blue_000'+n+'.fits', cache=True ) \
for n in ['1','2','3','4','5'] ]
# The long way
image_concat = []
for image in image_list:
image_concat.append(fits.getdata(image))
# The short way
#image_concat = [ fits.getdata(image) for image in IMAGE_LIST ]
Now I'll stack the images by summing my concatenated list.
In [ ]:
# The long way
final_image = np.zeros(shape=image_concat[0].shape)
for image in image_concat:
final_image += image
# The short way
#final_image = np.sum(image_concat, axis=0)
I'm going to show the image, but I want to decide on the best stretch. To do so I'll plot a histogram of the data.
In [ ]:
image_hist = plt.hist(final_image.flat, 1000)
I'll use the keywords vmin
and vmax
to set limits on the color scaling for imshow
.
In [ ]:
plt.imshow(final_image, cmap='gray', vmin=2.e3, vmax=3.e3)
plt.colorbar()
This is easy to do with the writeto()
method.
You will receive an error if the file you are trying to write already exists. That's why I've set clobber=True
.
In [ ]:
outfile = 'stacked_M13_blue.fits'
hdu = fits.PrimaryHDU(final_image)
hdu.writeto(outfile, clobber=True)
Determine the mean, median, and standard deviation of a part of the stacked M13 image where there is not light from M13. Use those statistics with a sum over the part of the image that includes M13 to estimate the total light in this image from M13.
In [ ]:
Show the image of the Horsehead Nebula, but in to units of surface brightness (magnitudes per square arcsecond). (Hint: the physical size of the image is 15x15 arcminutes.)
In [ ]:
Now write out the image you just created, preserving the header the original image had, but add a keyword 'UNITS' with the value 'mag per sq arcsec'. (Hint: you may need to read the astropy.io.fits documentation if you're not sure how to include both the header and the data)
In [ ]: