Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/9794.extract_2d.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
If the ``slit_names`` or ``source_ids`` are specified, but none of the slits are valid, a ``NoDataOnDetectorError`` exception is raised.
2 changes: 2 additions & 0 deletions docs/jwst/extract_2d/main.rst
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ modes. For NIRSpec observations there is one applicable argument:
of None will cause all known slits for the instrument to be extracted.

``slit_names`` and ``source_ids`` can be used at the same time, duplicates will be filtered out.
If either argument is specified, but no valid slits are identified, an error will be
raised and the step will exit.

There are several arguments available for Wide-Field Slitless Spectroscopy (WFSS) and
Time-Series (TSO) grism spectroscopy:
Expand Down
17 changes: 9 additions & 8 deletions jwst/extract_2d/extract_2d_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,16 @@ def process(self, input_model):
output_model : DataModel
The resulting DataModel of the extract_2d step
"""
reference_file_names = {}
if input_model.meta.exposure.type in extract_2d.slitless_modes:
# The wavelengthrange file is used only by the WFSS modes.
# If retrieved by a Nirspec mode, it would override the name of
# the file in meta.ref_file if a custom file was used.
for reftype in self.reference_file_types:
reffile = self.get_reference_file(input_model, reftype)
reference_file_names[reftype] = reffile if reffile else ""
with datamodels.open(input_model) as dm:
reference_file_names = {}
if dm.meta.exposure.type in extract_2d.slitless_modes:
# The wavelengthrange file is used only by the WFSS modes.
# If retrieved by a Nirspec mode, it would override the name of
# the file in meta.ref_file if a custom file was used.
for reftype in self.reference_file_types:
reffile = self.get_reference_file(input_model, reftype)
reference_file_names[reftype] = reffile if reffile else ""

output_model = extract_2d.extract2d(
dm,
self.slit_names,
Expand Down
19 changes: 13 additions & 6 deletions jwst/extract_2d/nirspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ def nrs_extract2d(input_model, slit_names=None, source_ids=None):
open_slits = input_model.meta.wcs.get_transform("gwa", "slit_frame").slits

# Select the slits to process
open_slits = select_slits(open_slits, slit_names, source_ids)
if slit_names is not None or source_ids is not None:
open_slits = select_slits(open_slits, slit_names, source_ids)

# NIRSpec BRIGHTOBJ (S1600A1 TSO) mode
if exp_type == "NRS_BRIGHTOBJ":
Expand Down Expand Up @@ -146,6 +147,11 @@ def select_slits(open_slits, slit_names, source_ids):
-------
selected_open_slits : list
List of slits selected by slit_name or source_id

Raises
------
`~jwst.assign_wcs.util.NoDataOnDetectorError`
If no valid slits are selected.
"""
open_slit_names = [str(x.name) for x in open_slits]
open_slit_source_ids = [str(x.source_id) for x in open_slits]
Expand All @@ -156,7 +162,7 @@ def select_slits(open_slits, slit_names, source_ids):
if this_slit in open_slit_names:
matched_slits.append(this_slit)
else:
log.warn(f"Slit {this_slit} is not in the list of open slits.")
log.warning(f"Slit {this_slit} is not in the list of open slits.")
for sub in open_slits:
if str(sub.name) in matched_slits:
selected_open_slits.append(sub)
Expand All @@ -166,7 +172,7 @@ def select_slits(open_slits, slit_names, source_ids):
if this_id in open_slit_source_ids:
matched_sources.append(this_id)
else:
log.warn(f"Source id {this_id} is not in the list of open slits.")
log.warning(f"Source id {this_id} is not in the list of open slits.")
for sub in open_slits:
if str(sub.source_id) in matched_sources:
if sub not in selected_open_slits:
Expand All @@ -179,8 +185,9 @@ def select_slits(open_slits, slit_names, source_ids):
log.info(f"Name: {this_slit.name}, source_id: {this_slit.source_id}")
return selected_open_slits
else:
log.info("All slits selected")
return open_slits
log_message = "No valid slits selected."
log.critical(log_message)
raise util.NoDataOnDetectorError(log_message)


def process_slit(input_model, slit):
Expand Down Expand Up @@ -363,7 +370,7 @@ class DitherMetadataError(Exception):
Handle DitherMetadataError exception.

This exception is raised if a Slit object doesn't have the required
dither attribute, or the x_ and y_ offsets aren't numeric.
dither attribute, or the x and y offsets aren't numeric.
"""

pass
Expand Down
24 changes: 21 additions & 3 deletions jwst/extract_2d/tests/test_nirspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from stdatamodels.jwst.transforms.models import Slit

from jwst.assign_wcs import AssignWcsStep
from jwst.assign_wcs.util import NoDataOnDetectorError
from jwst.extract_2d.extract_2d_step import Extract2dStep
from jwst.extract_2d.nirspec import select_slits

Expand Down Expand Up @@ -273,26 +274,43 @@ def test_extract_2d_nirspec_bots(nirspec_bots_rateints):

def test_select_slits(nirspec_slit_list):
slit_list = nirspec_slit_list
# Choose all slits
all_slits = select_slits(slit_list, None, None)
assert all_slits == slit_list

# No slits selected
with pytest.raises(NoDataOnDetectorError, match="No valid slits selected"):
select_slits(slit_list, None, None)
with pytest.raises(NoDataOnDetectorError, match="No valid slits selected"):
select_slits(slit_list, [], [])
with pytest.raises(NoDataOnDetectorError, match="No valid slits selected"):
select_slits(slit_list, ["-99"], [-9999])

# Just slit with name=='3'
single_name = select_slits(slit_list, ["3"], None)
assert single_name[0].name == "3"
assert single_name[0].source_id == "3000"

# Just slit with source_id == '3000'
single_id = select_slits(slit_list, None, ["2000"])
assert single_id[0].name == "2"
assert single_id[0].source_id == "2000"

# Slits with name == '4' and source_id == '4000' are duplicates
duplicates = select_slits(slit_list, ["1", "4"], ["2000", "4000"])
assert Slit(name="1", source_id="1000") in duplicates
assert Slit(name="2", source_id="2000") in duplicates
assert Slit(name="4", source_id="4000") in duplicates

# Select slit with a non-integer name
non_integer = select_slits(slit_list, ["S200A1"], None)
assert non_integer[0] == Slit(name="S200A1", source_id="2222")

# Select slits with mix of integer and string names
with_integer = select_slits(slit_list, [2, "5"], None)
assert Slit(name="2", source_id="2000") in with_integer
assert Slit(name="5", source_id="5000") in with_integer

# Select some valid, some invalid slits
some_valid = select_slits(slit_list, ["1", "4", "-99"], ["2000", "4000", "-9999"])
assert len(some_valid) == 3
assert Slit(name="1", source_id="1000") in some_valid
assert Slit(name="2", source_id="2000") in some_valid
assert Slit(name="4", source_id="4000") in some_valid