コード例 #1
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)])
コード例 #2
0
def identity_gwcs():
    """
    A simple 1-1 gwcs that converts from pixels to arcseconds

    Note this WCS does not have a correct axis correlation matrix.
    """
    identity = m.Multiply(1 * u.arcsec / u.pixel) & m.Multiply(
        1 * u.arcsec / 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.lat",
                             "custom:pos.helioprojective.lon"))
    detector_frame = cf.CoordinateFrame(name="detector",
                                        naxes=2,
                                        axes_order=(0, 1),
                                        axes_type=("pixel", "pixel"),
                                        axes_names=("x", "y"),
                                        unit=(u.pix, u.pix))
    wcs = gwcs.wcs.WCS(forward_transform=identity,
                       output_frame=sky_frame,
                       input_frame=detector_frame)
    wcs.pixel_shape = (10, 20)
    wcs.array_shape = wcs.pixel_shape[::-1]
    return wcs
コード例 #3
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
コード例 #4
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
コード例 #5
0
ファイル: pointing.py プロジェクト: kmacdonald-stsci/jwst
def create_fitswcs(inp, input_frame=None):
    if isinstance(inp, DataModel):
        wcsinfo = wcsinfo_from_model(inp)
        wavetable = None
        spatial_axes, spectral_axes, unknown = gwutils.get_axes(wcsinfo)
        if spectral_axes:
            sp_axis = spectral_axes[0]
            if wcsinfo['CTYPE'][sp_axis] == 'WAVE-TAB':
                wavetable = inp.wavetable
        transform = fitswcs_transform_from_model(wcsinfo, wavetable=wavetable)
        output_frame = frame_from_model(wcsinfo)
    else:
        raise TypeError(
            "Input is expected to be a DataModel instance or a FITS file.")

    if input_frame is None:
        wcsaxes = wcsinfo['WCSAXES']
        if wcsaxes == 2:
            input_frame = cf.Frame2D(name="detector")
        elif wcsaxes == 3:
            input_frame = cf.CoordinateFrame(
                name="detector",
                naxes=3,
                axes_order=(0, 1, 2),
                unit=(u.pix, u.pix, u.pix),
                axes_type=["SPATIAL", "SPATIAL", "SPECTRAL"],
                axes_names=('x', 'y', 'z'),
                axis_physical_types=None)
        else:
            raise TypeError(
                f"WCSAXES is expected to be 2 or 3, instead it is {wcsaxes}")
    pipeline = [(input_frame, transform), (output_frame, None)]

    wcsobj = wcs.WCS(pipeline)
    return wcsobj
コード例 #6
0
def build_pixel_frame(header):
    """
    Given a header, build the input
    `gwcs.coordinate_frames.CoordinateFrame` object describing the pixel frame.

    Parameters
    ----------

    header : `dict`
        A fits header.

    Returns
    -------

    pixel_frame : `gwcs.coordinate_frames.CoordinateFrame`
        The pixel frame.
    """
    axes_types = [header[f'DTYPE{n}'] for n in range(1, header['DNAXIS'] + 1)]

    return cf.CoordinateFrame(naxes=header['DNAXIS'],
                              axes_type=axes_types,
                              axes_order=range(header['DNAXIS']),
                              unit=[u.pixel] * header['DNAXIS'],
                              axes_names=[
                                  header[f'DPNAME{n}']
                                  for n in range(1, header['DNAXIS'] + 1)
                              ],
                              name='pixel')
コード例 #7
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)
コード例 #8
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)
コード例 #9
0
def _generate_generic_frame(naxes, unit, names=None, physical_types=None):
    """
    Generate a simple frame, where all axes have the same type and unit.
    """
    axes_order = tuple(range(naxes))

    name = None
    axes_type = "CUSTOM"

    if isinstance(unit, (u.Unit, u.IrreducibleUnit, u.CompositeUnit)):
        unit = tuple([unit] * naxes)

    if all([u.m.is_equivalent(un) for un in unit]):
        axes_type = "SPATIAL"

    if all([u.pix.is_equivalent(un) for un in unit]):
        name = "PixelFrame"
        axes_type = "PIXEL"

    axes_type = tuple([axes_type] * naxes)

    return cf.CoordinateFrame(naxes,
                              axes_type,
                              axes_order,
                              unit=unit,
                              axes_names=names,
                              name=name,
                              axis_physical_types=physical_types)
