def ecef2eci(x, y, z, dt): #This function takes a position in the ECI-J2000 corrdinate system and returns it #in ECEF. # # Input # x = ECI X-coordinate (m) # y = ECI Y-coordinate (m) # z = ECI Z-coordinate (m) # dt = UTC time (datetime object) # # # Output # # convert datetime object to astropy time object tt = time.Time(dt, format='datetime') # Read the coordinates in the Geocentric Celestial Reference System itrs = ITRS(CartesianRepresentation(x=x * units.km, y=y * units.km, z=z * units.km), obstime=tt) # Convert it to an Earth-fixed frame gcrs = itrs.transform_to(GCRS(obstime=tt)) x = gcrs.cartesian.x y = gcrs.cartesian.y z = gcrs.cartesian.z return x, y, z
def test_gcrs_cirs(): """ Check GCRS<->CIRS transforms for round-tripping. More complicated than the above two because it's multi-hop """ ra, dec, _ = randomly_sample_sphere(200) gcrs = GCRS(ra=ra, dec=dec, obstime='J2000') gcrs6 = GCRS(ra=ra, dec=dec, obstime='J2006') gcrs2 = gcrs.transform_to(CIRS()).transform_to(gcrs) gcrs6_2 = gcrs6.transform_to(CIRS()).transform_to(gcrs) assert_allclose(gcrs.ra, gcrs2.ra) assert_allclose(gcrs.dec, gcrs2.dec) assert not allclose(gcrs.ra, gcrs6_2.ra) assert not allclose(gcrs.dec, gcrs6_2.dec) # now try explicit intermediate pathways and ensure they're all consistent gcrs3 = gcrs.transform_to(ITRS()).transform_to(CIRS()).transform_to( ITRS()).transform_to(gcrs) assert_allclose(gcrs.ra, gcrs3.ra) assert_allclose(gcrs.dec, gcrs3.dec) gcrs4 = gcrs.transform_to(ICRS()).transform_to(CIRS()).transform_to( ICRS()).transform_to(gcrs) assert_allclose(gcrs.ra, gcrs4.ra) assert_allclose(gcrs.dec, gcrs4.dec)
def test_gcrs_cirs(): """ Check GCRS<->CIRS transforms for round-tripping. More complicated than the above two because it's multi-hop """ usph = golden_spiral_grid(200) gcrs = GCRS(usph, obstime='J2000') gcrs6 = GCRS(usph, obstime='J2006') gcrs2 = gcrs.transform_to(CIRS()).transform_to(gcrs) gcrs6_2 = gcrs6.transform_to(CIRS()).transform_to(gcrs) assert_allclose(gcrs.ra, gcrs2.ra) assert_allclose(gcrs.dec, gcrs2.dec) # these should be different: assert not allclose(gcrs.ra, gcrs6_2.ra, rtol=1e-8) assert not allclose(gcrs.dec, gcrs6_2.dec, rtol=1e-8) # now try explicit intermediate pathways and ensure they're all consistent gcrs3 = gcrs.transform_to(ITRS()).transform_to(CIRS()).transform_to( ITRS()).transform_to(gcrs) assert_allclose(gcrs.ra, gcrs3.ra) assert_allclose(gcrs.dec, gcrs3.dec) gcrs4 = gcrs.transform_to(ICRS()).transform_to(CIRS()).transform_to( ICRS()).transform_to(gcrs) assert_allclose(gcrs.ra, gcrs4.ra) assert_allclose(gcrs.dec, gcrs4.dec)
def ecef2eci(time,r_ecef,v_ecef,init_gps_weeknum): """Returns a tuple of position and velocity in ECI""" coord_ecef=ITRS(x=r_ecef[0]*u.m, y=r_ecef[1]*u.m, z=r_ecef[2]*u.m, v_x=v_ecef[0]*u.m/u.s, v_y=v_ecef[1]*u.m/u.s, v_z=v_ecef[2]*u.m/u.s, representation_type=CartesianRepresentation, differential_type=CartesianDifferential, obstime=time2astropyTime(time,init_gps_weeknum)) coord_eci= coord_ecef.transform_to(GCRS(obstime=time2astropyTime(time,init_gps_weeknum))) return (coord_eci.cartesian.xyz.to_value(u.m),coord_eci.velocity.d_xyz.to_value(u.m/u.s))
def ECEF2ECI_pos(Pos_ECEF, t): T = Time(t, format='jd', scale='utc') Pos_ECEF_SC = ITRS(x=Pos_ECEF[0] * u.m, y=Pos_ECEF[1] * u.m, z=Pos_ECEF[2] * u.m, obstime=T) Pos_ECI_SC = Pos_ECEF_SC.transform_to(GCRS(obstime=T)) Pos_ECI = np.vstack(Pos_ECI_SC.cartesian.xyz.value) return Pos_ECI
def setup_class(cls): cls.loc = loc = EarthLocation.from_geodetic( np.linspace(0, 360, 6)*u.deg, np.linspace(-90, 90, 6)*u.deg, 100*u.m) cls.obstime = obstime = Time(np.linspace(2000, 2010, 6), format='jyear') # Get comparison via a full transformation. We do not use any methods # of EarthLocation, since those depend on the fast transform. loc_itrs = ITRS(loc.x, loc.y, loc.z, obstime=obstime) zeros = np.broadcast_to(0. * (u.km / u.s), (3,) + loc_itrs.shape, subok=True) loc_itrs.data.differentials['s'] = CartesianDifferential(zeros) loc_gcrs_cart = loc_itrs.transform_to(GCRS(obstime=obstime)).cartesian cls.obsgeoloc = loc_gcrs_cart.without_differentials() cls.obsgeovel = loc_gcrs_cart.differentials['s'].to_cartesian()
def test_tete_transforms(): """ We test the TETE transforms for proper behaviour here. The TETE transforms are tested for accuracy against JPL Horizons in test_solar_system.py. Here we are looking to check for consistency and errors in the self transform. """ loc = EarthLocation.from_geodetic("-22°57'35.1", "-67°47'14.1", 5186 * u.m) time = Time('2020-04-06T00:00') p, v = loc.get_gcrs_posvel(time) gcrs_frame = GCRS(obstime=time, obsgeoloc=p, obsgeovel=v) moon = SkyCoord(169.24113968 * u.deg, 10.86086666 * u.deg, 358549.25381755 * u.km, frame=gcrs_frame) tete_frame = TETE(obstime=time, location=loc) # need to set obsgeoloc/vel explicity or skycoord behaviour over-writes tete_geo = TETE(obstime=time, location=EarthLocation(*([0, 0, 0] * u.km))) # test self-transform by comparing to GCRS-TETE-ITRS-TETE route tete_coo1 = moon.transform_to(tete_frame) tete_coo2 = moon.transform_to(tete_geo) assert_allclose(tete_coo1.separation_3d(tete_coo2), 0 * u.mm, atol=1 * u.mm) # test TETE-ITRS transform by comparing GCRS-CIRS-ITRS to GCRS-TETE-ITRS itrs1 = moon.transform_to(CIRS()).transform_to(ITRS()) itrs2 = moon.transform_to(TETE()).transform_to(ITRS()) # this won't be as close since it will round trip through ICRS until # we have some way of translating between the GCRS obsgeoloc/obsgeovel # attributes and the CIRS location attributes assert_allclose(itrs1.separation_3d(itrs2), 0 * u.mm, atol=100 * u.mm) # test round trip GCRS->TETE->GCRS new_moon = moon.transform_to(TETE()).transform_to(moon) assert_allclose(new_moon.separation_3d(moon), 0 * u.mm, atol=1 * u.mm) # test round trip via ITRS tete_rt = tete_coo1.transform_to( ITRS(obstime=time)).transform_to(tete_coo1) assert_allclose(tete_rt.separation_3d(tete_coo1), 0 * u.mm, atol=1 * u.mm) # ensure deprecated routine remains consistent # make sure test raises warning! with pytest.warns(AstropyDeprecationWarning, match='The use of'): tete_alt = _apparent_position_in_true_coordinates(moon) assert_allclose(tete_coo1.separation_3d(tete_alt), 0 * u.mm, atol=100 * u.mm)
def ecef_to_eci(r: np.ndarray, time: Time) -> np.ndarray: """ Converts coordinates in Earth Centered Earth Initial frame to Earth Centered Initial. :param r: position of satellite in ECEF frame. Units [km] :param time: Time of observation """ itrs = ITRS(CartesianRepresentation(r[0] * u.km, r[1] * u.km, r[2] * u.km), obstime=time) gcrs = itrs.transform_to(GCRS(obstime=time)) x_eci = gcrs.cartesian.x.value y_eci = gcrs.cartesian.y.value z_eci = gcrs.cartesian.z.value return np.array([x_eci, y_eci, z_eci])
def test_gcrs_altaz_bothroutes(testframe): """ Repeat of both the moonish and sunish tests above to make sure the two routes through the coordinate graph are consistent with each other """ sun = get_sun(testframe.obstime) sunaa_viaicrs = sun.transform_to(ICRS()).transform_to(testframe) sunaa_viaitrs = sun.transform_to(ITRS(obstime=testframe.obstime)).transform_to(testframe) moon = GCRS(MOONDIST_CART, obstime=testframe.obstime) moonaa_viaicrs = moon.transform_to(ICRS()).transform_to(testframe) moonaa_viaitrs = moon.transform_to(ITRS(obstime=testframe.obstime)).transform_to(testframe) assert_allclose(sunaa_viaicrs.cartesian.xyz, sunaa_viaitrs.cartesian.xyz) assert_allclose(moonaa_viaicrs.cartesian.xyz, moonaa_viaitrs.cartesian.xyz)
def sun_position(obs_time): location = EarthLocation(lon=115.2505 * u.deg, lat=42.211833333 * u.deg, height=1365.0 * u.m) solar_system_ephemeris.set('de432s') # GCRS phasecentre = get_body('sun', obs_time, location, ephemeris='jpl') print('SUN: RA:{} Dec:{}'.format(phasecentre.ra.value, phasecentre.dec.value)) # convert phasecentre into ITRS coordinate # ITRF - Alta cAltAz = phasecentre.transform_to( AltAz(obstime=obs_time, location=location)) newAltAzcoordiantes = SkyCoord(alt=cAltAz.alt, az=cAltAz.az, obstime=obs_time, frame='altaz') new_ra_dec = newAltAzcoordiantes.transform_to('icrs') print(new_ra_dec) c_ITRS = phasecentre.transform_to(ITRS(obstime=obs_time, location=location)) local_ha = location.lon - c_ITRS.spherical.lon local_ha.wrap_at(24 * u.hourangle, inplace=True) print("UTC: {} Local Hour Angle: {}".format(obs_time, local_ha.to('deg').value)) obs_time1 = Time(obs_time, scale='utc', location=location) lst = obs_time1.sidereal_time('mean') local_ha1 = lst.to('deg').value - phasecentre.ra.value print("UTC: {} Local Hour Angle: {}".format(obs_time, local_ha1 * u.deg))
def test_gcrs_altaz(): """ Check GCRS<->AltAz transforms for round-tripping. Has multiple paths """ from astropy.coordinates import EarthLocation ra, dec, _ = randomly_sample_sphere(1) gcrs = GCRS(ra=ra[0], dec=dec[0], obstime='J2000') # check array times sure N-d arrays work times = Time(np.linspace(2456293.25, 2456657.25, 51) * u.day, format='jd') loc = EarthLocation(lon=10 * u.deg, lat=80. * u.deg) aaframe = AltAz(obstime=times, location=loc) aa1 = gcrs.transform_to(aaframe) aa2 = gcrs.transform_to(ICRS()).transform_to(CIRS()).transform_to(aaframe) aa3 = gcrs.transform_to(ITRS()).transform_to(CIRS()).transform_to(aaframe) # make sure they're all consistent assert_allclose(aa1.alt, aa2.alt) assert_allclose(aa1.az, aa2.az) assert_allclose(aa1.alt, aa3.alt) assert_allclose(aa1.az, aa3.az)
def test_regression_futuretimes_4302(): """ Checks that an error is not raised for future times not covered by IERS tables (at least in a simple transform like CIRS->ITRS that simply requires the UTC<->UT1 conversion). Relevant comment: https://github.com/astropy/astropy/pull/4302#discussion_r44836531 """ from astropy.utils.exceptions import AstropyWarning # this is an ugly hack to get the warning to show up even if it has already # appeared from astropy.coordinates.builtin_frames import utils if hasattr(utils, '__warningregistry__'): utils.__warningregistry__.clear() with catch_warnings() as found_warnings: future_time = Time('2511-5-1') c = CIRS(1 * u.deg, 2 * u.deg, obstime=future_time) c.transform_to(ITRS(obstime=future_time)) if not isinstance(iers.IERS_Auto.iers_table, iers.IERS_Auto): saw_iers_warnings = False for w in found_warnings: if issubclass(w.category, AstropyWarning): if '(some) times are outside of range covered by IERS table' in str( w.message): saw_iers_warnings = True break assert saw_iers_warnings, 'Never saw IERS warning'
def test_default(self): # Test the initialisation model = "IGRF12" self.assertEqual(grand_tools.geomagnet.model(), model) # Test the default field getter c = self.get_coordinates() field = grand_tools.geomagnet.field(c) self.assertEqual(field.x.size, 1) self.assertEqual(field.x.unit, u.T) self.assertEqual(field.y.unit, u.T) self.assertEqual(field.z.unit, u.T) self.assertEqual(c.obstime, field.obstime) self.assertField(field) # Test the vectorized getter n = 10 c = self.get_coordinates(n) field = grand_tools.geomagnet.field(c) self.assertEqual(field.x.size, n) self.assertEqual(c.obstime, field.obstime) for value in field: self.assertEqual(field.x.unit, u.T) self.assertEqual(field.y.unit, u.T) self.assertEqual(field.z.unit, u.T) frame = ENU(location=self.location) enu = value.transform_to(frame) self.assertField(enu) # Test the getter from ITRS itrs = ITRS(self.location.itrs.cartesian, obstime=self.date) field = grand_tools.geomagnet.field(itrs) self.assertEqual(field.x.size, 1) self.assertEqual(c.obstime, field.obstime) self.assertField(field)
def test_get_body_fixed(): """Tests the body fixed coords output for multiple times.""" time = Time("2020-04-10T00:00:00", scale="utc") + np.arange(1, 4) * TimeDelta( 1, format="jd" ) gnd_loc = GroundLocation( 10 * u.deg, 15 * u.deg, 150 * u.m, ellipsoid=EARTH_ELLIPSOID_GRS80 ) gnd_loc_body_fixed = gnd_loc.to_body_fixed_coords(EARTH, obstime=time) r_itrs_true = ITRS( CartesianRepresentation( np.asarray( [ [6068714.27712043, 1070078.065267, 1640138.96300037], [6068714.27712043, 1070078.065267, 1640138.96300037], [6068714.27712043, 1070078.065267, 1640138.96300037], ] ).transpose(), unit=u.m, ), obstime=time, representation_type="cartesian", differential_type="cartesian", ) # print(gnd_loc_body_fixed) assert str(gnd_loc_body_fixed) == str(r_itrs_true)
def __init__(self, mccname): mccfile = file(mccname) header1 = mccfile.readline().strip() header2 = mccfile.readline().strip() self.mcc_epoch_year = float(header2.split()[0]) self.mcc_epoch = Time("{0:4.0f}-01-01T00:00:00".format( self.mcc_epoch_year), format='isot', scale='utc') cols = np.loadtxt(mccfile, usecols=(0, 1, 2, 3), unpack=True) self.t = cols[0] * u.s + self.mcc_epoch self.met = (self.t - MET0).to(u.s).value self.eci_x = (cols[1] * u.imperial.foot).to(u.m) self.eci_y = (cols[2] * u.imperial.foot).to(u.m) self.eci_z = (cols[3] * u.imperial.foot).to(u.m) self.eci_x_interp = InterpolatedUnivariateSpline(self.met, self.eci_x, ext='raise') self.eci_y_interp = InterpolatedUnivariateSpline(self.met, self.eci_y, ext='raise') self.eci_z_interp = InterpolatedUnivariateSpline(self.met, self.eci_z, ext='raise') # Convert ECI positions to lat, long using astropy cart = CartesianRepresentation(self.eci_x, self.eci_y, self.eci_z) eci = GCRS(cart, obstime=self.t) ecef = eci.transform_to(ITRS(obstime=self.t)) self.lat = ecef.earth_location.lat self.lon = ecef.earth_location.lon
def eci2lla(x, y, z, dt): """ Convert Earth-Centered Inertial (ECI) cartesian coordinates to latitude, longitude, and altitude, using astropy. Inputs : x = ECI X-coordinate (m) y = ECI Y-coordinate (m) z = ECI Z-coordinate (m) dt = UTC time (datetime object) Outputs : lon = longitude (radians) lat = geodetic latitude (radians) alt = height above WGS84 ellipsoid (m) """ # convert datetime object to astropy time object tt = Time(dt, format='datetime') # Read the coordinates in the Geocentric Celestial Reference System gcrs = GCRS(CartesianRepresentation(x=x * u.m, y=y * u.m, z=z * u.m), obstime=tt) # Convert it to an Earth-fixed frame itrs = gcrs.transform_to(ITRS(obstime=tt)) el = EarthLocation.from_geocentric(itrs.x, itrs.y, itrs.z) # conversion to geodetic lon, lat, alt = el.to_geodetic() # lon_val = lon.value return lon.value, lat.value, alt.value
def earth_location_itrf(self, time=None): '''Return NICER spacecraft location in ITRF coordinates''' if self.tt2tdb_mode.lower().startswith('none'): return None elif self.tt2tdb_mode.lower().startswith('geo'): return EarthLocation.from_geocentric(0.0 * u.m, 0.0 * u.m, 0.0 * u.m) elif self.tt2tdb_mode.lower().startswith('spacecraft'): # First, interpolate ECI geocentric location from orbit file. # These are inertial coorinates aligned with ICRF pos_gcrs = GCRS(CartesianRepresentation( self.X(time.tt.mjd) * u.m, self.Y(time.tt.mjd) * u.m, self.Z(time.tt.mjd) * u.m), obstime=time) # Now transform ECI (GCRS) to ECEF (ITRS) # By default, this uses the WGS84 ellipsoid pos_ITRS = pos_gcrs.transform_to(ITRS(obstime=time)) # Return geocentric ITRS coordinates as an EarthLocation object return pos_ITRS.earth_location else: log.error('Unknown tt2tdb_mode %s, using None', self.tt2tdb_mode) return None
def test_eloc_attributes(): from astropy.coordinates import AltAz, ITRS, GCRS, EarthLocation el = EarthLocation(lon=12.3*u.deg, lat=45.6*u.deg, height=1*u.km) it = ITRS(r.SphericalRepresentation(lon=12.3*u.deg, lat=45.6*u.deg, distance=1*u.km)) gc = GCRS(ra=12.3*u.deg, dec=45.6*u.deg, distance=6375*u.km) el1 = AltAz(location=el).location assert isinstance(el1, EarthLocation) # these should match *exactly* because the EarthLocation assert el1.lat == el.lat assert el1.lon == el.lon assert el1.height == el.height el2 = AltAz(location=it).location assert isinstance(el2, EarthLocation) # these should *not* match because giving something in Spherical ITRS is # *not* the same as giving it as an EarthLocation: EarthLocation is on an # elliptical geoid. So the longitude should match (because flattening is # only along the z-axis), but latitude should not. Also, height is relative # to the *surface* in EarthLocation, but the ITRS distance is relative to # the center of the Earth assert not allclose(el2.lat, it.spherical.lat) assert allclose(el2.lon, it.spherical.lon) assert el2.height < -6000*u.km el3 = AltAz(location=gc).location # GCRS inputs implicitly get transformed to ITRS and then onto # EarthLocation's elliptical geoid. So both lat and lon shouldn't match assert isinstance(el3, EarthLocation) assert not allclose(el3.lat, gc.dec) assert not allclose(el3.lon, gc.ra) assert np.abs(el3.height) < 500*u.km
def test_gcrs_itrs_cartesian_repr(): # issue 6436: transformation failed if coordinate representation was # Cartesian gcrs = GCRS(CartesianRepresentation((859.07256, -4137.20368, 5295.56871), unit='km'), representation_type='cartesian') gcrs.transform_to(ITRS())
def test_cirs_itrs(): """ Check basic CIRS<->ITRS transforms for round-tripping. """ ra, dec, _ = randomly_sample_sphere(200) cirs = CIRS(ra=ra, dec=dec, obstime='J2000') cirs6 = CIRS(ra=ra, dec=dec, obstime='J2006') cirs2 = cirs.transform_to(ITRS()).transform_to(cirs) cirs6_2 = cirs6.transform_to(ITRS()).transform_to(cirs) # different obstime # just check round-tripping assert_allclose(cirs.ra, cirs2.ra) assert_allclose(cirs.dec, cirs2.dec) assert not allclose(cirs.ra, cirs6_2.ra) assert not allclose(cirs.dec, cirs6_2.dec)
def test_gcrs_hadec(): """ Check GCRS<->HADec transforms for round-tripping. Has multiple paths """ from astropy.coordinates import EarthLocation usph = golden_spiral_grid(128) gcrs = GCRS(usph, obstime='J2000') # broadcast with times below # check array times sure N-d arrays work times = Time(np.linspace(2456293.25, 2456657.25, 51) * u.day, format='jd')[:, np.newaxis] loc = EarthLocation(lon=10 * u.deg, lat=80. * u.deg) hdframe = HADec(obstime=times, location=loc) hd1 = gcrs.transform_to(hdframe) hd2 = gcrs.transform_to(ICRS()).transform_to(CIRS()).transform_to(hdframe) hd3 = gcrs.transform_to(ITRS()).transform_to(CIRS()).transform_to(hdframe) # make sure they're all consistent assert_allclose(hd1.dec, hd2.dec) assert_allclose(hd1.ha, hd2.ha) assert_allclose(hd1.dec, hd3.dec) assert_allclose(hd1.ha, hd3.ha)
def test_gcrs_altaz(): """ Check GCRS<->AltAz transforms for round-tripping. Has multiple paths """ from astropy.coordinates import EarthLocation usph = golden_spiral_grid(128) gcrs = GCRS(usph, obstime='J2000')[None] # broadcast with times below # check array times sure N-d arrays work times = Time(np.linspace(2456293.25, 2456657.25, 51) * u.day, format='jd')[:, None] loc = EarthLocation(lon=10 * u.deg, lat=80. * u.deg) aaframe = AltAz(obstime=times, location=loc) aa1 = gcrs.transform_to(aaframe) aa2 = gcrs.transform_to(ICRS()).transform_to(CIRS()).transform_to(aaframe) aa3 = gcrs.transform_to(ITRS()).transform_to(CIRS()).transform_to(aaframe) # make sure they're all consistent assert_allclose(aa1.alt, aa2.alt) assert_allclose(aa1.az, aa2.az) assert_allclose(aa1.alt, aa3.alt) assert_allclose(aa1.az, aa3.az)
def eci2ecef(x: float | ndarray, y: float | ndarray, z: float | ndarray, time: datetime, *, use_astropy: bool = True) -> tuple[ndarray, ndarray, ndarray]: """ Observer => Point ECI => ECEF J2000 frame Parameters ---------- x : float ECI x-location [meters] y : float ECI y-location [meters] z : float ECI z-location [meters] time : datetime.datetime time of obsevation (UTC) use_astropy: bool, optional use AstroPy (much more accurate) Results ------- x_ecef : float x ECEF coordinate y_ecef : float y ECEF coordinate z_ecef : float z ECEF coordinate """ if use_astropy and Time is not None: gcrs = GCRS(CartesianRepresentation(x * u.m, y * u.m, z * u.m), obstime=time) itrs = gcrs.transform_to(ITRS(obstime=time)) x_ecef = itrs.x.value y_ecef = itrs.y.value z_ecef = itrs.z.value else: x = atleast_1d(x) y = atleast_1d(y) z = atleast_1d(z) gst = atleast_1d(greenwichsrt(juliandate(time))) assert x.shape == y.shape == z.shape assert x.size == gst.size eci = column_stack((x.ravel(), y.ravel(), z.ravel())) ecef = empty((x.size, 3)) for i in range(eci.shape[0]): ecef[i, :] = R3(gst[i]) @ eci[i, :].T x_ecef = ecef[:, 0].reshape(x.shape) y_ecef = ecef[:, 1].reshape(y.shape) z_ecef = ecef[:, 2].reshape(z.shape) return x_ecef, y_ecef, z_ecef
def eci2el(x, y, z, dt): """ Convert Earth-Centered Inertial (ECI) cartesian coordinates to ITRS for astropy EarthLocation object. Inputs : x = ECI X-coordinate y = ECI Y-coordinate z = ECI Z-coordinate dt = UTC time (datetime object) """ from astropy.coordinates import GCRS, ITRS, EarthLocation, CartesianRepresentation import astropy.units as u # convert datetime object to astropy time object tt = Time(dt, format='datetime') # Read the coordinates in the Geocentric Celestial Reference System gcrs = GCRS(CartesianRepresentation(x=x, y=y, z=z), obstime=tt) # Convert it to an Earth-fixed frame itrs = gcrs.transform_to(ITRS(obstime=tt)) el = EarthLocation.from_geocentric(itrs.x, itrs.y, itrs.z) return el
def test_regression_futuretimes_4302(): """ Checks that an error is not raised for future times not covered by IERS tables (at least in a simple transform like CIRS->ITRS that simply requires the UTC<->UT1 conversion). Relevant comment: https://github.com/astropy/astropy/pull/4302#discussion_r44836531 """ from astropy.utils.compat.context import nullcontext from astropy.utils.exceptions import AstropyWarning # this is an ugly hack to get the warning to show up even if it has already # appeared from astropy.coordinates.builtin_frames import utils if hasattr(utils, '__warningregistry__'): utils.__warningregistry__.clear() # check that out-of-range warning appears among any other warnings. If # tests are run with --remote-data then the IERS table will be an instance # of IERS_Auto which is assured of being "fresh". In this case getting # times outside the range of the table does not raise an exception. Only # if using IERS_B (which happens without --remote-data, i.e. for all CI # testing) do we expect another warning. if isinstance(iers.earth_orientation_table.get(), iers.IERS_B): ctx = pytest.warns( AstropyWarning, match=r'\(some\) times are outside of range covered by IERS table.*') else: ctx = nullcontext() with ctx: future_time = Time('2511-5-1') c = CIRS(1*u.deg, 2*u.deg, obstime=future_time) c.transform_to(ITRS(obstime=future_time))
def earth_location_itrf(self, time=None): '''Return RXTE spacecraft location in ITRF coordinates''' if self.tt2tdb_mode.lower().startswith('pint'): log.warning('Using location=None for TT to TDB conversion') return None elif self.tt2tdb_mode.lower().startswith('astropy'): # First, interpolate ECI geocentric location from orbit file. # These are inertial coorinates aligned with ICRF log.warning('Performing GCRS to ITRS transformation') pos_gcrs = GCRS(CartesianRepresentation( self.X(time.tt.mjd) * u.m, self.Y(time.tt.mjd) * u.m, self.Z(time.tt.mjd) * u.m), obstime=time) # Now transform ECI (GCRS) to ECEF (ITRS) # By default, this uses the WGS84 ellipsoid pos_ITRS = pos_gcrs.transform_to(ITRS(obstime=time)) # Return geocentric ITRS coordinates as an EarthLocation object return pos_ITRS.earth_location else: log.error('Unknown tt2tdb_mode %s, using None' % self.tt2tdb_mode) return None
def earth_location_itrf(self, time=None): '''Return POLAR spacecraft location in ITRF coordinates''' if self.tt2tdb_mode.lower().startswith('none'): log.warning('Using location=None for TT to TDB conversion') return None elif self.tt2tdb_mode.lower().startswith('geo'): log.warning('Using location geocenter for TT to TDB conversion') return EarthLocation.from_geocentric(0.0 * u.m, 0.0 * u.m, 0.0 * u.m) elif self.tt2tdb_mode.lower().startswith('spacecraft'): # First, interpolate Earth-Centered Inertial (ECI) geocentric # location from orbit file. # These are inertial coordinates aligned with ICRS, called GCRS # <http://docs.astropy.org/en/stable/api/astropy.coordinates.GCRS.html> pos_gcrs = GCRS(CartesianRepresentation( self.X(time.utc.unix) * u.m, self.Y(time.utc.unix) * u.m, self.Z(time.utc.unix) * u.m), obstime=time) # Now transform ECI (GCRS) to ECEF (ITRS) # By default, this uses the WGS84 ellipsoid pos_ITRS = pos_gcrs.transform_to(ITRS(obstime=time)) # Return geocentric ITRS coordinates as an EarthLocation object return pos_ITRS.earth_location else: log.error('Unknown tt2tdb_mode %s, using None', self.tt2tdb_mode) return None
def test_cirs_itrs(): """ Check basic CIRS<->ITRS transforms for round-tripping. """ usph = golden_spiral_grid(200) cirs = CIRS(usph, obstime='J2000') cirs6 = CIRS(usph, obstime='J2006') cirs2 = cirs.transform_to(ITRS()).transform_to(cirs) cirs6_2 = cirs6.transform_to(ITRS()).transform_to( cirs) # different obstime # just check round-tripping assert_allclose(cirs.ra, cirs2.ra) assert_allclose(cirs.dec, cirs2.dec) assert not allclose(cirs.ra, cirs6_2.ra) assert not allclose(cirs.dec, cirs6_2.dec)
def ecef2eci(x, y, z, dt): """This function takes a position in the ECEF coordinate system [m] and datetime.object [utc] and returns it in ECI-J2000 [m].""" # # Input # x = ECEF X-coordinate (m) # y = ECEF Y-coordinate (m) # z = ECEF Z-coordinate (m) # dt = UTC time (datetime object) # # # Output # # convert datetime object to astropy time object tt = time.Time(dt, format="datetime") # Read the coordinates in the Earth-fixed frame itrs = ITRS( CartesianRepresentation(x=x * units.m, y=y * units.m, z=z * units.m), obstime=tt ) # Convert it to Geocentric Celestial Reference System # gcrs = itrs.transform_to(itrs(obstime=tt)) gcrs = itrs.transform_to(GCRS(obstime=tt)) x = gcrs.cartesian.x.to_value() y = gcrs.cartesian.y.to_value() z = gcrs.cartesian.z.to_value() return x, y, z
def convert(t, states, in_frame, out_frame, logger=None, profiler=None, **kwargs): '''Perform predefined coordinate transformations. Always returns a copy of the array. ''' if logger is not None: logger.info( f'frames:convert: in_frame={in_frame}, out_frame={out_frame}') if profiler is not None: profiler.start(f'frames:convert:{in_frame}->{out_frame}') in_frame = in_frame.upper() out_frame = out_frame.upper() if in_frame == out_frame: return states.copy() if in_frame == 'TEME': astropy_states = _convert_to_astropy(states, TEME, obstime=t) elif in_frame in ['ITRS', 'ITRF']: #Reference System VS Reference Frame astropy_states = _convert_to_astropy(states, ITRS, obstime=t) elif in_frame in ['ICRS', 'ICRF']: astropy_states = _convert_to_astropy(states, ICRS) elif in_frame in ['GCRS', 'GCRF']: astropy_states = _convert_to_astropy(states, GCRS, obstime=t) else: raise ValueError( f'In frame "{in_frame}" not recognized, please perform manual transformation' ) if out_frame in ['ITRS', 'ITRF']: out_states = astropy_states.transform_to(ITRS(obstime=t)) elif out_frame == 'TEME': out_states = astropy_states.transform_to(TEME(obstime=t)) elif out_frame in ['ICRS', 'ICRF']: out_states = astropy_states.transform_to(ICRS()) elif out_frame in ['GCRS', 'GCRF']: out_states = astropy_states.transform_to(GCRS(obstime=t)) else: raise ValueError( f'Out frame "{out_frame}" not recognized, please perform manual transformation' ) rets = states.copy() rets[:3, ...] = out_states.cartesian.xyz.to(units.m).value rets[3:, ...] = out_states.velocity.d_xyz.to(units.m / units.s).value if logger is not None: logger.info('frames:convert:completed') if profiler is not None: profiler.stop(f'frames:convert:{in_frame}->{out_frame}') return rets