Skip to content

Commit 1d7bf37

Browse files
emolterzacharyburnett
authored andcommitted
Backport PR #9507: JP-4021: Fix a bug where insufficient valid background pixels case was not caught for WFSS background step
1 parent 1b78507 commit 1d7bf37

File tree

3 files changed

+55
-10
lines changed

3 files changed

+55
-10
lines changed

changes/9507.background.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a bug where highly-masked input data for wfss modes were raising errors instead of skipping

jwst/background/background_sub_wfss.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ def subtract_wfss_bkg(
6666
# i.e. in regions we can use as background.
6767
if got_catalog:
6868
bkg_mask = _mask_from_source_cat(input_model, wl_range_name, mmag_extract)
69-
if not _sufficient_background_pixels(input_model.dq, bkg_mask):
69+
if not _sufficient_background_pixels(input_model.dq, bkg_mask, bkg_ref.data):
7070
log.warning("Not enough background pixels to work with.")
7171
log.warning("Step will be SKIPPED.")
72+
bkg_ref.close()
7273
return None
7374
else:
7475
bkg_mask = np.ones(input_model.data.shape, dtype=bool)
@@ -86,6 +87,15 @@ def subtract_wfss_bkg(
8687
bkg = bkg_ref.data.copy()
8788
factor, _ = rescaler(sci, bkg, var, mask=~bkg_mask)
8889

90+
# check for bad value of factor
91+
if not np.isfinite(factor):
92+
log.warning(
93+
"Could not determine a finite scaling factor between reference background and data."
94+
" Step will be SKIPPED."
95+
)
96+
bkg_ref.close()
97+
return None
98+
8999
# extract the derived factor and apply it to the unmasked, non-outlier-rejected data
90100
subtract_this = factor * bkg_ref.data
91101
result = input_model.copy()
@@ -226,18 +236,40 @@ def _compute_rms_residual(self, sci_sub):
226236
return np.sqrt(np.nanmean(sci_sub_profile**2))
227237

228238

229-
def _sufficient_background_pixels(dq_array, bkg_mask, min_pixels=100):
230-
"""Count number of good pixels for background use.
239+
def _sufficient_background_pixels(dq_array, bkg_mask, bkg, min_pixfrac=0.05):
240+
"""
241+
Count number of good pixels for background use.
231242
232243
Check DQ flags of pixels selected for bkg use - XOR the DQ values with
233244
the DO_NOT_USE flag to flip the DO_NOT_USE bit. Then count the number
234245
of pixels that AND with the DO_NOT_USE flag, i.e. initially did not have
235246
the DO_NOT_USE bit set.
247+
248+
Parameters
249+
----------
250+
dq_array : ndarray
251+
Subarray input DQ array
252+
253+
bkg_mask : ndarray
254+
Boolean background mask. True where background is GOOD.
255+
256+
bkg : ndarray
257+
Background data array
258+
259+
min_pixfrac : float, optional
260+
Minimum fraction of good pixels required for background use.
261+
Default is 0.05 (5%).
262+
263+
Returns
264+
-------
265+
int or array of int
266+
The number of good pixels for background use.
236267
"""
237-
return np.count_nonzero((dq_array[bkg_mask]
238-
^ pixel['DO_NOT_USE'])
239-
& pixel['DO_NOT_USE']
240-
) > min_pixels
268+
good_bkg = bkg != 0
269+
good_mask = np.logical_and(bkg_mask, good_bkg)
270+
n_good = np.count_nonzero((dq_array[good_mask] ^ pixel["DO_NOT_USE"]) & pixel["DO_NOT_USE"])
271+
min_pixels = int(min_pixfrac * dq_array.size)
272+
return n_good > min_pixels
241273

242274

243275
def _mask_from_source_cat(input_model, wl_range_name, mmag_extract=None):

jwst/background/tests/test_background_wfss.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,15 +294,27 @@ def test_sufficient_background_pixels():
294294
model.dq[:, :4] = refpix_flags
295295
model.dq[:, -4:] = refpix_flags
296296

297+
bkg = np.ones((2048, 2048), dtype=float)
298+
297299
bkg_mask = np.ones((2048, 2048), dtype=bool)
298-
# With full array minux refpix available for bkg, should be sufficient
299-
assert _sufficient_background_pixels(model.dq, bkg_mask)
300+
# With full array minus refpix available for bkg, should be sufficient
301+
assert _sufficient_background_pixels(model.dq, bkg_mask, bkg)
300302

301303
bkg_mask[4: -4, :] = 0
302304
bkg_mask[:, 4: -4] = 0
303305
# Now mask out entire array, mocking full source coverage of detector -
304306
# no pixels should be available for bkg
305-
assert not _sufficient_background_pixels(model.dq, bkg_mask)
307+
assert not _sufficient_background_pixels(model.dq, bkg_mask, bkg)
308+
309+
310+
def test_sufficient_background_pixels_nonoverlapping():
311+
"""Valid pixels in bkg, and valid pixels in bkg_mask, but these do not overlap."""
312+
dq = np.zeros((2048, 2048), dtype=int)
313+
bkg_mask = np.zeros((2048, 2048), dtype=bool)
314+
bkg = np.zeros((2048, 2048), dtype=float)
315+
bkg_mask[:1024, :1024] = 1
316+
bkg[1024:, 1024:] = 1.0
317+
assert not _sufficient_background_pixels(dq, bkg_mask, bkg)
306318

307319

308320
def test_weighted_mean(make_wfss_datamodel, bkg_file):

0 commit comments

Comments
 (0)