Skip to content

Commit daa928d

Browse files
committed
JP-3967: SATURATION flag for partially saturated pixels should be propagated to the _rate DQ
1 parent 7162375 commit daa928d

File tree

4 files changed

+28
-30
lines changed

4 files changed

+28
-30
lines changed

changes/421.apichange.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Set saturation flag for any saturation. This reverts back to saturation flagging behavior prior to #125

docs/stcal/ramp_fitting/description.rst

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,11 @@ Segment-specific Computations
195195
+++++++++++++++++++++++++++++
196196
The variance of the slope of a segment due to read noise is:
197197

198-
.. math::
198+
.. math::
199199
var^R_{s} = \frac{12 \ R^2 }{ (ngroups_{s}^3 - ngroups_{s})(tgroup^2)(gain^2) } \,,
200200
201-
where :math:`R` is the noise in the difference between 2 frames,
202-
:math:`ngroups_{s}` is the number of groups in the segment, and :math:`tgroup` is the group
201+
where :math:`R` is the noise in the difference between 2 frames,
202+
:math:`ngroups_{s}` is the number of groups in the segment, and :math:`tgroup` is the group
203203
time in seconds (from the keyword TGROUP). The divide by gain converts to
204204
:math:`DN`. For the special case where as segment has length 1, the
205205
:math:`ngroups_{s}` is set to :math:`2`.
@@ -272,7 +272,7 @@ The square-root of the combined variance is stored in the ERR array of the outpu
272272
The overall slope depends on the slope and the combined variance of the slope of each integration's
273273
segments, so is a sum over integration values computed from the segements:
274274

275-
.. math::
275+
.. math::
276276
slope_{o} = \frac{ \sum_{i}{ \frac{slope_{i}} {var^C_{i}}}} { \sum_{i}{ \frac{1} {var^C_{i}}}}
277277
278278
@@ -300,7 +300,7 @@ Data Quality Propagation
300300
For a given pixel, if all groups in an integration are flagged as DO_NOT_USE or
301301
SATURATED, then that pixel will be flagged as DO_NOT_USE in the corresponding
302302
integration in the "rateints" product. Note this does NOT mean that all groups
303-
are flagged as SATURATED, nor that all groups are flagged as DO_NOT_USE. For
303+
are flagged as DO_NOT_USE. For
304304
example, slope calculations that are suppressed due to a ramp containing only
305305
one good group will be flagged as DO_NOT_USE in the
306306
first group, but not necessarily any other group, while only groups two and
@@ -312,9 +312,9 @@ For a given pixel, if all groups in an integration are flagged as SATURATED,
312312
then that pixel will be flagged as SATURATED and DO_NOT_USE in the corresponding
313313
integration in the "rateints" product. This is different from the above case in
314314
that this is only for all groups flagged as SATURATED, not for some combination
315-
of DO_NOT_USE and SATURATED. Further, only if all integrations in the "rateints"
316-
product are flagged as SATURATED, then the pixel will be flagged as SATURATED
317-
and DO_NOT_USE in the "rate" product.
315+
of DO_NOT_USE and SATURATED. Furthermore, if any integration in the "rateints"
316+
product is flagged as SATURATED, then the pixel will be flagged as SATURATED
317+
in the "rate" product.
318318

319319
For a given pixel, if any group in an integration is flagged as JUMP_DET, then
320320
that pixel will be flagged as JUMP_DET in the corresponding integration in the
@@ -338,12 +338,12 @@ group/resultant directly, the likelihood algorithm is based on differences of
338338
the groups/resultants :math:`d_i = r_i - r_{i-1}`. The model used to determine
339339
the slope/countrate, :math:`a`, is:
340340

341-
.. math::
341+
.. math::
342342
\chi^2 = ({\bf d} - a \cdot {\bf 1})^T C ({\bf d} - a \cdot {\bf 1}) \,,
343343
344-
Differentiating, setting to zero, then solving for :math:`a` results in
344+
Differentiating, setting to zero, then solving for :math:`a` results in
345345

346-
.. math::
346+
.. math::
347347
a = ({\bf 1}^T C {\bf d})({\bf 1}^T C {\bf 1})^T \,,
348348
349349
The covariance matrix :math:`C` is a tridiagonal matrix, due to the nature of the

