from keckdrpframework.primitives.base_img import BaseImg
from kcwidrp.primitives.kcwi_file_primitives import kcwi_fits_reader, \
kcwi_fits_writer, strip_fname
import os
import ccdproc
import numpy as np
[docs]class StackFlats(BaseImg):
"""Stack flat images"""
def __init__(self, action, context):
BaseImg.__init__(self, action, context)
self.logger = context.pipeline_logger
def _pre_condition(self):
"""
Checks if we can build a stacked frame based on the processing table
:return:
"""
# get list of input flats
self.logger.info("Checking precondition for StackFlats")
self.stacked_list = self.context.proctab.search_proctab(
frame=self.action.args.ccddata,
target_type=self.action.args.stack_type,
target_group=self.action.args.groupid)
if len(self.stacked_list) > 0:
self.logger.info(f"already have {len(self.stacked_list)},"
f" stacked flats, expecting 0")
return False
else:
self.combine_list = self.context.proctab.search_proctab(
frame=self.action.args.ccddata,
target_type=self.action.args.want_type,
target_group=self.action.args.groupid)
self.logger.info(f"pre condition got {len(self.combine_list)},"
f" expecting {self.action.args.min_files}")
# do we meet the criterion?
if len(self.combine_list) >= self.action.args.min_files:
return True
else:
self.action.new_event = None
return False
def _perform(self):
"""
Returns an Argument() with the parameters that depends on this operation
"""
method = 'average'
suffix = self.action.args.stack_type.lower()
self.logger.info("Stacking flats using method %s" % method)
combine_list = list(self.combine_list['filename'])
# get flat stack output name
stname = strip_fname(combine_list[-1]) + '_' + suffix + '.fits'
stack = []
stackf = []
mask = None
for flat in combine_list:
# get flat intensity (int) image file name in redux directory
stackf.append(strip_fname(flat) + '_intd.fits')
flatfn = os.path.join(self.config.instrument.cwd,
self.config.instrument.output_directory,
stackf[-1])
# using [0] gets just the image data
f = kcwi_fits_reader(flatfn)[0]
# Set mask to None to prevent ccdproc.combine from masking
f.mask = None
stack.append(f)
stacked = ccdproc.combine(stack, method=method, sigma_clip=True,
sigma_clip_low_thresh=None,
sigma_clip_high_thresh=2.0)
# Get the BPM out of one of the flats (bpm is the same for all)
# and add it to the stacked flat as the stack's mask
last_flat_name = strip_fname(combine_list[-1]) + '_intd.fits'
last_flat_path = os.path.join(self.config.instrument.cwd,
self.config.instrument.output_directory,
last_flat_name)
last_flat = kcwi_fits_reader(last_flat_path)[0]
stacked.mask = last_flat.mask
stacked.header['IMTYPE'] = self.action.args.stack_type
stacked.header['NSTACK'] = (len(combine_list),
'number of images stacked')
stacked.header['STCKMETH'] = (method, 'method used for stacking')
for ii, fname in enumerate(stackf):
stacked.header['STACKF%d' % (ii + 1)] = (fname, "stack input file")
log_string = StackFlats.__module__
stacked.header['HISTORY'] = log_string
# output stacked flat
kcwi_fits_writer(stacked, output_file=stname,
output_dir=self.config.instrument.output_directory)
self.context.proctab.update_proctab(frame=stacked, suffix=suffix,
newtype=self.action.args.stack_type,
filename=self.action.args.name)
self.context.proctab.write_proctab()
self.logger.info(log_string)
return self.action.args
# END: class StackFlats()