コード例 #1
0
def test_is_frame_attr_default():
    """
    Check that the `is_frame_attr_default` machinery works as expected
    """
    from astropy.time import Time
    from astropy.coordinates.builtin_frames import FK5

    c1 = FK5(ra=1 * u.deg, dec=1 * u.deg)
    c2 = FK5(ra=1 * u.deg,
             dec=1 * u.deg,
             equinox=FK5.get_frame_attr_names()['equinox'])
    c3 = FK5(ra=1 * u.deg, dec=1 * u.deg, equinox=Time('J2001.5'))

    assert c1.equinox == c2.equinox
    assert c1.equinox != c3.equinox

    assert c1.is_frame_attr_default('equinox')
    assert not c2.is_frame_attr_default('equinox')
    assert not c3.is_frame_attr_default('equinox')

    c4 = c1.realize_frame(r.UnitSphericalRepresentation(3 * u.deg, 4 * u.deg))
    c5 = c2.realize_frame(r.UnitSphericalRepresentation(3 * u.deg, 4 * u.deg))

    assert c4.is_frame_attr_default('equinox')
    assert not c5.is_frame_attr_default('equinox')
コード例 #2
0
def test_equivalent_frames():
    from astropy.coordinates import SkyCoord
    from astropy.coordinates.builtin_frames import ICRS, FK4, FK5, AltAz

    i = ICRS()
    i2 = ICRS(1 * u.deg, 2 * u.deg)
    assert i.is_equivalent_frame(i)
    assert i.is_equivalent_frame(i2)
    with pytest.raises(TypeError):
        assert i.is_equivalent_frame(10)
    with pytest.raises(TypeError):
        assert i2.is_equivalent_frame(SkyCoord(i2))

    f0 = FK5()  # this J2000 is TT
    f1 = FK5(equinox='J2000')
    f2 = FK5(1 * u.deg, 2 * u.deg, equinox='J2000')
    f3 = FK5(equinox='J2010')
    f4 = FK4(equinox='J2010')

    assert f1.is_equivalent_frame(f1)
    assert not i.is_equivalent_frame(f1)
    assert f0.is_equivalent_frame(f1)
    assert f1.is_equivalent_frame(f2)
    assert not f1.is_equivalent_frame(f3)
    assert not f3.is_equivalent_frame(f4)

    aa1 = AltAz()
    aa2 = AltAz(obstime='J2010')

    assert aa2.is_equivalent_frame(aa2)
    assert not aa1.is_equivalent_frame(i)
    assert not aa1.is_equivalent_frame(aa2)
コード例 #3
0
def test_realizing():
    from astropy.coordinates.builtin_frames import ICRS, FK5
    from astropy.time import Time

    rep = r.SphericalRepresentation(1 * u.deg, 2 * u.deg, 3 * u.kpc)

    i = ICRS()
    i2 = i.realize_frame(rep)

    assert not i.has_data
    assert i2.has_data

    f = FK5(equinox=Time('J2001'))
    f2 = f.realize_frame(rep)

    assert not f.has_data
    assert f2.has_data

    assert f2.equinox == f.equinox
    assert f2.equinox != FK5.get_frame_attr_names()['equinox']

    # Check that a nicer error message is returned:
    with pytest.raises(TypeError) as excinfo:
        f.realize_frame(f.representation_type)

    assert ('Class passed as data instead of a representation'
            in excinfo.value.args[0])
コード例 #4
0
def test_fk5_seps():
    """
    This tests if `separation` works for FK5 objects.

    This is a regression test for github issue #891
    """
    a = FK5(1. * u.deg, 1. * u.deg)
    b = FK5(2. * u.deg, 2. * u.deg)
    a.separation(b)
