Ejemplo n.º 1
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))
    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
Ejemplo n.º 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
Ejemplo n.º 3
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
Ejemplo n.º 4
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
Ejemplo n.º 5
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
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
def fitswcs_to_gwcs(hdr):
    """
    Create and return a gWCS object from a FITS header. If it can't
    construct one, it should quietly return None.
    """
    # Type of CoordinateFrame to construct for a FITS keyword
    frame_mapping = {'WAVE': cf.SpectralFrame}
    # coordinate names for CelestialFrame
    coordinate_outputs = {'alpha_C', 'delta_C'}

    # transform = gw.make_fitswcs_transform(hdr)
    try:
        transform = make_fitswcs_transform(hdr)
    except Exception as e:
        return None
    outputs = transform.outputs

    naxes = transform.n_inputs
    axes_names = ('x', 'y', 'z', 'u', 'v', 'w')[:naxes]
    in_frame = cf.CoordinateFrame(naxes=naxes, axes_type=['SPATIAL'] * naxes,
                                  axes_order=tuple(range(naxes)), name="pixels",
                                  axes_names=axes_names, unit=[u.pix] * naxes)

    out_frames = []
    for i, output in enumerate(outputs):
        unit_name = hdr.get(f'CUNIT{i+1}')
        try:
            unit = u.Unit(unit_name)
        except TypeError:
            unit = None
        try:
            frame = frame_mapping[output[:4].upper()](axes_order=(i,), unit=unit,
                                          axes_names=(output,), name=output)
        except KeyError:
            if output in coordinate_outputs:
                continue
            frame = cf.CoordinateFrame(naxes=1, axes_type=("SPATIAL",),
                                       axes_order=(i,), unit=unit,
                                       axes_names=(output,), name=output)
        out_frames.append(frame)

    if coordinate_outputs.issubset(outputs):
        frame_name = hdr.get('RADESYS') or hdr.get('RADECSYS')  # FK5, etc.
        try:
            ref_frame = getattr(coord, frame_name)()
            # TODO? Work out how to stuff EQUINOX and OBS-TIME into the frame
        except (AttributeError, TypeError):
            ref_frame = None
        axes_order = (outputs.index('alpha_C'), outputs.index('delta_C'))

        # Call it 'world' if there are no other axes, otherwise 'sky'
        name = 'SKY' if len(outputs) > 2 else 'world'
        cel_frame = cf.CelestialFrame(reference_frame=ref_frame, name=name,
                                      axes_order=axes_order)
        out_frames.append(cel_frame)

    out_frame = (out_frames[0] if len(out_frames) == 1
                 else cf.CompositeFrame(out_frames, name='world'))
    return gWCS([(in_frame, transform),
                 (out_frame, None)])
Ejemplo n.º 8
0
    def _new_output_frame(self, axes):
        """
        remove the frames for all axes and return a new output frame.

        This method assumes axes has already been sanitized for non-separable axes.
        """
        frames = self._get_frames()
        axes_map = self._get_axes_map(frames)

        frames = list(frames)
        for axis in axes:
            drop_frame = axes_map[axis]
            # If we are removing coupled axes we might have already removed the frame
            if drop_frame in frames:
                frames.remove(drop_frame)

        # We now need to reindex the axes_order of all the frames to account
        # for any removed axes.
        for i, frame in enumerate(frames):
            if i == 0:
                start = i
            else:
                axes_order = frames[i-1].axes_order
                start = axes_order[-1]
                # Start can either be an int or a list/tuple here.
                if not isinstance(start, int):
                    start = start[-1]  # pragma: no cover  # I can't work out how to hit this.
                # Increment start for the next frame.
                start += 1
            frame._axes_order = tuple(range(start, start + frame.naxes))

        if len(frames) == 1:
            return frames[0]
        else:
            return cf.CompositeFrame(frames, name=self.gwcs.output_frame.name)
Ejemplo n.º 9
0
Archivo: niriss.py Proyecto: 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)
Ejemplo n.º 10
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)
Ejemplo n.º 11
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
Ejemplo n.º 12
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)
Ejemplo n.º 13
0
    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
