Exemplo n.º 1
0
def test_spectralcoord_frame(header_spectral_frames):

    # This is a test to check the numerical results of transformations between
    # different velocity frames. We simply make sure that the returned
    # SpectralCoords are in the right frame but don't check the transformations
    # since this is already done in test_spectralcoord_accuracy
    # in astropy.coordinates.

    with iers.conf.set_temp('auto_download', False):

        obstime = Time(f"2009-05-04T04:44:23", scale='utc')

        header = header_spectral_frames.copy()
        header['MJD-OBS'] = obstime.mjd
        header['CRVAL1'] = 16.33211
        header['CRVAL2'] = -34.2221
        header['OBSGEO-L'] = 144.2
        header['OBSGEO-B'] = -20.2
        header['OBSGEO-H'] = 0.

        # We start off with a WCS defined in topocentric frequency
        with pytest.warns(FITSFixedWarning):
            wcs_topo = WCS(header)

        # We convert a single pixel coordinate to world coordinates and keep only
        # the second high level object - a SpectralCoord:
        sc_topo = wcs_topo.pixel_to_world(0, 0, 31)[1]

        # We check that this is in topocentric frame with zero velocities
        assert isinstance(sc_topo, SpectralCoord)
        assert isinstance(sc_topo.observer, ITRS)
        assert sc_topo.observer.obstime.isot == obstime.isot
        assert_equal(sc_topo.observer.data.differentials['s'].d_xyz.value, 0)

        observatory = EarthLocation.from_geodetic(
            144.2, -20.2).get_itrs(obstime=obstime).transform_to(ICRS())
        assert observatory.separation_3d(sc_topo.observer.transform_to(
            ICRS())) < 1 * u.km

        for specsys, expected_frame in VELOCITY_FRAMES.items():

            header['SPECSYS'] = specsys
            with pytest.warns(FITSFixedWarning):
                wcs = WCS(header)
            sc = wcs.pixel_to_world(0, 0, 31)[1]

            # Now transform to the expected velocity frame, which should leave
            # the spectral coordinate unchanged
            sc_check = sc.with_observer_stationary_relative_to(expected_frame)
            assert_quantity_allclose(sc.quantity, sc_check.quantity)
Exemplo n.º 2
0
def test_pixel_to_world_itrs(x_in, y_in):
    """Regression test for https://github.com/astropy/astropy/pull/9609"""
    with pytest.warns(None) as w:
        wcs = WCS({
            'NAXIS': 2,
            'CTYPE1': 'TLON-CAR',
            'CTYPE2': 'TLAT-CAR',
            'RADESYS': 'ITRS ',
            'DATE-OBS': '2017-08-17T12:41:04.444'
        })

    if Version(_wcs.__version__) >= Version('7.4'):
        assert len(w) == 1
        msg = str(w[0].message)
        assert "'datfix' made the change 'Set MJD-OBS to 57982.528524 from DATE-OBS'." in msg
    else:
        assert len(w) == 0

    # This shouldn't raise an exception.
    coord = wcs.pixel_to_world(x_in, y_in)

    # Check round trip transformation.
    x, y = wcs.world_to_pixel(coord)

    np.testing.assert_almost_equal(x, x_in)
    np.testing.assert_almost_equal(y, y_in)
Exemplo n.º 3
0
def assert_time_at(header, position, jd1, jd2, scale, format):
    wcs = WCS(header)
    time = wcs.pixel_to_world(position)
    assert_allclose(time.jd1, jd1, rtol=1e-10)
    assert_allclose(time.jd2, jd2, rtol=1e-10)
    assert time.format == format
    assert time.scale == scale
Exemplo n.º 4
0
def test_pixel_to_world_itrs(x_in, y_in):
    """Regression test for https://github.com/astropy/astropy/pull/9609"""
    if Version(_wcs.__version__) >= Version('7.4'):
        ctx = pytest.warns(
            FITSFixedWarning,
            match=
            r"'datfix' made the change 'Set MJD-OBS to 57982\.528524 from DATE-OBS'\."
        )
    else:
        ctx = nullcontext()

    with ctx:
        wcs = WCS({
            'NAXIS': 2,
            'CTYPE1': 'TLON-CAR',
            'CTYPE2': 'TLAT-CAR',
            'RADESYS': 'ITRS ',
            'DATE-OBS': '2017-08-17T12:41:04.444'
        })

    # This shouldn't raise an exception.
    coord = wcs.pixel_to_world(x_in, y_in)

    # Check round trip transformation.
    x, y = wcs.world_to_pixel(coord)

    np.testing.assert_almost_equal(x, x_in)
    np.testing.assert_almost_equal(y, y_in)
