示例#1
0
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
示例#2
0
def ifu(input_model, reference_files):
    """
    Create the WCS pipeline for a MIRI IFU observation.
    Goes from 0-indexed detector pixels (0,0) middle of lower left reference pixel
    to V2,V3 in arcsec.

    Parameters
    ----------
    input_model : `jwst.datamodels.ImagingModel`
        Data model.
    reference_files : dict
        Dictionary {reftype: reference file name}.
    """

    #reference_files = {'distortion': 'jwst_miri_distortion_00001.asdf', #files must hold 2 channels each
    #'specwcs': 'jwst_miri_specwcs_00001.asdf',
    #'regions': 'jwst_miri_regions_00001.asdf',
    #'wavelengthrange': 'jwst_miri_wavelengthrange_0001.asdf'}
    # Define reference frames
    detector = cf.Frame2D(name='detector',
                          axes_order=(0, 1),
                          unit=(u.pix, u.pix))
    alpha_beta = cf.Frame2D(name='alpha_beta_spatial',
                            axes_order=(0, 1),
                            unit=(u.arcsec, u.arcsec),
                            axes_names=('alpha', 'beta'))
    spec_local = cf.SpectralFrame(name='alpha_beta_spectral',
                                  axes_order=(2, ),
                                  unit=(u.micron, ),
                                  axes_names=('lambda', ))
    miri_focal = cf.CompositeFrame([alpha_beta, spec_local], name='alpha_beta')
    v23_spatial = cf.Frame2D(name='V2_V3_spatial',
                             axes_order=(0, 1),
                             unit=(u.deg, u.deg),
                             axes_names=('v2', 'v3'))
    spec = cf.SpectralFrame(name='spectral',
                            axes_order=(2, ),
                            unit=(u.micron, ),
                            axes_names=('lambda', ))
    v2v3 = cf.CompositeFrame([v23_spatial, spec], name='v2v3')
    icrs = cf.CelestialFrame(name='icrs',
                             reference_frame=coord.ICRS(),
                             axes_order=(0, 1),
                             unit=(u.deg, u.deg),
                             axes_names=('RA', 'DEC'))
    world = cf.CompositeFrame([icrs, spec], name='world')

    # Define the actual transforms
    det2abl = (detector_to_abl(input_model,
                               reference_files)).rename("detector_to_abl")
    abl2v2v3l = (abl_to_v2v3l(input_model,
                              reference_files)).rename("abl_to_v2v3l")
    tel2sky = pointing.v23tosky(input_model) & models.Identity(1)

    # Put the transforms together into a single transform
    shape = input_model.data.shape
    det2abl.bounding_box = ((-0.5, shape[0] - 0.5), (-0.5, shape[1] - 0.5))
    pipeline = [(detector, det2abl), (miri_focal, abl2v2v3l), (v2v3, tel2sky),
                (world, None)]
    return pipeline
示例#3
0
文件: miri.py 项目: jaytmiller/jwst
def ifu(input_model, reference_files):
    """
    The MIRI MRS WCS pipeline.

    It has the following coordinate frames:
    "detector", "alpha_beta", "v2v3", "world".

    It uses the "distortion", "regions", "specwcs"
    and "wavelengthrange" reference files.
    """
    # Define coordinate frames.
    detector = cf.Frame2D(name='detector',
                          axes_order=(0, 1),
                          unit=(u.pix, u.pix))
    alpha_beta = cf.Frame2D(name='alpha_beta_spatial',
                            axes_order=(0, 1),
                            unit=(u.arcsec, u.arcsec),
                            axes_names=('alpha', 'beta'))
    spec_local = cf.SpectralFrame(name='alpha_beta_spectral',
                                  axes_order=(2, ),
                                  unit=(u.micron, ),
                                  axes_names=('lambda', ))
    miri_focal = cf.CompositeFrame([alpha_beta, spec_local], name='alpha_beta')
    v23_spatial = cf.Frame2D(name='V2_V3_spatial',
                             axes_order=(0, 1),
                             unit=(u.arcsec, u.arcsec),
                             axes_names=('v2', 'v3'))
    spec = cf.SpectralFrame(name='spectral',
                            axes_order=(2, ),
                            unit=(u.micron, ),
                            axes_names=('lambda', ))
    v2v3 = cf.CompositeFrame([v23_spatial, spec], name='v2v3')
    icrs = cf.CelestialFrame(name='icrs',
                             reference_frame=coord.ICRS(),
                             axes_order=(0, 1),
                             unit=(u.deg, u.deg),
                             axes_names=('RA', 'DEC'))
    world = cf.CompositeFrame([icrs, spec], name='world')

    # Define the actual transforms
    det2abl = (detector_to_abl(input_model,
                               reference_files)).rename("detector_to_abl")
    abl2v2v3l = (abl_to_v2v3l(input_model,
                              reference_files)).rename("abl_to_v2v3l")

    tel2sky = pointing.v23tosky(input_model) & models.Identity(1)

    # Put the transforms together into a single transform
    shape = input_model.data.shape
    det2abl.bounding_box = ((-0.5, shape[0] - 0.5), (-0.5, shape[1] - 0.5))
    pipeline = [(detector, det2abl), (miri_focal, abl2v2v3l), (v2v3, tel2sky),
                (world, None)]
    return pipeline
示例#4
0
文件: niriss.py 项目: sosey/jwst
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)
示例#5
0
def gwcs_from_array(array):
    """
    Create a new WCS from provided tabular data. This defaults to being
    a GWCS object.
    """
    array = u.Quantity(array)

    coord_frame = cf.CoordinateFrame(naxes=1,
                                     axes_type=('SPECTRAL', ),
                                     axes_order=(0, ))
    spec_frame = cf.SpectralFrame(unit=array.unit, axes_order=(0, ))

    # In order for the world_to_pixel transformation to automatically convert
    # input units, the equivalencies in the look up table have to be extended
    # with spectral unit information.
    SpectralTabular1D = type(
        "SpectralTabular1D", (Tabular1D, ),
        {'input_units_equivalencies': {
            'x0': u.spectral()
        }})

    forward_transform = SpectralTabular1D(np.arange(len(array)),
                                          lookup_table=array)
    forward_transform.inverse = SpectralTabular1D(array,
                                                  lookup_table=np.arange(
                                                      len(array)))

    tabular_gwcs = GWCS(forward_transform=forward_transform,
                        input_frame=coord_frame,
                        output_frame=spec_frame)

    return tabular_gwcs
