Source code for potpyri.instruments.F2
"""F2/Gemini-S instrument configuration and reduction parameters."""
from potpyri._version import __version__
import os
import ccdproc
import numpy as np
import astropy.units as u
from astropy.io import fits
from astropy.time import Time
from astropy.nddata import CCDData
# Internal dependency
from . import instrument
[docs]
class F2(instrument.Instrument):
"""F2 at Gemini-South: NIR imaging with dark and flat calibration."""
def __init__(self):
self.version = __version__
self.name = 'F2'
# Extensions for keeping track of general metadata and WCS
self.raw_header_ext = 0
self.wcs_extension = 0
# Detector specific characteristics
self.pixscale = 0.1792
self.saturation = 65535.0
self.min_exptime = 1.0
# Run dark/bias/flat calibration?
self.dark = True
self.bias = False
self.flat = True
# Parameters for handling calibration files
# Run rejection on possible CR pixels in bias
self.cr_bias = True
# Extend header to first file extension for purposes of sort_files
self.extend_header = False
# How to combine images during stacking
self.stack_method = 'median'
self.wavelength = 'NIR'
self.gain = None
self.rdnoise = None
self.datasec = None
self.biassec = None
# Keywords for selecting files from Sort_files object
# This allows a single file type to be used for multiple purposes (e.g., for
# generating a flat-field image from science exposures)
self.filetype_keywords = {'SCIENCE':'SCIENCE', 'FLAT':'FLAT',
'DARK':'DARK','BIAS':'BIAS'}
# Header keywords
self.target_keyword = 'OBJECT'
self.exptime_keyword = 'EXPTIME'
self.filter_keyword = 'FILTER'
self.mjd_keyword = 'MJD-OBS'
self.bin_keyword = '11'
self.amp_keyword = '1'
# File sorting keywords
self.science_keywords = ['DECKER','MASKNAME']
self.science_values = ['open','none']
self.flat_keywords = ['OBJECT']
self.flat_values = ['gcalflat']
self.bias_keywords = []
self.bias_values = []
self.dark_keywords = ['OBSTYPE']
self.dark_values = ['dark']
self.spec_keywords = ['GRORDER']
self.spec_values = ['1']
self.bad_keywords = ['DECKER']
self.bad_values = ['closed']
self.detrend = False
self.catalog_zp = '2MASS'
self.out_size = 2500
[docs]
def get_saturation(self, hdr):
# Gives the saturation level in e-
return(self.saturation*hdr['NREADS']*hdr['GAIN'])
[docs]
def get_filter(self, hdr):
filt = hdr['FILTER'].replace(' ','').split('_')[0]
if filt == 'Ks':
filt = 'K'
return(filt)
[docs]
def get_rdnoise(self, hdr):
return(float(hdr['RDNOISE']))
[docs]
def get_gain(self, hdr):
return(float(hdr['GAIN']))
[docs]
def get_exptime(self, hdr):
return(hdr['EXPTIME'])
# Get a unique image number that can be derived only from the file header
[docs]
def get_number(self, hdr):
datestr = hdr['DATE-OBS']+'T'+hdr['TIME-OBS']
elap = Time(datestr)-Time('1980-01-01')
elap = int(np.round(elap.to(u.second).value))
return(elap)
[docs]
def import_image(self, filename, amp, log=None):
hdu = fits.open(filename)
# Create header
hdr = hdu[1].header
for key in hdu[0].header.keys():
if key not in hdr.keys():
try:
hdr[key]=hdu[0].header[key]
except ValueError:
continue
# Adjust WCS to be only 2 axes
for key in ['CRPIX3','CDELT3','CRVAL3','CD3_3']:
if key in hdr.keys():
del hdr[key]
hdr['WCSAXES']=2
# Create data array from first read
data = hdu[1].data
if len(data.shape)==3:
data = data[0,:,:]
raw = CCDData(data, header=hdr, unit=u.adu)
red = ccdproc.ccd_process(raw,
gain=self.get_gain(raw.header)*u.electron/u.adu,
readnoise=self.get_rdnoise(raw.header)*u.electron)
red.header['SATURATE'] = self.get_saturation(red.header)
return(red)