Exemplo n.º 5
0
def assert_time_at(header, position, jd1, jd2, scale, format):
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', FITSFixedWarning)
        wcs = WCS(header)
    time = wcs.pixel_to_world(position)
    assert_allclose(time.jd1, jd1, rtol=1e-10)
    assert_allclose(time.jd2, jd2, rtol=1e-10)
    assert time.format == format
    assert time.scale == scale
Exemplo n.º 6
0
def test_time_1d_roundtrip(header_time_1d, scale):

    # Check that coordinates round-trip

    pixel_in = np.arange(3, 10)

    header_time_1d['CTYPE1'] = scale.upper()
    wcs = WCS(header_time_1d)

    # Simple test
    time = wcs.pixel_to_world(pixel_in)
    pixel_out = wcs.world_to_pixel(time)
    assert_allclose(pixel_in, pixel_out)

    # Test with an intermediate change to a different scale/format
    time = wcs.pixel_to_world(pixel_in).tdb
    time.format = 'isot'
    pixel_out = wcs.world_to_pixel(time)
    assert_allclose(pixel_in, pixel_out)
Exemplo n.º 7
0
def test_time_1d_location_missing(header_time_1d_no_obs):

    # Check what happens when no location is present

    wcs = WCS(header_time_1d_no_obs)
    with pytest.warns(UserWarning,
                      match='Missing or incomplete observer location '
                      'information, setting location in Time to None'):
        time = wcs.pixel_to_world(10)

    assert time.location is None
Exemplo n.º 8
0
def test_time_1d_location_geocenter(header_time_1d_no_obs):

    header_time_1d_no_obs['TREFPOS'] = 'GEOCENTER'

    wcs = WCS(header_time_1d_no_obs)
    time = wcs.pixel_to_world(10)

    x, y, z = time.location.to_geocentric()

    assert_allclose(x.to_value(u.m), 0)
    assert_allclose(y.to_value(u.m), 0)
    assert_allclose(z.to_value(u.m), 0)
Exemplo n.º 9
0
def test_time_1d_unsupported_ctype(header_time_1d_no_obs):

    # For cases that we don't support yet, e.g. UT(...), use Time and drop sub-scale

    # Case where the MJDREF is split into two for high precision
    header_time_1d_no_obs['CTYPE1'] = 'UT(WWV)'

    wcs = WCS(header_time_1d_no_obs)
    with pytest.warns(UserWarning,
                      match="Dropping unsupported sub-scale WWV from scale UT"):
        time = wcs.pixel_to_world(10)

    assert isinstance(time, Time)
Exemplo n.º 10
0
def test_time_1d_location_incomplete(header_time_1d_noobs):

    # Check what happens when location information is incomplete

    header_time_1d_noobs['OBSGEO-L'] = 10.

    wcs = WCS(header_time_1d_noobs)
    with pytest.warns(UserWarning,
                      match='Missing or incomplete observer location '
                      'information, setting location in Time to None'):
        time = wcs.pixel_to_world(10)

    assert time.location is None
Exemplo n.º 11
0
def test_time_1d_location_unsupported(header_time_1d_no_obs):

    # Check what happens when TREFPOS is unsupported

    header_time_1d_no_obs['TREFPOS'] = 'BARYCENTER'

    wcs = WCS(header_time_1d_no_obs)
    with pytest.warns(UserWarning,
                      match="Observation location 'barycenter' is not "
                      "supported, setting location in Time to None"):
        time = wcs.pixel_to_world(10)

    assert time.location is None
Exemplo n.º 12
0
def test_time_1d_location_geodetic(header_time_1d):

    # Make sure that the location is correctly returned (geodetic case)

    wcs = WCS(header_time_1d)
    time = wcs.pixel_to_world(10)

    lon, lat, alt = time.location.to_geodetic()

    # FIXME: alt won't work for now because ERFA doesn't implement the IAU 1976
    # ellipsoid (https://github.com/astropy/astropy/issues/9420)
    assert_allclose(lon.degree, -20)
    assert_allclose(lat.degree, -70)
