def test_regression_4293(): """Really just an extra test on FK4 no e, after finding that the units were not always taken correctly. This test is against explicitly doing the transformations on pp170 of Explanatory Supplement to the Astronomical Almanac (Seidelmann, 2005). See https://github.com/astropy/astropy/pull/4293#issuecomment-234973086 """ # Check all over sky, but avoiding poles (note that FK4 did not ignore # e terms within 10∘ of the poles... see p170 of explan.supp.). ra, dec = np.meshgrid(np.arange(0, 359, 45), np.arange(-80, 81, 40)) fk4 = FK4(ra.ravel() * u.deg, dec.ravel() * u.deg) Dc = -0.065838*u.arcsec Dd = +0.335299*u.arcsec # Dc * tan(obliquity), as given on p.170 Dctano = -0.028553*u.arcsec fk4noe_dec = (fk4.dec - (Dd*np.cos(fk4.ra) - Dc*np.sin(fk4.ra))*np.sin(fk4.dec) - Dctano*np.cos(fk4.dec)) fk4noe_ra = fk4.ra - (Dc*np.cos(fk4.ra) + Dd*np.sin(fk4.ra)) / np.cos(fk4.dec) fk4noe = fk4.transform_to(FK4NoETerms()) # Tolerance here just set to how well the coordinates match, which is much # better than the claimed accuracy of <1 mas for this first-order in # v_earth/c approximation. # Interestingly, if one divides by np.cos(fk4noe_dec) in the ra correction, # the match becomes good to 2 μas. assert_quantity_allclose(fk4noe.ra, fk4noe_ra, atol=11.*u.uas, rtol=0) assert_quantity_allclose(fk4noe.dec, fk4noe_dec, atol=3.*u.uas, rtol=0)
def _wcs_to_celestial_frame_builtin(wcs): # Import astropy.coordinates here to avoid circular imports from astropy.coordinates import (FK4, FK4NoETerms, FK5, ICRS, ITRS, Galactic, SphericalRepresentation) # Import astropy.time here otherwise setup.py fails before extensions are compiled from astropy.time import Time if wcs.wcs.lng == -1 or wcs.wcs.lat == -1: return None radesys = wcs.wcs.radesys if np.isnan(wcs.wcs.equinox): equinox = None else: equinox = wcs.wcs.equinox xcoord = wcs.wcs.ctype[wcs.wcs.lng][:4] ycoord = wcs.wcs.ctype[wcs.wcs.lat][:4] # Apply logic from FITS standard to determine the default radesys if radesys == '' and xcoord == 'RA--' and ycoord == 'DEC-': if equinox is None: radesys = "ICRS" elif equinox < 1984.: radesys = "FK4" else: radesys = "FK5" if radesys == 'FK4': if equinox is not None: equinox = Time(equinox, format='byear') frame = FK4(equinox=equinox) elif radesys == 'FK4-NO-E': if equinox is not None: equinox = Time(equinox, format='byear') frame = FK4NoETerms(equinox=equinox) elif radesys == 'FK5': if equinox is not None: equinox = Time(equinox, format='jyear') frame = FK5(equinox=equinox) elif radesys == 'ICRS': frame = ICRS() else: if xcoord == 'GLON' and ycoord == 'GLAT': frame = Galactic() elif xcoord == 'TLON' and ycoord == 'TLAT': # The default representation for ITRS is cartesian, but for WCS # purposes, we need the spherical representation. frame = ITRS(representation_type=SphericalRepresentation, obstime=wcs.wcs.dateobs or None) else: frame = None return frame
def _wcs_to_celestial_frame_builtin(wcs): # Import astropy.coordinates here to avoid circular imports from astropy.coordinates import FK4, FK4NoETerms, FK5, ICRS, ITRS, Galactic # Import astropy.time here otherwise setup.py fails before extensions are compiled from astropy.time import Time # Keep only the celestial part of the axes wcs = wcs.sub([WCSSUB_LONGITUDE, WCSSUB_LATITUDE]) if wcs.wcs.lng == -1 or wcs.wcs.lat == -1: return None radesys = wcs.wcs.radesys if np.isnan(wcs.wcs.equinox): equinox = None else: equinox = wcs.wcs.equinox xcoord = wcs.wcs.ctype[0][:4] ycoord = wcs.wcs.ctype[1][:4] # Apply logic from FITS standard to determine the default radesys if radesys == '' and xcoord == 'RA--' and ycoord == 'DEC-': if equinox is None: radesys = "ICRS" elif equinox < 1984.: radesys = "FK4" else: radesys = "FK5" if radesys == 'FK4': if equinox is not None: equinox = Time(equinox, format='byear') frame = FK4(equinox=equinox) elif radesys == 'FK4-NO-E': if equinox is not None: equinox = Time(equinox, format='byear') frame = FK4NoETerms(equinox=equinox) elif radesys == 'FK5': if equinox is not None: equinox = Time(equinox, format='jyear') frame = FK5(equinox=equinox) elif radesys == 'ICRS': frame = ICRS() else: if xcoord == 'GLON' and ycoord == 'GLAT': frame = Galactic() elif xcoord == 'TLON' and ycoord == 'TLAT': frame = ITRS(obstime=wcs.wcs.dateobs or None) else: frame = None return frame
def _wcs_to_celestial_frame_builtin(wcs): from astropy.coordinates import FK4, FK4NoETerms, FK5, ICRS, Galactic from astropy.time import Time from astropy.wcs import WCSSUB_CELESTIAL # Keep only the celestial part of the axes wcs = wcs.sub([WCSSUB_CELESTIAL]) if wcs.wcs.lng == -1 or wcs.wcs.lat == -1: return None radesys = wcs.wcs.radesys if np.isnan(wcs.wcs.equinox): equinox = None else: equinox = wcs.wcs.equinox xcoord = wcs.wcs.ctype[0][:4] ycoord = wcs.wcs.ctype[1][:4] # Apply logic from FITS standard to determine the default radesys if radesys == '' and xcoord == 'RA--' and ycoord == 'DEC-': if equinox is None: radesys = "ICRS" elif equinox < 1984.: radesys = "FK4" else: radesys = "FK5" if radesys == 'FK4': if equinox is not None: equinox = Time(equinox, format='byear') frame = FK4(equinox=equinox) elif radesys == 'FK4-NO-E': if equinox is not None: equinox = Time(equinox, format='byear') frame = FK4NoETerms(equinox=equinox) elif radesys == 'FK5': if equinox is not None: equinox = Time(equinox, format='jyear') frame = FK5(equinox=equinox) elif radesys == 'ICRS': frame = ICRS() else: if xcoord == 'GLON' and ycoord == 'GLAT': frame = Galactic() else: frame = None return frame
def test_celestial_frame_to_wcs(): # Import astropy.coordinates here to avoid circular imports from astropy.coordinates import ICRS, ITRS, FK5, FK4, FK4NoETerms, Galactic, BaseCoordinateFrame class FakeFrame(BaseCoordinateFrame): pass frame = FakeFrame() with pytest.raises(ValueError) as exc: celestial_frame_to_wcs(frame) assert exc.value.args[0] == ("Could not determine WCS corresponding to " "the specified coordinate frame.") frame = ICRS() mywcs = celestial_frame_to_wcs(frame) mywcs.wcs.set() assert tuple(mywcs.wcs.ctype) == ('RA---TAN', 'DEC--TAN') assert mywcs.wcs.radesys == 'ICRS' assert np.isnan(mywcs.wcs.equinox) assert mywcs.wcs.lonpole == 180 assert mywcs.wcs.latpole == 0 frame = FK5(equinox='J1987') mywcs = celestial_frame_to_wcs(frame) assert tuple(mywcs.wcs.ctype) == ('RA---TAN', 'DEC--TAN') assert mywcs.wcs.radesys == 'FK5' assert mywcs.wcs.equinox == 1987. frame = FK4(equinox='B1982') mywcs = celestial_frame_to_wcs(frame) assert tuple(mywcs.wcs.ctype) == ('RA---TAN', 'DEC--TAN') assert mywcs.wcs.radesys == 'FK4' assert mywcs.wcs.equinox == 1982. frame = FK4NoETerms(equinox='B1982') mywcs = celestial_frame_to_wcs(frame) assert tuple(mywcs.wcs.ctype) == ('RA---TAN', 'DEC--TAN') assert mywcs.wcs.radesys == 'FK4-NO-E' assert mywcs.wcs.equinox == 1982. frame = Galactic() mywcs = celestial_frame_to_wcs(frame) assert tuple(mywcs.wcs.ctype) == ('GLON-TAN', 'GLAT-TAN') assert mywcs.wcs.radesys == '' assert np.isnan(mywcs.wcs.equinox) frame = Galactic() mywcs = celestial_frame_to_wcs(frame, projection='CAR') assert tuple(mywcs.wcs.ctype) == ('GLON-CAR', 'GLAT-CAR') assert mywcs.wcs.radesys == '' assert np.isnan(mywcs.wcs.equinox) frame = Galactic() mywcs = celestial_frame_to_wcs(frame, projection='CAR') mywcs.wcs.crval = [100, -30] mywcs.wcs.set() assert_allclose((mywcs.wcs.lonpole, mywcs.wcs.latpole), (180, 60)) frame = ITRS(obstime=Time('2017-08-17T12:41:04.43')) mywcs = celestial_frame_to_wcs(frame, projection='CAR') assert tuple(mywcs.wcs.ctype) == ('TLON-CAR', 'TLAT-CAR') assert mywcs.wcs.radesys == 'ITRS' assert mywcs.wcs.dateobs == '2017-08-17T12:41:04.430' frame = ITRS() mywcs = celestial_frame_to_wcs(frame, projection='CAR') assert tuple(mywcs.wcs.ctype) == ('TLON-CAR', 'TLAT-CAR') assert mywcs.wcs.radesys == 'ITRS' assert mywcs.wcs.dateobs == Time('J2000').utc.fits