示例#6
0
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)
示例#7
0
def identity_gwcs_4d():
    """
    A simple 1-1 gwcs that converts from pixels to arcseconds
    """
    identity = (m.Multiply(1 * u.arcsec / u.pixel)
                & m.Multiply(1 * u.arcsec / u.pixel)
                & m.Multiply(1 * u.nm / u.pixel)
                & m.Multiply(1 * u.nm / u.pixel))
    sky_frame = cf.CelestialFrame(
        axes_order=(0, 1),
        name='helioprojective',
        reference_frame=Helioprojective(obstime="2018-01-01"))
    wave_frame = cf.SpectralFrame(axes_order=(2, ), unit=u.nm)
    time_frame = cf.TemporalFrame(axes_order=(3, ), unit=u.s)

    frame = cf.CompositeFrame([sky_frame, wave_frame, time_frame])

    detector_frame = cf.CoordinateFrame(name="detector",
                                        naxes=4,
                                        axes_order=(0, 1, 2, 3),
                                        axes_type=("pixel", "pixel", "pixel",
                                                   "pixel"),
                                        axes_names=("x", "y", "z", "s"),
                                        unit=(u.pix, u.pix, u.pix, u.pix))

    return gwcs.wcs.WCS(forward_transform=identity,
                        output_frame=frame,
                        input_frame=detector_frame)
示例#8
0
def identity_gwcs_3d():
    """
    A simple 1-1 gwcs that converts from pixels to arcseconds
    """
    identity = (TwoDScale(1 * u.arcsec / u.pixel)
                & m.Multiply(1 * u.nm / u.pixel))

    sky_frame = cf.CelestialFrame(
        axes_order=(0, 1),
        name='helioprojective',
        reference_frame=Helioprojective(obstime="2018-01-01"),
        axes_names=("longitude", "latitude"),
        unit=(u.arcsec, u.arcsec),
        axis_physical_types=("custom:pos.helioprojective.lon",
                             "custom:pos.helioprojective.lat"))
    wave_frame = cf.SpectralFrame(axes_order=(2, ),
                                  unit=u.nm,
                                  axes_names=("wavelength", ))

    frame = cf.CompositeFrame([sky_frame, wave_frame])

    detector_frame = cf.CoordinateFrame(name="detector",
                                        naxes=3,
                                        axes_order=(0, 1, 2),
                                        axes_type=("pixel", "pixel", "pixel"),
                                        axes_names=("x", "y", "z"),
                                        unit=(u.pix, u.pix, u.pix))

    wcs = gwcs.wcs.WCS(forward_transform=identity,
                       output_frame=frame,
                       input_frame=detector_frame)
    wcs.pixel_shape = (10, 20, 30)
    wcs.array_shape = wcs.pixel_shape[::-1]

    return wcs
    def _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
示例#10
0
def create_coord_frames():
    gdetector = cf.Frame2D(name='grism_detector',
                           axes_order=(0, 1),
                           unit=(u.pix, u.pix))
    detector = cf.Frame2D(name='full_detector',
                          axes_order=(0, 1),
                          axes_names=('dx', 'dy'),
                          unit=(u.pix, u.pix))
    v2v3_spatial = cf.Frame2D(name='v2v3_spatial',
                              axes_order=(0, 1),
                              axes_names=('v2', 'v3'),
                              unit=(u.deg, u.deg))
    v2v3vacorr_spatial = cf.Frame2D(name='v2v3vacorr_spatial',
                                    axes_order=(0, 1),
                                    axes_names=('v2', 'v3'),
                                    unit=(u.arcsec, u.arcsec))
    sky_frame = cf.CelestialFrame(reference_frame=coord.ICRS(), name='icrs')
    spec = cf.SpectralFrame(name='spectral',
                            axes_order=(2, ),
                            unit=(u.micron, ),
                            axes_names=('wavelength', ))
    frames = {
        'grism_detector':
        gdetector,
        'direct_image':
        cf.CompositeFrame([detector, spec], name='direct_image'),
        'v2v3':
        cf.CompositeFrame([v2v3_spatial, spec], name='v2v3'),
        'v2v3vacorr':
        cf.CompositeFrame([v2v3vacorr_spatial, spec], name='v2v3vacorr'),
        'world':
        cf.CompositeFrame([sky_frame, spec], name='world')
    }
    return frames