コード例 #5
0
def test_transform():
    """
    This test just makes sure the transform architecture works, but does *not*
    actually test all the builtin transforms themselves are accurate
    """
    from astropy.coordinates.builtin_frames import ICRS, FK4, FK5, Galactic
    from astropy.time import Time

    i = ICRS(ra=[1, 2] * u.deg, dec=[3, 4] * u.deg)
    f = i.transform_to(FK5)
    i2 = f.transform_to(ICRS)

    assert i2.data.__class__ == r.UnitSphericalRepresentation

    assert_allclose(i.ra, i2.ra)
    assert_allclose(i.dec, i2.dec)

    i = ICRS(ra=[1, 2] * u.deg, dec=[3, 4] * u.deg, distance=[5, 6] * u.kpc)
    f = i.transform_to(FK5)
    i2 = f.transform_to(ICRS)

    assert i2.data.__class__ != r.UnitSphericalRepresentation

    f = FK5(ra=1 * u.deg, dec=2 * u.deg, equinox=Time('J2001'))
    f4 = f.transform_to(FK4)
    f4_2 = f.transform_to(FK4(equinox=f.equinox))

    # make sure attributes are copied over correctly
    assert f4.equinox == FK4.get_frame_attr_names()['equinox']
    assert f4_2.equinox == f.equinox

    # make sure self-transforms also work
    i = ICRS(ra=[1, 2] * u.deg, dec=[3, 4] * u.deg)
    i2 = i.transform_to(ICRS)

    assert_allclose(i.ra, i2.ra)
    assert_allclose(i.dec, i2.dec)

    f = FK5(ra=1 * u.deg, dec=2 * u.deg, equinox=Time('J2001'))
    f2 = f.transform_to(FK5)  # default equinox, so should be *different*
    assert f2.equinox == FK5().equinox
    with pytest.raises(AssertionError):
        assert_allclose(f.ra, f2.ra)
    with pytest.raises(AssertionError):
        assert_allclose(f.dec, f2.dec)

    # finally, check Galactic round-tripping
    i1 = ICRS(ra=[1, 2] * u.deg, dec=[3, 4] * u.deg)
    i2 = i1.transform_to(Galactic).transform_to(ICRS)

    assert_allclose(i1.ra, i2.ra)
    assert_allclose(i1.dec, i2.dec)
コード例 #6
0
def test_create_nodata_frames():
    from astropy.coordinates.builtin_frames import ICRS, FK4, FK5

    i = ICRS()
    assert len(i.get_frame_attr_names()) == 0

    f5 = FK5()
    assert f5.equinox == FK5.get_frame_attr_names()['equinox']

    f4 = FK4()
    assert f4.equinox == FK4.get_frame_attr_names()['equinox']

    # obstime is special because it's a property that uses equinox if obstime is not set
    assert f4.obstime in (FK4.get_frame_attr_names()['obstime'],
                          FK4.get_frame_attr_names()['equinox'])
コード例 #7
0
ファイル: test_frames.py プロジェクト: Cadair/astropy
def test_realizing():
    from astropy.coordinates.builtin_frames import ICRS, FK5
    from astropy.time import Time

    rep = r.SphericalRepresentation(1*u.deg, 2*u.deg, 3*u.kpc)

    i = ICRS()
    i2 = i.realize_frame(rep)

    assert not i.has_data
    assert i2.has_data

    f = FK5(equinox=Time('J2001'))
    f2 = f.realize_frame(rep)

    assert not f.has_data
    assert f2.has_data

    assert f2.equinox == f.equinox
    assert f2.equinox != FK5.get_frame_attr_names()['equinox']

    # Check that a nicer error message is returned:
    with pytest.raises(TypeError) as excinfo:
        f.realize_frame(f.representation_type)

    assert ('Class passed as data instead of a representation' in
            excinfo.value.args[0])
