Source code for lumos.geometry

"""
Geometry objects which are used throughout Lumos
"""

import numpy as np
import lumos.constants
import lumos.calculator
[docs]class Surface: """ Container to hold area, normal vector, and BRDF of a surface :param area: Area of surface :math:`m^2` :type area: float :param normal: Normal vector of surface. Measured in brightness frame. A function of the angle past terminator may be passed, which must return the surface normal as a :class:`np.ndarray` for given angles past the terminator. :type normal: :class:`np.ndarray` or function :param brdf: Bidirectional Reflectance Distribution Function (BRDF) of surface. :type brdf: function """ def __init__(self, area, normal, brdf): """ Constructor Method """ self.area = area self.normal = normal self.brdf = brdf def __str__(self): """ Printing Method """ return f'| Surface \n' \ f'|-- Area: {self.area:.2f} m^2 \n' \ f'|-- Normal Vector: ' \ f'<{self.normal[0]:.2f}, {self.normal[1]:.2f}, {self.normal[2]:.2f}> \n'
[docs]class EarthMesh: """ A mesh of points on Earth's surface :param angles_off_plane: 1D array of the angles-off-plane of the mesh. :type angles_off_plane: :class:`np.ndarray` :param angles_on_plane: 1D array of the angles-on-plane of the mesh. :type angles_on_plane: :class:`np.ndarray` """ def __init__(self, angles_off_plane, angles_on_plane): """ Constructor method """ self.d_phi = np.abs(angles_off_plane[1] - angles_off_plane[0]) self.d_theta = np.abs(angles_on_plane[1] - angles_on_plane[0]) self.angles_off_plane, self.angles_on_plane = np.meshgrid(angles_off_plane, angles_on_plane) self.dists_off_plane = lumos.constants.EARTH_RADIUS * self.angles_off_plane self.dists_on_plane = lumos.constants.EARTH_RADIUS * self.angles_on_plane # Set up panel positions self.z = ( lumos.constants.EARTH_RADIUS / np.sqrt(1 + np.tan(self.angles_on_plane)**2 + np.tan(self.angles_off_plane)**2 ) ) self.x = np.tan(self.angles_off_plane) * self.z self.y = np.tan(self.angles_on_plane) * self.z # Get normal vectors of panels self.nx = self.x / lumos.constants.EARTH_RADIUS self.ny = self.y / lumos.constants.EARTH_RADIUS self.nz = self.z / lumos.constants.EARTH_RADIUS self.shape = self.z.shape
[docs]class GroundObservers(EarthMesh): """ A mesh of observers visible to the satellite and on the night side of earth :param sat_height: Geodetic height of satellite (meters) :type sat_height: float :param angle_past_terminator: Angle of satellite past the terminator (radians) :type angle_past_terminator: float :param density: Mesh will have size density x density :type density: int """ def __init__(self, sat_height, angle_past_terminator, density): """ Constructor Method """ self.max_angle = np.arccos(lumos.constants.EARTH_RADIUS / (lumos.constants.EARTH_RADIUS + sat_height)) self.min_angle = angle_past_terminator angles_off_plane = np.linspace(-self.max_angle, self.max_angle, density) angles_on_plane = np.linspace(-self.max_angle, self.min_angle, density) super().__init__(angles_off_plane, angles_on_plane) self.sat_height = sat_height self.angle_past_terminator = angle_past_terminator
[docs] def calculate_intensity(self, surfaces, include_sun = True, include_earthshine = False, earth_panel_density = 151, earth_brdf = None): """ Calculates intensity for observers on ground :param surfaces: List of satellite surfaces :type surfaces: List[:py:func:`lumos.geometry.Surface`] :param include_sun: Whether to include contribution of brightness due to direct sunlight :type include_sun: bool, optional :param include_earthshine: Whether to include contribution of brightness due to earthshine :type include_earthshine: bool, optional :param earth_panel_density: Earthshine discretization has earth_panel_density squared pixels :type earth_panel_density: int, optional :param earth_brdf: The BRDF of Earth's surface :type earth_brdf: callable """ # Sets up an array to hold the intensity seen by each ground observer self.intensities = np.zeros(self.shape) for i in range(self.shape[0]): for j in range(self.shape[1]): self.intensities[i, j] = \ lumos.calculator.get_intensity_satellite_frame( surfaces, self.sat_height, self.angle_past_terminator, (self.x[i, j], self.y[i, j], self.z[i, j]), include_sun, include_earthshine, earth_panel_density, earth_brdf)