示例#11
0
文件: nirspec.py 项目: sosey/jwst
def create_frames():
    """
    Create the coordinate frames in the NIRSPEC WCS pipeline.

    These are
    "detector", "gwa", "slit_frame", "msa_frame", "oteip", "v2v3", "world".
    """
    det = cf.Frame2D(name='detector', axes_order=(0, 1))
    sca = cf.Frame2D(name='sca', axes_order=(0, 1))
    gwa = cf.Frame2D(name="gwa", axes_order=(0, 1), unit=(u.rad, u.rad),
                      axes_names=('alpha_in', 'beta_in'))
    msa_spatial = cf.Frame2D(name='msa_spatial', axes_order=(0, 1), unit=(u.m, u.m),
                             axes_names=('x_msa', 'y_msa'))
    slit_spatial = cf.Frame2D(name='slit_spatial', axes_order=(0, 1), unit=("", ""),
                             axes_names=('x_slit', 'y_slit'))
    sky = cf.CelestialFrame(name='sky', axes_order=(0, 1), reference_frame=coord.ICRS())
    v2v3_spatial = cf.Frame2D(name='v2v3_spatial', axes_order=(0, 1), unit=(u.deg, u.deg),
                             axes_names=('V2', 'V3'))

    # The oteip_to_v23 incorporates a scale to convert the spectral units from
    # meters to microns.  So the v2v3 output frame will be in u.deg, u.deg, u.micron
    spec = cf.SpectralFrame(name='spectral', axes_order=(2,), unit=(u.micron,),
                            axes_names=('wavelength',))
    v2v3 = cf.CompositeFrame([v2v3_spatial, spec], name='v2v3')
    slit_frame = cf.CompositeFrame([slit_spatial, spec], name='slit_frame')
    msa_frame = cf.CompositeFrame([msa_spatial, spec], name='msa_frame')
    oteip_spatial = cf.Frame2D(name='oteip', axes_order=(0, 1), unit=(u.deg, u.deg),
                               axes_names=('X_OTEIP', 'Y_OTEIP'))
    oteip = cf.CompositeFrame([oteip_spatial, spec], name='oteip')
    world = cf.CompositeFrame([sky, spec], name='world')
    return det, sca, gwa, slit_frame, msa_frame, oteip, v2v3, world
示例#12
0
def lrs(input_model, reference_files):
    """
    The LRS-FIXEDSLIT and LRS-SLITLESS WCS pipeline.

    Notes
    -----
    It includes three coordinate frames -
    "detector", "v2v3" and "world".
    "v2v3" and "world" each have (spatial, spatial, spectral) components.

    Uses the "specwcs" and "distortion" reference files.

    """
    # Define the various coordinate frames.
    # Original detector frame
    detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix))
    # Spectral component
    spec = cf.SpectralFrame(name='spec', axes_order=(2,), unit=(u.micron,), axes_names=('lambda',))
    # v2v3 spatial component
    v2v3_spatial = cf.Frame2D(name='v2v3_spatial', axes_order=(0, 1), unit=(u.arcsec, u.arcsec),
                              axes_names=('v2', 'v3'))
    v2v3vacorr_spatial = cf.Frame2D(
        name='v2v3vacorr_spatial',
        axes_order=(0, 1),
        unit=(u.arcsec, u.arcsec),
        axes_names=('v2', 'v3')
    )

    # v2v3 spatial+spectra
    v2v3 = cf.CompositeFrame([v2v3_spatial, spec], name='v2v3')
    v2v3vacorr = cf.CompositeFrame([v2v3vacorr_spatial, spec], name='v2v3vacorr')

    # 'icrs' frame which is the spatial sky component
    icrs = cf.CelestialFrame(name='icrs', reference_frame=coord.ICRS(),
                             axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('RA', 'DEC'))
    # Final 'world' composite frame with spatial and spectral components
    world = cf.CompositeFrame(name="world", frames=[icrs, spec])

    # Create the transforms
    dettotel = lrs_distortion(input_model, reference_files)
    v2v3tosky = pointing.v23tosky(input_model)
    teltosky = v2v3tosky & models.Identity(1)

    # Compute differential velocity aberration (DVA) correction:
    va_corr = pointing.dva_corr_model(
        va_scale=input_model.meta.velocity_aberration.scale_factor,
        v2_ref=input_model.meta.wcsinfo.v2_ref,
        v3_ref=input_model.meta.wcsinfo.v3_ref
    ) & models.Identity(1)

    # Put the transforms together into a single pipeline
    pipeline = [(detector, dettotel),
                (v2v3, va_corr),
                (v2v3vacorr, teltosky),
                (world, None)]

    return pipeline
示例#13
0
def tabular_wcs(xarray):

    coordinateframe = cf.CoordinateFrame(naxes=1, axes_type=('SPECTRAL',),
                                         axes_order=(0,))
    specframe = cf.SpectralFrame(unit=xarray.unit, axes_order=(0,))
    transform = Tabular1D(np.arange(len(xarray)), xarray.value)

    tabular_gwcs = gwcs.wcs.WCS([(coordinateframe, transform), (specframe, None)])

    return tabular_gwcs
示例#14
0
def test_composite_frame(tmpdir):
    icrs = coord.ICRS()
    fk5 = coord.FK5()
    cel1 = cf.CelestialFrame(reference_frame=icrs)
    cel2 = cf.CelestialFrame(reference_frame=fk5)

    spec1 = cf.SpectralFrame(name='freq', unit=[
        u.Hz,
    ], axes_order=(2, ))
    spec2 = cf.SpectralFrame(name='wave', unit=[
        u.m,
    ], axes_order=(2, ))

    comp1 = cf.CompositeFrame([cel1, spec1])
    comp2 = cf.CompositeFrame([cel2, spec2])
    comp = cf.CompositeFrame(
        [comp1, cf.SpectralFrame(axes_order=(3, ), unit=(u.m, ))])

    tree = {'comp1': comp1, 'comp2': comp2, 'comp': comp}

    helpers.assert_roundtrip_tree(tree, tmpdir)
示例#15
0
def gwcs_1d():
    detector_frame = cf.CoordinateFrame(
        name="detector",
        naxes=1,
        axes_order=(0, ),
        axes_type=("pixel"),
        axes_names=("x"),
        unit=(u.pix))

    spec_frame = cf.SpectralFrame(name="spectral", axes_order=(2, ), unit=u.nm)

    return WCS(forward_transform=Identity(1), input_frame=detector_frame, output_frame=spec_frame)