コード例 #8
0
def test_frame_repr():
    from astropy.coordinates.builtin_frames import ICRS, FK5

    i = ICRS()
    assert repr(i) == '<ICRS Frame>'

    f5 = FK5()
    assert repr(f5).startswith('<FK5 Frame (equinox=')

    i2 = ICRS(ra=1 * u.deg, dec=2 * u.deg)
    i3 = ICRS(ra=1 * u.deg, dec=2 * u.deg, distance=3 * u.kpc)

    assert repr(i2) == ('<ICRS Coordinate: (ra, dec) in deg\n' '    (1., 2.)>')
    assert repr(i3) == (
        '<ICRS Coordinate: (ra, dec, distance) in (deg, deg, kpc)\n'
        '    (1., 2., 3.)>')

    # try with arrays
    i2 = ICRS(ra=[1.1, 2.1] * u.deg, dec=[2.1, 3.1] * u.deg)
    i3 = ICRS(ra=[1.1, 2.1] * u.deg,
              dec=[-15.6, 17.1] * u.deg,
              distance=[11., 21.] * u.kpc)

    assert repr(i2) == ('<ICRS Coordinate: (ra, dec) in deg\n'
                        '    [(1.1, 2.1), (2.1, 3.1)]>')

    assert repr(i3) == (
        '<ICRS Coordinate: (ra, dec, distance) in (deg, deg, kpc)\n'
        '    [(1.1, -15.6, 11.), (2.1,  17.1, 21.)]>')
コード例 #9
0
def test_faux_fk5_galactic():

    from astropy.coordinates.builtin_frames.galactic_transforms import fk5_to_gal, _gal_to_fk5

    class Galactic2(Galactic):
        pass

    dt = 1000*u.s

    @frame_transform_graph.transform(FunctionTransformWithFiniteDifference,
                                     FK5, Galactic2, finite_difference_dt=dt,
                                     symmetric_finite_difference=True,
                                     finite_difference_frameattr_name=None)
    def fk5_to_gal2(fk5_coo, gal_frame):
        trans = DynamicMatrixTransform(fk5_to_gal, FK5, Galactic2)
        return trans(fk5_coo, gal_frame)

    @frame_transform_graph.transform(FunctionTransformWithFiniteDifference,
                                     Galactic2, ICRS, finite_difference_dt=dt,
                                     symmetric_finite_difference=True,
                                     finite_difference_frameattr_name=None)
    def gal2_to_fk5(gal_coo, fk5_frame):
        trans = DynamicMatrixTransform(_gal_to_fk5, Galactic2, FK5)
        return trans(gal_coo, fk5_frame)

    c1 = FK5(ra=150*u.deg, dec=-17*u.deg, radial_velocity=83*u.km/u.s,
             pm_ra_cosdec=-41*u.mas/u.yr, pm_dec=16*u.mas/u.yr,
             distance=150*u.pc)
    c2 = c1.transform_to(Galactic2)
    c3 = c1.transform_to(Galactic)

    # compare the matrix and finite-difference calculations
    assert quantity_allclose(c2.pm_l_cosb, c3.pm_l_cosb, rtol=1e-4)
    assert quantity_allclose(c2.pm_b, c3.pm_b, rtol=1e-4)
