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')
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)
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])
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)
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)
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'])
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])
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.)]>')
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)
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>"
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)
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)
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)
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
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
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')
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
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
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