forked from spacetelescope/jwst
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(JP-3337) Renaming of undersampling_correction to charge_migration. (s…
…pacetelescope#7825) Co-authored-by: Howard Bushouse <[email protected]>
- Loading branch information
1 parent
4a1d83c
commit 7ffed92
Showing
20 changed files
with
527 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Arguments | ||
========= | ||
|
||
The ``charge migration`` step has one optional argument that can be set by the user: | ||
|
||
* ``--signal_threshold``: A floating-point value in units of ADU for the science value above which | ||
a group's DQ will be flagged as CHARGELOSS and DO_NOT_USE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
Description | ||
=========== | ||
|
||
:Class: `jwst.charge_migration.ChargeMigrationStep` | ||
:Alias: charge_migration | ||
|
||
|
||
Overview | ||
-------- | ||
This step corrects for an artifact seen in undersampled NIRISS images that may depress flux | ||
in resampled images. The artifact is seen in dithered images where the star is centered in | ||
a pixel. When the peak pixels of such stars approach the saturation level, they suffer from | ||
significant :ref:`charge migration <charge_migration>`: | ||
the spilling of charge from a saturated pixel into its neighboring pixels. This charge migration | ||
causes group-to-group differences to decrease significantly once the signal level is greater than | ||
~25,000 ADU. As a result, the last several groups of these ramps get flagged by the :ref:`jump <jump_step>` | ||
step. The smaller number of groups used for these pixels in the :ref:`ramp_fitting <ramp_fitting_step>` | ||
step results in them having larger read noise variances, which in turn leads to lower weights used | ||
during resampling. This ultimately leads to a lower than normal flux for the star in resampled images. | ||
|
||
Once a group in a ramp has been flagged as affected by charge migration, all subsequent | ||
groups in the ramp are also flagged. By flagging these groups, they are not used in the | ||
computation of slopes in the :ref:`ramp_fitting <ramp_fitting_step>` step. However, as described | ||
in the algorithm section below, they _are_ used in the calculation of the variance of the slope | ||
due to readnoise. | ||
|
||
Input details | ||
------------- | ||
The input must be in the form of a `~jwst.datamodels.RampModel`. | ||
|
||
|
||
Algorithm | ||
--------- | ||
The first group, and all subsequent groups, exceeding the value of the | ||
``signal_threshold`` parameter is flagged as CHARGELOSS. ``signal_threshold`` is in units | ||
of ADUs. These groups will also be flagged as DO_NOT_USE, and will not | ||
be included in the slope calculation during the ``ramp_fitting`` step. Despite being flagged | ||
as DO_NOT_USE, these CHARGELOSS groups are still included in the calculation of the | ||
variance due to readnoise. | ||
This results in a readnoise variance for undersampled pixels that is similar to that of | ||
pixels unaffected by charge migration. For the Poisson noise variance calculation in | ||
:ref:`ramp_fitting <ramp_fitting_step>`, the CHARGELOSS/DO_NOT_USE groups are not included. | ||
|
||
For integrations having only 1 or 2 groups, no flagging will be performed. | ||
|
||
|
||
Output product | ||
-------------- | ||
The output is a new copy of the input `~jwst.datamodels.RampModel`, with the updated DQ flags | ||
added to the GROUPDQ array. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
.. _charge_migration_step: | ||
|
||
================ | ||
Charge Migration | ||
================ | ||
|
||
.. toctree:: | ||
:maxdepth: 2 | ||
|
||
description.rst | ||
arguments.rst | ||
reference_files.rst | ||
|
||
.. automodapi:: jwst.charge_migration |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Reference Files | ||
=============== | ||
This step does not use any reference files. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .charge_migration_step import ChargeMigrationStep | ||
|
||
__all__ = ['ChargeMigrationStep'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
# Module for charge migration | ||
# | ||
import logging | ||
import numpy as np | ||
|
||
from stdatamodels.jwst.datamodels import dqflags | ||
|
||
log = logging.getLogger(__name__) | ||
log.setLevel(logging.DEBUG) | ||
|
||
GOOD = dqflags.group["GOOD"] | ||
DNU = dqflags.group["DO_NOT_USE"] | ||
CHLO = dqflags.group["CHARGELOSS"] | ||
|
||
CHLO_DNU = CHLO + DNU | ||
|
||
|
||
def charge_migration(input_model, signal_threshold): | ||
""" | ||
Correct for chargemigration | ||
Parameters | ||
---------- | ||
input_model : `~jwst.datamodels.RampModel` | ||
The input science data to be corrected | ||
signal_threshold : float | ||
Science value above which a group will be flagged as CHARGELOSS | ||
Returns | ||
------- | ||
output_model : `~jwst.datamodels.RampModel` | ||
Data model with charge_migration applied; add CHARGELOSS and | ||
DO_NOT_USE flags to groups exceeding signal_threshold | ||
""" | ||
data = input_model.data | ||
gdq = input_model.groupdq | ||
|
||
# Create the output model as a copy of the input | ||
output_model = input_model.copy() | ||
|
||
log.info('Using signal_threshold: %.2f', signal_threshold) | ||
|
||
gdq_new = flag_pixels(data, gdq, signal_threshold) | ||
|
||
# Save the flags in the output GROUPDQ array | ||
output_model.groupdq = gdq_new | ||
|
||
return output_model | ||
|
||
|
||
def flag_pixels(data, gdq, signal_threshold): | ||
""" | ||
Flag each group in each ramp that exceeds signal_threshold as CHARGELOSS and DO_NOT_USE, | ||
skipping groups already flagged as DO_NOT_USE. | ||
Parameters | ||
---------- | ||
data : float, 4D array | ||
science array | ||
gdq : int, 4D array | ||
group dq array | ||
signal_threshold : float | ||
Science value above which a group will be flagged as CHARGELOSS and DO_NOT_USE | ||
Returns | ||
------- | ||
new_gdq : int, 4D array | ||
updated group dq array | ||
""" | ||
n_ints, n_grps, n_rows, n_cols = gdq.shape | ||
|
||
new_gdq = gdq.copy() # Updated gdq | ||
|
||
# Flag all exceedances with CHARGELOSS and NO_NOT_USE | ||
chargeloss_pix = (data > signal_threshold) & (gdq != DNU) | ||
new_gdq[chargeloss_pix] = np.bitwise_or(new_gdq[chargeloss_pix], CHLO | DNU) | ||
|
||
# Reset groups previously flagged as DNU | ||
gdq_orig = gdq.copy() # For resetting to previously flagged DNU | ||
wh_gdq_DNU = np.bitwise_and(gdq_orig, DNU) | ||
|
||
# Get indices for exceedances | ||
arg_where = np.argwhere(new_gdq == CHLO_DNU) | ||
|
||
a_int = arg_where[:, 0] # array of integrations | ||
a_grp = arg_where[:, 1] # array of groups | ||
a_row = arg_where[:, 2] # array of rows | ||
a_col = arg_where[:, 3] # array of columns | ||
|
||
# Process the 4 nearest neighbors of each exceedance | ||
# Pixel to the east | ||
xx_max_p1 = a_col[a_col < (n_cols-1)] + 1 | ||
i_int = a_int[a_col < (n_cols-1)] | ||
i_grp = a_grp[a_col < (n_cols-1)] | ||
i_row = a_row[a_col < (n_cols-1)] | ||
|
||
if len(xx_max_p1) > 0: | ||
new_gdq[i_int, i_grp, i_row, xx_max_p1] = \ | ||
np.bitwise_or(new_gdq[i_int, i_grp, i_row, xx_max_p1], CHLO | DNU) | ||
|
||
new_gdq[wh_gdq_DNU == 1] = gdq_orig[wh_gdq_DNU == 1] # reset for earlier DNUs | ||
|
||
# Pixel to the west | ||
xx_m1 = a_col[a_col > 0] - 1 | ||
i_int = a_int[a_col > 0] | ||
i_grp = a_grp[a_col > 0] | ||
i_row = a_row[a_col > 0] | ||
|
||
if len(xx_m1) > 0: | ||
new_gdq[i_int, i_grp, i_row, xx_m1] = \ | ||
np.bitwise_or(new_gdq[i_int, i_grp, i_row, xx_m1], CHLO | DNU) | ||
|
||
new_gdq[wh_gdq_DNU == 1] = gdq_orig[wh_gdq_DNU == 1] # reset for earlier DNUs | ||
|
||
# Pixel to the north | ||
yy_m1 = a_row[a_row > 0] - 1 | ||
i_int = a_int[a_row > 0] | ||
i_grp = a_grp[a_row > 0] | ||
i_col = a_col[a_row > 0] | ||
|
||
if len(yy_m1) > 0: | ||
new_gdq[i_int, i_grp, yy_m1, i_col] = \ | ||
np.bitwise_or(new_gdq[i_int, i_grp, yy_m1, i_col], CHLO | DNU) | ||
|
||
new_gdq[wh_gdq_DNU == 1] = gdq_orig[wh_gdq_DNU == 1] # reset for earlier DNUs | ||
|
||
# Pixel to the south | ||
yy_max_p1 = a_row[a_row < (n_rows-1)] + 1 | ||
i_int = a_int[a_row < (n_rows-1)] | ||
i_grp = a_grp[a_row < (n_rows-1)] | ||
i_col = a_col[a_row < (n_rows-1)] | ||
|
||
if len(yy_max_p1) > 0: | ||
new_gdq[i_int, i_grp, yy_max_p1, i_col] = \ | ||
np.bitwise_or(new_gdq[i_int, i_grp, yy_max_p1, i_col], CHLO | DNU) | ||
|
||
new_gdq[wh_gdq_DNU == 1] = gdq_orig[wh_gdq_DNU == 1] # reset for earlier DNUs | ||
|
||
return new_gdq |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#! /usr/bin/env python | ||
import logging | ||
|
||
from ..stpipe import Step | ||
|
||
from stdatamodels.jwst import datamodels | ||
|
||
from . import charge_migration | ||
|
||
log = logging.getLogger(__name__) | ||
log.setLevel(logging.DEBUG) | ||
|
||
__all__ = ["ChargeMigrationStep"] | ||
|
||
|
||
class ChargeMigrationStep(Step): | ||
""" | ||
This Step sets the CHARGELOSS flag for groups exhibiting significant | ||
charge migration. | ||
""" | ||
class_alias = "charge_migration" | ||
|
||
spec = """ | ||
signal_threshold = float(default=30000) | ||
skip = boolean(default=True) | ||
""" | ||
|
||
def process(self, input): | ||
|
||
# Open the input data model | ||
with datamodels.RampModel(input) as input_model: | ||
if (input_model.data.shape[1] < 3): # skip step if only 1 or 2 groups/integration | ||
log.info('Too few groups per integration; skipping charge_migration') | ||
|
||
result = input_model | ||
result.meta.cal_step.charge_migration = 'SKIPPED' | ||
|
||
return result | ||
|
||
# Retrieve the parameter value(s) | ||
signal_threshold = self.signal_threshold | ||
|
||
result = charge_migration.charge_migration(input_model, signal_threshold) | ||
result.meta.cal_step.charge_migration = 'COMPLETE' | ||
|
||
return result |
Oops, something went wrong.