diff --git a/CHANGES.rst b/CHANGES.rst index 4e6bf323be..e951c3763b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,12 @@ general - Increase asdf maximum version to 4 [#8018] +imprint +------- + +- Updated the logging to report which imprint image is being subtracted from the + science image. [#8041] + resample -------- diff --git a/docs/jwst/imprint/description.rst b/docs/jwst/imprint/description.rst index a053e84c4b..b667e7c513 100644 --- a/docs/jwst/imprint/description.rst +++ b/docs/jwst/imprint/description.rst @@ -9,12 +9,21 @@ MOS and IFU exposures by the MSA structure. This is accomplished by subtracting a dedicated exposure taken with all MSA shutters closed and the IFU entrance aperture blocked. -The step has two input parameters: the target exposure and a list of imprint -exposures. These arguments can be provided as either a file name -or a JWST data model. +The step has two input parameters: the target exposure and a list of one +or more imprint exposures. These arguments can be provided as either file names +or JWST data models. -The SCI data array of the imprint exposure is subtracted from the SCI array -of the target exposure. The DQ arrays of the two exposures are combined using +In the event that multiple imprint images are provided, the step uses the +meta data of the target and imprint exposures to find the imprint exposure +that matches the observation number (keyword "OBSERVTN") and dither pattern +position number (keyword "PATT_NUM") of the target exposure. The matching +imprint image is then subtracted from the target image. If no matching imprint +image is found, the step will be skipped, returning the input target image +unaltered. + +When subtracting the imprint data model from the target data model, +the SCI data array of the imprint exposure is subtracted from the SCI array +of the target exposure, and the DQ arrays of the two exposures are combined using a bitwise logical OR operation. The ERR and variance arrays are not currently used or modified. diff --git a/jwst/imprint/imprint_step.py b/jwst/imprint/imprint_step.py index b8a720fdb2..098166f844 100755 --- a/jwst/imprint/imprint_step.py +++ b/jwst/imprint/imprint_step.py @@ -9,7 +9,7 @@ class ImprintStep(Step): """ ImprintStep: Removes NIRSpec MSA imprint structure from an exposure - by subtracting an imprint exposure. + by subtracting an imprint (a.k.a. leakcal) exposure. """ class_alias = "imprint" @@ -19,46 +19,46 @@ class ImprintStep(Step): def process(self, input, imprint): - # subtract leakcal (imprint) image - # If there is only one imprint image is in the association use it for all the data. - # If there is more than one imprint image in the association then select - # the imprint image to subtract based on position number (DataModel.meta.dither.position_number) & - # observation number (Datamodel.meta.observation.observation_number) - - # Open the input data model and get position number of image + # Open the input science image and get its dither pattern position number input_model = datamodels.open(input) pos_no = input_model.meta.dither.position_number obs_no = input_model.meta.observation.observation_number - # find imprint that goes with input image - if there is only 1 imprint image - use it. + # If there is only one imprint image listed in the association, + # use it for all science images. + # If there is more than one imprint image in the association, + # then select the imprint image to be used by matching the dither pattern position + # number and observation number to the science image. num_imprint = len(imprint) - match = None if num_imprint == 1: - match = 0 + match = 0 # use the first, and only, imprint image else: - i = 0 - while match is None and i < num_imprint: - # open imprint images and read in pos_no to find match + match = None + for i in range(num_imprint): + # open imprint image and read in pos_no to find match imprint_model = datamodels.open(imprint[i]) imprint_pos_no = imprint_model.meta.dither.position_number imprint_obs_no = imprint_model.meta.observation.observation_number imprint_model.close() if pos_no == imprint_pos_no and obs_no == imprint_obs_no: match = i - i = i + 1 + break - # Initialize result to be input (just in case no matching imprint image was found) + # Copy the input image to the output (just in case no matching imprint image was found) result = input_model.copy() if match is not None: + # Subtract the matching imprint image imprint_model = datamodels.open(imprint[match]) + self.log.info(f"Subtracting imprint image {imprint_model.meta.filename}") result = subtract_images.subtract(input_model, imprint_model) # Update the step status and close the imprint model result.meta.cal_step.imprint = 'COMPLETE' imprint_model.close() else: - self.log.info(f'No imprint image was found for {input}') + self.log.warning(f'No matching imprint image was found for {input}') + self.log.warning('Step will be skipped') result.meta.cal_step.imprint = 'SKIPPED' input_model.close() diff --git a/jwst/regtest/test_nirspec_imprint.py b/jwst/regtest/test_nirspec_imprint.py new file mode 100644 index 0000000000..c4c9be6e60 --- /dev/null +++ b/jwst/regtest/test_nirspec_imprint.py @@ -0,0 +1,51 @@ +"""Regression test for NIRSpec imprint subtraction""" +import pytest + +from jwst.regtest import regtestdata as rt + +# Define artifactory source and truth +INPUT_PATH = 'nirspec/imprint' +TRUTH_PATH = 'truth/test_nirspec_imprint' + + +@pytest.fixture(scope='module') +def run_spec2(jail, rtdata_module): + """Run the Spec2Pipeline on a spec2 ASN containing a single exposure + with multiple imprint exposures""" + rtdata = rtdata_module + + # Setup the inputs + asn_name = 'jw01802-o011_spec2_00046_asn.json' + asn_path = INPUT_PATH + '/' + asn_name + + # Run the pipeline + step_params = { + 'input_path': asn_path, + 'step': 'calwebb_spec2', + 'args': [ + '--steps.assign_wcs.save_results=true', + '--steps.imprint_subtract.save_results=true', + '--steps.msa_flagging.skip=true', + '--steps.srctype.skip=true', + '--steps.flat_field.skip=true', + '--steps.pathloss.skip=true', + '--steps.photom.skip=true', + '--steps.cube_build.skip=true', + '--steps.extract_1d.skip=true', + ] + } + + rtdata = rt.run_step_from_dict(rtdata, **step_params) + return rtdata + + +@pytest.mark.bigdata +@pytest.mark.parametrize( + 'suffix', + ['assign_wcs', 'imprint_subtract', 'cal'] +) +def test_nirspec_imprint(run_spec2, fitsdiff_default_kwargs, suffix): + """Regression test matching output files""" + rt.is_like_truth(run_spec2, fitsdiff_default_kwargs, suffix, + truth_path=TRUTH_PATH) +