Skip to content

Commit af55359

Browse files
emoltertapastro
authored andcommitted
JP-4151: Give TSO3 x1dints files an S_REGION (spacetelescope#9927)
1 parent 1bb7224 commit af55359

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

changes/9927.pipeline.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add S_REGION to x1dints files generated by calwebb_tso3

jwst/pipeline/calwebb_tso3.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ def process(self, input_data):
172172
log.warning("extract_1d step could not be completed for any integrations")
173173
log.warning("x1dints products will not be created.")
174174
else:
175+
# Set S_REGION to allow the x1dints file to show up in MAST spatial queries
176+
self._populate_tso_spectral_sregion(x1d_result, input_models)
175177
self.save_model(x1d_result, suffix="x1dints")
176178

177179
# Done with all the inputs
@@ -192,3 +194,47 @@ def process(self, input_data):
192194
# All done. Nothing to return, because all products have
193195
# been created here.
194196
return
197+
198+
def _populate_tso_spectral_sregion(self, model, cal_model_list):
199+
"""
200+
Generate cumulative S_REGION footprint from input images.
201+
202+
Take the input S_REGION values from all input models, and combine
203+
them using a polygon union to create a cumulative footprint for the output
204+
TSO spectral product.
205+
The union is performed in pixel coordinates to avoid distortion,
206+
so the WCS of the first input model is used to convert to and from sky coordinates.
207+
208+
Parameters
209+
----------
210+
model : `~stdatamodels.jwst.datamodels.TSOMultiSpecModel`
211+
The newly generated TSOMultiSpecModel made as part of
212+
the save operation for spec3 processing of TSO data.
213+
214+
cal_model_list : `~jwst.datamodels.ModelContainer`
215+
The input models provided to Tso3Pipeline by the
216+
input association.
217+
"""
218+
if (len(cal_model_list) == 0) or (len(model.spec) == 0):
219+
log.warning("No input or output models provided; cannot set S_REGION.")
220+
return
221+
222+
input_sregions = [
223+
w.meta.wcsinfo.s_region for w in cal_model_list if w.meta.wcsinfo.hasattr("s_region")
224+
]
225+
if len(input_sregions) == 0:
226+
log.warning(
227+
"No input model(s) have an `s_region` attribute; output S_REGION will not be set."
228+
)
229+
return
230+
if len(input_sregions) < len(cal_model_list):
231+
log.warning(
232+
"One or more input model(s) are missing an `s_region` attribute; "
233+
"output S_REGION will be set to first available value."
234+
)
235+
if not all(s == input_sregions[0] for s in input_sregions):
236+
log.warning(
237+
"Input models have different S_REGION values; this is unexpected for tso3 data. "
238+
"Setting output S_REGION to the value of the first model."
239+
)
240+
model.spec[0].s_region = input_sregions[0]

jwst/pipeline/tests/test_calwebb_tso3.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import stdatamodels.jwst.datamodels as dm
2+
13
from jwst.associations.asn_from_list import asn_from_list
4+
from jwst.datamodels import ModelContainer
25
from jwst.extract_1d.tests.helpers import mock_niriss_soss_96_func, mock_niriss_soss_full_func
36
from jwst.pipeline.calwebb_tso3 import Tso3Pipeline
47

@@ -23,6 +26,7 @@ def niriss_soss_tso(subarray="SUBSTRIP96"):
2326
else:
2427
input_model = mock_niriss_soss_96_func()
2528
input_model.meta.wcs = None
29+
input_model.meta.wcsinfo.s_region = "POLYGON ICRS 0 0 0 1 1 1 1 0"
2630
input_model.meta.visit.tsovisit = True
2731
input_model.int_times = input_model.int_times
2832
return input_model
@@ -59,6 +63,9 @@ def test_niriss_soss(tmp_path):
5963
for filename in expected:
6064
assert (tmp_path / filename).exists()
6165

66+
with dm.open(tmp_path / "test_tso3_x1dints.fits") as x1d:
67+
assert x1d.spec[0].s_region == "POLYGON ICRS 0 0 0 1 1 1 1 0"
68+
6269

6370
def test_niriss_soss_full(tmp_path):
6471
"""Smoke test for tso3 for an invalid NIRISS SOSS TSO mode."""
@@ -74,3 +81,82 @@ def test_niriss_soss_full(tmp_path):
7481
assert (tmp_path / filename).exists()
7582
for filename in not_expected:
7683
assert not (tmp_path / filename).exists()
84+
85+
86+
def test_populate_tso_spectral_sregion(log_watcher):
87+
model = dm.TSOMultiSpecModel()
88+
model.spec.append(dm.SpecModel())
89+
model.spec.append(dm.SpecModel())
90+
cal_model = dm.CubeModel((10, 10, 10))
91+
cal_model_list = ModelContainer([cal_model, cal_model.copy()])
92+
93+
# no s_region attributes present
94+
watcher = log_watcher(
95+
"jwst.pipeline.calwebb_tso3",
96+
message="No input model(s) have an `s_region` attribute; output S_REGION will not be set.",
97+
level="warning",
98+
)
99+
Tso3Pipeline()._populate_tso_spectral_sregion(model, cal_model_list)
100+
watcher.assert_seen()
101+
assert not model.spec[0].hasattr("s_region")
102+
103+
# s_regions are all the same, should run without issues
104+
for m in cal_model_list:
105+
m.meta.wcsinfo.s_region = "POLYGON ICRS 0 0 0 1 1 1 1 0"
106+
Tso3Pipeline()._populate_tso_spectral_sregion(model, cal_model_list)
107+
assert model.spec[0].s_region == "POLYGON ICRS 0 0 0 1 1 1 1 0"
108+
assert not model.spec[1].hasattr("s_region")
109+
110+
# s_regions differ, should warn and set to first
111+
cal_model_list[1].meta.wcsinfo.s_region = "POLYGON ICRS 1 1 1 2 2 2 2 1"
112+
watcher = log_watcher(
113+
"jwst.pipeline.calwebb_tso3",
114+
message="Input models have different S_REGION values;",
115+
level="warning",
116+
)
117+
Tso3Pipeline()._populate_tso_spectral_sregion(model, cal_model_list)
118+
watcher.assert_seen()
119+
assert model.spec[0].s_region == "POLYGON ICRS 0 0 0 1 1 1 1 0"
120+
assert not model.spec[1].hasattr("s_region")
121+
122+
# only one model has s_region, should warn and set to that one
123+
del cal_model_list[0].meta.wcsinfo.s_region
124+
watcher = log_watcher(
125+
"jwst.pipeline.calwebb_tso3",
126+
message="One or more input model(s) are missing an `s_region` attribute;",
127+
level="warning",
128+
)
129+
Tso3Pipeline()._populate_tso_spectral_sregion(model, cal_model_list)
130+
watcher.assert_seen()
131+
assert model.spec[0].s_region == "POLYGON ICRS 1 1 1 2 2 2 2 1"
132+
assert not model.spec[1].hasattr("s_region")
133+
134+
135+
def test_populate_tso_spectral_sregion_empty_container(log_watcher):
136+
"""Test with an empty ModelContainer."""
137+
model = dm.TSOMultiSpecModel()
138+
model.spec.append(dm.SpecModel())
139+
cal_model_list = ModelContainer()
140+
141+
# Should handle empty container gracefully
142+
watcher = log_watcher(
143+
"jwst.pipeline.calwebb_tso3", message="No input or output models provided;", level="warning"
144+
)
145+
Tso3Pipeline()._populate_tso_spectral_sregion(model, cal_model_list)
146+
watcher.assert_seen()
147+
assert not model.spec[0].hasattr("s_region")
148+
149+
150+
def test_populate_tso_spectral_sregion_no_spec(log_watcher):
151+
"""Test with a model that has no spec entries."""
152+
model = dm.TSOMultiSpecModel()
153+
cal_model = dm.CubeModel((10, 10, 10))
154+
cal_model.meta.wcsinfo.s_region = "POLYGON ICRS 0 0 0 1 1 1 1 0"
155+
cal_model_list = ModelContainer([cal_model])
156+
157+
# Should handle gracefully when model.spec is empty
158+
watcher = log_watcher(
159+
"jwst.pipeline.calwebb_tso3", message="No input or output models provided;", level="warning"
160+
)
161+
Tso3Pipeline()._populate_tso_spectral_sregion(model, cal_model_list)
162+
watcher.assert_seen()

0 commit comments

Comments
 (0)