コード例 #10
0
def test_representation_subclass():

    # Regression test for #3354

    from astropy.coordinates.builtin_frames import FK5

    # Normally when instantiating a frame without a distance the frame will try
    # and use UnitSphericalRepresentation internally instead of
    # SphericalRepresentation.
    frame = FK5(representation_type=r.SphericalRepresentation,
                ra=32 * u.deg,
                dec=20 * u.deg)
    assert type(frame._data) == r.UnitSphericalRepresentation
    assert frame.representation_type == r.SphericalRepresentation

    # If using a SphericalRepresentation class this used to not work, so we
    # test here that this is now fixed.
    class NewSphericalRepresentation(r.SphericalRepresentation):
        attr_classes = r.SphericalRepresentation.attr_classes

    frame = FK5(representation_type=NewSphericalRepresentation,
                lon=32 * u.deg,
                lat=20 * u.deg)
    assert type(frame._data) == r.UnitSphericalRepresentation
    assert frame.representation_type == NewSphericalRepresentation

    # A similar issue then happened in __repr__ with subclasses of
    # SphericalRepresentation.
    assert repr(frame) == (
        "<FK5 Coordinate (equinox=J2000.000): (lon, lat) in deg\n"
        "    (32., 20.)>")

    # A more subtle issue is when specifying a custom
    # UnitSphericalRepresentation subclass for the data and
    # SphericalRepresentation or a subclass for the representation.

    class NewUnitSphericalRepresentation(r.UnitSphericalRepresentation):
        attr_classes = r.UnitSphericalRepresentation.attr_classes

        def __repr__(self):
            return "<NewUnitSphericalRepresentation: spam spam spam>"

    frame = FK5(NewUnitSphericalRepresentation(lon=32 * u.deg, lat=20 * u.deg),
                representation_type=NewSphericalRepresentation)

    assert repr(
        frame) == "<FK5 Coordinate (equinox=J2000.000):  spam spam spam>"
コード例 #11
0
def test_fk4_no_e_fk5():
    lines = get_pkg_data_contents('data/fk4_no_e_fk5.csv').split('\n')
    t = Table.read(lines, format='ascii', delimiter=',', guess=False)

    if N_ACCURACY_TESTS >= len(t):
        idxs = range(len(t))
    else:
        idxs = np.random.randint(len(t), size=N_ACCURACY_TESTS)

    diffarcsec1 = []
    diffarcsec2 = []
    for i in idxs:
        # Extract row
        r = t[int(i)]  # int here is to get around a py 3.x astropy.table bug

        # FK4NoETerms to FK5
        c1 = FK4NoETerms(ra=r['ra_in'] * u.deg,
                         dec=r['dec_in'] * u.deg,
                         obstime=Time(r['obstime']),
                         equinox=Time(r['equinox_fk4']))
        c2 = c1.transform_to(FK5(equinox=Time(r['equinox_fk5'])))

        # Find difference
        diff = angular_separation(c2.ra.radian, c2.dec.radian,
                                  np.radians(r['ra_fk5']),
                                  np.radians(r['dec_fk5']))

        diffarcsec1.append(np.degrees(diff) * 3600.)

        # FK5 to FK4NoETerms
        c1 = FK5(ra=r['ra_in'] * u.deg,
                 dec=r['dec_in'] * u.deg,
                 equinox=Time(r['equinox_fk5']))
        fk4neframe = FK4NoETerms(obstime=Time(r['obstime']),
                                 equinox=Time(r['equinox_fk4']))
        c2 = c1.transform_to(fk4neframe)

        # Find difference
        diff = angular_separation(c2.ra.radian, c2.dec.radian,
                                  np.radians(r['ra_fk4']),
                                  np.radians(r['dec_fk4']))

        diffarcsec2.append(np.degrees(diff) * 3600.)

    np.testing.assert_array_less(diffarcsec1, TOLERANCE)
    np.testing.assert_array_less(diffarcsec2, TOLERANCE)
コード例 #12
0
def test_transform_to_nonscalar_nodata_frame():
    # https://github.com/astropy/astropy/pull/5254#issuecomment-241592353
    from astropy.coordinates.builtin_frames import ICRS, FK5
    from astropy.time import Time
    times = Time('2016-08-23') + np.linspace(0, 10, 12) * u.day
    coo1 = ICRS(ra=[[0.], [10.], [20.]] * u.deg,
                dec=[[-30.], [30.], [60.]] * u.deg)
    coo2 = coo1.transform_to(FK5(equinox=times))
    assert coo2.shape == (3, 12)
