def abl_to_v2v3l(input_model, reference_files): """ Create the transform from "alpha_beta" to "v2v3" frame. Transform description: forward transform RegionsSelector label_mapper is LabelMapperDict() {channel_wave_range (): channel_number} selector is {channel_number: ab2v2 & ab2v3} bacward_transform RegionsSelector label_mapper is LabelMapperDict() {channel_wave_range (): channel_number} selector is {channel_number: v22ab & v32ab} """ 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] with DistortionMRSModel(reference_files['distortion']) as dist: v23 = dict(zip(dist.abv2v3_model.channel_band, dist.abv2v3_model.model)) with WavelengthrangeModel(reference_files['wavelengthrange']) as f: wr = dict(zip(f.waverange_selector, f.wavelengthrange)) dict_mapper = {} sel = {} # Since there are two channels in each reference file we need to loop over them for c in channels: ch = int(c[0]) dict_mapper[tuple(wr[c])] = (models.Mapping( (2, ), name="mapping_lam") | models.Const1D(ch, name="channel #")) 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 = chan_v23 v23_spatial.inverse = v23chan_backward # Tack on passing the third wavelength component 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() abl2v2v3l = selector.RegionsSelector(('alpha', 'beta', 'lam'), ('v2', 'v3', 'lam'), label_mapper=wave_range_mapper, selector=sel) return abl2v2v3l
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 remap_distortion_model(model, dispersion_axis): """ Remaps the distortion model so it can return a 2D array. Parameters ---------- model : :class:`~astropy.modeling.models.Model` A model that receives 2D data and returns 1D data. dispersion_axis : {0 or 1} Define distortion model along the rows (0) or along the columns (1). Returns ------- :class:`~astropy.modeling.models.Model` A model that receives and returns 2D data. See also -------- - https://docs.astropy.org/en/stable/modeling/compound-models.html#advanced-mappings """ m = models.Identity(2) if dispersion_axis == 0: m.inverse = models.Mapping((0, 1, 1)) | (model & models.Identity(1)) else: m.inverse = models.Mapping((0, 0, 1)) | (models.Identity(1) & model) return m
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 abtov2v3model(channel,**kwargs): # Construct the reference data model in general JWST imager type input_model = datamodels.ImageModel() # Convert input of type '1A' into the band and channel that pipeline needs theband,thechan=bandchan(channel) # Set the filter in the data model meta header input_model.meta.instrument.band = theband input_model.meta.instrument.channel = thechan # If passed input refs keyword, unpack and use it if ('refs' in kwargs): therefs=kwargs['refs'] # Otherwise use default reference files else: therefs=get_fitsreffile(channel) # The pipeline transform actually uses the triple # (alpha,beta,lambda) -> (v2,v3,lambda) basedistortion = miri.abl_to_v2v3l(input_model, therefs) distortion = basedistortion # Therefore we need to hack a reasonable wavelength onto our input, run transform, # then hack it back off again thewave=midwave(channel) # Duplicate the beta value at first, then replace with wavelength value map=models.Mapping((0,1,1)) | models.Identity(1) & models.Identity(1) & models.Const1D(thewave) map.inverse=models.Mapping((0,1),n_inputs=3) allmap= map | distortion | map.inverse allmap.inverse= map | distortion.inverse | map.inverse # Return the distortion object that can then be queried return allmap
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 gwcs_cube_with_separable_time(request): """ A mixed celestial + time WCS. """ cube_size = (64, 32, 128) axes_order = request.param time_axes_order = (axes_order.index(2), ) cel_axes_order = (axes_order.index(0), axes_order.index(1)) detector_frame = cf.CoordinateFrame(name="detector", naxes=3, axes_order=(0, 1, 2), axes_type=("pixel", "pixel", "pixel"), unit=(u.pix, u.pix, u.pix)) # time frame: time_model = models.Identity(1) # models.Linear1D(10, 0) time_frame = cf.TemporalFrame(Time("2010-01-01T00:00"), name='time', unit=u.s, axes_order=time_axes_order) # Values from data/acs.hdr: crpix = (12, 13) crval = (5.63, -72.05) cd = [[1.291E-05, 5.9532E-06], [5.02215E-06, -1.2645E-05]] aff = models.AffineTransformation2D(matrix=cd, name='rotation') offx = models.Shift(-crpix[0], name='x_translation') offy = models.Shift(-crpix[1], name='y_translation') wcslin = models.Mapping((1, 0)) | (offx & offy) | aff tan = models.Pix2Sky_TAN(name='tangent_projection') n2c = models.RotateNative2Celestial(*crval, 180, name='sky_rotation') cel_model = wcslin | tan | n2c icrs = cf.CelestialFrame(reference_frame=coord.ICRS(), name='sky', axes_order=cel_axes_order) wcs_forward = (cel_model & time_model) | models.Mapping(axes_order) comp_frm = cf.CompositeFrame(frames=[icrs, time_frame], name='TEST 3D FRAME WITH TIME') w = wcs.WCS(forward_transform=wcs_forward, output_frame=comp_frm, input_frame=detector_frame) w.bounding_box = tuple((0, k - 1) for k in cube_size) w.pixel_shape = cube_size w.array_shape = w.pixel_shape[::-1] return w
def create_channel_selector(alpha, lam, channel, beta, ch_v2, ch_v3): if channel == 1: nslice = range(101, 122) #21 elif channel == 2: nslice = range(201, 218) #17 elif channel == 3: nslice = 16 elif channel == 4: nslice = 12 else: raise ValueError("Incorrect channel #") # transformation from local system (alpha, beta) to V2/V3 p_v2 = models.Polynomial2D(2) p_v3 = models.Polynomial2D(2) p_v2.c0_0, p_v2.c0_1, p_v2.c1_0, p_v2.c1_1 = ch_v2[1:] p_v3.c0_0, p_v3.c0_1, p_v3.c1_0, p_v3.c1_1 = ch_v3[1:] ab_v2v3 = p_v2 & p_v3 ind = [] for i in range(5): for j in range(5): ind.append((i, j)) selector = {} # In the paper the formula is (x-xs)^j*y^i, so the 'x' corresponds # to y in modeling. - swapped in Mapping axs = alpha.field('x_s') lxs = lam.field('x_s') #for i in range(nslice): for i, sl in enumerate(nslice): ashift = models.Shift(axs[i]) lshift = models.Shift(lxs[i]) palpha = models.Polynomial2D(8) plam = models.Polynomial2D(8) for index, coeff in zip(ind, alpha[i][1:]): setattr(palpha, 'c{0}_{1}'.format(index[0], index[1]), coeff) for index, coeff in zip(ind, lam[i][1:]): setattr(plam, 'c{0}_{1}'.format(index[0], index[1]), coeff) alpha_model = ashift & models.Identity(1) | palpha lam_model = lshift & models.Identity(1) | plam beta_model = models.Const1D(beta[0] + (i - 1) * beta[1]) # Note swapping of axes a_b_l = models.Mapping( (1, 0, 0, 1, 0)) | alpha_model & beta_model & lam_model v2_v3_l = a_b_l | models.Mapping( (0, 1, 0, 1, 2)) | ab_v2v3 & models.Identity(1) selector[sl] = v2_v3_l # return alpha, beta, lambda return selector
def miri_models(): reg_models3 = miri_ifu_ref_tools.make_channel_models(3) reg_models4 = miri_ifu_ref_tools.make_channel_models(4) reg_models = {} for reg in reg_models3: lam_model, alpha_model, beta_model, _ = reg_models3[reg] model = models.Mapping((0, 1, 0, 0, 1)) | alpha_model & beta_model & lam_model reg_models[reg] = model for reg in reg_models4: lam_model, alpha_model, beta_model, _ = reg_models4[reg] model = models.Mapping((0, 1, 0, 0, 1)) | alpha_model & beta_model & lam_model reg_models[reg] = model return reg_models
def test_with_bounding_box(): """ Test the option to evaluate a model respecting its bunding_box. """ p = models.Polynomial2D(2) & models.Polynomial2D(2) m = models.Mapping((0, 1, 0, 1)) | p with NumpyRNGContext(1234567): m.parameters = np.random.rand(12) m.bounding_box = ((3, 9), (1, 8)) x, y = np.mgrid[:10, :10] a, b = m(x, y) aw, bw = m(x, y, with_bounding_box=True) ind = (~np.isnan(aw)).nonzero() assert_allclose(a[ind], aw[ind]) assert_allclose(b[ind], bw[ind]) aw, bw = m(x, y, with_bounding_box=True, fill_value=1000) ind = (aw != 1000).nonzero() assert_allclose(a[ind], aw[ind]) assert_allclose(b[ind], bw[ind]) # test the order of bbox is not reversed for 1D models p = models.Polynomial1D(1, c0=12, c1=2.3) p.bounding_box = (0, 5) assert (p(1) == p(1, with_bounding_box=True))
def miri_old_model(): d2c = fits.open('polyd2c_1A_01.00.00.fits') slices = d2c[1].data rids = np.unique(slices).tolist() rids.remove(0) shiftx = models.Shift(-d2c[0].header['CENTERX']) shifty = models.Shift(-d2c[0].header['CENTERY']) scalex = models.Scale(1. / d2c[0].header['NORMX']) scaley = models.Scale(1. / d2c[0].header['NORMY']) b1 = d2c[1].header['B_DEL'] b0 = d2c[1].header['B_MIN'] coeffs = d2c[2].data channel_selector = {} for i in rids: palpha = fits_column_to_model(coeffs.field("alpha_" + str(int(i))), 4, 4) plam = fits_column_to_model(coeffs.field("lambda_" + str(int(i))), 4, 4) malpha = (shiftx & shifty) | (scalex & scaley) | palpha mlam = (shiftx & shifty) | (scalex & scaley) | plam beta = models.Const1D(b0 + i * b1) channel_selector[i] = models.Mapping( (0, 1, 0, 0, 1)) | malpha & beta & mlam return channel_selector
def __init__(self, inputs, mapper, no_label=np.nan, inputs_mapping=None, name=None, **kwargs): self._no_label = no_label self._inputs = inputs self._n_inputs = len(inputs) self._outputs = tuple( ['x{0}'.format(ind) for ind in list(range(mapper.n_outputs))]) if isinstance(inputs_mapping, tuple): inputs_mapping = astmodels.Mapping(inputs_mapping) elif inputs_mapping is not None and not isinstance( inputs_mapping, astmodels.Mapping): raise TypeError( "inputs_mapping must be an instance of astropy.modeling.Mapping." ) self._inputs_mapping = inputs_mapping self._mapper = mapper self._input_units_strict = {key: False for key in self._inputs} self._input_units_allow_dimensionless = { key: False for key in self._inputs } super(_LabelMapper, self).__init__(name=name, **kwargs) self.outputs = ('label', )
def miri_models(): # Use channels 3 and 4 for this example reg_models3 = make_channel_models(3) reg_models4 = make_channel_models(4) reg_models = {} for reg in reg_models3: lam_model, alpha_model, beta_model, _ = reg_models3[reg] model = models.Mapping( (0, 1, 0, 0, 1)) | alpha_model & beta_model & lam_model reg_models[reg] = model for reg in reg_models4: lam_model, alpha_model, beta_model, _ = reg_models4[reg] model = models.Mapping( (0, 1, 0, 0, 1)) | alpha_model & beta_model & lam_model reg_models[reg] = model return reg_models
def test_LabelMapperDict(): dmapper = create_scalar_mapper() sel = selector.LabelMapperDict(('x', 'y'), dmapper, atol=10**-3, inputs_mapping=models.Mapping((0, ), n_inputs=2)) assert (sel(-1.9580, 2) == dmapper[-1.95805483](-1.95805483, 2))
def gwcs_7d_complex_mapping(): """ Useful features of this WCS (axes indices here are 0-based): - includes two celestial axes: input (0, 1) maps to world (2 - RA, 1 - Dec) - includes one separable frame with one axis: 4 -> 2 - includes one frame with 3 input and 4 output axes (1 degenerate), with separable world axes (3, 5) and (0, 6). """ offx = models.Shift(-64, name='x_translation') offy = models.Shift(-32, name='y_translation') cd = np.array([[1.2906, 0.59532], [0.50222, -1.2645]]) aff = models.AffineTransformation2D(matrix=1e-5 * cd, name='rotation') aff2 = models.AffineTransformation2D(matrix=cd, name='rotation2') wcslin = (offx & offy) | aff tan = models.Pix2Sky_TAN(name='tangent_projection') n2c = models.RotateNative2Celestial(5.630568, -72.0546, 180, name='skyrot') icrs = cf.CelestialFrame(reference_frame=coord.ICRS(), name='sky', axes_order=(2, 1)) spec = cf.SpectralFrame(name='wave', unit=[u.m], axes_order=(4, ), axes_names=('lambda', )) cmplx = cf.CoordinateFrame( name="complex", naxes=4, axes_order=(3, 5, 0, 6), axis_physical_types=(['em.wl', 'em.wl', 'time', 'time']), axes_type=("SPATIAL", "SPATIAL", "TIME", "TIME"), axes_names=("x", "y", "t", 'tau'), unit=(u.m, u.m, u.second, u.second)) comp_frm = cf.CompositeFrame(frames=[icrs, spec, cmplx], name='TEST 7D') wcs_forward = ( (wcslin & models.Shift(-3.14) & models.Scale(2.7) & aff2) | (tan & models.Identity(1) & models.Identity(1) & models.Identity(2)) | (n2c & models.Identity(1) & models.Identity(1) & models.Identity(2)) | models.Mapping((3, 1, 0, 4, 2, 5, 3))) detector_frame = cf.CoordinateFrame(name="detector", naxes=6, axes_order=(0, 1, 2, 3, 4, 5), axes_type=("pixel", "pixel", "pixel", "pixel", "pixel", "pixel"), unit=(u.pix, u.pix, u.pix, u.pix, u.pix, u.pix)) pipeline = [('detector', wcs_forward), (comp_frm, None)] w = wcs.WCS(forward_transform=wcs_forward, output_frame=comp_frm, input_frame=detector_frame) w.bounding_box = ((0, 15), (0, 31), (0, 20), (0, 10), (0, 10), (0, 1)) w.array_shape = (2, 11, 11, 21, 32, 16) w.pixel_shape = (16, 32, 21, 11, 11, 2) return w
def make_fitswcs_transform(header): """ Create a basic FITS WCS transform. It does not include distortions. Parameters ---------- header : `astropy.io.fits.Header` or dict FITS Header (or dict) with basic WCS information """ if isinstance(header, fits.Header): wcs_info = read_wcs_from_header(header) elif isinstance(header, dict): wcs_info = header else: raise TypeError("Expected a FITS Header or a dict.") # If a pixel axis maps directly to an output axis, we want to have that # model completely self-contained, so don't put all the CRPIXj shifts # in a single CompoundModel at the beginning transforms = [] # The tricky stuff! sky_model = fitswcs_image(wcs_info) linear_models = fitswcs_linear(wcs_info) all_models = linear_models if sky_model: all_models.append(sky_model) # Now arrange the models so the inputs and outputs are in the right places all_models.sort(key=lambda m: m.meta['output_axes'][0]) input_axes = [ax for m in all_models for ax in m.meta['input_axes']] output_axes = [ax for m in all_models for ax in m.meta['output_axes']] if input_axes != list(range(len(input_axes))): input_mapping = models.Mapping(input_axes) transforms.append(input_mapping) transforms.append(functools.reduce(core._model_oper('&'), all_models)) if output_axes != list(range(len(output_axes))): output_mapping = models.Mapping(output_axes) transforms.append(output_mapping) return functools.reduce(core._model_oper('|'), transforms)
def gwcs_2d_spatial_reordered(): """ A simple one step spatial WCS, in ICRS with a 1 and 2 px shift. """ out_frame = cf.CelestialFrame(reference_frame=coord.ICRS(), axes_order=(1, 0)) return wcs.WCS(model_2d_shift | models.Mapping((1, 0)), input_frame=detector_2d, output_frame=out_frame)
def gwcs_3d_galactic_spectral(): """ This fixture has the axes ordered as lat, spectral, lon. """ # lat,wav,lon crpix1, crpix2, crpix3 = 29, 39, 44 crval1, crval2, crval3 = 10, 20, 25 cdelt1, cdelt2, cdelt3 = -0.01, 0.5, 0.01 shift = models.Shift(-crpix3) & models.Shift(-crpix1) scale = models.Multiply(cdelt3) & models.Multiply(cdelt1) proj = models.Pix2Sky_CAR() skyrot = models.RotateNative2Celestial(crval3, 90 + crval1, 180) celestial = shift | scale | proj | skyrot wave_model = models.Shift(-crpix2) | models.Multiply( cdelt2) | models.Shift(crval2) transform = models.Mapping( (2, 0, 1)) | celestial & wave_model | models.Mapping((1, 2, 0)) transform.bounding_box = ((5, 50), (-2, 45), (-1, 35)) sky_frame = cf.CelestialFrame(axes_order=(2, 0), reference_frame=coord.Galactic(), axes_names=("Longitude", "Latitude")) wave_frame = cf.SpectralFrame(axes_order=(1, ), unit=u.Hz, axes_names=("Frequency", )) 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"), unit=(u.pix, u.pix, u.pix)) owcs = wcs.WCS(forward_transform=transform, output_frame=frame, input_frame=detector_frame) owcs.array_shape = (30, 20, 10) owcs.pixel_shape = (10, 20, 30) return owcs
def inverse(self): left_inverse = self.left.inverse right_inverse = self.right.inverse total_inputs = self.n_outputs n_left_only_inputs = total_inputs - self.shared_inputs # Pass through arguments to the left model unchanged while computing the right output mapping = list(range(n_left_only_inputs)) step1 = m.Mapping(mapping) & right_inverse # Now pass through the right outputs unchanged while also feeding them into the left model # This mapping duplicates the output of the right inverse to be fed # into the left and also out unmodified at the end of the transform inter_mapping = mapping + list(range(max(mapping) + 1, max(mapping) + 1 + right_inverse.n_outputs)) * 2 step2 = m.Mapping(inter_mapping) | (left_inverse & m.Identity(right_inverse.n_outputs)) return step1 | step2
def gwcs_spec_cel_time_4d(): """ A complex 4D mixed celestial + spectral + time WCS. """ # spectroscopic frame: wave_model = models.Shift(-5) | models.Multiply(3.7) | models.Shift(20) wave_model.bounding_box = (7, 50) wave_frame = cf.SpectralFrame(name='wave', unit=u.m, axes_order=(0, ), axes_names=('lambda', )) # time frame: time_model = models.Identity(1) # models.Linear1D(10, 0) time_frame = cf.TemporalFrame(Time("2010-01-01T00:00"), name='time', unit=u.s, axes_order=(3, )) # Values from data/acs.hdr: crpix = (12, 13) crval = (5.63, -72.05) cd = [[1.291E-05, 5.9532E-06], [5.02215E-06, -1.2645E-05]] aff = models.AffineTransformation2D(matrix=cd, name='rotation') offx = models.Shift(-crpix[0], name='x_translation') offy = models.Shift(-crpix[1], name='y_translation') wcslin = models.Mapping((1, 0)) | (offx & offy) | aff tan = models.Pix2Sky_TAN(name='tangent_projection') n2c = models.RotateNative2Celestial(*crval, 180, name='sky_rotation') cel_model = wcslin | tan | n2c icrs = cf.CelestialFrame(reference_frame=coord.ICRS(), name='sky', axes_order=(2, 1)) wcs_forward = wave_model & cel_model & time_model comp_frm = cf.CompositeFrame(frames=[wave_frame, icrs, time_frame], name='TEST 4D FRAME') detector_frame = cf.CoordinateFrame(name="detector", naxes=4, axes_order=(0, 1, 2, 3), axes_type=("pixel", "pixel", "pixel", "pixel"), unit=(u.pix, u.pix, u.pix, u.pix)) w = wcs.WCS(forward_transform=wcs_forward, output_frame=comp_frm, input_frame=detector_frame) w.bounding_box = ((0, 63), (0, 127), (0, 255), (0, 9)) w.array_shape = (10, 256, 128, 64) w.pixel_shape = (64, 128, 256, 10) return w
def test_LabelMapperDict(): dmapper = create_scalar_mapper() sel = selector.LabelMapperDict(('x', 'y'), dmapper, atol=10**-3, inputs_mapping=models.Mapping((0,), n_inputs=2)) assert(sel(-1.9580, 2) == dmapper[-1.95805483](-1.95805483, 2)) with pytest.raises(TypeError): selector.LabelMapperDict(('x', 'y'), mapper={1: models.Rotation2D(23), 2: models.Shift(1) } )
def test_prepare_outputs_complex_reshape(): x = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]) y = np.array([[16, 17, 18, 19, 20], [21, 22, 23, 24, 25], [26, 27, 28, 29, 30]]) m = models.Identity(3) | models.Mapping((2, 1, 0)) m.bounding_box = ((0, 100), (0, 200), (0, 50)) mf = models.fix_inputs(m, {2: 22}) t = mf | models.Mapping((2, 1), n_inputs=3) output = mf(1, 2) assert output == (22, 2, 1) output = t(1, 2) assert output == (1, 2) output = t(x, y) assert len(output) == 2 np.testing.assert_array_equal(output[0], x) np.testing.assert_array_equal(output[1], y) m = models.Identity(3) | models.Mapping((0, 1, 2)) m.bounding_box = ((0, 100), (0, 200), (0, 50)) mf = models.fix_inputs(m, {2: 22}) t = mf | models.Mapping((0, 1), n_inputs=3) output = mf(1, 2) assert output == (1, 2, 22) output = t(1, 2) assert output == (1, 2) output = t(x, y) assert len(output) == 2 np.testing.assert_array_equal(output[0], x) np.testing.assert_array_equal(output[1], y)
def create_beta_models(b0, bdel, channel, nslices): beta = {} slices = {} for s in range(nslices): sl = channel * 100 + s + 1 beta_s = b0 + s * bdel m = models.Const1D(beta_s, name='det2local') #xy2beta and xy2lam beta[sl] = m inv = models.Const1D(sl) slices[beta_s] = models.Mapping([ 1, ]) | inv return beta, slices
def _generate_compound_model(*lookup_tables, mesh=True): """ Takes a set of quantities and returns a ND compound model. """ model = _generate_tabular(lookup_tables[0]) for lt in lookup_tables[1:]: model = model & _generate_tabular(lt) if mesh: return model # If we are not meshing the inputs duplicate the inputs across all models mapping = list(range(lookup_tables[0].ndim)) * len(lookup_tables) return models.Mapping(mapping) | model
def lrs(input_model, reference_files): """ Create the WCS pipeline for a MIRI fixed slit observation. reference_files = {"specwcs": 'MIRI_FM_MIRIMAGE_P750L_DISTORTION_04.02.00.fits'} """ detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) focal_spatial = cf.Frame2D(name='focal', axes_order=(0, 1), unit=(u.arcmin, u.arcmin)) sky = cf.CelestialFrame(reference_frame=coord.ICRS()) spec = cf.SpectralFrame(name='wavelength', axes_order=(2, ), unit=(u.micron, ), axes_names=('lambda', )) focal = cf.CompositeFrame([focal_spatial, spec]) ref = fits.open(reference_files['specwcs']) ldata = ref[1].data if input_model.meta.exposure.type.lower() == 'mir_lrs-fixedslit': zero_point = ref[1].header['imx'], ref[1].header['imy'] elif input_model.meta.exposure.type.lower() == 'mir_lrs-slitless': #zero_point = ref[1].header['imysltl'], ref[1].header['imxsltl'] #zero point in reference file is wrong # This should eb moved eventually to the reference file. zero_point = [35, 442] #[35, 763] # account for subarray lrsdata = np.array([l for l in ldata]) x0 = lrsdata[:, 3] x1 = lrsdata[:, 5] y0 = lrsdata[:, 4] domain = [{ 'lower': x0.min() + zero_point[0], 'upper': x1.max() + zero_point[0] }, { 'lower': (y0.min() + zero_point[1]), 'upper': (y0.max() + zero_point[1]) }] log.info("Setting domain to {0}".format(domain)) lrs_wav_model = jwmodels.LRSWavelength(lrsdata, zero_point) ref.close() angle = np.arctan(0.00421924) spatial = models.Rotation2D(angle) det2focal = models.Mapping((0, 1, 0, 1)) | spatial & lrs_wav_model det2focal.meta['domain'] = domain pipeline = [(detector, det2focal), (focal, None)] #(sky, None) #] return pipeline
def gwcs_cube_with_separable_spectral(request): cube_size = (128, 64, 100) axes_order = request.param spectral_axes_order = (axes_order.index(2), ) cel_axes_order = (axes_order.index(0), axes_order.index(1)) # Values from data/acs.hdr: crpix = (64, 32) crval = (5.63056810618, -72.0545718428) cd = [[1.29058667557984E-05, 5.95320245884555E-06], [5.02215195623825E-06, -1.2645010396976E-05]] aff = models.AffineTransformation2D(matrix=cd, name='rotation') offx = models.Shift(-crpix[0], name='x_translation') offy = models.Shift(-crpix[1], name='y_translation') wcslin = (offx & offy) | aff tan = models.Pix2Sky_TAN(name='tangent_projection') n2c = models.RotateNative2Celestial(*crval, 180, name='sky_rotation') icrs = cf.CelestialFrame(reference_frame=coord.ICRS(), name='sky', axes_order=cel_axes_order) spec = cf.SpectralFrame(name='wave', unit=[ u.m, ], axes_order=spectral_axes_order, axes_names=('lambda', )) comp_frm = cf.CompositeFrame(frames=[icrs, spec], name='TEST 3D FRAME WITH SPECTRAL AXIS') wcs_forward = ((wcslin & models.Identity(1)) | (tan & models.Identity(1)) | (n2c & models.Identity(1)) | models.Mapping(axes_order)) detector_frame = cf.CoordinateFrame(name="detector", naxes=3, axes_order=(0, 1, 2), axes_type=("pixel", "pixel", "pixel"), unit=(u.pix, u.pix, u.pix)) w = wcs.WCS(forward_transform=wcs_forward, output_frame=comp_frm, input_frame=detector_frame) w.bounding_box = tuple((0, k - 1) for k in cube_size) w.pixel_shape = cube_size w.array_shape = w.pixel_shape[::-1] return w, axes_order
def test_compound_model_with_bounding_box_true_and_single_output(): """Regression test for issue #12373""" model = models.Mapping((1,)) | models.Shift(1) x = [1, 2] y = [3, 4] # Check baseline assert_equal(model(x, y), [4, 5]) # Check with_bounding_box=True should be the same assert_equal(model(x, y, with_bounding_box=True), [4, 5]) model.bounding_box = ((-np.inf, np.inf), (-np.inf, np.inf)) # Check baseline assert_equal(model(x, y), [4, 5]) # Check with_bounding_box=True should be the same assert_equal(model(x, y, with_bounding_box=True), [4, 5])
def test_coordinates_composite(): spec = cf.SpectralFrame(name='wavelength', unit=(u.micron, ), axes_order=(2, ), axes_names=('lambda', )) icrs = cf.CelestialFrame(reference_frame=coord.ICRS(), axes_order=(0, 1)) frame = cf.CompositeFrame([icrs, spec]) transform = models.Mapping( [0, 0, 1]) | models.Identity(2) & models.Polynomial1D(1, c0=.2, c1=.3) w = wcs.WCS(forward_transform=transform, output_frame=frame, input_frame=det) x = np.arange(3) result = getattr(w, w.output_frame).coordinates(x, x) assert_allclose(result[0].ra.value, w(x, x)[0]) assert_allclose(result[0].ra.value, w(x, x)[1]) assert_allclose(result[1].value, w(x, x)[2])
def create_range_mapper(): m = [] for i in np.arange(9) * .1: c0_0, c1_0, c0_1, c1_1 = np.ones((4, )) * i m.append( models.Polynomial2D(2, c0_0=c0_0, c1_0=c1_0, c0_1=c0_1, c1_1=c1_1)) keys = np.array([[4.88, 5.64], [5.75, 6.5], [6.67, 7.47], [7.7, 8.63], [8.83, 9.96], [10.19, 11.49], [11.77, 13.28], [13.33, 15.34], [15.56, 18.09]]) rmapper = {} for k, v in zip(keys, m): rmapper[tuple(k)] = v sel = selector.LabelMapperRange(('x', 'y'), rmapper, inputs_mapping=models.Mapping((0, ), n_inputs=2)) return sel
def __init__(self, inputs, mapper, no_label=np.nan, inputs_mapping=None, name=None, **kwargs): self._no_label = no_label self.inputs = inputs self.outputs = tuple( ['x{0}'.format(ind) for ind in list(range(mapper.n_outputs))]) if isinstance(inputs_mapping, tuple): inputs_mapping = astmodels.Mapping(inputs_mapping) elif inputs_mapping is not None and not isinstance( inputs_mapping, astmodels.Mapping): raise TypeError( "inputs-mapping must be an instance of astropy.modeling.Mapping." ) self._inputs_mapping = inputs_mapping self._mapper = mapper super(_LabelMapper, self).__init__(name=name, **kwargs)