Source code for kcwidrp.primitives.SubtractSky

from keckdrpframework.primitives.base_primitive import BasePrimitive
from kcwidrp.primitives.kcwi_file_primitives import kcwi_fits_reader, \
    kcwi_fits_writer, strip_fname  # , get_master_name
import os


[docs]class SubtractSky(BasePrimitive): """ Subtract sky model from observation. Reads in model of sky created in MakeMasterSky.py and subtracts it from observation. Which model is determined by the `kcwi.sky` file, if present. If not, then the model generated from the observation itself will be used. Which master sky was used will be recorded in the header keyword SKYMAST. If a mask file was used to generate the sky model, it will be recorded in SKYMSKF. If scaling was required prior to subtraction due to differing exposure times of observation and model, the scale value is recorded in SKYSCL. Writes out a \*_intk.fits file and adds an entry to the proc file. """ def __init__(self, action, context): BasePrimitive.__init__(self, action, context) self.logger = context.pipeline_logger def _pre_condition(self): """ Checks if a master sky exists to subtract """ self.logger.info("Checking precondition for SubtractSky") keycom = 'sky corrected?' if self.config.instrument.skipsky: self.logger.warning("Sky subtraction turned off, " "skipping SubtractSky") self.action.args.ccddata.header['SKYCOR'] = (False, keycom) return False skyfile = None skymask = None # check if kcwi.sky exists if os.path.exists('kcwi.sky'): f = open('kcwi.sky') skyproc = f.readlines() f.close() # is our file in the list? ofn = self.action.args.name for row in skyproc: # skip comments if row.startswith('#'): continue # skip empty lines if len(row.split()) < 1: continue # Parse row: # <raw sci file> <raw sky file> <optional mask file> # OR # <raw sci file> skip # to disable sky subtraction # Find match to current file if ofn in row.split()[0]: skyfile = row.split()[1] # Should we skip sky subtraction? if 'skip' in skyfile: self.logger.info("Skipping sky subtraction for %s" % ofn) self.action.args.ccddata.header['SKYCOR'] = (False, keycom) return False elif 'cont' in skyfile: self.logger.info("Using continuum source local sky") # Do we have an optional sky mask file? elif len(row.split()) > 2: skymask = row.split()[2] self.logger.info("Found sky mask entry for %s: %s" % (ofn, skymask)) self.logger.info("Found sky entry for %s: %s" % (ofn, skyfile)) # check if requested files exist if skyfile: if not os.path.exists(skyfile): skyfile = None if skymask: if not os.path.exists(skymask): skymask = None self.action.args.skyfile = skyfile self.action.args.skymask = skymask if skyfile: self.logger.info("pre condition got 1 master sky, expected 1") return True else: target_type = 'SKY' tab = self.context.proctab.search_proctab( frame=self.action.args.ccddata, target_type=target_type, nearest=True) self.logger.info("pre condition got %d master sky, expected 1" % len(tab)) if len(tab) <= 0: return False else: return True def _perform(self): self.logger.info("Subtracting sky background") # Header keyword to update key = 'SKYCOR' keycom = 'sky corrected?' target_type = 'SKY' skyfile = self.action.args.skyfile skymask = self.action.args.skymask if not self.action.args.skyfile: tab = self.context.proctab.search_proctab( frame=self.action.args.ccddata, target_type=target_type, nearest=True) self.logger.info("%d master sky frames found" % len(tab)) if len(tab) > 0: skyfile = tab['filename'][0] msname = strip_fname(skyfile) + '_' + target_type.lower() + ".fits" if os.path.exists(os.path.join(self.config.instrument.cwd, 'redux', msname)): self.logger.info("Reading image: %s" % msname) msky = kcwi_fits_reader( os.path.join(self.config.instrument.cwd, 'redux', msname))[0] # scale the sky? obtime = self.action.args.ccddata.header['XPOSURE'] sktime = msky.header['XPOSURE'] if obtime <= 0. or sktime <= 0.: self.logger.warning("Bad exposure times (obj, sky): %.1f, %1f" % (obtime, sktime)) skscl = 1. else: skscl = obtime / sktime self.logger.info("Sky scale factor = %.3f" % skscl) # store un-sky-subtracted image self.action.args.ccddata.noskysub = \ self.action.args.ccddata.data.copy() # do the subtraction self.action.args.ccddata.data -= msky.data * skscl # update header keywords self.action.args.ccddata.header[key] = (True, keycom) self.action.args.ccddata.header['SKYMAST'] = (msname, "Master sky filename") self.action.args.ccddata.header['SKYSCL'] = (skscl, 'sky scale factor') if skymask: self.action.args.ccddata.header['SKYMSKF'] = (skymask, 'sky mask file') else: # update header keywords self.action.args.ccddata.header[key] = (False, keycom) log_string = SubtractSky.__module__ self.action.args.ccddata.header['HISTORY'] = log_string # write out int image kcwi_fits_writer(self.action.args.ccddata, table=self.action.args.table, output_file=self.action.args.name, output_dir=self.config.instrument.output_directory, suffix="intk") self.context.proctab.update_proctab(frame=self.action.args.ccddata, suffix="intk", filename=self.action.args.name) self.context.proctab.write_proctab(tfil=self.config.instrument.procfile) self.logger.info(log_string) return self.action.args
# END: class SubtractSky()