''' Calculate the CENA FoV cross-section on the Moon's map
'''
import datetime
import logging
import numpy as np
from irfpy.util.intersection import los_sphere
from irfpy.util import intersection as _intersection
from irfpy.cy1orb import lseme
import irfpy.cy1orb.pvat2 as pvat
from irfpy.cena import frame
from irfpy.cena import fov
_logger = logging.getLogger(__name__)
[docs]def get_center_me(t, dir, as_vector=False):
''' Get the intersection between the given pixel and the surface.
Returns the intersection between the given pixel ``dir``
and the lunar surface. ME frame is used.
:param t: Time in ``datetime.datetime`` instance.
:type t: ``datetime.datetime``
:param dir: Direction number. 0 to 6.
:type dir: ``int``
:keyword as_vector: If ``True``, return as a vector in ME frame.
:type as_vector: ``boolean``
:returns: If ``as_vector`` is ``True``, the ``numpy.array`` instance
with (``x``, ``y``, ``z``) is returned. Otherwise (default),
A list of [``longitude (deg)``, ``latitude (deg)``] will be returned.
Note that the Moon is assumed to be a sphere with 1738 km radius here.
This is just a geometric vector calculation, and no SPICE is used.
>>> t = datetime.datetime(2009, 1, 31, 3, 25, 17)
>>> lon, lat = get_center_me(t, 4)
>>> print('%.1f' % lon)
69.9
>>> print('%.1f' % lat)
62.5
>>> lon, lat = get_center_me(t, 0)
>>> print('%.1f' % lon)
85.1
>>> print('%.1f' % lat)
62.3
>>> lon, lat = get_center_me(t, 6)
>>> print('%.1f' % lon)
59.8
>>> print('%.1f' % lat)
62.2
'''
scpos_me = pvat.getmepos(t, as_vector=True)
_logger.debug('sc = %s' % str(scpos_me))
_logger.debug('ELEV = %f, AZIM = %f' % (fov.elev_pix_center(dir), fov.azim_pix_center(dir)))
cenaarms = frame.angles2cena(fov.elev_pix_center(dir), fov.azim_pix_center(dir), degrees=True)
_logger.debug('Arm = %s' % str(cenaarms))
arms_sc = frame.cena2sc(cenaarms)
arms_lse = pvat.getlsevec(t, arms_sc)
arms_me = lseme.lse2me(t, arms_lse)
arms_me = np.array(arms_me)
_logger.debug('Arm [ME] = %s' % str(arms_me))
los = los_sphere(scpos_me, arms_me, np.array([0, 0, 0]), 1738.)
if los is None:
if as_vector:
return np.array([3]) + np.nan
else:
return [np.nan, np.nan]
los = np.array([los[0], los[1], los[2]])
if as_vector:
return los
len = np.sqrt((los ** 2).sum())
los = los / len
lat = np.arcsin(los[2]) * 180. / np.pi
lon = np.arctan2(los[1], los[0]) * 180. / np.pi
return [lon, lat]
[docs]def in_cena_fov(t, me_lon, me_lat):
""" Return if the given position is in CENA's FOV or not
:param t: Time
:param me_lon: Longitude of surface position, deg
:param me_lat: Latitude of surface position, deg
:returns: *True* if (me_lon, me_lat) is in CENA'f FOV
>>> print(in_cena_fov(datetime.datetime(2009, 4, 15, 2, 22, 59), 177.5, -45.5)) # False
False
>>> print(in_cena_fov(datetime.datetime(2009, 4, 15, 2, 26, 19), 177.5, -45.5)) # True
True
"""
t2 = t # Alias
lon0 = np.deg2rad(me_lon)
lat0 = np.deg2rad(me_lat)
pos_surf_me = np.array([np.cos(lon0) * np.cos(lat0),
np.sin(lon0) * np.cos(lat0),
np.sin(lat0)]) * 1738
pos_surf_lse2 = lseme.me2lse(t2, pos_surf_me)
pos_sc_lse2 = pvat.getlsepos(t2, asarray=True)
if not _intersection.isvisible(pos_sc_lse2, pos_surf_lse2, [0, 0, 0], 1738):
_logger.debug('Backside of Moon')
return False
dir_sc2surf_lse2 = pos_surf_lse2 - pos_sc_lse2
dir_sc2surf_sc2 = pvat.lse2sc(t2, dir_sc2surf_lse2)
dir_sc2surf_cena2 = frame.sc2cena(dir_sc2surf_sc2)
cena_theta2, cena_phi2 = frame.cena2angles(dir_sc2surf_cena2, degrees=True)
_logger.debug('Theta_CENA={}'.format(cena_theta2))
_logger.debug('Phi_CENA={}'.format(cena_phi2))
return fov.infov(cena_theta2, cena_phi2)