Exemplo n.º 13
0
def test_time_1d_high_precision(header_time_1d):

    # Case where the MJDREF is split into two for high precision
    del header_time_1d['MJDREF']
    header_time_1d['MJDREFI'] = 52000.
    header_time_1d['MJDREFF'] = 1e-11

    wcs = WCS(header_time_1d)
    time = wcs.pixel_to_world(10)

    # Here we have to use a very small rtol to really test that MJDREFF is
    # taken into account
    assert_allclose(time.jd1, 2452001.0, rtol=1e-12)
    assert_allclose(time.jd2, -0.5 + 25 / 3600 / 24 + 1e-11, rtol=1e-13)
Exemplo n.º 14
0
def test_pixel_to_world_itrs(x_in, y_in):
    """Regression test for https://github.com/astropy/astropy/pull/9609"""
    wcs = WCS({'NAXIS': 2,
               'CTYPE1': 'TLON-CAR',
               'CTYPE2': 'TLAT-CAR',
               'RADESYS': 'ITRS ',
               'DATE-OBS': '2017-08-17T12:41:04.444'})

    # This shouldn't raise an exception.
    coord = wcs.pixel_to_world(x_in, y_in)

    # Check round trip transformation.
    x, y = wcs.world_to_pixel(coord)
    np.testing.assert_almost_equal(x, x_in)
    np.testing.assert_almost_equal(y, y_in)
Exemplo n.º 15
0
def test_time_1d_location_incomplete(header_time_1d_no_obs):

    # Check what happens when location information is incomplete

    header_time_1d_no_obs['OBSGEO-L'] = 10.

    with warnings.catch_warnings():
        warnings.simplefilter('ignore', FITSFixedWarning)
        wcs = WCS(header_time_1d_no_obs)

    with pytest.warns(UserWarning,
                      match='Missing or incomplete observer location '
                      'information, setting location in Time to None'):
        time = wcs.pixel_to_world(10)

    assert time.location is None
Exemplo n.º 16
0
def test_time_1d_location_geocentric(header_time_1d_noobs):

    # Make sure that the location is correctly returned (geocentric case)

    header = header_time_1d_noobs

    header['OBSGEO-X'] = 10
    header['OBSGEO-Y'] = -20
    header['OBSGEO-Z'] = 30

    wcs = WCS(header)
    time = wcs.pixel_to_world(10)

    x, y, z = time.location.to_geocentric()

    assert_allclose(x.to_value(u.m), 10)
    assert_allclose(y.to_value(u.m), -20)
    assert_allclose(z.to_value(u.m), 30)
Exemplo n.º 17
0
def test_time_1d_location_geocentric(header_time_1d_no_obs):

    # Make sure that the location is correctly returned (geocentric case)

    header = header_time_1d_no_obs

    header['OBSGEO-X'] = 10
    header['OBSGEO-Y'] = -20
    header['OBSGEO-Z'] = 30

    with warnings.catch_warnings():
        warnings.simplefilter('ignore', FITSFixedWarning)
        wcs = WCS(header)

    time = wcs.pixel_to_world(10)

    x, y, z = time.location.to_geocentric()

    assert_allclose(x.to_value(u.m), 10)
    assert_allclose(y.to_value(u.m), -20)
    assert_allclose(z.to_value(u.m), 30)
Exemplo n.º 18
0
def test_fit_wcs_from_points(header_str, crval, sip_degree, user_proj_point,
                             exp_max_dist, exp_std_dist):
    header = fits.Header.fromstring(header_str, sep='\n')
    header["CRVAL1"] = crval

    true_wcs = WCS(header, relax=True)

    # Getting the pixel coordinates
    x, y = np.meshgrid(list(range(10)), list(range(10)))
    x = x.flatten()
    y = y.flatten()

    # Calculating the true sky positions
    world_pix = true_wcs.pixel_to_world(x, y)

    # which projection point to use
    if user_proj_point:
        proj_point = world_pix[0]
        projlon = proj_point.data.lon.deg
        projlat = proj_point.data.lat.deg
    else:
        proj_point = 'center'

    # Fitting the wcs
    fit_wcs = fit_wcs_from_points((x, y),
                                  world_pix,
                                  proj_point=proj_point,
                                  sip_degree=sip_degree)

    # Validate that the true sky coordinates
    # match sky coordinates calculated from the wcs fit
    world_pix_new = fit_wcs.pixel_to_world(x, y)

    dists = world_pix.separation(world_pix_new)

    assert dists.max() < exp_max_dist
    assert np.std(dists) < exp_std_dist

    if user_proj_point:
        assert (fit_wcs.wcs.crval == [projlon, projlat]).all()