src/stcal/ramp_fitting/utils.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#
33
# utils.py: utility functions
44
import logging
5-
import warnings
65

76
import numpy as np
87

@@ -146,11 +145,11 @@ def dq_compress_final(dq_int, ramp_data):
146145
dnu = np.uint32(ramp_data.flags_do_not_use)
147146
sat = np.uint32(ramp_data.flags_saturated)
148147

149-
# Remove DO_NOT_USE and SATURATED because they need special handling.
150-
# These flags are not set in the final pixel DQ array by simply being set
148+
# Remove DO_NOT_USE because it needs special handling.
149+
# This flag is not set in the final pixel DQ array by simply being set
151150
# in one of the integrations.
152-
not_sat_or_dnu = np.uint32(~(dnu | sat))
153-
final_dq = np.bitwise_and(final_dq, not_sat_or_dnu)
151+
not_dnu = np.uint32(~dnu)
152+
final_dq = np.bitwise_and(final_dq, not_dnu)
154153

155154
# If all integrations are DO_NOT_USE or SATURATED, then set DO_NOT_USE.
156155
set_if_total_integ(final_dq, dq_int, dnu | sat, dnu)

tests/test_ramp_fitting.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import pytest
21
import numpy as np
32

43
import sys
@@ -449,7 +448,6 @@ def test_2_group_cases():
449448
"""
450449
# XXX JP-3121: Still needs work
451450
base_group = [-12328.601, -4289.051]
452-
base_err = [0.0, 0.0]
453451
gain_val = 0.9699
454452
rnoise_val = 9.4552
455453

@@ -511,7 +509,7 @@ def test_2_group_cases():
511509
check = np.array([[551.0735, np.nan, np.nan, np.nan, -293.9943, -845.0678, -845.0677]])
512510
np.testing.assert_allclose(data, check, tol)
513511

514-
check = np.array([[GOOD, DNU | SAT, DNU | SAT, DNU, GOOD, GOOD, GOOD]])
512+
check = np.array([[GOOD, DNU | SAT, DNU | SAT, DNU | SAT, GOOD, GOOD, SAT]])
515513
# np.testing.assert_allclose(dq, check, tol) # XXX double
516514

517515
check = np.array([[38.945766, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
@@ -597,7 +595,7 @@ def test_one_group_ramp_suppressed_one_integration():
597595
check = np.array([[np.nan, np.nan, 1.0000001]])
598596
np.testing.assert_allclose(sdata, check, tol)
599597

600-
check = np.array([[DNU | SAT, DNU, GOOD]])
598+
check = np.array([[DNU | SAT, DNU | SAT, GOOD]])
601599
# np.testing.assert_allclose(sdq, check, tol) # XXX double
602600

603601
check = np.array([[0.0, 0.0, 0.25]])
@@ -615,7 +613,7 @@ def test_one_group_ramp_suppressed_one_integration():
615613
check = np.array([[[np.nan, np.nan, 1.0000001]]])
616614
np.testing.assert_allclose(cdata, check, tol)
617615

618-
check = np.array([[[DNU | SAT, DNU, GOOD]]])
616+
check = np.array([[[DNU | SAT, DNU | SAT, GOOD]]])
619617
# np.testing.assert_allclose(cdq, check, tol) # XXX double
620618

621619
check = np.array([[[0.0, 0.0, 0.25]]])
@@ -642,7 +640,7 @@ def test_one_group_ramp_not_suppressed_one_integration():
642640
check = np.array([[np.nan, 1.0, 1.0000001]])
643641
np.testing.assert_allclose(sdata, check, tol)
644642

645-
check = np.array([[DNU | SAT, GOOD, GOOD]])
643+
check = np.array([[DNU | SAT, SAT, GOOD]])
646644
# np.testing.assert_allclose(sdq, check, tol) # XXX double
647645

648646
check = np.array([[0.0, 1.0, 0.25]])
@@ -660,7 +658,7 @@ def test_one_group_ramp_not_suppressed_one_integration():
660658
check = np.array([[[np.nan, 1.0, 1.0000001]]])
661659
np.testing.assert_allclose(cdata, check, tol)
662660

663-
check = np.array([[[DNU | SAT, GOOD, GOOD]]])
661+
check = np.array([[[DNU | SAT, SAT, GOOD]]])
664662
# np.testing.assert_allclose(cdq, check, tol) # XXX double
665663

666664
check = np.array([[[0.0, 1, 0.25]]])
@@ -688,7 +686,7 @@ def test_one_group_ramp_suppressed_two_integrations():
688686
check = np.array([[1.0000001, 1.0000001, 1.0000001]])
689687
np.testing.assert_allclose(sdata, check, tol)
690688

691-
check = np.array([[GOOD, GOOD, GOOD]])
689+
check = np.array([[SAT, SAT, GOOD]])
692690
np.testing.assert_allclose(sdq, check, tol)
693691

694692
check = np.array([[0.125, 0.125, 0.125]])
@@ -706,7 +704,7 @@ def test_one_group_ramp_suppressed_two_integrations():
706704
check = np.array([[[np.nan, np.nan, 1.0000001]], [[1.0000001, 1.0000001, 1.0000001]]])
707705
np.testing.assert_allclose(cdata, check, tol)
708706

709-
check = np.array([[[DNU | SAT, DNU, GOOD]], [[GOOD, GOOD, GOOD]]])
707+
check = np.array([[[DNU | SAT, DNU | SAT, GOOD]], [[GOOD, GOOD, GOOD]]])
710708
# np.testing.assert_allclose(cdq, check, tol) # XXX double
711709

712710
check = np.array([[[0.0, 0.0, 0.25]], [[0.125, 0.125, 0.25]]])
@@ -734,7 +732,7 @@ def test_one_group_ramp_not_suppressed_two_integrations():
734732
check = np.array([[1.0000001, 1.0000001, 1.0000001]])
735733
np.testing.assert_allclose(sdata, check, tol)
736734

737-
check = np.array([[GOOD, GOOD, GOOD]])
735+
check = np.array([[SAT, SAT, GOOD]])
738736
np.testing.assert_allclose(sdq, check, tol)
739737

740738
check = np.array([[0.125, 0.2, 0.125]])
@@ -752,7 +750,7 @@ def test_one_group_ramp_not_suppressed_two_integrations():
752750
check = np.array([[[np.nan, 1.0, 1.0000001]], [[1.0000001, 1.0000001, 1.0000001]]])
753751
np.testing.assert_allclose(cdata, check, tol)
754752

755-
check = np.array([[[DNU | SAT, GOOD, GOOD]], [[GOOD, GOOD, GOOD]]])
753+
check = np.array([[[DNU | SAT, SAT, GOOD]], [[GOOD, GOOD, GOOD]]])
756754
# np.testing.assert_allclose(cdq, check, tol) # XXX double
757755

758756
check = np.array([[[0.0, 1.0, 0.25]], [[0.125, 0.25, 0.25]]])
@@ -866,7 +864,7 @@ def test_zeroframe():
866864
check = np.array([[48.965397, 18.628912, 47.863224]])
867865
np.testing.assert_allclose(sdata, check, tol, tol)
868866

869-
check = np.array([[GOOD, GOOD, GOOD]])
867+
check = np.array([[SAT, SAT, SAT]])
870868
np.testing.assert_allclose(sdq, check, tol, tol)
871869

872870
check = np.array([[0.13110262, 0.00867591, 0.29745975]])
@@ -887,7 +885,7 @@ def test_zeroframe():
887885
check = np.array([[[298.0626, np.nan, 652.01196]], [[18.62891, 18.62891, 18.62891]]])
888886
np.testing.assert_allclose(cdata, check, tol, tol)
889887

890-
check = np.array([[[GOOD, DNU | SAT, GOOD]], [[GOOD, GOOD, GOOD]]])
888+
check = np.array([[[SAT, DNU | SAT, SAT]], [[GOOD, GOOD, GOOD]]])
891889
# np.testing.assert_allclose(cdq, check, tol, tol) # XXX double
892890

893891
check = np.array([[[1.1799237, 0.0, 6.246655]], [[0.14749046, 0.00867591, 0.31233275]]])
@@ -1463,7 +1461,7 @@ def test_one_group():
14631461
sdata, sdq, svp, svr, serr = slopes
14641462

14651463
# XXX JP-3121: this is the value from python, which may not be correct
1466-
chk_data = 1.9618962
1464+
chk_data = 1.9618962
14671465
chk_dq = 0
14681466
chk_var_p = 0.02923839
14691467
chk_var_r = 0.03470363

0 commit comments

Comments
 (0)