コード例 #10
0
ファイル: wcs_wrappers.py プロジェクト: teuben/specutils
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
コード例 #11
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)
コード例 #12
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
コード例 #13
0
ファイル: test_api.py プロジェクト: mcara/gwcs
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"})
コード例 #14
0
ファイル: wcs_utils.py プロジェクト: rosteen/specutils
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
コード例 #15
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)
コード例 #16
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
コード例 #17
0
def identity_gwcs():
    """
    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)
    sky_frame = cf.CelestialFrame(
        axes_order=(0, 1),
        name='helioprojective',
        reference_frame=Helioprojective(obstime="2018-01-01"))
    detector_frame = cf.CoordinateFrame(name="detector",
                                        naxes=2,
                                        axes_order=(0, 1),
                                        axes_type=("pixel", "pixel"),
                                        axes_names=("x", "y"),
                                        unit=(u.pix, u.pix))
    return gwcs.wcs.WCS(forward_transform=identity,
                        output_frame=sky_frame,
                        input_frame=detector_frame)
コード例 #18
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)
コード例 #19
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
コード例 #20
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
コード例 #21
0
ファイル: wcs.py プロジェクト: DBerke/DRAGONS
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.
    """
    # 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
    wcs_info = read_wcs_from_header(hdr)

    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 = wcs_info["CUNIT"][i]
        try:
            unit = u.Unit(unit_name)
        except TypeError:
            unit = None
        try:
            frame_type = output[:4].upper()
            frame_info = frame_mapping[frame_type]
        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)
        else:
            frame = frame_info.cls(axes_order=(i, ),
                                   unit=unit,
                                   axes_names=(frame_type, ),
                                   name=frame_info.description)

        out_frames.append(frame)

    if coordinate_outputs.issubset(outputs):
        frame_name = wcs_info["RADESYS"]  # FK5, etc.
        axes_names = None
        try:
            ref_frame = getattr(coord, frame_name)()
            # TODO? Work out how to stuff EQUINOX and OBS-TIME into the frame
        except (AttributeError, TypeError):
            # TODO: Replace quick fix as gWCS doesn't recognize GAPPT
            if frame_name == "GAPPT":
                ref_frame = coord.FK5()
            else:
                ref_frame = None
                axes_names = ('lon', 'lat')
        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_names=axes_names,
                                      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)])
