In [6]:
# The standard fare:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
%matplotlib inline
from astropy.io import fits 
import astropy.stats as stat

from photutils import aperture_photometry, CircularAperture, CircularAnnulus, DAOStarFinder

Lab 9 - Aperture Photometry with Python Photutils

9.1 - Getting Started

The goal of this lab is to teach you how to extract aperture photometry for all of the stars in a given image. Although the extraction itself is automated, there is some art to setting the parameters for extraction, and this lab is designed to teach you to choose these in an intelligent, data-driven way.

To start we need to read in a raw image to work with.


In [57]:
#as an example, let's load in a randomly-selected raw Smith R band image
image = fits.getdata('M52-007_R.fit')

We will be using a python package called photutils, which is based on an old IRAF package of the same name. One of the key functions within this package is the DAOStarFinder function, which we'll just call "the star finder" here.

The star finder will extract sources, defined as some multiple (which you provide) of the background/sky level, so first we need to get a reasonable estimate of the background level. This is done using the function mad_std from the astropy.stats package, as below.


In [25]:
from astropy.stats import mad_std
bkg_sigma = mad_std(image)
print(bkg_sigma)


16.3086244036

In [58]:
print(np.std(image))


313.858966808

Exercise 1. Use the resources (docstrings, wikipedia, other functions) at your disposal to answer the following questions in the cell below.

  1. What does the mad_std function do?
  2. How is it different from the more typical np.std function? How different are the answers in these two cases, and why?

Your answers go here

9.2 - Extracting Stars

The star finder requires two parameters to extract stars in the image:

1) The threshhold, which we will define as some number of background levels, above which we will call something a star
2) An estimate for the FWHM of point-sources (stars) in the image

Exercise 2

To start, estimate the FWHM of the stars in your image using pyraf's imexam functions, as you did in Lab 8. Measure the FWHM for at least 10 stars and average them. In the cell below, paste the imexam output and calculate the average of the measurements in the cell below that. Insert your calculated average FWHM in the third cell below.

insert imexam output here


In [30]:
#insert calculation of average FWHM here

In [32]:
#FWHM= this is a placeholder. INSERT YOUR VALUE IN PLACE OF 10 BELOW
FWHM=10

We also need to set the threshhold (described above) for star finder, which we define as some multiple (nsigma) of the background level. To start, let's set nsigma to 10, meaning that in order for somehting to be considered a star, it must have at least 10x the detector counts of the background level.

The next several lines below set up the parameters for the star finder (by specifying the FWHM and threshhold parameters), apply the star finder to the image, and then extract and print the number of sources.


In [59]:
nsigma=10
daofind = DAOStarFinder(fwhm=FWHM, threshold=nsigma*bkg_sigma)
sources = daofind(image)
nstars=len(sources)
nstars


Out[59]:
665

To check how well we're doing here, we need to be able to see how the sources that were automatically extracted line up with apparent sources in the image. To do so, we are going to write the information that star finder extracted from the sources it found into a DS9 region file, so that we can load it with the image. DS9 region files are text files where each line contains the following basic info:
regiontype xcen ycen FWHM

The code below writes the relevant outpt from daofind into a text file with this format.


In [36]:
xpos = np.array(sources['xcentroid'])
ypos = np.array(sources['ycentroid'])
f = open('M52_R.reg', 'w') #you will need to change the first input if you want to write to a different filename later
for i in range(0,len(xpos)):
    f.write('circle '+str(xpos[i])+' '+str(ypos[i])+' '+str(FWHM)+'\n')
f.close()

To display this region file, you should open the science image in DS9, then click Region --> Load Regions and navigate to the .reg file above. When you load it, you will see green circles appear on top of all of the stars that the Star Finder has extracted. Place a screenshot of this overlay in the cell below.

DS9 screenshot goes here

Exercise 3

Using the median-combined V and R images that you generated for Homework 9, answer the following questions. Include code, screenshots, etc. to support your argument, and add cells below as needed to do calculations, generate new region files, etc.
1) How many sources can you extract at V and R for nsigma=10 from your median-combined images? How much does the number of sources vary between the two wavelengths and why, do you think?
2) How different are the number of extracted stars in the raw R image you used in the example vs. the reduced and median combined R image that you generated for your homework? Name at least one potential reason why they are different, and find an example in the images that shows it.
Hint: An example really means a source that was identified in one image and not the other. Remember you can load multiple images in DS9, and can load a separate region file in each. Zoom in on your discrpant source. To match the zoom level and location between the two images, select Frame --> Match --> Frame --> Physical.
3) For one of your images (V or R), discuss how the number of extracted sources changes when you change the nsigma threshhold. Make an argument based on the images for what you think the most reasonable limit is for this data.

1. Problem 1 explanation and images go here


In [60]:
#problem 1 code goes here

2. Problem 2 explanation and images go here


In [61]:
#problem 2 code goes here

3. Problem 3 explanation and images go here


In [ ]:
#problem 3 code goes here

9.3 - Aperture Photometry

The next step is to actually extract the photometry, and here too there is some art to choosing parameters. Although photutils will extract the photometry for each star in an automated way, you need to intelligently choose the parameters based on your data.

