def topo_posvels(xyz, toa): """ topo_posvels(xyz, toa) This routine returns a PosVel instance , containing the positions (m) and velocities (m / UT1 s) at the time of the toa and referenced to the ITRF geocentric coordinates. This routine is basically SOFA's pvtob() with an extra rotation from c2ixys. """ # All the times are passed as TT tt = toa.mjd.tt.jd1, toa.mjd.tt.jd2 # Get a floating-point MJD to use for interpolating IERS values mjd = toa.mjd.utc.mjd # Gets x,y coords of Celestial Intermediate Pole and CIO locator s X, Y, S = erfa.xys00a(*tt) # Get dX and dY from IERS A #dX = numpy.interp(mjd, iers_tab['MJD'], iers_tab['dX_2000A_B']) * u.arcsec #dY = numpy.interp(mjd, iers_tab['MJD'], iers_tab['dY_2000A_B']) * u.arcsec # Get dX and dY from IERS B dX = numpy.interp(mjd, iers_tab['MJD'], iers_tab['dX_2000A']) * u.arcsec dY = numpy.interp(mjd, iers_tab['MJD'], iers_tab['dY_2000A']) * u.arcsec # Get GCRS to CIRS matrix rc2i = erfa.c2ixys(X+dX.to(u.rad).value, Y+dY.to(u.rad).value, S) # Gets the TIO locator s' sp = erfa.sp00(*tt) # Get X and Y from IERS A #xp = numpy.interp(mjd, iers_tab['MJD'], iers_tab['PM_X_B']) * u.arcsec #yp = numpy.interp(mjd, iers_tab['MJD'], iers_tab['PM_Y_B']) * u.arcsec # Get X and Y from IERS B xp = numpy.interp(mjd, iers_tab['MJD'], iers_tab['PM_x']) * u.arcsec yp = numpy.interp(mjd, iers_tab['MJD'], iers_tab['PM_y']) * u.arcsec # Get the polar motion matrix rpm = erfa.pom00(xp.to(u.rad).value, yp.to(u.rad).value, sp) # Observatory XYZ coords in meters xyzm = [a.to(u.m).value for a in xyz] x, y, z = erfa.trxp(rpm, xyzm) # Functions of Earth Rotation Angle ut1 = toa.mjd.ut1.jd1, toa.mjd.ut1.jd2 theta = erfa.era00(*ut1) s, c = math.sin(theta), math.cos(theta) # Position pos = numpy.asarray([c*x - s*y, s*x + c*y, z]) pos = erfa.trxp(rc2i, pos) * u.m # Earth rotation rate in radians per UT1 second OM = 1.00273781191135448 * 2 * math.pi / erfa.DAYSEC # Velocity vel = numpy.asarray([OM * (-s*x - c*y), OM * (c*x - s*y), 0.0]) vel = erfa.trxp(rc2i, vel) * u.m / u.s return utils.PosVel(pos, vel, obj=toa.obs, origin="EARTH")
============================================ IAU 2000A, CIO based, using classical angles ============================================ ''') # CIP and CIO, IAU 2000A. X, Y, S = erfa.xys00a(DJMJD0, TT) # Add CIP corrections. X = X + DX00 Y = Y + DY00 print("CIP corrections") print('X = %.17f\nY = %.17f\nS = %.17f' % (X, Y, S * R2AS)) # GCRS to CIRS matrix. RC2I = erfa.c2ixys(X, Y, S) print("NPB matrix, CIO based") pprint(RC2I) # Earth rotation angle. ERA = erfa.era00(DJMJD0 + DATE, TUT) print("Earth rotation angle") print('ERA = %.17f radians' % ERA) print(" = %.17f degrees" % math.degrees(ERA)) print(" = %s%dd%dm%d.%ds" % erfa.a2af(6, ERA)) print(" = %s%dh%dm%d.%ds" % erfa.a2tf(6, ERA)) # Form celestial-terrestrial matrix (no polar motion yet). ##RC2TI = erfa.cr(RC2I) ##RC2TI = erfa.rz(ERA, RC2TI) RC2TI = erfa.rz(ERA, RC2I)
============================================ IAU 2000A, CIO based, using classical angles ============================================ ''') # CIP and CIO, IAU 2000A. X, Y, S = erfa.xys00a(DJMJD0, TT) # Add CIP corrections. X = X + DX00 Y = Y + DY00 print("CIP corrections") print('X = %.17f\nY = %.17f\nS = %.17f'%(X, Y, S*R2AS)) # GCRS to CIRS matrix. RC2I = erfa.c2ixys(X, Y, S) print("NPB matrix, CIO based") pprint(RC2I) # Earth rotation angle. ERA = erfa.era00(DJMJD0+DATE, TUT) print("Earth rotation angle") print('ERA = %.17f radians'%ERA) print(" = %.17f degrees"%math.degrees(ERA)) print(" = %s%dd%dm%d.%ds"%erfa.a2af(6, ERA)) print(" = %s%dh%dm%d.%ds"%erfa.a2tf(6, ERA)) # Form celestial-terrestrial matrix (no polar motion yet). ##RC2TI = erfa.cr(RC2I) ##RC2TI = erfa.rz(ERA, RC2TI) RC2TI = erfa.rz(ERA, RC2I)
def old_gcrs_posvel_from_itrf(loc, toas, obsname="obs"): """Return a list of PosVel instances for the observatory at the TOA times. Observatory location should be given in the loc argument as an astropy EarthLocation object. This location will be in the ITRF frame (i.e. co-rotating with the Earth). The optional obsname argument will be used as label in the returned PosVel instance. This routine returns a list of PosVel instances, containing the positions (m) and velocities (m / s) at the times of the toas and referenced to the Earth-centered Inertial (ECI, aka GCRS) coordinates. This routine is basically SOFA's pvtob() [Position and velocity of a terrestrial observing station] with an extra rotation from c2ixys() [Form the celestial to intermediate-frame-of-date matrix given the CIP X,Y and the CIO locator s]. """ unpack = False # If the input is a single TOA (i.e. a row from the table), # then put it into a list if type(toas) == table.row.Row: ttoas = Time([toas["mjd"]]) unpack = True elif type(toas) == table.table.Table: ttoas = toas["mjd"] elif isinstance(toas, Time): if toas.isscalar: ttoas = Time([toas]) unpack = True else: ttoas = toas else: if np.isscalar(toas): ttoas = Time([toas], format="mjd") unpack = True else: ttoas = toas N = len(ttoas) if len(ttoas.shape) != 1: raise ValueError("At most one-dimensional array of times possible, " "shape was {}".format(ttoas.shape)) # Get various times from the TOAs as arrays tts = np.asarray([(t.jd1, t.jd2) for t in ttoas.tt]).T ut1s = np.asarray([(t.jd1, t.jd2) for t in ttoas.ut1]).T mjds = np.asarray(ttoas.mjd) iers_b = get_iers_b_up_to_date(mjds.max()) # Get x, y coords of Celestial Intermediate Pole and CIO locator s X, Y, S = erfa.xys00a(*tts) # Get dX and dY from IERS A in arcsec and convert to radians # dX = np.interp(mjds, iers_tab['MJD'], iers_tab['dX_2000A_B']) * asec2rad # dY = np.interp(mjds, iers_tab['MJD'], iers_tab['dY_2000A_B']) * asec2rad # Get dX and dY from IERS B in arcsec and convert to radians dX = np.interp(mjds, iers_b["MJD"].to_value(u.d), iers_b["dX_2000A"].to_value(u.rad)) dY = np.interp(mjds, iers_b["MJD"].to_value(u.d), iers_b["dY_2000A"].to_value(u.rad)) # Get GCRS to CIRS matrices rc2i = erfa.c2ixys(X + dX, Y + dY, S) # Gets the TIO locator s' sp = erfa.sp00(*tts) # Get X and Y from IERS A in arcsec and convert to radians # xp = np.interp(mjds, iers_tab['MJD'], iers_tab['PM_X_B']) * asec2rad # yp = np.interp(mjds, iers_tab['MJD'], iers_tab['PM_Y_B']) * asec2rad # Get X and Y from IERS B in arcsec and convert to radians xp = np.interp(mjds, iers_b["MJD"].to_value(u.d), iers_b["PM_x"].to_value(u.rad)) yp = np.interp(mjds, iers_b["MJD"].to_value(u.d), iers_b["PM_y"].to_value(u.rad)) # Get the polar motion matrices rpm = erfa.pom00(xp, yp, sp) # Observatory geocentric coords in m xyzm = np.array([a.to_value(u.m) for a in loc.geocentric]) x, y, z = np.dot(xyzm, rpm).T # Functions of Earth Rotation Angle theta = erfa.era00(*ut1s) s, c = np.sin(theta), np.cos(theta) sx, cx = s * x, c * x sy, cy = s * y, c * y # Initial positions and velocities iposs = np.asarray([cx - sy, sx + cy, z]).T ivels = np.asarray([OM * (-sx - cy), OM * (cx - sy), np.zeros_like(x)]).T # There is probably a way to do this with np.einsum or something... # and here it is . poss = np.empty((N, 3), dtype=np.float64) vels = np.empty((N, 3), dtype=np.float64) poss = np.einsum("ij,ijk->ik", iposs, rc2i) vels = np.einsum("ij,ijk->ik", ivels, rc2i) r = PosVel(poss.T * u.m, vels.T * u.m / u.s, obj=obsname, origin="earth") if unpack: return r[0] else: return r