diff --git a/changes/8908.resample_spec.rst b/changes/8908.resample_spec.rst new file mode 100644 index 0000000000..2d69d9feee --- /dev/null +++ b/changes/8908.resample_spec.rst @@ -0,0 +1 @@ +Update NIRSpec spectral resampling to add a missing correction factor in resampled WCS tangent plane transformation. \ No newline at end of file diff --git a/jwst/resample/resample_spec.py b/jwst/resample/resample_spec.py index 9316a838c0..0d90d0d891 100644 --- a/jwst/resample/resample_spec.py +++ b/jwst/resample/resample_spec.py @@ -335,32 +335,43 @@ def build_nirspec_output_wcs(self, input_models, refmodel=None): raise ValueError("Not enough data to construct output WCS.") # Find the spatial extent in x/y tangent - min_tan, max_tan = self._max_spatial_extent(all_wcs, undist2sky.inverse, swap_xy) - diff = np.abs(max_tan - min_tan) - if swap_xy: - pix_to_tan_slope = np.abs(pix_to_ytan.slope) - slope_sign = np.sign(pix_to_ytan.slope) - else: - pix_to_tan_slope = np.abs(pix_to_xtan.slope) - slope_sign = np.sign(pix_to_xtan.slope) + min_tan_x, max_tan_x, min_tan_y, max_tan_y = self._max_spatial_extent( + all_wcs, undist2sky.inverse) + diff_y = np.abs(max_tan_y - min_tan_y) + diff_x = np.abs(max_tan_x - min_tan_x) + + pix_to_tan_slope_y = np.abs(pix_to_ytan.slope) + slope_sign_y = np.sign(pix_to_ytan.slope) + pix_to_tan_slope_x = np.abs(pix_to_xtan.slope) + slope_sign_x = np.sign(pix_to_xtan.slope) # Image size in spatial dimension from the maximum slope # and tangent offset span, plus one pixel to make sure # we catch all the data - ny = int(np.ceil(diff / pix_to_tan_slope)) + 1 + if swap_xy: + ny = int(np.ceil(diff_y / pix_to_tan_slope_y)) + 1 + else: + ny = int(np.ceil(diff_x / pix_to_tan_slope_x)) + 1 # Correct the intercept for the new minimum value. # Also account for integer pixel size to make sure the # data is centered in the array. - offset = ny/2 * pix_to_tan_slope - diff/2 - if slope_sign > 0: - zero_value = min_tan + offset_y = ny/2 * pix_to_tan_slope_y - diff_y/2 + offset_x = ny/2 * pix_to_tan_slope_x - diff_x/2 + + if slope_sign_y > 0: + zero_value_y = min_tan_y else: - zero_value = max_tan - if swap_xy: - pix_to_ytan.intercept = zero_value - slope_sign * offset + zero_value_y = max_tan_y + + if slope_sign_x > 0: + zero_value_x = min_tan_x else: - pix_to_xtan.intercept = zero_value - slope_sign * offset + zero_value_x = max_tan_x + + + pix_to_ytan.intercept = zero_value_y - slope_sign_y * offset_y + pix_to_xtan.intercept = zero_value_x - slope_sign_x * offset_x # Now set up the final transforms @@ -447,12 +458,12 @@ def build_nirspec_output_wcs(self, input_models, refmodel=None): return output_wcs - def _max_spatial_extent(self, wcs_list, transform, swap_xy): + def _max_spatial_extent(self, wcs_list, transform): """ - Compute min & max spatial coordinates for all nods in the "virtual" - slit frame. + Compute spatial coordinate limits for all nods in the tangent plane. """ - min_tan_all, max_tan_all = np.inf, -np.inf + limits_x = [np.inf, -np.inf] + limits_y = [np.inf, -np.inf] for wcs in wcs_list: x, y = wcstools.grid_from_bounding_box(wcs.bounding_box) ra, dec, _ = wcs(x, y) @@ -462,20 +473,16 @@ def _max_spatial_extent(self, wcs_list, transform, swap_xy): dec = dec[good] xtan, ytan = transform(ra, dec) - if swap_xy: - tan_all = ytan - else: - tan_all = xtan - - min_tan = np.min(tan_all) - max_tan = np.max(tan_all) + for tan_all, limits in zip([xtan, ytan], [limits_x, limits_y]): + min_tan = np.min(tan_all) + max_tan = np.max(tan_all) - if min_tan < min_tan_all: - min_tan_all = min_tan - if max_tan > max_tan_all: - max_tan_all = max_tan + if min_tan < limits[0]: + limits[0] = min_tan + if max_tan > limits[1]: + limits[1] = max_tan - return min_tan_all, max_tan_all + return *limits_x, *limits_y def build_interpolated_output_wcs(self, input_models): """ @@ -944,4 +951,4 @@ def compute_spectral_pixel_scale(wcs, fiducial=None, disp_axis=1): fiducial = wcs(center_x, center_y) pixel_scale = compute_scale(wcs, fiducial, disp_axis=disp_axis) - return float(pixel_scale) \ No newline at end of file + return float(pixel_scale)