コード例 #22
0
ファイル: test_fits.py プロジェクト: astrochun/DRAGONS
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.)
コード例 #23
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.
    """

    input_frame = cf.CoordinateFrame(naxes=1,
                                     axes_type=("SPATIAL", ),
                                     axes_order=(0, ),
                                     unit=(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', ))
    world = cf.CompositeFrame([sky, spec], name='world')

    pixel = np.arange(len(wavelength), dtype=np.float)
    tab = Mapping((0, 0, 0)) | \
          Const1D(ra) & Const1D(dec) & Tabular1D(points=pixel,
                                                 lookup_table=wavelength,
                                                 bounds_error=False,
                                                 fill_value=None)
    tab.name = "pixel_to_world"

    if all(np.diff(wavelength) > 0):
        tab.inverse = Mapping((2, )) | Tabular1D(
            points=wavelength,
            lookup_table=pixel,
            bounds_error=False,
        )
    elif all(np.diff(wavelength) < 0):
        tab.inverse = Mapping((2, )) | Tabular1D(
            points=wavelength[::-1],
            lookup_table=pixel[::-1],
            bounds_error=False,
        )
    else:
        log.warning(
            "Wavelengths are not strictly monotonic, inverse transform is not set"
        )

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

    return WCS(pipeline)
コード例 #24
0
ファイル: spectral.py プロジェクト: b1quint/DRAGONS
    def __init__(self, spectrum=None, spectral_axis=None, wcs=None, **kwargs):
        # This handles cases where arithmetic is being performed, and an
        # object is created that's just a number
        if not isinstance(spectrum, (AstroData, NDData)):
            super().__init__(spectrum,
                             spectral_axis=spectral_axis,
                             wcs=wcs,
                             **kwargs)
            return

        if isinstance(spectrum, AstroData) and not spectrum.is_single:
            raise TypeError("Input spectrum must be a single AstroData slice")

        # Unit handling
        try:  # for NDData-like
            flux_unit = spectrum.unit
        except AttributeError:
            try:  # for AstroData
                flux_unit = u.Unit(spectrum.hdr.get('BUNIT'))
            except (TypeError, ValueError):  # unknown/missing
                flux_unit = None
        if flux_unit is None:
            flux_unit = u.dimensionless_unscaled
        try:
            kwargs['mask'] = spectrum.mask
        except AttributeError:
            flux = spectrum
        else:
            flux = spectrum.data
            kwargs['uncertainty'] = spectrum.uncertainty

        # If spectrum was a Quantity, it already has units so we'd better
        # not multiply them in again!
        if not isinstance(flux, u.Quantity):
            flux *= flux_unit

        # If no wavelength information is included, get it from the input
        if spectral_axis is None and wcs is None:
            if isinstance(spectrum, AstroData):
                if spectrum.wcs is not None:
                    wcs = spectrum.wcs
                else:
                    spec_unit = u.Unit(spectrum.hdr.get('CUNIT1', 'nm'))
                    try:
                        wavecal = dict(
                            zip(spectrum.WAVECAL["name"],
                                spectrum.WAVECAL["coefficients"]))
                    except (AttributeError,
                            KeyError):  # make a Model from the FITS WCS info
                        det2wave = (models.Shift(1 - spectrum.hdr['CRPIX1'])
                                    | models.Scale(spectrum.hdr['CD1_1'])
                                    | models.Shift(spectrum.hdr['CRVAL1']))
                    else:
                        det2wave = am.dict_to_chebyshev(wavecal)
                        det2wave.inverse = am.make_inverse_chebyshev1d(
                            det2wave, sampling=1)
                        spec_unit = u.nm
                    detector_frame = cf.CoordinateFrame(1,
                                                        axes_type='SPATIAL',
                                                        axes_order=(0, ),
                                                        unit=u.pix,
                                                        axes_names='x')
                    spec_frame = cf.SpectralFrame(unit=spec_unit,
                                                  name='lambda')
                    wcs = gWCS.WCS([(detector_frame, det2wave),
                                    (spec_frame, None)])
            else:
                wcs = spectrum.wcs  # from an NDData-like object

        super().__init__(flux=flux,
                         spectral_axis=spectral_axis,
                         wcs=wcs,
                         **kwargs)
        self.filename = getattr(spectrum, 'filename', None)
コード例 #25
0
ファイル: generate_aia_dataset.py プロジェクト: DKISTDC/dkist
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))
コード例 #26
0
def main():
    path = Path('~/Git/DKIST/dkist/dkist/data/test/EIT').expanduser()
    files = glob.glob(str(path / '*.fits'))

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

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

    headers = []

    for i, filepath in enumerate(files):
        with fits.open(filepath) as hdul:
            header = hdul[0].header
            headers.append(dict(header))
        time = parse_time(header['DATE-OBS'])
        if i == 0:
            start_time = time
        inds.append(i)
        times.append(time)
        seconds.append((time - start_time).to(u.s))

    # Extract a list of coordinates in time and wavelength
    # this assumes all wavelength images are taken at the same time
    time_coords = np.array([str(t.isot) for t in times])

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

    timemodel = LookupTable(lookup_table=seconds * u.s)

    hcubemodel = spatial & timemodel

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

    sky_frame = cf.CompositeFrame([sky_frame, time_frame], name="world")
    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=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(files, relative_to=str(path))

    tree = {
        'wcs':
        wcs,
        'data':
        ea,
        'headers':
        table_from_headers(headers),
        'meta':
        generate_datset_inventory_from_headers(headers,
                                               "eit_test_dataset.asdf")
    }

    with asdf.AsdfFile(tree) as ff:
        filename = path / "eit_test_dataset.asdf"
        ff.write_to(filename)
        print("Saved to : {}".format(filename))