示例#16
0
def frame_from_model(wcsinfo):
    """
    Initialize a coordinate frame based on values in model.meta.wcsinfo.

    Parameters
    ----------
    wcsinfo : `~stdatamodels.DataModel` or dict
        Either one of the JWST data models or a dict with model.meta.wcsinfo.

    Returns
    -------
    frame : `~coordinate_frames.CoordinateFrame`

    """
    if isinstance(wcsinfo, DataModel):
        wcsinfo = wcsinfo_from_model(wcsinfo)

    wcsaxes = wcsinfo['WCSAXES']
    celestial_axes, spectral_axes, other = gwutils.get_axes(wcsinfo)
    cunit = wcsinfo['CUNIT']
    frames = []
    if celestial_axes:
        ref_frame = coords.ICRS()
        celestial = cf.CelestialFrame(name='sky',
                                      axes_order=tuple(celestial_axes),
                                      reference_frame=ref_frame,
                                      unit=cunit[celestial_axes],
                                      axes_names=('RA', 'DEC'))
        frames.append(celestial)
    if spectral_axes:
        spec = cf.SpectralFrame(name='spectral',
                                axes_order=tuple(spectral_axes),
                                unit=cunit[spectral_axes],
                                axes_names=('wavelength', ))
        frames.append(spec)
    if other:
        # Make sure these are strings and not np.str_ objects.
        axes_names = tuple([str(name) for name in wcsinfo['CTYPE'][other]])
        name = "_".join(wcsinfo['CTYPE'][other])
        spatial = cf.Frame2D(name=name,
                             axes_order=tuple(other),
                             unit=cunit[other],
                             axes_names=axes_names)
        frames.append(spatial)
    if wcsaxes == 2:
        return frames[0]
    elif wcsaxes == 3:
        world = cf.CompositeFrame(frames, name='world')
        return world
    else:
        raise ValueError("WCSAXES can be 2 or 3, got {0}".format(wcsaxes))
示例#17
0
def gwcs_from_array(array):
    """
    Create a new WCS from provided tabular data. This defaults to being
    a GWCS object.
    """
    orig_array = u.Quantity(array)

    # TODO: Input arrays must be strictly ascending. This is not always the
    #  case for a spectral axis (e.g. when in frequency space). Thus, we
    #  convert to wavelength to create the wcs.
    if orig_array.unit.physical_type != 'length' and \
            orig_array.unit.is_equivalent(u.AA, equivalencies=u.spectral()):
        array = orig_array.to(u.AA, equivalencies=u.spectral())

    coord_frame = cf.CoordinateFrame(naxes=1,
                                     axes_type=('SPECTRAL', ),
                                     axes_order=(0, ))
    spec_frame = cf.SpectralFrame(unit=array.unit, axes_order=(0, ))

    # In order for the world_to_pixel transformation to automatically convert
    # input units, the equivalencies in the look up table have to be extended
    # with spectral unit information.
    SpectralTabular1D = type(
        "SpectralTabular1D", (Tabular1D, ),
        {'input_units_equivalencies': {
            'x0': u.spectral()
        }})

    forward_transform = SpectralTabular1D(np.arange(len(array)),
                                          lookup_table=array)
    forward_transform.inverse = SpectralTabular1D(array,
                                                  lookup_table=np.arange(
                                                      len(array)))

    class SpectralGWCS(GWCS):
        def pixel_to_world(self, *args, **kwargs):
            if orig_array.unit == '':
                return u.Quantity(super().pixel_to_world_values(
                    *args, **kwargs))
            return super().pixel_to_world(*args, **kwargs).to(
                orig_array.unit, equivalencies=u.spectral())

    tabular_gwcs = SpectralGWCS(forward_transform=forward_transform,
                                input_frame=coord_frame,
                                output_frame=spec_frame)

    # Store the intended unit from the origin input array
    #     tabular_gwcs._input_unit = orig_array.unit

    return tabular_gwcs
示例#18
0
文件: miri.py 项目: nden/jwst
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
示例#19
0
def gwcs_from_array(array):
    """
    Create a new WCS from provided tabular data. This defaults to being
    a GWCS object.
    """
    orig_array = u.Quantity(array)

    coord_frame = cf.CoordinateFrame(naxes=1,
                                     axes_type=('SPECTRAL', ),
                                     axes_order=(0, ))
    spec_frame = cf.SpectralFrame(unit=array.unit, axes_order=(0, ))

    # In order for the world_to_pixel transformation to automatically convert
    # input units, the equivalencies in the look up table have to be extended
    # with spectral unit information.
    SpectralTabular1D = type(
        "SpectralTabular1D", (Tabular1D, ),
        {'input_units_equivalencies': {
            'x0': u.spectral()
        }})

    forward_transform = SpectralTabular1D(np.arange(len(array)),
                                          lookup_table=array)
    # If our spectral axis is in descending order, we have to flip the lookup
    # table to be ascending in order for world_to_pixel to work.
    if len(array) == 0 or array[-1] > array[0]:
        forward_transform.inverse = SpectralTabular1D(array,
                                                      lookup_table=np.arange(
                                                          len(array)))
    else:
        forward_transform.inverse = SpectralTabular1D(array[::-1],
                                                      lookup_table=np.arange(
                                                          len(array))[::-1])

    class SpectralGWCS(GWCS):
        def pixel_to_world(self, *args, **kwargs):
            if orig_array.unit == '':
                return u.Quantity(super().pixel_to_world_values(
                    *args, **kwargs))
            return super().pixel_to_world(*args, **kwargs).to(
                orig_array.unit, equivalencies=u.spectral())

    tabular_gwcs = SpectralGWCS(forward_transform=forward_transform,
                                input_frame=coord_frame,
                                output_frame=spec_frame)

    # Store the intended unit from the origin input array
    #     tabular_gwcs._input_unit = orig_array.unit

    return tabular_gwcs
示例#20
0
def gwcs_3d():
    detector_frame = cf.CoordinateFrame(
        name="detector",
        naxes=3,
        axes_order=(0, 1, 2),
        axes_type=("pixel", "pixel", "pixel"),
        axes_names=("x", "y", "z"),
        unit=(u.pix, u.pix, u.pix))

    sky_frame = cf.CelestialFrame(reference_frame=Helioprojective(), name='hpc')
    spec_frame = cf.SpectralFrame(name="spectral", axes_order=(2, ), unit=u.nm)
    out_frame = cf.CompositeFrame(frames=(sky_frame, spec_frame))

    return WCS(forward_transform=spatial_like_model(),
               input_frame=detector_frame, output_frame=out_frame)
