This notebook briefly shows how to calculate zeropoints and other photometric system values using the python package stsynphot as of January 05, 2021. This is especially useful for calculating Vegamag zeropoints at different times for WFC3/UVIS (as of 01/2021 the WFC3/IR zeropoints are not time dependent). To install stsynphot, activate your conda environment in a bash shell and enter the command pip install stsynphot. More documentation on stsynphot is available here.
Using stsynphot requires downloading the throughput curves for the HST instruments and optical path. One method of doing this is shown below. More information can be found here.
import os
cmd_input = 'curl -O ftp://archive.stsci.edu/pub/hst/pysynphot/synphot1.tar.gz'
os.system(cmd_input)
Once the files are downloaded, unpack the files and set the environment variable PYSYN_CDBS to the path of the unpacked files.
os.environ['PYSYN_CDBS'] = '/YOUR/PATH/HERE/'
# os.environ['PYSYN_CDBS'] = '/grp/hst/cdbs/' # for STScI staff
import numpy as np
import stsynphot as stsyn
from astropy.table import Table
from astropy.time import Time
from synphot import Observation
Parameters to set include observation date (in MJD), size of photometric aperture (in arcseconds), and filters to calculate zeropoints for. Note that a six arsecond aperture is considered to be infinite, thus containing all of the flux. The zeropoints posted on the WFC3 website are calculated for an infinite aperture, so when calibrating photometry, aperture corrections should be applied.
These inputs can be changed to match other observations, some example alternate parameters are shown as commented lines.
#Date
mjd = '55008'
# mjd = str(Time.now().mjd) # Time right now
#Aperture Radius
aper = '6.0' # 151 pixels (infinity) [default behavior]
#aper = '0.396' # 10 pixels
#Detector:
detectors = ['uvis1']
#detectors = ['uvis1', 'uvis2'] # both chips
#detectors = ['ir'] # IF USING IR, MUST CHANGE FILTER SET IN FILTNAMES
#Filters:
filtnames = ['f200lp','f218w','f225w','f275w','f280n','f300x','f336w',
'f343n','f350lp','f373n', 'f390m','f390w','f395n','f410m',
'f438w','f467m','f469n','f475w','f475x','f487n','f502n','f547m',
'f555w','f600lp','f606w','f621m','f625w','f631n','f645n','f656n',
'f657n','f658n','f665n','f673n', 'f680n','f689m','f763m', 'f775w',
'f814w','f845m','f850lp','f953n']
#filtnames = ['f200lp','f218w','f225w','f275w'] # Just the first 4 filters
# IR filters, must set detectors = ['ir'] to work
#filtnames = ['f098m', 'f105w', 'f110w', 'f125w', 'f126n', 'f127m', 'f128n', 'f130n', 'f132n', 'f139m', 'f140w', 'f153m', 'f160w', 'f164n', 'f167n']
The calculation of the zeropoints starts with creating a specific bandpas object. Bandpasses generally consist of at least an instrument name, detector name, and filter name, though other parameters (such as the MJD and aperture radius shown above) are optional. For example:
obsmode = 'wfc3,uvis1,f225w'
bp = stsyn.band(obsmode) # creates bandpass object
Optional parameters are supplied on the end of the basic bandpass:
obsmode = 'wfc3,uvis1,f225w,mjd#55008,aper#6.0'
# or to use parameters above:
obsmode = 'wfc3,{},{},mjd#{},aper#{}'.format(detectors[0],filtnames[0],mjd,aper)
bp = stsyn.band(obsmode)
With the bandpass objects we can now calculate zeropoints, pivot wavelengths, and photometric bandwidths. To calculate Vegamag zeropoints, we need the Vega spectrum to calculate flux in a given bandpass.
def calculate_values(detector, filt, mjd, aper):
# parameters can be removed from obsmode as needed
obsmode = 'wfc3,{},{},mjd#{},aper#{}'.format(detector, filt, mjd, aper)
bp = stsyn.band(obsmode)
# STMag
photflam = bp.unit_response(stsyn.conf.area) # inverse sensitivity in flam
stmag = -21.1 -2.5 * np.log10(photflam.value)
# Pivot Wavelength and bandwidth
photplam = bp.pivot() # pivot wavelength in angstroms
bandwidth = bp.photbw() # bandwidth in angstroms
# ABMag
abmag = stmag - 5 * np.log10(photplam.value) + 18.6921
# Vegamag
obs = Observation(stsyn.Vega, bp, binset=bp.binset) # synthetic observation of vega in bandpass using vega spectrum
vegamag = -obs.effstim(flux_unit='obmag', area=stsyn.conf.area)
return obsmode, photplam.value, bandwidth.value, photflam.value, stmag, abmag, vegamag.value
obsmode, photplam, bandwidth, photflam, stmag, abmag, vegamag = calculate_values(detectors[0], filtnames[0], mjd, aper)
# print values
print('Obsmode PivotWave Photflam STMAG ABMAG VEGAMAG')
print(f'{obsmode}, {photplam:.1f}, {photflam:.4e}, {stmag:.3f}, {abmag:.3f}, {vegamag:.3f}')
Obsmode PivotWave Photflam STMAG ABMAG VEGAMAG wfc3,uvis1,f200lp,mjd#55008,aper#6.0, 4971.9, 4.9157e-20, 27.171, 27.381, 26.931
To calculate multiple bandpasses for different filter and detectors: (note each detector/filter combination must be valid)
oms, pivots, bws, pfs, st, ab, vm = [], [], [], [], [], [], []
print('Obsmode PivotWave Photflam STMAG ABMAG VEGAMAG')
for detector in detectors:
for filt in filtnames:
res = calculate_values(detector, filt, mjd, aper)
obsmode, photplam, bandwidth, photflam, stmag, abmag, vegamag = res # solely for readability
# print values
print(f'{obsmode}, {photplam:.1f}, {photflam:.4e}, {stmag:.3f}, {abmag:.3f}, {vegamag:.3f}')
oms.append(obsmode)
pivots.append(photplam)
bws.append(bandwidth)
pfs.append(photflam)
st.append(stmag)
ab.append(abmag)
vm.append(vegamag)
Obsmode PivotWave Photflam STMAG ABMAG VEGAMAG wfc3,uvis1,f200lp,mjd#55008,aper#6.0, 4971.9, 4.9157e-20, 27.171, 27.381, 26.931 wfc3,uvis1,f218w,mjd#55008,aper#6.0, 2228.0, 1.4594e-17, 20.990, 22.942, 21.278 wfc3,uvis1,f225w,mjd#55008,aper#6.0, 2372.1, 4.5688e-18, 22.251, 24.067, 22.430 wfc3,uvis1,f275w,mjd#55008,aper#6.0, 2709.7, 3.2206e-18, 22.630, 24.158, 22.677 wfc3,uvis1,f280n,mjd#55008,aper#6.0, 2832.9, 5.7472e-17, 19.501, 20.932, 19.516 wfc3,uvis1,f300x,mjd#55008,aper#6.0, 2820.5, 1.4093e-18, 23.527, 24.968, 23.565 wfc3,uvis1,f336w,mjd#55008,aper#6.0, 3354.5, 1.2848e-18, 23.628, 24.692, 23.527 wfc3,uvis1,f343n,mjd#55008,aper#6.0, 3435.2, 2.5672e-18, 22.876, 23.889, 22.754 wfc3,uvis1,f350lp,mjd#55008,aper#6.0, 5873.9, 5.1638e-20, 27.118, 26.965, 26.810 wfc3,uvis1,f373n,mjd#55008,aper#6.0, 3730.2, 1.3488e-17, 21.075, 21.909, 21.036 wfc3,uvis1,f390m,mjd#55008,aper#6.0, 3897.2, 2.5524e-18, 22.883, 23.621, 23.545 wfc3,uvis1,f390w,mjd#55008,aper#6.0, 3923.7, 5.0142e-19, 24.649, 25.373, 25.174 wfc3,uvis1,f395n,mjd#55008,aper#6.0, 3955.2, 5.9589e-18, 21.962, 22.668, 22.712 wfc3,uvis1,f410m,mjd#55008,aper#6.0, 4109.0, 2.3481e-18, 22.973, 23.597, 23.771 wfc3,uvis1,f438w,mjd#55008,aper#6.0, 4326.2, 6.7475e-19, 24.327, 24.839, 25.003 wfc3,uvis1,f467m,mjd#55008,aper#6.0, 4682.6, 1.6498e-18, 23.356, 23.696, 23.859 wfc3,uvis1,f469n,mjd#55008,aper#6.0, 4688.1, 9.3089e-18, 21.478, 21.815, 21.981 wfc3,uvis1,f475w,mjd#55008,aper#6.0, 4773.1, 2.4962e-19, 25.407, 25.705, 25.810 wfc3,uvis1,f475x,mjd#55008,aper#6.0, 4940.7, 1.5343e-19, 25.935, 26.158, 26.216 wfc3,uvis1,f487n,mjd#55008,aper#6.0, 4871.4, 5.8860e-18, 21.975, 22.229, 22.050 wfc3,uvis1,f502n,mjd#55008,aper#6.0, 5009.6, 5.0824e-18, 22.135, 22.328, 22.421 wfc3,uvis1,f547m,mjd#55008,aper#6.0, 5447.5, 4.5847e-19, 24.747, 24.758, 24.761 wfc3,uvis1,f555w,mjd#55008,aper#6.0, 5308.4, 1.8272e-19, 25.746, 25.813, 25.841 wfc3,uvis1,f600lp,mjd#55008,aper#6.0, 7468.1, 8.6226e-20, 26.561, 25.887, 25.554 wfc3,uvis1,f606w,mjd#55008,aper#6.0, 5889.2, 1.1506e-19, 26.248, 26.090, 26.006 wfc3,uvis1,f621m,mjd#55008,aper#6.0, 6218.9, 4.0126e-19, 24.891, 24.615, 24.465 wfc3,uvis1,f625w,mjd#55008,aper#6.0, 6242.6, 1.7139e-19, 25.815, 25.530, 25.379 wfc3,uvis1,f631n,mjd#55008,aper#6.0, 6304.3, 4.8250e-18, 22.191, 21.885, 21.723 wfc3,uvis1,f645n,mjd#55008,aper#6.0, 6453.6, 3.3059e-18, 22.602, 22.245, 22.049 wfc3,uvis1,f656n,mjd#55008,aper#6.0, 6561.4, 1.6713e-17, 20.842, 20.450, 19.868 wfc3,uvis1,f657n,mjd#55008,aper#6.0, 6566.6, 2.1811e-18, 23.053, 22.659, 22.333 wfc3,uvis1,f658n,mjd#55008,aper#6.0, 6584.0, 9.7496e-18, 21.428, 21.027, 20.672 wfc3,uvis1,f665n,mjd#55008,aper#6.0, 6655.9, 1.9774e-18, 23.160, 22.736, 22.492 wfc3,uvis1,f673n,mjd#55008,aper#6.0, 6765.9, 2.1926e-18, 23.048, 22.588, 22.343 wfc3,uvis1,f680n,mjd#55008,aper#6.0, 6877.6, 6.8241e-19, 24.315, 23.820, 23.556 wfc3,uvis1,f689m,mjd#55008,aper#6.0, 6876.8, 3.7208e-19, 24.973, 24.479, 24.196 wfc3,uvis1,f763m,mjd#55008,aper#6.0, 7614.4, 3.8291e-19, 24.942, 24.226, 23.837 wfc3,uvis1,f775w,mjd#55008,aper#6.0, 7651.4, 2.0922e-19, 25.599, 24.872, 24.480 wfc3,uvis1,f814w,mjd#55008,aper#6.0, 8039.1, 1.4994e-19, 25.960, 25.126, 24.698 wfc3,uvis1,f845m,mjd#55008,aper#6.0, 8439.1, 4.5207e-19, 24.762, 23.823, 23.316 wfc3,uvis1,f850lp,mjd#55008,aper#6.0, 9176.1, 3.7052e-19, 24.978, 23.857, 23.326 wfc3,uvis1,f953n,mjd#55008,aper#6.0, 9530.6, 8.0946e-18, 21.630, 20.426, 19.803
Values can also be written into an astropy table:
tbl = Table([oms, pivots, bws, pfs, st, ab, vm],
names=['Obsmode', 'Pivot Wave', 'Bandwidth', 'Photflam', 'STMag', 'ABMag', 'VegaMag'])
# Just for rounding columns to smaller number of decimals
for col in tbl.itercols():
if col.name == 'Photflam':
col.info.format = '.4e'
elif col.info.dtype.kind == 'f':
col.info.format = '.3f'
# Show table
tbl
| Obsmode | Pivot Wave | Bandwidth | Photflam | STMag | ABMag | VegaMag |
|---|---|---|---|---|---|---|
| str36 | float64 | float64 | float64 | float64 | float64 | float64 |
| wfc3,uvis1,f200lp,mjd#55008,aper#6.0 | 4971.860 | 1742.198 | 4.9157e-20 | 27.171 | 27.381 | 26.931 |
| wfc3,uvis1,f218w,mjd#55008,aper#6.0 | 2228.039 | 128.941 | 1.4594e-17 | 20.990 | 22.942 | 21.278 |
| wfc3,uvis1,f225w,mjd#55008,aper#6.0 | 2372.053 | 177.430 | 4.5688e-18 | 22.251 | 24.067 | 22.430 |
| wfc3,uvis1,f275w,mjd#55008,aper#6.0 | 2709.689 | 164.435 | 3.2206e-18 | 22.630 | 24.158 | 22.677 |
| wfc3,uvis1,f280n,mjd#55008,aper#6.0 | 2832.862 | 200.689 | 5.7472e-17 | 19.501 | 20.932 | 19.516 |
| wfc3,uvis1,f300x,mjd#55008,aper#6.0 | 2820.469 | 316.561 | 1.4093e-18 | 23.527 | 24.968 | 23.565 |
| wfc3,uvis1,f336w,mjd#55008,aper#6.0 | 3354.492 | 158.422 | 1.2848e-18 | 23.628 | 24.692 | 23.527 |
| wfc3,uvis1,f343n,mjd#55008,aper#6.0 | 3435.151 | 86.713 | 2.5672e-18 | 22.876 | 23.889 | 22.754 |
| wfc3,uvis1,f350lp,mjd#55008,aper#6.0 | 5873.870 | 1490.060 | 5.1638e-20 | 27.118 | 26.965 | 26.810 |
| wfc3,uvis1,f373n,mjd#55008,aper#6.0 | 3730.170 | 18.343 | 1.3488e-17 | 21.075 | 21.909 | 21.036 |
| ... | ... | ... | ... | ... | ... | ... |
| wfc3,uvis1,f665n,mjd#55008,aper#6.0 | 6655.876 | 42.191 | 1.9774e-18 | 23.160 | 22.736 | 22.492 |
| wfc3,uvis1,f673n,mjd#55008,aper#6.0 | 6765.939 | 41.943 | 2.1926e-18 | 23.048 | 22.588 | 22.343 |
| wfc3,uvis1,f680n,mjd#55008,aper#6.0 | 6877.596 | 112.013 | 6.8241e-19 | 24.315 | 23.820 | 23.556 |
| wfc3,uvis1,f689m,mjd#55008,aper#6.0 | 6876.755 | 207.613 | 3.7208e-19 | 24.973 | 24.479 | 24.196 |
| wfc3,uvis1,f763m,mjd#55008,aper#6.0 | 7614.371 | 229.425 | 3.8291e-19 | 24.942 | 24.226 | 23.837 |
| wfc3,uvis1,f775w,mjd#55008,aper#6.0 | 7651.363 | 419.719 | 2.0922e-19 | 25.599 | 24.872 | 24.480 |
| wfc3,uvis1,f814w,mjd#55008,aper#6.0 | 8039.056 | 666.760 | 1.4994e-19 | 25.960 | 25.126 | 24.698 |
| wfc3,uvis1,f845m,mjd#55008,aper#6.0 | 8439.057 | 260.304 | 4.5207e-19 | 24.762 | 23.823 | 23.316 |
| wfc3,uvis1,f850lp,mjd#55008,aper#6.0 | 9176.126 | 470.529 | 3.7052e-19 | 24.978 | 23.857 | 23.326 |
| wfc3,uvis1,f953n,mjd#55008,aper#6.0 | 9530.579 | 71.190 | 8.0946e-18 | 21.630 | 20.426 | 19.803 |
# Write to a file
tbl.write('uvis_zp_tbl.txt', format='ascii.commented_header')