コード例 #13
0
def test_against_pytpm_doc_example():
    """
    Check that Astropy's Ecliptic systems give answers consistent with pyTPM

    Currently this is only testing against the example given in the pytpm docs
    """
    fk5_in = SkyCoord('12h22m54.899s', '15d49m20.57s', frame=FK5(equinox='J2000'))
    pytpm_out = BarycentricMeanEcliptic(lon=178.78256462*u.deg,
                                        lat=16.7597002513*u.deg,
                                        equinox='J2000')
    astropy_out = fk5_in.transform_to(pytpm_out)

    assert pytpm_out.separation(astropy_out) < (1*u.arcsec)
コード例 #14
0
ファイル: test_frames.py プロジェクト: Cadair/astropy
def test_create_nodata_frames():
    from astropy.coordinates.builtin_frames import ICRS, FK4, FK5

    i = ICRS()
    assert len(i.get_frame_attr_names()) == 0

    f5 = FK5()
    assert f5.equinox == FK5.get_frame_attr_names()['equinox']

    f4 = FK4()
    assert f4.equinox == FK4.get_frame_attr_names()['equinox']

    # obstime is special because it's a property that uses equinox if obstime is not set
    assert f4.obstime in (FK4.get_frame_attr_names()['obstime'],
                          FK4.get_frame_attr_names()['equinox'])
コード例 #15
0
def test_fk5_galactic():
    """
    Check that FK5 -> Galactic gives the same as FK5 -> FK4 -> Galactic.
    """

    fk5 = FK5(ra=1*u.deg, dec=2*u.deg)

    direct = fk5.transform_to(Galactic)
    indirect = fk5.transform_to(FK4).transform_to(Galactic)

    assert direct.separation(indirect).degree < 1.e-10

    direct = fk5.transform_to(Galactic)
    indirect = fk5.transform_to(FK4NoETerms).transform_to(Galactic)

    assert direct.separation(indirect).degree < 1.e-10
コード例 #16
0
def test_precession():
    """
    Ensures that FK4 and FK5 coordinates precess their equinoxes
    """
    j2000 = Time('J2000')
    b1950 = Time('B1950')
    j1975 = Time('J1975')
    b1975 = Time('B1975')

    fk4 = FK4(ra=1*u.radian, dec=0.5*u.radian)
    assert fk4.equinox.byear == b1950.byear
    fk4_2 = fk4.transform_to(FK4(equinox=b1975))
    assert fk4_2.equinox.byear == b1975.byear

    fk5 = FK5(ra=1*u.radian, dec=0.5*u.radian)
    assert fk5.equinox.jyear == j2000.jyear
    fk5_2 = fk5.transform_to(FK4(equinox=j1975))
    assert fk5_2.equinox.jyear == j1975.jyear
コード例 #17
0
ファイル: test_frames.py プロジェクト: Cadair/astropy
def test_is_frame_attr_default():
    """
    Check that the `is_frame_attr_default` machinery works as expected
    """
    from astropy.time import Time
    from astropy.coordinates.builtin_frames import FK5

    c1 = FK5(ra=1*u.deg, dec=1*u.deg)
    c2 = FK5(ra=1*u.deg, dec=1*u.deg, equinox=FK5.get_frame_attr_names()['equinox'])
    c3 = FK5(ra=1*u.deg, dec=1*u.deg, equinox=Time('J2001.5'))

    assert c1.equinox == c2.equinox
    assert c1.equinox != c3.equinox

    assert c1.is_frame_attr_default('equinox')
    assert not c2.is_frame_attr_default('equinox')
    assert not c3.is_frame_attr_default('equinox')

    c4 = c1.realize_frame(r.UnitSphericalRepresentation(3*u.deg, 4*u.deg))
    c5 = c2.realize_frame(r.UnitSphericalRepresentation(3*u.deg, 4*u.deg))

    assert c4.is_frame_attr_default('equinox')
    assert not c5.is_frame_attr_default('equinox')
