def alpha_beta2XanYan(input_model, reference_files): """ Create the transform from detector to Xan, Yan frame. forward transform: RegionsSelector label_mapper is LabelMapperDict() {channel_wave_range (): channel_number} selector is {channel_number: ab2Xan & ab2Yan} bacward_transform RegionsSelector label_mapper is LabelMapperDict() {channel_wave_range (): channel_number} selector is {channel_number: Xan2ab & Yan2ab} """ band = input_model.meta.instrument.band channel = input_model.meta.instrument.channel # used to read the wavelength range channels = [c + band for c in channel] f = AsdfFile.open(reference_files['v2v3']) v23 = f.tree['model'] f.close() f = AsdfFile.open(reference_files['wavelengthrange']) # the following should go in the asdf reader wave_range = f.tree['wavelengthrange'].copy() wave_channels = f.tree['channels'] wr = {} for ch, r in zip(wave_channels, wave_range): wr[ch] = r f.close() dict_mapper = {} sel = {} for c in channels: ch = int(c[0]) dict_mapper[tuple(wr[c])] = models.Mapping((2,), name="mapping_lam") | \ models.Const1D(ch, name="channel #") map1 = models.Mapping((1, 0, 1, 0), name='map2poly') map1._outputs = ('alpha', 'beta', 'alpha', 'beta') map1._inputs = ('alpha', 'beta') map1.inverse = models.Mapping((0, 1)) ident1 = models.Identity(1, name='identity_lam') ident1._inputs = ('lam',) chan_v23 = v23[c] v23chan_backward = chan_v23.inverse del chan_v23.inverse v23_spatial = map1 | chan_v23 v23_spatial.inverse = map1 | v23chan_backward v23c = v23_spatial & ident1 sel[ch] = v23c wave_range_mapper = selector.LabelMapperRange(('alpha', 'beta', 'lam'), dict_mapper, inputs_mapping=models.Mapping([2, ])) wave_range_mapper.inverse = wave_range_mapper.copy() ab2xyan = selector.RegionsSelector(('alpha', 'beta', 'lam'), ('v2', 'v3', 'lam'), label_mapper=wave_range_mapper, selector=sel) return ab2xyan
def detector_to_gwa(reference_files, detector, disperser): """ Transform from DETECTOR frame to GWA frame. Parameters ---------- reference_files: dict Dictionary with reference files returned by CRDS. detector : str The detector keyword. disperser : dict A corrected disperser ASDF object. Returns ------- model : `~astropy.modeling.core.Model` model. Transform from DETECTOR frame to GWA frame. """ with AsdfFile.open(reference_files['fpa']) as f: fpa = f.tree[detector].copy() with AsdfFile.open(reference_files['camera']) as f: camera = f.tree['model'].copy() angles = [ disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y'] ] rotation = Rotation3DToGWA(angles, axes_order="xyzy", name='rotaton') u2dircos = Unitless2DirCos(name='unitless2directional_cosines') model = (fpa | camera | u2dircos | rotation) return model
def alpha_beta2XanYan(input_model, reference_files): """ Create the transform from detector to Xan, Yan frame. forward transform: RegionsSelector label_mapper is LabelMapperDict() {channel_wave_range (): channel_number} selector is {channel_number: ab2Xan & ab2Yan} bacward_transform RegionsSelector label_mapper is LabelMapperDict() {channel_wave_range (): channel_number} selector is {channel_number: Xan2ab & Yan2ab} """ band = input_model.meta.instrument.band channel = input_model.meta.instrument.channel # used to read the wavelength range channels = [c + band for c in channel] f = AsdfFile.open(reference_files['v2v3']) v23 = f.tree['model'] f.close() f = AsdfFile.open(reference_files['wavelengthrange']) # the following should go in the asdf reader wave_range = f.tree['wavelengthrange'].copy() wave_channels = f.tree['channels'] wr = {} for ch, r in zip(wave_channels, wave_range): wr[ch] = r f.close() dict_mapper = {} sel = {} for c in channels: ch = int(c[0]) dict_mapper[tuple(wr[c])] = models.Mapping((2,), name="mapping_lam") | \ models.Const1D(ch, name="channel #") map1 = models.Mapping((1, 0, 1, 0), name='map2poly') map1._outputs = ('alpha', 'beta', 'alpha', 'beta') map1._inputs = ('alpha', 'beta') map1.inverse = models.Mapping((0, 1)) ident1 = models.Identity(1, name='identity_lam') ident1._inputs = ('lam',) chan_v23 = v23[c] v23chan_backward = chan_v23.inverse del chan_v23.inverse v23_spatial = map1 | chan_v23 v23_spatial.inverse = map1 | v23chan_backward v23c = v23_spatial & ident1 sel[ch] = v23c wave_range_mapper = selector.LabelMapperRange(('alpha', 'beta', 'lam'), dict_mapper, inputs_mapping=models.Mapping([2,])) wave_range_mapper.inverse = wave_range_mapper.copy() ab2xyan = selector.RegionsSelector(('alpha', 'beta', 'lam'), ('v2', 'v3', 'lam'), label_mapper=wave_range_mapper, selector=sel) return ab2xyan
def imaging_distortion(input_model, reference_files): """ Create pixe2sky and sky2pixel transformation for the MIRI imager. Parameters ---------- model : jwst_lib.models.ImagingModel input model reference_files : dict reference files from CRDS using CDP 3 Reference distortion file MIRI_FM_MIRIMAGE_F1000W_PSF_03.01.00.fits reference files/corrections needed (pixel to sky): 1. Filter dependent shift in (x,y) (!with an oposite sign to that delievred by the IT) 2. Apply MI 3. Apply Ai and BI matrices 4. Apply the TI matrix (this gives V2/V3 coordinates) 5. Apply V2/V3 to sky transformation ref_file: filter_offset.asdf - (1) ref_file: distortion.asdf -(2,3,4) """ distortion = AsdfFile.open(reference_files['distortion']).tree['model'] filter_offset = AsdfFile.open(reference_files['filteroffset']).tree[input_model.meta.instrument.filter] full_distortion = models.Shift(filter_offset['row_offset']) & models.Shift( filter_offset['column_offset']) | distortion full_distortion = full_distortion.rename('distortion') return full_distortion
def calc_cube(numb, fried_parameter = 4, time_between = 0.7): filepath = os.getcwd().split("vApp_reduction",1)[0]+"vApp_reduction/data/psf_cube_cache/" filepath += "psf_cube_"+str(float(fried_parameter))+"_"+str(float(time_between))+"_"+str(int(numb))+".asdf" #expand to only demand numb =< numb on disk if os.path.exists(filepath): tree = AsdfFile.open(filepath, copy_arrays=True).tree tree_keys = tree.keys() psf_params = sorted(list(filter(lambda key: isinstance(key, float), tree_keys))) psf_cube = list(map(lambda param: np.copy(tree[param]), psf_params)) return psf_cube, psf_params else: path = os.getcwd()+"/code/psf/generate_vAPP_cube.py" params = [str(fried_parameter), str(time_between), str(numb)] cmd = [sys.executable, path, *params] print("please run: ") print(' '.join(cmd)) input("Press Enter to continue...") tree = AsdfFile.open(filepath).tree tree_keys = tree.keys() psf_params = sorted(list(filter(lambda key: isinstance(key, float), tree_keys))) psf_cube = list(map(lambda param: tree[param], psf_params)) return psf_cube, psf_params
def test_backwards_compat_gcrs(): obsgeoloc = ( 3.0856775814671916e+16, 9.257032744401574e+16, 6.1713551629343834e+19 ) obsgeovel = (2.0, 1.0, 8.0) old_frame_yaml = """ frames: - !wcs/celestial_frame-1.0.0 axes_names: [lon, lat] name: CelestialFrame reference_frame: type: GCRS obsgeoloc: - [%f, %f, %f] - !unit/unit-1.0.0 m obsgeovel: - [%f, %f, %f] - !unit/unit-1.0.0 m s-1 obstime: !time/time-1.0.0 2010-01-01 00:00:00.000 unit: [!unit/unit-1.0.0 deg, !unit/unit-1.0.0 deg] """ % (obsgeovel + obsgeoloc) new_frame_yaml = """ frames: - !wcs/celestial_frame-1.1.0 axes_names: [lon, lat] name: CelestialFrame reference_frame: type: GCRS obsgeoloc: - !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: %f} - !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: %f} - !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m, value: %f} obsgeovel: - !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: %f} - !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: %f} - !unit/quantity-1.1.0 {unit: !unit/unit-1.0.0 m s-1, value: %f} obstime: !time/time-1.1.0 2010-01-01 00:00:00.000 unit: [!unit/unit-1.0.0 deg, !unit/unit-1.0.0 deg] """ % (obsgeovel + obsgeoloc) old_buff = helpers.yaml_to_asdf(old_frame_yaml) old_asdf = AsdfFile.open(old_buff) old_frame = old_asdf.tree['frames'][0] old_loc = old_frame.reference_frame.obsgeoloc old_vel = old_frame.reference_frame.obsgeovel new_buff = helpers.yaml_to_asdf(new_frame_yaml) new_asdf = AsdfFile.open(new_buff) new_frame = new_asdf.tree['frames'][0] new_loc = new_frame.reference_frame.obsgeoloc new_vel = new_frame.reference_frame.obsgeovel assert (old_loc.x == new_loc.x and old_loc.y == new_loc.y and old_loc.z == new_loc.z) assert (old_vel.x == new_vel.x and old_vel.y == new_vel.y and old_vel.z == new_vel.z)
def detector_to_gwa(reference_files, detector, disperser): """ Transform from DETECTOR frame to GWA frame. Parameters ---------- reference_files: dict Dictionary with reference files returned by CRDS. detector : str The detector keyword. disperser : dict A corrected disperser ASDF object. Returns ------- model : `~astropy.modeling.core.Model` model. Transform from DETECTOR frame to GWA frame. """ with AsdfFile.open(reference_files['fpa']) as f: fpa = f.tree[detector].copy() with AsdfFile.open(reference_files['camera']) as f: camera = f.tree['model'].copy() angles = [disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y']] rotation = Rotation3DToGWA(angles, axes_order="xyzy", name='rotaton') u2dircos = Unitless2DirCos(name='unitless2directional_cosines') model = (models.Shift(-1) & models.Shift(-1) | fpa | camera | u2dircos | rotation) return model
def ifuslit_to_msa(slits, reference_files): """ The transform from slit_frame to msa_frame. Parameters ---------- slits_id : list A list of slit IDs for all open shutters/slitlets. msafile : str The name of the msa reference file. Returns ------- model : `~jwst_lib.pipeline_models.Slit2Msa` model. Transform from slit_frame to msa_frame. """ with AsdfFile.open(reference_files['ifufore']) as f: ifufore = f.tree['model'] ifuslicer = AsdfFile.open(reference_files['ifuslicer']) models = {} ifuslicer_model = (ifuslicer.tree['model']).rename('ifuslicer_model') for slit in slits: slitdata = ifuslicer.tree['data'][slit] slitdata_model = (get_slit_location_model(slitdata)).rename('slitdata_model') msa_transform = slitdata_model | ifuslicer_model models[slit] = msa_transform ifuslicer.close() return Slit2Msa(models)
def ifu_msa_to_oteip(reference_files): """ Transform from the MSA frame to the OTEIP frame. Parameters ---------- reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~astropy.modeling.core.Model` model. Transform from MSA to OTEIP. """ with AsdfFile.open(reference_files['fore']) as f: fore = f.tree['model'].copy() with AsdfFile.open(reference_files['ifufore']) as f: ifufore = f.tree['model'].copy() msa2fore_mapping = Mapping((0, 1, 2, 2)) msa2fore_mapping.inverse = Identity(3) ifu_fore_transform = ifufore & Identity(1) ifu_fore_transform.inverse = Mapping( (0, 1, 2, 2)) | ifufore.inverse & Identity(1) fore_transform = msa2fore_mapping | fore & Identity(1) return msa2fore_mapping | ifu_fore_transform | fore_transform
def ifuslit_to_msa(slits, reference_files): """ The transform from slit_frame to msa_frame. Parameters ---------- slits_id : list A list of slit IDs for all open shutters/slitlets. msafile : str The name of the msa reference file. Returns ------- model : `~jwst_lib.pipeline_models.Slit2Msa` model. Transform from slit_frame to msa_frame. """ with AsdfFile.open(reference_files['ifufore']) as f: ifufore = f.tree['model'] ifuslicer = AsdfFile.open(reference_files['ifuslicer']) models = {} ifuslicer_model = (ifuslicer.tree['model']).rename('ifuslicer_model') for slit in slits: slitdata = ifuslicer.tree['data'][slit] slitdata_model = ( get_slit_location_model(slitdata)).rename('slitdata_model') msa_transform = slitdata_model | ifuslicer_model models[slit] = msa_transform ifuslicer.close() return Slit2Msa(models)
def ifu_msa_to_oteip(reference_files): """ Transform from the MSA frame to the OTEIP frame. Parameters ---------- reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~astropy.modeling.core.Model` model. Transform from MSA to OTEIP. """ with AsdfFile.open(reference_files['fore']) as f: fore = f.tree['model'].copy() with AsdfFile.open(reference_files['ifufore']) as f: ifufore = f.tree['model'].copy() msa2fore_mapping = Mapping((0, 1, 2, 2)) msa2fore_mapping.inverse = Identity(3) ifu_fore_transform = ifufore & Identity(1) ifu_fore_transform.inverse = Mapping((0, 1, 2, 2)) | ifufore.inverse & Identity(1) fore_transform = msa2fore_mapping | fore & Identity(1) return msa2fore_mapping | ifu_fore_transform | fore_transform
def imaging_distortion(input_model, reference_files): """ Create pixe2sky and sky2pixel transformation for the MIRI imager. Parameters ---------- model : jwst.datamodels.ImagingModel input model reference_files : dict reference files from CRDS using CDP 3 Reference distortion file MIRI_FM_MIRIMAGE_F1000W_PSF_03.01.00.fits reference files/corrections needed (pixel to sky): 1. Filter dependent shift in (x,y) (!with an oposite sign to that delievred by the IT) 2. Apply MI 3. Apply Ai and BI matrices 4. Apply the TI matrix (this gives V2/V3 coordinates) 5. Apply V2/V3 to sky transformation ref_file: filter_offset.asdf - (1) ref_file: distortion.asdf -(2,3,4) """ distortion = AsdfFile.open(reference_files['distortion']).tree['model'] filter_offset = AsdfFile.open(reference_files['filteroffset']).tree[input_model.meta.instrument.filter] full_distortion = models.Shift(filter_offset['row_offset']) & models.Shift( filter_offset['column_offset']) | distortion full_distortion = full_distortion.rename('distortion') return full_distortion
def gwa_to_ifuslit(slits, disperser, wrange, order, reference_files): """ GWA to SLIT transform. Parameters ---------- slits : list A list of slit IDs for all IFU slits 0-29. disperser : dict A corrected disperser ASDF object. filter : str The filter used. grating : str The grating used in the observation. reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~jwst_lib.pipeline_models.Gwa2Slit` model. Transform from GWA frame to SLIT frame. """ agreq = AngleFromGratingEquation(disperser['groove_density'], order, name='alpha_from_greq') lgreq = WavelengthFromGratingEquation(disperser['groove_density'], order, name='lambda_from_greq') collimator2gwa = collimator_to_gwa(reference_files, disperser) lam = (wrange[1] - wrange[0]) / 2 + wrange[0] ifuslicer = AsdfFile.open(reference_files['ifuslicer']) ifupost = AsdfFile.open(reference_files['ifupost']) slit_models = {} ifuslicer_model = ifuslicer.tree['model'] for slit in slits: slitdata = ifuslicer.tree['data'][slit] slitdata_model = get_slit_location_model(slitdata) ifuslicer_transform = (slitdata_model | ifuslicer_model) ifupost_transform = ifupost.tree[slit]['model'] msa2gwa = ifuslicer_transform | ifupost_transform | collimator2gwa gwa2msa = gwa_to_ymsa(msa2gwa) # TODO: Use model sets here bgwa2msa = Mapping((0, 1, 0, 1), n_inputs=3) | \ Const1D(0) * Identity(1) & Const1D(-1) * Identity(1) & Identity(2) | \ Identity(1) & gwa2msa & Identity(2) | \ Mapping((0, 1, 0, 1, 2, 3)) | Identity(2) & msa2gwa & Identity(2) | \ Mapping((0, 1, 2, 5), n_inputs=7)| Identity(2) & lgreq # msa to before_gwa #msa2bgwa = Mapping((0, 1, 2, 2)) | msa2gwa & Identity(1) | Mapping((3, 0, 1, 2)) | agreq msa2bgwa = msa2gwa & Identity(1) | Mapping((3, 0, 1, 2)) | agreq bgwa2msa.inverse = msa2bgwa slit_models[slit] = bgwa2msa ifuslicer.close() ifupost.close() return Gwa2Slit(slit_models)
def imaging_distortion(input_model, reference_files): """ Create pixe2sky and sky2pixel transformation for the MIRI imager. Parameters ---------- model : jwst.datamodels.ImagingModel input model reference_files : dict reference files from CRDS using CDP 3 Reference distortion file Old one: ~~MIRI_FM_MIRIMAGE_F1000W_PSF_03.01.00.fits~~ Current one: MIRI_FM_MIRIMAGE_DISTORTION_06.03.00.fits reference files/corrections needed (pixel to sky): 1. Filter dependent shift in (x,y) (!with an oposite sign to that delievred by the IT) 2. Apply MI 3. Apply Ai and BI matrices 4. Apply the TI matrix (this gives V2/V3 coordinates) 5. Apply V2/V3 to sky transformation ref_file: filter_offset.asdf - (1) ref_file: distortion.asdf -(2,3,4) """ # Load the distortion and filter from the reference files. # Load in the distortion file. distortion = AsdfFile.open(reference_files['distortion']).tree['model'] filter_offset = AsdfFile.open(reference_files['filteroffset']).tree[ input_model.meta.instrument.filter] # Now apply each of the models. The Scale(60) converts from arc-minutes to deg. full_distortion = models.Shift( filter_offset['column_offset']) & models.Shift( filter_offset['row_offset']) | distortion | models.Scale( 1 / 60) & models.Scale(1 / 60) # ToDo: This will likely have to change in the future, but the "filteroffset" file we have # ToDo: currently does not contain that key. filter_offset = None if input_model.meta.instrument.filter in AsdfFile.open( reference_files['filteroffset']).tree: filter_offset = AsdfFile.open(reference_files['filteroffset']).tree[ input_model.meta.instrument.filter] full_distortion = models.Shift( filter_offset['row_offset']) & models.Shift( filter_offset['column_offset']) | distortion else: full_distortion = distortion full_distortion = full_distortion.rename('distortion') return full_distortion
def imaging(input_model, reference_files): """ Imaging pipeline frames : detector, gwa, msa, sky """ # Get the corrected disperser model disperser = get_disperser(input_model, reference_files['disperser']) # DETECTOR to GWA transform det2gwa = detector_to_gwa(reference_files, input_model.meta.instrument.detector, disperser) gwa_through = Const1D(-1) * Identity(1) & Const1D(-1) * Identity( 1) & Identity(1) angles = [ disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y'] ] rotation = Rotation3DToGWA(angles, axes_order="xyzy", name='rotaton').inverse dircos2unitless = DirCos2Unitless(name='directional_cosines2unitless') col = AsdfFile.open(reference_files['collimator']).tree['model'] # Get the default spectral order and wavelength range and record them in the model. sporder, wrange = get_spectral_order_wrange( input_model, reference_files['wavelengthrange']) input_model.meta.wcsinfo.waverange_start = wrange[0] input_model.meta.wcsinfo.waverange_end = wrange[1] input_model.meta.wcsinfo.spectral_order = sporder lam = wrange[0] + (wrange[1] - wrange[0]) * .5 lam_model = Mapping((0, 1, 1)) | Identity(2) & Const1D(lam) gwa2msa = gwa_through | rotation | dircos2unitless | col | lam_model gwa2msa.inverse = col.inverse | dircos2unitless.inverse | rotation.inverse | gwa_through # MSA to OTEIP transform msa2ote = msa_to_oteip(reference_files) msa2oteip = msa2ote | Mapping((0, 1), n_inputs=3) msa2oteip.inverse = Mapping((0, 1, 0, 1)) | msa2ote.inverse | Mapping( (0, 1), n_inputs=3) # OTEIP to V2,V3 transform with AsdfFile.open(reference_files['ote']) as f: oteip2v23 = f.tree['model'].copy() # Create coordinate frames in the NIRSPEC WCS pipeline # "detector", "gwa", "msa", "oteip", "v2v3", "world" det, gwa, msa_frame, oteip, v2v3 = create_imaging_frames() imaging_pipeline = [(det, det2gwa), (gwa, gwa2msa), (msa_frame, msa2oteip), (oteip, oteip2v23), (v2v3, None)] return imaging_pipeline
def gwa_to_ifuslit(slits, disperser, wrange, order, reference_files): """ GWA to SLIT transform. Parameters ---------- slits : list A list of slit IDs for all IFU slits 0-29. disperser : dict A corrected disperser ASDF object. filter : str The filter used. grating : str The grating used in the observation. reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~jwst.transforms.Gwa2Slit` model. Transform from GWA frame to SLIT frame. """ ymin = -.55 ymax = .55 agreq = AngleFromGratingEquation(disperser['groove_density'], order, name='alpha_from_greq') lgreq = WavelengthFromGratingEquation(disperser['groove_density'], order, name='lambda_from_greq') collimator2gwa = collimator_to_gwa(reference_files, disperser) mask = mask_slit(ymin, ymax) ifuslicer = AsdfFile.open(reference_files['ifuslicer']) ifupost = AsdfFile.open(reference_files['ifupost']) slit_models = {} ifuslicer_model = ifuslicer.tree['model'] for slit in slits: slitdata = ifuslicer.tree['data'][slit] slitdata_model = get_slit_location_model(slitdata) ifuslicer_transform = (slitdata_model | ifuslicer_model) ifupost_transform = ifupost.tree[slit]['model'] msa2gwa = ifuslicer_transform | ifupost_transform | collimator2gwa gwa2msa = gwa_to_ymsa(msa2gwa)# TODO: Use model sets here bgwa2msa = Mapping((0, 1, 0, 1), n_inputs=3) | \ Const1D(0) * Identity(1) & Const1D(-1) * Identity(1) & Identity(2) | \ Identity(1) & gwa2msa & Identity(2) | \ Mapping((0, 1, 0, 1, 2, 3)) | Identity(2) & msa2gwa & Identity(2) | \ Mapping((0, 1, 2, 5), n_inputs=7) | Identity(2) & lgreq | mask # msa to before_gwa #msa2bgwa = Mapping((0, 1, 2, 2)) | msa2gwa & Identity(1) | Mapping((3, 0, 1, 2)) | agreq msa2bgwa = msa2gwa & Identity(1) | Mapping((3, 0, 1, 2)) | agreq bgwa2msa.inverse = msa2bgwa slit_models[slit] = bgwa2msa ifuslicer.close() ifupost.close() return Gwa2Slit(slit_models)
def imaging(input_model, reference_files): """ Imaging pipeline frames : detector, gwa, msa, sky """ # Get the corrected disperser model disperser = get_disperser(input_model, reference_files['disperser']) # DETECTOR to GWA transform det2gwa = detector_to_gwa(reference_files, input_model.meta.instrument.detector, disperser) gwa_through = Const1D(-1) * Identity(1) & Const1D(-1) * Identity(1) & Identity(1) angles = [ disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y']] rotation = Rotation3DToGWA(angles, axes_order="xyzy", name='rotaton').inverse dircos2unitless = DirCos2Unitless(name='directional_cosines2unitless') col = AsdfFile.open(reference_files['collimator']).tree['model'] # Get the default spectral order and wavelength range and record them in the model. sporder, wrange = get_spectral_order_wrange(input_model, reference_files['wavelengthrange']) input_model.meta.wcsinfo.waverange_start = wrange[0] input_model.meta.wcsinfo.waverange_end = wrange[1] input_model.meta.wcsinfo.spectral_order = sporder lam = wrange[0] + (wrange[1] - wrange[0]) * .5 lam_model = Mapping((0, 1, 1)) | Identity(2) & Const1D(lam) gwa2msa = gwa_through | rotation | dircos2unitless | col | lam_model gwa2msa.inverse = col.inverse | dircos2unitless.inverse | rotation.inverse | gwa_through # MSA to OTEIP transform msa2ote = msa_to_oteip(reference_files) msa2oteip = msa2ote | Mapping((0, 1), n_inputs=3) msa2oteip.inverse = Mapping((0, 1, 0, 1)) | msa2ote.inverse | Mapping((0, 1), n_inputs=3) # OTEIP to V2,V3 transform with AsdfFile.open(reference_files['ote']) as f: oteip2v23 = f.tree['model'].copy() # Create coordinate frames in the NIRSPEC WCS pipeline # "detector", "gwa", "msa", "oteip", "v2v3", "world" det, gwa, msa_frame, oteip, v2v3 = create_imaging_frames() imaging_pipeline = [(det, det2gwa), (gwa, gwa2msa), (msa_frame, msa2oteip), (oteip, oteip2v23), (v2v3, None)] return imaging_pipeline
def imaging_distortion(input_model, reference_files): """ Create pixe2sky and sky2pixel transformation for the MIRI imager. Parameters ---------- model : jwst.datamodels.ImagingModel input model reference_files : dict reference files from CRDS using CDP 3 Reference distortion file Old one: ~~MIRI_FM_MIRIMAGE_F1000W_PSF_03.01.00.fits~~ Current one: MIRI_FM_MIRIMAGE_DISTORTION_06.03.00.fits reference files/corrections needed (pixel to sky): 1. Filter dependent shift in (x,y) (!with an oposite sign to that delievred by the IT) 2. Apply MI 3. Apply Ai and BI matrices 4. Apply the TI matrix (this gives V2/V3 coordinates) 5. Apply V2/V3 to sky transformation ref_file: filter_offset.asdf - (1) ref_file: distortion.asdf -(2,3,4) """ # Load the distortion and filter from the reference files. # Load in the distortion file. distortion = AsdfFile.open(reference_files['distortion']).tree['model'] filter_offset = AsdfFile.open(reference_files['filteroffset']).tree[input_model.meta.instrument.filter] # Now apply each of the models. The Scale(60) converts from arc-minutes to deg. full_distortion = models.Shift(filter_offset['column_offset']) & models.Shift( filter_offset['row_offset']) | distortion | models.Scale(1/60) & models.Scale(1/60) # ToDo: This will likely have to change in the future, but the "filteroffset" file we have # ToDo: currently does not contain that key. filter_offset = None if input_model.meta.instrument.filter in AsdfFile.open(reference_files['filteroffset']).tree: filter_offset = AsdfFile.open(reference_files['filteroffset']).tree[input_model.meta.instrument.filter] full_distortion = models.Shift(filter_offset['row_offset']) & models.Shift( filter_offset['column_offset']) | distortion else: full_distortion = distortion full_distortion = full_distortion.rename('distortion') return full_distortion
def slit_to_msa(slits_id, msafile): """ The transform from slit_frame to msa_frame. Parameters ---------- slits_id : list A list of slit IDs for all open shutters/slitlets. msafile : str The name of the msa reference file. Returns ------- model : `~jwst_lib.pipeline_models.Slit2Msa` model. Transform from slit_frame to msa_frame. """ msa = AsdfFile.open(msafile) models = {} for i in range(1, 6): slit_names = slits_id[slits_id[:, 0] == i] if slit_names.any(): msa_model = msa.tree[i]['model'] for slit in slit_names: index = slit[1] - 1 slitdata = msa.tree[slit[0]]['data'][index] slitdata_model = get_slit_location_model(slitdata) msa_transform = slitdata_model | msa_model s = slitid_to_slit(np.array([slit]))[0] models[s] = msa_transform msa.close() return Slit2Msa(models)
def get_coord_transform_model(self, filename): #read in asdf distortion transformation reference file #Read in the CRDS-format distortion reference file with AsdfFile.open(filename) as dist_file: coord_transform = dist_file.tree['model'] return coord_transform
def get_spectral_order_wrange(input_model, wavelengthrange_file): """ Read the spectral order and wavelength range from the reference file. Parameters ---------- filter : str The filter used. grating : str The grating used in the observation. wavelength_range_file : str Reference file of type "wavelengthrange". """ full_range = [.6e-6, 5.3e-6] filter = input_model.meta.instrument.filter lamp = input_model.meta.instrument.lamp_state grating = input_model.meta.instrument.grating wave_range = AsdfFile.open(wavelengthrange_file) if filter == "OPAQUE": keyword = lamp + '_' + grating else: keyword = filter + '_' + grating try: order = wave_range.tree['filter_grating'][keyword]['order'] wrange = wave_range.tree['filter_grating'][keyword]['range'] except KeyError: order = -1 wrange = full_range log.warning( "Combination {0} missing in wavelengthrange file, setting order to -1 and range to {1}." .format(keyword, full_range)) wave_range.close() return order, wrange
def test_msa(self): for slit in self.slits: msa = AsdfFile.open( self.model.meta.ref_file.msa.name).tree[slit]['model'] name, xmsa, ymsa, xsizemsa, ysizemsa, xsky, ysky, xsizesky, yskysize, \ xsca1, ysca1, xsca2, ysca2, xsizesca, ysizesca = self._get_reference_data(slit) assert_allclose(msa(0, 0), (xmsa, ymsa))
def oteip_to_v23(reference_files): """ Transform from the OTEIP frame to the V2V3 frame. Parameters ---------- reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~astropy.modeling.core.Model` model. Transform from OTEIP to V2V3. """ with AsdfFile.open(reference_files['ote']) as f: ote = f.tree['model'].copy() fore2ote_mapping = Identity(3, name='fore2ote_mapping') fore2ote_mapping.inverse = Mapping((0, 1, 2, 2)) # Create the transform to v2/v3/lambda. The wavelength units up to this point are # meters as required by the pipeline but the desired output wavelength units is microns. # So we are going to Scale the spectral units by 1e6 (meters -> microns) # The spatial units are currently in deg. Convertin to arcsec. oteip_to_xyan = fore2ote_mapping | (ote & Scale(1e6)) # Add a shift for the aperture. oteip2v23 = oteip_to_xyan | Identity(1) & (Shift(468 / 3600) | Scale(-1)) & Identity(1) return oteip2v23
def slit_to_msa(open_slits, msafile): """ The transform from slit_frame to msa_frame. Parameters ---------- open_slits : list A list of slit IDs for all open shutters/slitlets. msafile : str The name of the msa reference file. Returns ------- model : `~jwst.transforms.Slit2Msa` model. Transform from slit_frame to msa_frame. """ msa = AsdfFile.open(msafile) models = [] for quadrant in range(1, 6): slits_in_quadrant = [s for s in open_slits if s.quadrant==quadrant] if any(slits_in_quadrant): msa_data = msa.tree[quadrant]['data'] msa_model = msa.tree[quadrant]['model'] for slit in slits_in_quadrant: slit_id = slit.shutter_id slitdata = msa_data[slit_id] slitdata_model = get_slit_location_model(slitdata) msa_transform = slitdata_model | msa_model models.append(msa_transform) msa.close() return Slit2Msa(open_slits, models)
def get_wavelength_range(input_model, path=None): """ Return the wavelength range used for computing the WCS. Needs access to the reference file used to construct the WCS object. Parameters ---------- input_model : `jwst.datamodels.ImagingModel` Data model after assign_wcs has been run. path : str Directory where the reference file is. (optional) """ fname = input_model.meta.ref_file.wavelengthrange.name.split('/')[-1] if path is None and not os.path.exists(fname): raise IOError( "Reference file {0} not found. Please specify a path.".format( fname)) else: fname = os.path.join(path, fname) f = AsdfFile.open(fname) wave_range = f.tree['wavelengthrange'].copy() wave_channels = f.tree['channels'] f.close() wr = dict(zip(wave_channels, wave_range)) channel = input_model.meta.instrument.channel band = input_model.meta.instrument.band return dict([(ch + band, wr[ch + band]) for ch in channel])
def get_wavelength_range(input_model, path=None): """ Return the wavelength range used for computing the WCS. Needs access to the reference file used to construct the WCS object. Parameters ---------- input_model : `jwst.datamodels.ImagingModel` Data model after assign_wcs has been run. path : str Directory where the reference file is. (optional) """ fname = input_model.meta.ref_file.wavelengthrange.name.split('/')[-1] if path is None and not os.path.exists(fname): raise IOError("Reference file {0} not found. Please specify a path.".format(fname)) else: fname = os.path.join(path, fname) f = AsdfFile.open(fname) wave_range = f.tree['wavelengthrange'].copy() wave_channels = f.tree['channels'] f.close() wr = dict(zip(wave_channels, wave_range)) channel = input_model.meta.instrument.channel band = input_model.meta.instrument.band return dict([(ch+band, wr[ch+band]) for ch in channel ])
def slit_to_msa(slits_id, msafile): """ The transform from slit_frame to msa_frame. Parameters ---------- slits_id : list A list of slit IDs for all open shutters/slitlets. msafile : str The name of the msa reference file. Returns ------- model : `~jwst.transforms.Slit2Msa` model. Transform from slit_frame to msa_frame. """ msa = AsdfFile.open(msafile) models = {} for i in range(1, 6): slit_names = slits_id[slits_id[:, 0] == i] if slit_names.any(): msa_model = msa.tree[i]['model'] for slit in slit_names: index = slit[1] - 1 slitdata = msa.tree[slit[0]]['data'][index] slitdata_model = get_slit_location_model(slitdata) msa_transform = slitdata_model | msa_model s = slitid_to_slit(np.array([slit]))[0] models[s] = msa_transform msa.close() return Slit2Msa(models)
def collimator_to_gwa(reference_files, disperser): """ Transform from COLLIMATOR to GWA frame. Parameters ---------- reference_files: dict Dictionary with reference files returned by CRDS. disperser : dict A corrected disperser ASDF object. Returns ------- model : `~astropy.modeling.core.Model` model. Transform from COLLIMATOR to GWA frame. """ with AsdfFile.open(reference_files['collimator']) as f: collimator = f.tree['model'].copy() angles = [disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y']] rotation = Rotation3DToGWA(angles, axes_order="xyzy", name='rotaton') u2dircos = Unitless2DirCos(name='unitless2directional_cosines') return collimator.inverse | u2dircos | rotation
def get_spectral_order_wrange(input_model, wavelengthrange_file): """ Read the spectral order and wavelength range from the reference file. Parameters ---------- filter : str The filter used. grating : str The grating used in the observation. wavelength_range_file : str Reference file of type "wavelengthrange". """ full_range = [.6e-6, 5.3e-6] filter = input_model.meta.instrument.filter lamp = input_model.meta.instrument.lamp_state grating = input_model.meta.instrument.grating wave_range = AsdfFile.open(wavelengthrange_file) if filter == "OPAQUE": keyword = lamp + '_' + grating else: keyword = filter + '_' + grating try: order = wave_range.tree['filter_grating'][keyword]['order'] wrange = wave_range.tree['filter_grating'][keyword]['range'] except KeyError: order = -1 wrange = full_range log.warning("Combination {0} missing in wavelengthrange file, setting order to -1 and range to {1}.".format(keyword, full_range)) wave_range.close() return order, wrange
def collimator_to_gwa(reference_files, disperser): """ Transform from COLLIMATOR to GWA frame. Parameters ---------- reference_files: dict Dictionary with reference files returned by CRDS. disperser : dict A corrected disperser ASDF object. Returns ------- model : `~astropy.modeling.core.Model` model. Transform from COLLIMATOR to GWA frame. """ with AsdfFile.open(reference_files['collimator']) as f: collimator = f.tree['model'].copy() angles = [ disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y'] ] rotation = Rotation3DToGWA(angles, axes_order="xyzy", name='rotaton') u2dircos = Unitless2DirCos(name='unitless2directional_cosines') return collimator.inverse | u2dircos | rotation
def test_transform(asdf_file): """ Parameters ---------- asdf_file: str reference file with distortion xy, v2, v3 values are from technical report with CDP-3 delivery """ v2 = np.array([-8, -7.5, -7, -6.5, -8, -7.5, -7, -6.5, -8, -7.5, -7, -6.5], dtype=np.float) v3 = np.array([-2, -2, -2, -2, -1.5, -1.5, -1.5, -1.5, -1, -1, -1, -1], dtype=np.float) xy = np.array([[945.80, 728.45], [676.57, 748.63], [408.29, 768.69], [138.02, 789.09], [924.30, 456.59], [655.18, 477.89], [387.05, 498.99], [116.92, 519.96], [904.31, 185.02], [635.09, 207.37], [366.53, 229.45], [95.58, 250.95]], dtype=np.float) f = AsdfFile.open(asdf_file) transform = f.tree['model'] x, y = transform.inverse(v2, v3) assert_allclose(x, xy[:, 0], atol=.05) assert_allclose(y, xy[:, 1], atol=.05) s1, s2 = transform(xy[:, 0], xy[:, 1]) assert_allclose(s1, v2, atol=0.05) assert_allclose(s2, v3, atol=.05)
def gwa_to_slit(slits_id, disperser, wrange, order, reference_files): """ GWA to SLIT transform. Parameters ---------- slits_id : list A list of slit IDs for all open shutters/slitlets. disperser : dict A corrected disperser ASDF object. filter : str The filter used. grating : str The grating used in the observation. reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~jwst_lib.pipeline_models.Gwa2Slit` model. Transform from GWA frame to SLIT frame. """ agreq = AngleFromGratingEquation(disperser['groove_density'], order, name='alpha_from_greq') lgreq = WavelengthFromGratingEquation(disperser['groove_density'], order, name='lambda_from_greq') collimator2gwa = collimator_to_gwa(reference_files, disperser) msa = AsdfFile.open(reference_files['msa']) slit_models = {} for i in range(1, 6): slit_names = slits_id[slits_id[:, 0] == i] if slit_names.any(): msa_model = msa.tree[i]['model'] for slit in slit_names: index = slit[1] - 1 slitdata = msa.tree[slit[0]]['data'][index] slitdata_model = get_slit_location_model(slitdata) msa_transform = slitdata_model | msa_model msa2gwa = (msa_transform | collimator2gwa) gwa2msa = gwa_to_ymsa(msa2gwa) # TODO: Use model sets here bgwa2msa = Mapping((0, 1, 0, 1), n_inputs=3) | \ Const1D(0) * Identity(1) & Const1D(-1) * Identity(1) & Identity(2) | \ Identity(1) & gwa2msa & Identity(2) | \ Mapping((0, 1, 0, 1, 2, 3)) | Identity(2) & msa2gwa & Identity(2) | \ Mapping((0, 1, 2, 5), n_inputs=7)| Identity(2) & lgreq # msa to before_gwa msa2bgwa = msa2gwa & Identity(1) | Mapping( (3, 0, 1, 2)) | agreq bgwa2msa.inverse = msa2bgwa s = slitid_to_slit(np.array([slit]))[0] slit_models[s] = bgwa2msa msa.close() return Gwa2Slit(slit_models)
def gwa_to_slit(slits_id, disperser, wrange, order, reference_files): """ GWA to SLIT transform. Parameters ---------- slits_id : list A list of slit IDs for all open shutters/slitlets. disperser : dict A corrected disperser ASDF object. filter : str The filter used. grating : str The grating used in the observation. reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~jwst.transforms.Gwa2Slit` model. Transform from GWA frame to SLIT frame. """ ymin = -.55 ymax = .55 agreq = AngleFromGratingEquation(disperser['groove_density'], order, name='alpha_from_greq') lgreq = WavelengthFromGratingEquation(disperser['groove_density'], order, name='lambda_from_greq') collimator2gwa = collimator_to_gwa(reference_files, disperser) mask = mask_slit(ymin, ymax) msa = AsdfFile.open(reference_files['msa']) slit_models = {} for i in range(1, 6): slit_names = slits_id[slits_id[:, 0] == i] if slit_names.any(): msa_model = msa.tree[i]['model'] for slit in slit_names: index = slit[1] - 1 slitdata = msa.tree[slit[0]]['data'][index] slitdata_model = get_slit_location_model(slitdata) msa_transform = slitdata_model | msa_model msa2gwa = (msa_transform | collimator2gwa) gwa2msa = gwa_to_ymsa(msa2gwa)# TODO: Use model sets here bgwa2msa = Mapping((0, 1, 0, 1), n_inputs=3) | \ Const1D(0) * Identity(1) & Const1D(-1) * Identity(1) & Identity(2) | \ Identity(1) & gwa2msa & Identity(2) | \ Mapping((0, 1, 0, 1, 2, 3)) | Identity(2) & msa2gwa & Identity(2) | \ Mapping((0, 1, 2, 5), n_inputs=7) | Identity(2) & lgreq | mask # msa to before_gwa msa2bgwa = msa2gwa & Identity(1) | Mapping((3, 0, 1, 2)) | agreq bgwa2msa.inverse = msa2bgwa s = slitid_to_slit(np.array([slit]))[0] slit_models[s] = bgwa2msa msa.close() return Gwa2Slit(slit_models)
def imaging_distortion(input_model, reference_files): distortion = AsdfFile.open(reference_files['distortion']).tree['model'] # Convert to deg - output of distortion models is in arcsec. transform = distortion | Scale(1 / 3600) & Scale(1 / 3600) try: bb = transform.bounding_box except NotImplementedError: shape = input_model.data.shape # Note: Since bounding_box is attached to the model here it's in reverse order. transform.bounding_box = ((-0.5, shape[0] - 0.5), (-0.5, shape[1] - 0.5)) return transform
def imaging_distortion(input_model, reference_files): """ Create pixe2sky and sky2pixel transformation for the MIRI imager. Parameters ---------- input_model : `jwst.datamodels.ImagingModel` Data model. reference_files : dict Dictionary {reftype: reference file name}. 1. Filter dependent shift in (x,y) (!with an oposite sign to that delivered by the IT) 2. Apply MI 3. Apply Ai and BI matrices 4. Apply the TI matrix (this gives Xan/Yan coordinates) 5. Aply the XanYan --> V2V3 transform 5. Apply V2V3 --> sky transform ref_file: filter_offset.asdf - (1) ref_file: distortion.asdf -(2,3,4) """ # Read in the distortion. distortion = AsdfFile.open(reference_files['distortion']).tree['model'] obsfilter = input_model.meta.instrument.filter # Add an offset for the filter with AsdfFile.open(reference_files['filteroffset']) as filter_offset: if obsfilter in filter_offset.tree: filter_corr = filter_offset.tree[obsfilter] distortion = models.Shift( filter_corr['column_offset']) & models.Shift( filter_corr['row_offset']) | distortion # Apply XanYan --> V2V3 and scale to degrees distortion = distortion | models.Identity(1) & (models.Scale(-1) | models.Shift(-7.8)) | \ models.Scale(1/60) & models.Scale(1/60) return distortion
def imaging_distortion(input_model, reference_files): """ Create pixe2sky and sky2pixel transformation for the MIRI imager. Parameters ---------- model : jwst.datamodels.ImagingModel input model reference_files : dict reference files from CRDS 1. Filter dependent shift in (x,y) (!with an oposite sign to that delivered by the IT) 2. Apply MI 3. Apply Ai and BI matrices 4. Apply the TI matrix (this gives Xan/Yan coordinates) 5. Aply the XanYan --> V2V3 transform 5. Apply V2V3 --> sky transform ref_file: filter_offset.asdf - (1) ref_file: distortion.asdf -(2,3,4) """ # Read in the distortion. distortion = AsdfFile.open(reference_files['distortion']).tree['model'] obsfilter = input_model.meta.instrument.filter # Add an offset for the filter with AsdfFile.open(reference_files['filteroffset']) as filter_offset: if obsfilter in filter_offset.tree: filter_corr = filter_offset.tree[obsfilter] distortion = models.Shift(filter_corr['column_offset']) & models.Shift( filter_corr['row_offset']) | distortion # Apply XanYan --> V2V3 and scale to degrees distortion = distortion | models.Identity(1) & (models.Scale(-1) | models.Shift(-7.8)) | \ models.Scale(1/60) & models.Scale(1/60) return distortion
def niriss_soss(input_model, reference_files): """ The NIRISS SOSS pipeline includes 3 coordinate frames - detector, focal plane and sky reference_files={'specwcs': 'soss_wavelengths_configuration.asdf'} """ # Get the target RA and DEC, they will be used for setting the WCS RA and DEC based on a conversation # with Kevin Volk. try: target_ra = float(input_model['meta.target.ra']) target_dec = float(input_model['meta.target.dec']) except: # There was an error getting the target RA and DEC, so we are not going to continue. raise ValueError('Problem getting the TARG_RA or TARG_DEC from input model {}'.format(input_model)) # Define the frames detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) spec = cf.SpectralFrame(name='spectral', axes_order=(2,), unit=(u.micron,), axes_names=('wavelength',)) sky = cf.CelestialFrame(reference_frame=coord.ICRS(), axes_names=('ra', 'dec'), axes_order=(0, 1), unit=(u.deg, u.deg), name='sky') world = cf.CompositeFrame([sky, spec], name='world') try: with AsdfFile.open(reference_files['specwcs']) as wl: wl1 = wl.tree[1].copy() wl2 = wl.tree[2].copy() wl3 = wl.tree[3].copy() except Exception as e: raise IOError('Error reading wavelength correction from {}'.format(reference_files['specwcs'])) cm_order1 = (Mapping((0, 1, 0, 1)) | (Const1D(target_ra) & Const1D(target_dec) & wl1)).rename('Order1') cm_order2 = (Mapping((0, 1, 0, 1)) | (Const1D(target_ra) & Const1D(target_dec) & wl2)).rename('Order2') cm_order3 = (Mapping((0, 1, 0, 1)) | (Const1D(target_ra) & Const1D(target_dec) & wl3)).rename('Order3') # Define the transforms, they should accept (x,y) and return (ra, dec, lambda) soss_model = NirissSOSSModel([1, 2, 3], [cm_order1, cm_order2, cm_order3]).rename('3-order SOSS Model') # Define the pipeline based on the frames and models above. pipeline = [(detector, soss_model), (world, None) ] return pipeline
def oteip_to_v23(reference_files): """ Transform from the OTEIP frame to the V2V3 frame. Parameters ---------- reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~astropy.modeling.core.Model` model. Transform from OTEIP to V2V3. """ with AsdfFile.open(reference_files['ote']) as f: ote = f.tree['model'].copy() fore2ote_mapping = Identity(3, name='fore2ote_mapping') fore2ote_mapping.inverse = Mapping((0, 1, 2, 2)) # Convert the wavelength to microns return fore2ote_mapping | (ote & Identity(1) / Const1D(1e-6))
def get_disperser(input_model, disperserfile): """ Return the disperser information corrected for the uncertainty in the GWA position. Parameters ---------- input_model : `jwst_lib.models.DataModel` The input data model - either an ImageModel or a CubeModel. disperserfile : str The name of the disperser reference file. Returns ------- disperser : dict The corrected disperser information. """ with AsdfFile.open(disperserfile) as f: disperser = f.tree xtilt = input_model.meta.instrument.gwa_xtilt ytilt = input_model.meta.instrument.gwa_ytilt disperser = correct_tilt(disperser, xtilt, ytilt) return disperser
def get_disperser(input_model, disperserfile): """ Return the disperser information corrected for the uncertainty in the GWA position. Parameters ---------- input_model : `jwst.datamodels.DataModel` The input data model - either an ImageModel or a CubeModel. disperserfile : str The name of the disperser reference file. Returns ------- disperser : dict The corrected disperser information. """ with AsdfFile.open(disperserfile) as f: disperser = f.tree xtilt = input_model.meta.instrument.gwa_xtilt ytilt = input_model.meta.instrument.gwa_ytilt disperser = correct_tilt(disperser, xtilt, ytilt) return disperser
def oteip_to_v23(reference_files): """ Transform from the OTEIP frame to the V2V3 frame. Parameters ---------- reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~astropy.modeling.core.Model` model. Transform from OTEIP to V2V3. """ with AsdfFile.open(reference_files['ote']) as f: ote = f.tree['model'].copy() fore2ote_mapping = Identity(3, name='fore2ote_mapping') fore2ote_mapping.inverse = Mapping((0, 1, 2, 2)) # Create the transform to v2/v3/lambda. The wavelength units up to this point are # meters as required by the pipeline but the desired output wavelength units is microns. # So we are going to Scale the spectral units by 1e6 (meters -> microns) return fore2ote_mapping | (ote & Scale(1e6))
def test_transform(asdf_file): """ Parameters ---------- asdf_file: str reference file with distortion xy, v2, v3 values are from technical report with CDP-3 delivery """ v2 = np.array([-2, -2, -2, -2, -1.5, -1.5, -1.5, -1.5, -1, -1, -1, -1], dtype=np.float) v3 = np.array([-8, -7.5, -7, -6.5, -8, -7.5, -7, -6.5, -8, -7.5, -7, -6.5], dtype=np.float) xy = np.array([[945.80, 728.45], [676.57, 748.63], [408.29, 768.69], [138.02, 789.09], [924.30, 456.59],[655.18, 477.89], [387.05, 498.99], [116.92, 519.96], [904.31, 185.02], [635.09, 207.37], [366.53, 229.45], [95.58, 250.95]], dtype=np.float) f = AsdfFile.open(asdf_file) transform = f.tree['distortion'] x, y = transform.inverse(v2, v3) assert_allclose(x, xy[:,0], atol=.05) assert_allclose(y, xy[:,1], atol=.05) s1, s2 = transform (xy[:,0], xy[:,1]) assert_allclose(s1, v2, atol=0.05) assert_allclose(s2, v3, atol=.05)
def run(self): filename = self.arguments[0] cwd = os.getcwd() os.chdir(TMPDIR) parts = [] try: ff = AsdfFile() code = AsdfFile._open_impl(ff, filename, _get_yaml_content=True) code = '{0} {1}\n'.format(ASDF_MAGIC, version_string) + code.strip().decode('utf-8') literal = nodes.literal_block(code, code) literal['language'] = 'yaml' set_source_info(self, literal) parts.append(literal) kwargs = dict() # Use the ignore_unrecognized_tag parameter as a proxy for both options kwargs['ignore_unrecognized_tag'] = 'ignore_unrecognized_tag' in self.arguments kwargs['ignore_missing_extensions'] = 'ignore_unrecognized_tag' in self.arguments with AsdfFile.open(filename, **kwargs) as ff: for i, block in enumerate(ff.blocks.internal_blocks): data = codecs.encode(block.data.tostring(), 'hex') if len(data) > 40: data = data[:40] + '...'.encode() allocated = block._allocated size = block._size data_size = block._data_size flags = block._flags if flags & BLOCK_FLAG_STREAMED: allocated = size = data_size = 0 lines = [] lines.append('BLOCK {0}:'.format(i)) human_flags = [] for key, val in FLAGS.items(): if flags & key: human_flags.append(val) if len(human_flags): lines.append(' flags: {0}'.format(' | '.join(human_flags))) if block.input_compression: lines.append(' compression: {0}'.format(block.input_compression)) lines.append(' allocated_size: {0}'.format(allocated)) lines.append(' used_size: {0}'.format(size)) lines.append(' data_size: {0}'.format(data_size)) lines.append(' data: {0}'.format(data)) code = '\n'.join(lines) literal = nodes.literal_block(code, code) literal['language'] = 'yaml' set_source_info(self, literal) parts.append(literal) internal_blocks = list(ff.blocks.internal_blocks) if (len(internal_blocks) and internal_blocks[-1].array_storage != 'streamed'): buff = io.BytesIO() ff.blocks.write_block_index(buff, ff) block_index = buff.getvalue().decode('utf-8') literal = nodes.literal_block(block_index, block_index) literal['language'] = 'yaml' set_source_info(self, literal) parts.append(literal) finally: os.chdir(cwd) result = nodes.literal_block() textnodes, messages = self.state.inline_text(filename, self.lineno) title = nodes.title(filename, '', *textnodes) result += title result += parts return [result]
def dist_coeff(): """ Create distortion correction reference file. Parameters: ___________ coefficients: float coefficients The order of the input text files with coefficients is from det2sky and then sky2det. """ "Put coefficients into variables by reading in text files" coeffxr, coeffyr = np.loadtxt(sys.argv[1], skiprows=6, usecols=(1, 2), unpack=True) print(coeffxr) print(coeffyr) coeffxi, coeffyi = np.loadtxt(sys.argv[2], skiprows=6, usecols=(1, 2), unpack=True) print(coeffxi) print(coeffyi) "Transform coefficients to get undistorted, real, sky x." x0_0r = coeffxr[0] print('Coefficient for x0_0: ', x0_0r) x1_0r = coeffxr[1] print('Coefficient for x1_0: ', x1_0r) x0_1r = coeffxr[2] print('Coefficient for x0_1: ', x0_1r) x2_0r = coeffxr[3] print('Coefficient for x2_0: ', x2_0r) x1_1r = coeffxr[4] print('Coefficient for x1_1: ', x1_1r) x0_2r = coeffxr[5] print('Coefficient for x0_2: ', x0_2r) x3_0r = coeffxr[6] print('Coefficient for x3_0: ', x3_0r) x2_1r = coeffxr[7] print('Coefficient for x2_1: ', x2_1r) x1_2r = coeffxr[8] print('Coefficient for x1_2: ', x1_2r) x0_3r = coeffxr[9] print('Coefficient for x0_3: ', x0_3r) x4_0r = coeffxr[10] print('Coefficient for x4_0: ', x4_0r) x3_1r = coeffxr[11] print('Coefficient for x3_1: ', x3_1r) x2_2r = coeffxr[12] print('Coefficient for x2_2: ', x2_2r) x1_3r = coeffxr[13] print('Coefficient for x1_3: ', x1_3r) x0_4r = coeffxr[14] print('Coefficient for x0_4: ', x0_4r) "Transform coefficients to get undistorted, real, sky y." y0_0r = coeffyr[0] print('Coefficient for y0_0: ', y0_0r) y1_0r = coeffyr[1] print('Coefficient for y1_0: ', y1_0r) y0_1r = coeffyr[2] print('Coefficient for y0_1: ', y0_1r) y2_0r = coeffyr[3] print('Coefficient for y2_0: ', y2_0r) y1_1r = coeffyr[4] print('Coefficient for y1_1: ', y1_1r) y0_2r = coeffyr[5] print('Coefficient for y0_2: ', y0_2r) y3_0r = coeffyr[6] print('Coefficient for y3_0: ', y3_0r) y2_1r = coeffyr[7] print('Coefficient for y2_1: ', y2_1r) y1_2r = coeffyr[8] print('Coefficient for y1_2: ', y1_2r) y0_3r = coeffyr[9] print('Coefficient for y0_3: ', y0_3r) y4_0r = coeffyr[10] print('Coefficient for y4_0: ', y4_0r) y3_1r = coeffyr[11] print('Coefficient for y3_1: ', y3_1r) y2_2r = coeffyr[12] print('Coefficient for y2_2: ', y2_2r) y1_3r = coeffyr[13] print('Coefficient for y1_3: ', y1_3r) y0_4r = coeffyr[14] print('Coefficient for y0_4: ', y0_4r) "Transform coefficients to get distorted, ideal, detector x." x0_0i = coeffxi[0] print('Coefficient for x0_0: ', x0_0i) x1_0i = coeffxi[1] print('Coefficient for x1_0: ', x1_0i) x0_1i = coeffxi[2] print('Coefficient for x0_1: ', x0_1i) x2_0i = coeffxi[3] print('Coefficient for x2_0: ', x2_0i) x1_1i = coeffxi[4] print('Coefficient for x1_1: ', x1_1i) x0_2i = coeffxi[5] print('Coefficient for x0_2: ', x0_2i) x3_0i = coeffxi[6] print('Coefficient for x3_0: ', x3_0i) x2_1i = coeffxi[7] print('Coefficient for x2_1: ', x2_1i) x1_2i = coeffxi[8] print('Coefficient for x1_2: ', x1_2i) x0_3i = coeffxi[9] print('Coefficient for x0_3: ', x0_3i) x4_0i = coeffxi[10] print('Coefficient for x4_0: ', x4_0i) x3_1i = coeffxi[11] print('Coefficient for x3_1: ', x3_1i) x2_2i = coeffxi[12] print('Coefficient for x2_2: ', x2_2i) x1_3i = coeffxi[13] print('Coefficient for x1_3: ', x1_3i) x0_4i = coeffxi[14] print('Coefficient for x0_4: ', x0_4i) "Transform coefficients to get distorted, ideal, detector y." y0_0i = coeffyi[0] print('Coefficient for y0_0: ', y0_0i) y1_0i = coeffyi[1] print('Coefficient for y1_0: ', y1_0i) y0_1i = coeffyi[2] print('Coefficient for y0_1: ', y0_1i) y2_0i = coeffyi[3] print('Coefficient for y2_0: ', y2_0i) y1_1i = coeffyi[4] print('Coefficient for y1_1: ', y1_1i) y0_2i = coeffyi[5] print('Coefficient for y0_2: ', y0_2i) y3_0i = coeffyi[6] print('Coefficient for y3_0: ', y3_0i) y2_1i = coeffyi[7] print('Coefficient for y2_1: ', y2_1i) y1_2i = coeffyi[8] print('Coefficient for y1_2: ', y1_2i) y0_3i = coeffyi[9] print('Coefficient for y0_3: ', y0_3i) y4_0i = coeffyi[10] print('Coefficient for y4_0: ', y4_0i) y3_1i = coeffyi[11] print('Coefficient for y3_1: ', y3_1i) y2_2i = coeffyi[12] print('Coefficient for y2_2: ', y2_2i) y1_3i = coeffyi[13] print('Coefficient for y1_3: ', y1_3i) y0_4i = coeffyi[14] print('Coefficient for y0_4: ', y0_4i) "Generate ideal or detector coordinates." x_pix = np.arange(0, 2048, 1) y_pix = np.arange(0, 2048, 1) x_det_orig = [] y_det_orig = [] for x, y in itertools.product(x_pix, y_pix): x_det_orig.append(x) y_det_orig.append(y) print('Done with first for loop!!!!') print(len(x_det_orig)) print(len(y_det_orig)) "To go from ideal, distorted to real, undistorted." x_sky = [] y_sky = [] #------- for x, y in zip(x_det_orig, y_det_orig): x_real, y_real = apply_coeff(x, y, coeffxr, coeffyr) x_sky.append(x_real) y_sky.append(y_real) #------- print(' ') print('Done with second for loop!!!!') print(len(x_sky)) print(len(y_sky)) x_sky = np.array(x_sky) y_sky = np.array(y_sky) print('Above is for transformation to sky pixels.') "To go from real, undistorted to ideal, distorted." x_det = [] y_det = [] for x, y in zip(x_sky, y_sky): x_ideal, y_ideal = apply_coeff(x, y, coeffxi, coeffyi) x_det.append(x_ideal) y_det.append(y_ideal) print(' ') print('Done with third for loop!!!!') print(len(x_det)) print(len(y_det)) print('Above is for transformation to detector pixels.') "Derive residuals from the complete transformation." x_det = np.array(x_det) y_det = np.array(y_det) x_det_orig = np.array(x_det_orig) y_det_orig = np.array(y_det_orig) resid_x = x_det - x_det_orig resid_y = y_det - y_det_orig print(' ') print('Residual in x: ', resid_x) print(np.min(resid_x), np.max(resid_x)) print(' ') print('Residual in y: ', resid_y) print(np.min(resid_y), np.max(resid_y)) 'Open asdf reference file and transfrom from det to sky.' f = AsdfFile.open('niriss_ref_distortion_image.asdf') det2sky_trans = f.tree['model'] sky_x, sky_y = det2sky_trans(x_det_orig, y_det_orig) 'Transform from sky to det.' sky2det_trans = det2sky_trans.inverse inv_x, inv_y = sky2det_trans(sky_x, sky_y) 'Calculate residuals from reference file.' x_resid_ref = inv_x - x_det_orig y_resid_ref = inv_y - y_det_orig 'Calculate residuals of residuals.' x_resid_resid = np.absolute(resid_x - x_resid_ref) y_resid_resid = np.absolute(resid_y - y_resid_ref) print(' ') print(x_resid_resid) print('The minimum in x_resid_resid is: ', np.min(x_resid_resid)) print('The maximum in x_resid_resid is: ', np.max(x_resid_resid)) print('The mean in x_resid_resid is: ', np.mean(x_resid_resid)) print('The standard deviation in x_resid_resid is: ', np.std(x_resid_resid)) print('The median in x_resid_resid is: ', np.median(x_resid_resid)) print(' ') print(y_resid_resid) print('The minimum in y_resid_resid is: ', np.min(y_resid_resid)) print('The maximum in y_resid_resid is: ', np.max(y_resid_resid)) print('The mean in y_resid_resid is: ', np.mean(y_resid_resid)) print('The standard deviation in y_resid_resid is: ', np.std(y_resid_resid)) print('The median in y_resid_resid is: ', np.median(y_resid_resid)) print(' ') print('Done, Done, and Done. Git the bleep along little doggies.')
def detector_to_alpha_beta(input_model, reference_files): """ Create the transform from detector to alpha, beta frame. forward transform: RegionsSelector label_mapper is the regions array selector is {slice_number: alphs_model & beta_model & lambda_model} backward transform: RegionsSelector label_mapper is LabelMapperDict {channel_wave_range (): LabelMapperDict} {beta: slice_number} selector is {slice_number: x_transform & y_transform} """ band = input_model.meta.instrument.band channel = input_model.meta.instrument.channel # used to read the wavelength range channels = [c + band for c in channel] f = AsdfFile.open(reference_files['distortion']) # The name of the model indicates the output coordinate alpha_model = f.tree['alpha_model'] beta_model = f.tree['beta_model'] x_model = f.tree['x_model'] y_model = f.tree['y_model'] slice_model = f.tree['slice_model'] f.close() f = AsdfFile.open(reference_files['specwcs']) lambda_model = f.tree['model'] f.close() f = AsdfFile.open(reference_files['regions']) regions = f.tree['regions'].copy() f.close() label_mapper = selector.LabelMapperArray(regions) transforms = {} for sl in alpha_model: chan = str(sl // 100) + band forward = models.Mapping([1, 0, 0, 1, 0]) | \ alpha_model[sl] & beta_model[sl] & lambda_model[sl] inv = models.Mapping([2, 0, 2, 0]) | x_model[sl] & y_model[sl] forward.inverse = inv transforms[sl] = forward f = AsdfFile.open(reference_files['wavelengthrange']) # the following should go in the asdf reader wave_range = f.tree['wavelengthrange'].copy() wave_channels = f.tree['channels'] wr = {} for ch, r in zip(wave_channels, wave_range): wr[ch] = r f.close() ch_dict = {} for c in channels: ch_dict.update({tuple(wr[c]): selector.LabelMapperDict(('alpha', 'beta', 'lam'), slice_model[c], models.Mapping([1,], n_inputs=3))}) alpha_beta_mapper = selector.LabelMapperRange(('alpha', 'beta', 'lam'), ch_dict, models.Mapping((2,))) label_mapper.inverse = alpha_beta_mapper det2alpha_beta = selector.RegionsSelector(('x', 'y'), ('alpha', 'beta', 'lam'), label_mapper=label_mapper, selector=transforms) return det2alpha_beta
def slit_to_detector(input_model, slits_id, lam, reference_files): """ For each slit computes the transform from the MSA to the detector. Used to flag stuck open shutters. Reftypes needed: reftypes = ['fpa', 'camera', 'disperser', 'collimator', 'msa', 'wavelengthrange'] Parameters ---------- input_model : jwst.datamodels.DataModel Input data model slits : list A list of slit IDs. A slit ID is a tuple of (quadrant, slit_nimber) lam : float wavelength, in meters reference_files : dict A dictionary with WCS reference_files, {reftype: refname} Returns ------- msa2det : dict A dictionary with the MSA to detector transform for each slit, {slit_id: astropy.modeling.Model} """ slits_msa2det = {} # read models from reference files with AsdfFile.open(reference_files['fpa']) as f: fpa = f.tree[input_model.meta.instrument.detector].copy() with AsdfFile.open(reference_files['camera']) as f: camera = f.tree['model'].copy() with AsdfFile.open(reference_files['disperser']) as f: disperser = f.tree dircos2u = DirCos2Unitless(name='directional2unitless_cosines') disperser = correct_tilt(disperser, input_model.meta.instrument.gwa_xtilt, input_model.meta.instrument.gwa_ytilt) angles = [disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y']] rotation = Rotation3DToGWA(angles, axes_order="xyzy", name='rotaton') order, wrange = get_spectral_order_wrange(input_model, reference_files['wavelengthrange']) input_model.meta.wcsinfo.waverange_start = wrange[0] input_model.meta.wcsinfo.waverange_end = wrange[1] input_model.meta.wcsinfo.spectral_order = order agreq = AngleFromGratingEquation(disperser['groove_density'], order, name='alpha_from_greq') # GWA to detector gwa2det = rotation.inverse | dircos2u | camera.inverse | fpa.inverse # collimator to GWA collimator2gwa = collimator_to_gwa(reference_files, disperser) msa = AsdfFile.open(reference_files['msa']) for i in range(1, 5): slit_names = slits_id[slits_id[:, 0] == i] if slit_names.any(): msa_model = msa.tree[i]['model'] for slit in slit_names: index = slit[1] - 1 slitdata = msa.tree[slit[0]]['data'][index] slitdata_model = get_slit_location_model(slitdata) # absolute positions of the slit on the MSA msa_transform = slitdata_model | msa_model s = slitid_to_slit(np.array([slit]))[0] msa2gwa = (msa_transform | collimator2gwa) & Identity(1) | Mapping((3, 0, 1, 2)) | agreq slits_msa2det[s] = msa2gwa | gwa2det msa.close() return slits_msa2det
def __init__(self, init=None, schema=None, extensions=None, pass_invalid_values=False): """ Parameters ---------- init : shape tuple, file path, file object, astropy.io.fits.HDUList, numpy array, None - None: A default data model with no shape - shape tuple: Initialize with empty data of the given shape - file path: Initialize from the given file (FITS or ASDF) - readable file object: Initialize from the given file object - ``astropy.io.fits.HDUList``: Initialize from the given `~astropy.io.fits.HDUList`. - A numpy array: Used to initialize the data array - dict: The object model tree for the data model schema : tree of objects representing a JSON schema, or string naming a schema, optional The schema to use to understand the elements on the model. If not provided, the schema associated with this class will be used. extensions: classes extending the standard set of extensions pass_invalid_values: If True, values that do not validate the schema can be read and written, but with a warning message """ filename = os.path.abspath(inspect.getfile(self.__class__)) base_url = os.path.join( os.path.dirname(filename), 'schemas', '') if schema is None: schema_path = os.path.join(base_url, self.schema_url) schema = asdf_schema.load_schema( schema_path, resolve_references=True) self._schema = mschema.flatten_combiners(schema) if extensions is not None: extensions.extend(jwst_extensions) else: extensions = jwst_extensions[:] self._extensions = extensions if "PASS_INVALID_VALUES" in os.environ: pass_invalid_values = os.environ["PASS_INVALID_VALUES"] try: self._pass_invalid_values = bool(int(pass_invalid_values)) except ValueError: self._pass_invalid_values = False else: self._pass_invalid_values = pass_invalid_values self._files_to_close = [] is_array = False is_shape = False shape = None if init is None: asdf = AsdfFile(extensions=extensions) elif isinstance(init, dict): asdf = AsdfFile(init, extensions=extensions) elif isinstance(init, np.ndarray): asdf = AsdfFile(extensions=extensions) shape = init.shape is_array = True elif isinstance(init, self.__class__): instance = copy.deepcopy(init._instance) self._schema = init._schema self._shape = init._shape self._asdf = AsdfFile(instance, extensions=self._extensions) self._instance = instance self._ctx = self self.__class__ = init.__class__ return elif isinstance(init, DataModel): raise TypeError( "Passed in {0!r} is not of the expected subclass {1!r}".format( init.__class__.__name__, self.__class__.__name__)) elif isinstance(init, AsdfFile): asdf = init elif isinstance(init, tuple): for item in init: if not isinstance(item, int): raise ValueError("shape must be a tuple of ints") shape = init asdf = AsdfFile() is_shape = True elif isinstance(init, fits.HDUList): asdf = fits_support.from_fits(init, self._schema, extensions=self._extensions, validate=False, pass_invalid_values=self._pass_invalid_values) elif isinstance(init, six.string_types): if isinstance(init, bytes): init = init.decode(sys.getfilesystemencoding()) try: hdulist = fits.open(init) except IOError: try: asdf = AsdfFile.open(init, extensions=self._extensions) # TODO: Add json support except ValueError: raise IOError( "File does not appear to be a FITS or ASDF file.") else: asdf = fits_support.from_fits(hdulist, self._schema, extensions=self._extensions, validate=False, pass_invalid_values=self._pass_invalid_values) self._files_to_close.append(hdulist) self._shape = shape self._instance = asdf.tree self._asdf = asdf self._ctx = self # if the input model doesn't have a date set, use the current date/time if self.meta.date is None: self.meta.date = Time(datetime.datetime.now()) self.meta.date.format='isot' self.meta.date = self.meta.date.value # if the input is from a file, set the filename attribute if isinstance(init, six.string_types): self.meta.filename = os.path.basename(init) if is_array: primary_array_name = self.get_primary_array_name() if primary_array_name is None: raise TypeError( "Array passed to model.__init__, but model has no primary " "array in its schema") setattr(self, primary_array_name, init) if is_shape: getattr(self, self.get_primary_array_name())
def imaging_distortion(input_model, reference_files): distortion = AsdfFile.open(reference_files['distortion']).tree['model'] # Convert to deg - output of distortion models is in arcsec. transform = distortion | Scale(1/3600) & Scale(1/3600) return transform
def gwa_to_slit(open_slits, input_model, disperser, reference_files): """ GWA to SLIT transform. Parameters ---------- open_slits : list A list of slit IDs for all open shutters/slitlets. disperser : dict A corrected disperser ASDF object. filter : str The filter used. grating : str The grating used in the observation. reference_files: dict Dictionary with reference files returned by CRDS. Returns ------- model : `~jwst.transforms.Gwa2Slit` model. Transform from GWA frame to SLIT frame. """ wrange = (input_model.meta.wcsinfo.waverange_start, input_model.meta.wcsinfo.waverange_end), order = input_model.meta.wcsinfo.spectral_order agreq = angle_from_disperser(disperser, input_model) collimator2gwa = collimator_to_gwa(reference_files, disperser) lgreq = wavelength_from_disperser(disperser, input_model) # The wavelength units up to this point are # meters as required by the pipeline but the desired output wavelength units is microns. # So we are going to Scale the spectral units by 1e6 (meters -> microns) if input_model.meta.instrument.filter == 'OPAQUE': lgreq = lgreq | Scale(1e6) msa = AsdfFile.open(reference_files['msa']) slit_models = [] for quadrant in range(1, 6): slits_in_quadrant = [s for s in open_slits if s.quadrant==quadrant] log.info("There are {0} open slits in quadrant {1}".format(len(slits_in_quadrant), quadrant)) if any(slits_in_quadrant): msa_model = msa.tree[quadrant]['model'] log.info("Getting slits location for quadrant {0}".format(quadrant)) msa_data = msa.tree[quadrant]['data'] for slit in slits_in_quadrant: mask = mask_slit(slit.ymin, slit.ymax) slit_id = slit.shutter_id slitdata = msa_data[slit_id] slitdata_model = get_slit_location_model(slitdata) msa_transform = slitdata_model | msa_model msa2gwa = (msa_transform | collimator2gwa) gwa2msa = gwa_to_ymsa(msa2gwa)# TODO: Use model sets here bgwa2msa = Mapping((0, 1, 0, 1), n_inputs=3) | \ Const1D(0) * Identity(1) & Const1D(-1) * Identity(1) & Identity(2) | \ Identity(1) & gwa2msa & Identity(2) | \ Mapping((0, 1, 0, 1, 2, 3)) | Identity(2) & msa2gwa & Identity(2) | \ Mapping((0, 1, 2, 3, 5), n_inputs=7) | Identity(2) & lgreq | mask #Mapping((0, 1, 2, 5), n_inputs=7) | Identity(2) & lgreq | mask # and modify lgreq to accept alpha_in, beta_in, alpha_out # msa to before_gwa msa2bgwa = msa2gwa & Identity(1) | Mapping((3, 0, 1, 2)) | agreq bgwa2msa.inverse = msa2bgwa slit_models.append(bgwa2msa) msa.close() return Gwa2Slit(open_slits, slit_models)
def __init__(self, init=None, schema=None, extensions=None, pass_invalid_values=False): """ Parameters ---------- init : shape tuple, file path, file object, astropy.io.fits.HDUList, numpy array, None - None: A default data model with no shape - shape tuple: Initialize with empty data of the given shape - file path: Initialize from the given file (FITS or ASDF) - readable file object: Initialize from the given file object - ``astropy.io.fits.HDUList``: Initialize from the given `~astropy.io.fits.HDUList`. - A numpy array: Used to initialize the data array - dict: The object model tree for the data model schema : tree of objects representing a JSON schema, or string naming a schema, optional The schema to use to understand the elements on the model. If not provided, the schema associated with this class will be used. extensions: classes extending the standard set of extensions, optional. If an extension is defined, the prefix used should be 'url'. pass_invalid_values: If true, values that do not validate the schema can be read and written and only a warning will be generated """ # Set the extensions if extensions is None: extensions = jwst_extensions[:] else: extensions.extend(jwst_extensions) self._extensions = extensions # Override value of pass_invalid value if environment value set if "PASS_INVALID_VALUES" in os.environ: pass_invalid_values = os.environ["PASS_INVALID_VALUES"] try: pass_invalid_values = bool(int(pass_invalid_values)) except ValueError: pass_invalid_values = False self._pass_invalid_values = pass_invalid_values # Construct the path to the schema files filename = os.path.abspath(inspect.getfile(self.__class__)) base_url = os.path.join(os.path.dirname(filename), 'schemas', '') # Load the schema files if schema is None: schema_path = os.path.join(base_url, self.schema_url) extension_list = asdf_extension.AsdfExtensionList(self._extensions) schema = asdf_schema.load_schema( schema_path, resolver=extension_list.url_mapping, resolve_references=True) self._schema = mschema.flatten_combiners(schema) # Determine what kind of input we have (init) and execute the # proper code to intiailize the model self._files_to_close = [] self._iscopy = False is_array = False is_shape = False shape = None if init is None: asdf = AsdfFile(extensions=extensions) elif isinstance(init, dict): asdf = AsdfFile(init, extensions=extensions) elif isinstance(init, np.ndarray): asdf = AsdfFile(extensions=extensions) shape = init.shape is_array = True elif isinstance(init, self.__class__): self.clone(self, init) return elif isinstance(init, DataModel): raise TypeError( "Passed in {0!r} is not of the expected subclass {1!r}".format( init.__class__.__name__, self.__class__.__name__)) elif isinstance(init, AsdfFile): asdf = init elif isinstance(init, tuple): for item in init: if not isinstance(item, int): raise ValueError("shape must be a tuple of ints") shape = init asdf = AsdfFile() is_shape = True elif isinstance(init, fits.HDUList): asdf = fits_support.from_fits(init, self._schema, extensions, pass_invalid_values) elif isinstance(init, (six.string_types, bytes)): if isinstance(init, bytes): init = init.decode(sys.getfilesystemencoding()) file_type = filetype.check(init) if file_type == "fits": hdulist = fits.open(init) asdf = fits_support.from_fits(hdulist, self._schema, extensions, pass_invalid_values) self._files_to_close.append(hdulist) elif file_type == "asdf": asdf = AsdfFile.open(init, extensions=extensions) else: # TODO handle json files as well raise IOError( "File does not appear to be a FITS or ASDF file.") else: raise ValueError("Can't initialize datamodel using {0}".format( str(type(init)))) # Initialize object fields as determined fro the code above self._shape = shape self._instance = asdf.tree self._asdf = asdf self._ctx = self # if the input is from a file, set the filename attribute if isinstance(init, six.string_types): self.meta.filename = os.path.basename(init) elif isinstance(init, fits.HDUList): info = init.fileinfo(0) if info is not None: filename = info.get('filename') if filename is not None: self.meta.filename = os.path.basename(filename) # if the input model doesn't have a date set, use the current date/time if self.meta.date is None: self.meta.date = Time(datetime.datetime.now()) if hasattr(self.meta.date, 'value'): self.meta.date.format = 'isot' self.meta.date = str(self.meta.date.value) # store the data model type, if not already set if hasattr(self.meta, 'model_type'): if self.meta.model_type is None: self.meta.model_type = self.__class__.__name__ else: self.meta.model_type = None if is_array: primary_array_name = self.get_primary_array_name() if primary_array_name is None: raise TypeError( "Array passed to DataModel.__init__, but model has " "no primary array in its schema") setattr(self, primary_array_name, init) # TODO this code looks useless if is_shape: getattr(self, self.get_primary_array_name())
def __init__(self, init=None, schema=None, extensions=None, pass_invalid_values=False, strict_validation=False): """ Parameters ---------- init : shape tuple, file path, file object, astropy.io.fits.HDUList, numpy array, None - None: A default data model with no shape - shape tuple: Initialize with empty data of the given shape - file path: Initialize from the given file (FITS or ASDF) - readable file object: Initialize from the given file object - ``astropy.io.fits.HDUList``: Initialize from the given `~astropy.io.fits.HDUList`. - A numpy array: Used to initialize the data array - dict: The object model tree for the data model schema : tree of objects representing a JSON schema, or string naming a schema, optional The schema to use to understand the elements on the model. If not provided, the schema associated with this class will be used. extensions: classes extending the standard set of extensions, optional. If an extension is defined, the prefix used should be 'url'. pass_invalid_values: If true, values that do not validate the schema will be added to the metadata. If false, they will be set to None strict_validation: if true, an schema validation errors will generate an excption. If false, they will generate a warning. """ # Set the extensions self._extensions = extensions # Override value of validation parameters # if environment value set self._pass_invalid_values = self.get_envar("PASS_INVALID_VALUES", pass_invalid_values) self._strict_validation = self.get_envar("STRICT_VALIDATION", strict_validation) # Construct the path to the schema files filename = os.path.abspath(inspect.getfile(self.__class__)) base_url = os.path.join(os.path.dirname(filename), 'schemas', '') # Load the schema files if schema is None: schema_path = os.path.join(base_url, self.schema_url) # Create an AsdfFile so we can use its resolver for loading schemas asdf_file = AsdfFile(extensions=self._extensions) if hasattr(asdf_file, 'resolver'): file_resolver = asdf_file.resolver else: file_resolver = self.get_resolver(asdf_file) schema = asdf_schema.load_schema(schema_path, resolver=file_resolver, resolve_references=True) self._schema = mschema.flatten_combiners(schema) # Provide the object as context to other classes and functions self._ctx = self # Determine what kind of input we have (init) and execute the # proper code to intiailize the model self._files_to_close = [] self._iscopy = False is_array = False is_shape = False shape = None if init is None: asdf = AsdfFile(extensions=extensions) elif isinstance(init, dict): asdf = AsdfFile(init, extensions=self._extensions) elif isinstance(init, np.ndarray): asdf = AsdfFile(extensions=self._extensions) shape = init.shape is_array = True elif isinstance(init, tuple): for item in init: if not isinstance(item, int): raise ValueError("shape must be a tuple of ints") shape = init asdf = AsdfFile() is_shape = True elif isinstance(init, DataModel): self.clone(self, init) if not isinstance(init, self.__class__): self.validate() return elif isinstance(init, AsdfFile): asdf = init elif isinstance(init, fits.HDUList): asdf = fits_support.from_fits(init, self._schema, self._extensions, self._ctx) elif isinstance(init, (str, bytes)): if isinstance(init, bytes): init = init.decode(sys.getfilesystemencoding()) file_type = filetype.check(init) if file_type == "fits": hdulist = fits.open(init) asdf = fits_support.from_fits(hdulist, self._schema, self._extensions, self._ctx) self._files_to_close.append(hdulist) elif file_type == "asdf": asdf = AsdfFile.open(init, extensions=self._extensions) else: # TODO handle json files as well raise IOError( "File does not appear to be a FITS or ASDF file.") else: raise ValueError("Can't initialize datamodel using {0}".format( str(type(init)))) # Initialize object fields as determined from the code above self._shape = shape self._instance = asdf.tree self._asdf = asdf # Initalize class dependent hidden fields self._no_asdf_extension = False # Instantiate the primary array of the image if is_array: primary_array_name = self.get_primary_array_name() if not primary_array_name: raise TypeError( "Array passed to DataModel.__init__, but model has " "no primary array in its schema") setattr(self, primary_array_name, init) if is_shape: if not self.get_primary_array_name(): raise TypeError( "Shape passed to DataModel.__init__, but model has " "no primary array in its schema") # if the input is from a file, set the filename attribute if isinstance(init, str): self.meta.filename = os.path.basename(init) elif isinstance(init, fits.HDUList): info = init.fileinfo(0) if info is not None: filename = info.get('filename') if filename is not None: self.meta.filename = os.path.basename(filename) # if the input model doesn't have a date set, use the current date/time if not self.meta.hasattr('date'): current_date = Time(datetime.datetime.now()) current_date.format = 'isot' self.meta.date = current_date.value # store the data model type, if not already set klass = self.__class__.__name__ if klass != 'DataModel': if not self.meta.hasattr('model_type'): self.meta.model_type = klass
def imaging_distortion(input_model, reference_files): distortion = AsdfFile.open(reference_files['distortion']).tree['model'] return distortion