From 6439c494421b83e4a47e82619d5f16af29d7b8f0 Mon Sep 17 00:00:00 2001 From: jemorrison Date: Wed, 18 Sep 2024 16:14:00 -0700 Subject: [PATCH] various updates from review --- docs/jwst/cube_build/arguments.rst | 41 -------- jwst/cube_build/cube_build_step.py | 34 +++---- jwst/cube_build/ifu_cube.py | 138 +++++++++----------------- jwst/cube_build/ifuoffset.schema.yaml | 5 +- jwst/cube_build/tests/test_offset.py | 20 ++-- 5 files changed, 69 insertions(+), 169 deletions(-) diff --git a/docs/jwst/cube_build/arguments.rst b/docs/jwst/cube_build/arguments.rst index 717095d38da..8d2bfa30531 100644 --- a/docs/jwst/cube_build/arguments.rst +++ b/docs/jwst/cube_build/arguments.rst @@ -167,44 +167,3 @@ An example of making an offset file for an association containing three files is -Below is an example of making an offset file for `num` files. -The user has set up three lists `file`, `ra_offset` and `dec_offset`. The `file` list -contains the filenames and the `ra_offset` and `dec_offset` contain the Ra and Dec offsets respectively. -In this example, all the list have five values. The units of the of Ra and Dec offsets are given in -the `units` value and this value must be arc seconds. - -.. code-block:: python - - import asdf - import astropy.units as u - def create_offset_asdf(files, ra_offset, dec_offset): - - filename = [] - raoffset = [] - decoffset = [] - num = len(files) - for i in range(num): - filename.append(files[i]) - raoffset.append(ra_offset[i]) - decoffset.append(dec_offset[i]) - - tree = { - "units": str(u.arcsec), - "filename": filename, - "raoffset": raoffset, - "decoffset": decoffset - } - af = asdf.AsdfFile(tree) - af.write_to( 'offsets.asdf') - - -Set up the lists and call the above function: - -.. code-block:: python - - files = ['test1.fits', 'test2.fits', 'test3.fits', 'test4,fits', 'test5.fits'] - ra_offset = [0.1, 0.12, 0.13, 0.11, 0.12] - dec_offset = [0.14, 0.15, 0.16, 0.01, 0.1] - create_offset_asdf(files, ra_offset, dec_offset) - - diff --git a/jwst/cube_build/cube_build_step.py b/jwst/cube_build/cube_build_step.py index 3341b6ba184..30da89f019a 100755 --- a/jwst/cube_build/cube_build_step.py +++ b/jwst/cube_build/cube_build_step.py @@ -11,7 +11,7 @@ from ..assign_wcs.util import update_s_region_keyword from ..stpipe import Step, record_step_status from pathlib import Path - +from astropy import units __all__ = ["CubeBuildStep"] @@ -564,51 +564,41 @@ def check_offset_file(self): try: af = asdf.open(self.offset_file, custom_schema=DATA_PATH/'ifuoffset.schema.yaml') except: - self.log.error('Validation Error for offset file') - self.log.error('Turning off adjusting by offsets') - return None + schema_message = ('Validation Error for offset file. Fix the offset file. \n' + \ + 'The offset file needs to have the same number of elements the filename, raoffset and decoffset lists.\n' +\ + 'The units need to provided and only arcsec is allowed.') + raise Exception(schema_message) offset_filename = af['filename'] offset_ra = af['raoffset'] offset_dec = af['decoffset'] - offset_unit = af['units'] - if offset_unit != 'arcsec': - self.log.error('Provide the offset units in units of arcsec ') - self.log.error('Turning off adjusting by offsets ') - af.close() - return None - # check that all the file names in input_model are in the offset filename for model in self.input_models: file_check = model.meta.filename if file_check in offset_filename: continue else: - self.log.error('File in assocation is not found in offset list list %s', file_check) - self.log.error('Turning off adjusting by offsets') af.close() - return None + raise Exception('Error in offset file. A file in assocation is not found in offset list list %s', file_check) + # check that all the lists have the same length len_file = len(offset_filename) len_ra = len(offset_ra) len_dec = len(offset_dec) if (len_file != len_ra or len_ra != len_dec or len_file != len_dec): - self.log.error('The offset file does not have the same number of values for filename, offset_ra, offset_dec') - self.log.error('Turning off adjusting by offsets') af.close() - return None + raise Exception('Offset file error. The offset file does not have the same number of values for filename, offset_ra, offset_dec') + + offset_ra = offset_ra* units.arcsec + offset_dec = offset_dec* units.arcsec # The offset file has passed tests so set the offset dictionary offsets = {} offsets['filename'] = offset_filename offsets['raoffset'] = offset_ra offsets['decoffset'] = offset_dec - n = len(offsets['raoffset']) - # convert to degrees - for i in range(n): - offsets['raoffset'][i] = offsets['raoffset'][i]/3600.0 - offsets['decoffset'][i] = offsets['decoffset'][i]/3600.0 + af.close() return offsets diff --git a/jwst/cube_build/ifu_cube.py b/jwst/cube_build/ifu_cube.py index bccd8d3854c..4d3d6a71280 100644 --- a/jwst/cube_build/ifu_cube.py +++ b/jwst/cube_build/ifu_cube.py @@ -8,14 +8,13 @@ import math from astropy.stats import circmean -from astropy import units as u from gwcs import wcstools from stdatamodels.jwst import datamodels from stdatamodels.jwst.datamodels import dqflags from stdatamodels.jwst.transforms.models import _toindex -from astropy import units from astropy.coordinates import SkyCoord +from astropy import units as u from ..model_blender import blendmeta from ..assign_wcs import pointing @@ -116,7 +115,6 @@ def __init__(self, self.naxis3 = None self.cdelt3_normal = None self.rot_angle = None # rotation angle between Ra-Dec and IFU local instrument plane - self.median_dec = None self.a_min = 0 self.a_max = 0 @@ -1319,10 +1317,7 @@ def setup_ifucube_wcs(self): decoffset = 0.0 # pull out ra dec offset if it exists if self.offsets is not None: - filename = input_model.meta.filename - index = self.offsets['filename'].index(filename) - raoffset = self.offsets['raoffset'][index] - decoffset = self.offsets['decoffset'][index] + raoffset, decoffset = self.find_ra_dec_offset(input_model.meta.filename) # ________________________________________________________________________________ # Find the footprint of the image spectral_found = hasattr(input_model.meta.wcsinfo, 'spectral_region') @@ -1380,28 +1375,11 @@ def setup_ifucube_wcs(self): # now append this model spatial and spectral corner if self.offsets is not None: - c1 = SkyCoord(ca1, cb1, unit='deg') - c2 = SkyCoord(ca2, cb2, unit='deg') - c3 = SkyCoord(ca3, cb3, unit='deg') - c4 = SkyCoord(ca4, cb4, unit='deg') - raoffset = raoffset* units.deg - decoffset = decoffset* units.deg - - c1_new = c1.spherical_offsets_by(raoffset, decoffset) - c2_new = c2.spherical_offsets_by(raoffset, decoffset) - c3_new = c3.spherical_offsets_by(raoffset, decoffset) - c4_new = c4.spherical_offsets_by(raoffset, decoffset) - ca1 = c1_new.ra.value - cb1 = c1_new.dec.value - - ca2 = c2_new.ra.value - cb2 = c2_new.dec.value - - ca3 = c3_new.ra.value - cb3 = c3_new.dec.value - - ca4 = c4_new.ra.value - cb4 = c4_new.dec.value + ca1, cb1 = self.offset_coord(ca1, cb1, raoffset, decoffset) + ca2, cb2 = self.offset_coord(ca2, cb2, raoffset, decoffset) + ca3, cb3 = self.offset_coord(ca3, cb3, raoffset, decoffset) + ca4, cb4 = self.offset_coord(ca4, cb4, raoffset, decoffset) + corner_a.append(ca1) corner_a.append(ca2) corner_a.append(ca3) @@ -1758,15 +1736,11 @@ def map_miri_pixel_to_sky(self, input_model, this_par1, subtract_background, decoffset = 0.0 # pull out ra dec offset if it exists if offsets is not None: - filename = input_model.meta.filename - index = offsets['filename'].index(filename) - raoffset = offsets['raoffset'][index] - decoffset = offsets['decoffset'][index] + raoffset, decoffset = self.find_ra_dec_offset(input_model.meta.filename) log.info("Ra and Dec offset (arc seconds) applied to file :%8.6f, %8.6f, %s", - raoffset*3600.0, - decoffset*3600.0, filename) - raoffset = raoffset* units.deg - decoffset = decoffset* units.deg + raoffset.value, + decoffset.value, input_model.meta.filename) + # check if background sky matching as been done in mrs_imatch step # If it has not been subtracted and the background has not been # subtracted - subtract it. @@ -1805,10 +1779,7 @@ def map_miri_pixel_to_sky(self, input_model, this_par1, subtract_background, # offset the central pixel if offsets is not None: - c1 = SkyCoord(ra, dec, unit='deg') - c1_new = c1.spherical_offsets_by(raoffset, decoffset) - ra = c1_new.ra.value - dec = c1_new.dec.value + ra, dec = self.offset_coord(ra, dec, raoffset, decoffset) valid1 = ~np.isnan(ra) ra = ra[valid1] @@ -1851,27 +1822,11 @@ def map_miri_pixel_to_sky(self, input_model, this_par1, subtract_background, # now offset the pixel corners if offsets is not None: - c1 = SkyCoord(ra1, dec1, unit='deg') - c2 = SkyCoord(ra2, dec2, unit='deg') - c3 = SkyCoord(ra3, dec3, unit='deg') - c4 = SkyCoord(ra4, dec4, unit='deg') - - c1_new = c1.spherical_offsets_by(raoffset, decoffset) - c2_new = c2.spherical_offsets_by(raoffset, decoffset) - c3_new = c3.spherical_offsets_by(raoffset, decoffset) - c4_new = c4.spherical_offsets_by(raoffset, decoffset) - ra1 = c1_new.ra.value - dec1 = c1_new.dec.value - - ra2 = c2_new.ra.value - dec2 = c2_new.dec.value - - ra3 = c3_new.ra.value - dec3 = c3_new.dec.value - - ra4 = c4_new.ra.value - dec4 = c4_new.dec.value - + ra1, dec1 = self.offset_coord(ra1, dec1, raoffset, decoffset) + ra2, dec2 = self.offset_coord(ra2, dec2, raoffset, decoffset) + ra3, dec3 = self.offset_coord(ra3, dec3, raoffset, decoffset) + ra4, dec4 = self.offset_coord(ra4, dec4, raoffset, decoffset) + corner_coord = [ra1, dec1, ra2, dec2, ra3, dec3, ra4, dec4] sky_result = (x, y, ra, dec, wave, slice_no, dwave, corner_coord) @@ -1901,15 +1856,10 @@ def map_nirspec_pixel_to_sky(self, input_model, offsets): decoffset = 0.0 # pull out ra dec offset if it exists if offsets is not None: - filename = input_model.meta.filename - index = offsets['filename'].index(filename) - raoffset = offsets['raoffset'][index] - decoffset = offsets['decoffset'][index] + raoffset, decoffset = self.find_ra_dec_offset(input_model.meta.filename) log.info("Ra and Dec offset (arc seconds) applied to file :%8.6f, %8.6f, %s", - raoffset*3600.0, decoffset*3600.0, filename) + raoffset.value, decoffset.value, input_model.meta.filename) - raoffset = raoffset* units.deg - decoffset = decoffset* units.deg # initialize the ra,dec, and wavelength arrays # we will loop over slice_nos and fill in values # the flag_det will be set when a slice_no pixel is filled in @@ -2071,32 +2021,14 @@ def map_nirspec_pixel_to_sky(self, input_model, offsets): if offsets is not None: # central pixel - c1 = SkyCoord(ra, dec, unit='deg') - c1_new = c1.spherical_offsets_by(raoffset, decoffset) - ra = c1_new.ra.value - dec = c1_new.dec.value + ra, dec = self.offset_coord(ra, dec, raoffset, decoffset) # pixel corners - c1 = SkyCoord(ra1, dec1, unit='deg') - c2 = SkyCoord(ra2, dec2, unit='deg') - c3 = SkyCoord(ra3, dec3, unit='deg') - c4 = SkyCoord(ra4, dec4, unit='deg') - c1_new = c1.spherical_offsets_by(raoffset, decoffset) - c2_new = c2.spherical_offsets_by(raoffset, decoffset) - c3_new = c3.spherical_offsets_by(raoffset, decoffset) - c4_new = c4.spherical_offsets_by(raoffset, decoffset) - ra1 = c1_new.ra.value - dec1 = c1_new.dec.value - - ra2= c2_new.ra.value - dec2 = c2_new.dec.value - - ra3 = c3_new.ra.value - dec3 = c3_new.dec.value - - ra4= c4_new.ra.value - dec4 = c4_new.dec.value - + ra1, dec1 = self.offset_coord(ra1, dec1, raoffset, decoffset) + ra2, dec2 = self.offset_coord(ra2, dec2, raoffset, decoffset) + ra3, dec3 = self.offset_coord(ra3, dec3, raoffset, decoffset) + ra4, dec4 = self.offset_coord(ra4, dec4, raoffset, decoffset) + corner_coord = [ra1, dec1, ra2, dec2, ra3, dec3, ra4, dec4] sky_result = (x, y, ra, dec, wave, slice_no, dwave, corner_coord) return sky_result @@ -2497,7 +2429,27 @@ def blend_output_metadata(self, IFUCube): ], ) + # ******************************************************************************** + def find_ra_dec_offset(self, filename): + """ Match the filename in the offset list with input_model.meta.filename and return + the corresponding Ra and Dec offset + """ + + index = self.offsets['filename'].index(filename) + raoffset = self.offsets['raoffset'][index] + decoffset = self.offsets['decoffset'][index] + return raoffset, decoffset + + # ******************************************************************************** + def offset_coord(self, ra, dec, raoffset, decoffset): + coord = SkyCoord(ra, dec, unit='deg') + coord_new = coord.spherical_offsets_by(raoffset, decoffset) + + ra_new = coord_new.ra.value + dec_new = coord_new.dec.value + return ra_new, dec_new + class IncorrectInput(Exception): """ Raises an exception if input parameter, Interpolation, is set to area when more than one file is used to build the cube. diff --git a/jwst/cube_build/ifuoffset.schema.yaml b/jwst/cube_build/ifuoffset.schema.yaml index c2c7d40c6a1..cd9d2737a40 100644 --- a/jwst/cube_build/ifuoffset.schema.yaml +++ b/jwst/cube_build/ifuoffset.schema.yaml @@ -7,9 +7,8 @@ type: object properties: units: description: Units of the ra and dec offset values. - anyOf: - - type: string - - $ref: http://stsci.edu/schemas/asdf/unit/unit-1.0.0 + type: string + enum: ['arcsec'] filename: description: list of filenames type: array diff --git a/jwst/cube_build/tests/test_offset.py b/jwst/cube_build/tests/test_offset.py index 275764bba22..58149a5bd5b 100644 --- a/jwst/cube_build/tests/test_offset.py +++ b/jwst/cube_build/tests/test_offset.py @@ -158,8 +158,9 @@ def test2_offset_file_config(tmp_cwd, miri_ifushort_short_2files, offset_file): miri_ifushort_short_2files[0].meta.filename = 'test3.fits' step.offset_file = offset_file - offsets = step.check_offset_file() - assert offsets is None + + with pytest.raises(Exception): + offsets = step.check_offset_file() def test_offset_file_units(tmp_cwd, miri_ifushort_short_2files, offset_file_arcmin): @@ -170,9 +171,8 @@ def test_offset_file_units(tmp_cwd, miri_ifushort_short_2files, offset_file_arcm step.input_models = miri_ifushort_short_2files step.offset_file = offset_file_arcmin - offsets = step.check_offset_file() - assert offsets is None - + with pytest.raises(Exception): + offsets = step.check_offset_file() def test_read_offset_file(miri_ifushort_short_2files, offset_file): """ Test offset file has been read in correctly""" @@ -276,15 +276,15 @@ def test_read_offset_file(miri_ifushort_short_2files, offset_file): raoffset = [0.0, 0.1] decoffset = [0.0, 0.15] - ravalues = thiscube.offsets['raoffset'] + ravalues = thiscube.offsets['raoffset'] decvalues = thiscube.offsets['decoffset'] assert thiscube.offsets['filename'] == filename - assert math.isclose(ravalues[0]*3600.0, raoffset[0], abs_tol=0.0001) - assert math.isclose(ravalues[1]*3600.0, raoffset[1], abs_tol=0.0001) - assert math.isclose(decvalues[0]*3600.0, decoffset[0], abs_tol=0.0001) - assert math.isclose(decvalues[1]*3600.0, decoffset[1], abs_tol=0.0001) + assert math.isclose(ravalues[0].value, raoffset[0], abs_tol=0.0001) + assert math.isclose(ravalues[1].value, raoffset[1], abs_tol=0.0001) + assert math.isclose(decvalues[0].value, decoffset[0], abs_tol=0.0001) + assert math.isclose(decvalues[1].value, decoffset[1], abs_tol=0.0001)