Skip to content

Commit

Permalink
JP-3426: Ensure proper order of bitwise operations (spacetelescope#8916)
Browse files Browse the repository at this point in the history
  • Loading branch information
tapastro authored Oct 31, 2024
1 parent ae0fa9e commit 2a55d5b
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 8 deletions.
1 change: 1 addition & 0 deletions changes/8916.background.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Apply bitwise operations in correct order when counting good pixels in the background mask during WFSS background subtraction.
22 changes: 15 additions & 7 deletions jwst/background/background_sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,20 @@ def average_background(input_model, bkg_list, sigma, maxiters):
return avg_bkg


def sufficient_background_pixels(dq_array, bkg_mask, min_pixels=100):
"""Count number of good pixels for background use.
Check DQ flags of pixels selected for bkg use - XOR the DQ values with
the DO_NOT_USE flag to flip the DO_NOT_USE bit. Then count the number
of pixels that AND with the DO_NOT_USE flag, i.e. initially did not have
the DO_NOT_USE bit set.
"""
return np.count_nonzero((dq_array[bkg_mask]
^ pixel['DO_NOT_USE'])
& pixel['DO_NOT_USE']
) > min_pixels


def subtract_wfss_bkg(input_model, bkg_filename, wl_range_name, mmag_extract=None):
"""Scale and subtract a background reference image from WFSS/GRISM data.
Expand Down Expand Up @@ -310,18 +324,12 @@ def subtract_wfss_bkg(input_model, bkg_filename, wl_range_name, mmag_extract=Non
# i.e. in regions we can use as background.
if got_catalog:
bkg_mask = mask_from_source_cat(input_model, wl_range_name, mmag_extract)
# Ensure mask has 100 pixels and that those pixels correspond to valid
# pixels using model DQ array
if np.count_nonzero(input_model.dq[bkg_mask]
^ pixel['DO_NOT_USE']
& pixel['DO_NOT_USE']
) < 100:
if not sufficient_background_pixels(input_model.dq, bkg_mask):
log.warning("Not enough background pixels to work with.")
log.warning("Step will be SKIPPED.")
return None
else:
bkg_mask = np.ones(input_model.data.shape, dtype=bool)

# Compute the mean values of science image and background reference
# image, including only regions where there are no identified sources.
# Exclude pixel values in the lower and upper 25% of the histogram.
Expand Down
24 changes: 23 additions & 1 deletion jwst/background/tests/test_background.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
from numpy.testing import assert_allclose

from stdatamodels.jwst import datamodels
from stdatamodels.jwst.datamodels.dqflags import pixel

from jwst.assign_wcs import AssignWcsStep
from jwst.background import BackgroundStep
from jwst.stpipe import Step
from jwst.background.background_sub import robust_mean, mask_from_source_cat, no_NaN
from jwst.background.background_sub import (robust_mean, mask_from_source_cat,
no_NaN, sufficient_background_pixels)


@pytest.fixture(scope="module")
Expand Down Expand Up @@ -403,3 +405,23 @@ def test_no_nan():

# Make sure arrays are equal.
assert np.array_equal(model.data, result.data)


def test_sufficient_background_pixels():
model = datamodels.ImageModel(data=np.zeros((2048, 2048)),
dq=np.zeros((2048, 2048)))
refpix_flags = pixel['DO_NOT_USE'] | pixel['REFERENCE_PIXEL']
model.dq[:4, :] = refpix_flags
model.dq[-4:, :] = refpix_flags
model.dq[:, :4] = refpix_flags
model.dq[:, -4:] = refpix_flags

bkg_mask = np.ones((2048, 2048), dtype=bool)
# With full array minux refpix available for bkg, should be sufficient
assert sufficient_background_pixels(model.dq, bkg_mask)

bkg_mask[4: -4, :] = 0
bkg_mask[:, 4: -4] = 0
# Now mask out entire array, mocking full source coverage of detector -
# no pixels should be available for bkg
assert not sufficient_background_pixels(model.dq, bkg_mask)

0 comments on commit 2a55d5b

Please sign in to comment.