def test_sep(): from astropy.coordinates.builtin_frames import ICRS i1 = ICRS(ra=0*u.deg, dec=1*u.deg) i2 = ICRS(ra=0*u.deg, dec=2*u.deg) sep = i1.separation(i2) assert sep.deg == 1 i3 = ICRS(ra=[1, 2]*u.deg, dec=[3, 4]*u.deg, distance=[5, 6]*u.kpc) i4 = ICRS(ra=[1, 2]*u.deg, dec=[3, 4]*u.deg, distance=[4, 5]*u.kpc) sep3d = i3.separation_3d(i4) assert_allclose(sep3d.to(u.kpc), np.array([1, 1])*u.kpc) # check that it works even with velocities i5 = ICRS(ra=[1, 2]*u.deg, dec=[3, 4]*u.deg, distance=[5, 6]*u.kpc, pm_ra_cosdec=[1, 2]*u.mas/u.yr, pm_dec=[3, 4]*u.mas/u.yr, radial_velocity=[5, 6]*u.km/u.s) i6 = ICRS(ra=[1, 2]*u.deg, dec=[3, 4]*u.deg, distance=[7, 8]*u.kpc, pm_ra_cosdec=[1, 2]*u.mas/u.yr, pm_dec=[3, 4]*u.mas/u.yr, radial_velocity=[5, 6]*u.km/u.s) sep3d = i5.separation_3d(i6) assert_allclose(sep3d.to(u.kpc), np.array([2, 2])*u.kpc)
def test_sep(): from astropy.coordinates.builtin_frames import ICRS i1 = ICRS(ra=0*u.deg, dec=1*u.deg) i2 = ICRS(ra=0*u.deg, dec=2*u.deg) sep = i1.separation(i2) assert sep.deg == 1 i3 = ICRS(ra=[1, 2]*u.deg, dec=[3, 4]*u.deg, distance=[5, 6]*u.kpc) i4 = ICRS(ra=[1, 2]*u.deg, dec=[3, 4]*u.deg, distance=[4, 5]*u.kpc) sep3d = i3.separation_3d(i4) assert_allclose(sep3d.to(u.kpc), np.array([1, 1])*u.kpc) # check that it works even with velocities i5 = ICRS(ra=[1, 2]*u.deg, dec=[3, 4]*u.deg, distance=[5, 6]*u.kpc, pm_ra_cosdec=[1, 2]*u.mas/u.yr, pm_dec=[3, 4]*u.mas/u.yr, radial_velocity=[5, 6]*u.km/u.s) i6 = ICRS(ra=[1, 2]*u.deg, dec=[3, 4]*u.deg, distance=[7, 8]*u.kpc, pm_ra_cosdec=[1, 2]*u.mas/u.yr, pm_dec=[3, 4]*u.mas/u.yr, radial_velocity=[5, 6]*u.km/u.s) sep3d = i5.separation_3d(i6) assert_allclose(sep3d.to(u.kpc), np.array([2, 2])*u.kpc) # 3d separations of dimensionless distances should still work i7 = ICRS(ra=1*u.deg, dec=2*u.deg, distance=3*u.one) i8 = ICRS(ra=1*u.deg, dec=2*u.deg, distance=4*u.one) sep3d = i7.separation_3d(i8) assert_allclose(sep3d, 1*u.one) # but should fail with non-dimensionless with pytest.raises(ValueError): i7.separation_3d(i3)
def test_3d_separations(): """ Test 3D separation functionality """ c1 = ICRS(ra=1*u.deg, dec=1*u.deg, distance=9*u.kpc) c2 = ICRS(ra=1*u.deg, dec=1*u.deg, distance=10*u.kpc) sep3d = c2.separation_3d(c1) assert isinstance(sep3d, Distance) assert_allclose(sep3d - 1*u.kpc, 0*u.kpc, atol=1e-12*u.kpc)
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 raises(AttributeError): fk5.equinox = J2001 # Similar for the representation data. with 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 raises(ValueError): assert coo1.separation_3d(coo2).kpc == 1.0