๐๐ ๐ Loading FITS Imagesยถ
This page provides a basic introduction to using python to load FITS (Flexible Image Transport System) data, display images, access pixel data, and find metadata.
What is an array?ยถ
In a few steps, we're going to load a FITS image into python as an array of numbers. But first, we should be familiar with what an array looks like. Let's start by importing some common tools.
import matplotlib.pyplot as plt
import numpy as np
Now, let's create a small array of numbers and store it as a variable named some_array. This will generate a 3x5 array with random values ranging from 0 to 100.
some_array = np.random.randint(0, 100, [3,5])
Let's print the numbers in that array.
print(some_array)
[[93 36 61 98 73] [45 89 86 86 88] [98 24 91 5 66]]
We can think of this array as a tiny image, so let's show it as an image. Check visually, do the bright pixels in the image correspond to high values in the array?
plt.imshow(some_array);
We can see the shape of the array by looking at its .shape attribute.
some_array.shape
(3, 5)
We can access a subset of a 2D array by indexing it with [row, column] where row and column refer to one or more rows or columns of the array. To extract a single row and a single column (= one pixel), just enter one integer for each. In Python, row and column indices start from 0, so the 1st row and 1st column would be:
some_array[0,0]
93
The 3rd row and 2th column would be:
some_array[2,1]
24
The special character : means "extract all possible values." We can use this to extract 1D arrays along a particular row or column. The entirety of the 1st row (row 0, all columns) would be:
some_array[0,:]
array([93, 36, 61, 98, 73])
The entirety of the 4th column (all rows, column 3) would be:
some_array[:,3]
array([98, 86, 5])
We can plot one of these 1D arrays to see the pixel values a bit more quantitatively.
# extract the row we want
the_row_i_want_to_plot = some_array[0,:]
# plot that data and add labels
plt.plot(the_row_i_want_to_plot, marker='o')
plt.xlabel('column (pixels)')
plt.ylabel('pixel value');
We can calculate summary statistics on our array, such as the minimum and maximum value, with a variety of np. functions.
np.min(some_array)
5
np.max(some_array)
98
And finally, we can do math with arrays, including either individual numbers or other arrays.
another_array = some_array + 10000
print(another_array)
[[10093 10036 10061 10098 10073] [10045 10089 10086 10086 10088] [10098 10024 10091 10005 10066]]
How do we load a FITS image into an array?ยถ
FITS files are a (mostly) astronomy-specific file format, so the astropy package provides tools for loading these files into Python. Let's import the input/output tool for FITS files.
from astropy.io import fits
And then use that tool to open our image into a Python variable. Here, you'll want to use the filename of the file you want to open (which must be in the same directory as your notebook).
our_file = fits.open('some-test-image.fit')
Once that file is loaded into the variable our_file, we can preview its contents with the .info() method.
our_file.info()
Filename: some-test-image.fit No. Name Ver Type Cards Dimensions Format 0 PRIMARY 1 PrimaryHDU 50 (2048, 2048) int16 (rescales to uint16)
Some FITS files can have multiple "extensions" which can each hold separate data. The files from the SBO telescopes have only one extension. Let's extract the image data from that 1st extension, and store it in the variable our_image.
our_image = our_file[0].data
That's it! The variable our_image now contains our image data as an array. It's a bit bigger than the tiny array we made above, but exactly the same principles apply. Let's print out the values (thankfully, notice Python abbreviates and only shows us some of the pixels), and display it as an image.
print(our_image)
[[3216 3234 3244 ... 3046 3148 2406] [3119 3179 3058 ... 3045 3084 2392] [3097 3065 2974 ... 3061 3072 2359] ... [2967 2998 2915 ... 3024 3107 2426] [2943 2917 2918 ... 3008 3224 2451] [2978 2970 2945 ... 3123 3467 2392]]
plt.imshow(our_image);
Dealing with real data, it may be useful to change the colormap used to translate from numbers to brightness/color for display. Inside plt.imshow we can change which set of colors is used via cmap=, and change the minimum and maximum pixel values via vmin= and vmax=. We can show the translation between color and number with plt.colorbar().
plt.imshow(our_image, cmap='gray', vmin=0, vmax=10000)
plt.colorbar();
With your image array, and using what we've learned above, write and run code cells to do each of the following tasks:
- Print the shape (number of rows, number of columns) of your image.
- Print the pixel value for the pixel located at the 100th row and the 3rd column.
- Print the pixel values for the entire 100th row (it's OK if Python abbreviates this).
- Make a plot of the pixel values for the entire 100th row.
- Find a bright object in your image, and make a plot of the pixel values along a column that intersects your object.
- Print the minimum pixel value in your image.
- Create a new array consisting of your original image minus the minimum value in your original image, and confirm with
printthat the numbers are different.
How do we view FITS headers?ยถ
FITS headers contain useful metadata that might be necessary for our analyses. We can access the header from our loaded file as follows.
our_header = our_file[0].header
Then we can print the complete header simply by putting it in a code cell and running it.
our_header
SIMPLE = T / file does conform to FITS standard
BITPIX = 16 / number of bits per data pixel
NAXIS = 2 / number of data axes
NAXIS1 = 2048 / length of data axis 1
NAXIS2 = 2048 / length of data axis 2
EXTEND = T / FITS dataset may contain extensions
COMMENT FITS (Flexible Image Transport System) format is defined in 'Astronomy
COMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H
BZERO = 32768 / offset data range to that of unsigned short
BSCALE = 1 / default scaling factor
SBUUID = '{f9d1c135-27c4-4b43-8ba9-9f34e52476a0}' / Photo UUID
EXPTIME = 300. / SBIGFITSEXT Total exposure time in seconds
SWCREATE= 'TheSkyX Version 10.5.0 Build 13210' / SBIGFITSEXT Name & version of s
COLORCCD= 0 / Non zero if image is from a Bayer color ccd
DISPINCR= 1 / Non zero to automatically display the image in
PICTTYPE= 1 / Image type as index 0= Unknown 1=Light, 2=Bias,
IMAGETYP= 'Light Frame' / SBIGFITSEXT Light, Dark, Bias or Flat
XORGSUBF= 0 / SBIGFITSEXT Subframe x upper-left pixel in bin
YORGSUBF= 0 / SBIGFITSEXT Subframe y upper-left pixel in bin
XBINNING= 2 / SBIGFITSEXT Binning factor in width
YBINNING= 2 / SBIGFITSEXT Binning factor in height
EXPSTATE= 294
EGAIN = 1.33 / SBIGFITSEXT Electronic gain in e- per ADU
CCD-TEMP= -10.3329360071113 / SBIGFITSEXT Temperature of the CCD
SET-TEMP= -10.5147985994181 / SBIGFITSEXT The cooler setpoint in degrees C
SITELAT = '+40 00 13.45' / SBIGFITSEXT Latitude of the imaging location
SITELONG= '+105 15 46.86' / SBIGFITSEXT Longitude of the imaging location
LST = '+18 20 52.51' / Local sidereal time
OBSGEO-B= 40.003737 / Latitude of the observation in degrees, North +
OBSGEO-L= -105.263016666667 / Longitude of the observation in degrees, East +
OBSGEO-H= 1653. / Altitude of the observation in meters
BTP = 0 / Beyond the pole
CENTAZ = 124.000825664785 / SBIGFITSEXT Azimuth of the center of the image
CENTALT = 71.1169446959094 / SBIGFITSEXT Altitude of the center of the image
AIRMASS = 1.0568792681925 / Airmass of the telescope
TELEHA = '-01 10 46.07' / Telescope hour angle
MOUNT = 'Bisque TCS Professional' / The telescope mount
OBJCTRA = '19 30 43.399' / SBIGFITSEXT The right ascension of the center o
OBJCTDEC= '+27 57 31.25' / SBIGFITSEXT The declination of the center of th
OBJECT = 'Albireo ' / SBIGFITSEXT The name of the object imaged
INSTRUME= 'SBIG STX-16803 3 CCD Camera' / SBIGFITSEXT The model camera used.
XPIXSZ = 18. / SBIGFITSEXT Pixel width in microns after binnin
YPIXSZ = 18. / SBIGFITSEXT Pixel height in microns after binni
PEDESTAL= -100 / SBIGFITSEXT Add this count to each pixel value
FOCPOS = 157927. / The focuser position.
FOCTEMP = 0. / The focuser temperature in degrees C.
FOCTMPSC= 'Focuser (Default)' / The focuser temperature source.
FILTER = 'B ' / SBIGFITSEXT The optical filter used to take ima
DATE-OBS= '2022-09-02T02:36:59.860' / SBIGFITSEXT UTC of start exp. in ISO 8601
LOCALTIM= '9/1/2022 08:36:59.859 PM DST' / Local time at exposure start
We can access specific entries in the header by indexing it we a header keyword.
our_header['OBJECT']
'Albireo'
Good luck!ยถ
You'll earn course credit for completing this worksheet, but we won't grade your individual responses. It is your responsibility to make sure you learn the skills to complete the tasks above. If you have questions (you probably will!), please ask in-person or on slack!