def gei_to_hme(geicoord, hmeframe): """ Convert from Geocentric Earth Equatorial to Heliocentric Mean Ecliptic """ if geicoord.obstime is None: raise ConvertError("To perform this transformation, the coordinate" " frame needs a specified `obstime`.") # Use an intermediate frame of HME at the GEI observation time int_frame = HeliocentricMeanEcliptic(obstime=geicoord.obstime, equinox=geicoord.equinox) # Get the Sun-Earth vector in the intermediate frame sun_earth = HCRS(_sun_earth_icrf(int_frame.obstime), obstime=int_frame.obstime) sun_earth_int = sun_earth.transform_to(int_frame).cartesian # Rotate from Earth equatorial to ecliptic rot_matrix = _rotation_matrix_obliquity(int_frame.equinox) earth_object_int = geicoord.cartesian.transform(rot_matrix) # Find the Sun-object vector in the intermediate frame sun_object_int = sun_earth_int + earth_object_int int_coord = int_frame.realize_frame(sun_object_int) # Convert to the final frame through HCRS return int_coord.transform_to(HCRS(obstime=int_coord.obstime)).transform_to(hmeframe)
def hme_to_gei(hmecoord, geiframe): """ Convert from Heliocentric Mean Ecliptic to Geocentric Earth Equatorial """ if geiframe.obstime is None: raise ConvertError("To perform this transformation, the coordinate" " frame needs a specified `obstime`.") # Use an intermediate frame of HME at the GEI observation time, through HCRS int_frame = HeliocentricMeanEcliptic(obstime=geiframe.obstime, equinox=geiframe.equinox) int_coord = hmecoord.transform_to( HCRS(obstime=int_frame.obstime)).transform_to(int_frame) # Get the Sun-Earth vector in the intermediate frame sun_earth = HCRS(_sun_earth_icrf(int_frame.obstime), obstime=int_frame.obstime) sun_earth_int = sun_earth.transform_to(int_frame).cartesian # Find the Earth-object vector in the intermediate frame earth_object_int = int_coord.cartesian - sun_earth_int # Rotate from ecliptic to Earth equatorial rot_matrix = matrix_transpose(_rotation_matrix_obliquity( int_frame.equinox)) newrepr = earth_object_int.transform(rot_matrix) return geiframe.realize_frame(newrepr)
def test_hcrs_hgs_reversibility(): # Test whether the HCRS->HGS transformation is reversed by the HGS->HCRS transformation time1 = Time('2001-01-01') time2 = Time('2001-02-01') coord = HCRS(1*u.km, 2*u.km, 3*u.km, representation_type='cartesian', obstime=time1) new_coord = coord.transform_to(HeliographicStonyhurst(obstime=time2)).transform_to(coord) assert quantity_allclose(coord.cartesian.xyz, new_coord.cartesian.xyz)
def test_regression_4926(): times = Time('2010-01-1') + np.arange(20)*u.day green = get_builtin_sites()['greenwich'] # this is the regression test moon = get_moon(times, green) # this is an additional test to make sure the GCRS->ICRS transform works for complex shapes moon.transform_to(ICRS()) # and some others to increase coverage of transforms moon.transform_to(HCRS(obstime="J2000")) moon.transform_to(HCRS(obstime=times))
def test_hcrs_hgs_different_obstime(): # Test whether the HCRS->HGS transformation handles a change in obstime the same way as forcing # a HCRS loopback in Astropy time1 = Time('2001-01-01') time2 = Time('2001-02-01') coord = HCRS(1*u.km, 2*u.km, 3*u.km, representation_type='cartesian', obstime=time1) out_frame = HeliographicStonyhurst(obstime=time2) sunpy_coord = coord.transform_to(out_frame) astropy_coord = coord.transform_to(HCRS(obstime=time2)).transform_to(out_frame) assert quantity_allclose(sunpy_coord.cartesian.xyz, astropy_coord.cartesian.xyz)
def HCI2ECI_pos(Pos_HCI, t): # Position & velocity relative to the sun T = Time(t, format='jd', scale='utc') Pos_HCRS = HCI2HCRS(Pos_HCI) # TODO. HARD: had to remove it #Vel_HCRS_rel = HCI2HCRS(Vel_HCI - EarthVelocity(t)) Pos_HCRS_SC = HCRS(x=Pos_HCRS[0]*u.m, y=Pos_HCRS[1]*u.m, z=Pos_HCRS[2]*u.m, representation_type='cartesian', obstime=T) Pos_ECI = np.vstack(Pos_HCRS_SC.transform_to(GCRS(obstime=T)).cartesian.xyz.value) return Pos_ECI
def _rotation_matrix_hme_to_hee(hmeframe): """ Return the rotation matrix from HME to HEE at the same observation time """ # Get the Sun-Earth vector sun_earth = HCRS(_sun_earth_icrf(hmeframe.obstime), obstime=hmeframe.obstime) sun_earth_hme = sun_earth.transform_to(hmeframe).cartesian # Rotate the Sun-Earth vector about the Z axis so that it lies in the XZ plane rot_matrix = _rotation_matrix_reprs_to_xz_about_z(sun_earth_hme) # Tilt the rotated Sun-Earth vector so that it is aligned with the X axis tilt_matrix = _rotation_matrix_reprs_to_reprs(sun_earth_hme.transform(rot_matrix), CartesianRepresentation(1, 0, 0)) return matrix_product(tilt_matrix, rot_matrix)
def hgs_to_hgs(from_coo, to_frame): """ Convert between two Heliographic Stonyhurst frames. """ if np.all(from_coo.obstime == to_frame.obstime): return to_frame.realize_frame(from_coo.data) else: return from_coo.transform_to(HCRS(obstime=from_coo.obstime)).transform_to(to_frame)
def gei_to_gei(from_coo, to_frame): """ Convert between two Geocentric Earth Equatorial frames. """ if _times_are_equal(from_coo.equinox, to_frame.equinox) and \ _times_are_equal(from_coo.obstime, to_frame.obstime): return to_frame.realize_frame(from_coo.data) else: return from_coo.transform_to(HCRS(obstime=from_coo.obstime)).transform_to(to_frame)
def hee_to_hee(from_coo, to_frame): """ Convert between two Heliocentric Earth Ecliptic frames. """ if _times_are_equal(from_coo.obstime, to_frame.obstime): return to_frame.realize_frame(from_coo.data) elif to_frame.obstime is None: return from_coo else: return from_coo.transform_to(HCRS(obstime=from_coo.obstime)).transform_to(to_frame)
def hee_to_gse(heecoord, gseframe): """ Convert from Heliocentric Earth Ecliptic to Geocentric Solar Ecliptic """ # Use an intermediate frame of HEE at the GSE observation time int_frame = HeliocentricEarthEcliptic(obstime=gseframe.obstime) int_coord = heecoord.transform_to(int_frame) # Get the Sun-Earth vector in the intermediate frame sun_earth = HCRS(_sun_earth_icrf(int_frame.obstime), obstime=int_frame.obstime) sun_earth_int = sun_earth.transform_to(int_frame).cartesian # Find the Earth-object vector in the intermediate frame earth_object_int = int_coord.cartesian - sun_earth_int # Flip the vector in X and Y, but leave Z untouched # (The additional transpose operations are to handle both scalar and array inputs) newrepr = CartesianRepresentation((earth_object_int.xyz.T * [-1, -1, 1]).T) return gseframe.realize_frame(newrepr)
def hgs_to_hgs(from_coo, to_frame): """ Convert between two Heliographic Stonyhurst frames. """ if to_frame.obstime is None: return from_coo.replicate() elif _times_are_equal(from_coo.obstime, to_frame.obstime): return to_frame.realize_frame(from_coo.data) else: return from_coo.transform_to( HCRS(obstime=from_coo.obstime)).transform_to(to_frame)
def hgs_to_hgs(from_coo, to_frame): """ Convert between two Heliographic Stonyhurst frames. """ if to_frame.obstime is None: return from_coo.replicate() elif _times_are_equal(from_coo.obstime, to_frame.obstime): return to_frame.realize_frame(from_coo.data) else: if _autoapply_diffrot: from_coo = from_coo._apply_diffrot((to_frame.obstime - from_coo.obstime).to('day'), _autoapply_diffrot) return from_coo.transform_to(HCRS(obstime=to_frame.obstime)).transform_to(to_frame)
def ECI2HCI_pos(Pos_ECI, t): # Position & velocity relative to the sun T = Time(t, format='jd', scale='utc') dist_vect = norm(Pos_ECI, axis=0) ra_vect = np.arctan2(Pos_ECI[1], Pos_ECI[0]) dec_vect = np.arcsin(Pos_ECI[2] / dist_vect) Pos_ECI_SC = GCRS(ra=ra_vect * u.rad, dec=dec_vect * u.rad, distance=dist_vect * u.m, obstime=T) Pos_HCRS = np.vstack(Pos_ECI_SC.transform_to(HCRS(obstime=T)).cartesian.xyz.value) Pos_HCI = HCRS2HCI(Pos_HCRS) return Pos_HCI
def hee_to_hme(heecoord, hmeframe): """ Convert from Heliocentric Earth Ecliptic to Heliocentric Mean Ecliptic """ if heecoord.obstime is None: raise ConvertError("To perform this transformation, the coordinate" " frame needs a specified `obstime`.") int_frame = HeliocentricMeanEcliptic(obstime=heecoord.obstime, equinox=heecoord.obstime) # Rotate the HEE coord to the intermediate frame total_matrix = matrix_transpose(_rotation_matrix_hme_to_hee(int_frame)) int_repr = heecoord.cartesian.transform(total_matrix) int_coord = int_frame.realize_frame(int_repr) # Convert to the HME frame through HCRS return int_coord.transform_to(HCRS(obstime=int_coord.obstime)).transform_to(hmeframe)
def hme_to_hee(hmecoord, heeframe): """ Convert from Heliocentric Mean Ecliptic to Heliocentric Earth Ecliptic """ if heeframe.obstime is None: raise ConvertError("To perform this transformation, the coordinate" " frame needs a specified `obstime`.") # Convert to the HME frame with mean equinox of date at the HEE obstime, through HCRS int_frame = HeliocentricMeanEcliptic(obstime=heeframe.obstime, equinox=heeframe.obstime) int_coord = hmecoord.transform_to(HCRS(obstime=hmecoord.obstime)).transform_to(int_frame) # Rotate the intermediate coord to the HEE frame total_matrix = _rotation_matrix_hme_to_hee(int_frame) newrepr = int_coord.cartesian.transform(total_matrix) return heeframe.realize_frame(newrepr)
def test_ephemerides(): """ We test that using different ephemerides gives very similar results for transformations """ t = Time("2014-12-25T07:00") moon = SkyCoord( GCRS(318.10579159 * u.deg, -11.65281165 * u.deg, 365042.64880308 * u.km, obstime=t)) icrs_frame = ICRS() hcrs_frame = HCRS(obstime=t) ecl_frame = HeliocentricMeanEcliptic(equinox=t) cirs_frame = CIRS(obstime=t) moon_icrs_builtin = moon.transform_to(icrs_frame) moon_hcrs_builtin = moon.transform_to(hcrs_frame) moon_helioecl_builtin = moon.transform_to(ecl_frame) moon_cirs_builtin = moon.transform_to(cirs_frame) with solar_system_ephemeris.set('jpl'): moon_icrs_jpl = moon.transform_to(icrs_frame) moon_hcrs_jpl = moon.transform_to(hcrs_frame) moon_helioecl_jpl = moon.transform_to(ecl_frame) moon_cirs_jpl = moon.transform_to(cirs_frame) # most transformations should differ by an amount which is # non-zero but of order milliarcsecs sep_icrs = moon_icrs_builtin.separation(moon_icrs_jpl) sep_hcrs = moon_hcrs_builtin.separation(moon_hcrs_jpl) sep_helioecl = moon_helioecl_builtin.separation(moon_helioecl_jpl) sep_cirs = moon_cirs_builtin.separation(moon_cirs_jpl) assert_allclose([sep_icrs, sep_hcrs, sep_helioecl], 0.0 * u.deg, atol=10 * u.mas) assert all(sep > 10 * u.microarcsecond for sep in (sep_icrs, sep_hcrs, sep_helioecl)) # CIRS should be the same assert_allclose(sep_cirs, 0.0 * u.deg, atol=1 * u.microarcsecond)
def EarthPosition(t, ephem='builtin'): ''' The position of Earth at time, t, w.r.t. the Sun using astropy.coordinates.solar_system_ephemeris. ''' # logger = logging.getLogger() # logger.critical('As of 1.3, astropy has changed the behavior of some functions, giving diverging answers from previous versions') T = Time(t, format='jd', scale='utc') # pos_bary, vel_bary = get_body_barycentric_posvel('earth', time=T) with solar_system_ephemeris.set(ephem): pos_bary = get_body_barycentric('earth', time=T) pos_ICRS = ICRS(pos_bary) hcrs_frame = HCRS(obstime=T) Pos_HCRS = np.vstack((SkyCoord(pos_ICRS).transform_to(hcrs_frame). cartesian.xyz.to(u.meter).value)) Pos_HCI = HCRS2HCI(Pos_HCRS) return Pos_HCI
def __init__(self, orbit_type, a, e, i, omega, Omega, theta, ra_corr=np.nan * u.rad, dec_corr=np.nan * u.rad, v_g=np.nan * u.m / u.second): self.semi_major_axis = a.to(u.au) self.eccentricity = e self.inclination = i.to(u.deg) self.argument_periapsis = omega.to(u.deg) self.longitude_ascending_node = Omega.to(u.deg) self.longitude_perihelion = (self.longitude_ascending_node + self.argument_periapsis) % (360 * u.deg) self.true_anomaly = theta.to(u.deg) self.orbit_type = orbit_type self.perihelion = (1 - self.eccentricity) * self.semi_major_axis self.aphelion = (1 + self.eccentricity) * self.semi_major_axis self.corr_radiant_ra = (ra_corr.to(u.deg)) % (360 * u.deg) self.corr_radiant_dec = dec_corr.to(u.deg) radiant = HCRS(ra=self.corr_radiant_ra, dec=self.corr_radiant_dec, distance=1.0 * u.au) ecpliptic_radiant = HCRS2HCI(np.vstack(radiant.cartesian.xyz.value)) self.ecliptic_latitude = np.rad2deg( np.arcsin(ecpliptic_radiant[2] / norm(ecpliptic_radiant))) * u.deg self.velocity_g = v_g.to(u.m / u.second) self.T_j = self.tisserand_criterion_wrt_jupiter()
def SunDynamics(y, t, Perturbations, record=False): ''' The state rate dynamics are used in Runge-Kutta integration method to calculate the next set of equinoctial element values. ''' ''' State Rates ''' # Equinoctial element vector decomposed [p, f, g, h, k, L] = y.flatten()[:6] # Short-hand elements w = 1 + f * np.cos(L) + g * np.sin(L) s2 = 1 + h**2 + k**2 alpha2 = h**2 - k**2 pm = np.sqrt(p / mu_s) / w hk = h * np.sin(L) - k * np.cos(L) # State rate constant b = np.vstack((0, 0, 0, 0, 0, np.sqrt(mu_s * p) * (w / p)**2)) Backward = True if Perturbations >= 10: Backward = False Perturbations = Perturbations - 10 if Backward: # State rate matrix A = np.array([ [0, 2 * p * pm, 0], [pm * w * np.sin(L), pm * ((w + 1) * np.cos(L) + f), -pm * g * hk], [-pm * w * np.cos(L), pm * ((w + 1) * np.sin(L) + g), pm * f * hk], [0, 0, pm * s2 * np.cos(L) / 2], [0, 0, pm * s2 * np.sin(L) / 2], [0, 0, pm * hk] ]) # Calculate the current position of meteoroid (m) r = p / w Pos_HCI = r / s2 * np.vstack( (np.cos(L) + alpha2 * np.cos(L) + 2 * h * k * np.sin(L), np.sin(L) - alpha2 * np.sin(L) + 2 * h * k * np.cos(L), 2 * hk)) Vel_HCI = -1 / (s2 * pm * w) * np.vstack( (np.sin(L) + alpha2 * np.sin(L) - 2 * h * k * np.cos(L) + g - 2 * f * h * k + alpha2 * g, -np.cos(L) + alpha2 * np.cos(L) + 2 * h * k * np.sin(L) - f + 2 * g * h * k + alpha2 * f, -2 * (h * np.cos(L) + k * np.sin(L) + f * h + g * k))) # Body frame unit vectors X_body = Pos_HCI / r Z_body = np.cross(Pos_HCI, Vel_HCI, axis=0) / norm( np.cross(Pos_HCI, Vel_HCI, axis=0), axis=0) Y_body = np.cross(Z_body, X_body, axis=0) / norm( np.cross(Z_body, X_body, axis=0), axis=0) # Rotation matrix HCI2Body = np.vstack((X_body.T, Y_body.T, Z_body.T)) ''' Secondary Body Perturbations: Earth ''' # Position vector from Sun to Earth (m) rho_e = EarthPosition(t) # Third body perturbation acceleration (Earth) -HCI frame u_earth = ThirdBodyPerturbation(Pos_HCI, rho_e, mu_e) if Perturbations: ''' Secondary Body Perturbations: Moon ''' # Position vector from Earth to Moon (m) T = Time(t, format='jd', scale='utc') Moon_GCRS_SC = get_body('moon', T) rho_m = np.vstack( Moon_GCRS_SC.transform_to(HCRS(obstime=T)).cartesian.xyz.to( u.meter).value) rho_m = HCRS2HCI(rho_m) # Third body perturbation acceleration (Moon) -HCI frame u_moon = ThirdBodyPerturbation(Pos_HCI, rho_m, mu_m) ''' Total Perturbing Acceleration (in the body frame) ''' u_tot = np.dot(HCI2Body, u_earth + u_moon) else: ''' Total Perturbing Acceleration (in the body frame) ''' u_tot = np.dot(HCI2Body, u_earth) rho_m = np.nan if record: EARTH = mu_e / (norm(Pos_HCI - rho_e))**2 MOON = mu_m / (norm(Pos_HCI - rho_m))**2 SUN = mu_s / r**2 global Pert Pert.append([t, EARTH, MOON, SUN, np.nan, np.nan]) ''' State Rate Equation ''' y_dot = np.vstack((np.dot(A, u_tot) + b, 0, 0)) else: ''' State Rate Equation ''' y_dot = np.vstack((b, 0, 0)) return y_dot