Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JP-3593: Saturation step should increase flagging for group 3 saturation #8499

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9e79eff
check for saturation bias in group 2 for nframes > 1
penaguerrero May 21, 2024
f2ba9c8
added PR number
penaguerrero May 21, 2024
9335de7
Merge branch 'master' into jp3593
penaguerrero May 22, 2024
d4658b3
fixed tests and code
penaguerrero May 22, 2024
f8e394c
avoid breaking Roman code
penaguerrero May 22, 2024
a436b40
Merge branch 'master' into jp3593
penaguerrero May 23, 2024
5333cea
Merge branch 'master' into jp3593
penaguerrero May 28, 2024
0455eb1
added changes to implement read_pattern solution
penaguerrero May 28, 2024
5a2601c
Merge branch 'master' into jp3593
penaguerrero May 30, 2024
85a7bab
removing previous code and adding modification to read_pattern code
penaguerrero May 31, 2024
4300770
Merge branch 'master' into jp3593
penaguerrero May 31, 2024
d64c67c
Merge branch 'master' into jp3593
penaguerrero Jun 3, 2024
9948880
Merge branch 'master' into jp3593
penaguerrero Jun 5, 2024
0f145e5
Merge branch 'master' into jp3593
penaguerrero Jun 6, 2024
343b631
Merge branch 'master' into jp3593
penaguerrero Jun 7, 2024
17677b0
fixing calling the right array and index accessing
penaguerrero Jun 7, 2024
f7271da
Merge branch 'master' into jp3593
penaguerrero Jun 17, 2024
b632603
addressing comments
penaguerrero Jun 17, 2024
850aa05
addressing comments
penaguerrero Jun 17, 2024
9b01f26
addressing comments
penaguerrero Jun 17, 2024
444b11e
Merge branch 'master' into jp3593
penaguerrero Jun 19, 2024
66d98d3
Merge branch 'master' into jp3593
penaguerrero Jun 20, 2024
fdcbd8d
Merge branch 'master' into jp3593
penaguerrero Jun 21, 2024
1207d58
Merge branch 'master' into jp3593
penaguerrero Jun 24, 2024
8f90a84
Merge branch 'master' into jp3593
penaguerrero Jun 24, 2024
be2b053
Merge branch 'master' into jp3593
penaguerrero Jun 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ pixel_replace
- Added estimated errors and variances for replaced pixels, following the
interpolation scheme used for the data. [#8504]

saturation
----------

- Adds a check for saturation bias in group 2 for nframes > 1. [#8499]

ramp_fitting
------------

Expand Down
32 changes: 31 additions & 1 deletion jwst/saturation/saturation.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def flag_saturation(input_model, ref_model, n_pix_grow_sat):
"""

data = input_model.data
ngroups = input_model.meta.exposure.ngroups
nframes = input_model.meta.exposure.nframes

# Create the output model as a copy of the input
output_model = input_model.copy()
Expand All @@ -68,9 +70,10 @@ def flag_saturation(input_model, ref_model, n_pix_grow_sat):
sat_dq = ref_sub_model.dq.copy()
ref_sub_model.close()

read_pattern = [[x + 1 + groupstart * nframes for x in range(nframes)] for groupstart in range(ngroups)]
gdq_new, pdq_new, zframe = flag_saturated_pixels(
data, gdq, pdq, sat_thresh, sat_dq, ATOD_LIMIT, dqflags.pixel,
n_pix_grow_sat=n_pix_grow_sat, zframe=zframe)
n_pix_grow_sat=n_pix_grow_sat, read_pattern=read_pattern, zframe=zframe)

# Save the flags in the output GROUPDQ array
output_model.groupdq = gdq_new
Expand Down Expand Up @@ -117,6 +120,8 @@ def irs2_flag_saturation(input_model, ref_model, n_pix_grow_sat):
nints = data.shape[0]
ngroups = data.shape[1]
detector = input_model.meta.instrument.detector
nframes = input_model.meta.exposure.nframes
read_pattern = [[x + 1 + groupstart * nframes for x in range(nframes)] for groupstart in range(ngroups)]

# create a mask of the appropriate size
irs2_mask = x_irs2.make_mask(input_model)
Expand Down Expand Up @@ -160,6 +165,31 @@ def irs2_flag_saturation(input_model, ref_model, n_pix_grow_sat):
irs2_mask, detector)
# check for saturation
flag_temp = np.where(sci_temp >= sat_thresh, SATURATED, 0)
if group == 2:
# Identify groups which we wouldn't expect to saturate by the third group,
# on the basis of the first group
scigp1 = x_irs2.from_irs2(data[ints, 0, :, :], irs2_mask, detector)
mask = scigp1 / np.mean(read_pattern[0]) * read_pattern[2][-1] < sat_thresh

# Identify groups with suspiciously large values in the second group
scigp2 = x_irs2.from_irs2(data[ints, 1, :, :], irs2_mask, detector)
mask &= scigp2 > sat_thresh / len(read_pattern[1])

# Identify groups that are saturated in the third group
gp3mask = np.where(flag_temp & SATURATED, True, False)
mask &= gp3mask

# Flag the 2nd group for the pixels passing that gauntlet
dq_temp = x_irs2.from_irs2(groupdq[ints, 1, :, :], irs2_mask, detector)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nearly there, but I think this line is problematic. Since it's using the existing groupdq array, it's going to be growing ALL pixels flagged as SATURATED, not just those that passed the gauntlet above, so things in group1 will get grown twice.

I think this should be possible to deal with by replacing
dq_temp = x_irs2.from_irs2(groupdq[ints, 1, :, :], irs2_mask, detector)
with
dq_temp = np.zeros_like(mask).astype(int)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it would probably be better form though to explicitly cast the dq_temp to be the same dtype as groupdq.

dq_temp[mask] |= SATURATED
# flag any pixels that border saturated pixels
if n_pix_grow_sat > 0:
dq_temp = adjacency_sat(dq_temp, SATURATED, n_pix_grow_sat)
# set the flags in dq array for group 2, i.e. index 1
x_irs2.to_irs2(flagarray, dq_temp, irs2_mask, detector)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is being passed back correctly; we're populating flagarray, but flagarray only gets put into the groupdq array a few lines later for group==2 whereas we're trying to set saturation bits for group==1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@drlaw1558 I made some changes and I believe you were correct and now it sets the flags ok, can you verify please?

np.bitwise_or(groupdq[ints, 1, ...], flagarray,
groupdq[ints, 1, ...])

# check for A/D floor
flaglow_temp = np.where(sci_temp <= 0, AD_FLOOR | DONOTUSE, 0)

Expand Down
9 changes: 7 additions & 2 deletions jwst/saturation/tests/test_saturation.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ def test_basic_saturation_flagging(setup_nrc_cube):
# Add ramp values up to the saturation limit
data.data[0, 0, 5, 5] = 0
data.data[0, 1, 5, 5] = 20000
data.data[0, 2, 5, 5] = 40000
data.data[0, 3, 5, 5] = 60000 # Signal reaches saturation limit
data.data[0, 2, 5, 5] = 60000 # Signal reaches saturation limit
data.data[0, 3, 5, 5] = 60000
data.data[0, 4, 5, 5] = 62000

# Set saturation value in the saturation model
Expand Down Expand Up @@ -386,6 +386,7 @@ def _cube(ngroups, nrows, ncols):
data_model.meta.subarray.xsize = ncols
data_model.meta.subarray.ysize = nrows
data_model.meta.exposure.ngroups = ngroups
data_model.meta.exposure.nframes = 3
data_model.meta.instrument.name = 'NIRCAM'
data_model.meta.instrument.detector = 'NRCA1'
data_model.meta.observation.date = '2017-10-01'
Expand Down Expand Up @@ -432,6 +433,8 @@ def _cube(xstart, ystart, ngroups, nrows, ncols):
data_model.meta.subarray.xsize = ncols
data_model.meta.subarray.ystart = ystart
data_model.meta.subarray.ysize = nrows
data_model.meta.exposure.ngroups = ngroups
data_model.meta.exposure.nframes = 3

# create a saturation model for the saturation step
saturation_model = SaturationModel((1032, 1024))
Expand Down Expand Up @@ -477,6 +480,8 @@ def _cube():
data_model.meta.exposure.nrs_normal = 16
data_model.meta.exposure.nrs_reference = 4
data_model.meta.exposure.readpatt = 'NRSIRS2RAPID'
data_model.meta.exposure.nframes = 3
data_model.meta.exposure.ngroups = 5

# create a saturation model for the saturation step
saturation_model = SaturationModel((2048, 2048))
Expand Down