示例#21
0
文件: niriss.py 项目: sosey/jwst
def niriss_soss(input_model, reference_files):
    """
    The NIRISS SOSS pipeline includes 3 coordinate frames -
    detector, focal plane and sky

    reference_files={'specwcs': 'soss_wavelengths_configuration.asdf'}
    """

    # Get the target RA and DEC, they will be used for setting the WCS RA and DEC based on a conversation
    # with Kevin Volk.
    try:
        target_ra = float(input_model['meta.target.ra'])
        target_dec = float(input_model['meta.target.dec'])
    except:
        # There was an error getting the target RA and DEC, so we are not going to continue.
        raise ValueError('Problem getting the TARG_RA or TARG_DEC from input model {}'.format(input_model))

    # Define the frames
    detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix))
    spec = cf.SpectralFrame(name='spectral', axes_order=(2,), unit=(u.micron,),
                            axes_names=('wavelength',))
    sky = cf.CelestialFrame(reference_frame=coord.ICRS(),
                            axes_names=('ra', 'dec'),
                            axes_order=(0, 1), unit=(u.deg, u.deg), name='sky')
    world = cf.CompositeFrame([sky, spec], name='world')
    try:
        with AsdfFile.open(reference_files['specwcs']) as wl:
            wl1 = wl.tree[1].copy()
            wl2 = wl.tree[2].copy()
            wl3 = wl.tree[3].copy()
    except Exception as e:
        raise IOError('Error reading wavelength correction from {}'.format(reference_files['specwcs']))

    cm_order1 = (Mapping((0, 1, 0, 1)) | (Const1D(target_ra) & Const1D(target_dec) & wl1)).rename('Order1')
    cm_order2 = (Mapping((0, 1, 0, 1)) | (Const1D(target_ra) & Const1D(target_dec) & wl2)).rename('Order2')
    cm_order3 = (Mapping((0, 1, 0, 1)) | (Const1D(target_ra) & Const1D(target_dec) & wl3)).rename('Order3')

    # Define the transforms, they should accept (x,y) and return (ra, dec, lambda)
    soss_model = NirissSOSSModel([1, 2, 3], [cm_order1, cm_order2, cm_order3]).rename('3-order SOSS Model')

    # Define the pipeline based on the frames and models above.
    pipeline = [(detector, soss_model),
                (world, None)
                ]

    return pipeline
示例#22
0
文件: spec_wcs.py 项目: zonca/jwst
def create_spectral_wcs(ra, dec, wavelength):
    """Assign a WCS for sky coordinates and a table of wavelengths

    Parameters
    ----------
    ra: float
        The right ascension (in degrees) at the nominal location of the
        entrance aperture (slit).

    dec: float
        The declination (in degrees) at the nominal location of the
        entrance aperture.

    wavelength: ndarray
        The wavelength in microns at each pixel of the extracted spectrum.

    Returns:
    --------
    wcs: a gwcs.wcs.WCS object
        This takes a float or sequence of float and returns a tuple of
        the right ascension, declination, and wavelength (or sequence of
        wavelengths) at the pixel(s) specified by the input argument.
    """

    # Only the first coordinate is used.
    input_frame = cf.Frame2D(axes_order=(0, 1),
                             unit=(u.pix, u.pix),
                             name="pixel_frame")

    sky = cf.CelestialFrame(name='sky',
                            axes_order=(0, 1),
                            reference_frame=coord.ICRS())
    spec = cf.SpectralFrame(name='spectral',
                            axes_order=(2, ),
                            unit=(u.micron, ),
                            axes_names=('wavelength', ))

    pixel = np.arange(len(wavelength), dtype=np.float)
    tab = Mapping((0, 0, 0)) | \
          Const1D(ra) & Const1D(dec) & Tabular1D(pixel, wavelength)

    world = cf.CompositeFrame([sky, spec], name='world')

    pipeline = [(input_frame, tab), (world, None)]

    return WCS(pipeline)
示例#23
0
    def _create_fake_data(object_name):
        from astropy.table import Table
        astrofaker = pytest.importorskip('astrofaker')

        wavelength, flux = _get_spectrophotometric_data(object_name)

        wavecal = {
            'degree': 1,
            'domain': [0., wavelength.size - 1],
            'c0': wavelength.mean(),
            'c1': wavelength.mean() / 2,
        }
        wave_model = models.Chebyshev1D(**wavecal)
        wave_model.inverse = astromodels.make_inverse_chebyshev1d(
            wave_model, rms=0.01, max_deviation=0.03)

        hdu = fits.ImageHDU()
        hdu.header['CCDSUM'] = "1 1"
        hdu.data = flux[np.newaxis, :]  # astrofaker needs 2D data

        _ad = astrofaker.create('GMOS-S')
        _ad.add_extension(hdu, pixel_scale=1.0)

        _ad[0].data = _ad[0].data.ravel()
        _ad[0].mask = np.zeros(_ad[0].data.size,
                               dtype=np.uint16)  # ToDo Requires mask
        _ad[0].variance = np.ones_like(_ad[0].data)  # ToDo Requires Variance
        in_frame = cf.CoordinateFrame(naxes=1,
                                      axes_type=['SPATIAL'],
                                      axes_order=(0, ),
                                      unit=u.pix,
                                      axes_names=('x', ),
                                      name='pixels')
        out_frame = cf.SpectralFrame(unit=u.nm, name='world')
        _ad[0].wcs = gWCS([(in_frame, wave_model), (out_frame, None)])

        _ad[0].hdr.set('NAXIS', 1)
        _ad[0].phu.set('OBJECT', object_name)
        _ad[0].phu.set('EXPTIME', 1.)
        _ad[0].hdr.set('BUNIT', "electron")

        assert _ad.object() == object_name
        assert _ad.exposure_time() == 1

        return _ad
