Skip to content
1 change: 1 addition & 0 deletions changes/9625.combine_1d.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow all-NaN spectra to be skipped instead of causing crashes
12 changes: 12 additions & 0 deletions jwst/combine_1d/combine1d.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,12 @@
else:
spectra = input_model.spec
for in_spec in spectra:
if not np.any(np.isfinite(in_spec.spec_table.field("flux"))):
log.warning(

Check warning on line 731 in jwst/combine_1d/combine1d.py

View check run for this annotation

Codecov / codecov/patch

jwst/combine_1d/combine1d.py#L730-L731

Added lines #L730 - L731 were not covered by tests
f"Input spectrum {in_spec.source_id} order {in_spec.spectral_order} "
f"from group_id {in_spec.meta.group_id} has no valid flux values; skipping."
)
continue

Check warning on line 735 in jwst/combine_1d/combine1d.py

View check run for this annotation

Codecov / codecov/patch

jwst/combine_1d/combine1d.py#L735

Added line #L735 was not covered by tests
spectral_order = in_spec.spectral_order
if spectral_order not in input_spectra:
input_spectra[spectral_order] = []
Expand Down Expand Up @@ -768,6 +774,12 @@
else:
_read_input_spectra(input_model, exptime_key, input_spectra)

if len(input_spectra) == 0:
log.error("No valid input spectra found for source. Skipping.")
result = input_model.copy()
result.meta.cal_step.combine_1d = "SKIPPED"
return result

Check warning on line 781 in jwst/combine_1d/combine1d.py

View check run for this annotation

Codecov / codecov/patch

jwst/combine_1d/combine1d.py#L777-L781

Added lines #L777 - L781 were not covered by tests

for order in input_spectra:
output_spectra[order] = OutputSpectrumModel()
output_spectra[order].assign_wavelengths(input_spectra[order])
Expand Down
10 changes: 9 additions & 1 deletion jwst/combine_1d/combine_1d_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,15 @@
result = combine1d.combine_1d_spectra(
model, self.exptime_key, sigma_clip=self.sigma_clip
)
results_list.append(result)
if not result.meta.cal_step.combine_1d == "SKIPPED":
results_list.append(result)
if not results_list:
self.log.error(

Check warning on line 77 in jwst/combine_1d/combine_1d_step.py

View check run for this annotation

Codecov / codecov/patch

jwst/combine_1d/combine_1d_step.py#L74-L77

Added lines #L74 - L77 were not covered by tests
"No valid input spectra found in WFSSMultiSpecModel. Skipping."
)
result = input_model.copy()
result.meta.cal_step.combine_1d = "SKIPPED"
return result

Check warning on line 82 in jwst/combine_1d/combine_1d_step.py

View check run for this annotation

Codecov / codecov/patch

jwst/combine_1d/combine_1d_step.py#L80-L82

Added lines #L80 - L82 were not covered by tests
result = make_wfss_multicombined(results_list)
result.meta.cal_step.combine_1d = "COMPLETE"
return result
Expand Down
34 changes: 34 additions & 0 deletions jwst/combine_1d/tests/test_combine1d.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import numpy as np
import pytest
import logging
from jwst.tests.helpers import LogWatcher

from jwst import datamodels

Expand Down Expand Up @@ -227,3 +229,35 @@ def test_wfss_multi_input(wfss_multiexposure):
assert np.all(tab["SOURCE_TYPE"] == "POINT")

assert result.spec[0].dispersion_direction == 3


def test_allnan_skip(wfss_multiexposure, monkeypatch):
"""Test that all-nan spectra are skipped."""
# Set all flux values to NaN
for spec in wfss_multiexposure.spec:
spec.spec_table["FLUX"][:] = np.nan

# message when a single spectrum has no valid flux values
watcher0 = LogWatcher(
"Input spectrum 5 order 1 from group_id 1 has no valid flux values; skipping."
)
monkeypatch.setattr(logging.getLogger("jwst.combine_1d.combine1d"), "warning", watcher0)
result = Combine1dStep.call(wfss_multiexposure)
assert result.meta.cal_step.combine_1d == "SKIPPED"
watcher0.assert_seen()

# check for the other log messages
# these must be done one at a time because the watcher can only be monkeypatched once
# message when no valid input spectra are found for the source
watcher1 = LogWatcher("No valid input spectra found for source. Skipping.")
monkeypatch.setattr(logging.getLogger("jwst.combine_1d.combine1d"), "error", watcher1)
result = Combine1dStep.call(wfss_multiexposure)
assert result.meta.cal_step.combine_1d == "SKIPPED"
watcher1.assert_seen()

# message when no valid input spectra at all are found
watcher2 = LogWatcher("No valid input spectra found in WFSSMultiSpecModel")
monkeypatch.setattr(logging.getLogger("stpipe.Combine1dStep"), "error", watcher2)
result = Combine1dStep.call(wfss_multiexposure)
assert result.meta.cal_step.combine_1d == "SKIPPED"
watcher2.assert_seen()
18 changes: 11 additions & 7 deletions jwst/pipeline/calwebb_spec3.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,13 +296,17 @@
extraction_complete = (
result is not None and result.meta.cal_step.extract_1d == "COMPLETE"
)
if extraction_complete:
# Combine the results for all sources
comb = self.combine_1d.run(result)
# add metadata that only WFSS wants
comb.spec[0].source_ra = result.spec[0].spec_table["SOURCE_RA"][0]
comb.spec[0].source_dec = result.spec[0].spec_table["SOURCE_DEC"][0]
wfss_comb.append(comb)
if not extraction_complete:
continue

Check warning on line 300 in jwst/pipeline/calwebb_spec3.py

View check run for this annotation

Codecov / codecov/patch

jwst/pipeline/calwebb_spec3.py#L299-L300

Added lines #L299 - L300 were not covered by tests
# Combine the results for all sources
comb = self.combine_1d.run(result)
comb_complete = comb is not None and comb.meta.cal_step.combine_1d == "COMPLETE"
if not comb_complete:
continue

Check warning on line 305 in jwst/pipeline/calwebb_spec3.py

View check run for this annotation

Codecov / codecov/patch

jwst/pipeline/calwebb_spec3.py#L302-L305

Added lines #L302 - L305 were not covered by tests
# add metadata that only WFSS wants
comb.spec[0].source_ra = result.spec[0].spec_table["SOURCE_RA"][0]
comb.spec[0].source_dec = result.spec[0].spec_table["SOURCE_DEC"][0]
wfss_comb.append(comb)

Check warning on line 309 in jwst/pipeline/calwebb_spec3.py

View check run for this annotation

Codecov / codecov/patch

jwst/pipeline/calwebb_spec3.py#L307-L309

Added lines #L307 - L309 were not covered by tests

elif resample_complete is not None and resample_complete.upper() == "COMPLETE":
# If 2D data were resampled and combined, just do a 1D extraction
Expand Down