Exemplo n.º 19
0
def test_different_ctypes(header_spectral_frames, ctype3, observer):

    header = header_spectral_frames.copy()
    header['CTYPE3'] = ctype3
    header['CRVAL3'] = 0.1
    header['CDELT3'] = 0.001

    if ctype3[0] == 'V':
        header['CUNIT3'] = 'm s-1'
    else:
        header['CUNIT3'] = ''

    header['RESTWAV'] = 1.420405752E+09
    header['MJD-OBS'] = 55197

    if observer:
        header['OBSGEO-L'] = 144.2
        header['OBSGEO-B'] = -20.2
        header['OBSGEO-H'] = 0.
        header['SPECSYS'] = 'BARYCENT'

    with warnings.catch_warnings():
        warnings.simplefilter('ignore', FITSFixedWarning)
        wcs = WCS(header)

    skycoord, spectralcoord = wcs.pixel_to_world(0, 0, 31)

    assert isinstance(spectralcoord, SpectralCoord)

    if observer:
        pix = wcs.world_to_pixel(skycoord, spectralcoord)
    else:
        with pytest.warns(AstropyUserWarning,
                          match='No observer defined on WCS'):
            pix = wcs.world_to_pixel(skycoord, spectralcoord)

    assert_allclose(pix, [0, 0, 31], rtol=1e-6)
