Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions changes/9053.skymatch.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add option to pass in user-defined sky levels
8 changes: 7 additions & 1 deletion docs/jwst/skymatch/arguments.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The ``skymatch`` step uses the following optional arguments:

``skymethod`` (str, default='match')
The sky computation algorithm to be used.
Allowed values: `local`, `global`, `match`, `global+match`
Allowed values: `local`, `global`, `match`, `global+match`, `user`

``match_down`` (boolean, default=True)
Specifies whether the sky *differences* should be subtracted from images with
Expand All @@ -23,6 +23,12 @@ The ``skymatch`` step uses the following optional arguments:
the images. The BKGSUB keyword (boolean) will be set in each output image to
record whether or not the background was subtracted.

``skylist`` (list, default=None)
A list of user-defined sky values to be used for sky subtraction. The list
must be in the same order (and have the same length) as the input images,
irrespective of association grouping. This argument is used only when
``skymethod`` is set to `user`.

**Image bounding polygon parameters:**

``stepsize`` (int, default=None)
Expand Down
10 changes: 10 additions & 0 deletions docs/jwst/skymatch/description.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,16 @@ of sky in the images. This method cannot measure the true sky level, but
instead provides additive corrections that can be used to equalize the signal
between overlapping images.

User-Supplied Sky Values
-------------------------
The ``skymatch`` step can also accept user-supplied sky values for each image.
This is useful when sky values have been determined based on a custom workflow
outside the pipeline. To use this feature, the user must provide a list of sky
values matching the number of images (``skylist`` parameter) and set the
``skymethod`` parameter to "user". Note that the skylist will be applied on a
per-image basis irrespective of the groups defined in the association, and the
order of the list must match the order of the input images.

Examples
--------
To get a better idea of the behavior of these different methods, the tables below
Expand Down
7 changes: 3 additions & 4 deletions jwst/skymatch/skymatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from . skyimage import SkyImage, SkyGroup


__all__ = ['match']
__all__ = ['skymatch']


__author__ = 'Mihai Cara'
Expand All @@ -25,7 +25,7 @@
log.setLevel(logging.DEBUG)


def match(images, skymethod='global+match', match_down=True, subtract=False):
def skymatch(images, skymethod='global+match', match_down=True, subtract=False):
"""
A function to compute and/or "equalize" sky background in input images.

Expand Down Expand Up @@ -94,7 +94,6 @@ def match(images, skymethod='global+match', match_down=True, subtract=False):
subtract : bool (Default = False)
Subtract computed sky value from image data.


Raises
------

Expand Down Expand Up @@ -233,7 +232,7 @@ def match(images, skymethod='global+match', match_down=True, subtract=False):
in sky levels.

"""
function_name = match.__name__
function_name = skymatch.__name__

# Time it
runtime_begin = datetime.now()
Expand Down
41 changes: 38 additions & 3 deletions jwst/skymatch/skymatch_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@
from ..stpipe import Step

# LOCAL:
from .skymatch import match
from .skymatch import skymatch
from .skyimage import SkyImage, SkyGroup
from .skystatistics import SkyStats

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)


__all__ = ['SkyMatchStep']

Expand All @@ -42,9 +45,10 @@ class SkyMatchStep(Step):

