Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JP-3616: Fix NIRSpec FS spec3 slit name #8470

Merged
merged 3 commits into from
May 9, 2024
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
4 changes: 4 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,15 @@ extract_1d
regions are specified and the lower and upper limits for one of them are
outside the valid area for some data range. [#8433]

- Correct the output slit name for non-primary slit extractions in the
spec3 pipeline, for NIRSpec fixed slit mode. [#8470]

extract_2d
----------

- Added handling for NIRCam GRISM time series pointing offsets. [#8449]


flat_field
----------

Expand Down
5 changes: 4 additions & 1 deletion jwst/extract_1d/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -2986,7 +2986,10 @@ def do_extract1d(

# For NRS_FIXEDSLIT, the slit name comes from the FXD_SLIT keyword in the model meta
if input_model.meta.exposure.type == 'NRS_FIXEDSLIT':
slitname = input_model.meta.instrument.fixed_slit
if hasattr(input_model, "name") and input_model.name is not None:
slitname = input_model.name
else:
slitname = input_model.meta.instrument.fixed_slit

# Loop over all spectral orders available for extraction
prev_offset = OFFSET_NOT_ASSIGNED_YET
Expand Down
118 changes: 118 additions & 0 deletions jwst/extract_1d/tests/test_extract_1d_step.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import numpy as np
import pytest
import stdatamodels.jwst.datamodels as dm

from jwst.assign_wcs.util import wcs_bbox_from_shape
from jwst.extract_1d.extract_1d_step import Extract1dStep


@pytest.fixture
def simple_wcs():
shape = (50, 50)
xcenter = shape[1] // 2.0

def simple_wcs_function(x, y):
""" Simple WCS for testing """
crpix1 = xcenter
crpix3 = 1.0
cdelt1 = 0.1
cdelt2 = 0.1
cdelt3 = 0.01

crval1 = 45.0
crval2 = 45.0
crval3 = 7.5

wave = (x + 1 - crpix3) * cdelt3 + crval3
ra = (x + 1 - crpix1) * cdelt1 + crval1
dec = np.full_like(ra, crval2 + 1 * cdelt2)

return ra, dec, wave

simple_wcs_function.bounding_box = wcs_bbox_from_shape(shape)

return simple_wcs_function


@pytest.fixture()
def mock_nirspec_fs_one_slit(simple_wcs):
model = dm.SlitModel()
model.meta.instrument.name = 'NIRSPEC'
model.meta.instrument.detector = 'NRS1'
model.meta.observation.date = '2023-07-22'
model.meta.observation.time = '06:24:45.569'
model.meta.instrument.fixed_slit = 'S200A1'
model.meta.exposure.type = 'NRS_FIXEDSLIT'
model.meta.subarray.name = 'ALLSLITS'

model.source_type = 'EXTENDED'
model.meta.wcsinfo.dispersion_direction = 1
model.meta.wcs = simple_wcs

model.data = np.arange(50 * 50, dtype=float).reshape((50, 50))
model.var_poisson = model.data * 0.02
model.var_rnoise = model.data * 0.02
model.var_flat = model.data * 0.05
yield model
model.close()


@pytest.fixture()
def mock_nirspec_mos(mock_nirspec_fs_one_slit):
model = dm.MultiSlitModel()
model.meta.instrument.name = 'NIRSPEC'
model.meta.instrument.detector = 'NRS1'
model.meta.observation.date = '2023-07-22'
model.meta.observation.time = '06:24:45.569'
model.meta.exposure.type = 'NRS_MSASPEC'

nslit = 3
for i in range(nslit):
slit = mock_nirspec_fs_one_slit.copy()
slit.name = str(i + 1)
model.slits.append(slit)

yield model
model.close()


@pytest.mark.parametrize('slit_name', [None, 'S200A1', 'S1600A1'])
def test_extract_nirspec_fs_slit(mock_nirspec_fs_one_slit, simple_wcs, slit_name):
mock_nirspec_fs_one_slit.name = slit_name
result = Extract1dStep.call(mock_nirspec_fs_one_slit)
assert result.meta.cal_step.extract_1d == 'COMPLETE'

if slit_name is None:
assert (result.spec[0].name
== mock_nirspec_fs_one_slit.meta.instrument.fixed_slit)
else:
assert result.spec[0].name == slit_name

# output wavelength is the same as input
_, _, expected_wave = simple_wcs(np.arange(50), np.arange(50))
assert np.allclose(result.spec[0].spec_table['WAVELENGTH'], expected_wave)

# output flux and errors are non-zero, exact values will depend
# on extraction parameters
assert np.all(result.spec[0].spec_table['FLUX'] > 0)
assert np.all(result.spec[0].spec_table['FLUX_ERROR'] > 0)
result.close()


def test_extract_nirspec_mos_multi_slit(mock_nirspec_mos, simple_wcs):
result = Extract1dStep.call(mock_nirspec_mos)
assert result.meta.cal_step.extract_1d == 'COMPLETE'

for i, spec in enumerate(result.spec):
assert spec.name == str(i + 1)

# output wavelength is the same as input
_, _, expected_wave = simple_wcs(np.arange(50), np.arange(50))
assert np.allclose(spec.spec_table['WAVELENGTH'], expected_wave)

# output flux and errors are non-zero, exact values will depend
# on extraction parameters
assert np.all(spec.spec_table['FLUX'] > 0)
assert np.all(spec.spec_table['FLUX_ERROR'] > 0)

result.close()
Loading