コード例 #18
0
def test_celestial_frame_to_wcs():

    # Import astropy.coordinates here to avoid circular imports
    from astropy.coordinates import ICRS, ITRS, FK5, FK4, FK4NoETerms, Galactic, BaseCoordinateFrame

    class FakeFrame(BaseCoordinateFrame):
        pass

    frame = FakeFrame()
    with pytest.raises(ValueError) as exc:
        celestial_frame_to_wcs(frame)
    assert exc.value.args[0] == ("Could not determine WCS corresponding to "
                                 "the specified coordinate frame.")

    frame = ICRS()
    mywcs = celestial_frame_to_wcs(frame)
    mywcs.wcs.set()
    assert tuple(mywcs.wcs.ctype) == ('RA---TAN', 'DEC--TAN')
    assert mywcs.wcs.radesys == 'ICRS'
    assert np.isnan(mywcs.wcs.equinox)
    assert mywcs.wcs.lonpole == 180
    assert mywcs.wcs.latpole == 0

    frame = FK5(equinox='J1987')
    mywcs = celestial_frame_to_wcs(frame)
    assert tuple(mywcs.wcs.ctype) == ('RA---TAN', 'DEC--TAN')
    assert mywcs.wcs.radesys == 'FK5'
    assert mywcs.wcs.equinox == 1987.

    frame = FK4(equinox='B1982')
    mywcs = celestial_frame_to_wcs(frame)
    assert tuple(mywcs.wcs.ctype) == ('RA---TAN', 'DEC--TAN')
    assert mywcs.wcs.radesys == 'FK4'
    assert mywcs.wcs.equinox == 1982.

    frame = FK4NoETerms(equinox='B1982')
    mywcs = celestial_frame_to_wcs(frame)
    assert tuple(mywcs.wcs.ctype) == ('RA---TAN', 'DEC--TAN')
    assert mywcs.wcs.radesys == 'FK4-NO-E'
    assert mywcs.wcs.equinox == 1982.

    frame = Galactic()
    mywcs = celestial_frame_to_wcs(frame)
    assert tuple(mywcs.wcs.ctype) == ('GLON-TAN', 'GLAT-TAN')
    assert mywcs.wcs.radesys == ''
    assert np.isnan(mywcs.wcs.equinox)

    frame = Galactic()
    mywcs = celestial_frame_to_wcs(frame, projection='CAR')
    assert tuple(mywcs.wcs.ctype) == ('GLON-CAR', 'GLAT-CAR')
    assert mywcs.wcs.radesys == ''
    assert np.isnan(mywcs.wcs.equinox)

    frame = Galactic()
    mywcs = celestial_frame_to_wcs(frame, projection='CAR')
    mywcs.wcs.crval = [100, -30]
    mywcs.wcs.set()
    assert_allclose((mywcs.wcs.lonpole, mywcs.wcs.latpole), (180, 60))

    frame = ITRS(obstime=Time('2017-08-17T12:41:04.43'))
    mywcs = celestial_frame_to_wcs(frame, projection='CAR')
    assert tuple(mywcs.wcs.ctype) == ('TLON-CAR', 'TLAT-CAR')
    assert mywcs.wcs.radesys == 'ITRS'
    assert mywcs.wcs.dateobs == '2017-08-17T12:41:04.430'

    frame = ITRS()
    mywcs = celestial_frame_to_wcs(frame, projection='CAR')
    assert tuple(mywcs.wcs.ctype) == ('TLON-CAR', 'TLAT-CAR')
    assert mywcs.wcs.radesys == 'ITRS'
    assert mywcs.wcs.dateobs == Time('J2000').utc.fits