spec = """
# General sky matching parameters:
skymethod = option('local', 'global', 'match', 'global+match', default='match') # sky computation method
skymethod = option('local', 'global', 'match', 'global+match', 'user', default='match') # sky computation method
match_down = boolean(default=True) # adjust sky to lowest measured value?
subtract = boolean(default=False) # subtract computed sky from image data?
skylist = list(default=None) # List of sky values to use when skymethod='user'

# Image's bounding polygon parameters:
stepsize = integer(default=None) # Max vertex separation
Expand Down Expand Up @@ -76,6 +80,10 @@ def process(self, input):
else:
library = ModelLibrary(input, on_disk=not self.in_memory)

# Method: "user". Use user-provided sky values, and bypass skymatch() altogether.
if self.skymethod == 'user':
return self._user_sky(library)

self._dqbits = interpret_bit_flags(self.dqbits, flag_name_map=pixel)

# set sky statistics:
Expand Down Expand Up @@ -105,7 +113,7 @@ def process(self, input):
images.append(SkyGroup(sky_images, id=group_index))

# match/compute sky values:
match(images, skymethod=self.skymethod, match_down=self.match_down,
skymatch(images, skymethod=self.skymethod, match_down=self.match_down,
subtract=self.subtract)

# set sky background value in each image's meta:
Expand Down Expand Up @@ -216,3 +224,30 @@ def _set_sky_background(self, sky_image, library, step_status):

dm.meta.cal_step.skymatch = step_status
library.shelve(dm, index)


def _user_sky(self, library):
"""Handle user-provided sky values for each image.
"""

log.info(" ")
log.info("---- Using user-provided sky values for each image.")

if self.skylist is None:
raise ValueError('skymethod set to "user", but no sky values provided.')
if len(self.skylist) != len(library):
raise ValueError(f"Number of entries in skylist ({len(self.skylist)}) does not match "
f"number of input images ({len(library)}).")

with library:
for i, model in enumerate(library):
sky = self.skylist[i]
model.meta.background.level = sky
model.meta.background.subtracted = self.subtract
model.meta.background.method = self.skymethod
if self.subtract:
model.data -= sky
model.meta.cal_step.skymatch = "COMPLETE"
library.shelve(model)

return library
2 changes: 1 addition & 1 deletion jwst/skymatch/skystatistics.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
`skystatistics` module provides statistics computation class used by
:py:func:`~jwst.skymatch.skymatch.match`
:py:func:`~jwst.skymatch.skymatch.skymatch`
and :py:class:`~jwst.skymatch.skyimage.SkyImage`.

:Authors: Mihai Cara (contact: [email protected])
Expand Down
38 changes: 36 additions & 2 deletions jwst/skymatch/tests/test_skymatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def _add_bad_pixels(im, sat_val, dont_use_val):
'skymethod, subtract, skystat, match_down, grouped',
tuple(
product(
['local', 'match', 'global', 'global+match'],
['local', 'match', 'global', 'global+match', 'user'],
[False, True],
['median', 'mean', 'midpt', 'mode'],
[False, True],
Expand Down Expand Up @@ -211,7 +211,8 @@ def test_skymatch(nircam_rate, skymethod, subtract, skystat, match_down,
skystat=skystat,
binwidth=0.2,
nclip=0,
dqbits='~DO_NOT_USE+SATURATED'
dqbits='~DO_NOT_USE+SATURATED',
skylist=levels
)

if skymethod == 'match' and grouped:
Expand Down Expand Up @@ -243,6 +244,9 @@ def test_skymatch(nircam_rate, skymethod, subtract, skystat, match_down,
elif skymethod == 'global':
ref_levels = len(levels) * [min(levels)]

elif skymethod == 'user':
ref_levels = levels

sub_levels = np.subtract(levels, ref_levels)

with result:
Expand Down Expand Up @@ -547,3 +551,33 @@ def test_skymatch_2x(tmp_cwd, nircam_rate, tmp_path, skymethod, subtract):
else:
assert abs(np.mean(im2.data[dq_mask]) - lev) < 0.01
result2.shelve(im2)


def test_user_sky_bad_inputs(nircam_rate):

im1 = nircam_rate.copy()
im2 = im1.copy()
im3 = im1.copy()

container = [im1, im2, im3]

# define some background:
levels = [9.12, 8.28, 2.56]

for im, lev in zip(container, levels):
im.data += lev

with pytest.raises(ValueError):
# skylist must be provided
SkyMatchStep.call(
container,
skymethod='user',
)

with pytest.raises(ValueError):
# skylist must have the same length as the number of input images
SkyMatchStep.call(
container,
skymethod='user',
skylist=levels[:-1]
)
Loading