def test_frames(tmpdir): frames = [ cf.CelestialFrame(reference_frame=coord.ICRS()), cf.CelestialFrame(reference_frame=coord.FK5( equinox=time.Time('2010-01-01'))), cf.CelestialFrame(reference_frame=coord.FK4( equinox=time.Time('2010-01-01'), obstime=time.Time('2015-01-01'))), cf.CelestialFrame(reference_frame=coord.FK4NoETerms( equinox=time.Time('2010-01-01'), obstime=time.Time('2015-01-01'))), cf.CelestialFrame(reference_frame=coord.Galactic()), cf.CelestialFrame( reference_frame=coord.Galactocentric(galcen_distance=5.0 * u.m, galcen_ra=45 * u.deg, galcen_dec=1 * u.rad, z_sun=3 * u.pc, roll=3 * u.deg)), cf.CelestialFrame( reference_frame=coord.GCRS(obstime=time.Time('2010-01-01'), obsgeoloc=[1, 3, 2000] * u.pc, obsgeovel=[2, 1, 8] * (u.m / u.s))), cf.CelestialFrame(reference_frame=coord.CIRS( obstime=time.Time('2010-01-01'))), cf.CelestialFrame(reference_frame=coord.ITRS( obstime=time.Time('2022-01-03'))), cf.CelestialFrame(reference_frame=coord.PrecessedGeocentric( obstime=time.Time('2010-01-01'), obsgeoloc=[1, 3, 2000] * u.pc, obsgeovel=[2, 1, 8] * (u.m / u.s))) ] tree = {'frames': frames} helpers.assert_roundtrip_tree(tree, tmpdir)
def ifu(input_model, reference_files): """ Create the WCS pipeline for a MIRI IFU observation. """ #reference_files = {'distortion': 'jwst_miri_distortion_00001.asdf', #files must hold 2 channels each #'specwcs': 'jwst_miri_specwcs_00001.asdf', #'regions': 'jwst_miri_regions_00001.asdf', #'v2v3': 'jwst_miri_v2v3_00001.asdf' #'wavelengthrange': 'jwst_miri_wavelengthrange_0001.asdf'} detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) alpha_beta = cf.Frame2D(name='alpha_beta_spatial', axes_order=(0, 1), unit=(u.arcsec, u.arcsec), axes_names=('alpha', 'beta')) spec_local = cf.SpectralFrame(name='alpha_beta_spectral', axes_order=(2,), unit=(u.micron,), axes_names=('lambda',)) miri_focal = cf.CompositeFrame([alpha_beta, spec_local], name='alpha_beta') xyan_spatial = cf.Frame2D(name='Xan_Yan_spatial', axes_order=(0, 1), unit=(u.arcmin, u.arcmin), axes_names=('v2', 'v3')) spec = cf.SpectralFrame(name='Xan_Yan_spectral', axes_order=(2,), unit=(u.micron,), axes_names=('lambda',)) xyan = cf.CompositeFrame([xyan_spatial, spec], name='Xan_Yan') v23_spatial = cf.Frame2D(name='V2_V3_spatial', axes_order=(0, 1), unit=(u.arcmin, u.arcmin), axes_names=('v2', 'v3')) spec = cf.SpectralFrame(name='V2_v3_spectral', axes_order=(2,), unit=(u.micron,), axes_names=('lambda',)) v2v3 = cf.CompositeFrame([v23_spatial, spec], name='V2_V3') icrs = cf.CelestialFrame(name='icrs', reference_frame=coord.ICRS(), axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('RA', 'DEC')) sky = cf.CompositeFrame([icrs, spec], name='sky_and_wavelength') det2alpha_beta = (detector_to_alpha_beta(input_model, reference_files)).rename( "detector_to_alpha_beta") ab2xyan = (alpha_beta2XanYan(input_model, reference_files)).rename("alpha_beta_to_Xan_Yan") xyan2v23 = models.Identity(1) & (models.Shift(7.8) | models.Scale(-1)) & models.Identity(1) fitswcs_transform = pointing.create_fitswcs_transform(input_model) & models.Identity(1) pipeline = [(detector, det2alpha_beta), (miri_focal, ab2xyan), (xyan, xyan2v23), (v2v3, fitswcs_transform), (sky, None) ] return pipeline
def imaging(input_model, reference_files): """ Create MIRI Imagng WCS. Parameters ---------- input_model : `jwst.datamodels.ImagingModel` Data model. reference_files : dict Dictionary {reftype: reference file name}. The MIRI imaging pipeline includes 3 coordinate frames - detector, focal plane and sky reference_files={'distortion': 'test.asdf', 'filter_offsets': 'filter_offsets.asdf'} """ # Create the Frames detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), unit=(u.deg, u.deg)) world = cf.CelestialFrame(reference_frame=coord.ICRS(), name='world') # Create the transforms distortion = imaging_distortion(input_model, reference_files) tel2sky = pointing.v23tosky(input_model) # Create the pipeline pipeline = [(detector, distortion), (v2v3, tel2sky), (world, None)] return pipeline
def imaging(input_model, reference_files): """ The MIRI Imaging WCS pipeline. It includes three coordinate frames - "detector", "v2v3" and "world". Parameters ---------- input_model : `jwst.datamodels.ImagingModel` Data model. reference_files : dict Dictionary {reftype: reference file name}. Uses "distortion" and "filteroffset" reference files. """ # Create the Frames detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.arcsec, u.arcsec)) v2v3vacorr = cf.Frame2D(name='v2v3vacorr', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.arcsec, u.arcsec)) world = cf.CelestialFrame(reference_frame=coord.ICRS(), name='world') # Create the transforms distortion = imaging_distortion(input_model, reference_files) subarray2full = subarray_transform(input_model) if subarray2full is not None: distortion = subarray2full | distortion distortion.bounding_box = bounding_box_from_subarray(input_model) else: # TODO: remove setting the bounding box if it is set in the new ref file. try: bb = distortion.bounding_box except NotImplementedError: shape = input_model.data.shape # Note: Since bounding_box is attached to the model here it's in reverse order. bb = ((-0.5, shape[0] - 0.5), (3.5, shape[1] - 4.5)) distortion.bounding_box = bb # Compute differential velocity aberration (DVA) correction: va_corr = pointing.dva_corr_model( va_scale=input_model.meta.velocity_aberration.scale_factor, v2_ref=input_model.meta.wcsinfo.v2_ref, v3_ref=input_model.meta.wcsinfo.v3_ref) tel2sky = pointing.v23tosky(input_model) # Create the pipeline pipeline = [(detector, distortion), (v2v3, va_corr), (v2v3vacorr, tel2sky), (world, None)] return pipeline
def imaging(input_model, reference_files): """ The FGS imaging WCS pipeline. It includes 3 coordinate frames - "detector", "v2v3" and "world". Uses a ``distortion`` reference file. """ detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), unit=(u.arcsec, u.arcsec)) world = cf.CelestialFrame(name='world', reference_frame=coord.ICRS()) # Crete the v2v3 to sky transform. tel2sky = pointing.v23tosky(input_model) # If subarray, ceate an offset transform to be prepended to the distortion. subarray2full = subarray_transform(input_model) if reference_files: imdistortion = imaging_distortion(input_model, reference_files) distortion = subarray2full | imdistortion # If the bounding box is saved in the model, move it to the first transform. distortion.bounding_box = imdistortion.bounding_box del imdistortion.bounding_box else: distortion = subarray2full pipeline = [(detector, distortion), (v2v3, tel2sky), (world, None)] return pipeline
def fitswcs_to_gwcs(hdr): """ Create and return a gWCS object from a FITS header. If it can't construct one, it should quietly return None. """ # Type of CoordinateFrame to construct for a FITS keyword frame_mapping = {'WAVE': cf.SpectralFrame} # coordinate names for CelestialFrame coordinate_outputs = {'alpha_C', 'delta_C'} # transform = gw.make_fitswcs_transform(hdr) try: transform = make_fitswcs_transform(hdr) except Exception as e: return None outputs = transform.outputs naxes = transform.n_inputs axes_names = ('x', 'y', 'z', 'u', 'v', 'w')[:naxes] in_frame = cf.CoordinateFrame(naxes=naxes, axes_type=['SPATIAL'] * naxes, axes_order=tuple(range(naxes)), name="pixels", axes_names=axes_names, unit=[u.pix] * naxes) out_frames = [] for i, output in enumerate(outputs): unit_name = hdr.get(f'CUNIT{i+1}') try: unit = u.Unit(unit_name) except TypeError: unit = None try: frame = frame_mapping[output[:4].upper()](axes_order=(i,), unit=unit, axes_names=(output,), name=output) except KeyError: if output in coordinate_outputs: continue frame = cf.CoordinateFrame(naxes=1, axes_type=("SPATIAL",), axes_order=(i,), unit=unit, axes_names=(output,), name=output) out_frames.append(frame) if coordinate_outputs.issubset(outputs): frame_name = hdr.get('RADESYS') or hdr.get('RADECSYS') # FK5, etc. try: ref_frame = getattr(coord, frame_name)() # TODO? Work out how to stuff EQUINOX and OBS-TIME into the frame except (AttributeError, TypeError): ref_frame = None axes_order = (outputs.index('alpha_C'), outputs.index('delta_C')) # Call it 'world' if there are no other axes, otherwise 'sky' name = 'SKY' if len(outputs) > 2 else 'world' cel_frame = cf.CelestialFrame(reference_frame=ref_frame, name=name, axes_order=axes_order) out_frames.append(cel_frame) out_frame = (out_frames[0] if len(out_frames) == 1 else cf.CompositeFrame(out_frames, name='world')) return gWCS([(in_frame, transform), (out_frame, None)])
def ifu(input_model, reference_files): """ Create the WCS pipeline for a MIRI IFU observation. Goes from 0-indexed detector pixels (0,0) middle of lower left reference pixel to V2,V3 in arcsec. Parameters ---------- input_model : `jwst.datamodels.ImagingModel` Data model. reference_files : dict Dictionary {reftype: reference file name}. """ #reference_files = {'distortion': 'jwst_miri_distortion_00001.asdf', #files must hold 2 channels each #'specwcs': 'jwst_miri_specwcs_00001.asdf', #'regions': 'jwst_miri_regions_00001.asdf', #'wavelengthrange': 'jwst_miri_wavelengthrange_0001.asdf'} # Define reference frames detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) alpha_beta = cf.Frame2D(name='alpha_beta_spatial', axes_order=(0, 1), unit=(u.arcsec, u.arcsec), axes_names=('alpha', 'beta')) spec_local = cf.SpectralFrame(name='alpha_beta_spectral', axes_order=(2, ), unit=(u.micron, ), axes_names=('lambda', )) miri_focal = cf.CompositeFrame([alpha_beta, spec_local], name='alpha_beta') v23_spatial = cf.Frame2D(name='V2_V3_spatial', axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('v2', 'v3')) spec = cf.SpectralFrame(name='spectral', axes_order=(2, ), unit=(u.micron, ), axes_names=('lambda', )) v2v3 = cf.CompositeFrame([v23_spatial, spec], name='v2v3') icrs = cf.CelestialFrame(name='icrs', reference_frame=coord.ICRS(), axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('RA', 'DEC')) world = cf.CompositeFrame([icrs, spec], name='world') # Define the actual transforms det2abl = (detector_to_abl(input_model, reference_files)).rename("detector_to_abl") abl2v2v3l = (abl_to_v2v3l(input_model, reference_files)).rename("abl_to_v2v3l") tel2sky = pointing.v23tosky(input_model) & models.Identity(1) # Put the transforms together into a single transform shape = input_model.data.shape det2abl.bounding_box = ((-0.5, shape[0] - 0.5), (-0.5, shape[1] - 0.5)) pipeline = [(detector, det2abl), (miri_focal, abl2v2v3l), (v2v3, tel2sky), (world, None)] return pipeline
def test_simple_gwcs(): # https://gwcs.readthedocs.io/en/latest/#getting-started shift_by_crpix = models.Shift(-(2048 - 1) * u.pix) & models.Shift(-(1024 - 1) * u.pix) matrix = np.array([[1.290551569736E-05, 5.9525007864732E-06], [5.0226382102765E-06, -1.2644844123757E-05]]) rotation = models.AffineTransformation2D(matrix * u.deg, translation=[0, 0] * u.deg) rotation.input_units_equivalencies = {"x": u.pixel_scale(1 * (u.deg / u.pix)), "y": u.pixel_scale(1 * (u.deg / u.pix))} rotation.inverse = models.AffineTransformation2D(np.linalg.inv(matrix) * u.pix, translation=[0, 0] * u.pix) rotation.inverse.input_units_equivalencies = {"x": u.pixel_scale(1 * (u.pix / u.deg)), "y": u.pixel_scale(1 * (u.pix / u.deg))} tan = models.Pix2Sky_TAN() celestial_rotation = models.RotateNative2Celestial( 5.63056810618 * u.deg, -72.05457184279 * u.deg, 180 * u.deg) det2sky = shift_by_crpix | rotation | tan | celestial_rotation det2sky.name = "linear_transform" detector_frame = cf.Frame2D(name="detector", axes_names=("x", "y"), unit=(u.pix, u.pix)) sky_frame = cf.CelestialFrame(reference_frame=ICRS(), name='icrs', unit=(u.deg, u.deg)) pipeline = [(detector_frame, det2sky), (sky_frame, None)] w = gwcs.wcs.WCS(pipeline) result = wcs_utils.get_compass_info(w, (1024, 2048), r_fac=0.25) assert_allclose(result[:-1], (1024.0, 512.0, 1131.0265005852038, 279.446189124443, 1262.0057201165127, 606.2863901330095, 155.2870478938214, -86.89813081941797)) assert not result[-1]
def _from_skycoord(self, lookup_tables, mesh=False, names=None, physical_types=None, **kwargs): if len(lookup_tables) > 1: raise ValueError("Can only parse one SkyCoord lookup table.") def _generate_skycoord_lookup(components): return self._model_from_quantity(components, mesh=mesh) sc = lookup_tables[0] components = tuple( getattr(sc.data, comp) for comp in sc.data.components) ref_frame = sc.frame.replicate_without_data() units = list(c.unit for c in components) if names and len(names) != 2: names = None # TODO: Currently this limits you to 2D due to gwcs#120 frame = cf.CelestialFrame(reference_frame=ref_frame, unit=units, axes_names=names, axis_physical_types=physical_types, name="CelestialFrame") return DelayedLookupTable(components, _generate_skycoord_lookup, mesh), frame
def niriss_soss_set_input(model, order_number): """ Get the right model given the order number. Parameters ---------- model - Input model order_number - the, well, order number desired Returns ------- WCS - the WCS corresponding to the order_number """ # Make sure the order number is correct. if order_number < 1 or order_number > 3: raise ValueError('Order must be between 1 and 3') # Return the correct transform based on the order_number obj = model.meta.wcs.forward_transform.get_model(order_number) # use the size of the input subarray7 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') pipeline = [(detector, obj), (world, None) ] return wcs.WCS(pipeline)
def make_spatial(self): """ Add a helioprojective spatial pair to the builder. .. note:: This increments the counter by two. """ i = self._i name = self.header[f'DWNAME{self.n}'] name = name.split(' ')[0] axes_names = [(self.header[f'DWNAME{nn}'].rsplit(' ')[1]) for nn in (self.n, self._n(i + 1))] obstime = Time(self.header['DATE-BGN']) self._frames.append( cf.CelestialFrame(axes_order=(i, i + 1), name=name, reference_frame=Helioprojective(obstime=obstime), axes_names=axes_names, unit=self.get_units(self._i, self._i + 1))) self._transforms.append(spatial_model_from_header(self.header)) self._i += 2
def generate_s3d_wcs(): """ create a fake gwcs for a cube """ # create input /output frames detector = cf.CoordinateFrame(name='detector', axes_order=(0,1,2), axes_names=['x', 'y', 'z'], axes_type=['spatial', 'spatial', 'spatial'], naxes=3, unit=['pix', 'pix', 'pix']) sky = cf.CelestialFrame(reference_frame=coord.ICRS(), name='sky', axes_names=("RA", "DEC")) spec = cf.SpectralFrame(name='spectral', unit=['um'], axes_names=['wavelength'], axes_order=(2,)) world = cf.CompositeFrame(name="world", frames=[sky, spec]) # create fake transform to at least get a bounding box # for the s3d jwst loader # shape 30,10,10 (spec, y, x) crpix1, crpix2, crpix3 = 5, 5, 15 # (x, y, spec) crval1, crval2, crval3 = 1, 1, 1 cdelt1, cdelt2, cdelt3 = 0.01, 0.01, 0.05 shift = models.Shift(-crpix2) & models.Shift(-crpix1) scale = models.Multiply(cdelt2) & models.Multiply(cdelt1) proj = models.Pix2Sky_TAN() skyrot = models.RotateNative2Celestial(crval2, 90 + crval1, 180) celestial = shift | scale | proj | skyrot wave_model = models.Shift(-crpix3) | models.Multiply(cdelt3) | models.Shift(crval3) transform = models.Mapping((2, 0, 1)) | celestial & wave_model | models.Mapping((1, 2, 0)) # bounding box based on shape (30,10,10) in test transform.bounding_box = ((0, 29), (0, 9), (0, 9)) # create final wcs pipeline = [(detector, transform), (world, None)] return WCS(pipeline)
def create_imaging_frames(): """ Create the coordinate frames in the NIRSPEC WCS pipeline. These are "detector", "gwa", "msa_frame", "oteip", "v2v3", "world". """ det = cf.Frame2D(name='detector', axes_order=(0, 1)) sca = cf.Frame2D(name='sca', axes_order=(0, 1)) gwa = cf.Frame2D(name="gwa", axes_order=(0, 1), unit=(u.rad, u.rad), axes_names=('alpha_in', 'beta_in')) msa = cf.Frame2D(name='msa', axes_order=(0, 1), unit=(u.m, u.m), axes_names=('x_msa', 'y_msa')) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('v2', 'v3')) oteip = cf.Frame2D(name='oteip', axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('x_oteip', 'y_oteip')) world = cf.CelestialFrame(name='world', axes_order=(0, 1), reference_frame=coord.ICRS()) return det, sca, gwa, msa, oteip, v2v3, world
def create_frames(): """ Create the coordinate frames in the NIRSPEC WCS pipeline. These are "detector", "gwa", "slit_frame", "msa_frame", "oteip", "v2v3", "world". """ det = cf.Frame2D(name='detector', axes_order=(0, 1)) sca = cf.Frame2D(name='sca', axes_order=(0, 1)) gwa = cf.Frame2D(name="gwa", axes_order=(0, 1), unit=(u.rad, u.rad), axes_names=('alpha_in', 'beta_in')) msa_spatial = cf.Frame2D(name='msa_spatial', axes_order=(0, 1), unit=(u.m, u.m), axes_names=('x_msa', 'y_msa')) slit_spatial = cf.Frame2D(name='slit_spatial', axes_order=(0, 1), unit=("", ""), axes_names=('x_slit', 'y_slit')) sky = cf.CelestialFrame(name='sky', axes_order=(0, 1), reference_frame=coord.ICRS()) v2v3_spatial = cf.Frame2D(name='v2v3_spatial', axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('V2', 'V3')) # The oteip_to_v23 incorporates a scale to convert the spectral units from # meters to microns. So the v2v3 output frame will be in u.deg, u.deg, u.micron spec = cf.SpectralFrame(name='spectral', axes_order=(2,), unit=(u.micron,), axes_names=('wavelength',)) v2v3 = cf.CompositeFrame([v2v3_spatial, spec], name='v2v3') slit_frame = cf.CompositeFrame([slit_spatial, spec], name='slit_frame') msa_frame = cf.CompositeFrame([msa_spatial, spec], name='msa_frame') oteip_spatial = cf.Frame2D(name='oteip', axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('X_OTEIP', 'Y_OTEIP')) oteip = cf.CompositeFrame([oteip_spatial, spec], name='oteip') world = cf.CompositeFrame([sky, spec], name='world') return det, sca, gwa, slit_frame, msa_frame, oteip, v2v3, world
def identity_gwcs_3d(): """ A simple 1-1 gwcs that converts from pixels to arcseconds """ identity = (TwoDScale(1 * u.arcsec / u.pixel) & m.Multiply(1 * u.nm / u.pixel)) sky_frame = cf.CelestialFrame( axes_order=(0, 1), name='helioprojective', reference_frame=Helioprojective(obstime="2018-01-01"), axes_names=("longitude", "latitude"), unit=(u.arcsec, u.arcsec), axis_physical_types=("custom:pos.helioprojective.lon", "custom:pos.helioprojective.lat")) wave_frame = cf.SpectralFrame(axes_order=(2, ), unit=u.nm, axes_names=("wavelength", )) frame = cf.CompositeFrame([sky_frame, wave_frame]) detector_frame = cf.CoordinateFrame(name="detector", naxes=3, axes_order=(0, 1, 2), axes_type=("pixel", "pixel", "pixel"), axes_names=("x", "y", "z"), unit=(u.pix, u.pix, u.pix)) wcs = gwcs.wcs.WCS(forward_transform=identity, output_frame=frame, input_frame=detector_frame) wcs.pixel_shape = (10, 20, 30) wcs.array_shape = wcs.pixel_shape[::-1] return wcs
def identity_gwcs(): """ A simple 1-1 gwcs that converts from pixels to arcseconds Note this WCS does not have a correct axis correlation matrix. """ identity = m.Multiply(1 * u.arcsec / u.pixel) & m.Multiply( 1 * u.arcsec / u.pixel) sky_frame = cf.CelestialFrame( axes_order=(0, 1), name='helioprojective', reference_frame=Helioprojective(obstime="2018-01-01"), unit=(u.arcsec, u.arcsec), axis_physical_types=("custom:pos.helioprojective.lat", "custom:pos.helioprojective.lon")) detector_frame = cf.CoordinateFrame(name="detector", naxes=2, axes_order=(0, 1), axes_type=("pixel", "pixel"), axes_names=("x", "y"), unit=(u.pix, u.pix)) wcs = gwcs.wcs.WCS(forward_transform=identity, output_frame=sky_frame, input_frame=detector_frame) wcs.pixel_shape = (10, 20) wcs.array_shape = wcs.pixel_shape[::-1] return wcs
def create_coord_frames(): gdetector = cf.Frame2D(name='grism_detector', axes_order=(0, 1), unit=(u.pix, u.pix)) detector = cf.Frame2D(name='full_detector', axes_order=(0, 1), axes_names=('dx', 'dy'), unit=(u.pix, u.pix)) v2v3_spatial = cf.Frame2D(name='v2v3_spatial', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.deg, u.deg)) v2v3vacorr_spatial = cf.Frame2D(name='v2v3vacorr_spatial', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.arcsec, u.arcsec)) sky_frame = cf.CelestialFrame(reference_frame=coord.ICRS(), name='icrs') spec = cf.SpectralFrame(name='spectral', axes_order=(2, ), unit=(u.micron, ), axes_names=('wavelength', )) frames = { 'grism_detector': gdetector, 'direct_image': cf.CompositeFrame([detector, spec], name='direct_image'), 'v2v3': cf.CompositeFrame([v2v3_spatial, spec], name='v2v3'), 'v2v3vacorr': cf.CompositeFrame([v2v3vacorr_spatial, spec], name='v2v3vacorr'), 'world': cf.CompositeFrame([sky_frame, spec], name='world') } return frames
def _generate_wcs_transform(dispaxis): """Create mock gwcs.WCS object for resampled s2d data""" detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) icrs = cf.CelestialFrame(name='icrs', reference_frame=coord.ICRS(), axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('RA', 'DEC')) spec = cf.SpectralFrame(name='spec', axes_order=(2, ), unit=(u.micron, ), axes_names=('lambda', )) world = cf.CompositeFrame(name="world", frames=[icrs, spec]) if dispaxis == 1: mapping = models.Mapping((0, 1, 0)) if dispaxis == 2: mapping = models.Mapping((0, 1, 1)) transform = mapping | (models.Const1D(42) & models.Const1D(42) & (models.Shift(30) | models.Scale(0.1))) pipeline = [(detector, transform), (world, None)] wcs = WCS(pipeline) return wcs
def identity_gwcs_4d(): """ A simple 1-1 gwcs that converts from pixels to arcseconds """ identity = (m.Multiply(1 * u.arcsec / u.pixel) & m.Multiply(1 * u.arcsec / u.pixel) & m.Multiply(1 * u.nm / u.pixel) & m.Multiply(1 * u.nm / u.pixel)) sky_frame = cf.CelestialFrame( axes_order=(0, 1), name='helioprojective', reference_frame=Helioprojective(obstime="2018-01-01")) wave_frame = cf.SpectralFrame(axes_order=(2, ), unit=u.nm) time_frame = cf.TemporalFrame(axes_order=(3, ), unit=u.s) frame = cf.CompositeFrame([sky_frame, wave_frame, time_frame]) detector_frame = cf.CoordinateFrame(name="detector", naxes=4, axes_order=(0, 1, 2, 3), axes_type=("pixel", "pixel", "pixel", "pixel"), axes_names=("x", "y", "z", "s"), unit=(u.pix, u.pix, u.pix, u.pix)) return gwcs.wcs.WCS(forward_transform=identity, output_frame=frame, input_frame=detector_frame)
def imaging(input_model, reference_files): """ The FGS imaging pipeline includes 3 coordinate frames - detector, focal plane and sky. reference_files={'distortion': 'jwst_fgs_distortioon_0001.asdf'} """ detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), unit=(u.deg, u.deg)) world = cf.CelestialFrame(name='world', reference_frame=coord.ICRS()) # V2, V3 to sky tel2sky = pointing.v23tosky(input_model) subarray2full = subarray_transform(input_model) if reference_files: imdistortion = imaging_distortion(input_model, reference_files) distortion = subarray2full | imdistortion distortion.bounding_box = imdistortion.bounding_box del imdistortion.bounding_box else: distortion = subarray2full pipeline = [(detector, distortion), (v2v3, tel2sky), (world, None)] return pipeline
def imaging(input_model, reference_files): """ The NIRISS imaging WCS pipeline. It includes three coordinate frames - "detector" "v2v3" and "world". It uses the "distortion" reference file. """ detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), unit=(u.arcsec, u.arcsec)) world = cf.CelestialFrame(reference_frame=coord.ICRS(), name='world') subarray2full = subarray_transform(input_model) imdistortion = imaging_distortion(input_model, reference_files) distortion = subarray2full | imdistortion distortion.bounding_box = imdistortion.bounding_box del imdistortion.bounding_box tel2sky = pointing.v23tosky(input_model) pipeline = [(detector, distortion), (v2v3, tel2sky), (world, None)] return pipeline
def test1(tmpdir, ret=False): shift_by_crpix = models.Shift(-2048 * u.pix) & models.Shift(-1024 * u.pix) matrix = np.array([[1.290551569736E-05, 5.9525007864732E-06], [5.0226382102765E-06, -1.2644844123757E-05]]) rotation = models.AffineTransformation2D(matrix * u.deg, translation=[0, 0] * u.deg) rotation.input_units_equivalencies = { "x": u.pixel_scale(1 * u.deg / u.pix), "y": u.pixel_scale(1 * u.deg / u.pix) } rotation.inverse = models.AffineTransformation2D( np.linalg.inv(matrix) * u.pix, translation=[0, 0] * u.pix) rotation.inverse.input_units_equivalencies = { "x": u.pixel_scale(1 * u.pix / u.deg), "y": u.pixel_scale(1 * u.pix / u.deg) } tan = models.Pix2Sky_TAN() celestial_rotation = models.RotateNative2Celestial(5.63056810618 * u.deg, -72.05457184279 * u.deg, 180 * u.deg) det2sky = shift_by_crpix | rotation | tan | celestial_rotation det2sky.name = "linear_transform" detector_frame = cf.Frame2D(name="detector", axes_names=("x", "y"), unit=(u.pix, u.pix)) sky_frame = cf.CelestialFrame(reference_frame=coords.ICRS(), name='icrs', unit=(u.deg, u.deg)) pipeline = [(detector_frame, det2sky), (sky_frame, None)] wcsobj = gwcs.wcs.WCS(pipeline) wcs_set = WcsSet(default=wcsobj, extra=wcsobj) tree = {'wcs_set': wcs_set} if ret: return wcs_set helpers.assert_roundtrip_tree(tree, tmpdir)
def _make_reference_gwcs_wcs(fits_hdr): hdr = fits.Header.fromfile(get_pkg_data_filename(fits_hdr)) fw = fitswcs.WCS(hdr) unit_conv = Scale(1.0 / 3600.0, name='arcsec_to_deg_1D') unit_conv = unit_conv & unit_conv unit_conv.name = 'arcsec_to_deg_2D' unit_conv_inv = Scale(3600.0, name='deg_to_arcsec_1D') unit_conv_inv = unit_conv_inv & unit_conv_inv unit_conv_inv.name = 'deg_to_arcsec_2D' c2s = CartesianToSpherical(name='c2s', wrap_lon_at=180) s2c = SphericalToCartesian(name='s2c', wrap_lon_at=180) c2tan = ((Mapping((0, 1, 2), name='xyz') / Mapping( (0, 0, 0), n_inputs=3, name='xxx')) | Mapping((1, 2), name='xtyt')) c2tan.name = 'Cartesian 3D to TAN' tan2c = (Mapping((0, 0, 1), n_inputs=2, name='xtyt2xyz') | (Const1D(1, name='one') & Identity(2, name='I(2D)'))) tan2c.name = 'TAN to cartesian 3D' tan2c.inverse = c2tan c2tan.inverse = tan2c aff = AffineTransformation2D(matrix=fw.wcs.cd) offx = Shift(-fw.wcs.crpix[0]) offy = Shift(-fw.wcs.crpix[1]) s = 5e-6 scale = Scale(s) & Scale(s) det2tan = (offx & offy) | scale | tan2c | c2s | unit_conv_inv taninv = s2c | c2tan tan = Pix2Sky_TAN() n2c = RotateNative2Celestial(fw.wcs.crval[0], fw.wcs.crval[1], 180) wcslin = unit_conv | taninv | scale.inverse | aff | tan | n2c sky_frm = cf.CelestialFrame(reference_frame=coord.ICRS()) det_frm = cf.Frame2D(name='detector') v2v3_frm = cf.Frame2D(name="v2v3", unit=(u.arcsec, u.arcsec), axes_names=('x', 'y'), axes_order=(0, 1)) pipeline = [(det_frm, det2tan), (v2v3_frm, wcslin), (sky_frm, None)] gw = gwcs.WCS(input_frame=det_frm, output_frame=sky_frm, forward_transform=pipeline) gw.crpix = fw.wcs.crpix gw.crval = fw.wcs.crval gw.bounding_box = ((-0.5, fw.pixel_shape[0] - 0.5), (-0.5, fw.pixel_shape[1] - 0.5)) return gw
def lrs(input_model, reference_files): """ The LRS-FIXEDSLIT and LRS-SLITLESS WCS pipeline. Notes ----- It includes three coordinate frames - "detector", "v2v3" and "world". "v2v3" and "world" each have (spatial, spatial, spectral) components. Uses the "specwcs" and "distortion" reference files. """ # Define the various coordinate frames. # Original detector frame detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) # Spectral component spec = cf.SpectralFrame(name='spec', axes_order=(2,), unit=(u.micron,), axes_names=('lambda',)) # v2v3 spatial component v2v3_spatial = cf.Frame2D(name='v2v3_spatial', axes_order=(0, 1), unit=(u.arcsec, u.arcsec), axes_names=('v2', 'v3')) v2v3vacorr_spatial = cf.Frame2D( name='v2v3vacorr_spatial', axes_order=(0, 1), unit=(u.arcsec, u.arcsec), axes_names=('v2', 'v3') ) # v2v3 spatial+spectra v2v3 = cf.CompositeFrame([v2v3_spatial, spec], name='v2v3') v2v3vacorr = cf.CompositeFrame([v2v3vacorr_spatial, spec], name='v2v3vacorr') # 'icrs' frame which is the spatial sky component icrs = cf.CelestialFrame(name='icrs', reference_frame=coord.ICRS(), axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('RA', 'DEC')) # Final 'world' composite frame with spatial and spectral components world = cf.CompositeFrame(name="world", frames=[icrs, spec]) # Create the transforms dettotel = lrs_distortion(input_model, reference_files) v2v3tosky = pointing.v23tosky(input_model) teltosky = v2v3tosky & models.Identity(1) # Compute differential velocity aberration (DVA) correction: va_corr = pointing.dva_corr_model( va_scale=input_model.meta.velocity_aberration.scale_factor, v2_ref=input_model.meta.wcsinfo.v2_ref, v3_ref=input_model.meta.wcsinfo.v3_ref ) & models.Identity(1) # Put the transforms together into a single pipeline pipeline = [(detector, dettotel), (v2v3, va_corr), (v2v3vacorr, teltosky), (world, None)] return pipeline
def imaging(input_model, reference_files): """ The FGS imaging WCS pipeline. It includes 3 coordinate frames - "detector", "v2v3" and "world". Uses a ``distortion`` reference file. Parameters ---------- input_model : `~jwst.datamodels.DataModel` The data model. reference_files : dict {reftype: file_name} mapping. Reference files. Returns ------- pipeline : list The WCS pipeline. """ # Create coordinate frames for the ``imaging`` mode. detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.arcsec, u.arcsec)) v2v3vacorr = cf.Frame2D(name='v2v3vacorr', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.arcsec, u.arcsec)) world = cf.CelestialFrame(name='world', reference_frame=coord.ICRS()) # Create the v2v3 to sky transform. tel2sky = pointing.v23tosky(input_model) # Read the distortion from the reference file distortion = imaging_distortion(input_model, reference_files) # If subarray, create an offset transform to be prepended to the distortion. subarray2full = subarray_transform(input_model) if subarray2full is not None: # Assign a bounding_box based on subarray's xsize and ysize distortion = subarray2full | distortion distortion.bounding_box = bounding_box_from_subarray(input_model) # Compute differential velocity aberration (DVA) correction: va_corr = pointing.dva_corr_model( va_scale=input_model.meta.velocity_aberration.scale_factor, v2_ref=input_model.meta.wcsinfo.v2_ref, v3_ref=input_model.meta.wcsinfo.v3_ref) pipeline = [(detector, distortion), (v2v3, va_corr), (v2v3vacorr, tel2sky), (world, None)] return pipeline
def load_wcs(input_model, reference_files=None): """ Create a gWCS object and store it in ``Model.meta``. Parameters ---------- input_model : `~roman_datamodels.datamodels.WfiImage` The exposure. reference_files : dict A dict {reftype: reference_file_name} containing all reference files that apply to this exposure. Returns ------- output_model : `~roman_datamodels.ImageModel` The input image file with attached gWCS object. The data is not modified. """ output_model = input_model.copy() if reference_files is not None: for ref_type, ref_file in reference_files.items(): if ref_file not in ["N/A", ""]: reference_files[ref_type] = ref_file else: reference_files[ref_type] = None else: reference_files = {} # Frames detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.arcsec, u.arcsec)) world = cf.CelestialFrame(reference_frame=coord.ICRS(), name='world') # Transforms between frames distortion = wfi_distortion(output_model, reference_files) tel2sky = pointing.v23tosky(output_model) pipeline = [ Step(detector, distortion), Step(v2v3, tel2sky), Step(world, None) ] wcs = WCS(pipeline) if wcs.bounding_box is None: wcs.bounding_box = wcs_bbox_from_shape(output_model.data.shape) output_model.meta['wcs'] = wcs output_model.meta.cal_step['assign_wcs'] = 'COMPLETE' return output_model
def imaging(input_model, reference_files): """ The NIRISS imaging WCS pipeline. Parameters ---------- input_model : `~jwst.datamodel.DataModel` Input datamodel for processing reference_files : dict The dictionary of reference file names and their associated files {reftype: reference file name}. Returns ------- pipeline : list The pipeline list that is returned is suitable for input into gwcs.wcs.WCS to create a GWCS object. Notes ----- It includes three coordinate frames - "detector" "v2v3" and "world". It uses the "distortion" reference file. """ detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.arcsec, u.arcsec)) v2v3vacorr = cf.Frame2D(name='v2v3vacorr', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.arcsec, u.arcsec)) world = cf.CelestialFrame(reference_frame=coord.ICRS(), name='world') distortion = imaging_distortion(input_model, reference_files) # Compute differential velocity aberration (DVA) correction: va_corr = pointing.dva_corr_model( va_scale=input_model.meta.velocity_aberration.scale_factor, v2_ref=input_model.meta.wcsinfo.v2_ref, v3_ref=input_model.meta.wcsinfo.v3_ref) subarray2full = subarray_transform(input_model) if subarray2full is not None: distortion = subarray2full | distortion distortion.bounding_box = bounding_box_from_subarray(input_model) tel2sky = pointing.v23tosky(input_model) pipeline = [(detector, distortion), (v2v3, va_corr), (v2v3vacorr, tel2sky), (world, None)] return pipeline
def test_composite_frame(tmpdir): icrs = coord.ICRS() fk5 = coord.FK5() cel1 = cf.CelestialFrame(reference_frame=icrs) cel2 = cf.CelestialFrame(reference_frame=fk5) spec1 = cf.SpectralFrame(name='freq', unit=[ u.Hz, ], axes_order=(2, )) spec2 = cf.SpectralFrame(name='wave', unit=[ u.m, ], axes_order=(2, )) comp1 = cf.CompositeFrame([cel1, spec1]) comp2 = cf.CompositeFrame([cel2, spec2]) comp = cf.CompositeFrame( [comp1, cf.SpectralFrame(axes_order=(3, ), unit=(u.m, ))]) tree = {'comp1': comp1, 'comp2': comp2, 'comp': comp} helpers.assert_roundtrip_tree(tree, tmpdir)
def ifu(input_model, reference_files): """ The MIRI MRS WCS pipeline. It has the following coordinate frames: "detector", "alpha_beta", "v2v3", "world". It uses the "distortion", "regions", "specwcs" and "wavelengthrange" reference files. """ # Define coordinate frames. detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) alpha_beta = cf.Frame2D(name='alpha_beta_spatial', axes_order=(0, 1), unit=(u.arcsec, u.arcsec), axes_names=('alpha', 'beta')) spec_local = cf.SpectralFrame(name='alpha_beta_spectral', axes_order=(2, ), unit=(u.micron, ), axes_names=('lambda', )) miri_focal = cf.CompositeFrame([alpha_beta, spec_local], name='alpha_beta') v23_spatial = cf.Frame2D(name='V2_V3_spatial', axes_order=(0, 1), unit=(u.arcsec, u.arcsec), axes_names=('v2', 'v3')) spec = cf.SpectralFrame(name='spectral', axes_order=(2, ), unit=(u.micron, ), axes_names=('lambda', )) v2v3 = cf.CompositeFrame([v23_spatial, spec], name='v2v3') icrs = cf.CelestialFrame(name='icrs', reference_frame=coord.ICRS(), axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('RA', 'DEC')) world = cf.CompositeFrame([icrs, spec], name='world') # Define the actual transforms det2abl = (detector_to_abl(input_model, reference_files)).rename("detector_to_abl") abl2v2v3l = (abl_to_v2v3l(input_model, reference_files)).rename("abl_to_v2v3l") tel2sky = pointing.v23tosky(input_model) & models.Identity(1) # Put the transforms together into a single transform shape = input_model.data.shape det2abl.bounding_box = ((-0.5, shape[0] - 0.5), (-0.5, shape[1] - 0.5)) pipeline = [(detector, det2abl), (miri_focal, abl2v2v3l), (v2v3, tel2sky), (world, None)] return pipeline
def load_wcs(input_model, reference_files={}): """ Create a gWCS object and store it in ``Model.meta``. Parameters ---------- input_model : `~jwst.datamodels.DataModel` The exposure. reference_files : dict A dict {reftype: reference_file_name} containing all reference files that apply to this exposure. """ if "wcsinfo" not in input_model.meta: input_model.meta.cal_step.assign_wcs = "SKIPPED" log.warning("assign_wcs: SKIPPED") return input_model else: output_model = input_model.copy() shift_by_crpix = models.Shift( -(input_model.meta.wcsinfo.crpix1 - 1) * u.pix ) & models.Shift(-(input_model.meta.wcsinfo.crpix2 - 1) * u.pix) pix2sky = getattr( models, "Pix2Sky_{}".format(input_model.meta.wcsinfo.ctype1[-3:]) )() celestial_rotation = models.RotateNative2Celestial( input_model.meta.wcsinfo.crval1 * u.deg, input_model.meta.wcsinfo.crval2 * u.deg, 180 * u.deg, ) pix2sky.input_units_equivalencies = { "x": u.pixel_scale(input_model.meta.wcsinfo.cdelt1 * u.deg / u.pix), "y": u.pixel_scale(input_model.meta.wcsinfo.cdelt2 * u.deg / u.pix), } det2sky = shift_by_crpix | pix2sky | celestial_rotation det2sky.name = "linear_transform" detector_frame = cf.Frame2D( name="detector", axes_names=("x", "y"), unit=(u.pix, u.pix) ) sky_frame = cf.CelestialFrame( reference_frame=getattr( coord, input_model.meta.coordinates.reference_frame )(), name="sky_frame", unit=(u.deg, u.deg), ) pipeline = [(detector_frame, det2sky), (sky_frame, None)] wcs = WCS(pipeline) output_model.meta.wcs = wcs output_model.meta.cal_step.assign_wcs = "COMPLETE" return output_model