Ejemplo n.º 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)
Ejemplo n.º 15
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
Ejemplo n.º 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))
Ejemplo n.º 17
0
Archivo: miri.py Proyecto: 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
Ejemplo n.º 18
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)
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
Archivo: niriss.py Proyecto: 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
Ejemplo n.º 21
0
    def frame(self):
        """
        The gWCS coordinate frame for all the lookup tables.
        """
        if len(self._table_coords) == 1:
            return self._table_coords[0].frame
        else:
            frames = [t.frame for t in self._table_coords]

            # We now have to set the axes_order of all the frames so that we
            # have one consistent WCS with the correct number of pixel
            # dimensions.
            ind = 0
            for f in frames:
                new_ind = ind + f.naxes
                f._axes_order = tuple(range(ind, new_ind))
                ind = new_ind

            return cf.CompositeFrame(frames)
Ejemplo n.º 22
0
def gwcs_from_headers(headers):
    """
    Given a list of headers build a gwcs.

    Parameters
    ----------

    headers : `list`
        A list of headers. These are expected to have already been validated.
    """
    header = headers[0]

    pixel_frame = build_pixel_frame(header)

    builder = TransformBuilder(headers)
    world_frame = cf.CompositeFrame(builder.frames)

    return gwcs.WCS(forward_transform=builder.transform,
                    input_frame=pixel_frame,
                    output_frame=world_frame)
Ejemplo n.º 23
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)
Ejemplo n.º 24
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))
Ejemplo n.º 25
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
Ejemplo n.º 26
0
def test_composite_many_base_frame():
    q_frame_1 = cf.CoordinateFrame(name='distance',
                                   axes_order=(0, ),
                                   naxes=1,
                                   axes_type="SPATIAL",
                                   unit=(u.m, ))
    q_frame_2 = cf.CoordinateFrame(name='distance',
                                   axes_order=(1, ),
                                   naxes=1,
                                   axes_type="SPATIAL",
                                   unit=(u.m, ))
    frame = cf.CompositeFrame([q_frame_1, q_frame_2])

    wao_classes = frame._world_axis_object_classes

    assert len(wao_classes) == 2
    assert not set(wao_classes.keys()).difference({"SPATIAL", "SPATIAL1"})

    wao_components = frame._world_axis_object_components

    assert len(wao_components) == 2
    assert not {c[0]
                for c in wao_components}.difference({"SPATIAL", "SPATIAL1"})
Ejemplo n.º 27
0
def identity_gwcs_5d_stokes(identity_gwcs_4d):
    stokes_frame = cf.StokesFrame(axes_order=(4, ))
    stokes_model = generate_lookup_table([0, 1, 2, 3] * u.one,
                                         interpolation='nearest')
    transform = identity_gwcs_4d.forward_transform
    frame = cf.CompositeFrame(identity_gwcs_4d.output_frame.frames +
                              [stokes_frame])

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

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

    return wcs