示例#24
0
    def from_array(array):
        """
        Create a new WCS from provided tabular data. This defaults to being
        a GWCS object.
        """
        array = u.Quantity(array)

        coord_frame = cf.CoordinateFrame(naxes=1,
                                         axes_type=('SPECTRAL', ),
                                         axes_order=(0, ))
        spec_frame = cf.SpectralFrame(unit=array.unit, axes_order=(0, ))
        forward_transform = Tabular1D(np.arange(len(array)), array.value)
        forward_transform.inverse = Tabular1D(array.value,
                                              np.arange(len(array)))

        tabular_gwcs = gwcs.wcs.WCS(forward_transform=forward_transform,
                                    input_frame=coord_frame,
                                    output_frame=spec_frame)

        return WCSWrapper(wcs=tabular_gwcs)
示例#25
0
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)
示例#26
0
def frame_from_model(wcsinfo):
    wcsaxes = wcsinfo['WCSAXES']
    spatial_axes, spectral_axes = gwutils.get_axes(wcsinfo)
    cunit = wcsinfo['CUNIT']
    ref_frame = coords.ICRS()
    sky = cf.CelestialFrame(name='sky',
                            axes_order=tuple(spatial_axes),
                            reference_frame=ref_frame,
                            unit=cunit[spatial_axes],
                            axes_names=('RA', 'DEC'))
    if wcsaxes == 2:
        return sky
    elif wcsaxes == 3:
        spec = cf.SpectralFrame(name='spectral',
                                axes_order=tuple(spectral_axes),
                                unit=cunit[spectral_axes[0]],
                                axes_names=('wavelength', ))
        world = cf.CompositeFrame([sky, spec], name='world')
        return world
    else:
        raise ValueError("WCSAXES can be 2 or 3, got {0}".format(wcsaxes))
示例#27
0
def create_frames():
    """
    Create the coordinate frames in the NIRSPEC WCS pipeline.

    These are
    "detector", "gwa", "slit_frame", "msa_frame", "oteip", "v2v3", "world".
    """
    det = cf.Frame2D(name='detector', axes_order=(0, 1))
    gwa = cf.Frame2D(name="gwa",
                     axes_order=(0, 1),
                     unit=(u.rad, u.rad),
                     axes_names=('alpha_in', 'beta_in'))
    msa_spatial = cf.Frame2D(name='msa_spatial',
                             axes_order=(0, 1),
                             unit=(u.m, u.m),
                             axes_names=('x_msa', 'y_msa'))
    slit_spatial = cf.Frame2D(name='slit_spatial',
                              axes_order=(0, 1),
                              unit=("", ""),
                              axes_names=('x_slit', 'y_slit'))
    #sky = cf.CelestialFrame(name='sky', axes_order=(0, 1), reference_frame=coord.ICRS())
    spec = cf.SpectralFrame(name='spectral',
                            axes_order=(2, ),
                            unit=(u.m, ),
                            axes_names=('wavelength', ))
    v2v3_spatial = cf.Frame2D(name='V2V3_spatial',
                              axes_order=(0, 1),
                              unit=(u.arcsec, u.arcsec),
                              axes_names=('V2', 'V3'))
    v2v3 = cf.CompositeFrame([v2v3_spatial, spec], name='v2v3')
    slit_frame = cf.CompositeFrame([slit_spatial, spec], name='slit_frame')
    msa_frame = cf.CompositeFrame([msa_spatial, spec], name='msa_frame')
    oteip_spatial = cf.Frame2D(name='OTEIP_spatial',
                               axes_order=(0, 1),
                               unit=(u.arcsec, u.arcsec),
                               axes_names=('X_OTEIP', 'Y_OTEIP'))
    oteip = cf.CompositeFrame([oteip_spatial, spec], name='oteip')
    #world = cf.CompositeFrame([sky, spec], name='world')
    return det, gwa, slit_frame, msa_frame, oteip, v2v3
示例#28
0
def identity_gwcs_4d():
    """
    A simple 1-1 gwcs that converts from pixels to arcseconds
    """
    identity = (TwoDScale(1 * u.arcsec / u.pixel)
                & m.Multiply(1 * u.nm / u.pixel)
                & m.Multiply(1 * u.s / u.pixel))
    sky_frame = cf.CelestialFrame(
        axes_order=(0, 1),
        name='helioprojective',
        reference_frame=Helioprojective(obstime="2018-01-01"),
        unit=(u.arcsec, u.arcsec),
        axis_physical_types=("custom:pos.helioprojective.lon",
                             "custom:pos.helioprojective.lat"))
    wave_frame = cf.SpectralFrame(axes_order=(2, ), unit=u.nm)
    time_frame = cf.TemporalFrame(Time("2020-01-01T00:00",
                                       format="isot",
                                       scale="utc"),
                                  axes_order=(3, ),
                                  unit=u.s)

    frame = cf.CompositeFrame([sky_frame, wave_frame, time_frame])

    detector_frame = cf.CoordinateFrame(name="detector",
                                        naxes=4,
                                        axes_order=(0, 1, 2, 3),
                                        axes_type=("pixel", "pixel", "pixel",
                                                   "pixel"),
                                        axes_names=("x", "y", "z", "s"),
                                        unit=(u.pix, u.pix, u.pix, u.pix))

    wcs = gwcs.wcs.WCS(forward_transform=identity,
                       output_frame=frame,
                       input_frame=detector_frame)
    wcs.pixel_shape = (10, 20, 30, 40)
    wcs.array_shape = wcs.pixel_shape[::-1]

    return wcs