Exemplo n.º 20
0
def test_fit_wcs_from_points():
    header_str_linear = """
XTENSION= 'IMAGE   '           / Image extension
BITPIX  =                  -32 / array data type
NAXIS   =                    2 / number of array dimensions
NAXIS1  =                   50
NAXIS2  =                   50
PCOUNT  =                    0 / number of parameters
GCOUNT  =                    1 / number of groups
RADESYS = 'ICRS    '
EQUINOX =               2000.0
WCSAXES =                    2
CTYPE1  = 'RA---TAN'
CTYPE2  = 'DEC--TAN'
CRVAL1  =    250.3497414839765
CRVAL2  =    2.280925599609063
CRPIX1  =               1045.0
CRPIX2  =               1001.0
CD1_1   =   -0.005564478186178
CD1_2   =   -0.001042099258152
CD2_1   =     0.00118144146585
CD2_2   =   -0.005590816683583
"""

    header_str_sip = """
XTENSION= 'IMAGE   '           / Image extension
BITPIX  =                  -32 / array data type
NAXIS   =                    2 / number of array dimensions
NAXIS1  =                   50
NAXIS2  =                   50
PCOUNT  =                    0 / number of parameters
GCOUNT  =                    1 / number of groups
RADESYS = 'ICRS    '
EQUINOX =               2000.0
WCSAXES =                    2
CTYPE1  = 'RA---TAN-SIP'
CTYPE2  = 'DEC--TAN-SIP'
CRVAL1  =    250.3497414839765
CRVAL2  =    2.280925599609063
CRPIX1  =               1045.0
CRPIX2  =               1001.0
CD1_1   =   -0.005564478186178
CD1_2   =   -0.001042099258152
CD2_1   =     0.00118144146585
CD2_2   =   -0.005590816683583
A_ORDER =                    2
B_ORDER =                    2
A_2_0   =    2.02451189234E-05
A_0_2   =   3.317603337918E-06
A_1_1   = 1.73456334971071E-05
B_2_0   =   3.331330003472E-06
B_0_2   = 2.04247482482589E-05
B_1_1   = 1.71476710804143E-05
AP_ORDER=                    2
BP_ORDER=                    2
AP_1_0  = 0.000904700296389636
AP_0_1  = 0.000627660715584716
AP_2_0  =  -2.023482905861E-05
AP_0_2  =  -3.332285841011E-06
AP_1_1  =  -1.731636633824E-05
BP_1_0  = 0.000627960882053211
BP_0_1  = 0.000911222886084808
BP_2_0  =  -3.343918167224E-06
BP_0_2  =  -2.041598249021E-05
BP_1_1  =  -1.711876336719E-05
A_DMAX  =    44.72893589844534
B_DMAX  =    44.62692873032506
"""
    # A known header that failed before
    header_str_prob = """
NAXIS   =                    2 / number of array dimensions
WCSAXES =                    2 / Number of coordinate axes
CRPIX1  =               1024.5 / Pixel coordinate of reference point
CRPIX2  =               1024.5 / Pixel coordinate of reference point
CD1_1   = -1.7445934400771E-05 / Coordinate transformation matrix element
CD1_2   = -4.9826985362578E-08 / Coordinate transformation matrix element
CD2_1   = -5.0068838822312E-08 / Coordinate transformation matrix element
CD2_2   =  1.7530614610951E-05 / Coordinate transformation matrix element
CTYPE1  = 'RA---TAN'           / Right ascension, gnomonic projection
CTYPE2  = 'DEC--TAN'           / Declination, gnomonic projection
CRVAL1  =      5.8689341666667 / [deg] Coordinate value at reference point
CRVAL2  =     -71.995508583333 / [deg] Coordinate value at reference point
"""

    header_linear = fits.Header.fromstring(header_str_linear, sep='\n')
    header_sip = fits.Header.fromstring(header_str_sip, sep='\n')
    header_prob = fits.Header.fromstring(header_str_prob, sep='\n')

    true_wcs_linear = WCS(header_linear, relax=True)
    true_wcs_sip = WCS(header_sip, relax=True)
    true_wcs_prob = WCS(header_prob, relax=True)

    # Getting the pixel coordinates
    x, y = np.meshgrid(list(range(10)), list(range(10)))
    x = x.flatten()
    y = y.flatten()

    # Calculating the true sky positions
    world_pix_linear = true_wcs_linear.pixel_to_world(x, y)
    world_pix_sip = true_wcs_sip.pixel_to_world(x, y)
    world_pix_prob = true_wcs_prob.pixel_to_world(x, y)

    # Fitting the wcs, no distortion.
    fit_wcs_linear = fit_wcs_from_points((x, y),
                                         world_pix_linear,
                                         proj_point='center',
                                         sip_degree=None)

    # Fitting the wcs, with distortion.
    fit_wcs_sip = fit_wcs_from_points((x, y),
                                      world_pix_sip,
                                      proj_point='center',
                                      sip_degree=2)

    # Fitting the problematic WCS
    fit_wcs_prob = fit_wcs_from_points((x, y),
                                       world_pix_prob,
                                       proj_point='center',
                                       sip_degree=None)

    # Validate that the true sky coordinates calculated with `true_wcs_linear`
    # match sky coordinates calculated from the wcs fit with only linear terms

    world_pix_linear_new = fit_wcs_linear.pixel_to_world(x, y)

    dists = world_pix_linear.separation(world_pix_linear_new)

    assert dists.max() < 7e-5 * u.deg
    assert np.std(dists) < 2.5e-5 * u.deg

    # Validate that the true sky coordinates calculated with `true_wcs_sip`
    # match the sky coordinates calculated from the wcs fit with SIP of same
    # degree (2)

    world_pix_sip_new = fit_wcs_sip.pixel_to_world(x, y)
    dists = world_pix_sip.separation(world_pix_sip_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Validate that the true sky coordinates calculated from the problematic
    # WCS match

    world_pix_prob_new = fit_wcs_prob.pixel_to_world(x, y)
    dists = world_pix_prob.separation(world_pix_prob_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Test 360->0 degree crossover
    header_linear["CRVAL1"] = 352.3497414839765
    header_sip["CRVAL1"] = 352.3497414839765
    header_prob["CRVAL1"] = 352.3497414839765

    true_wcs_linear = WCS(header_linear, relax=True)
    true_wcs_sip = WCS(header_sip, relax=True)
    true_wcs_prob = WCS(header_prob)

    # Calculating the true sky positions
    world_pix_linear = true_wcs_linear.pixel_to_world(x, y)
    world_pix_sip = true_wcs_sip.pixel_to_world(x, y)
    world_pix_prob = true_wcs_prob.pixel_to_world(x, y)

    # Fitting the wcs, no distortion.
    fit_wcs_linear = fit_wcs_from_points((x, y),
                                         world_pix_linear,
                                         proj_point='center',
                                         sip_degree=None)

    # Fitting the wcs, with distortion.
    fit_wcs_sip = fit_wcs_from_points((x, y),
                                      world_pix_sip,
                                      proj_point='center',
                                      sip_degree=2)

    # Fitting the problem WCS
    fit_wcs_prob = fit_wcs_from_points((x, y),
                                       world_pix_prob,
                                       proj_point='center',
                                       sip_degree=None)

    # Validate that the true sky coordinates calculated with `true_wcs_linear`
    # match sky coordinates calculated from the wcs fit with only linear terms

    world_pix_linear_new = fit_wcs_linear.pixel_to_world(x, y)

    dists = world_pix_linear.separation(world_pix_linear_new)

    assert dists.max() < 7e-5 * u.deg
    assert np.std(dists) < 2.5e-5 * u.deg

    # Validate fit with SIP
    world_pix_sip_new = fit_wcs_sip.pixel_to_world(x, y)
    dists = world_pix_sip.separation(world_pix_sip_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Validate the problematic WCS
    world_pix_prob_new = fit_wcs_prob.pixel_to_world(x, y)
    dists = world_pix_prob.separation(world_pix_prob_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Test CRPIX bounds requirement
    wcs_str = """
WCSAXES =                    2 / Number of coordinate axes
CRPIX1  =               1045.0 / Pixel coordinate of reference point
CRPIX2  =               1001.0 / Pixel coordinate of reference point
PC1_1   =  0.00056205870415378 / Coordinate transformation matrix element
PC1_2   =    -0.00569181083243 / Coordinate transformation matrix element
PC2_1   =   0.0056776810932466 / Coordinate transformation matrix element
PC2_2   =   0.0004208048403273 / Coordinate transformation matrix element
CDELT1  =                  1.0 / [deg] Coordinate increment at reference point
CDELT2  =                  1.0 / [deg] Coordinate increment at reference point
CUNIT1  = 'deg'                / Units of coordinate increment and value
CUNIT2  = 'deg'                / Units of coordinate increment and value
CTYPE1  = 'RA---TAN'           / Right ascension, gnomonic projection
CTYPE2  = 'DEC--TAN'           / Declination, gnomonic projection
CRVAL1  =      104.57797893504 / [deg] Coordinate value at reference point
CRVAL2  =     -74.195502593322 / [deg] Coordinate value at reference point
LONPOLE =                180.0 / [deg] Native longitude of celestial pole
LATPOLE =     -74.195502593322 / [deg] Native latitude of celestial pole
TIMESYS = 'TDB'                / Time scale
TIMEUNIT= 'd'                  / Time units
DATEREF = '1858-11-17'         / ISO-8601 fiducial time
MJDREFI =                  0.0 / [d] MJD of fiducial time, integer part
MJDREFF =                  0.0 / [d] MJD of fiducial time, fractional part
DATE-OBS= '2019-03-27T03:30:13.832Z' / ISO-8601 time of observation
MJD-OBS =      58569.145993426 / [d] MJD of observation
MJD-OBS =      58569.145993426 / [d] MJD at start of observation
TSTART  =      1569.6467941661 / [d] Time elapsed since fiducial time at start
DATE-END= '2019-03-27T04:00:13.831Z' / ISO-8601 time at end of observation
MJD-END =      58569.166826748 / [d] MJD at end of observation
TSTOP   =      1569.6676274905 / [d] Time elapsed since fiducial time at end
TELAPSE =        0.02083332443 / [d] Elapsed time (start to stop)
TIMEDEL =    0.020833333333333 / [d] Time resolution
TIMEPIXR=                  0.5 / Reference position of timestamp in binned data
RADESYS = 'ICRS'               / Equatorial coordinate system
"""
    wcs_header = fits.Header.fromstring(wcs_str, sep='\n')
    ffi_wcs = WCS(wcs_header)

    yi, xi = (1000, 1000)
    y, x = (10, 200)

    center_coord = SkyCoord(ffi_wcs.all_pix2world([[xi + x // 2, yi + y // 2]],
                                                  0),
                            unit='deg')[0]
    ypix, xpix = [arr.flatten() for arr in np.mgrid[xi:xi + x, yi:yi + y]]
    world_pix = SkyCoord(*ffi_wcs.all_pix2world(xpix, ypix, 0), unit='deg')

    fit_wcs = fit_wcs_from_points((ypix, xpix), world_pix, proj_point='center')

    assert (fit_wcs.wcs.crpix.astype(int) == [1100, 1005]).all()
    assert fit_wcs.pixel_shape == (200, 10)
Exemplo n.º 21
0
def test_spectral_1d(header_spectral_1d, ctype1, observer):

    # This is a regression test for issues that happened with 1-d WCS
    # where the target is not defined but observer is.

    header = header_spectral_1d.copy()
    header['CTYPE1'] = ctype1
    header['CRVAL1'] = 0.1
    header['CDELT1'] = 0.001

    if ctype1[0] == 'V':
        header['CUNIT1'] = 'm s-1'
    else:
        header['CUNIT1'] = ''

    header['RESTWAV'] = 1.420405752E+09
    header['MJD-OBS'] = 55197

    if observer:
        header['OBSGEO-L'] = 144.2
        header['OBSGEO-B'] = -20.2
        header['OBSGEO-H'] = 0.
        header['SPECSYS'] = 'BARYCENT'

    with warnings.catch_warnings():
        warnings.simplefilter('ignore', FITSFixedWarning)
        wcs = WCS(header)

    # First ensure that transformations round-trip

    spectralcoord = wcs.pixel_to_world(31)

    assert isinstance(spectralcoord, SpectralCoord)
    assert spectralcoord.target is None
    assert (spectralcoord.observer is not None) is observer

    if observer:
        expected_message = 'No target defined on SpectralCoord'
    else:
        expected_message = 'No observer defined on WCS'

    with pytest.warns(AstropyUserWarning, match=expected_message):
        pix = wcs.world_to_pixel(spectralcoord)

    assert_allclose(pix, [31], rtol=1e-6)

    # Also make sure that we can convert a SpectralCoord on which the observer
    # is not defined but the target is.

    with pytest.warns(AstropyUserWarning,
                      match='No velocity defined on frame'):
        spectralcoord_no_obs = SpectralCoord(
            spectralcoord.quantity,
            doppler_rest=spectralcoord.doppler_rest,
            doppler_convention=spectralcoord.doppler_convention,
            target=ICRS(10 * u.deg, 20 * u.deg, distance=1 * u.kpc))

    if observer:
        expected_message = 'No observer defined on SpectralCoord'
    else:
        expected_message = 'No observer defined on WCS'

    with pytest.warns(AstropyUserWarning, match=expected_message):
        pix2 = wcs.world_to_pixel(spectralcoord_no_obs)
    assert_allclose(pix2, [31], rtol=1e-6)

    # And finally check case when both observer and target are defined on the
    # SpectralCoord

    with pytest.warns(AstropyUserWarning,
                      match='No velocity defined on frame'):
        spectralcoord_no_obs = SpectralCoord(
            spectralcoord.quantity,
            doppler_rest=spectralcoord.doppler_rest,
            doppler_convention=spectralcoord.doppler_convention,
            observer=ICRS(10 * u.deg, 20 * u.deg, distance=0 * u.kpc),
            target=ICRS(10 * u.deg, 20 * u.deg, distance=1 * u.kpc))

    if observer:
        pix3 = wcs.world_to_pixel(spectralcoord_no_obs)
    else:
        with pytest.warns(AstropyUserWarning,
                          match='No observer defined on WCS'):
            pix3 = wcs.world_to_pixel(spectralcoord_no_obs)

    assert_allclose(pix3, [31], rtol=1e-6)
Exemplo n.º 22
0
def test_fit_wcs_from_points():
    header_str_linear = """
XTENSION= 'IMAGE   '           / Image extension
BITPIX  =                  -32 / array data type
NAXIS   =                    2 / number of array dimensions
NAXIS1  =                   50
NAXIS2  =                   50
PCOUNT  =                    0 / number of parameters
GCOUNT  =                    1 / number of groups
RADESYS = 'ICRS    '
EQUINOX =               2000.0
WCSAXES =                    2
CTYPE1  = 'RA---TAN'
CTYPE2  = 'DEC--TAN'
CRVAL1  =    250.3497414839765
CRVAL2  =    2.280925599609063
CRPIX1  =               1045.0
CRPIX2  =               1001.0
CD1_1   =   -0.005564478186178
CD1_2   =   -0.001042099258152
CD2_1   =     0.00118144146585
CD2_2   =   -0.005590816683583
"""

    header_str_sip = """
XTENSION= 'IMAGE   '           / Image extension
BITPIX  =                  -32 / array data type
NAXIS   =                    2 / number of array dimensions
NAXIS1  =                   50
NAXIS2  =                   50
PCOUNT  =                    0 / number of parameters
GCOUNT  =                    1 / number of groups
RADESYS = 'ICRS    '
EQUINOX =               2000.0
WCSAXES =                    2
CTYPE1  = 'RA---TAN-SIP'
CTYPE2  = 'DEC--TAN-SIP'
CRVAL1  =    250.3497414839765
CRVAL2  =    2.280925599609063
CRPIX1  =               1045.0
CRPIX2  =               1001.0
CD1_1   =   -0.005564478186178
CD1_2   =   -0.001042099258152
CD2_1   =     0.00118144146585
CD2_2   =   -0.005590816683583
A_ORDER =                    2
B_ORDER =                    2
A_2_0   =    2.02451189234E-05
A_0_2   =   3.317603337918E-06
A_1_1   = 1.73456334971071E-05
B_2_0   =   3.331330003472E-06
B_0_2   = 2.04247482482589E-05
B_1_1   = 1.71476710804143E-05
AP_ORDER=                    2
BP_ORDER=                    2
AP_1_0  = 0.000904700296389636
AP_0_1  = 0.000627660715584716
AP_2_0  =  -2.023482905861E-05
AP_0_2  =  -3.332285841011E-06
AP_1_1  =  -1.731636633824E-05
BP_1_0  = 0.000627960882053211
BP_0_1  = 0.000911222886084808
BP_2_0  =  -3.343918167224E-06
BP_0_2  =  -2.041598249021E-05
BP_1_1  =  -1.711876336719E-05
A_DMAX  =    44.72893589844534
B_DMAX  =    44.62692873032506
"""
    header_linear = fits.Header.fromstring(header_str_linear, sep='\n')
    header_sip = fits.Header.fromstring(header_str_sip, sep='\n')

    true_wcs_linear = WCS(header_linear, relax=True)
    true_wcs_sip = WCS(header_sip, relax=True)

    # Getting the pixel coordinates
    x, y = np.meshgrid(list(range(10)), list(range(10)))
    x = x.flatten()
    y = y.flatten()

    # Calculating the true sky positions
    world_pix_linear = true_wcs_linear.pixel_to_world(x, y)
    world_pix_sip = true_wcs_sip.pixel_to_world(x, y)

    # Fitting the wcs, no distortion.
    fit_wcs_linear = fit_wcs_from_points((x, y),
                                         world_pix_linear,
                                         proj_point='center',
                                         sip_degree=None)

    # Fitting the wcs, with distortion.
    fit_wcs_sip = fit_wcs_from_points((x, y),
                                      world_pix_sip,
                                      proj_point='center',
                                      sip_degree=2)

    # Validate that the true sky coordinates calculated with `true_wcs_linear`
    # match sky coordinates calculated from the wcs fit with only linear terms

    world_pix_linear_new = fit_wcs_linear.pixel_to_world(x, y)

    dists = world_pix_linear.separation(world_pix_linear_new)

    assert dists.max() < 7e-5 * u.deg
    assert np.std(dists) < 2.5e-5 * u.deg

    # Validate that the true sky coordinates calculated with `true_wcs_sip`
    # match the sky coordinates calculated from the wcs fit with SIP of same
    # degree (2)

    world_pix_sip_new = fit_wcs_sip.pixel_to_world(x, y)
    dists = world_pix_sip.separation(world_pix_sip_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Test 360->0 degree crossover
    header_linear["CRVAL1"] = 352.3497414839765
    header_sip["CRVAL1"] = 352.3497414839765

    true_wcs_linear = WCS(header_linear, relax=True)
    true_wcs_sip = WCS(header_sip, relax=True)

    # Calculating the true sky positions
    world_pix_linear = true_wcs_linear.pixel_to_world(x, y)
    world_pix_sip = true_wcs_sip.pixel_to_world(x, y)

    # Fitting the wcs, no distortion.
    fit_wcs_linear = fit_wcs_from_points((x, y),
                                         world_pix_linear,
                                         proj_point='center',
                                         sip_degree=None)

    # Fitting the wcs, with distortion.
    fit_wcs_sip = fit_wcs_from_points((x, y),
                                      world_pix_sip,
                                      proj_point='center',
                                      sip_degree=2)

    # Validate that the true sky coordinates calculated with `true_wcs_linear`
    # match sky coordinates calculated from the wcs fit with only linear terms

    world_pix_linear_new = fit_wcs_linear.pixel_to_world(x, y)

    dists = world_pix_linear.separation(world_pix_linear_new)

    assert dists.max() < 7e-5 * u.deg
    assert np.std(dists) < 2.5e-5 * u.deg