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 test_hme_hee_sunspice(): # Compare our HME->HEE transformation against SunSPICE # "HAE" is equivalent to Astropy's Heliocentric Mean Ecliptic, and defaults to J2000.0 # # IDL> coord = [1.d, 0.d, 10.d] # IDL> convert_sunspice_lonlat, '2019-06-01', coord, 'HAE', 'HEE', /au, /degrees # IDL> print, coord # 1.0000000 110.01610 10.000300 old = SkyCoord(0*u.deg, 10*u.deg, 1*u.AU, frame=HeliocentricMeanEcliptic(obstime='2019-06-01')) new = old.transform_to(HeliocentricEarthEcliptic) assert_quantity_allclose(new.lon, Longitude(110.01610*u.deg), atol=0.01*u.arcsec, rtol=0) assert_quantity_allclose(new.lat, 10.000300*u.deg, atol=0.01*u.arcsec, rtol=0) assert_quantity_allclose(new.distance, old.distance) # Transform from HAE precessed to the mean ecliptic of date instead of J2000.0 # IDL> coord = [1.d, 0.d, 10.d] # IDL> convert_sunspice_lonlat, '2019-06-01', coord, 'HAE', 'HEE', /au, /degrees, /precess # IDL> print, coord # 1.0000000 109.74535 10.000070 old = SkyCoord(0*u.deg, 10*u.deg, 1*u.AU, frame=HeliocentricMeanEcliptic(obstime='2019-06-01', equinox='2019-06-01')) new = old.transform_to(HeliocentricEarthEcliptic) assert_quantity_allclose(new.lon, Longitude(109.74535*u.deg), atol=0.05*u.arcsec, rtol=0) assert_quantity_allclose(new.lat, 10.000070*u.deg, atol=0.01*u.arcsec, rtol=0) assert_quantity_allclose(new.distance, old.distance)
def test_hme_gei_sunspice(): # Compare our HME->GEI transformation against SunSPICE # "HAE" is equivalent to Astropy's Heliocentric Mean Ecliptic, and defaults to J2000.0 # # IDL> coord = [1.d, 120.d, 10.d] # IDL> convert_sunspice_lonlat, '2019-06-01', coord, 'HAE', 'GEI', /au, /degrees # IDL> print, coord # 1.8197210 95.230617 28.830109 old = SkyCoord(120*u.deg, 10*u.deg, 1*u.AU, frame=HeliocentricMeanEcliptic(obstime='2019-06-01')) new = old.transform_to(GeocentricEarthEquatorial) assert_quantity_allclose(new.lon, Longitude(95.230617*u.deg), atol=0.01*u.arcsec, rtol=0) assert_quantity_allclose(new.lat, 28.830109*u.deg, atol=0.05*u.arcsec, rtol=0) assert_quantity_allclose(new.distance, 1.8197210*u.AU) # Transform from HAE precessed to the mean ecliptic of date instead of J2000.0 # IDL> coord = [1.d, 120.d, 10.d] # IDL> convert_sunspice_lonlat, '2019-06-01', coord, 'HAE', 'GEI', /au, /degrees, /precess # IDL> print, coord # 1.8217103 95.079030 28.827750 old = SkyCoord(120*u.deg, 10*u.deg, 1*u.AU, frame=HeliocentricMeanEcliptic(obstime='2019-06-01', equinox='2019-06-01')) new = old.transform_to(GeocentricEarthEquatorial(equinox=_J2000)) assert_quantity_allclose(new.lon, Longitude(95.079030*u.deg), atol=0.05*u.arcsec, rtol=0) assert_quantity_allclose(new.lat, 28.827750*u.deg, atol=0.05*u.arcsec, rtol=0) assert_quantity_allclose(new.distance, 1.8217103*u.AU)
def hee_to_hme(heecoord, hmeframe): """ Convert from Heliocentric Earth Ecliptic to Heliocentric Mean Ecliptic """ 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).transform_to(hmeframe)
def test_hgs_hcrs(): # This test checks the HGS->HCRS transformation by transforming from HGS to # HeliocentricMeanEcliptic (HME). It will fail if there are errors in Astropy's # HCRS->ICRS or ICRS->HME transformations. # Use published HGS coordinates in the Astronomical Almanac (2013), pages C6-C7 obstime = Time('2013-01-28') earth_hgs = SkyCoord(0 * u.deg, -5.73 * u.deg, 0.9848139 * u.AU, frame=HeliographicStonyhurst, obstime=obstime) # Transform to HME at observation-time equinox earth_hme = earth_hgs.transform_to( HeliocentricMeanEcliptic(equinox=obstime)) # Validate against published values from the Astronomical Almanac (2013), page C6 per page E2 # The dominant source of inaccuracy is the limited precision of the published B0 used above assert quantity_allclose(earth_hme.lon, Angle('308d13m30.51s') - 180 * u.deg, atol=5 * u.arcsec) assert quantity_allclose(earth_hme.lat, -Angle('-0.27s'), atol=10 * u.arcsec) assert quantity_allclose(earth_hme.distance, 0.9848139 * u.AU, atol=5e-7 * u.AU)
def test_hgs_hcrs_sunspice(): # Compare our HGS->HCRS transformation against SunSPICE by transforming beyond it # "HEQ" is another name for HEEQ, which is equivalent to Heliographic Stonyhurst # "HAE" is equivalent to Astropy's Heliocentric Mean Ecliptic, and defaults to J2000.0 # # IDL> coord = [1.d, 0.d, 10.d] # IDL> convert_sunspice_lonlat, '2019-06-01', coord, 'HEQ', 'HAE', /au, /degrees # IDL> print, coord # 1.0000000 -108.65371 10.642778 old = SkyCoord(0*u.deg, 10*u.deg, 1*u.AU, frame=HeliographicStonyhurst(obstime='2019-06-01')) new = old.transform_to(HeliocentricMeanEcliptic) assert_quantity_allclose(new.lon, Longitude(-108.65371*u.deg), atol=0.1*u.arcsec, rtol=0) assert_quantity_allclose(new.lat, 10.642778*u.deg, atol=0.1*u.arcsec, rtol=0) assert_quantity_allclose(new.distance, old.radius) # Transform to HAE precessed to the mean ecliptic of date instead of J2000.0 # IDL> coord = [1.d, 0.d, 10.d] # IDL> convert_sunspice_lonlat, '2019-06-01', coord, 'HEQ', 'HAE', /precess, /au, /degrees # IDL> print, coord # 1.0000000 -108.38240 10.640314 new = old.transform_to(HeliocentricMeanEcliptic(equinox='2019-06-01')) assert_quantity_allclose(new.lon, Longitude(-108.38240*u.deg), atol=0.1*u.arcsec, rtol=0) assert_quantity_allclose(new.lat, 10.640314*u.deg, atol=0.1*u.arcsec, rtol=0) assert_quantity_allclose(new.distance, old.radius)
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_observer_not_hgs_astropy(oca): observer = HeliocentricMeanEcliptic(0*u.deg, 0*u.deg, 1*u.AU, obstime='2001-01-01') result, converted = oca.convert_input(observer) assert isinstance(result, HeliographicStonyhurst) assert result.obstime == observer.obstime assert converted
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 rot_hme(): return (HeliocentricMeanEcliptic, RotatedSunFrame(lon=1 * u.deg, lat=2 * u.deg, distance=3 * u.AU, base=HeliocentricMeanEcliptic( obstime='2001-01-01', equinox='2001-01-01'), duration=4 * u.day))
def _rotation_matrix_hgs_to_hci(obstime): """ Return the rotation matrix from HGS to HCI at the same observation time """ z_axis = CartesianRepresentation(0, 0, 1)*u.m if not obstime.isscalar: z_axis = z_axis._apply('repeat', obstime.size) # Get the ecliptic pole in HGS ecliptic_pole = HeliocentricMeanEcliptic(z_axis, obstime=obstime, equinox=_J2000) ecliptic_pole_hgs = ecliptic_pole.transform_to(HeliographicStonyhurst(obstime=obstime)) # Rotate the ecliptic pole to the -YZ plane, which aligns the solar ascending node with the X # axis rot_matrix = _rotation_matrix_reprs_to_xz_about_z(ecliptic_pole_hgs.cartesian) xz_to_yz_matrix = rotation_matrix(-90*u.deg, 'z') return xz_to_yz_matrix @ rot_matrix
def hme_to_hee(hmecoord, heeframe): """ Convert from Heliocentric Mean Ecliptic to Heliocentric Earth Ecliptic """ # 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).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 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 true_longitude(t='now'): """ Returns the Sun's true geometric longitude, referred to the mean equinox of date. No corrections for nutation or aberration are included. Parameters ---------- t : {parse_time_types} Time to use in a parse-time-compatible format """ time = parse_time(t) # Calculate Earth's true geometric longitude and add 180 degrees for the Sun's longitude. # This approach is used because Astropy's GeocentricMeanEcliptic includes aberration. earth = SkyCoord(0*u.deg, 0*u.deg, 0*u.AU, frame='gcrs', obstime=time) coord = earth.transform_to(HeliocentricMeanEcliptic(equinox=time)) lon = coord.lon + 180*u.deg return Longitude(lon)