Ejemplo n.º 28
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
Ejemplo n.º 29
0
def test_round_trip_gwcs(tmpdir):
    """
    Add a 2-step gWCS instance to NDAstroData, save to disk, reload & compare.
    """

    from gwcs import coordinate_frames as cf
    from gwcs import WCS

    arr = np.zeros((10, 10), dtype=np.float32)
    ad1 = astrodata.create(fits.PrimaryHDU(), [fits.ImageHDU(arr, name='SCI')])

    # Transformation from detector pixels to pixels in some reference row,
    # removing relative distortions in wavelength:
    det_frame = cf.Frame2D(name='det_mosaic',
                           axes_names=('x', 'y'),
                           unit=(u.pix, u.pix))
    dref_frame = cf.Frame2D(name='dist_ref_row',
                            axes_names=('xref', 'y'),
                            unit=(u.pix, u.pix))

    # A made-up example model that looks vaguely like some real distortions:
    fdist = models.Chebyshev2D(2,
                               2,
                               c0_0=4.81125,
                               c1_0=5.43375,
                               c0_1=-0.135,
                               c1_1=-0.405,
                               c0_2=0.30375,
                               c1_2=0.91125,
                               x_domain=[0., 9.],
                               y_domain=[0., 9.])

    # This is not an accurate inverse, but will do for this test:
    idist = models.Chebyshev2D(2,
                               2,
                               c0_0=4.89062675,
                               c1_0=5.68581232,
                               c2_0=-0.00590263,
                               c0_1=0.11755526,
                               c1_1=0.35652358,
                               c2_1=-0.01193828,
                               c0_2=-0.29996306,
                               c1_2=-0.91823397,
                               c2_2=0.02390594,
                               x_domain=[-1.5, 12.],
                               y_domain=[0., 9.])

    # The resulting 2D co-ordinate mapping from detector to ref row pixels:
    distrans = models.Mapping((0, 1, 1)) | (fdist & models.Identity(1))
    distrans.inverse = models.Mapping((0, 1, 1)) | (idist & models.Identity(1))

    # Transformation from reference row pixels to linear, row-stacked spectra:
    spec_frame = cf.SpectralFrame(axes_order=(0, ),
                                  unit=u.nm,
                                  axes_names='lambda',
                                  name='wavelength')
    row_frame = cf.CoordinateFrame(1,
                                   'SPATIAL',
                                   axes_order=(1, ),
                                   unit=u.pix,
                                   axes_names='y',
                                   name='row')
    rss_frame = cf.CompositeFrame([spec_frame, row_frame])

    # Toy wavelength model & approximate inverse:
    fwcal = models.Chebyshev1D(2, c0=500.075, c1=0.05, c2=0.001, domain=[0, 9])
    iwcal = models.Chebyshev1D(2,
                               c0=4.59006292,
                               c1=4.49601817,
                               c2=-0.08989608,
                               domain=[500.026, 500.126])

    # The resulting 2D co-ordinate mapping from ref pixels to wavelength:
    wavtrans = fwcal & models.Identity(1)
    wavtrans.inverse = iwcal & models.Identity(1)

    # The complete WCS chain for these 2 transformation steps:
    ad1[0].nddata.wcs = WCS([(det_frame, distrans), (dref_frame, wavtrans),
                             (rss_frame, None)])

    # Save & re-load the AstroData instance with its new WCS attribute:
    testfile = str(tmpdir.join('round_trip_gwcs.fits'))
    ad1.write(testfile)
    ad2 = astrodata.open(testfile)

    wcs1 = ad1[0].nddata.wcs
    wcs2 = ad2[0].nddata.wcs

    # # Temporary workaround for issue #9809, to ensure the test is correct:
    # wcs2.forward_transform[1].x_domain = (0, 9)
    # wcs2.forward_transform[1].y_domain = (0, 9)
    # wcs2.forward_transform[3].domain = (0, 9)
    # wcs2.backward_transform[0].domain = (500.026, 500.126)
    # wcs2.backward_transform[3].x_domain = (-1.5, 12.)
    # wcs2.backward_transform[3].y_domain = (0, 9)

    # Did we actually get a gWCS instance back?
    assert isinstance(wcs2, WCS)

    # Do the transforms have the same number of submodels, with the same types,
    # degrees, domains & parameters? Here the inverse gets checked redundantly
    # as both backward_transform and forward_transform.inverse, but it would be
    # convoluted to ensure that both are correct otherwise (since the transforms
    # get regenerated as new compound models each time they are accessed).
    compare_models(wcs1.forward_transform, wcs2.forward_transform)
    compare_models(wcs1.backward_transform, wcs2.backward_transform)

    # Do the instances have matching co-ordinate frames?
    for f in wcs1.available_frames:
        assert repr(getattr(wcs1, f)) == repr(getattr(wcs2, f))

    # Also compare a few transformed values, as the "proof of the pudding":
    y, x = np.mgrid[0:9:2, 0:9:2]
    np.testing.assert_allclose(wcs1(x, y), wcs2(x, y), rtol=1e-7, atol=0.)

    y, w = np.mgrid[0:9:2, 500.025:500.12:0.0225]
    np.testing.assert_allclose(wcs1.invert(w, y),
                               wcs2.invert(w, y),
                               rtol=1e-7,
                               atol=0.)