The tunable parameters are:

  1. the aperture radius inside of which to count the flux from the star
  2. the inner and outer radius of the sky aperture. The annulus defined by these two numbers needs to be large enough to get a good measurement of the background level, but small enough to generally avoid confusion with other nearby sources.

We'll start with some potentially reasonable values for these parameters.


In [62]:
aprad = 8
skyin=10
skyout=15

Exercise 4

For each of the next two cells, write a comment describing what each line is doing in the line above it.


In [55]:
#add comments to this cell
starapertures = CircularAperture((xpos,ypos),r=aprad)
skyannuli = CircularAnnulus((xpos,ypos),r_in=skyin,r_out=skyout)
phot_apers = [starapertures, skyannuli]
phot_table = aperture_photometry(image,phot_apers)
phot_table


Out[55]:
<QTable length=665>
idxcenterycenteraperture_sum_0aperture_sum_1
pixpix
int64float64float64float64float64
14.6164703682775214.589495379459705181721.467793179962.293757
23066.41157754659254.571913537362626182439.204788181024.019525
32320.6761886236676.243823887119223286271.490439329501.698746
42978.1491321355987.3140943957772215331345.579822352772.149364
51035.04886626200419.167955843784714445499.307939397231.92137
62997.616059958427314.004456164365937253586.352161486845.114856
71482.942584091919328.934800099868003249162.065464474827.73854
81547.133470038881832.245483880448404420492.87616496756.723371
92574.016393962577234.657107656309257369252.963491632307.95996
...............
656329.606177857404132002.9208059207845254343.899392471637.62105
6571362.6825945964992010.9209270397196250957.942831474503.949623
6582634.47761121637772014.7501240149975249358.057919472717.99751
6592256.2554464611252017.0573852696452269079.983732476947.424678
660798.88623790369762018.414939764279286685.263118479311.699603
6612556.24776034817022019.3808400971914251761.633482472970.728321
6621689.34158584447192028.0481452777492265055.616388476851.961822
6634.6181513685434992041.3800240373994180543.875526179358.277753
6641290.42157659000172041.9870000713547330594.515438303311.052491
6653066.3909611538762041.4365135497503181459.508517180566.947525

In [56]:
#add comments to this cell
bkg_mean = phot_table['aperture_sum_1']/skyannuli.area()
bkg_starap_sum = bkg_mean * starapertures.area()
final_sum = phot_table['aperture_sum_0']-bkg_starap_sum
phot_table['background subtracted star counts'] = final_sum
phot_table


Out[56]:
<QTable length=665>
idxcenterycenteraperture_sum_0aperture_sum_1background subtracted star counts
pixpix
int64float64float64float64float64float64
14.6164703682775214.589495379459705181721.467793179962.29375789580.7733894
23066.41157754659254.571913537362626182439.204788181024.01952589754.9067907
32320.6761886236676.243823887119223286271.490439329501.698746117566.620681
42978.1491321355987.3140943957772215331345.579822352772.149364150726.239348
51035.04886626200419.167955843784714445499.307939397231.92137242116.564197
62997.616059958427314.004456164365937253586.352161486845.1148564321.65335521
71482.942584091919328.934800099868003249162.065464474827.738546050.2633311
81547.133470038881832.245483880448404420492.87616496756.723371166153.433794
92574.016393962577234.657107656309257369252.963491632307.959966533511.28799
..................
656329.606177857404132002.9208059207845254343.899392471637.6210512865.4374143
6571362.6825945964992010.9209270397196250957.942831474503.9496238011.92062432
6582634.47761121637772014.7501240149975249358.057919472717.997517326.44319444
6592256.2554464611252017.0573852696452269079.983732476947.42467824882.902297
660798.88623790369762018.414939764279286685.263118479311.69960341277.6729211
6612556.24776034817022019.3808400971914251761.633482472970.7283219600.62058152
6621689.34158584447192028.0481452777492265055.616388476851.96182220907.4119353
6634.6181513685434992041.3800240373994180543.875526179358.27775388712.437317
6641290.42157659000172041.9870000713547330594.515438303311.052491175299.256562
6653066.3909611538762041.4365135497503181459.508517180566.94752589009.2313845

Exercise 5 -

Spend the rest of the lab time investigating what changes about the photometric measurement (background subtracted sky counts caluclated column) when you adjust the tunable parameters (aperture radius and inner/outer sky annulus) and report your findings below. You may wish to examine only a handful of stars in the table and avoid pr (to print just a few rows of a table, see the example below), but make sure the rows you select include stars with a range of brightnesses. You may also wish to make separate versions/copies of the table with different aperture parameters so that you can compare without overwriting. Think in particular about crowded fields and see if you can derive the best parameters for this case as well (identify things in the table with very close values for xcenter and ycenter to find these crowded regions).


In [65]:
#example of printing just a few rows in a table - chosen to be one bright star, one faint
phot_table[6:8]


Out[65]:
<QTable length=2>
idxcenterycenteraperture_sum_0aperture_sum_1background subtracted star counts
pixpix
int64float64float64float64float64float64
71482.942584091919328.934800099868003249162.065464474827.738546050.2633311
81547.133470038881832.245483880448404420492.87616496756.723371166153.433794