def get_planet_angular_sep(body: str, ra: float, dec: float, time=None, observer_position: str = 'earth') -> float: """Get angular separation between planet ``body`` and target ``ra``, ``dec``. Valid values for the ``observer_position`` argument are: - 'earth' (default, approximate, fastest) - 'chandra' (reasonably accurate fast, requires fetching ephemeris) - 'chandra-horizons' (most accurate, slow, requires internet access) :param body: str Body name (lower case planet name) :param ra: float RA in degrees :param dec: float Dec in degrees :param time: CxoTime-compatible object Time or times of observation :param observer_position: str Observer position ('earth', 'chandra', or 'chandra-horizons') :returns: angular separation (deg) """ from agasc import sphere_dist if not isinstance(time, CxoTime): time = CxoTime(time) if observer_position == 'earth': eci = get_planet_eci(body, time) body_ra, body_dec = eci_to_radec(eci) elif observer_position == 'chandra': eci = get_planet_chandra(body, time) body_ra, body_dec = eci_to_radec(eci) elif observer_position == 'chandra-horizons': if time.shape == (): time = CxoTime([time, time + 1000 * u.s]) is_scalar = True else: is_scalar = False pos = get_planet_chandra_horizons(body, time[0], time[1], n_times=len(time)) body_ra = pos['ra'] body_dec = pos['dec'] if is_scalar: body_ra = body_ra[0] body_dec = body_dec[0] else: raise ValueError(f'{observer_position} is not an allowed value: ' f'("earth", "chandra", or "chandra-horizons")') sep = sphere_dist(ra, dec, body_ra, body_dec) return sep
def test_eci_to_radec(): eci = np.array([0.92541658, 0.16317591, 0.34202014]) ra, dec = eci_to_radec(eci) assert np.allclose(ra, 9.9999999129952908) assert np.allclose(dec, 19.999999794004037) assert isinstance(ra, np.float64) assert isinstance(dec, np.float64)
def test_venus_position2(): # ******************************************************************************* # Target body name: Venus (299) {source: CHANDRA_MERGED} # Center body name: Chandra Observatory (spacecraft) (-151) {source: CHANDRA_MERGED} # Center-site name: BODYCENTRIC # ******************************************************************************* # Start time : A.D. 2020-Jan-01 00:00:00.0000 UT # Stop time : A.D. 2020-Jun-01 00:00:00.0000 UT # Step-size : 21600 minutes # ******************************************************************************* txt = """ date ra dec 2020-01-01T00:00 21:08:43.02 -18:22:41.8 2020-01-16T00:00 22:19:56.31 -12:03:15.4 2020-01-31T00:00 23:26:25.34 -04:40:18.3 2020-02-15T00:00 00:29:55.07 +03:09:41.1 2020-03-01T00:00 01:31:42.96 +10:46:02.6 2020-03-16T00:00 02:32:52.02 +17:25:28.9 2020-03-31T00:00 03:32:39.01 +22:40:58.7 2020-04-15T00:00 04:26:52.03 +26:10:57.3 2020-04-30T00:00 05:07:55.28 +27:38:30.8 2020-05-15T00:00 05:22:08.73 +27:05:38.1 2020-05-30T00:00 04:59:36.37 +24:14:26.9 """ dat = ascii.read(txt) date = CxoTime(dat['date']) sc = SkyCoord(dat['ra'], dat['dec'], unit=(u.hr, u.deg)) eci = get_planet_chandra('venus', date) ra, dec = eci_to_radec(eci) dist = sphere_dist(ra, dec, sc.ra.to_value(u.deg), sc.dec.to_value(u.deg)) * 3600 assert np.all(dist < 4.0)
def test_vectorized_eci_to_radec(): eci = np.array([[0.92541658, 0.16317591, 0.34202014], [0.9248273, -0.16307201, 0.34365969]]) ra, dec = eci_to_radec(eci) assert np.allclose(ra[0], 9.9999999129952908) assert np.allclose(ra[1], 349.9999997287627) assert np.allclose(dec[0], 19.999999794004037) assert np.allclose(dec[1], 20.099999743270516) assert isinstance(ra, np.ndarray) assert isinstance(dec, np.ndarray)
def test_planet_positions_array(): bary = get_planet_barycentric('saturn', ['2020:324:11:44:00', '2020:324:11:44:01']) assert bary.shape == (2, 3) eci = get_planet_eci('saturn', ['2020:324:11:44:00', '2020:324:11:44:01']) assert eci.shape == (2, 3) eci = get_planet_chandra('saturn', ['2020:324:11:44:00', '2020:324:11:44:01']) assert eci.shape == (2, 3) ra, dec = eci_to_radec(eci) # Value from JPL Horizons (Saturn from Chandra Observatory -151) ra2, dec2 = 299.27358333, -21.07644444 assert np.all(sphere_dist(ra, dec, ra2, dec2) * 3600 < 1.0)
def test_venus_position1(): """Obsid 18695 starcat at 2017:010:05:07:20.875, approx obs star 0510z""" # Output from JPL Horizons for Venus from Chandra date = CxoTime('2017-01-10T05:10') sc = SkyCoord('22:36:02.59', '-09:39:07.2', unit=(u.hr, u.deg)) q_att = [-0.54137601, 0.17071483, -0.10344611, 0.81674192] eci = get_planet_chandra('venus', date) ra, dec = eci_to_radec(eci) yag, zag = radec_to_yagzag(ra, dec, q_att) # Confirm yag value is on "left side" of CCD, opposite all stars in 18695 assert np.isclose(yag, 210.20, rtol=0, atol=0.01) assert np.isclose(zag, 69.45, rtol=0, atol=0.01) dist = sphere_dist(ra, dec, sc.ra.to_value(u.deg), sc.dec.to_value(u.deg)) * 3600 assert np.all(dist < 4.0)
def test_planet_positions(): # Test basic functionality and include regression values (not an independent # functional test) bary = get_planet_barycentric('saturn', '2020:324:11:44:00') assert np.allclose(bary, [7.92469846e+08, -1.15786689e+09, -5.12388561e+08]) eci = get_planet_eci('saturn', '2020:324:11:44:00') assert np.allclose(eci, [7.13565053e+08, -1.27291136e+09, -5.62273593e+08]) eci = get_planet_chandra('saturn', '2020:324:11:44') assert np.allclose(eci, [7.13516810e+08, -1.27285190e+09, -5.62368753e+08]) # Independent functional test to compare with JPL Horizons (Saturn from # Chandra Observatory -151) ra, dec = eci_to_radec(eci) ra2, dec2 = 299.27358333, -21.07644444 assert sphere_dist(ra, dec, ra2, dec2) * 3600 < 1.0
def test_radec_eci_multidim(shape): """Test radec_to_eci and eci_to_radec for multidimensional inputs""" ras = np.linspace(0., 359., 24) decs = np.linspace(-90., 90., 24) ras_nd = ras.reshape(shape) decs_nd = decs.reshape(shape) # First do everything as scalars ecis_list = [ radec_to_eci(ra, dec) for ra, dec in zip(ras.tolist(), decs.tolist()) ] ecis_nd_from_list = np.array(ecis_list).reshape(shape + (3, )) ecis = radec_to_eci(ras_nd, decs_nd) assert ecis.shape == shape + (3, ) assert np.allclose(ecis, ecis_nd_from_list) ras_rt, decs_rt = eci_to_radec(ecis) assert ras_rt.shape == shape assert decs_rt.shape == shape assert np.allclose(ras_rt, ras_nd) assert np.allclose(decs_rt, decs_nd)