def test_gcrs_diffs(): time = Time('J2017') gf = GCRS(obstime=time) sung = get_sun(time) # should have very little vhelio # qtr-year off sun location should be the direction of ~ maximal vhelio qtrsung = get_sun(time-.25*u.year) # now we use those essentially as directions where the velocities should # be either maximal or minimal - with or perpendiculat to Earh's orbit msungr = CartesianRepresentation(-sung.cartesian.xyz).represent_as(SphericalRepresentation) suni = ICRS(ra=msungr.lon, dec=msungr.lat, distance=100*u.au, pm_ra_cosdec=0*u.marcsec/u.yr, pm_dec=0*u.marcsec/u.yr, radial_velocity=0*u.km/u.s) qtrsuni = ICRS(ra=qtrsung.ra, dec=qtrsung.dec, distance=100*u.au, pm_ra_cosdec=0*u.marcsec/u.yr, pm_dec=0*u.marcsec/u.yr, radial_velocity=0*u.km/u.s) # Now we transform those parallel- and perpendicular-to Earth's orbit # directions to GCRS, which should shift the velocity to either include # the Earth's velocity vector, or not (for parallel and perpendicular, # respectively). sung = suni.transform_to(gf) qtrsung = qtrsuni.transform_to(gf) # should be high along the ecliptic-not-sun sun axis and # low along the sun axis assert np.abs(qtrsung.radial_velocity) > 30*u.km/u.s assert np.abs(qtrsung.radial_velocity) < 40*u.km/u.s assert np.abs(sung.radial_velocity) < 1*u.km/u.s suni2 = sung.transform_to(ICRS) assert np.all(np.abs(suni2.data.differentials['s'].d_xyz) < 3e-5*u.km/u.s) qtrisun2 = qtrsung.transform_to(ICRS) assert np.all(np.abs(qtrisun2.data.differentials['s'].d_xyz) < 3e-5*u.km/u.s)
def test_create_data_frames(): from astropy.coordinates.builtin_frames import ICRS # from repr i1 = ICRS(r.SphericalRepresentation(1*u.deg, 2*u.deg, 3*u.kpc)) i2 = ICRS(r.UnitSphericalRepresentation(lon=1*u.deg, lat=2*u.deg)) # from preferred name i3 = ICRS(ra=1*u.deg, dec=2*u.deg, distance=3*u.kpc) i4 = ICRS(ra=1*u.deg, dec=2*u.deg) assert i1.data.lat == i3.data.lat assert i1.data.lon == i3.data.lon assert i1.data.distance == i3.data.distance assert i2.data.lat == i4.data.lat assert i2.data.lon == i4.data.lon # now make sure the preferred names work as properties assert_allclose(i1.ra, i3.ra) assert_allclose(i2.ra, i4.ra) assert_allclose(i1.distance, i3.distance) with pytest.raises(AttributeError): i1.ra = [11.]*u.deg
def test_all_arg_options(kwargs): # Above is a list of all possible valid combinations of arguments. # Here we do a simple thing and just verify that passing them in, we have # access to the relevant attributes from the resulting object icrs = ICRS(**kwargs) gal = icrs.transform_to(Galactic) repr_gal = repr(gal) for k in kwargs: if k == 'differential_type': continue getattr(icrs, k) if 'pm_ra_cosdec' in kwargs: # should have both assert 'pm_l_cosb' in repr_gal assert 'pm_b' in repr_gal assert 'mas / yr' in repr_gal if 'radial_velocity' not in kwargs: assert 'radial_velocity' not in repr_gal if 'radial_velocity' in kwargs: assert 'radial_velocity' in repr_gal assert 'km / s' in repr_gal if 'pm_ra_cosdec' not in kwargs: assert 'pm_l_cosb' not in repr_gal assert 'pm_b' not in repr_gal
def test_altaz_diffs(): time = Time('J2015') + np.linspace(-1, 1, 1000)*u.day loc = get_builtin_sites()['greenwich'] aa = AltAz(obstime=time, location=loc) icoo = ICRS(np.zeros_like(time)*u.deg, 10*u.deg, 100*u.au, pm_ra_cosdec=np.zeros_like(time)*u.marcsec/u.yr, pm_dec=0*u.marcsec/u.yr, radial_velocity=0*u.km/u.s) acoo = icoo.transform_to(aa) # Make sure the change in radial velocity over ~2 days isn't too much # more than the rotation speed of the Earth - some excess is expected # because the orbit also shifts the RV, but it should be pretty small # over this short a time. assert np.ptp(acoo.radial_velocity)/2 < (2*np.pi*constants.R_earth/u.day)*1.2 # MAGIC NUMBER cdiff = acoo.data.differentials['s'].represent_as(CartesianDifferential, acoo.data) # The "total" velocity should be > c, because the *tangential* velocity # isn't a True velocity, but rather an induced velocity due to the Earth's # rotation at a distance of 100 AU assert np.all(np.sum(cdiff.d_xyz**2, axis=0)**0.5 > constants.c)
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_arraytransforms(): """ Test that transforms to/from ecliptic coordinates work on array coordinates (not testing for accuracy.) """ ra = np.ones((4, ), dtype=float) * u.deg dec = 2*np.ones((4, ), dtype=float) * u.deg distance = np.ones((4, ), dtype=float) * u.au test_icrs = ICRS(ra=ra, dec=dec, distance=distance) test_gcrs = GCRS(test_icrs.data) bary_arr = test_icrs.transform_to(BarycentricTrueEcliptic) assert bary_arr.shape == ra.shape helio_arr = test_icrs.transform_to(HeliocentricTrueEcliptic) assert helio_arr.shape == ra.shape geo_arr = test_gcrs.transform_to(GeocentricTrueEcliptic) assert geo_arr.shape == ra.shape # now check that we also can go back the other way without shape problems bary_icrs = bary_arr.transform_to(ICRS) assert bary_icrs.shape == test_icrs.shape helio_icrs = helio_arr.transform_to(ICRS) assert helio_icrs.shape == test_icrs.shape geo_gcrs = geo_arr.transform_to(GCRS) assert geo_gcrs.shape == test_gcrs.shape
def test_skyoffset_functional_ra(): # we do the 12)[1:-1] business because sometimes machine precision issues # lead to results that are either ~0 or ~360, which mucks up the final # comparison and leads to spurious failures. So this just avoids that by # staying away from the edges input_ra = np.linspace(0, 360, 12)[1:-1] input_dec = np.linspace(-90, 90, 12)[1:-1] icrs_coord = ICRS(ra=input_ra*u.deg, dec=input_dec*u.deg, distance=1.*u.kpc) for ra in np.linspace(0, 360, 24): # expected rotation expected = ICRS(ra=np.linspace(0-ra, 360-ra, 12)[1:-1]*u.deg, dec=np.linspace(-90, 90, 12)[1:-1]*u.deg, distance=1.*u.kpc) expected_xyz = expected.cartesian.xyz # actual transformation to the frame skyoffset_frame = SkyOffsetFrame(origin=ICRS(ra*u.deg, 0*u.deg)) actual = icrs_coord.transform_to(skyoffset_frame) actual_xyz = actual.cartesian.xyz # back to ICRS roundtrip = actual.transform_to(ICRS) roundtrip_xyz = roundtrip.cartesian.xyz # Verify assert_allclose(actual_xyz, expected_xyz, atol=1E-5*u.kpc) assert_allclose(icrs_coord.ra, roundtrip.ra, atol=1E-5*u.deg) assert_allclose(icrs_coord.dec, roundtrip.dec, atol=1E-5*u.deg) assert_allclose(icrs_coord.distance, roundtrip.distance, atol=1E-5*u.kpc)
def test_getitem_representation(): """ Make sure current representation survives __getitem__ even if different from data representation. """ from astropy.coordinates.builtin_frames import ICRS c = ICRS([1, 1] * u.deg, [2, 2] * u.deg) c.representation_type = 'cartesian' assert c[0].representation_type is r.CartesianRepresentation
def test_skyoffset_velocity(): c = ICRS(ra=170.9*u.deg, dec=-78.4*u.deg, pm_ra_cosdec=74.4134*u.mas/u.yr, pm_dec=-93.2342*u.mas/u.yr) skyoffset_frame = SkyOffsetFrame(origin=c) c_skyoffset = c.transform_to(skyoffset_frame) assert_allclose(c_skyoffset.pm_lon_coslat, c.pm_ra_cosdec) assert_allclose(c_skyoffset.pm_lat, c.pm_dec)
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_rotation(rotation, expectedlatlon): origin = ICRS(45*u.deg, 45*u.deg) target = ICRS(45*u.deg, 46*u.deg) aframe = SkyOffsetFrame(origin=origin, rotation=rotation) trans = target.transform_to(aframe) assert_allclose([trans.lon.wrap_at(180*u.deg), trans.lat], expectedlatlon, atol=1e-10*u.deg)
def test_slicing_preserves_differential(): icrs = ICRS(ra=37.4*u.deg, dec=-55.8*u.deg, distance=150*u.pc, pm_ra_cosdec=-21.2*u.mas/u.yr, pm_dec=17.1*u.mas/u.yr, radial_velocity=105.7*u.km/u.s) icrs2 = icrs.reshape(1,1)[:1,0] for name in icrs.representation_component_names.keys(): assert getattr(icrs, name) == getattr(icrs2, name)[0] for name in icrs.get_representation_component_names('s').keys(): assert getattr(icrs, name) == getattr(icrs2, name)[0]
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_ecliptic_true_mean(trueframe, meanframe): """ Check that the ecliptic true/mean transformations at least roundtrip """ icrs = ICRS(1*u.deg, 2*u.deg, distance=1.5*R_sun) truecoo = icrs.transform_to(trueframe) meancoo = icrs.transform_to(meanframe) truecoo2 = icrs.transform_to(trueframe) assert not quantity_allclose(truecoo.cartesian.xyz, meancoo.cartesian.xyz) assert quantity_allclose(truecoo.cartesian.xyz, truecoo2.cartesian.xyz)
def test_galactocentric(): # when z_sun=0, transformation should be very similar to Galactic icrs_coord = ICRS(ra=np.linspace(0, 360, 10)*u.deg, dec=np.linspace(-90, 90, 10)*u.deg, distance=1.*u.kpc) g_xyz = icrs_coord.transform_to(Galactic).cartesian.xyz gc_xyz = icrs_coord.transform_to(Galactocentric(z_sun=0*u.kpc)).cartesian.xyz diff = np.abs(g_xyz - gc_xyz) assert allclose(diff[0], 8.3*u.kpc, atol=1E-5*u.kpc) assert allclose(diff[1:], 0*u.kpc, atol=1E-5*u.kpc) # generate some test coordinates g = Galactic(l=[0, 0, 45, 315]*u.deg, b=[-45, 45, 0, 0]*u.deg, distance=[np.sqrt(2)]*4*u.kpc) xyz = g.transform_to(Galactocentric(galcen_distance=1.*u.kpc, z_sun=0.*u.pc)).cartesian.xyz true_xyz = np.array([[0, 0, -1.], [0, 0, 1], [0, 1, 0], [0, -1, 0]]).T*u.kpc assert allclose(xyz.to(u.kpc), true_xyz.to(u.kpc), atol=1E-5*u.kpc) # check that ND arrays work # from Galactocentric to Galactic x = np.linspace(-10., 10., 100) * u.kpc y = np.linspace(-10., 10., 100) * u.kpc z = np.zeros_like(x) g1 = Galactocentric(x=x, y=y, z=z) g2 = Galactocentric(x=x.reshape(100, 1, 1), y=y.reshape(100, 1, 1), z=z.reshape(100, 1, 1)) g1t = g1.transform_to(Galactic) g2t = g2.transform_to(Galactic) assert_allclose(g1t.cartesian.xyz, g2t.cartesian.xyz[:, :, 0, 0]) # from Galactic to Galactocentric l = np.linspace(15, 30., 100) * u.deg b = np.linspace(-10., 10., 100) * u.deg d = np.ones_like(l.value) * u.kpc g1 = Galactic(l=l, b=b, distance=d) g2 = Galactic(l=l.reshape(100, 1, 1), b=b.reshape(100, 1, 1), distance=d.reshape(100, 1, 1)) g1t = g1.transform_to(Galactocentric) g2t = g2.transform_to(Galactocentric) np.testing.assert_almost_equal(g1t.cartesian.xyz.value, g2t.cartesian.xyz.value[:, :, 0, 0])
def test_converting_units(): import re from astropy.coordinates.baseframe import RepresentationMapping from astropy.coordinates.builtin_frames import ICRS, FK5 # this is a regular expression that with split (see below) removes what's # the decimal point to fix rounding problems rexrepr = re.compile(r'(.*?=\d\.).*?( .*?=\d\.).*?( .*)') # Use values that aren't subject to rounding down to X.9999... i2 = ICRS(ra=2.*u.deg, dec=2.*u.deg) i2_many = ICRS(ra=[2., 4.]*u.deg, dec=[2., -8.1]*u.deg) # converting from FK5 to ICRS and back changes the *internal* representation, # but it should still come out in the preferred form i4 = i2.transform_to(FK5).transform_to(ICRS) i4_many = i2_many.transform_to(FK5).transform_to(ICRS) ri2 = ''.join(rexrepr.split(repr(i2))) ri4 = ''.join(rexrepr.split(repr(i4))) assert ri2 == ri4 assert i2.data.lon.unit != i4.data.lon.unit # Internal repr changed ri2_many = ''.join(rexrepr.split(repr(i2_many))) ri4_many = ''.join(rexrepr.split(repr(i4_many))) assert ri2_many == ri4_many assert i2_many.data.lon.unit != i4_many.data.lon.unit # Internal repr changed # but that *shouldn't* hold if we turn off units for the representation class FakeICRS(ICRS): frame_specific_representation_info = { 'spherical': [RepresentationMapping('lon', 'ra', u.hourangle), RepresentationMapping('lat', 'dec', None), RepresentationMapping('distance', 'distance')] # should fall back to default of None unit } fi = FakeICRS(i4.data) ri2 = ''.join(rexrepr.split(repr(i2))) rfi = ''.join(rexrepr.split(repr(fi))) rfi = re.sub('FakeICRS', 'ICRS', rfi) # Force frame name to match assert ri2 != rfi # the attributes should also get the right units assert i2.dec.unit == i4.dec.unit # unless no/explicitly given units assert i2.dec.unit != fi.dec.unit assert i2.ra.unit != fi.ra.unit assert fi.ra.unit == u.hourangle
def test_frame_affinetransform(kwargs, expect_success): """There are already tests in test_transformations.py that check that an AffineTransform fails without full-space data, but this just checks that things work as expected at the frame level as well. """ icrs = ICRS(**kwargs) if expect_success: gc = icrs.transform_to(Galactocentric) else: with pytest.raises(ConvertError): icrs.transform_to(Galactocentric)
class TestHCRS(): """ Check HCRS<->ICRS coordinate conversions. Uses ICRS Solar positions predicted by get_body_barycentric; with `t1` and `tarr` as defined below, the ICRS Solar positions were predicted using, e.g. coord.ICRS(coord.get_body_barycentric(tarr, 'sun')). """ def setup(self): self.t1 = Time("2013-02-02T23:00") self.t2 = Time("2013-08-02T23:00") self.tarr = Time(["2013-02-02T23:00", "2013-08-02T23:00"]) self.sun_icrs_scalar = ICRS(ra=244.52984668*u.deg, dec=-22.36943723*u.deg, distance=406615.66347377*u.km) # array of positions corresponds to times in `tarr` self.sun_icrs_arr = ICRS(ra=[244.52989062, 271.40976248]*u.deg, dec=[-22.36943605, -25.07431079]*u.deg, distance=[406615.66347377, 375484.13558956]*u.km) # corresponding HCRS positions self.sun_hcrs_t1 = HCRS(CartesianRepresentation([0.0, 0.0, 0.0] * u.km), obstime=self.t1) twod_rep = CartesianRepresentation([[0.0, 0.0], [0.0, 0.0], [0.0, 0.0]] * u.km) self.sun_hcrs_tarr = HCRS(twod_rep, obstime=self.tarr) self.tolerance = 5*u.km def test_from_hcrs(self): # test scalar transform transformed = self.sun_hcrs_t1.transform_to(ICRS()) separation = transformed.separation_3d(self.sun_icrs_scalar) assert_allclose(separation, 0*u.km, atol=self.tolerance) # test non-scalar positions and times transformed = self.sun_hcrs_tarr.transform_to(ICRS()) separation = transformed.separation_3d(self.sun_icrs_arr) assert_allclose(separation, 0*u.km, atol=self.tolerance) def test_from_icrs(self): # scalar positions transformed = self.sun_icrs_scalar.transform_to(HCRS(obstime=self.t1)) separation = transformed.separation_3d(self.sun_hcrs_t1) assert_allclose(separation, 0*u.km, atol=self.tolerance) # nonscalar positions transformed = self.sun_icrs_arr.transform_to(HCRS(obstime=self.tarr)) separation = transformed.separation_3d(self.sun_hcrs_tarr) assert_allclose(separation, 0*u.km, atol=self.tolerance)
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_roundtrip_scalar(): icrs = ICRS(ra=1*u.deg, dec=2*u.deg, distance=3*u.au) gcrs = GCRS(icrs.cartesian) bary = icrs.transform_to(BarycentricTrueEcliptic) helio = icrs.transform_to(HeliocentricTrueEcliptic) geo = gcrs.transform_to(GeocentricTrueEcliptic) bary_icrs = bary.transform_to(ICRS) helio_icrs = helio.transform_to(ICRS) geo_gcrs = geo.transform_to(GCRS) assert quantity_allclose(bary_icrs.cartesian.xyz, icrs.cartesian.xyz) assert quantity_allclose(helio_icrs.cartesian.xyz, icrs.cartesian.xyz) assert quantity_allclose(geo_gcrs.cartesian.xyz, gcrs.cartesian.xyz)
def test_xhip_galactic(hip, ra, dec, pmra, pmdec, glon, glat, dist, pmglon, pmglat, rv, U, V, W): i = ICRS(ra*u.deg, dec*u.deg, dist*u.pc, pm_ra_cosdec=pmra*u.marcsec/u.yr, pm_dec=pmdec*u.marcsec/u.yr, radial_velocity=rv*u.km/u.s) g = i.transform_to(Galactic) # precision is limited by 2-deciimal digit string representation of pms assert quantity_allclose(g.pm_l_cosb, pmglon*u.marcsec/u.yr, atol=.01*u.marcsec/u.yr) assert quantity_allclose(g.pm_b, pmglat*u.marcsec/u.yr, atol=.01*u.marcsec/u.yr) # make sure UVW also makes sense uvwg = g.cartesian.differentials['s'] # precision is limited by 1-decimal digit string representation of vels assert quantity_allclose(uvwg.d_x, U*u.km/u.s, atol=.1*u.km/u.s) assert quantity_allclose(uvwg.d_y, V*u.km/u.s, atol=.1*u.km/u.s) assert quantity_allclose(uvwg.d_z, W*u.km/u.s, atol=.1*u.km/u.s)
def test_dynamic_attrs(): from astropy.coordinates.builtin_frames import ICRS c = ICRS(1*u.deg, 2*u.deg) assert 'ra' in dir(c) assert 'dec' in dir(c) with pytest.raises(AttributeError) as err: c.blahblah assert "object has no attribute 'blahblah'" in str(err) with pytest.raises(AttributeError) as err: c.ra = 1 assert "Cannot set any frame attribute" in str(err) c.blahblah = 1 assert c.blahblah == 1
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_ecliptic_heliobary(): """ Check that the ecliptic transformations for heliocentric and barycentric at least more or less make sense """ icrs = ICRS(1*u.deg, 2*u.deg, distance=1.5*R_sun) bary = icrs.transform_to(BarycentricTrueEcliptic) helio = icrs.transform_to(HeliocentricTrueEcliptic) # make sure there's a sizable distance shift - in 3d hundreds of km, but # this is 1D so we allow it to be somewhat smaller assert np.abs(bary.distance - helio.distance) > 1*u.km # now make something that's got the location of helio but in bary's frame. # this is a convenience to allow `separation` to work as expected helio_in_bary_frame = bary.realize_frame(helio.cartesian) assert bary.separation(helio_in_bary_frame) > 1*u.arcmin
def test_numerical_limits(distance): """ Tests the numerical stability of the default settings for the finite difference transformation calculation. This is *known* to fail for at >~1kpc, but this may be improved in future versions. """ time = Time('J2017') + np.linspace(-.5, .5, 100)*u.year icoo = ICRS(ra=0*u.deg, dec=10*u.deg, distance=distance, pm_ra_cosdec=0*u.marcsec/u.yr, pm_dec=0*u.marcsec/u.yr, radial_velocity=0*u.km/u.s) gcoo = icoo.transform_to(GCRS(obstime=time)) rv = gcoo.radial_velocity.to('km/s') # if its a lot bigger than this - ~the maximal velocity shift along # the direction above with a small allowance for noise - finite-difference # rounding errors have ruined the calculation assert np.ptp(rv) < 65*u.km/u.s
def test_faux_lsr(dt, symmetric): class LSR2(LSR): obstime = TimeAttribute(default=J2000) @frame_transform_graph.transform(FunctionTransformWithFiniteDifference, ICRS, LSR2, finite_difference_dt=dt, symmetric_finite_difference=symmetric) def icrs_to_lsr(icrs_coo, lsr_frame): dt = lsr_frame.obstime - J2000 offset = lsr_frame.v_bary * dt.to(u.second) return lsr_frame.realize_frame(icrs_coo.data.without_differentials() + offset) @frame_transform_graph.transform(FunctionTransformWithFiniteDifference, LSR2, ICRS, finite_difference_dt=dt, symmetric_finite_difference=symmetric) def lsr_to_icrs(lsr_coo, icrs_frame): dt = lsr_coo.obstime - J2000 offset = lsr_coo.v_bary * dt.to(u.second) return icrs_frame.realize_frame(lsr_coo.data - offset) ic = ICRS(ra=12.3*u.deg, dec=45.6*u.deg, distance=7.8*u.au, pm_ra_cosdec=0*u.marcsec/u.yr, pm_dec=0*u.marcsec/u.yr, radial_velocity=0*u.km/u.s) lsrc = ic.transform_to(LSR2()) assert quantity_allclose(ic.cartesian.xyz, lsrc.cartesian.xyz) idiff = ic.cartesian.differentials['s'] ldiff = lsrc.cartesian.differentials['s'] change = (ldiff.d_xyz - idiff.d_xyz).to(u.km/u.s) totchange = np.sum(change**2)**0.5 assert quantity_allclose(totchange, np.sum(lsrc.v_bary.d_xyz**2)**0.5) ic2 = ICRS(ra=120.3*u.deg, dec=45.6*u.deg, distance=7.8*u.au, pm_ra_cosdec=0*u.marcsec/u.yr, pm_dec=10*u.marcsec/u.yr, radial_velocity=1000*u.km/u.s) lsrc2 = ic2.transform_to(LSR2()) ic2_roundtrip = lsrc2.transform_to(ICRS) tot = np.sum(lsrc2.cartesian.differentials['s'].d_xyz**2)**0.5 assert np.abs(tot.to('km/s') - 1000*u.km/u.s) < 20*u.km/u.s assert quantity_allclose(ic2.cartesian.xyz, ic2_roundtrip.cartesian.xyz)
def test_skyoffset_functional_ra_dec(): # we do the 12)[1:-1] business because sometimes machine precision issues # lead to results that are either ~0 or ~360, which mucks up the final # comparison and leads to spurious failures. So this just avoids that by # staying away from the edges input_ra = np.linspace(0, 360, 12)[1:-1] input_dec = np.linspace(-90, 90, 12)[1:-1] input_ra_rad = np.deg2rad(input_ra) input_dec_rad = np.deg2rad(input_dec) icrs_coord = ICRS(ra=input_ra*u.deg, dec=input_dec*u.deg, distance=1.*u.kpc) for ra in np.linspace(0, 360, 10): for dec in np.linspace(-90, 90, 5): # expected rotation dec_rad = -np.deg2rad(dec) ra_rad = np.deg2rad(ra) expected_x = (-np.sin(input_dec_rad) * np.sin(dec_rad) + np.cos(input_ra_rad) * np.cos(input_dec_rad) * np.cos(dec_rad) * np.cos(ra_rad) + np.sin(input_ra_rad) * np.cos(input_dec_rad) * np.cos(dec_rad) * np.sin(ra_rad)) expected_y = (np.sin(input_ra_rad) * np.cos(input_dec_rad) * np.cos(ra_rad) - np.cos(input_ra_rad) * np.cos(input_dec_rad) * np.sin(ra_rad)) expected_z = (np.sin(input_dec_rad) * np.cos(dec_rad) + np.sin(dec_rad) * np.cos(ra_rad) * np.cos(input_ra_rad) * np.cos(input_dec_rad) + np.sin(dec_rad) * np.sin(ra_rad) * np.sin(input_ra_rad) * np.cos(input_dec_rad)) expected = SkyCoord(x=expected_x, y=expected_y, z=expected_z, unit='kpc', representation_type='cartesian') expected_xyz = expected.cartesian.xyz # actual transformation to the frame skyoffset_frame = SkyOffsetFrame(origin=ICRS(ra*u.deg, dec*u.deg)) actual = icrs_coord.transform_to(skyoffset_frame) actual_xyz = actual.cartesian.xyz # back to ICRS roundtrip = actual.transform_to(ICRS) # Verify assert_allclose(actual_xyz, expected_xyz, atol=1E-5*u.kpc) assert_allclose(icrs_coord.ra, roundtrip.ra, atol=1E-4*u.deg) assert_allclose(icrs_coord.dec, roundtrip.dec, atol=1E-5*u.deg) assert_allclose(icrs_coord.distance, roundtrip.distance, atol=1E-5*u.kpc)
def test_shorthand_attributes(): # Check that attribute access works # for array data: n = 4 icrs1 = ICRS(ra=np.random.uniform(0, 360, n)*u.deg, dec=np.random.uniform(-90, 90, n)*u.deg, distance=100*u.pc, pm_ra_cosdec=np.random.normal(0, 100, n)*u.mas/u.yr, pm_dec=np.random.normal(0, 100, n)*u.mas/u.yr, radial_velocity=np.random.normal(0, 100, n)*u.km/u.s) v = icrs1.velocity pm = icrs1.proper_motion assert quantity_allclose(pm[0], icrs1.pm_ra_cosdec) assert quantity_allclose(pm[1], icrs1.pm_dec) # for scalar data: icrs2 = ICRS(ra=37.4*u.deg, dec=-55.8*u.deg, distance=150*u.pc, pm_ra_cosdec=-21.2*u.mas/u.yr, pm_dec=17.1*u.mas/u.yr, radial_velocity=105.7*u.km/u.s) v = icrs2.velocity pm = icrs2.proper_motion assert quantity_allclose(pm[0], icrs2.pm_ra_cosdec) assert quantity_allclose(pm[1], icrs2.pm_dec) # check that it fails where we expect: # no distance rv = 105.7*u.km/u.s icrs3 = ICRS(ra=37.4*u.deg, dec=-55.8*u.deg, pm_ra_cosdec=-21.2*u.mas/u.yr, pm_dec=17.1*u.mas/u.yr, radial_velocity=rv) with pytest.raises(ValueError): icrs3.velocity icrs3.set_representation_cls('cartesian') assert hasattr(icrs3, 'radial_velocity') assert quantity_allclose(icrs3.radial_velocity, rv) icrs4 = ICRS(x=30*u.pc, y=20*u.pc, z=11*u.pc, v_x=10*u.km/u.s, v_y=10*u.km/u.s, v_z=10*u.km/u.s, representation_type=r.CartesianRepresentation, differential_type=r.CartesianDifferential) icrs4.radial_velocity
def setup(self): self.t1 = Time("2013-02-02T23:00") self.t2 = Time("2013-08-02T23:00") self.tarr = Time(["2013-02-02T23:00", "2013-08-02T23:00"]) self.sun_icrs_scalar = ICRS(ra=244.52984668*u.deg, dec=-22.36943723*u.deg, distance=406615.66347377*u.km) # array of positions corresponds to times in `tarr` self.sun_icrs_arr = ICRS(ra=[244.52989062, 271.40976248]*u.deg, dec=[-22.36943605, -25.07431079]*u.deg, distance=[406615.66347377, 375484.13558956]*u.km) # corresponding HCRS positions self.sun_hcrs_t1 = HCRS(CartesianRepresentation([0.0, 0.0, 0.0] * u.km), obstime=self.t1) twod_rep = CartesianRepresentation([[0.0, 0.0], [0.0, 0.0], [0.0, 0.0]] * u.km) self.sun_hcrs_tarr = HCRS(twod_rep, obstime=self.tarr) self.tolerance = 5*u.km
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_missing_component_error_names(): """ This test checks that the component names are frame component names, not representation or differential names, when referenced in an exception raised when not passing in enough data. For example: ICRS(ra=10*u.deg) should state: TypeError: __init__() missing 1 required positional argument: 'dec' """ from astropy.coordinates.builtin_frames import ICRS with pytest.raises(TypeError) as e: ICRS(ra=150 * u.deg) assert "missing 1 required positional argument: 'dec'" in str(e.value) with pytest.raises(TypeError) as e: ICRS(ra=150*u.deg, dec=-11*u.deg, pm_ra=100*u.mas/u.yr, pm_dec=10*u.mas/u.yr) assert "pm_ra_cosdec" in str(e.value)
def test_replicating(): from astropy.coordinates.builtin_frames import ICRS, AltAz from astropy.time import Time i = ICRS(ra=[1]*u.deg, dec=[2]*u.deg) icopy = i.replicate(copy=True) irepl = i.replicate(copy=False) i.data._lat[:] = 0*u.deg assert np.all(i.data.lat == irepl.data.lat) assert np.all(i.data.lat != icopy.data.lat) iclone = i.replicate_without_data() assert i.has_data assert not iclone.has_data aa = AltAz(alt=1*u.deg, az=2*u.deg, obstime=Time('J2000')) aaclone = aa.replicate_without_data(obstime=Time('J2001')) assert not aaclone.has_data assert aa.obstime != aaclone.obstime assert aa.pressure == aaclone.pressure assert aa.obswl == aaclone.obswl
def test_cache_clear(): from astropy.coordinates.builtin_frames import ICRS i = ICRS(1*u.deg, 2*u.deg) # Add an in frame units version of the rep to the cache. repr(i) assert len(i.cache['representation']) == 2 i.cache.clear() assert len(i.cache['representation']) == 0
def setup(self): self.t1 = Time("2013-02-02T23:00") self.t2 = Time("2013-08-02T23:00") self.tarr = Time(["2013-02-02T23:00", "2013-08-02T23:00"]) self.sun_icrs_scalar = ICRS(ra=244.52984668 * u.deg, dec=-22.36943723 * u.deg, distance=406615.66347377 * u.km) # array of positions corresponds to times in `tarr` self.sun_icrs_arr = ICRS(ra=[244.52989062, 271.40976248] * u.deg, dec=[-22.36943605, -25.07431079] * u.deg, distance=[406615.66347377, 375484.13558956] * u.km) # corresponding HCRS positions self.sun_hcrs_t1 = HCRS(CartesianRepresentation([0.0, 0.0, 0.0] * u.km), obstime=self.t1) twod_rep = CartesianRepresentation( [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0]] * u.km) self.sun_hcrs_tarr = HCRS(twod_rep, obstime=self.tarr) self.tolerance = 5 * u.km
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' ' ({})>').format(' 1., 2.' if NUMPY_LT_1_14 else '1., 2.') assert repr(i3) == ( '<ICRS Coordinate: (ra, dec, distance) in (deg, deg, kpc)\n' ' ({})>').format(' 1., 2., 3.' if NUMPY_LT_1_14 else '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' ' [{}]>').format('( 1.1, 2.1), ( 2.1, 3.1)' if NUMPY_LT_1_14 else '(1.1, 2.1), (2.1, 3.1)') if NUMPY_LT_1_14: assert repr(i3) == ( '<ICRS Coordinate: (ra, dec, distance) in (deg, deg, kpc)\n' ' [( 1.1, -15.6, 11.), ( 2.1, 17.1, 21.)]>') else: 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_shorthand_attributes(): # Check that attribute access works # for array data: n = 4 icrs1 = ICRS(ra=np.random.uniform(0, 360, n) * u.deg, dec=np.random.uniform(-90, 90, n) * u.deg, distance=100 * u.pc, pm_ra_cosdec=np.random.normal(0, 100, n) * u.mas / u.yr, pm_dec=np.random.normal(0, 100, n) * u.mas / u.yr, radial_velocity=np.random.normal(0, 100, n) * u.km / u.s) v = icrs1.velocity pm = icrs1.proper_motion assert quantity_allclose(pm[0], icrs1.pm_ra_cosdec) assert quantity_allclose(pm[1], icrs1.pm_dec) # for scalar data: icrs2 = ICRS(ra=37.4 * u.deg, dec=-55.8 * u.deg, distance=150 * u.pc, pm_ra_cosdec=-21.2 * u.mas / u.yr, pm_dec=17.1 * u.mas / u.yr, radial_velocity=105.7 * u.km / u.s) v = icrs2.velocity pm = icrs2.proper_motion assert quantity_allclose(pm[0], icrs2.pm_ra_cosdec) assert quantity_allclose(pm[1], icrs2.pm_dec) # check that it fails where we expect: # no distance rv = 105.7 * u.km / u.s icrs3 = ICRS(ra=37.4 * u.deg, dec=-55.8 * u.deg, pm_ra_cosdec=-21.2 * u.mas / u.yr, pm_dec=17.1 * u.mas / u.yr, radial_velocity=rv) with pytest.raises(ValueError): icrs3.velocity icrs3.set_representation_cls('cartesian') assert hasattr(icrs3, 'radial_velocity') assert quantity_allclose(icrs3.radial_velocity, rv) icrs4 = ICRS(x=30 * u.pc, y=20 * u.pc, z=11 * u.pc, v_x=10 * u.km / u.s, v_y=10 * u.km / u.s, v_z=10 * u.km / u.s, representation_type=r.CartesianRepresentation, differential_type=r.CartesianDifferential) icrs4.radial_velocity
def setup(self): lon = Longitude(np.arange(0, 24, 4), u.hourangle) lat = Latitude(np.arange(-90, 91, 30), u.deg) # With same-sized arrays, no attributes self.s0 = ICRS(lon[:, np.newaxis] * np.ones(lat.shape), lat * np.ones(lon.shape)[:, np.newaxis]) # Make an AltAz frame since that has many types of attributes. # Match one axis with times. self.obstime = (Time('2012-01-01') + np.arange(len(lon))[:, np.newaxis] * u.s) # And another with location. self.location = EarthLocation(20. * u.deg, lat, 100 * u.m) # Ensure we have a quantity scalar. self.pressure = 1000 * u.hPa # As well as an array. self.temperature = np.random.uniform( 0., 20., size=(lon.size, lat.size)) * u.deg_C self.s1 = AltAz(az=lon[:, np.newaxis], alt=lat, obstime=self.obstime, location=self.location, pressure=self.pressure, temperature=self.temperature) # For some tests, also try a GCRS, since that has representation # attributes. We match the second dimension (via the location) self.obsgeoloc, self.obsgeovel = self.location.get_gcrs_posvel( self.obstime[0, 0]) self.s2 = GCRS(ra=lon[:, np.newaxis], dec=lat, obstime=self.obstime, obsgeoloc=self.obsgeoloc, obsgeovel=self.obsgeovel) # For completeness, also some tests on an empty frame. self.s3 = GCRS(obstime=self.obstime, obsgeoloc=self.obsgeoloc, obsgeovel=self.obsgeovel) # And make a SkyCoord self.sc = SkyCoord(ra=lon[:, np.newaxis], dec=lat, frame=self.s3)
def test_create_orderered_data(): from astropy.coordinates.builtin_frames import ICRS, Galactic, AltAz TOL = 1e-10 * u.deg i = ICRS(1 * u.deg, 2 * u.deg) assert (i.ra - 1 * u.deg) < TOL assert (i.dec - 2 * u.deg) < TOL g = Galactic(1 * u.deg, 2 * u.deg) assert (g.l - 1 * u.deg) < TOL assert (g.b - 2 * u.deg) < TOL a = AltAz(1 * u.deg, 2 * u.deg) assert (a.az - 1 * u.deg) < TOL assert (a.alt - 2 * u.deg) < TOL with pytest.raises(TypeError): ICRS(1 * u.deg, 2 * u.deg, 1 * u.deg, 2 * u.deg) with pytest.raises(TypeError): sph = r.SphericalRepresentation(1 * u.deg, 2 * u.deg, 3 * u.kpc) ICRS(sph, 1 * u.deg, 2 * u.deg)
def test_frame_repr_vels(): from astropy.coordinates.builtin_frames import ICRS i = ICRS(ra=1 * u.deg, dec=2 * u.deg, pm_ra_cosdec=1 * u.marcsec / u.yr, pm_dec=2 * u.marcsec / u.yr) # unit comes out as mas/yr because of the preferred units defined in the # frame RepresentationMapping assert repr(i) == ('<ICRS Coordinate: (ra, dec) in deg\n' ' (1., 2.)\n' ' (pm_ra_cosdec, pm_dec) in mas / yr\n' ' (1., 2.)>')
def test_getitem(): from astropy.coordinates.builtin_frames import ICRS rep = r.SphericalRepresentation([1, 2, 3] * u.deg, [4, 5, 6] * u.deg, [7, 8, 9] * u.kpc) i = ICRS(rep) assert len(i.ra) == 3 iidx = i[1:] assert len(iidx.ra) == 2 iidx2 = i[0] assert iidx2.ra.isscalar
def test_representation_with_multiple_differentials(): from astropy.coordinates.builtin_frames import ICRS dif1 = r.CartesianDifferential([1, 2, 3] * u.km / u.s) dif2 = r.CartesianDifferential([1, 2, 3] * u.km / u.s**2) rep = r.CartesianRepresentation([1, 2, 3] * u.pc, differentials={ 's': dif1, 's2': dif2 }) # check warning is raised for a scalar with pytest.raises(ValueError): ICRS(rep)
def test_skyoffset(inradec, expectedlatlon, tolsep, originradec=(45, 45) * u.deg): origin = ICRS(*originradec) skyoffset_frame = SkyOffsetFrame(origin=origin) skycoord = SkyCoord(*inradec, frame=ICRS) skycoord_inaf = skycoord.transform_to(skyoffset_frame) assert hasattr(skycoord_inaf, 'lon') assert hasattr(skycoord_inaf, 'lat') expected = SkyCoord(*expectedlatlon, frame=skyoffset_frame) assert skycoord_inaf.separation(expected) < tolsep
def test_representation_arg_backwards_compatibility(): # TODO: this test can be removed when the `representation` argument is # removed from the BaseCoordinateFrame initializer. from astropy.coordinates.builtin_frames import ICRS c1 = ICRS(x=1 * u.pc, y=2 * u.pc, z=3 * u.pc, representation_type=r.CartesianRepresentation) c2 = ICRS(x=1 * u.pc, y=2 * u.pc, z=3 * u.pc, representation_type=r.CartesianRepresentation) c3 = ICRS(x=1 * u.pc, y=2 * u.pc, z=3 * u.pc, representation_type='cartesian') assert c1.x == c2.x assert c1.y == c2.y assert c1.z == c2.z assert c1.x == c3.x assert c1.y == c3.y assert c1.z == c3.z assert c1.representation_type == c1.representation_type with pytest.raises(ValueError): ICRS(x=1 * u.pc, y=2 * u.pc, z=3 * u.pc, representation_type='cartesian', representation='cartesian')
def test_skyoffset(inradec, expectedlatlon, tolsep, originradec=(45, 45) * u.deg): origin = ICRS(*originradec) skyoffset_frame = SkyOffsetFrame(origin=origin) skycoord = SkyCoord(*inradec, frame=ICRS) skycoord_inaf = skycoord.transform_to(skyoffset_frame) assert hasattr(skycoord_inaf, 'lon') assert hasattr(skycoord_inaf, 'lat') expected = SkyCoord(*expectedlatlon, frame=skyoffset_frame) assert skycoord_inaf.separation(expected) < tolsep # Check we can also transform back (regression test for gh-11254). try: roundtrip = skycoord_inaf.transform_to(ICRS()) except AttributeError as err: if 'to_geodetic' in str(err): pytest.xfail('See Issue 11277') else: raise else: assert roundtrip.separation(skycoord) < 1 * u.uas
def test_xhip_galactic(hip, ra, dec, pmra, pmdec, glon, glat, dist, pmglon, pmglat, rv, U, V, W): i = ICRS(ra * u.deg, dec * u.deg, dist * u.pc, pm_ra_cosdec=pmra * u.marcsec / u.yr, pm_dec=pmdec * u.marcsec / u.yr, radial_velocity=rv * u.km / u.s) g = i.transform_to(Galactic) # precision is limited by 2-deciimal digit string representation of pms assert quantity_allclose(g.pm_l_cosb, pmglon * u.marcsec / u.yr, atol=.01 * u.marcsec / u.yr) assert quantity_allclose(g.pm_b, pmglat * u.marcsec / u.yr, atol=.01 * u.marcsec / u.yr) # make sure UVW also makes sense uvwg = g.cartesian.differentials['s'] # precision is limited by 1-decimal digit string representation of vels assert quantity_allclose(uvwg.d_x, U * u.km / u.s, atol=.1 * u.km / u.s) assert quantity_allclose(uvwg.d_y, V * u.km / u.s, atol=.1 * u.km / u.s) assert quantity_allclose(uvwg.d_z, W * u.km / u.s, atol=.1 * u.km / u.s)
def test_galactocentric_loopback(to_frame): xyz = CartesianRepresentation(1, 2, 3) * u.pc from_coo = Galactocentric(xyz) explicit_coo = from_coo.transform_to(ICRS()).transform_to(to_frame) implicit_coo = from_coo.transform_to(to_frame) # Confirm that the explicit transformation changes the position assert not allclose( explicit_coo.cartesian.xyz, from_coo.cartesian.xyz, rtol=1e-10) # Confirm that the loopback matches the explicit transformation assert allclose(explicit_coo.cartesian.xyz, implicit_coo.cartesian.xyz, rtol=1e-10)
def test_shorthand_representations(): from astropy.coordinates.builtin_frames import ICRS rep = r.CartesianRepresentation([1, 2, 3] * u.pc) dif = r.CartesianDifferential([1, 2, 3] * u.km / u.s) rep = rep.with_differentials(dif) icrs = ICRS(rep) sph = icrs.spherical assert isinstance(sph, r.SphericalRepresentation) assert isinstance(sph.differentials['s'], r.SphericalDifferential) sph = icrs.sphericalcoslat assert isinstance(sph, r.SphericalRepresentation) assert isinstance(sph.differentials['s'], r.SphericalCosLatDifferential)
def setup_class(cls): # For these tests, we set up frames and coordinates using copy=False, # so we can check that broadcasting is handled correctly. lon = Longitude(np.arange(0, 24, 4), u.hourangle) lat = Latitude(np.arange(-90, 91, 30), u.deg) # With same-sized arrays, no attributes. cls.s0 = ICRS(lon[:, np.newaxis] * np.ones(lat.shape), lat * np.ones(lon.shape)[:, np.newaxis], copy=False) # Make an AltAz frame since that has many types of attributes. # Match one axis with times. cls.obstime = (Time('2012-01-01') + np.arange(len(lon))[:, np.newaxis] * u.s) # And another with location. cls.location = EarthLocation(20. * u.deg, lat, 100 * u.m) # Ensure we have a quantity scalar. cls.pressure = 1000 * u.hPa # As well as an array. cls.temperature = np.random.uniform( 0., 20., size=(lon.size, lat.size)) * u.deg_C cls.s1 = AltAz(az=lon[:, np.newaxis], alt=lat, obstime=cls.obstime, location=cls.location, pressure=cls.pressure, temperature=cls.temperature, copy=False) # For some tests, also try a GCRS, since that has representation # attributes. We match the second dimension (via the location) cls.obsgeoloc, cls.obsgeovel = cls.location.get_gcrs_posvel( cls.obstime[0, 0]) cls.s2 = GCRS(ra=lon[:, np.newaxis], dec=lat, obstime=cls.obstime, obsgeoloc=cls.obsgeoloc, obsgeovel=cls.obsgeovel, copy=False) # For completeness, also some tests on an empty frame. cls.s3 = GCRS(obstime=cls.obstime, obsgeoloc=cls.obsgeoloc, obsgeovel=cls.obsgeovel, copy=False) # And make a SkyCoord cls.sc = SkyCoord(ra=lon[:, np.newaxis], dec=lat, frame=cls.s3, copy=False)
def test_gcrs_diffs(): time = Time('2017-01-01') gf = GCRS(obstime=time) sung = get_sun(time) # should have very little vhelio # qtr-year off sun location should be the direction of ~ maximal vhelio qtrsung = get_sun(time - .25 * u.year) # now we use those essentially as directions where the velocities should # be either maximal or minimal - with or perpendiculat to Earh's orbit msungr = CartesianRepresentation(-sung.cartesian.xyz).represent_as( SphericalRepresentation) suni = ICRS(ra=msungr.lon, dec=msungr.lat, distance=100 * u.au, pm_ra_cosdec=0 * u.marcsec / u.yr, pm_dec=0 * u.marcsec / u.yr, radial_velocity=0 * u.km / u.s) qtrsuni = ICRS(ra=qtrsung.ra, dec=qtrsung.dec, distance=100 * u.au, pm_ra_cosdec=0 * u.marcsec / u.yr, pm_dec=0 * u.marcsec / u.yr, radial_velocity=0 * u.km / u.s) # Now we transform those parallel- and perpendicular-to Earth's orbit # directions to GCRS, which should shift the velocity to either include # the Earth's velocity vector, or not (for parallel and perpendicular, # respectively). sung = suni.transform_to(gf) qtrsung = qtrsuni.transform_to(gf) # should be high along the ecliptic-not-sun sun axis and # low along the sun axis assert np.abs(qtrsung.radial_velocity) > 30 * u.km / u.s assert np.abs(qtrsung.radial_velocity) < 40 * u.km / u.s assert np.abs(sung.radial_velocity) < 1 * u.km / u.s suni2 = sung.transform_to(ICRS()) assert np.all( np.abs(suni2.data.differentials['s'].d_xyz) < 3e-5 * u.km / u.s) qtrisun2 = qtrsung.transform_to(ICRS()) assert np.all( np.abs(qtrisun2.data.differentials['s'].d_xyz) < 3e-5 * u.km / u.s)
def test_faux_lsr(dt, symmetric): class LSR2(LSR): obstime = TimeAttribute(default=J2000) @frame_transform_graph.transform(FunctionTransformWithFiniteDifference, ICRS, LSR2, finite_difference_dt=dt, symmetric_finite_difference=symmetric) def icrs_to_lsr(icrs_coo, lsr_frame): dt = lsr_frame.obstime - J2000 offset = lsr_frame.v_bary * dt.to(u.second) return lsr_frame.realize_frame(icrs_coo.data.without_differentials() + offset) @frame_transform_graph.transform(FunctionTransformWithFiniteDifference, LSR2, ICRS, finite_difference_dt=dt, symmetric_finite_difference=symmetric) def lsr_to_icrs(lsr_coo, icrs_frame): dt = lsr_coo.obstime - J2000 offset = lsr_coo.v_bary * dt.to(u.second) return icrs_frame.realize_frame(lsr_coo.data - offset) ic = ICRS(ra=12.3 * u.deg, dec=45.6 * u.deg, distance=7.8 * u.au, pm_ra_cosdec=0 * u.marcsec / u.yr, pm_dec=0 * u.marcsec / u.yr, radial_velocity=0 * u.km / u.s) lsrc = ic.transform_to(LSR2()) assert quantity_allclose(ic.cartesian.xyz, lsrc.cartesian.xyz) idiff = ic.cartesian.differentials['s'] ldiff = lsrc.cartesian.differentials['s'] change = (ldiff.d_xyz - idiff.d_xyz).to(u.km / u.s) totchange = np.sum(change**2)**0.5 assert quantity_allclose(totchange, np.sum(lsrc.v_bary.d_xyz**2)**0.5) ic2 = ICRS(ra=120.3 * u.deg, dec=45.6 * u.deg, distance=7.8 * u.au, pm_ra_cosdec=0 * u.marcsec / u.yr, pm_dec=10 * u.marcsec / u.yr, radial_velocity=1000 * u.km / u.s) lsrc2 = ic2.transform_to(LSR2()) ic2_roundtrip = lsrc2.transform_to(ICRS) tot = np.sum(lsrc2.cartesian.differentials['s'].d_xyz**2)**0.5 assert np.abs(tot.to('km/s') - 1000 * u.km / u.s) < 20 * u.km / u.s assert quantity_allclose(ic2.cartesian.xyz, ic2_roundtrip.cartesian.xyz)
def test_skyoffset_lonwrap(): origin = ICRS(45 * u.deg, 45 * u.deg) sc = SkyCoord(190 * u.deg, -45 * u.deg, frame=SkyOffsetFrame(origin=origin)) assert sc.lon < 180 * u.deg sc2 = SkyCoord(-10 * u.deg, -45 * u.deg, frame=SkyOffsetFrame(origin=origin)) assert sc2.lon < 180 * u.deg sc3 = sc.realize_frame(sc.represent_as('cartesian')) assert sc3.lon < 180 * u.deg sc4 = sc2.realize_frame(sc2.represent_as('cartesian')) assert sc4.lon < 180 * u.deg
def test_hcrs_icrs_differentials(): # Regression to ensure that we can transform velocities from HCRS to LSR. # Numbers taken from the original issue, gh-6835. hcrs = HCRS(ra=8.67*u.deg, dec=53.09*u.deg, distance=117*u.pc, pm_ra_cosdec=4.8*u.mas/u.yr, pm_dec=-15.16*u.mas/u.yr, radial_velocity=23.42*u.km/u.s) icrs = hcrs.transform_to(ICRS()) # The position and velocity should not change much assert allclose(hcrs.cartesian.xyz, icrs.cartesian.xyz, rtol=1e-8) assert allclose(hcrs.velocity.d_xyz, icrs.velocity.d_xyz, rtol=1e-2) hcrs2 = icrs.transform_to(HCRS()) # The values should round trip assert allclose(hcrs.cartesian.xyz, hcrs2.cartesian.xyz, rtol=1e-12) assert allclose(hcrs.velocity.d_xyz, hcrs2.velocity.d_xyz, rtol=1e-12)
def test_static_matrix_combine_paths(): """ Check that combined staticmatrixtransform matrices provide the same transformation as using an intermediate transformation. This is somewhat of a regression test for #7706 """ from astropy.coordinates.baseframe import BaseCoordinateFrame from astropy.coordinates.matrix_utilities import rotation_matrix class AFrame(BaseCoordinateFrame): default_representation = r.SphericalRepresentation default_differential = r.SphericalCosLatDifferential t1 = t.StaticMatrixTransform(rotation_matrix(30.*u.deg, 'z'), ICRS, AFrame) t1.register(frame_transform_graph) t2 = t.StaticMatrixTransform(rotation_matrix(30.*u.deg, 'z').T, AFrame, ICRS) t2.register(frame_transform_graph) class BFrame(BaseCoordinateFrame): default_representation = r.SphericalRepresentation default_differential = r.SphericalCosLatDifferential t3 = t.StaticMatrixTransform(rotation_matrix(30.*u.deg, 'x'), ICRS, BFrame) t3.register(frame_transform_graph) t4 = t.StaticMatrixTransform(rotation_matrix(30.*u.deg, 'x').T, BFrame, ICRS) t4.register(frame_transform_graph) c = Galactic(123*u.deg, 45*u.deg) c1 = c.transform_to(BFrame()) # direct c2 = c.transform_to(AFrame()).transform_to(BFrame()) # thru A c3 = c.transform_to(ICRS()).transform_to(BFrame()) # thru ICRS assert quantity_allclose(c1.lon, c2.lon) assert quantity_allclose(c1.lat, c2.lat) assert quantity_allclose(c1.lon, c3.lon) assert quantity_allclose(c1.lat, c3.lat) for t_ in [t1, t2, t3, t4]: t_.unregister(frame_transform_graph)
def test_converting_units(): import re from astropy.coordinates.baseframe import RepresentationMapping from astropy.coordinates.builtin_frames import ICRS, FK5 # this is a regular expression that with split (see below) removes what's # the decimal point to fix rounding problems rexrepr = re.compile(r'(.*?=\d\.).*?( .*?=\d\.).*?( .*)') # Use values that aren't subject to rounding down to X.9999... i2 = ICRS(ra=2. * u.deg, dec=2. * u.deg) i2_many = ICRS(ra=[2., 4.] * u.deg, dec=[2., -8.1] * u.deg) # converting from FK5 to ICRS and back changes the *internal* representation, # but it should still come out in the preferred form i4 = i2.transform_to(FK5).transform_to(ICRS) i4_many = i2_many.transform_to(FK5).transform_to(ICRS) ri2 = ''.join(rexrepr.split(repr(i2))) ri4 = ''.join(rexrepr.split(repr(i4))) assert ri2 == ri4 assert i2.data.lon.unit != i4.data.lon.unit # Internal repr changed ri2_many = ''.join(rexrepr.split(repr(i2_many))) ri4_many = ''.join(rexrepr.split(repr(i4_many))) assert ri2_many == ri4_many assert i2_many.data.lon.unit != i4_many.data.lon.unit # Internal repr changed # but that *shouldn't* hold if we turn off units for the representation class FakeICRS(ICRS): frame_specific_representation_info = { 'spherical': [ RepresentationMapping('lon', 'ra', u.hourangle), RepresentationMapping('lat', 'dec', None), RepresentationMapping('distance', 'distance') ] # should fall back to default of None unit } fi = FakeICRS(i4.data) ri2 = ''.join(rexrepr.split(repr(i2))) rfi = ''.join(rexrepr.split(repr(fi))) rfi = re.sub('FakeICRS', 'ICRS', rfi) # Force frame name to match assert ri2 != rfi # the attributes should also get the right units assert i2.dec.unit == i4.dec.unit # unless no/explicitly given units assert i2.dec.unit != fi.dec.unit assert i2.ra.unit != fi.ra.unit assert fi.ra.unit == u.hourangle
def test_component_error_useful(): """ Check that a data-less frame gives useful error messages about not having data when the attributes asked for are possible coordinate components """ from astropy.coordinates.builtin_frames import ICRS i = ICRS() with pytest.raises(ValueError) as excinfo: i.ra assert 'does not have associated data' in str(excinfo.value) with pytest.raises(AttributeError) as excinfo1: i.foobar with pytest.raises(AttributeError) as excinfo2: i.lon # lon is *not* the component name despite being the underlying representation's name assert "object has no attribute 'foobar'" in str(excinfo1.value) assert "object has no attribute 'lon'" in str(excinfo2.value)
def test_loopback_obstime(frame): # Test that the loopback properly handles a change in obstime from_coo = frame(1 * u.deg, 2 * u.deg, 3 * u.AU, obstime='2001-01-01') to_frame = frame(obstime='2001-06-30') explicit_coo = from_coo.transform_to(ICRS()).transform_to(to_frame) implicit_coo = from_coo.transform_to(to_frame) # Confirm that the explicit transformation changes the coordinate assert not quantity_allclose(explicit_coo.lon, from_coo.lon, rtol=1e-10) assert not quantity_allclose(explicit_coo.lat, from_coo.lat, rtol=1e-10) assert not quantity_allclose( explicit_coo.distance, from_coo.distance, rtol=1e-10) # Confirm that the loopback matches the explicit transformation assert quantity_allclose(explicit_coo.lon, implicit_coo.lon, rtol=1e-10) assert quantity_allclose(explicit_coo.lat, implicit_coo.lat, rtol=1e-10) assert quantity_allclose(explicit_coo.distance, implicit_coo.distance, rtol=1e-10)
def test_inplace_array(): from astropy.coordinates.builtin_frames import ICRS i = ICRS([[1, 2], [3, 4]] * u.deg, [[10, 20], [30, 40]] * u.deg) # Add an in frame units version of the rep to the cache. repr(i) # Check that repr() has added a rep to the cache assert len(i.cache['representation']) == 2 # Modify the data i.data.lon[:, 0] = [100, 200] * u.deg # Clear the cache i.cache.clear() # This will use a second (potentially cached rep) assert_allclose(i.ra, [[100, 2], [200, 4]] * u.deg) assert_allclose(i.dec, [[10, 20], [30, 40]] * u.deg)
def test_inplace_change(): from astropy.coordinates.builtin_frames import ICRS i = ICRS(1 * u.deg, 2 * u.deg) # Add an in frame units version of the rep to the cache. repr(i) # Check that repr() has added a rep to the cache assert len(i.cache['representation']) == 2 # Modify the data i.data.lon[()] = 10 * u.deg # Clear the cache i.cache.clear() # This will use a second (potentially cached rep) assert i.ra == 10 * u.deg assert i.dec == 2 * u.deg
def test_roundtrip_scalar(): icrs = ICRS(ra=1 * u.deg, dec=2 * u.deg, distance=3 * u.au) gcrs = GCRS(icrs.cartesian) bary = icrs.transform_to(BarycentricMeanEcliptic()) helio = icrs.transform_to(HeliocentricMeanEcliptic()) geo = gcrs.transform_to(GeocentricMeanEcliptic()) bary_icrs = bary.transform_to(ICRS()) helio_icrs = helio.transform_to(ICRS()) geo_gcrs = geo.transform_to(GCRS()) assert quantity_allclose(bary_icrs.cartesian.xyz, icrs.cartesian.xyz) assert quantity_allclose(helio_icrs.cartesian.xyz, icrs.cartesian.xyz) assert quantity_allclose(geo_gcrs.cartesian.xyz, gcrs.cartesian.xyz)
def test_loopback_obliquity(): # Test that the loopback properly handles a change in obliquity from_coo = CustomBarycentricEcliptic(1 * u.deg, 2 * u.deg, 3 * u.AU, obliquity=84000 * u.arcsec) to_frame = CustomBarycentricEcliptic(obliquity=85000 * u.arcsec) explicit_coo = from_coo.transform_to(ICRS()).transform_to(to_frame) implicit_coo = from_coo.transform_to(to_frame) # Confirm that the explicit transformation changes the lon/lat but not the distance assert not quantity_allclose(explicit_coo.lon, from_coo.lon, rtol=1e-10) assert not quantity_allclose(explicit_coo.lat, from_coo.lat, rtol=1e-10) assert quantity_allclose(explicit_coo.distance, from_coo.distance, rtol=1e-10) # Confirm that the loopback matches the explicit transformation assert quantity_allclose(explicit_coo.lon, implicit_coo.lon, rtol=1e-10) assert quantity_allclose(explicit_coo.lat, implicit_coo.lat, rtol=1e-10) assert quantity_allclose(explicit_coo.distance, implicit_coo.distance, rtol=1e-10)