Repository: spacetelescope/jwst

Issue:
Resampling edge effects for off-center MOS targets
_Issue [JP-3365](https://jira.stsci.edu/browse/JP-3365) was created on JIRA by [Melanie Clarke](https://jira.stsci.edu/secure/ViewProfile.jspa?name=mclarke):_

In performing calibration analysis for MOS mode, we discovered that there are discontinuities in the extracted level 2 spectra and s2d images at the upper and/or lower nod positions. These may be as large as ~ 40%.  The cause appears to be that there is missing flux along partial rows of the upper and lower edges in the resampled s2d file.  These edges correspond to areas in the cal file set to NaN due to missing WCS information.

The effects in level 3 products appear to be much smaller and/or absent, since combining the nods results in at least some coverage for the full spatial extent.  However, flux calibration and/or data quality may still be impacted in ways that could be improved if the wings of the upper and lower spectra were included in the final combination.

We can currently work around this issue by editing the MSA metadata FITS files to add an extra "open" shutter to each defined slitlet.  That is, for each 3-shutter slitlet, we pretend that 5 shutters were open, where the actual nod pattern uses only the central 3.  This allows the wings of the spectra to be included in the cal file and resampled properly in the s2d file, prior to extraction.  However, this workaround may also impact calibration for the source, including the pathloss correction (JP-3357).

The NIRSpec team will continue analyzing the issue to determine an appropriate fix.  We may want to extend the WCS coverage to all pixels currently included in the cal file.  We may also want add an extra pixel or two to the cutout boundaries to further mitigate the edge effects.

Discussion:
hbushouse: Started a regression test run against the PR branch at https://plwishmaster.stsci.edu:8081/job/RT/job/JWST-Developers-Pull-Requests/977  Expecting small differences in results for any MOS processing.
hbushouse: Regression test results show a few unrelated failures (cause is known) and many expected differences in all MOS products beyond the stage where extract_2d has been run to extract individual slitlets. All cal, s2d, and other intermediate level-2b products show differences in the extraction region size, almost always an extra 4 pixels in the cross-dispersion direction (2 on top and bottom?), all of which seems reasonable. 1D extractions also show small differences due to inclusion of new edge pixel values. So I think this looks OK.

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 2cc597ae1..563ed3b8b 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,11 +1,17 @@
 1.12.2 (unreleased)
 ===================
 
+assign_wcs
+----------
+
+- Increase margin at edges of NIRSpec MOS slits to reduce edge effects in resampling. [#7976]
+
 charge_migration
 ----------------
 
 - Added tests to see if the data array is changed after runnung the step and
-  setting signal_threshold to 25000. [#7895]
+  set the default signal_threshold to 25000. [#7895]
+
 
 1.12.1 (2023-09-26)
 ===================
diff --git a/jwst/assign_wcs/nirspec.py b/jwst/assign_wcs/nirspec.py
index 532ea0766..f106dc4c9 100644
--- a/jwst/assign_wcs/nirspec.py
+++ b/jwst/assign_wcs/nirspec.py
@@ -635,7 +635,7 @@ def get_open_msa_slits(msa_file, msa_metadata_id, dither_position,
         slitlet_ids_unique.remove(-1)
 
     # add a margin to the slit y limits
-    margin = 0.05
+    margin = 0.5
 
     # Now lets look at each unique slitlet id
     for slitlet_id in slitlet_ids_unique:


Test patch:
diff --git a/jwst/assign_wcs/tests/test_nirspec.py b/jwst/assign_wcs/tests/test_nirspec.py
index 03ee98a3d..7fdbaffd1 100644
--- a/jwst/assign_wcs/tests/test_nirspec.py
+++ b/jwst/assign_wcs/tests/test_nirspec.py
@@ -281,7 +281,7 @@ def test_msa_configuration_normal():
     dither_position = 1
     slitlet_info = nirspec.get_open_msa_slits(msaconfl, msa_meta_id, dither_position,
                                               slit_y_range=[-.5, .5])
-    ref_slit = trmodels.Slit(55, 9376, 1, 251, 26, -5.15, 0.55, 4, 1, '1111x', '95065_1', '2122',
+    ref_slit = trmodels.Slit(55, 9376, 1, 251, 26, -5.6, 1.0, 4, 1, '1111x', '95065_1', '2122',
                              0.13, -0.31716078999999997, -0.18092266)
     _compare_slits(slitlet_info[0], ref_slit)
 
@@ -310,7 +310,7 @@ def test_msa_configuration_all_background():
     dither_position = 1
     slitlet_info = nirspec.get_open_msa_slits(msaconfl, msa_meta_id, dither_position,
                                               slit_y_range=[-.5, .5])
-    ref_slit = trmodels.Slit(57, 8281, 1, 251, 23, -1.7, 1.7, 4, 0, '1x1', 'background_57', 'bkg_57',
+    ref_slit = trmodels.Slit(57, 8281, 1, 251, 23, -2.15, 2.15, 4, 0, '1x1', 'background_57', 'bkg_57',
                              0, -0.5, -0.5)
     _compare_slits(slitlet_info[0], ref_slit)
 
@@ -326,7 +326,7 @@ def test_msa_configuration_row_skipped():
     dither_position = 1
     slitlet_info = nirspec.get_open_msa_slits(msaconfl, msa_meta_id, dither_position,
                                               slit_y_range=[-.5, .5])
-    ref_slit = trmodels.Slit(58, 8646, 1, 251, 24, -2.85, 5.15, 4, 1, '11x1011', '95065_1', '2122',
+    ref_slit = trmodels.Slit(58, 8646, 1, 251, 24, -3.3, 5.6, 4, 1, '11x1011', '95065_1', '2122',
                              0.130, -0.31716078999999997, -0.18092266)
     _compare_slits(slitlet_info[0], ref_slit)
 
@@ -341,9 +341,9 @@ def test_msa_configuration_multiple_returns():
     dither_position = 1
     slitlet_info = nirspec.get_open_msa_slits(msaconfl, msa_meta_id, dither_position,
                                               slit_y_range=[-.5, .5])
-    ref_slit1 = trmodels.Slit(59, 8651, 1, 256, 24, -2.85, 5.15, 4, 1, '11x1011', '95065_1', '2122',
+    ref_slit1 = trmodels.Slit(59, 8651, 1, 256, 24, -3.3, 5.6, 4, 1, '11x1011', '95065_1', '2122',
                               0.13000000000000003, -0.31716078999999997, -0.18092266)
-    ref_slit2 = trmodels.Slit(60, 11573, 1, 258, 32, -2.85, 4, 4, 2, '11x111', '95065_2', '172',
+    ref_slit2 = trmodels.Slit(60, 11573, 1, 258, 32, -3.3, 4.45, 4, 2, '11x111', '95065_2', '172',
                               0.70000000000000007, -0.31716078999999997, -0.18092266)
     _compare_slits(slitlet_info[0], ref_slit1)
     _compare_slits(slitlet_info[1], ref_slit2)
diff --git a/jwst/wavecorr/tests/test_wavecorr.py b/jwst/wavecorr/tests/test_wavecorr.py
index aa9e713cf..e4a06cb62 100644
--- a/jwst/wavecorr/tests/test_wavecorr.py
+++ b/jwst/wavecorr/tests/test_wavecorr.py
@@ -51,7 +51,8 @@ def test_wavecorr():
     zero_point1 = wavecorr.compute_zero_point_correction(lam, freference, source_xpos1, 'MOS', dispersion)
     zero_point2 = wavecorr.compute_zero_point_correction(lam, freference, source_xpos2, 'MOS', dispersion)
     diff_correction = np.abs(zero_point1[1] - zero_point2[1])
-    assert_allclose(np.nanmean(diff_correction), 0.49, atol=0.01)
+    non_zero = diff_correction[diff_correction != 0]
+    assert_allclose(np.nanmean(non_zero), 0.75, atol=0.01)
 
 
 def test_ideal_to_v23_fs():