示例#29
0
    def make_spectral(self):
        """
        Decide how to make a spectral axes.
        """
        name = self.header[f'DWNAME{self.n}']
        self._frames.append(
            cf.SpectralFrame(axes_order=(self._i, ),
                             axes_names=(name, ),
                             unit=self.get_units(self._i),
                             name=name))

        if "WAVE" in self.header.get(f'CTYPE{self.n}', ''):
            transform = self.make_spectral_from_wcs()
        elif "FRAMEWAV" in self.header.keys():
            transform = self.make_spectral_from_dataset()
        else:
            raise ValueError(
                "Could not parse spectral WCS information from this header."
            )  # pragma: no cover

        self._transforms.append(transform)

        self._i += 1
示例#30
0
    def build_interpolated_output_wcs(self, refmodel=None):
        """
        Create a spatial/spectral WCS output frame using all the input models

        Creates output frame by linearly fitting RA, Dec along the slit and
        producing a lookup table to interpolate wavelengths in the dispersion
        direction.

        Parameters
        ----------
        refmodel : `~jwst.datamodels.DataModel`
            The reference input image from which the fiducial WCS is created.
            If not specified, the first image in self.input_models is used.

        Returns
        -------
        output_wcs : `~gwcs.WCS` object
            A gwcs WCS object defining the output frame WCS
        """

        # for each input model convert slit x,y to ra,dec,lam
        # use first input model to set spatial scale
        # use center of appended ra and dec arrays to set up
        # center of final ra,dec
        # append all ra,dec, wavelength array for each slit
        # use first model to initialize wavelenth array
        # append wavelengths that fall outside the endpoint of
        # of wavelength array when looping over additional data

        all_wavelength = []
        all_ra_slit = []
        all_dec_slit = []

        for im, model in enumerate(self.input_models):
            wcs = model.meta.wcs
            bb = wcs.bounding_box
            grid = wcstools.grid_from_bounding_box(bb)
            ra, dec, lam = np.array(wcs(*grid))
            spectral_axis = find_dispersion_axis(model)
            spatial_axis = spectral_axis ^ 1

            # Compute the wavelength array, trimming NaNs from the ends
            # In many cases, a whole slice is NaNs, so ignore those warnings
            warnings.simplefilter("ignore")
            wavelength_array = np.nanmedian(lam, axis=spectral_axis)
            warnings.resetwarnings()
            wavelength_array = wavelength_array[~np.isnan(wavelength_array)]

            # We need to estimate the spatial sampling to use for the output WCS.
            # Tt is assumed the spatial sampling is the same for all the input
            # models. So we can use the first input model to set the spatial
            # sampling.

            # Steps to do this for first input model:
            # 1. find the middle of the spectrum in wavelength
            # 2. Pull out the ra and dec at the center of the slit.
            # 3. Find the mean ra,dec and the center of the slit this will
            #    represent the tangent point
            # 4. Convert ra,dec -> tangent plane projection: x_tan,y_tan
            # 5. using x_tan, y_tan perform a linear fit to find spatial sampling
            # first input model sets intializes wavelength array and defines
            # the spatial scale of the output wcs
            if im == 0:
                for iw in wavelength_array:
                    all_wavelength.append(iw)

                lam_center_index = int(
                    (bb[spectral_axis][1] - bb[spectral_axis][0]) / 2)
                if spatial_axis == 0:
                    ra_center = ra[lam_center_index, :]
                    dec_center = dec[lam_center_index, :]
                else:
                    ra_center = ra[:, lam_center_index]
                    dec_center = dec[:, lam_center_index]
                # find the ra and dec for this slit using center of slit
                ra_center_pt = np.nanmean(ra_center)
                dec_center_pt = np.nanmean(dec_center)

                if resample_utils.is_sky_like(model.meta.wcs.output_frame):
                    # convert ra and dec to tangent projection
                    tan = Pix2Sky_TAN()
                    native2celestial = RotateNative2Celestial(
                        ra_center_pt, dec_center_pt, 180)
                    undist2sky1 = tan | native2celestial
                    # Filter out RuntimeWarnings due to computed NaNs in the WCS
                    warnings.simplefilter("ignore")
                    # at this center of slit find x,y tangent projection - x_tan, y_tan
                    x_tan, y_tan = undist2sky1.inverse(ra, dec)
                    warnings.resetwarnings()
                else:
                    # for non sky-like output frames, no need to do tangent plane projections
                    # but we still use the same variables
                    x_tan, y_tan = ra, dec

                # pull out data from center
                if spectral_axis == 0:
                    x_tan_array = x_tan.T[lam_center_index]
                    y_tan_array = y_tan.T[lam_center_index]
                else:
                    x_tan_array = x_tan[lam_center_index]
                    y_tan_array = y_tan[lam_center_index]

                x_tan_array = x_tan_array[~np.isnan(x_tan_array)]
                y_tan_array = y_tan_array[~np.isnan(y_tan_array)]

                # estimate the spatial sampling
                fitter = LinearLSQFitter()
                fit_model = Linear1D()
                xstop = x_tan_array.shape[0] / self.pscale_ratio
                xstep = 1 / self.pscale_ratio
                ystop = y_tan_array.shape[0] / self.pscale_ratio
                ystep = 1 / self.pscale_ratio
                pix_to_xtan = fitter(fit_model, np.arange(0, xstop, xstep),
                                     x_tan_array)
                pix_to_ytan = fitter(fit_model, np.arange(0, ystop, ystep),
                                     y_tan_array)

            # append all ra and dec values to use later to find min and max
            # ra and dec
            ra_use = ra.flatten()
            ra_use = ra_use[~np.isnan(ra_use)]
            dec_use = dec.flatten()
            dec_use = dec_use[~np.isnan(dec_use)]
            all_ra_slit.append(ra_use)
            all_dec_slit.append(dec_use)

            # now check wavelength array to see if we need to add to it
            this_minw = np.min(wavelength_array)
            this_maxw = np.max(wavelength_array)
            all_minw = np.min(all_wavelength)
            all_maxw = np.max(all_wavelength)

            if this_minw < all_minw:
                addpts = wavelength_array[wavelength_array < all_minw]
                for ip in range(len(addpts)):
                    all_wavelength.append(addpts[ip])
            if this_maxw > all_maxw:
                addpts = wavelength_array[wavelength_array > all_maxw]
                for ip in range(len(addpts)):
                    all_wavelength.append(addpts[ip])

        # done looping over set of models

        all_ra = np.hstack(all_ra_slit)
        all_dec = np.hstack(all_dec_slit)
        all_wave = np.hstack(all_wavelength)
        all_wave = all_wave[~np.isnan(all_wave)]
        all_wave = np.sort(all_wave, axis=None)
        # Tabular interpolation model, pixels -> lambda
        wavelength_array = np.unique(all_wave)
        # Check if the data is MIRI LRS FIXED Slit. If it is then
        # the wavelength array needs to be flipped so that the resampled
        # dispersion direction matches the disperion direction on the detector.
        if self.input_models[0].meta.exposure.type == 'MIR_LRS-FIXEDSLIT':
            wavelength_array = np.flip(wavelength_array, axis=None)

        step = 1 / self.pscale_ratio
        stop = wavelength_array.shape[0] / self.pscale_ratio
        points = np.arange(0, stop, step)
        pix_to_wavelength = Tabular1D(points=points,
                                      lookup_table=wavelength_array,
                                      bounds_error=False,
                                      fill_value=None,
                                      name='pix2wavelength')

        # Tabular models need an inverse explicitly defined.
        # If the wavelength array is decending instead of ascending, both
        # points and lookup_table need to be reversed in the inverse transform
        # for scipy.interpolate to work properly
        points = wavelength_array
        lookup_table = np.arange(0, stop, step)

        if not np.all(np.diff(wavelength_array) > 0):
            points = points[::-1]
            lookup_table = lookup_table[::-1]
        pix_to_wavelength.inverse = Tabular1D(points=points,
                                              lookup_table=lookup_table,
                                              bounds_error=False,
                                              fill_value=None,
                                              name='wavelength2pix')

        # For the input mapping, duplicate the spatial coordinate
        mapping = Mapping((spatial_axis, spatial_axis, spectral_axis))

        # Sometimes the slit is perpendicular to the RA or Dec axis.
        # For example, if the slit is perpendicular to RA, that means
        # the slope of pix_to_xtan will be nearly zero, so make sure
        # mapping.inverse uses pix_to_ytan.inverse.  The auto definition
        # of mapping.inverse is to use the 2nd spatial coordinate, i.e. Dec.

        if np.isclose(pix_to_ytan.slope, 0, atol=1e-8):
            mapping_tuple = (0, 1)
            # Account for vertical or horizontal dispersion on detector
            if spatial_axis:
                mapping.inverse = Mapping(mapping_tuple[::-1])
            else:
                mapping.inverse = Mapping(mapping_tuple)

        # The final transform
        # redefine the ra, dec center tangent point to include all data

        # check if all_ra crosses 0 degress - this makes it hard to
        # define the min and max ra correctly
        all_ra = wrap_ra(all_ra)
        ra_min = np.amin(all_ra)
        ra_max = np.amax(all_ra)

        ra_center_final = (ra_max + ra_min) / 2.0
        dec_min = np.amin(all_dec)
        dec_max = np.amax(all_dec)
        dec_center_final = (dec_max + dec_min) / 2.0
        tan = Pix2Sky_TAN()
        if len(self.input_models
               ) == 1:  # single model use ra_center_pt to be consistent
            # with how resample was done before
            ra_center_final = ra_center_pt
            dec_center_final = dec_center_pt

        if resample_utils.is_sky_like(model.meta.wcs.output_frame):
            native2celestial = RotateNative2Celestial(ra_center_final,
                                                      dec_center_final, 180)
            undist2sky = tan | native2celestial
            # find the spatial size of the output - same in x,y
            x_tan_all, _ = undist2sky.inverse(all_ra, all_dec)
        else:
            x_tan_all, _ = all_ra, all_dec
        x_min = np.amin(x_tan_all)
        x_max = np.amax(x_tan_all)
        x_size = int(np.ceil((x_max - x_min) / np.absolute(pix_to_xtan.slope)))

        # single model use size of x_tan_array
        # to be consistent with method before
        if len(self.input_models) == 1:
            x_size = len(x_tan_array)

        # define the output wcs
        if resample_utils.is_sky_like(model.meta.wcs.output_frame):
            transform = mapping | (pix_to_xtan & pix_to_ytan
                                   | undist2sky) & pix_to_wavelength
        else:
            transform = mapping | (pix_to_xtan
                                   & pix_to_ytan) & pix_to_wavelength

        det = cf.Frame2D(name='detector', axes_order=(0, 1))
        if resample_utils.is_sky_like(model.meta.wcs.output_frame):
            sky = cf.CelestialFrame(name='sky',
                                    axes_order=(0, 1),
                                    reference_frame=coord.ICRS())
        else:
            sky = cf.Frame2D(
                name=f'resampled_{model.meta.wcs.output_frame.name}',
                axes_order=(0, 1))
        spec = cf.SpectralFrame(name='spectral',
                                axes_order=(2, ),
                                unit=(u.micron, ),
                                axes_names=('wavelength', ))
        world = cf.CompositeFrame([sky, spec], name='world')

        pipeline = [(det, transform), (world, None)]

        output_wcs = WCS(pipeline)

        # import ipdb; ipdb.set_trace()

        # compute the output array size in WCS axes order, i.e. (x, y)
        output_array_size = [0, 0]
        output_array_size[spectral_axis] = int(
            np.ceil(len(wavelength_array) / self.pscale_ratio))
        output_array_size[spatial_axis] = int(
            np.ceil(x_size / self.pscale_ratio))
        # turn the size into a numpy shape in (y, x) order
        self.data_size = tuple(output_array_size[::-1])
        bounding_box = resample_utils.wcs_bbox_from_shape(self.data_size)
        output_wcs.bounding_box = bounding_box

        return output_wcs