Source code for sofia_redux.instruments.hawc.steps.stepscanmapflat

# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""Scan flat field generation pipeline step."""

import os
import warnings

from astropy import log

from sofia_redux.instruments.hawc.datafits import DataFits
from sofia_redux.instruments.hawc.stepparent import StepParent
from sofia_redux.instruments.hawc.steps.stepscanmap import StepScanMap
from sofia_redux.scan.reduction.reduction import Reduction


__all__ = ['StepScanMapFlat']


[docs] class StepScanMapFlat(StepParent): """ Generate a flat field from scanning data. This step calls scan map with special parameters to produce a flat field from a scanning observation of a bright source. Additional options for the scan map algorithm may be passed in the 'options' parameter. Input data for this step is raw HAWC data FITS files. Output from this step is a single output DataFits, with 4 image planes (HDUs): R ARRAY GAIN, T ARRAY GAIN, R BAD PIXEL MASK, and T BAD PIXEL MASK. """
[docs] def setup(self): """ Set parameters and metadata for the pipeline step. Output files have PRODTYPE = 'scanmapflat', and are named with the step abbreviation 'SFL'. Parameters defined for this step are: options : str Command-line options to pass to scan map. use_frames : str Frames to use from the reduction. Specify a particular range, as '400:-400' or '400:1000'. """ # Name of the pipeline reduction step self.name = 'scanmapflat' self.description = 'Make Scan Flat' # Shortcut for pipeline reduction step and identifier for # saved file names. self.procname = 'sfl' # Clear Parameter list self.paramlist = [] # Append parameters self.paramlist.append(['scanmappath', '.', 'Path to the scan map installation']) self.paramlist.append(['options', '', 'Command line options for scan map']) self.paramlist.append(['use_frames', '', "Frames to use from reduction. " "Specify a particular range, as " "'400:-400', or '400:1000'."])
# The following comment is for PyCharm: # allow scanmap command list to be assembled # without complaining -- it's more readable that way. # # noinspection PyListCreation
[docs] def run(self): """ Run the data reduction algorithm. This step is run as a single-in single-out (SISO) step: self.datain should be a DataFits, and output will also be a DataFits, stored in self.dataout. The process is: 1. Assemble the scan map command from input parameters. 2. Call scan map as a subprocess. 3. Read scan map output from disk and update headers as necessary. """ # collect input options in dict kwargs = {} options = {} outpath = os.path.dirname(self.datain.filename) kwargs['outpath'] = outpath # output basename outname = os.path.basename(self.datain.filenamebegin + self.procname.upper() + self.datain.filenameend) kwargs['name'] = outname # Add all subarrays kwargs['subarray'] = 'R0,T0,R1' kwargs['lock'] = 'subarray' # Add frame clipping if necessary use_frames = str(self.getarg('use_frames')).strip() use_frames = StepScanMap.check_use_frames([self.datain], use_frames) if use_frames != '': kwargs['frames'] = use_frames # Add flat field and output options kwargs['source'] = {'flatfield': True} kwargs['write'] = {'source': False, 'flatfield': {'value': True, 'name': outname}} flatname = os.path.join(outpath, outname) # add additional options from parameters at end, # so they can override any defaults set by the above additional = str(self.getarg('options')).strip() if additional != '': all_val = additional.split() for val in all_val: try: k, v = val.split('=') except (IndexError, ValueError, TypeError): pass else: options[k] = v kwargs['options'] = options # get input file name if os.path.exists(self.datain.filename): infile = self.datain.filename else: rawname = self.datain.rawname if os.path.exists(rawname): infile = rawname # log input log.debug(f'All provided options: {kwargs}') log.debug(f'Input file: {infile}') # run the reduction with warnings.catch_warnings(): warnings.simplefilter('ignore', RuntimeWarning) reduction = Reduction('hawc_plus') reduction.run(infile, **kwargs) # check for appropriate output if not os.path.isfile(flatname): log.error(f"Unable to open scan map output " f"file = {outname}") raise ValueError("No scan map output found.") # load flat output file df = DataFits(config=self.config) df.load(flatname) os.remove(flatname) df.filename = self.datain.filename # Store the output in dataout self.dataout = df # Copy and save headers scnhead = self.dataout.header.copy() self.dataout.header = self.datain.header.copy() StepScanMap.merge_scan_hdr(self.dataout, scnhead, [self.datain]) # Update SOFIA mandated keywords (since this is first pipe step) obsid = 'P_' + self.datain.getheadval('OBS_ID') self.dataout.setheadval('OBS_ID', obsid) self.dataout.setheadval('PIPELINE', 'HAWC_DRP')