FITS (Flexible Image Transport System) is the data format most widely used within astronomy for transporting, analyzing, and archiving scientific data files. FITS is much more than just another image format (such as JPG or GIF) and is primarily designed to store scientific data sets consisting of multidimensional arrays (images) and 2-dimensional tables organized into rows and columns of information.
In [ ]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import astropy.io.fits as fits
In [ ]:
plt.style.use('ggplot')
plt.rc('axes', grid=False) # turn off the background grid for images
Header
and Data
Primary HDU
.Header Unit
. Cards
)
In [ ]:
data_file = "./MyData/bsg01.fits"
my_fits_file = fits.open(data_file)
my_fits_file.info()
In [ ]:
image_data = my_fits_file[0].data
image_header = my_fits_file[0].header
In [ ]:
image_header
In [ ]:
print("The image has a shape [height,width] of {0}".format(image_data.shape))
print("The image is made up of data of type {0}".format(image_data.dtype))
In [ ]:
print("The image has a maximum value of {0}".format(image_data.max()))
print("The image has a minimum value of {0}".format(image_data.min()))
In [ ]:
fig, ax = plt.subplots(1,2)
fig.set_size_inches(12,6)
fig.tight_layout()
ax[0].imshow(image_data,cmap=plt.cm.gray)
ax[1].hist(image_data.flatten(),bins=20);
In [ ]:
copy_data = np.copy(image_data) # make a copy of the data to work with
cut_off = 40
mask = np.where(copy_data > cut_off)
copy_data[mask] = 60 # You can not just throw data away, you have to set it to something.
In [ ]:
print("The cropped image has a maximum value of {0}".format(copy_data.max()))
print("The cropped image has a minimum value of {0}".format(copy_data.min()))
In [ ]:
my_bins = np.arange(0,110,5)
my_bins
In [ ]:
fig, ax = plt.subplots(1,2)
fig.set_size_inches(12,6)
fig.tight_layout()
ax[0].imshow(copy_data,cmap=plt.cm.gray)
ax[1].hist(image_data.flatten(),bins=my_bins)
ax[1].hist(copy_data.flatten(),bins=my_bins, alpha = 0.40);
In [ ]:
another_image_file = "./MyData/bsg02.fits"
another_image_data = fits.getdata(another_image_file) # a quick way to just get the data
In [ ]:
fig, ax = plt.subplots(1,2)
fig.set_size_inches(12,6)
fig.tight_layout()
ax[0].set_title("Original Image")
ax[1].set_title("Another Image")
ax[0].imshow(image_data, cmap=plt.cm.gray)
ax[1].imshow(another_image_data, cmap=plt.cm.gray);
In [ ]:
real_image = image_data - another_image_data # Subtract the images pixel by pixel
In [ ]:
fig, ax = plt.subplots(1,3)
fig.set_size_inches(12,6)
fig.tight_layout()
ax[0].set_title("Original Image")
ax[1].set_title("Another Image")
ax[2].set_title("Real Image!")
ax[0].imshow(image_data, cmap=plt.cm.gray)
ax[1].imshow(another_image_data, cmap=plt.cm.gray);
ax[2].imshow(real_image, cmap=plt.cm.gray);
In [ ]:
print("The real image has a maximum value of {0}".format(real_image.max()))
print("The real image has a minimum value of {0}".format(real_image.min()))
In [ ]:
my_spectra_file = './MyData/Star_G5.fits'
my_spectra_fits = fits.open(my_spectra_file)
my_spectra_fits.info()
In [ ]:
spectra_data = my_spectra_fits[0].data
spectra_header = my_spectra_fits[0].header
In [ ]:
spectra_header[0:15]
In [ ]:
# The FITS header has the information to make an array of wavelengths
start_wavelength = spectra_header['CRVAL1']
num_of_points = spectra_header['NAXIS1']
width_of_points = spectra_header['CDELT1']
end_wavelength = start_wavelength + (num_of_points * width_of_points)
wavelength_range = np.arange(start_wavelength,end_wavelength,width_of_points)
In [ ]:
fig, ax = plt.subplots(2,1)
fig.set_size_inches(11,8.5)
fig.tight_layout()
# Full spectra
ax[0].plot(wavelength_range, spectra_data, color='b')
ax[0].set_ylabel("Flux")
ax[0].set_xlabel("Wavelength [angstroms]")
# Just the visible range with the hydrogen Balmer lines
ax[1].set_xlim(4000,7000)
ax[1].set_ylim(0.6,1.2)
ax[1].plot(wavelength_range, spectra_data, color='b')
ax[1].set_ylabel("Flux")
ax[1].set_xlabel("Wavelength [angstroms]")
H_Balmer = [6563,4861,4341,4102,3970,3889,3835,3646]
ax[1].vlines(H_Balmer,0,2, color='r', linewidth=3, alpha = 0.25);
In [ ]:
import glob
star_list = glob.glob('./MyData/Star_*5.fits')
star_list
In [ ]:
fig, ax = plt.subplots(1,1)
fig.set_size_inches(9,5)
fig.tight_layout()
# Full spectra
ax.set_ylabel("Flux")
ax.set_xlabel("Wavelength [angstroms]")
ax.set_ylim(0.0, 1.05)
for file in star_list:
spectra = fits.getdata(file)
spectra_normalized = spectra / spectra.max()
ax.plot(wavelength_range, spectra_normalized, label=file)
ax.legend(loc=0,shadow=True);
In [ ]:
star_file = "./MyData/star_field.fits"
star_fits_file = fits.open(star_file)
star_fits_file.info()
In [ ]:
star_data = star_fits_file[0].data
star_header = star_fits_file[0].header
In [ ]:
plt.imshow(star_data, cmap=plt.cm.gray)
In [ ]:
plt.imshow(star_data, origin='lower', cmap=plt.cm.gray)
In [ ]:
from astropy.wcs import WCS
In [ ]:
my_wcs = WCS(star_header)
In [ ]:
my_wcs
In [ ]:
fig = plt.figure()
ax = fig.add_subplot(111, projection=my_wcs)
fig.set_size_inches(6,6)
fig.tight_layout()
ax.grid(color='y', ls='-')
ax.set_xlabel('Right Ascension (J2000)')
ax.set_ylabel('Declination (J2000)')
ax.imshow(star_data, origin='lower', cmap=plt.cm.gray);
In [ ]:
from astropy.visualization import make_lupton_rgb
In [ ]:
red_img = fits.getdata("./MyData/m51_IR.fits").astype(float)
green_img = fits.getdata("./MyData/m51_red.fits").astype(float)
blue_img= fits.getdata("./MyData/m51_blue.fits").astype(float)
In [ ]:
clean_r = red_img - np.median(red_img)
clean_g = green_img - np.median(green_img)
clean_b = blue_img - np.median(blue_img)
In [ ]:
fig, ax = plt.subplots(1,3)
fig.set_size_inches(12,6)
fig.tight_layout()
ax[0].set_title("R")
ax[1].set_title("G")
ax[2].set_title("B")
ax[0].imshow(clean_r, origin='lower', cmap=plt.cm.gray)
ax[1].imshow(clean_g, origin='lower', cmap=plt.cm.gray);
ax[2].imshow(clean_b, origin='lower', cmap=plt.cm.gray);
In [ ]:
image = make_lupton_rgb(clean_r, clean_g, clean_b, stretch = 5000)
In [ ]:
fig, ax = plt.subplots(1,1)
fig.set_size_inches(6,6)
fig.tight_layout()
ax.imshow(image, origin='lower', cmap=plt.cm.gray);
In [ ]:
from astropy import stats
In [ ]:
my_data = np.array([1, 5, 6, 8, 100, 5, 3, 2, 4, 5])
my_data.mean(), my_data.std()
In [ ]:
filtered_data = stats.sigma_clip(my_data, sigma=2, iters=5)
filtered_data
In [ ]:
my_data[filtered_data.mask]
In [ ]:
my_data[~filtered_data.mask]
In [ ]:
star_data.mean(), star_data.std(), star_data.max(), star_data.min()
In [ ]:
clip_star = stats.sigma_clip(star_data, sigma=8, iters=5)
In [ ]:
copy_data = np.copy(star_data) # make a copy of the data to work with
copy_data[~clip_star.mask] = star_data.min()
In [ ]:
fig, ax = plt.subplots(1,2)
fig.set_size_inches(12,6)
fig.tight_layout()
ax[0].imshow(star_data, origin='lower', cmap=plt.cm.gray)
ax[1].imshow(copy_data, origin='lower', cmap=plt.cm.gray);