def test_ShiftModel(): # Shift by a scalar m = models.Shift(42) assert m(0) == 42 assert_equal(m([1, 2]), [43, 44]) # Shift by a list m = models.Shift([42, 43], n_models=2) assert_equal(m(0), [42, 43]) assert_equal(m([1, 2], model_set_axis=False), [[43, 44], [44, 45]])
def test_calculate_affine_matrices(angle, scale, xoffset, yoffset): m = ((models.Scale(scale) & models.Scale(scale)) | models.Rotation2D(angle) | (models.Shift(xoffset) & models.Shift(yoffset))) affine = adwcs.calculate_affine_matrices(m, (100, 100)) assert_allclose(affine.offset, (yoffset, xoffset), atol=1e-10) angle = math.radians(angle) assert_allclose(affine.matrix, ((scale * math.cos(angle), scale * math.sin(angle)), (-scale * math.sin(angle), scale * math.cos(angle))), atol=1e-10)
def test_transforms_compound(tmpdir): tree = { 'compound': astmodels.Shift(1) & astmodels.Shift(2) | astmodels.Sky2Pix_TAN() | astmodels.Rotation2D() | astmodels.AffineTransformation2D([[2, 0], [0, 2]], [42, 32]) + astmodels.Rotation2D(32) } helpers.assert_roundtrip_tree(tree, tmpdir)
def test_to_fits_sip_pc_normalization(gwcs_simple_imaging_units, matrix_type): y, x = np.mgrid[:1024:10, :1024:10] xflat = np.ravel(x[1:-1, 1:-1]) yflat = np.ravel(y[1:-1, 1:-1]) bounding_box = ((0, 1024), (0, 1024)) # create a simple imaging WCS without distortions: cdmat = np.array([[1.29e-5, 5.95e-6], [5.02e-6, -1.26e-5]]) aff = models.AffineTransformation2D(matrix=cdmat, name='rotation') offx = models.Shift(-501, name='x_translation') offy = models.Shift(-501, name='y_translation') wcslin = (offx & offy) | aff n2c = models.RotateNative2Celestial(5.63, -72.05, 180, name='sky_rotation') tan = models.Pix2Sky_TAN(name='tangent_projection') wcs_forward = wcslin | tan | n2c sky_cs = cf.CelestialFrame(reference_frame=coord.ICRS(), name='sky') pipeline = [('detector', wcs_forward), (sky_cs, None)] wcs_lin = wcs.WCS( input_frame=cf.Frame2D(name='detector'), output_frame=sky_cs, forward_transform=pipeline ) _, _, celestial_group = wcs_lin._separable_groups(detect_celestial=True) fits_wcs = wcs_lin._to_fits_sip( celestial_group=celestial_group, keep_axis_position=False, bounding_box=bounding_box, max_pix_error=0.1, degree=None, max_inv_pix_error=0.1, inv_degree=None, npoints=32, crpix=None, projection='TAN', matrix_type=matrix_type, verbose=False ) fitssip = astwcs.WCS(fits_wcs) fitsvalx, fitsvaly = fitssip.wcs_pix2world(xflat, yflat, 0) inv_fitsvalx, inv_fitsvaly = fitssip.wcs_world2pix(fitsvalx, fitsvaly, 0) gwcsvalx, gwcsvaly = wcs_lin(xflat, yflat) assert_allclose(gwcsvalx, fitsvalx, atol=4e-11, rtol=0) assert_allclose(gwcsvaly, fitsvaly, atol=4e-11, rtol=0) assert_allclose(xflat, inv_fitsvalx, atol=5e-9, rtol=0) assert_allclose(yflat, inv_fitsvaly, atol=5e-9, rtol=0)
def fpa2asdf(fpafile, outname, ref_kw): """ Create an asdf reference file with the FPA description. The CDP2 delivery includes a fits file - "FPA.fpa" which is the input to this function. This file is converted to asdf and is a reference file of type "FPA". nirspec_fs_ref_tools.fpa2asdf('Ref_Files/CoordTransform/Description/FPA.fpa', 'fpa.asdf') Parameters ---------- fpafile : str A fits file with FPA description (FPA.fpa) outname : str Name of output ASDF file. """ with open(fpafile) as f: lines = [l.strip() for l in f.readlines()] # NRS1 ind = lines.index("*SCA491_PitchX") scalex_nrs1 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_x') ind = lines.index("*SCA491_PitchY") scaley_nrs1 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_y') ind = lines.index("*SCA491_RotAngle") rot_nrs1 = models.Rotation2D(np.rad2deg(-float(lines[ind + 1])), name='fpa_rotation') ind = lines.index("*SCA491_PosX") shiftx_nrs1 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_x') ind = lines.index("*SCA491_PosY") shifty_nrs1 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_y') # NRS2 ind = lines.index("*SCA492_PitchX") scalex_nrs2 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_x') ind = lines.index("*SCA492_PitchY") scaley_nrs2 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_y') ind = lines.index("*SCA492_RotAngle") rot_nrs2 = models.Rotation2D(np.rad2deg(float(lines[ind + 1])), name='fpa_rotation') ind = lines.index("*SCA492_PosX") shiftx_nrs2 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_x') ind = lines.index("*SCA492_PosY") shifty_nrs2 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_y') tree = ref_kw.copy() tree['NRS1'] = (shiftx_nrs1 & shifty_nrs1) | rot_nrs1 | (scalex_nrs1 & scaley_nrs1) tree['NRS2'] = (shiftx_nrs2 & shifty_nrs2) | rot_nrs2 | (scalex_nrs2 & scaley_nrs2) fasdf = AsdfFile() fasdf.tree = tree fasdf.write_to(outname) return fasdf
def time_init_7_with_units(): aff = models.AffineTransformation2D(matrix=[[1, 0], [0, 1]] * u.arcsec, translation=[0, 0] * u.arcsec) aff.input_units_equivalencies = { 'x': u.pixel_scale(1 * u.arcsec / u.pix), 'y': u.pixel_scale(1 * u.arcsec / u.pix) } m = (models.Shift(-10.5 * u.pix) & models.Shift(-13.2 * u.pix) | aff | models.Scale(.01 * u.arcsec) & models.Scale(.04 * u.arcsec) | models.Pix2Sky_TAN() | models.RotateNative2Celestial( 5.6 * u.deg, -72.05 * u.deg, 180 * u.deg))
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_compound_bounding_box(): trans3 = models.Shift(10) & models.Scale(2) & models.Shift(-1) pipeline = [('detector', trans3), ('sky', None)] w = wcs.WCS(pipeline) cbb = { 1: ((-1, 10), (6, 15)), 2: ((-1, 5), (3, 17)), 3: ((-3, 7), (1, 27)), } if new_bbox: # Test attaching a valid bounding box (ignoring input 'x') w.attach_compound_bounding_box(cbb, [('x',)]) from astropy.modeling.bounding_box import CompoundBoundingBox cbb = CompoundBoundingBox.validate(trans3, cbb, selector_args=[('x',)], order='F') assert w.bounding_box == cbb assert w.bounding_box is trans3.bounding_box # Test evaluating assert_allclose(w(13, 2, 1), (np.nan, np.nan, np.nan)) assert_allclose(w(13, 2, 2), (np.nan, np.nan, np.nan)) assert_allclose(w(13, 0, 3), (np.nan, np.nan, np.nan)) # No bounding box for selector with pytest.raises(RuntimeError): w(13, 13, 4) # Test attaching a invalid bounding box (not ignoring input 'x') with pytest.raises(ValueError): w.attach_compound_bounding_box(cbb, [('x', False)]) else: with pytest.raises(NotImplementedError) as err: w.attach_compound_bounding_box(cbb, [('x',)]) assert str(err.value) == 'Compound bounding box is not supported for your version of astropy' # Test that bounding_box with quantities can be assigned and evaluates trans = models.Shift(10 * u .pix) & models.Shift(2 * u.pix) pipeline = [('detector', trans), ('sky', None)] w = wcs.WCS(pipeline) cbb = { 1 * u.pix: (1 * u.pix, 5 * u.pix), 2 * u.pix: (2 * u.pix, 6 * u.pix) } if new_bbox: w.attach_compound_bounding_box(cbb, [('x1',)]) from astropy.modeling.bounding_box import CompoundBoundingBox cbb = CompoundBoundingBox.validate(trans, cbb, selector_args=[('x1',)], order='F') assert w.bounding_box == cbb assert w.bounding_box is trans.bounding_box assert_allclose(w(-1*u.pix, 1*u.pix), (np.nan, np.nan)) assert_allclose(w(7*u.pix, 2*u.pix), (np.nan, np.nan)) else: with pytest.raises(NotImplementedError) as err: w.attach_compound_bounding_box(cbb, [('x1',)])
def test_validate_transform(tmp_path): """ Tests that custom types, like transform, can be validated. """ file_path = tmp_path / "test.asdf" with TransformModel(transform=models.Shift(1) & models.Shift(2), strict_validation=True) as m: m.validate() m.save(file_path) with TransformModel(file_path, strict_validation=True) as m: m.validate()
def test_domain(): trans3 = models.Shift(10) & models.Scale(2) & models.Shift(-1) pipeline = [('detector', trans3), ('sky', None)] w = wcs.WCS(pipeline) bb = ((-1, 10), (6, 15)) with pytest.raises(DimensionalityError): w.bounding_box = bb trans2 = models.Shift(10) & models.Scale(2) pipeline = [('detector', trans2), ('sky', None)] w = wcs.WCS(pipeline) w.bounding_box = bb assert w.bounding_box == w.forward_transform.bounding_box[::-1]
def test_validate_transform(): """ Tests that custom types, like transform, can be validated. """ m = CollimatorModel(model=models.Shift(1) & models.Shift(2), strict_validation=True) m.meta.description = "Test validate a WCS reference file." m.meta.author = "ND" m.meta.pedigree = "GROUND" m.meta.useafter = "2018/06/18" m.meta.reftype = "collimator" m.validate()
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
def fitswcs_linear(header): """ Create WCS linear transforms for any axes not associated with celestial coordinates. We require that each world axis aligns precisely with only a single pixel axis. Parameters ---------- header : `astropy.io.fits.Header` or dict FITS Header or dict with basic FITS WCS keywords. """ # We *always* want the wavelength solution model to be called "WAVE" # even if the CTYPE keyword is "AWAV" model_name_mapping = {"AWAV": "WAVE"} 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.") cd = wcs_info['CD'] crpix = wcs_info['CRPIX'] crval = wcs_info['CRVAL'] # get the part of the CD matrix corresponding to the imaging axes sky_axes, spec_axes, unknown = get_axes(wcs_info) if not sky_axes and len(unknown) == 2: unknown = [] linear_models = [] for ax in spec_axes + unknown: pixel_axes = _get_contributing_axes(wcs_info, ax) if len(pixel_axes) == 1: pixel_axis = pixel_axes[0] linear_model = (models.Shift(1 - crpix[pixel_axis], name='crpix' + str(pixel_axis + 1)) | models.Scale(cd[ax, pixel_axis]) | models.Shift(crval[ax])) ctype = wcs_info['CTYPE'][ax][:4].upper() linear_model.name = model_name_mapping.get(ctype, ctype) linear_model.outputs = (wcs_info['CTYPE'][ax], ) linear_model.meta.update({ 'input_axes': pixel_axes, 'output_axes': [ax] }) linear_models.append(linear_model) else: raise ValueError(f"Axis {ax} depends on more than one input axis") return linear_models
def test_domain(): trans3 = models.Shift(10) & models.Scale(2) & models.Shift(-1) pipeline = [('detector', trans3), ('sky', None)] w = wcs.WCS(pipeline) domain = [{'lower': -1, 'upper': 10, 'include_lower': True, 'include_upper': False, 'step': .1}, {'lower': 6, 'upper': 15, 'include_lower': False, 'include_upper': True, 'step': .5}] with pytest.raises(ValueError): w.domain = domain trans2 = models.Shift(10) & models.Scale(2) pipeline = [('detector', trans2), ('sky', None)] w = wcs.WCS(pipeline) w.domain = domain assert w.domain == w.forward_transform.meta['domain']
def test_coupled_compound_model_nested(): ccm = CoupledCompoundModel("&", m.Shift(5) & m.Scale(2), m.Scale(10) | m.Shift(3)) new = roundtrip_object(ccm) assert isinstance(new, CoupledCompoundModel) assert isinstance(new.left, CompoundModel) assert isinstance(new.left.left, m.Shift) assert isinstance(new.left.right, m.Scale) assert isinstance(new.right, CompoundModel) assert isinstance(new.right.left, m.Scale) assert isinstance(new.right.right, m.Shift) assert ccm.n_inputs == new.n_inputs assert ccm.inputs == new.inputs
def test_create_wcs(tmpdir): m1 = models.Shift(12.4) & models.Shift(-2) icrs = cf.CelestialFrame(name='icrs', reference_frame=coord.ICRS()) det = cf.Frame2D(name='detector', axes_order=(0, 1)) gw1 = wcs.WCS(output_frame='icrs', input_frame='detector', forward_transform=m1) gw2 = wcs.WCS(output_frame='icrs', forward_transform=m1) gw3 = wcs.WCS(output_frame=icrs, input_frame=det, forward_transform=m1) assert_wcs_roundtrip(gw1, tmpdir) assert_wcs_roundtrip(gw2, tmpdir) assert_wcs_roundtrip(gw3, tmpdir)
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 test_create_wcs(tmpdir): m1 = models.Shift(12.4) & models.Shift(-2) m2 = models.Scale(2) & models.Scale(-2) icrs = cf.CelestialFrame(name='icrs', reference_frame=coord.ICRS()) det = cf.Frame2D(name='detector', axes_order=(0, 1)) gw1 = wcs.WCS(output_frame='icrs', input_frame='detector', forward_transform=m1) gw2 = wcs.WCS(output_frame='icrs', forward_transform=m1) gw3 = wcs.WCS(output_frame=icrs, input_frame=det, forward_transform=m1) tree = {'gw1': gw1, 'gw2': gw2, 'gw3': gw3} helpers.assert_roundtrip_tree(tree, tmpdir)
def test_compound_bounding_box_pass_with_ignored(): model = models.Shift(1) & models.Shift(2) & models.Identity(1) model.inputs = ('x', 'y', 'slit_id') bbox = {(0,): (-0.5, 1047.5), (1,): (-0.5, 2047.5), } cbbox = CompoundBoundingBox.validate(model, bbox, selector_args=[('slit_id', True)], ignored=['y'], order='F') model.bounding_box = cbbox model = models.Shift(1) & models.Shift(2) & models.Identity(1) model.inputs = ('x', 'y', 'slit_id') bind_compound_bounding_box(model, bbox, selector_args=[('slit_id', True)], ignored=['y'], order='F') assert model.bounding_box == cbbox
def subarray_transform(input_model): """ Inputs are in full frame coordinates. If a subarray observation - shift the inputs. """ xstart = input_model.meta.subarray.xstart ystart = input_model.meta.subarray.ystart if xstart is None: xstart = 1 if ystart is None: ystart = 1 subarray2full = astmodels.Shift(xstart - 1) & astmodels.Shift(ystart - 1) return subarray2full
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 test_initialize_wcs_with_list(): # test that you can initialize a wcs with a pipeline that is a list # containing both Step() and (frame, transform) tuples # make pipline consisting of tuples and Steps shift1 = models.Shift(10 * u .pix) & models.Shift(2 * u.pix) shift2 = models.Shift(3 * u.pix) pipeline = [('detector', shift1), wcs.Step('extra_step', shift2)] extra_step = ('extra_step', None) pipeline.append(extra_step) # make sure no warnings occur when creating wcs with this pipeline wcs.WCS(pipeline)
def test_compound_model_mixed_array_scalar_bounding_box(): """Regression test for issue #12319""" model = models.Shift(1) & models.Shift(2) & models.Identity(1) model.inputs = ('x', 'y', 'slit_id') bbox = ModelBoundingBox.validate(model, ((-0.5, 1047.5), (-0.5, 2047.5), (-np.inf, np.inf)), order='F') model.bounding_box = bbox x = np.array([1000, 1001]) y = np.array([2000, 2001]) slit_id = 0 # Everything works when its all in the bounding box value0 = model(x, y, slit_id) value1 = model(x, y, slit_id, with_bounding_box=True) assert_equal(value0, value1)
def test_custom_and_analytical(): m1 = custom_and_analytical_inverse() m = astmodels.Shift(1) & astmodels.Shift(2) | m1 fa = AsdfFile() fa.tree['model'] = m fa.write_to('custom_and_analytical_inverse.asdf') f = asdf.open('custom_and_analytical_inverse.asdf') assert f.tree['model'].inverse is not None m = astmodels.Shift(1) & m1 fa = AsdfFile() fa.tree['model'] = m fa.write_to('custom_and_analytical_inverse.asdf') f = asdf.open('custom_and_analytical_inverse.asdf') assert f.tree['model'].inverse is not None
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_2d_affine_transform(): """Test a simple 2D transform with and without flux conservation""" size = 10 x = np.arange(size * size, dtype=float).reshape(size, size) # We still lose the pixels at either end, resulting in a 18x18-pixel array m = models.Shift(0.5) | models.Scale(2) | models.Shift(-0.5) dg = transform.DataGroup([x], [transform.Transform(m & m)]) output = dg.transform() y = output['data'][1:-1, 1:-1].reshape(8,2,8,2).mean(axis=3).mean(axis=1) assert np.array_equal(x[1:-1, 1:-1], y) output = dg.transform(conserve=True) y = output['data'][1:-1, 1:-1].reshape(8,2,8,2).sum(axis=3).sum(axis=1) assert np.array_equal(x[1:-1, 1:-1], y)
def create_poly_models(data, channel, coeff_names, name): """ Create a 2D polynomial model for the transformation detector --> local MIRI frame Works for alpha and lambda coordinates. """ nslices = len(data) sl = channel * 100 + np.arange(1, nslices + 1) transforms = {} for i in range(nslices): sl = channel * 100 + i + 1 al = data[i] xs = al[0] coeffs = {} for c, val in zip(coeff_names, al[1:]): coeffs[c] = val # As of CDP-8b both the IDT transform as the pipeline use 0-indexed pixels, and # include the 4 reference pixels in their counting. Therefore we do not need to # apply any index shift, just the transform. thisxform = models.Identity(1) & models.Shift( -xs) | models.Polynomial2D(8, name=name, **coeffs) # Put the models together transforms[sl] = thisxform return transforms
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 create_xy_models(data, channel, coeff_names, name): """ Create a 2D polynomial model for the transformation local_MIRI --> detector frame. """ nslices = len(data) sl = channel * 100 + np.arange(1, nslices + 1) shname = "shift_{0}".format(name) pname = "polynomial_{0}".format(name) transforms = {} for i in range(nslices): sl = channel * 100 + i + 1 al = data[i] xs = al[0] coeffs = {} for c, val in zip(coeff_names, al[1:]): coeffs[c] = val # As of CDP-8b both the IDT transform as the pipeline use 0-indexed pixels, and # include the 4 reference pixels in their counting. Therefore we do not need to # apply any index shift, just the transform. thisxform = models.Shift( -xs, name=shname) & models.Identity(1) | models.Polynomial2D( 8, name=pname, **coeffs) transforms[sl] = thisxform return transforms
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