Ejemplo n.º 30
0
def main():
    path = Path('~/sunpy/data/jsocflare/').expanduser()
    files = glob.glob(str(path / '*.fits'))

    # requestid = 'JSOC_20180831_1097'
    requestid = None

    if not files:
        if requestid:
            c = JSOCClient()
            filesd = c.get_request(requestid, path=str(path),
                                   overwrite=False).wait()
            files = []
            for f in filesd.values():
                files.append(f['path'])
        else:
            results = Fido.search(
                a.jsoc.Time('2017-09-06T12:00:00', '2017-09-06T12:02:00'),
                a.jsoc.Series('aia.lev1_euv_12s'), a.jsoc.Segment('image'),
                a.jsoc.Notify("*****@*****.**"))

            print(results)

            files = Fido.fetch(results, path=str(path))

    files.sort()
    files = np.array(files)

    # For each image get:
    # the index
    inds = []
    # the time
    times = []
    # the dt from the first image
    seconds = []
    # the wavelength
    waves = []

    for i, filepath in enumerate(files):
        with fits.open(filepath) as hdul:
            header = hdul[1].header
        time = parse_time(header['DATE-OBS'])
        if i == 0:
            root_header = header
            start_time = time
        inds.append(i)
        times.append(time)
        seconds.append((time - start_time).total_seconds())
        waves.append(header['WAVELNTH'])

    # Construct an array and sort it by wavelength and time
    arr = np.array((inds, seconds, waves)).T
    sorter = np.lexsort((arr[:, 1], arr[:, 2]))

    # Using this double-sorted array get the list indicies
    list_sorter = np.array(arr[sorter][:, 0], dtype=int)

    # Calculate the desired shape of the output array
    n_waves = len(list(set(waves)))
    shape = (n_waves, len(files) // n_waves)

    # Construct a 2D array of filenames
    cube = files[list_sorter].reshape(shape)

    # Extract a list of coordinates in time and wavelength
    # this assumes all wavelength images are taken at the same time
    time_coords = np.array([t.isoformat()
                            for t in times])[list_sorter].reshape(shape)[0, :]
    wave_coords = np.array(waves)[list_sorter].reshape(shape)[:, 0]

    smap0 = sunpy.map.Map(files[0])
    spatial = map_to_transform(smap0)

    timemodel = generate_lookup_table(lookup_table=seconds[:shape[1]] * u.s)
    wavemodel = generate_lookup_table(lookup_table=waves[:shape[0]] * u.AA)

    hcubemodel = spatial & timemodel & wavemodel

    wave_frame = cf.SpectralFrame(axes_order=(3, ),
                                  unit=u.AA,
                                  name="wavelength",
                                  axes_names=("wavelength", ))
    time_frame = cf.TemporalFrame(axes_order=(2, ),
                                  unit=u.s,
                                  reference_time=Time(time_coords[0]),
                                  name="time",
                                  axes_names=("time", ))
    sky_frame = cf.CelestialFrame(axes_order=(0, 1),
                                  name='helioprojective',
                                  reference_frame=smap0.coordinate_frame,
                                  axes_names=("helioprojective longitude",
                                              "helioprojective latitude"))

    sky_frame = cf.CompositeFrame([sky_frame, time_frame, wave_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", "time",
                                                    "wavelength"),
                                        unit=(u.pix, u.pix, u.pix, u.pix))

    wcs = gwcs.wcs.WCS(forward_transform=hcubemodel,
                       input_frame=detector_frame,
                       output_frame=sky_frame)

    print(repr(wcs))

    print(wcs(*[1 * u.pix] * 4, with_units=True))

    ea = references_from_filenames(cube, relative_to=str(path))

    tree = {
        'gwcs': wcs,
        'dataset': ea,
    }

    with asdf.AsdfFile(tree) as ff:
        # ff.write_to("test.asdf")
        filename = str(path / "aia_{}.asdf".format(time_coords[0]))
        ff.write_to(filename)
        print("Saved to : {}".format(filename))

    # import sys; sys.exit(0)

    from dkist.dataset import Dataset

    ds = Dataset.from_directory(str(path))
    print(repr(ds))
    print(repr(ds.wcs))
    print(ds.wcs(*[1 * u.pix] * 4, with_units=True))