def assert_objects_equal(obj1, obj2, attrs, compare_class=True): if compare_class: assert obj1.__class__ is obj2.__class__ # For a column that is a native astropy Column, ignore the specified # `attrs`. This happens for a mixin like Quantity that is stored in a # `Table` (not QTable). if isinstance(obj1, Column): attrs = [] assert obj1.shape == obj2.shape info_attrs = ['info.name', 'info.format', 'info.unit', 'info.description'] for attr in attrs + info_attrs: a1 = obj1 a2 = obj2 for subattr in attr.split('.'): try: a1 = getattr(a1, subattr) a2 = getattr(a2, subattr) except AttributeError: a1 = a1[subattr] a2 = a2[subattr] if isinstance(a1, np.ndarray) and a1.dtype.kind == 'f': assert quantity_allclose(a1, a2, rtol=1e-10) else: assert np.all(a1 == a2) # For no attrs that means we just compare directly. if not attrs: if isinstance(obj1, np.ndarray) and obj1.dtype.kind == 'f': assert quantity_allclose(obj1, obj2, rtol=1e-15) else: assert np.all(obj1 == obj2)
def test_parallax(): d = Distance(parallax=1 * u.arcsecond) assert d.pc == 1. with pytest.raises(ValueError): d = Distance(15 * u.pc, parallax=20 * u.milliarcsecond) with pytest.raises(ValueError): d = Distance(parallax=20 * u.milliarcsecond, distmod=20) # array plx = [1, 10, 100.] * u.mas d = Distance(parallax=plx) assert quantity_allclose(d.pc, [1000., 100., 10.]) assert quantity_allclose(plx, d.parallax) # check behavior for negative parallax with pytest.raises(ValueError): Distance(parallax=-1 * u.mas) with pytest.raises(ValueError): Distance(parallax=[10, 1, -1] * u.mas) with catch_warnings(AstropyWarning) as w: Distance(parallax=-1 * u.mas, allow_negative=True) assert len(w) > 0 with catch_warnings(AstropyWarning) as w: Distance(parallax=[10, 1, -1] * u.mas, allow_negative=True) assert len(w) > 0
def test_parallax(): d = Distance(parallax=1 * u.arcsecond) assert d.pc == 1. with pytest.raises(ValueError): d = Distance(15 * u.pc, parallax=20 * u.milliarcsecond) with pytest.raises(ValueError): d = Distance(parallax=20 * u.milliarcsecond, distmod=20) # array plx = [1, 10, 100.] * u.mas d = Distance(parallax=plx) assert quantity_allclose(d.pc, [1000., 100., 10.]) assert quantity_allclose(plx, d.parallax) # check behavior for negative parallax with pytest.raises(ValueError): Distance(parallax=-1 * u.mas) with pytest.raises(ValueError): Distance(parallax=[10, 1, -1] * u.mas) with pytest.warns(AstropyWarning): Distance(parallax=-1 * u.mas, allow_negative=True) with pytest.warns(AstropyWarning): Distance(parallax=[10, 1, -1] * u.mas, allow_negative=True) # Regression test for #12569; `unit` was ignored if `parallax` was given. d = Distance(parallax=1 * u.mas, unit=u.kpc) assert d.value == 1. assert d.unit is u.kpc
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_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 assert_objects_equal(obj1, obj2, attrs, compare_class=True): if compare_class: assert obj1.__class__ is obj2.__class__ assert obj1.shape == obj2.shape info_attrs = [ 'info.name', 'info.format', 'info.unit', 'info.description', 'info.dtype' ] for attr in attrs + info_attrs: a1 = obj1 a2 = obj2 for subattr in attr.split('.'): try: a1 = getattr(a1, subattr) a2 = getattr(a2, subattr) except AttributeError: a1 = a1[subattr] a2 = a2[subattr] if isinstance(a1, np.ndarray) and a1.dtype.kind == 'f': assert quantity_allclose(a1, a2, rtol=1e-10) else: assert np.all(a1 == a2) # For no attrs that means we just compare directly. if not attrs: if isinstance(obj1, np.ndarray) and obj1.dtype.kind == 'f': assert quantity_allclose(obj1, obj2, rtol=1e-15) else: assert np.all(obj1 == obj2)
def test_ecliptic_true_mean_preserve_latitude(trueframe, meanframe): """ Check that the ecliptic true/mean transformations preserve latitude """ truecoo = trueframe(90*u.deg, 0*u.deg, distance=1*u.AU) meancoo = truecoo.transform_to(meanframe) assert not quantity_allclose(truecoo.lon, meancoo.lon) assert quantity_allclose(truecoo.lat, meancoo.lat, atol=1e-10*u.arcsec)
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_ecliptic_roundtrips(trueframe, meanframe): """ Check that the various ecliptic transformations at least roundtrip """ icrs = ICRS(1*u.deg, 2*u.deg, distance=1.5*R_sun) truecoo = icrs.transform_to(trueframe) meancoo = truecoo.transform_to(meanframe) truecoo2 = meancoo.transform_to(trueframe) assert not quantity_allclose(truecoo.cartesian.xyz, meancoo.cartesian.xyz) assert quantity_allclose(truecoo.cartesian.xyz, truecoo2.cartesian.xyz)
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 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_geodetic_tuple(): lat = 2*u.deg lon = 10*u.deg height = 100*u.m el = EarthLocation.from_geodetic(lat=lat, lon=lon, height=height) res1 = el.to_geodetic() res2 = el.geodetic assert res1.lat == res2.lat and quantity_allclose(res1.lat, lat) assert res1.lon == res2.lon and quantity_allclose(res1.lon, lon) assert res1.height == res2.height and quantity_allclose(res1.height, height)
def test_geodetic_tuple(): lat = 2*u.deg lon = 10*u.deg height = 100*u.m el = EarthLocation.from_geodetic(lat=lat, lon=lon, height=height) res1 = el.to_geodetic() res2 = el.geodetic assert res1.lat == res2.lat and quantity_allclose(res1.lat, lat) assert res1.lon == res2.lon and quantity_allclose(res1.lon, lon) assert res1.height == res2.height and quantity_allclose(res1.height, height)
def test_earth_barycentric_velocity_multi_d(): # Might as well test it with a multidimensional array too. t = Time('2016-03-20T12:30:00') + np.arange(8.).reshape(2, 2, 2) * u.yr / 2. ep, ev = get_body_barycentric_posvel('earth', t) # note: assert_quantity_allclose doesn't like the shape mismatch. # this is a problem with np.testing.assert_allclose. assert quantity_allclose(ep.get_xyz(xyz_axis=-1), [[-1., 0., 0.], [+1., 0., 0.]]*u.AU, atol=0.06*u.AU) expected = u.Quantity([0.*u.one, np.cos(23.5*u.deg), np.sin(23.5*u.deg)]) * ([[-30.], [30.]] * u.km / u.s) assert quantity_allclose(ev.get_xyz(xyz_axis=-1), expected, atol=2.*u.km/u.s)
def test_earth_barycentric_velocity_multi_d(): # Might as well test it with a multidimensional array too. t = Time('2016-03-20T12:30:00') + np.arange(8.).reshape(2, 2, 2) * u.yr / 2. ep, ev = get_body_barycentric_posvel('earth', t) # note: assert_quantity_allclose doesn't like the shape mismatch. # this is a problem with np.testing.assert_allclose. assert quantity_allclose(ep.get_xyz(xyz_axis=-1), [[-1., 0., 0.], [+1., 0., 0.]]*u.AU, atol=0.06*u.AU) expected = u.Quantity([0.*u.one, np.cos(23.5*u.deg), np.sin(23.5*u.deg)]) * ([[-30.], [30.]] * u.km / u.s) assert quantity_allclose(ev.get_xyz(xyz_axis=-1), expected, atol=2.*u.km/u.s)
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_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 check_builtin_matches_remote(download_url=True): """ This function checks that the builtin sites registry is consistent with the remote registry (or a registry at some other location). Note that current this is *not* run by the testing suite (because it doesn't start with "test", and is instead meant to be used as a check before merging changes in astropy-data) """ builtin_registry = EarthLocation._get_site_registry(force_builtin=True) dl_registry = EarthLocation._get_site_registry(force_download=download_url) in_dl = {} matches = {} for name in builtin_registry.names: in_dl[name] = name in dl_registry if in_dl[name]: matches[name] = quantity_allclose(builtin_registry[name], dl_registry[name]) else: matches[name] = False if not all(matches.values()): # this makes sure we actually see which don't match print("In builtin registry but not in download:") for name in in_dl: if not in_dl[name]: print(' ', name) print("In both but not the same value:") for name in matches: if not matches[name] and in_dl[name]: print(' ', name, 'builtin:', builtin_registry[name], 'download:', dl_registry[name]) assert False, "Builtin and download registry aren't consistent - failures printed to stdout"
def assert_objects_equal(obj1, obj2, attrs, compare_class=True): if compare_class: assert obj1.__class__ is obj2.__class__ info_attrs = [ 'info.name', 'info.format', 'info.unit', 'info.description', 'info.meta' ] for attr in attrs + info_attrs: a1 = obj1 a2 = obj2 for subattr in attr.split('.'): try: a1 = getattr(a1, subattr) a2 = getattr(a2, subattr) except AttributeError: a1 = a1[subattr] a2 = a2[subattr] # Mixin info.meta can None instead of empty OrderedDict(), #6720 would # fix this. if attr == 'info.meta': if a1 is None: a1 = {} if a2 is None: a2 = {} if isinstance(a1, np.ndarray) and a1.dtype.kind == 'f': assert quantity_allclose(a1, a2, rtol=1e-15) else: assert np.all(a1 == a2)
def check_builtin_matches_remote(download_url=True): """ This function checks that the builtin sites registry is consistent with the remote registry (or a registry at some other location). Note that current this is *not* run by the testing suite (because it doesn't start with "test", and is instead meant to be used as a check before merging changes in astropy-data) """ builtin_registry = EarthLocation._get_site_registry(force_builtin=True) dl_registry = EarthLocation._get_site_registry(force_download=download_url) in_dl = {} matches = {} for name in builtin_registry.names: in_dl[name] = name in dl_registry if in_dl[name]: matches[name] = quantity_allclose(builtin_registry[name], dl_registry[name]) else: matches[name] = False if not all(matches.values()): # this makes sure we actually see which don't match print("In builtin registry but not in download:") for name in in_dl: if not in_dl[name]: print(' ', name) print("In both but not the same value:") for name in matches: if not matches[name] and in_dl[name]: print(' ', name, 'builtin:', builtin_registry[name], 'download:', dl_registry[name]) assert False, "Builtin and download registry aren't consistent - failures printed to stdout"
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_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_negative_distance(): """ Regression test: #7408 Make sure that negative parallaxes turned into distances are handled right """ RA = 150 * u.deg DEC = -11*u.deg c = ICRS(ra=RA, dec=DEC, distance=(-10*u.mas).to(u.pc, u.parallax()), pm_ra_cosdec=10*u.mas/u.yr, pm_dec=10*u.mas/u.yr) assert quantity_allclose(c.ra, RA) assert quantity_allclose(c.dec, DEC) c = ICRS(ra=RA, dec=DEC, distance=(-10*u.mas).to(u.pc, u.parallax())) assert quantity_allclose(c.ra, RA) assert quantity_allclose(c.dec, DEC)
def test_negative_distance(): """ Regression test: #7408 Make sure that negative parallaxes turned into distances are handled right """ RA = 150 * u.deg DEC = -11 * u.deg c = ICRS(ra=RA, dec=DEC, distance=(-10 * u.mas).to(u.pc, u.parallax()), pm_ra_cosdec=10 * u.mas / u.yr, pm_dec=10 * u.mas / u.yr) assert quantity_allclose(c.ra, RA) assert quantity_allclose(c.dec, DEC) c = ICRS(ra=RA, dec=DEC, distance=(-10 * u.mas).to(u.pc, u.parallax())) assert quantity_allclose(c.ra, RA) assert quantity_allclose(c.dec, DEC)
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 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_ecl_geo(): """ Check that the geocentric version at least gets well away from GCRS. For a true "accuracy" test we need a comparison dataset that is similar to the geocentric/GCRS comparison we want to do here. Contributions welcome! """ gcrs = GCRS(10*u.deg, 20*u.deg, distance=1.5*R_earth) gecl = gcrs.transform_to(GeocentricTrueEcliptic) assert quantity_allclose(gecl.distance, gcrs.distance)
def test_ecl_geo(): """ Check that the geocentric version at least gets well away from GCRS. For a true "accuracy" test we need a comparison dataset that is similar to the geocentric/GCRS comparison we want to do here. Contributions welcome! """ gcrs = GCRS(10 * u.deg, 20 * u.deg, distance=1.5 * R_earth) gecl = gcrs.transform_to(GeocentricTrueEcliptic) assert quantity_allclose(gecl.distance, gcrs.distance)
def test_helioecliptic_induced_velocity(frame): # Create a coordinate with zero speed in ICRS time = Time('2021-01-01') icrs = ICRS(ra=1 * u.deg, dec=2 * u.deg, distance=3 * u.AU, pm_ra_cosdec=0 * u.deg / u.s, pm_dec=0 * u.deg / u.s, radial_velocity=0 * u.m / u.s) # Transforming to a helioecliptic frame should give an induced speed equal to the Sun's speed transformed = icrs.transform_to(frame(obstime=time)) _, vel = get_body_barycentric_posvel('sun', time) assert quantity_allclose(transformed.velocity.norm(), vel.norm()) # Transforming back to ICRS should get back to zero speed back = transformed.transform_to(ICRS()) assert quantity_allclose(back.velocity.norm(), 0 * u.m / u.s, atol=1e-10 * u.m / u.s)
def test_of_address(google_api_key): NYC_lon = -74.0 * u.deg NYC_lat = 40.7 * u.deg # ~10 km tolerance to address difference between OpenStreetMap and Google # for "New York, NY". This doesn't matter in practice because this test is # only used to verify that the query succeeded, not that the returned # position is precise. NYC_tol = 0.1 * u.deg # just a location try: loc = EarthLocation.of_address("New York, NY") except NameResolveError as e: # API limit might surface even here in Travis CI. if 'unknown failure with' not in str(e): pytest.xfail(str(e)) else: assert quantity_allclose(loc.lat, NYC_lat, atol=NYC_tol) assert quantity_allclose(loc.lon, NYC_lon, atol=NYC_tol) assert np.allclose(loc.height.value, 0.) # Put this one here as buffer to get around Google map API limit per sec. # no match: This always raises NameResolveError with pytest.raises(NameResolveError): EarthLocation.of_address("lkjasdflkja") if google_api_key is not None: # a location and height try: loc = EarthLocation.of_address("New York, NY", get_height=True) except NameResolveError as e: # Buffer above sometimes insufficient to get around API limit but # we also do not want to drag things out with time.sleep(0.195), # where 0.195 was empirically determined on some physical machine. pytest.xfail(str(e.value)) else: assert quantity_allclose(loc.lat, NYC_lat, atol=NYC_tol) assert quantity_allclose(loc.lon, NYC_lon, atol=NYC_tol) assert quantity_allclose(loc.height, 10.438 * u.meter, atol=1. * u.cm)
def test_cartesian_wgs84geodetic_roundtrip(): # Test array-valued input in the process. s1 = CartesianRepresentation(x=[1, 3000.] * u.km, y=[7000., 4.] * u.km, z=[5., 6000.] * u.km) s2 = WGS84GeodeticRepresentation.from_representation(s1) s3 = CartesianRepresentation.from_representation(s2) s4 = WGS84GeodeticRepresentation.from_representation(s3) assert quantity_allclose(s1.x, s3.x) assert quantity_allclose(s1.y, s3.y) assert quantity_allclose(s1.z, s3.z) assert quantity_allclose(s2.lon, s4.lon) assert quantity_allclose(s2.lat, s4.lat) assert quantity_allclose(s2.height, s4.height) # Test initializer just for the sake of it. s5 = WGS84GeodeticRepresentation(s2.lon, s2.lat, s2.height) assert_array_equal(s2.lon, s5.lon) assert_array_equal(s2.lat, s5.lat) assert_array_equal(s2.height, s5.height)
def test_differential_type_arg(): """ Test passing in an explicit differential class to the initializer or changing the differential class via set_representation_cls """ from astropy.coordinates.builtin_frames import ICRS icrs = ICRS(ra=1 * u.deg, dec=60 * u.deg, pm_ra=10 * u.mas / u.yr, pm_dec=-11 * u.mas / u.yr, differential_type=r.UnitSphericalDifferential) assert icrs.pm_ra == 10 * u.mas / u.yr icrs = ICRS(ra=1 * u.deg, dec=60 * u.deg, pm_ra=10 * u.mas / u.yr, pm_dec=-11 * u.mas / u.yr, differential_type={'s': r.UnitSphericalDifferential}) assert icrs.pm_ra == 10 * u.mas / u.yr icrs = ICRS(ra=1 * u.deg, dec=60 * u.deg, pm_ra_cosdec=10 * u.mas / u.yr, pm_dec=-11 * u.mas / u.yr) icrs.set_representation_cls(s=r.UnitSphericalDifferential) assert quantity_allclose(icrs.pm_ra, 20 * u.mas / u.yr) # incompatible representation and differential with pytest.raises(TypeError): ICRS(ra=1 * u.deg, dec=60 * u.deg, v_x=1 * u.km / u.s, v_y=-2 * u.km / u.s, v_z=-2 * u.km / u.s, differential_type=r.CartesianDifferential) # specify both icrs = ICRS(x=1 * u.pc, y=2 * u.pc, z=3 * u.pc, v_x=1 * u.km / u.s, v_y=2 * u.km / u.s, v_z=3 * u.km / u.s, representation_type=r.CartesianRepresentation, differential_type=r.CartesianDifferential) assert icrs.x == 1 * u.pc assert icrs.y == 2 * u.pc assert icrs.z == 3 * u.pc assert icrs.v_x == 1 * u.km / u.s assert icrs.v_y == 2 * u.km / u.s assert icrs.v_z == 3 * u.km / u.s
def test_of_address(google_api_key): NYC_lon = -74.0 * u.deg NYC_lat = 40.7 * u.deg # ~10 km tolerance to address difference between OpenStreetMap and Google # for "New York, NY". This doesn't matter in practice because this test is # only used to verify that the query succeeded, not that the returned # position is precise. NYC_tol = 0.1 * u.deg # just a location try: loc = EarthLocation.of_address("New York, NY") except NameResolveError as e: # API limit might surface even here in Travis CI. if 'unknown failure with' not in str(e): pytest.xfail(str(e)) else: assert quantity_allclose(loc.lat, NYC_lat, atol=NYC_tol) assert quantity_allclose(loc.lon, NYC_lon, atol=NYC_tol) assert np.allclose(loc.height.value, 0.) # Put this one here as buffer to get around Google map API limit per sec. # no match: This always raises NameResolveError with pytest.raises(NameResolveError): EarthLocation.of_address("lkjasdflkja") if google_api_key is not None: # a location and height try: loc = EarthLocation.of_address("New York, NY", get_height=True) except NameResolveError as e: # Buffer above sometimes insufficient to get around API limit but # we also do not want to drag things out with time.sleep(0.195), # where 0.195 was empirically determined on some physical machine. pytest.xfail(str(e)) else: assert quantity_allclose(loc.lat, NYC_lat, atol=NYC_tol) assert quantity_allclose(loc.lon, NYC_lon, atol=NYC_tol) assert quantity_allclose(loc.height, 10.438*u.meter, atol=1.*u.cm)
def test_affine_transform_succeed(transfunc, rep): c = TCoo1(rep) # compute expected output M, offset = transfunc(c, TCoo2) _rep = rep.to_cartesian() diffs = dict([(k, diff.represent_as(r.CartesianDifferential, rep)) for k, diff in rep.differentials.items()]) expected_rep = _rep.with_differentials(diffs) if M is not None: expected_rep = expected_rep.transform(M) expected_pos = expected_rep.without_differentials() if offset is not None: expected_pos = expected_pos + offset.without_differentials() expected_vel = None if c.data.differentials: expected_vel = expected_rep.differentials['s'] if offset and offset.differentials: expected_vel = (expected_vel + offset.differentials['s']) # register and do the transformation and check against expected trans = t.AffineTransform(transfunc, TCoo1, TCoo2) trans.register(frame_transform_graph) c2 = c.transform_to(TCoo2) assert quantity_allclose(c2.data.to_cartesian().xyz, expected_pos.to_cartesian().xyz) if expected_vel is not None: diff = c2.data.differentials['s'].to_cartesian(base=c2.data) assert quantity_allclose(diff.xyz, expected_vel.d_xyz) trans.unregister(frame_transform_graph)
def test_regression_5133(): N = 1000 np.random.seed(12345) lon = np.random.uniform(-10, 10, N) * u.deg lat = np.random.uniform(50, 52, N) * u.deg alt = np.random.uniform(0, 10., N) * u.km time = Time('2010-1-1') objects = EarthLocation.from_geodetic(lon, lat, height=alt) itrs_coo = objects.get_itrs(time) homes = [EarthLocation.from_geodetic(lon=-1 * u.deg, lat=52 * u.deg, height=h) for h in (0, 1000, 10000)*u.km] altaz_frames = [AltAz(obstime=time, location=h) for h in homes] altaz_coos = [itrs_coo.transform_to(f) for f in altaz_frames] # they should all be different for coo in altaz_coos[1:]: assert not quantity_allclose(coo.az, coo.az[0]) assert not quantity_allclose(coo.alt, coo.alt[0])
def test_affine_transform_succeed(transfunc, rep): c = TCoo1(rep) # compute expected output M, offset = transfunc(c, TCoo2) _rep = rep.to_cartesian() diffs = {k: diff.represent_as(r.CartesianDifferential, rep) for k, diff in rep.differentials.items()} expected_rep = _rep.with_differentials(diffs) if M is not None: expected_rep = expected_rep.transform(M) expected_pos = expected_rep.without_differentials() if offset is not None: expected_pos = expected_pos + offset.without_differentials() expected_vel = None if c.data.differentials: expected_vel = expected_rep.differentials['s'] if offset and offset.differentials: expected_vel = (expected_vel + offset.differentials['s']) # register and do the transformation and check against expected trans = t.AffineTransform(transfunc, TCoo1, TCoo2) trans.register(frame_transform_graph) c2 = c.transform_to(TCoo2()) assert quantity_allclose(c2.data.to_cartesian().xyz, expected_pos.to_cartesian().xyz) if expected_vel is not None: diff = c2.data.differentials['s'].to_cartesian(base=c2.data) assert quantity_allclose(diff.xyz, expected_vel.d_xyz) trans.unregister(frame_transform_graph)
def test_regression_5133(): N = 1000 np.random.seed(12345) lon = np.random.uniform(-10, 10, N) * u.deg lat = np.random.uniform(50, 52, N) * u.deg alt = np.random.uniform(0, 10., N) * u.km time = Time('2010-1-1') objects = EarthLocation.from_geodetic(lon, lat, height=alt) itrs_coo = objects.get_itrs(time) homes = [EarthLocation.from_geodetic(lon=-1 * u.deg, lat=52 * u.deg, height=h) for h in (0, 1000, 10000)*u.km] altaz_frames = [AltAz(obstime=time, location=h) for h in homes] altaz_coos = [itrs_coo.transform_to(f) for f in altaz_frames] # they should all be different for coo in altaz_coos[1:]: assert not quantity_allclose(coo.az, coo.az[0]) assert not quantity_allclose(coo.alt, coo.alt[0])
def assert_objects_equal(obj1, obj2, attrs, compare_class=True): if compare_class: assert obj1.__class__ is obj2.__class__ info_attrs = ['info.name', 'info.format', 'info.unit', 'info.description'] for attr in attrs + info_attrs: a1 = obj1 a2 = obj2 for subattr in attr.split('.'): try: a1 = getattr(a1, subattr) a2 = getattr(a2, subattr) except AttributeError: a1 = a1[subattr] a2 = a2[subattr] if isinstance(a1, np.ndarray) and a1.dtype.kind == 'f': assert quantity_allclose(a1, a2, rtol=1e-10) else: assert np.all(a1 == a2)
def assert_objects_equal(obj1, obj2, attrs, compare_class=True): if compare_class: assert obj1.__class__ is obj2.__class__ info_attrs = [ 'info.name', 'info.format', 'info.unit', 'info.description', 'info.meta', 'info.dtype' ] for attr in attrs + info_attrs: a1 = obj1 a2 = obj2 for subattr in attr.split('.'): try: a1 = getattr(a1, subattr) a2 = getattr(a2, subattr) except AttributeError: a1 = a1[subattr] a2 = a2[subattr] # Mixin info.meta can None instead of empty OrderedDict(), #6720 would # fix this. if attr == 'info.meta': if a1 is None: a1 = {} if a2 is None: a2 = {} if isinstance(a1, np.ndarray) and a1.dtype.kind == 'f': assert quantity_allclose(a1, a2, rtol=1e-15) elif isinstance(a1, np.dtype): # HDF5 does not perfectly preserve dtype: byte order can change, and # unicode gets stored as bytes. So, we just check safe casting, to # ensure we do not, e.g., accidentally change integer to float, etc. if NUMPY_LT_1_22 and a1.names: # For old numpy, can_cast does not deal well with structured dtype. assert a1.names == a2.names else: assert np.can_cast(a2, a1, casting='safe') else: assert np.all(a1 == a2)
def test_differential_type_arg(): """ Test passing in an explicit differential class to the initializer or changing the differential class via set_representation_cls """ from astropy.coordinates.builtin_frames import ICRS icrs = ICRS(ra=1*u.deg, dec=60*u.deg, pm_ra=10*u.mas/u.yr, pm_dec=-11*u.mas/u.yr, differential_type=r.UnitSphericalDifferential) assert icrs.pm_ra == 10*u.mas/u.yr icrs = ICRS(ra=1*u.deg, dec=60*u.deg, pm_ra=10*u.mas/u.yr, pm_dec=-11*u.mas/u.yr, differential_type={'s': r.UnitSphericalDifferential}) assert icrs.pm_ra == 10*u.mas/u.yr icrs = ICRS(ra=1*u.deg, dec=60*u.deg, pm_ra_cosdec=10*u.mas/u.yr, pm_dec=-11*u.mas/u.yr) icrs.set_representation_cls(s=r.UnitSphericalDifferential) assert quantity_allclose(icrs.pm_ra, 20*u.mas/u.yr) # incompatible representation and differential with pytest.raises(TypeError): ICRS(ra=1*u.deg, dec=60*u.deg, v_x=1*u.km/u.s, v_y=-2*u.km/u.s, v_z=-2*u.km/u.s, differential_type=r.CartesianDifferential) # specify both icrs = ICRS(x=1*u.pc, y=2*u.pc, z=3*u.pc, v_x=1*u.km/u.s, v_y=2*u.km/u.s, v_z=3*u.km/u.s, representation_type=r.CartesianRepresentation, differential_type=r.CartesianDifferential) assert icrs.x == 1*u.pc assert icrs.y == 2*u.pc assert icrs.z == 3*u.pc assert icrs.v_x == 1*u.km/u.s assert icrs.v_y == 2*u.km/u.s assert icrs.v_z == 3*u.km/u.s
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_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)
def allclose_m8(a, b, rtol=1.e-8, atol=None): if atol is None: atol = 1.e-8 * getattr(a, 'unit', 1) return quantity_allclose(a, b, rtol, atol)
def vvd(val, valok, dval, func, test, status): """Mimic routine of erfa/src/t_erfa_c.c (to help copy & paste)""" assert quantity_allclose(val, valok * val.unit, atol=dval * val.unit)
def allclose_m8(a, b, rtol=1.e-8, atol=None): if atol is None: atol = 1.e-8 * getattr(a, 'unit', 1) return quantity_allclose(a, b, rtol, atol)
def test_read_only_input(): lon = np.array([80., 440.]) * u.deg lat = np.array([45.]) * u.deg lon.flags.writeable = lat.flags.writeable = False loc = EarthLocation.from_geodetic(lon=lon, lat=lat) assert quantity_allclose(loc[1].x, loc[0].x)
def vvd(val, valok, dval, func, test, status): """Mimic routine of erfa/src/t_erfa_c.c (to help copy & paste)""" assert quantity_allclose(val, valok * val.unit, atol=dval * val.unit)