コード例 #19
0
def test_transform_api():
    from astropy.coordinates.representation import UnitSphericalRepresentation
    from astropy.coordinates.builtin_frames import ICRS, FK5
    from astropy.coordinates.baseframe import frame_transform_graph, BaseCoordinateFrame
    from astropy.coordinates.transformations import DynamicMatrixTransform
    # <------------------------Transformations------------------------------------->
    # Transformation functionality is the key to the whole scheme: they transform
    # low-level classes from one frame to another.

    # (used below but defined above in the API)
    fk5 = FK5(ra=8 * u.hour, dec=5 * u.deg)

    # If no data (or `None`) is given, the class acts as a specifier of a frame, but
    # without any stored data.
    J2001 = time.Time('J2001')
    fk5_J2001_frame = FK5(equinox=J2001)

    # if they do not have data, the string instead is the frame specification
    assert repr(fk5_J2001_frame) == "<FK5 Frame (equinox=J2001.000)>"

    #  Note that, although a frame object is immutable and can't have data added, it
    #  can be used to create a new object that does have data by giving the
    # `realize_frame` method a representation:
    srep = UnitSphericalRepresentation(lon=8 * u.hour, lat=5 * u.deg)
    fk5_j2001_with_data = fk5_J2001_frame.realize_frame(srep)
    assert fk5_j2001_with_data.data is not None
    # Now `fk5_j2001_with_data` is in the same frame as `fk5_J2001_frame`, but it
    # is an actual low-level coordinate, rather than a frame without data.

    # These frames are primarily useful for specifying what a coordinate should be
    # transformed *into*, as they are used by the `transform_to` method
    # E.g., this snippet precesses the point to the new equinox
    newfk5 = fk5.transform_to(fk5_J2001_frame)
    assert newfk5.equinox == J2001

    # classes can also be given to `transform_to`, which then uses the defaults for
    # the frame information:
    samefk5 = fk5.transform_to(FK5)
    # `fk5` was initialized using default `obstime` and `equinox`, so:
    assert_allclose(samefk5.ra, fk5.ra, atol=1e-10 * u.deg)
    assert_allclose(samefk5.dec, fk5.dec, atol=1e-10 * u.deg)

    # transforming to a new frame necessarily loses framespec information if that
    # information is not applicable to the new frame.  This means transforms are not
    # always round-trippable:
    fk5_2 = FK5(ra=8 * u.hour, dec=5 * u.deg, equinox=J2001)
    ic_trans = fk5_2.transform_to(ICRS)

    # `ic_trans` does not have an `equinox`, so now when we transform back to FK5,
    # it's a *different* RA and Dec
    fk5_trans = ic_trans.transform_to(FK5)
    assert not allclose(fk5_2.ra, fk5_trans.ra, rtol=0, atol=1e-10 * u.deg)

    # But if you explicitly give the right equinox, all is fine
    fk5_trans_2 = fk5_2.transform_to(FK5(equinox=J2001))
    assert_allclose(fk5_2.ra, fk5_trans_2.ra, rtol=0, atol=1e-10 * u.deg)

    # Trying to transforming a frame with no data is of course an error:
    with pytest.raises(ValueError):
        FK5(equinox=J2001).transform_to(ICRS)

    # To actually define a new transformation, the same scheme as in the
    # 0.2/0.3 coordinates framework can be re-used - a graph of transform functions
    # connecting various coordinate classes together.  The main changes are:
    # 1) The transform functions now get the frame object they are transforming the
    #    current data into.
    # 2) Frames with additional information need to have a way to transform between
    #    objects of the same class, but with different framespecinfo values

    # An example transform function:
    class SomeNewSystem(BaseCoordinateFrame):
        pass

    @frame_transform_graph.transform(DynamicMatrixTransform, SomeNewSystem,
                                     FK5)
    def new_to_fk5(newobj, fk5frame):
        _ = newobj.obstime
        _ = fk5frame.equinox
        # ... build a *cartesian* transform matrix using `eq` that transforms from
        # the `newobj` frame as observed at `ot` to FK5 an equinox `eq`
        matrix = np.eye(3)
        return matrix
