def create_datamodel(hdul): im = ImageModel(hdul) ref = create_reference_files(im) pipeline = miri.create_pipeline(im, ref) wcsobj = wcs.WCS(pipeline) im.meta.wcs = wcsobj return im
def create_wfss_wcs(pupil, filtername='F444W'): """Help create WFSS GWCS object.""" hdul = create_hdul(exptype='NRC_WFSS', filtername=filtername, pupil=pupil) im = ImageModel(hdul) ref = get_reference_files(im) pipeline = nircam.create_pipeline(im, ref) wcsobj = wcs.WCS(pipeline) return wcsobj
def test_create_wcs(tmpdir, version): 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 } write_options = dict(version=version) helpers.assert_roundtrip_tree(tree, tmpdir, write_options=write_options)
def _create_image_model(grating='G395H', filter='F290LP', **kwargs): hdul = create_nirspec_ifu_file(grating=grating, filter=filter, **kwargs) im = datamodels.ImageModel(hdul) refs = create_reference_files(im) pipeline = nirspec.create_pipeline(im, refs, slit_y_range=[-0.5, 0.5]) w = wcs.WCS(pipeline) im.meta.wcs = w return im, refs
def create_tso_wcs(filtername=tsgrism_filters[0], subarray="SUBGRISM256"): """Help create tsgrism GWCS object.""" hdul = create_hdul(exptype='NRC_TSGRISM', pupil='GRISMR', filtername=filtername, detector='NRCALONG', subarray=subarray, wcskeys=wcs_tso_kw) im = CubeModel(hdul) ref = get_reference_files(im) pipeline = nircam.create_pipeline(im, ref) wcsobj = wcs.WCS(pipeline) return wcsobj
def test_reproject(): hdr1 = fits.Header.fromfile(get_pkg_data_filename('data/simple_wcs.hdr')) hdr2 = fits.Header.fromfile(get_pkg_data_filename('data/simple_wcs2.hdr')) w1 = fitswcs.WCS(hdr1) w2 = fitswcs.WCS(hdr2) gw2 = wcs.WCS(output_frame='icrs', forward_transform=gwutil.make_fitswcs_transform(hdr2)) func1 = reproject(w1, w2) func2 = reproject(w1, gw2) x1, y1 = func1(1, 2) x2, y2 = func2(1, 2) utils.assert_allclose(x1, x2, atol=10**-7) utils.assert_allclose(y1, y2, atol=10**-7)
def create_slit(model, x0, y0, order): """ Create a SlitModel representing a grism slit.""" ymin = 0 xmin = 0 # ymax = 58 # xmax = 1323 model = Mapping((0, 1, 0, 0, 0)) | (Shift(xmin) & Shift(ymin) & Const1D(x0) & Const1D(y0) & Const1D(order)) | model wcsobj = wcs.WCS([('det', model), ('world', None)]) wcsobj.bounding_box = ((20, 25), (800, 805)) slit = SlitModel() slit.meta.wcs = wcsobj slit.source_xpos = x0 slit.source_ypos = y0 return slit
def test_nirspec_imaging(): """ Test Nirspec Imaging mode using build 6 reference files. """ #Test creating the WCS f = create_nirspec_imaging_file() im = datamodels.ImageModel(f) refs = create_reference_files(im) pipe = nirspec.create_pipeline(im, refs) w = wcs.WCS(pipe) im.meta.wcs = w # Test evaluating the WCS im.meta.wcs(1, 2)
def create_fitswcs(inp, input_frame=None): if isinstance(inp, DataModel): wcsinfo = wcsinfo_from_model(inp) transform = fitswcs_transform_from_model(wcsinfo) output_frame = frame_from_model(wcsinfo) #elif isinstance(inp, six.string_types): #transform = create_fitswcs_transform(inp) #output_frame = frame_from_fits(inp) else: raise TypeError("Input is expected to be a DataModel instance or a FITS file.") if input_frame is None: input_frame = "detector" pipeline = [(input_frame, transform), (output_frame, None)] wcsobj = wcs.WCS(pipeline) return wcsobj
def test_miri_mrs_1A(): #ref = {} ref = { 'distortion': '', 'regions': '', 'specwcs': '', 'v2v3': '', 'wavelengthrange': '' } im = ImageModel() im.meta.instrument.name = 'MIRI' im.meta.instrument.detector = 'MIRIFUSHORT' im.meta.instrument.channel = '12' im.meta.instrument.band = 'SHORT' im.meta.exposure.type = 'MIR_MRS' step = AssignWcsStep() for reftype in refs: ref[reftype] = step.get_reference_file(im, reftype) pipeline = miri.create_pipeline(im, ref) wcsobj = wcs.WCS(pipeline) for ch in im.meta.instrument.channel: ref_data = mrs_ref_data[ch + band_mapping[im.meta.instrument.band]] #ref_data = mrs_ref_data[im.meta.instrument.channel + band_mapping[im.meta.instrument.band]] #x = np.trunc(ref_data['x']).astype(np.int) #y = np.trunc(ref_data['y']).astype(np.int) for i, s in enumerate(ref_data['s']): sl = int(ch) * 100 + s detector_to_alpha_beta = wcsobj.get_transform( 'detector', 'alpha_beta') alpha, beta, lam = detector_to_alpha_beta.set_input(sl)( ref_data['x'][i], ref_data['y'][i]) ##xan, yan, lam = wcsobj.forward_transform.set_input(sl)(ref_data['x'][i], ref_data['y'][i]) utils.assert_allclose(alpha, ref_data['alpha'][i], atol=10**-5) utils.assert_allclose(beta, ref_data['beta'][i], atol=10**-5) utils.assert_allclose(lam, ref_data['lam'][i], atol=10**-5) detector_to_xan_yan = wcsobj.get_transform('detector', 'Xan_Yan') xan, yan, lam = wcsobj(ref_data['x'], ref_data['y']) utils.assert_allclose(xan, ref_data['v2'][i], atol=10**-5) utils.assert_allclose(yan, ref_data['v3'][i], atol=10**-5) utils.assert_allclose(lam, ref_data['lam'][i], atol=10**-5)
def test_nirspec_fs_esa(): """ Test Nirspec FS mode using build 6 reference files. """ #Test creating the WCS filename = create_nirspec_fs_file(grating="G140M", filter="F100LP") im = datamodels.ImageModel(filename) im.meta.filename = "test_fs.fits" refs = create_reference_files(im) pipe = nirspec.create_pipeline(im, refs) w = wcs.WCS(pipe) im.meta.wcs = w # Test evaluating the WCS w1 = nirspec.nrs_wcs_set_input(im, "S200A1") ref = fits.open( get_file_path( 'Trace_SLIT_A_200_1_V84600010001P0000000002101_39547_JLAB88.fits')) pyw = astwcs.WCS(ref[1].header) # get positions within the slit and the coresponding lambda slit1 = ref[5].data # y offset on the slit lam = ref[4].data # filter out locations outside the slit cond = np.logical_and(slit1 < .5, slit1 > -.5) y, x = cond.nonzero() # 0-based x, y = pyw.wcs_pix2world(x, y, 0) # The pipeline works with 0-based coordinates x -= 1 y -= 1 sca2world = w1.get_transform('sca', 'v2v3') ra, dec, lp = sca2world(x, y) # w1 now outputs in microns hence the 1e6 factor lp *= 1e-6 lam = lam[cond] nan_cond = ~np.isnan(lp) assert_allclose(lp[nan_cond], lam[nan_cond], atol=10**-13) ref.close()
def niriss_soss_set_input(model, order_number): """ Extract a WCS fr a specific spectral order. Parameters ---------- model : `~jwst.datamodels.ImageModel` An instance of an ImageModel order_number : int the spectral order Returns ------- WCS - the WCS corresponding to the spectral order. """ # Make sure the spectral order is available. 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 subarray 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 test_nirspec_ifu_against_esa(): """ Test Nirspec IFU mode using build 6 reference files. """ # Test creating the WCS # hdu = create_nirspec_ifu_file('OPAQUE', 'G140H', 'REF') hdul = create_nirspec_ifu_file("F100LP", "G140H") im = datamodels.ImageModel(hdul) im.meta.filename = "test_ifu.fits" refs = create_reference_files(im) pipe = nirspec.create_pipeline(im, refs) w = wcs.WCS(pipe) im.meta.wcs = w # Test evaluating the WCS (slice 0) w0 = nirspec.nrs_wcs_set_input(im, 0) #ref = fits.open(get_file_path('Trace_IFU_Slice_00_MON-COMBO-IFU-06_8410_jlab85.fits.gz')) ref = fits.open( get_file_path( 'Trace_IFU_Slice_00_MON-COMBO-IFU-06_8410_jlab85.fits.gz')) crpix = np.array([ref[1].header['crpix1'], ref[1].header['crpix2']]) crval = np.array([ref[1].header['crval1'], ref[1].header['crval2']]) # get positions within the slit and the coresponding lambda slit1 = ref[5].data # y offset on the slit lam = ref[4].data # filter out locations outside the slit cond = np.logical_and(slit1 < .5, slit1 > -.5) y, x = cond.nonzero() cor = crval - np.array(crpix) y = y + cor[1] x = x + cor[0] sca2world = w0.get_transform('sca', 'msa_frame') _, slit_y, lp = sca2world(x, y) # Convert meters to microns for the second parameters as the # first parameter will be in microns. assert_allclose(lp, lam[cond] * 1e6, rtol=1e-4, atol=1e-4) ref.close()
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 test_nirspec_fs_esa(): """ Test Nirspec FS mode using build 6 reference files. """ #Test creating the WCS filename = create_nirspec_fs_file(grating="G140M", filter="F100LP") im = datamodels.ImageModel(filename) im.meta.filename = "test_fs.fits" refs = create_reference_files(im) #refs['disperser'] = get_file_path('jwst_nirspec_disperser_0001.asdf') pipe = nirspec.create_pipeline(im, refs) w = wcs.WCS(pipe) im.meta.wcs = w # Test evaluating the WCS w1 = nirspec.nrs_wcs_set_input(im, "S200A1") #ref = fits.open(get_file_path('Trace_SLIT_A_200_1_SLIT-COMBO-016_9791_jlab85_0001.fits.gz')) ref = fits.open( get_file_path( 'Trace_SLIT_A_200_1_V84600010001P0000000002101_39547_JLAB88.fits')) crpix = np.array([ref[1].header['crpix1'], ref[1].header['crpix2']]) crval = np.array([ref[1].header['crval1'], ref[1].header['crval2']]) # get positions within the slit and the coresponding lambda slit1 = ref[5].data # y offset on the slit lam = ref[4].data # filter out locations outside the slit cond = np.logical_and(slit1 < .5, slit1 > -.5) y, x = cond.nonzero() cor = crval - np.array(crpix) y = y + cor[1] x = x + cor[0] sca2world = w1.get_transform('sca', 'v2v3') ra, dec, lp = sca2world(x, y) # w1 now outputs in microns hence the 1e6 factor lp *= 1e-6 lam = lam[cond] nan_cond = ~np.isnan(lp) assert_allclose(lp[nan_cond], lam[nan_cond], atol=10**-13) ref.close()
def create_fitswcs(inp, input_frame=None): if isinstance(inp, DataModel): wcsinfo = wcsinfo_from_model(inp) wavetable = None spatial_axes, spectral_axes, unknown = gwutils.get_axes(wcsinfo) sp_axis = spectral_axes[0] if wcsinfo['CTYPE'][sp_axis] == 'WAVE-TAB': wavetable = inp.wavetable transform = fitswcs_transform_from_model(wcsinfo, wavetable) output_frame = frame_from_model(wcsinfo) #elif isinstance(inp, str): #transform = create_fitswcs_transform(inp) #output_frame = frame_from_fits(inp) else: raise TypeError( "Input is expected to be a DataModel instance or a FITS file.") if input_frame is None: input_frame = "detector" pipeline = [(input_frame, transform), (output_frame, None)] wcsobj = wcs.WCS(pipeline) return wcsobj
def test_miri_mrs_1C(): ref = {} im = ImageModel() im.meta.instrument.name = 'MIRI' im.meta.instrument.detector = 'MIRIFUSHORT' im.meta.instrument.channel = '12' im.meta.instrument.band = 'LONG' im.meta.exposure.type = 'MIR_MRS' step = AssignWcsStep() for reftype in refs: ref[reftype] = step.get_reference_file(im, reftype) pipeline = miri.create_pipeline(im, ref) wcsobj = wcs.WCS(pipeline) for ch in im.meta.instrument.channel: ref_data = mrs_ref_data[ch + band_mapping[im.meta.instrument.band]] for i, s in enumerate(ref_data['s']): sl = int(ch) * 100 + s xan, yan, lam = wcsobj.forward_transform.set_input(sl)( ref_data['x'][i], ref_data['y'][i]) utils.assert_allclose(xan, ref_data['v2'][i], atol=10**-5) utils.assert_allclose(yan, ref_data['v3'][i], atol=10**-5) utils.assert_allclose(lam, ref_data['lam'][i], atol=10**-5) for i, s in enumerate(ref_data['s']): sl = int(ch) * 100 + s xan, yan, lam = wcsobj.forward_transform(ref_data['x'][i], ref_data['y'][i]) utils.assert_allclose(xan, ref_data['v2'][i], atol=10**-5) utils.assert_allclose(yan, ref_data['v3'][i], atol=10**-5) utils.assert_allclose(lam, ref_data['lam'][i], atol=10**-5) xin, yin = wcsobj.backward_transform(ref_data['v2'][i], ref_data['v3'][i], ref_data['lam'][i]) utils.assert_allclose(xin, ref_data['x'][i], atol=10**-5) utils.assert_allclose(y, ref_data['y'][i], atol=10**-5)
def test_nirspec_ifu_against_esa(): """ Test Nirspec IFU mode using CV3 reference files. """ ref = fits.open( get_file_path( 'Trace_IFU_Slice_00_SMOS-MOD-G1M-17-5344175105_30192_JLAB88.fits')) # Test NRS1 pyw = astwcs.WCS(ref['SLITY1'].header) hdul = create_nirspec_ifu_file("OPAQUE", "G140M") im = datamodels.ImageModel(hdul) im.meta.filename = "test_ifu.fits" refs = create_reference_files(im) pipe = nirspec.create_pipeline(im, refs) w = wcs.WCS(pipe) im.meta.wcs = w # Test evaluating the WCS (slice 0) w0 = nirspec.nrs_wcs_set_input(im, 0) # get positions within the slit and the coresponding lambda slit1 = ref['SLITY1'].data # y offset on the slit lam = ref['LAMBDA1'].data # filter out locations outside the slit cond = np.logical_and(slit1 < .5, slit1 > -.5) y, x = cond.nonzero() # 0-based x, y = pyw.wcs_pix2world(x, y, 0) # The pipeline accepts 0-based cooridnates x -= 1 y -= 1 sca2world = w0.get_transform('sca', 'msa_frame') _, slit_y, lp = sca2world(x, y) lp *= 10**-6 assert_allclose(lp, lam[cond], atol=1e-13)
def test_ifu_bbox(): bbox = { 0: ((122.0908542999878, 1586.2584665188083), (773.5411133037417, 825.1150258966278)), 1: ((140.3793485788431, 1606.8904629423566), (1190.353197027459, 1243.0853605832503)), 2: ((120.0139534379125, 1583.9271768905855), (724.3249534782219, 775.8104288584977)), 3: ((142.50252648927454, 1609.3106221382388), (1239.4122720740888, 1292.288713688988)), 4: ((117.88884113088403, 1581.5517394150106), (674.9787657901347, 726.3752061973377)), 5: ((144.57465414462143, 1611.688447569682), (1288.4808318659427, 1341.5035313084197)), 6: ((115.8602297714846, 1579.27471654949), (625.7982466386104, 677.1147840452901)), 7: ((146.7944728147906, 1614.2161842198498), (1337.531525654835, 1390.7050687363856)), 8: ((113.86384530944383, 1577.0293086386203), (576.5344359685643, 627.777022204828)), 9: ((149.0259581360621, 1616.7687282225652), (1386.5118806905086, 1439.843598490326)), 10: ((111.91564190274217, 1574.8351095461135), (527.229828693075, 578.402894851317)), 11: ((151.3053466801954, 1619.3720722471498), (1435.423685040875, 1488.917203728964)), 12: ((109.8957204607345, 1572.570246400894), (477.9699083444277, 529.0782087498488)), 13: ((153.5023503173659, 1621.9005029476564), (1484.38405923062, 1538.0443479389924)), 14: ((107.98320121613297, 1570.411787034636), (428.6704834494425, 479.7217241891257)), 15: ((155.77991404913857, 1624.5184927460925), (1533.169633314481, 1586.9984359105376)), 16: ((106.10212081215678, 1568.286103827344), (379.3860245240618, 430.3780648366697)), 17: ((158.23149941845386, 1627.305849064835), (1582.0496119714928, 1636.0513450787032)), 18: ((104.09366374413436, 1566.030231370944), (330.0822744105267, 381.01974582564395)), 19: ((160.4511021152353, 1629.888830991371), (1630.7797743277185, 1684.9592727079018)), 20: ((102.25220592881234, 1563.9475099032868), (280.7233309522168, 331.6093009077988)), 21: ((162.72784286205734, 1632.5257403739463), (1679.6815760587567, 1734.03692957156)), 22: ((100.40115742738622, 1561.8476640376036), (231.35443588323855, 282.19575854747006)), 23: ((165.05939163941662, 1635.2270773628682), (1728.511467615387, 1783.0485841263735)), 24: ((98.45723949658425, 1559.6499479349648), (182.0417295679079, 232.83530870639865)), 25: ((167.44628840053574, 1637.9923229870349), (1777.2512197664128, 1831.971115503598)), 26: ((96.56508092457855, 1557.5079027818058), (132.5285162704088, 183.27350269292484)), 27: ((169.8529496136358, 1640.778485168005), (1826.028691168028, 1880.9336718824313)), 28: ((94.71390837793813, 1555.4048050512263), (82.94691422559131, 133.63901517357235)), 29: ((172.3681094850081, 1643.685604697228), (1874.8184744639657, 1929.9072657798927)) } hdul = create_nirspec_ifu_file("F290LP", "G140M") im = datamodels.IFUImageModel(hdul) im.meta.filename = "test_ifu.fits" refs = create_reference_files(im) pipe = nirspec.create_pipeline(im, refs, slit_y_range=[-.5, .5]) w = wcs.WCS(pipe) im.meta.wcs = w _, wrange = nirspec.spectral_order_wrange_from_model(im) pipe = im.meta.wcs.pipeline g2s = pipe[2].transform transforms = [pipe[0].transform] transforms.append(pipe[1].transform[1:]) transforms.append(astmodels.Identity(1)) transforms.append(astmodels.Identity(1)) transforms.extend([step.transform for step in pipe[4:-1]]) for sl in range(30): transforms[2] = g2s.get_model(sl) m = functools.reduce(lambda x, y: x | y, [tr.inverse for tr in transforms[:3][::-1]]) bbox_sl = nirspec.compute_bounding_box(m, wrange) assert_allclose(bbox[sl], bbox_sl)
def test_functional_ifu_prism(): """Compare Nirspec instrument model with IDT model for IFU prism.""" # setup test model_file = 'ifu_prism_functional_ESA_v1_20180619.txt' hdu1 = create_nirspec_ifu_file(grating='PRISM', filter='CLEAR', gwa_xtil=0.35986012, gwa_ytil=0.13448857, gwa_tilt=37.1) im = datamodels.ImageModel(hdu1) refs = create_reference_files(im) pipeline = nirspec.create_pipeline(im, refs, slit_y_range=[-0.55, 0.55]) w = wcs.WCS(pipeline) im.meta.wcs = w slit_wcs = nirspec.nrs_wcs_set_input(im, 0) # use slice 0 ins_file = get_file_path(model_file) ins_tab = table.Table.read(ins_file, format='ascii') slitx = [0] * 5 slity = [-.5, -.25, 0, .25, .5] lam = np.array([.7e-7, 1e-6, 2e-6, 3e-6, 5e-6]) order, wrange = nirspec.get_spectral_order_wrange(im, refs['wavelengthrange']) im.meta.wcsinfo.sporder = order im.meta.wcsinfo.waverange_start = wrange[0] im.meta.wcsinfo.waverange_end = wrange[1] # Slit to MSA entrance # This includes the Slicer transform and the IFUFORE transform slit2msa = slit_wcs.get_transform('slit_frame', 'msa_frame') msax, msay, _ = slit2msa(slitx, slity, lam) assert_allclose(slitx, ins_tab['xslitpos']) assert_allclose(slity, ins_tab['yslitpos']) assert_allclose(msax + 0.0073, ins_tab['xmsapos'], rtol=1e-2) # expected offset assert_allclose(msay + 0.0085, ins_tab['ymaspos'], rtol=1e-2) # expected offset # Slicer slit2slicer = slit_wcs.get_transform('slit_frame', 'slicer') x_slicer, y_slicer, _ = slit2slicer(slitx, slity, lam) # MSA exit # Applies the IFUPOST transform to coordinates at the Slicer with datamodels.IFUPostModel(refs['ifupost']) as ifupost: ifupost_transform = nirspec._create_ifupost_transform(ifupost.slice_0) x_msa_exit, y_msa_exit = ifupost_transform(x_slicer, y_slicer, lam) assert_allclose(x_msa_exit, ins_tab['xmsapos']) assert_allclose(y_msa_exit, ins_tab['ymaspos']) # Coordinates at Collimator exit # Applies the Collimator forward transform to coordinates at the MSA exit with datamodels.open(refs['collimator']) as col: colx, coly = col.model.inverse(x_msa_exit, y_msa_exit) assert_allclose(colx, ins_tab['xcoll']) assert_allclose(coly, ins_tab['ycoll']) # After applying direcitonal cosines dircos = trmodels.Unitless2DirCos() xcolDircosi, ycolDircosi, z = dircos(colx, coly) assert_allclose(xcolDircosi, ins_tab['xcolDirCosi']) assert_allclose(ycolDircosi, ins_tab['ycolDirCosi']) # Slit to GWA entrance # applies the Collimator forward, Unitless to Directional and 3D Rotation to MSA exit coordinates with datamodels.DisperserModel(refs['disperser']) as disp: disperser = nirspec.correct_tilt(disp, im.meta.instrument.gwa_xtilt, im.meta.instrument.gwa_ytilt) collimator2gwa = nirspec.collimator_to_gwa(refs, disperser) x_gwa_in, y_gwa_in, z_gwa_in = collimator2gwa(x_msa_exit, y_msa_exit) assert_allclose(x_gwa_in, ins_tab['xdispIn']) # Slit to GWA out # Runs slit--> slicer --> msa_exit --> collimator --> dircos --> rotation --> angle_from_grating equation slit2gwa = slit_wcs.get_transform('slit_frame', 'gwa') x_gwa_out, y_gwa_out, z_gwa_out = slit2gwa(slitx, slity, lam) assert_allclose(x_gwa_out, ins_tab['xdispLaw']) assert_allclose(y_gwa_out, ins_tab['ydispLaw']) # CAMERA entrance (assuming direction is from sky to detector) angles = [ disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y'] ] rotation = trmodels.Rotation3DToGWA(angles, axes_order="xyzy", name='rotation') dircos2unitless = trmodels.DirCos2Unitless() gwa2cam = rotation.inverse | dircos2unitless x_camera_entrance, y_camera_entrance = gwa2cam(x_gwa_out, y_gwa_out, z_gwa_out) assert_allclose(x_camera_entrance, ins_tab['xcamCosi']) assert_allclose(y_camera_entrance, ins_tab['ycamCosi']) # at FPA with datamodels.CameraModel(refs['camera']) as camera: x_fpa, y_fpa = camera.model.inverse(x_camera_entrance, y_camera_entrance) assert_allclose(x_fpa, ins_tab['xfpapos']) assert_allclose(y_fpa, ins_tab['yfpapos']) # at SCA slit2sca = slit_wcs.get_transform('slit_frame', 'sca') x_sca_nrs1, y_sca_nrs1 = slit2sca(slitx, slity, lam) # At NRS2 with datamodels.FPAModel(refs['fpa']) as fpa: x_sca_nrs2, y_sca_nrs2 = fpa.nrs2_model.inverse(x_fpa, y_fpa) assert_allclose(x_sca_nrs1 + 1, ins_tab['i']) assert_allclose(y_sca_nrs1 + 1, ins_tab['j']) # at oteip # Goes through slicer, ifufore, and fore transforms slit2oteip = slit_wcs.get_transform('slit_frame', 'oteip') x_oteip, y_oteip, _ = slit2oteip(slitx, slity, lam) assert_allclose(x_oteip, ins_tab['xOTEIP']) assert_allclose(y_oteip, ins_tab['yOTEIP']) # at v2, v3 [in arcsec] slit2v23 = slit_wcs.get_transform('slit_frame', 'v2v3') v2, v3, _ = slit2v23(slitx, slity, lam) v2 /= 3600 v3 /= 3600 assert_allclose(v2, ins_tab['xV2V3']) assert_allclose(v3, ins_tab['yV2V3'])
def test_functional_ifu_grating(): """Compare Nirspec instrument model with IDT model for IFU grating.""" # setup test model_file = 'ifu_grating_functional_ESA_v1_20180619.txt' hdul = create_nirspec_ifu_file(grating='G395H', filter='F290LP', gwa_xtil=0.35986012, gwa_ytil=0.13448857) im = datamodels.ImageModel(hdul) refs = create_reference_files(im) pipeline = nirspec.create_pipeline(im, refs, slit_y_range=[-0.55, 0.55]) w = wcs.WCS(pipeline) im.meta.wcs = w slit_wcs = nirspec.nrs_wcs_set_input(im, 0) # use slice 0 ins_file = get_file_path(model_file) ins_tab = table.Table.read(ins_file, format='ascii') slitx = [0] * 5 slity = [-.5, -.25, 0, .25, .5] lam = np.array([2.9, 3.39, 3.88, 4.37, 5]) * 10**-6 order, wrange = nirspec.get_spectral_order_wrange(im, refs['wavelengthrange']) im.meta.wcsinfo.sporder = order im.meta.wcsinfo.waverange_start = wrange[0] im.meta.wcsinfo.waverange_end = wrange[1] # Slit to MSA entrance # This includes the Slicer transform and the IFUFORE transform slit2msa = slit_wcs.get_transform('slit_frame', 'msa_frame') msax, msay, _ = slit2msa(slitx, slity, lam) assert_allclose(slitx, ins_tab['xslitpos']) assert_allclose(slity, ins_tab['yslitpos']) assert_allclose(msax + 0.0073, ins_tab['xmsapos'], rtol=1e-2) # expected offset assert_allclose(msay + 0.0085, ins_tab['ymaspos'], rtol=1e-2) # expected offset # Slicer slit2slicer = slit_wcs.get_transform('slit_frame', 'slicer') x_slicer, y_slicer, _ = slit2slicer(slitx, slity, lam) # MSA exit # Applies the IFUPOST transform to coordinates at the Slicer with datamodels.IFUPostModel(refs['ifupost']) as ifupost: ifupost_transform = nirspec._create_ifupost_transform(ifupost.slice_0) x_msa_exit, y_msa_exit = ifupost_transform(x_slicer, y_slicer, lam) assert_allclose(x_msa_exit, ins_tab['xmsapos']) assert_allclose(y_msa_exit, ins_tab['ymaspos']) # Computations are done using the eact form of the equations in the reports # Part I of the Forward IFU-POST transform - the linear transform xc_out = 0.0487158154447 yc_out = 0.00856211956976 xc_in = 0.000355277216 yc_in = -3.0089012e-05 theta = np.deg2rad(-0.129043957046) factor_x = 0.100989874454 factor_y = 0.100405184145 # Slicer coordinates xS = 0.000399999989895 yS = -0.00600000005215 x = xc_out + factor_x * (+cos(theta) * (xS - xc_in) + sin(theta) * (yS - yc_in)) y = yc_out + factor_y * (-sin(theta) * (xS - xc_in) + cos(theta) * (yS - yc_in)) # Forward IFU-POST II part - non-linear transform lam = 2.9e-6 coef_names = [ f'c{x}_{y}' for x in range(6) for y in range(6) if x + y <= 5 ] y_forw = [ -82.3492267824, 29234.6982762, -540260.780853, 771881.305018, -2563462.26848, 29914272.1164, 4513.04082605, -2212869.44311, 32875633.0303, -29923698.5288, 27293902.5636, -39820.4434726, 62431493.9962, -667197265.033, 297253538.182, -1838860.86305, -777169857.2, 4514693865.7, 42790637.764, 3596423850.94, -260274017.448 ] y_forw_dist = [ 188531839.97, -43453434864.0, 70807756765.8, -308272809909.0, 159768473071.0, 9712633344590.0, -11762923852.9, 3545938873190.0, -4198643655420.0, 12545642983100.0, -11707051591600.0, 173091230285.0, -108534069056000.0, 82893348097600.0, -124708740989000.0, 2774389757990.0, 1476779720300000.0, -545358301961000.0, -93101557994100.0, -7536890639430000.0, 646310545048000.0 ] y_coeff = {} for i, coef in enumerate(coef_names): y_coeff[coef] = y_forw[i] + lam * y_forw_dist[i] poly2d = astmodels.Polynomial2D(5, **y_coeff) ifupost_y = poly2d(x, y) assert_allclose(ifupost_y, ins_tab['ymaspos'][0]) assert_allclose(ifupost_y, y_msa_exit[0]) # reset 'lam' lam = np.array([2.9, 3.39, 3.88, 4.37, 5]) * 10**-6 # Coordinates at Collimator exit # Applies the Collimator forward transform to coordinates at the MSA exit with datamodels.open(refs['collimator']) as col: colx, coly = col.model.inverse(x_msa_exit, y_msa_exit) assert_allclose(colx, ins_tab['xcoll']) assert_allclose(coly, ins_tab['ycoll']) # After applying direcitonal cosines dircos = trmodels.Unitless2DirCos() xcolDircosi, ycolDircosi, z = dircos(colx, coly) assert_allclose(xcolDircosi, ins_tab['xcolDirCosi']) assert_allclose(ycolDircosi, ins_tab['ycolDirCosi']) # Slit to GWA entrance # applies the Collimator forward, Unitless to Directional and 3D Rotation to MSA exit coordinates with datamodels.DisperserModel(refs['disperser']) as disp: disperser = nirspec.correct_tilt(disp, im.meta.instrument.gwa_xtilt, im.meta.instrument.gwa_ytilt) collimator2gwa = nirspec.collimator_to_gwa(refs, disperser) x_gwa_in, y_gwa_in, z_gwa_in = collimator2gwa(x_msa_exit, y_msa_exit) assert_allclose(x_gwa_in, ins_tab['xdispIn']) # Slit to GWA out # Runs slit--> slicer --> msa_exit --> collimator --> dircos --> rotation --> angle_from_grating equation slit2gwa = slit_wcs.get_transform('slit_frame', 'gwa') x_gwa_out, y_gwa_out, z_gwa_out = slit2gwa(slitx, slity, lam) assert_allclose(x_gwa_out, ins_tab['xdispLaw']) assert_allclose(y_gwa_out, ins_tab['ydispLaw']) # CAMERA entrance (assuming direction is from sky to detector) angles = [ disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y'] ] rotation = trmodels.Rotation3DToGWA(angles, axes_order="xyzy", name='rotation') dircos2unitless = trmodels.DirCos2Unitless() gwa2cam = rotation.inverse | dircos2unitless x_camera_entrance, y_camera_entrance = gwa2cam(x_gwa_out, y_gwa_out, z_gwa_out) assert_allclose(x_camera_entrance, ins_tab['xcamCosi']) assert_allclose(y_camera_entrance, ins_tab['ycamCosi']) # at FPA with datamodels.CameraModel(refs['camera']) as camera: x_fpa, y_fpa = camera.model.inverse(x_camera_entrance, y_camera_entrance) assert_allclose(x_fpa, ins_tab['xfpapos']) assert_allclose(y_fpa, ins_tab['yfpapos']) # at SCA slit2sca = slit_wcs.get_transform('slit_frame', 'sca') x_sca_nrs1, y_sca_nrs1 = slit2sca(slitx, slity, lam) # At NRS2 with datamodels.FPAModel(refs['fpa']) as fpa: x_sca_nrs2, y_sca_nrs2 = fpa.nrs2_model.inverse(x_fpa, y_fpa) assert_allclose(x_sca_nrs1[:3] + 1, ins_tab['i'][:3]) assert_allclose(y_sca_nrs1[:3] + 1, ins_tab['j'][:3]) assert_allclose(x_sca_nrs2[3:] + 1, ins_tab['i'][3:]) assert_allclose(y_sca_nrs2[3:] + 1, ins_tab['j'][3:]) # at oteip # Goes through slicer, ifufore, and fore transforms slit2oteip = slit_wcs.get_transform('slit_frame', 'oteip') x_oteip, y_oteip, _ = slit2oteip(slitx, slity, lam) assert_allclose(x_oteip, ins_tab['xOTEIP']) assert_allclose(y_oteip, ins_tab['yOTEIP']) # at v2, v3 [in arcsec] slit2v23 = slit_wcs.get_transform('slit_frame', 'v2v3') v2, v3, _ = slit2v23(slitx, slity, lam) v2 /= 3600 v3 /= 3600 assert_allclose(v2, ins_tab['xV2V3']) assert_allclose(v3, ins_tab['yV2V3'])
def test_functional_fs_msa(mode): # """ # Compare Nirspec instrument model with IDT model for FS and MSA. # """ if mode == 'fs': model_file = 'fixed_slits_functional_ESA_v4_20180618.txt' hdul = create_nirspec_fs_file(grating='G395H', filter='F290LP') im = datamodels.ImageModel(hdul) refs = create_reference_files(im) pipeline = nirspec.create_pipeline(im, refs, slit_y_range=[-0.55, 0.55]) w = wcs.WCS(pipeline) im.meta.wcs = w # Use slit S200A1 slit_wcs = nirspec.nrs_wcs_set_input(im, 'S200A1') if mode == 'msa': model_file = 'msa_functional_ESA_v2_20180620.txt' hdul = create_nirspec_mos_file(grating='G395H', filt='F290LP') im = datamodels.ImageModel(hdul) refs = create_reference_files(im) slit = trmodels.Slit(name=1, shutter_id=4699, xcen=319, ycen=13, ymin=-0.55000000000000004, ymax=0.55000000000000004, quadrant=3, source_id=1, shutter_state='x', source_name='lamp', source_alias='foo', stellarity=100.0, source_xpos=-0.5, source_ypos=0.5) open_slits = [slit] pipeline = nirspec.slitlets_wcs(im, refs, open_slits) w = wcs.WCS(pipeline) im.meta.wcs = w slit_wcs = nirspec.nrs_wcs_set_input(im, 1) ins_file = get_file_path(model_file) ins_tab = table.Table.read(ins_file, format='ascii') # Setup the test slitx = [0] * 5 slity = [-.5, -.25, 0, .25, .5] lam = np.array([2.9, 3.39, 3.88, 4.37, 5]) * 10**-6 # Slit to MSA absolute slit2msa = slit_wcs.get_transform('slit_frame', 'msa_frame') msax, msay, _ = slit2msa(slitx, slity, lam) assert_allclose(slitx, ins_tab['xslitpos']) assert_allclose(slity, ins_tab['yslitpos']) assert_allclose(msax, ins_tab['xmsapos']) assert_allclose(msay, ins_tab['ymaspos']) # Coordinates at Collimator exit # Applies the Collimator forward transform to MSa absolute coordinates with datamodels.open(refs['collimator']) as col: colx, coly = col.model.inverse(msax, msay) assert_allclose(colx, ins_tab['xcoll']) assert_allclose(coly, ins_tab['ycoll']) # After applying direcitonal cosines dircos = trmodels.Unitless2DirCos() xcolDircosi, ycolDircosi, z = dircos(colx, coly) assert_allclose(xcolDircosi, ins_tab['xcolDirCosi']) assert_allclose(ycolDircosi, ins_tab['ycolDirCosi']) # MSA to GWA entrance # This runs the Collimator forward, Unitless to Directional cosine, and # 3D Rotation. It uses the corrected GWA tilt value with datamodels.DisperserModel(refs['disperser']) as disp: disperser = nirspec.correct_tilt(disp, im.meta.instrument.gwa_xtilt, im.meta.instrument.gwa_ytilt) collimator2gwa = nirspec.collimator_to_gwa(refs, disperser) x_gwa_in, y_gwa_in, z_gwa_in = collimator2gwa(msax, msay) assert_allclose(x_gwa_in, ins_tab['xdispIn']) assert_allclose(y_gwa_in, ins_tab['ydispIn']) # Slit to GWA out slit2gwa = slit_wcs.get_transform('slit_frame', 'gwa') x_gwa_out, y_gwa_out, z_gwa_out = slit2gwa(slitx, slity, lam) assert_allclose(x_gwa_out, ins_tab['xdispLaw']) assert_allclose(y_gwa_out, ins_tab['ydispLaw']) # CAMERA entrance (assuming direction is from sky to detector) angles = [ disperser['theta_x'], disperser['theta_y'], disperser['theta_z'], disperser['tilt_y'] ] rotation = trmodels.Rotation3DToGWA(angles, axes_order="xyzy", name='rotation') dircos2unitless = trmodels.DirCos2Unitless() gwa2cam = rotation.inverse | dircos2unitless x_camera_entrance, y_camera_entrance = gwa2cam(x_gwa_out, y_gwa_out, z_gwa_out) assert_allclose(x_camera_entrance, ins_tab['xcamCosi']) assert_allclose(y_camera_entrance, ins_tab['ycamCosi']) # at FPA with datamodels.CameraModel(refs['camera']) as camera: x_fpa, y_fpa = camera.model.inverse(x_camera_entrance, y_camera_entrance) assert_allclose(x_fpa, ins_tab['xfpapos']) assert_allclose(y_fpa, ins_tab['yfpapos']) # at SCA These are 0-based , the IDT results are 1-based slit2sca = slit_wcs.get_transform('slit_frame', 'sca') x_sca_nrs1, y_sca_nrs1 = slit2sca(slitx, slity, lam) # At NRS2 with datamodels.FPAModel(refs['fpa']) as fpa: x_sca_nrs2, y_sca_nrs2 = fpa.nrs2_model.inverse(x_fpa, y_fpa) # expect 1 pix difference wvlns_on_nrs1 = slice(2) wvlns_on_nrs2 = slice(2, 4) assert_allclose(x_sca_nrs1[wvlns_on_nrs1] + 1, ins_tab['i'][wvlns_on_nrs1]) assert_allclose(y_sca_nrs1[wvlns_on_nrs1] + 1, ins_tab['j'][wvlns_on_nrs1]) assert_allclose(x_sca_nrs2[wvlns_on_nrs2] + 1, ins_tab['i'][wvlns_on_nrs2]) assert_allclose(y_sca_nrs2[wvlns_on_nrs2] + 1, ins_tab['j'][wvlns_on_nrs2]) # at oteip slit2oteip = slit_wcs.get_transform('slit_frame', 'oteip') x_oteip, y_oteip, _ = slit2oteip(slitx, slity, lam) assert_allclose(x_oteip, ins_tab['xOTEIP']) assert_allclose(y_oteip, ins_tab['yOTEIP']) # at v2, v3 [in arcsec] slit2v23 = slit_wcs.get_transform('slit_frame', 'v2v3') v2, v3, _ = slit2v23(slitx, slity, lam) v2 /= 3600 v3 /= 3600 assert_allclose(v2, ins_tab['xV2V3']) assert_allclose(v3, ins_tab['yV2V3'])
def __init__(self, spectrum=None, spectral_axis=None, wcs=None, **kwargs): # This handles cases where arithmetic is being performed, and an # object is created that's just a number if not isinstance(spectrum, (AstroData, NDData)): super().__init__(spectrum, spectral_axis=spectral_axis, wcs=wcs, **kwargs) return if isinstance(spectrum, AstroData) and not spectrum.is_single: raise TypeError("Input spectrum must be a single AstroData slice") # Unit handling try: # for NDData-like flux_unit = spectrum.unit except AttributeError: try: # for AstroData flux_unit = u.Unit(spectrum.hdr.get('BUNIT')) except (TypeError, ValueError): # unknown/missing flux_unit = None if flux_unit is None: flux_unit = u.dimensionless_unscaled try: kwargs['mask'] = spectrum.mask except AttributeError: flux = spectrum else: flux = spectrum.data kwargs['uncertainty'] = spectrum.uncertainty # If spectrum was a Quantity, it already has units so we'd better # not multiply them in again! if not isinstance(flux, u.Quantity): flux *= flux_unit # If no wavelength information is included, get it from the input if spectral_axis is None and wcs is None: if isinstance(spectrum, AstroData): if spectrum.wcs is not None: wcs = spectrum.wcs else: spec_unit = u.Unit(spectrum.hdr.get('CUNIT1', 'nm')) try: wavecal = dict( zip(spectrum.WAVECAL["name"], spectrum.WAVECAL["coefficients"])) except (AttributeError, KeyError): # make a Model from the FITS WCS info det2wave = (models.Shift(1 - spectrum.hdr['CRPIX1']) | models.Scale(spectrum.hdr['CD1_1']) | models.Shift(spectrum.hdr['CRVAL1'])) else: det2wave = am.dict_to_chebyshev(wavecal) det2wave.inverse = am.make_inverse_chebyshev1d( det2wave, sampling=1) spec_unit = u.nm detector_frame = cf.CoordinateFrame(1, axes_type='SPATIAL', axes_order=(0, ), unit=u.pix, axes_names='x') spec_frame = cf.SpectralFrame(unit=spec_unit, name='lambda') wcs = gWCS.WCS([(detector_frame, det2wave), (spec_frame, None)]) else: wcs = spectrum.wcs # from an NDData-like object super().__init__(flux=flux, spectral_axis=spectral_axis, wcs=wcs, **kwargs) self.filename = getattr(spectrum, 'filename', None)
def make_gwcs(shape, galactic=False): """ Create a simple celestial gWCS object in the ICRS coordinate frame. This function requires the `gwcs <https://github.com/spacetelescope/gwcs>`_ package. Parameters ---------- shape : 2-tuple of int The shape of the 2D array to be used with the output `~gwcs.wcs.WCS` object. galactic : bool, optional If `True`, then the output WCS will be in the Galactic coordinate frame. If `False` (default), then the output WCS will be in the ICRS coordinate frame. Returns ------- wcs : `gwcs.wcs.WCS` object The generalized world coordinate system (WCS) transformation. See Also -------- make_wcs, make_imagehdu Notes ----- The `make_wcs` function returns an equivalent WCS transformation to this one, but as an `astropy.wcs.WCS` object. Examples -------- >>> from photutils.datasets import make_gwcs >>> shape = (100, 100) >>> gwcs = make_gwcs(shape) >>> print(gwcs) From Transform -------- ---------------- detector linear_transform icrs None """ from gwcs import wcs as gwcs_wcs from gwcs import coordinate_frames as cf rho = np.pi / 3. scale = 0.1 / 3600. # 0.1 arcsec/pixel in deg/pix shift_by_crpix = (models.Shift((-shape[1] / 2) + 1) & models.Shift((-shape[0] / 2) + 1)) cd_matrix = np.array([[-scale * np.cos(rho), scale * np.sin(rho)], [scale * np.sin(rho), scale * np.cos(rho)]]) rotation = models.AffineTransformation2D(cd_matrix, translation=[0, 0]) rotation.inverse = models.AffineTransformation2D(np.linalg.inv(cd_matrix), translation=[0, 0]) tan = models.Pix2Sky_TAN() celestial_rotation = models.RotateNative2Celestial(197.8925, -1.36555556, 180.0) 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)) if galactic: sky_frame = cf.CelestialFrame(reference_frame=coord.Galactic(), name='galactic', unit=(u.deg, u.deg)) else: sky_frame = cf.CelestialFrame(reference_frame=coord.ICRS(), name='icrs', unit=(u.deg, u.deg)) pipeline = [(detector_frame, det2sky), (sky_frame, None)] return gwcs_wcs.WCS(pipeline)
def convert_wcs(fitswcs): ''' Accepts an astropy.wcs wcs object (based on the FITS standard). Returns the GWCS equivalent WCS object. ''' # this first version only handles non distorted ra,dec tangent projections # check that it is that case radesys_dict = { 'ICRS': coord.ICRS, 'FK5': coord.FK5, 'FK4': coord.FK4, } projection_dict = { 'TAN': projections.Pix2Sky_TAN(), 'SIN': projections.Pix2Sky_SIN() } fctypes = fitswcs.wcs.ctype fcrval = fitswcs.wcs.crval fcrpix = fitswcs.wcs.crpix if fitswcs.naxis != 2: raise ValueError("currently only handles 2d images") print(fctypes) ptypes = [ct[5:8] for ct in fctypes] for ptype in ptypes: print(ptype) if ptype not in ['TAN', 'SIN']: raise ValueError("currently only supports TAN and SIN projections") tptype = ptype # temporary since this part is only for celestial coordinates if fitswcs.cpdis1 or fitswcs.cpdis2: ### error here raise ValueError("currently doesn't support distortion") # Check for SIP correction fsip = fitswcs.sip if fsip: sipa = Polynomial2D(fsip.a_order) sipb = Polynomial2D(fsip.b_order) assign_coefficients(sipa, fsip.a) assign_coefficients(sipb, fsip.b) # now the inverse, if it exists if fsip.ap_order and fsip.bp_order: sipap = Polynomial2D(fsip.ap_order) sipbp = Polynomial2D(fsip.bp_order) assign_coefficients(sipap, fsip.ap) assign_coefficients(sipbp, fsip.bp) else: sipap = None siptrans = Identity(2) + (Mapping((0, 1, 0, 1)) | (sipa & sipb)) if sipap: siptrans.inverse = Identity(2) + (Mapping( (0, 1, 0, 1)) | (sipap & sipbp)) # construct transformation if fitswcs.wcs.has_cd(): trans1 = (Shift(-fcrpix[0]) & Shift(-fcrpix[1])) trans2 = (projections.AffineTransformation2D(fitswcs.wcs.cd) | projection_dict[tptype] | rotations.RotateNative2Celestial( fcrval[0], fcrval[1], 180.)) elif fitswcs.wcs.has_pc(): trans1 = (Shift(-fcrpix[0]) & Shift(-fcrpix[1])) pcmatrix = np.array(fitswcs.wcs.cdelt) * fitswcs.wcs.pc trans2 = (projections.AffineTransformation2D(pcmatrix) | projection_dict[tptype] | rotations.RotateNative2Celestial( fcrval[0], fcrval[1], 180.)) else: cdelt = fitswcs.wcs.cdelt crota2 = fitswcs.wcs.crota[1] * np.pi / 180 # unware of any crota1 case pscale_ratio = cdelt[1] / cdelt[0] pcmatrix = np.array( [[np.cos(crota2) * cdelt[0], -np.sin(crota2) * cdelt[1]], [np.sin(crota2) * cdelt[0], np.cos(crota2) * cdelt[1]]]) trans1 = (Shift(-fcrpix[0]) & Shift(-fcrpix[1])) trans2 = (projections.AffineTransformation2D(pcmatrix) | projection_dict[tptype] | rotations.RotateNative2Celestial( fcrval[0], fcrval[1], 180.)) if fsip: trans = trans1 | siptrans | trans2 else: trans = trans1 | trans2 detector_frame = cf.Frame2D(name="detector", axes_names=('x', 'y'), unit=(u.pix, u.pix)) # Now see if a standard frame is referenced. if fitswcs.wcs.radesys: if fitswcs.wcs.radesys in radesys_dict: reference_frame = radesys_dict[fitswcs.wcs.radesys]() sky_frame = cf.CelestialFrame(reference_frame=reference_frame, name=fitswcs.wcs.radesys.lower()) else: sky_frame = '' # or None? wcsobj = ggwcs.WCS(forward_transform=trans, input_frame=detector_frame, output_frame=sky_frame) return wcsobj
def create_wcsobj(hdul): im = ImageModel(hdul) ref = get_reference_files(im) pipeline = niriss.create_pipeline(im, ref) wcsobj = wcs.WCS(pipeline) return wcsobj
def wcs_append(wcs_obj, forward_transform, output_frame): pipeline = [(getattr(wcs_obj, f) or f, m) for f, m in wcs_obj.pipeline] pipeline[-1] = (pipeline[-1][0], forward_transform) pipeline.append((output_frame, None)) return wcs.WCS(pipeline)
shift = models.Shift(-1. * u.pix) & models.Shift(-2. * u.pix) #shift = models.Chebyshev2D(2, 2) #shift = models.Polynomial2D(2, 2) detector_frame = cf.Frame2D(name="detector", axes_names=("x", "y"), unit=(u.pix, u.pix)) sky_frame = cf.CelestialFrame(reference_frame=coord.ICRS(), name='icrs', unit=(u.deg, u.deg)) pipeline = [(detector_frame, shift), (sky_frame, None)] wcsobj = wcs.WCS(pipeline) tree = {"wcs": wcsobj} #fa = fits_embed.AsdfInFits(hdul, tree) #fa = fits_embed.AsdfInFits(fits.HDUList(), tree) #fa.write_to('test.fits') af = AsdfFile(tree) fd = io.BytesIO() #af._write_tree(tree, fd, pad_blocks=False) af.write_to(fd) fd.seek(0) wcsbytes = fd.read() fd.close()