コード例 #20
0
def test_frame_api():
    from astropy.coordinates.representation import SphericalRepresentation, \
                                 UnitSphericalRepresentation
    from astropy.coordinates.builtin_frames import ICRS, FK5
    # <--------------------Reference Frame/"Low-level" classes--------------------->
    # The low-level classes have a dual role: they act as specifiers of coordinate
    # frames and they *may* also contain data as one of the representation objects,
    # in which case they are the actual coordinate objects themselves.

    # They can always accept a representation as a first argument
    icrs = ICRS(UnitSphericalRepresentation(lon=8 * u.hour, lat=5 * u.deg))

    # which is stored as the `data` attribute
    assert icrs.data.lat == 5 * u.deg
    assert icrs.data.lon == 8 * u.hourangle

    # Frames that require additional information like equinoxs or obstimes get them
    # as keyword parameters to the frame constructor.  Where sensible, defaults are
    # used. E.g., FK5 is almost always J2000 equinox
    fk5 = FK5(UnitSphericalRepresentation(lon=8 * u.hour, lat=5 * u.deg))
    J2000 = time.Time('J2000')
    fk5_2000 = FK5(UnitSphericalRepresentation(lon=8 * u.hour, lat=5 * u.deg),
                   equinox=J2000)
    assert fk5.equinox == fk5_2000.equinox

    # the information required to specify the frame is immutable
    J2001 = time.Time('J2001')
    with pytest.raises(AttributeError):
        fk5.equinox = J2001

    # Similar for the representation data.
    with pytest.raises(AttributeError):
        fk5.data = UnitSphericalRepresentation(lon=8 * u.hour, lat=5 * u.deg)

    # There is also a class-level attribute that lists the attributes needed to
    # identify the frame.  These include attributes like `equinox` shown above.
    assert all(nm in ('equinox', 'obstime')
               for nm in fk5.get_frame_attr_names())

    # the result of `get_frame_attr_names` is called for particularly in  the
    # high-level class (discussed below) to allow round-tripping between various
    # frames.  It is also part of the public API for other similar developer /
    # advanced users' use.

    # The actual position information is accessed via the representation objects
    assert_allclose(icrs.represent_as(SphericalRepresentation).lat, 5 * u.deg)
    # shorthand for the above
    assert_allclose(icrs.spherical.lat, 5 * u.deg)
    assert icrs.cartesian.z.value > 0

    # Many frames have a "default" representation, the one in which they are
    # conventionally described, often with a special name for some of the
    # coordinates. E.g., most equatorial coordinate systems are spherical with RA and
    # Dec. This works simply as a shorthand for the longer form above

    assert_allclose(icrs.dec, 5 * u.deg)
    assert_allclose(fk5.ra, 8 * u.hourangle)

    assert icrs.representation_type == SphericalRepresentation

    # low-level classes can also be initialized with names valid for that representation
    # and frame:
    icrs_2 = ICRS(ra=8 * u.hour, dec=5 * u.deg, distance=1 * u.kpc)
    assert_allclose(icrs.ra, icrs_2.ra)

    # and these are taken as the default if keywords are not given:
    # icrs_nokwarg = ICRS(8*u.hour, 5*u.deg, distance=1*u.kpc)
    # assert icrs_nokwarg.ra == icrs_2.ra and icrs_nokwarg.dec == icrs_2.dec

    # they also are capable of computing on-sky or 3d separations from each other,
    # which will be a direct port of the existing methods:
    coo1 = ICRS(ra=0 * u.hour, dec=0 * u.deg)
    coo2 = ICRS(ra=0 * u.hour, dec=1 * u.deg)
    # `separation` is the on-sky separation
    assert coo1.separation(coo2).degree == 1.0

    # while `separation_3d` includes the 3D distance information
    coo3 = ICRS(ra=0 * u.hour, dec=0 * u.deg, distance=1 * u.kpc)
    coo4 = ICRS(ra=0 * u.hour, dec=0 * u.deg, distance=2 * u.kpc)
    assert coo3.separation_3d(coo4).kpc == 1.0

    # The next example fails because `coo1` and `coo2` don't have distances
    with pytest.raises(ValueError):
        assert coo1.separation_3d(coo2).kpc == 1.0