Coverage Analysis

Coverage class

class missiontools.Coverage(aoi, sensors, *, el_min_deg=0.0, sza_max_deg=None, sza_min_deg=None)[source]

Bases: object

Coverage analysis for an area of interest observed by one or more sensors.

Each sensor must be attached to a Spacecraft via add_sensor() before constructing a Coverage object. The spacecraft orbit and propagator are derived automatically from each sensor’s back-reference.

Combined visibility at each timestep is the union of all sensor FOVs. The SZA constraint (if any) is applied globally after the union — it represents an illumination or link condition on the ground, not on any individual sensor.

Parameters:
  • aoi (AoI) – Area of interest containing ground sample points.

  • sensors (sequence of Sensor) – One or more Sensor instances (list, tuple, or any iterable). All sensors must be attached to a spacecraft. Sensors may belong to the same spacecraft (multi-FOV) or to different spacecraft (constellation).

  • el_min_deg (float, optional) – Minimum ground elevation angle (degrees) for a ground point to be considered in view. Default 0 (horizon).

  • sza_max_deg (float | None, optional) – Maximum solar zenith angle (degrees) for access (daytime constraint). None disables the constraint.

  • sza_min_deg (float | None, optional) – Minimum solar zenith angle (degrees) for access (nighttime constraint). None disables the constraint.

Parameters:

Notes

All five coverage methods evaluate each sensor’s LVLH boresight at t_start and assume it is constant in the LVLH frame for the full analysis window. This is exact for sensors with fixed-LVLH pointing (nadir, fixed tilt, body-mounted on a nadir spacecraft) and an approximation for time-varying pointing modes.

Examples

Single sensor:

import numpy as np
from missiontools import Spacecraft, Sensor, AoI, Coverage

sc     = Spacecraft(a=6_771_000., e=0., i=np.radians(51.6),
                    raan=0., arg_p=0., ma=0.,
                    epoch=np.datetime64('2025-01-01', 'us'))
sensor = Sensor(30.0, body_vector=[0, 0, 1])
sc.add_sensor(sensor)

aoi = AoI.from_region(-60, 60, -180, 180)
cov = Coverage(aoi, [sensor], el_min_deg=5.0)

result = cov.coverage_fraction(
    np.datetime64('2025-01-01', 'us'),
    np.datetime64('2025-01-02', 'us'),
)
print(result['final_cumulative'])

Constellation (two spacecraft at different RAANs):

sc2    = Spacecraft(a=6_771_000., e=0., i=np.radians(51.6),
                    raan=np.radians(90.), arg_p=0., ma=0.,
                    epoch=np.datetime64('2025-01-01', 'us'))
s2     = Sensor(30.0, body_vector=[0, 0, 1])
sc2.add_sensor(s2)

cov2 = Coverage(aoi, [sensor, s2], el_min_deg=5.0)
result2 = cov2.coverage_fraction(
    np.datetime64('2025-01-01', 'us'),
    np.datetime64('2025-01-02', 'us'),
)
print(result2['final_cumulative'])   # ≥ single-satellite result
property aoi: AoI

Area of interest.

property sensors: list

Attached sensors (read-only copy).

coverage_fraction(t_start, t_end, *, alt=0.0, max_step=np.timedelta64(30, 's'), batch_size=1000)[source]

Instantaneous and cumulative coverage fraction over time.

Parameters:
  • t_start (np.datetime64) – Start of the analysis window.

  • t_end (np.datetime64) – End of the analysis window (inclusive).

  • alt (float, optional) – Altitude of ground targets above WGS84 (m). Default 0.

  • max_step (np.timedelta64, optional) – Maximum propagation step (default 30 s).

  • batch_size (int, optional) – Propagation batch size (default 1000).

Returns:

dict't', 'fraction', 'cumulative', 'mean_fraction', 'final_cumulative'. See coverage_fraction().

Parameters:
Return type:

dict

revisit_time(t_start, t_end, *, alt=0.0, max_step=np.timedelta64(30, 's'), batch_size=1000)[source]

Per-point revisit statistics.

Parameters:
  • t_start (np.datetime64) – Start of the analysis window.

  • t_end (np.datetime64) – End of the analysis window (inclusive).

  • alt (float, optional) – Altitude of ground targets above WGS84 (m). Default 0.

  • max_step (np.timedelta64, optional) – Maximum propagation step (default 30 s).

  • batch_size (int, optional) – Propagation batch size (default 1000).

Returns:

dict'max_revisit' : (M,) float — maximum gap between consecutive accesses for each ground point (s). nan for points with fewer than two accesses.

'mean_revisit' : (M,) float — mean gap (s). nan for points with fewer than two accesses.

'global_max' : float — maximum value across all points (s). nan if no point has two or more accesses.

'global_mean' : float — mean of per-point mean revisit times (s). nan if no point has two or more accesses.

Parameters:
Return type:

dict

pointwise_coverage(t_start, t_end, *, alt=0.0, max_step=np.timedelta64(30, 's'), batch_size=1000)[source]

Raw per-timestep visibility matrix.

Parameters:
  • t_start (np.datetime64) – Start of the analysis window.

  • t_end (np.datetime64) – End of the analysis window (inclusive).

  • alt (float, optional) – Altitude of ground targets above WGS84 (m). Default 0.

  • max_step (np.timedelta64, optional) – Maximum propagation step (default 30 s).

  • batch_size (int, optional) – Propagation batch size (default 1000).

Returns:

dict't', 'lat', 'lon', 'alt', 'visible'. See pointwise_coverage().

Parameters:
Return type:

dict

access_pointwise(t_start, t_end, *, alt=0.0, max_step=np.timedelta64(30, 's'), batch_size=1000)[source]

Per-point access intervals (AOS / LOS pairs).

Parameters:
  • t_start (np.datetime64) – Start of the analysis window.

  • t_end (np.datetime64) – End of the analysis window (inclusive).

  • alt (float, optional) – Altitude of ground targets above WGS84 (m). Default 0.

  • max_step (np.timedelta64, optional) – Maximum propagation step (default 30 s).

  • batch_size (int, optional) – Propagation batch size (default 1000).

Returns:

list[list[tuple[np.datetime64, np.datetime64]]]result[m] is a list of (AOS, LOS) pairs for ground point m. See access_pointwise().

Parameters:
Return type:

list

revisit_pointwise(t_start, t_end, *, alt=0.0, max_step=np.timedelta64(30, 's'), batch_size=1000)[source]

Per-point revisit gap arrays.

Parameters:
  • t_start (np.datetime64) – Start of the analysis window.

  • t_end (np.datetime64) – End of the analysis window (inclusive).

  • alt (float, optional) – Altitude of ground targets above WGS84 (m). Default 0.

  • max_step (np.timedelta64, optional) – Maximum propagation step (default 30 s).

  • batch_size (int, optional) – Propagation batch size (default 1000).

Returns:

list[np.ndarray of timedelta64]result[m] is an array of LOS-to-AOS gap durations for ground point m. See revisit_pointwise().

Parameters:
Return type:

list

Functional API

missiontools.coverage

Coverage and access analysis, and geographic area sampling.

Sampling

sample_aoi()

Sample points inside an arbitrary lat/lon polygon using the Fibonacci sphere lattice filtered by a point-in-polygon test.

sample_region()

Fibonacci-sphere sample points inside a rectangular lat/lon region. All parameters are optional; omitting both latitude bounds gives the full sphere.

sample_shapefile()

Fibonacci-sphere sample points inside an ESRI Shapefile polygon, including antimeridian-crossing geometries.

sample_geography()

Fibonacci-sphere sample points for a Natural Earth geography, resolved by country/subdivision name, ISO 3166 code, or 'Country/Region' slash pattern.

Coverage

coverage_fraction()

Fraction of the AoI visible at each timestep plus the cumulative (ever-seen) fraction over the analysis window.

revisit_time()

Per-point maximum and mean gap between consecutive accesses over the analysis window.

Pointwise access

pointwise_coverage()

Raw (T × M) boolean visibility matrix — which ground points are in view at each timestep.

access_pointwise()

AOS/LOS access intervals for every ground point.

revisit_pointwise()

LOS-to-AOS gap arrays for every ground point.

Notes

All sampling functions return latitudes and longitudes in radians. Coverage and access functions accept angles in radians and distances in metres, consistent with the package-wide SI convention.

missiontools.coverage.sample_aoi(polygon, n)[source]

Sample n approximately equal-area points inside an AoI polygon.

Uses a Fibonacci lattice to generate a near-uniform global distribution, then filters to the points inside the polygon. The returned count may differ slightly from n depending on AoI shape; use a larger n for denser or irregular regions.

Note

The polygon test is planar (lat/lon space in radians). Results are accurate for regions that do not span the anti-meridian or enclose a pole. Split such regions into separate polygons and combine samples.

Parameters:
  • polygon (npt.NDArray[np.floating]) – Polygon vertices, shape (V, 2), each row [lat, lon] in radians.

  • n (int) – Target number of sample points.

Returns:

  • lat (npt.NDArray[np.floating]) – Sample latitudes (rad), shape (M,).

  • lon (npt.NDArray[np.floating]) – Sample longitudes (rad), shape (M,).

Parameters:
Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

missiontools.coverage.sample_region(lat_min=None, lat_max=None, lon_min=None, lon_max=None, point_density=100000000000.0)[source]

Sample an approximately equal-area Fibonacci lattice over a lat/lon band.

A convenience wrapper around the Fibonacci lattice for rectangular regions. The number of points is derived from the spherical zone area and the requested point_density, so the grid automatically becomes denser for small regions and sparser for large ones.

Unlike sample_aoi(), this function filters the lattice directly by coordinate bounds, so it handles anti-meridian-crossing regions and global or banded coverage correctly.

Parameters:
  • lat_min (float | None, optional) – Southern boundary (rad). None extends to the South Pole (−π/2).

  • lat_max (float | None, optional) – Northern boundary (rad). None extends to the North Pole (+π/2).

  • lon_min (float | None, optional) – Western boundary (rad). Must be paired with lon_max; None (together with lon_max=None) includes all longitudes.

  • lon_max (float | None, optional) – Eastern boundary (rad). Must be paired with lon_min; None (together with lon_min=None) includes all longitudes. May be less than lon_min to indicate a region that crosses the anti-meridian (e.g. lon_min=np.radians(170), lon_max=np.radians(-170)).

  • point_density (float, optional) – Approximate area represented by each sample point (m²). Defaults to 1×10¹¹ m² (~100 000 km² per point, ~5 100 points globally).

Returns:

  • lat (npt.NDArray[np.floating]) – Sample latitudes (rad), shape (M,).

  • lon (npt.NDArray[np.floating]) – Sample longitudes (rad), shape (M,).

Raises:

ValueError – If exactly one of lon_min / lon_max is None, if lat_min >= lat_max, or if point_density is not positive.

Parameters:
Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

Examples

Global coverage at ~100 000 km²/point:

lat, lon = sample_region()

Europe (approximate):

lat, lon = sample_region(np.radians(35), np.radians(70),
                         np.radians(-10), np.radians(40),
                         point_density=1e9)

Pacific Ocean band crossing the anti-meridian:

lat, lon = sample_region(np.radians(-30), np.radians(30),
                         np.radians(150), np.radians(-120),
                         point_density=1e10)
missiontools.coverage.sample_shapefile(path, *, feature_index=None, point_density=100000000000.0)[source]

Sample approximately equal-area points from an ESRI Shapefile polygon.

Reads the polygon geometry from a .shp file and returns a Fibonacci lattice filtered to the interior, using the same density convention as sample_region(). Antimeridian-crossing polygons (e.g. Pacific island groups, Russia) are handled correctly via coordinate unwrapping and shifted-point PIP tests.

Parameters:
  • path (str) – Path to the .shp file.

  • feature_index (int or None, optional) – Index of the feature/shape to sample from. None (default) unions all features in the layer.

  • point_density (float, optional) – Approximate area represented by each sample point (m²). Defaults to 1×10¹¹ m² (~100 000 km² per point).

Returns:

  • lat (npt.NDArray[np.floating]) – Sample latitudes (rad), shape (M,).

  • lon (npt.NDArray[np.floating]) – Sample longitudes (rad), shape (M,).

Raises:

ValueError – If the file contains no polygon features, or if no lattice points land inside the geometry (degenerate or very small region).

Parameters:
  • path (str)

  • feature_index (int | None)

  • point_density (float)

Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

Notes

Requires pyshp and shapely (both declared as package dependencies).

missiontools.coverage.sample_geography(geography, *, point_density=100000000000.0)[source]

Sample approximately equal-area points from a Natural Earth geography.

Looks up the requested country or subdivision in the bundled Natural Earth 50 m dataset and returns a Fibonacci lattice filtered to its interior, using the same density convention as sample_region().

Parameters:
  • geography (str) – The geography to sample. Accepted formats (auto-detected):

    • Country name: 'Canada' (case-insensitive, matched against the admin-0 NAME field; falls back to admin-1 name if no match).

    • 'Country/Subdivision': 'Canada/Quebec', 'United States of America/Alaska'. Sub-national data is available only for Australia, Brazil, Canada, China, India, Indonesia, Russia, South Africa, and the United States of America.

    • ISO 3166-1 alpha-2: 'CA', 'US'

    • ISO 3166-1 alpha-3: 'CAN', 'USA'

    • ISO 3166-2: 'CA-QC', 'US-AK'

  • point_density (float, optional) – Approximate area represented by each sample point (m²). Defaults to 1×10¹¹ m² (~100 000 km² per point).

Returns:

  • lat ((M,) float64) – Sample latitudes (rad).

  • lon ((M,) float64) – Sample longitudes (rad).

  • geometry (shapely Polygon or MultiPolygon) – Shapely geometry of the matched feature(s).

Raises:

ValueError – If geography does not match any feature, point_density is non-positive, or no lattice points fall inside the geometry.

Parameters:
Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]], object]

Examples

lat, lon, geom = sample_geography('Canada')
lat, lon, geom = sample_geography('Canada/Quebec')
lat, lon, geom = sample_geography('CA-QC')
lat, lon, geom = sample_geography('CAN')
missiontools.coverage.coverage_fraction(lat, lon, keplerian_params, t_start, t_end, alt=0.0, el_min=0.0, propagator_type='twobody', max_step=np.timedelta64(30, 's'), batch_size=1000, fov_pointing_lvlh=None, fov_half_angle=None, sza_max=None, sza_min=None)[source]

Compute instantaneous and cumulative coverage fraction over a time window.

For each sample epoch, the instantaneous fraction is the proportion of ground points with the satellite above el_min. The cumulative fraction is the proportion of ground points seen at least once up to that epoch.

Parameters:
  • lat, lon (npt.NDArray[np.floating]) – Ground-point latitudes/longitudes (rad), shape (M,). Typically from sample_aoi().

  • keplerian_params (dict) – Orbital elements dict, e.g. from sun_synchronous_orbit().

  • t_start, t_end (np.datetime64) – Analysis window (datetime64[us]).

  • alt (float | np.floating, optional) – Ground-point altitude above WGS84 (m). Defaults to 0.

  • el_min (float | np.floating, optional) – Minimum elevation angle (rad). Defaults to 0 (horizon).

  • propagator_type (str, optional) – 'twobody' (default) or 'j2'.

  • max_step (np.timedelta64, optional) – Scan time step. Defaults to 30 s.

  • batch_size (int, optional) – Time steps per propagation batch. Defaults to 1 000.

Returns:

dictt : (N,) datetime64[us] — sample timestamps.

fraction : (N,) float — instantaneous coverage fraction.

cumulative : (N,) float — cumulative coverage fraction.

mean_fraction : float — time-averaged instantaneous fraction.

final_cumulative : float — fraction of points covered ≥ once.

Parameters:
Return type:

dict

missiontools.coverage.revisit_time(lat, lon, keplerian_params, t_start, t_end, alt=0.0, el_min=0.0, propagator_type='twobody', max_step=np.timedelta64(30, 's'), batch_size=1000, fov_pointing_lvlh=None, fov_half_angle=None, sza_max=None, sza_min=None)[source]

Compute per-point revisit time statistics over a time window.

The revisit time for a ground point is the gap between loss of signal (LOS, last visible step) and the next acquisition of signal (AOS, first visible step on the following pass). The initial gap from t_start to the first AOS is not included.

Note

Accuracy is limited to max_step. For exact edge times on individual points of interest use earth_access_intervals().

Parameters:
  • lat, lon (npt.NDArray[np.floating]) – Ground-point latitudes/longitudes (rad), shape (M,).

  • keplerian_params (dict) – Orbital elements dict.

  • t_start, t_end (np.datetime64) – Analysis window.

  • alt (float | np.floating, optional) – Ground-point altitude above WGS84 (m). Defaults to 0.

  • el_min (float | np.floating, optional) – Minimum elevation angle (rad). Defaults to 0 (horizon).

  • propagator_type (str, optional) – 'twobody' or 'j2'.

  • max_step (np.timedelta64, optional) – Scan step. Defaults to 30 s.

  • batch_size (int, optional) – Time steps per propagation batch. Defaults to 1 000.

Returns:

dictmax_revisit : (M,) float — per-point max revisit time (s). nan for points accessed fewer than twice.

mean_revisit : (M,) float — per-point mean revisit time (s). nan for points accessed fewer than twice.

global_max : float — worst-case revisit time across all points (s).

global_mean : float — mean of per-point mean revisit times (s).

Parameters:
Return type:

dict

missiontools.coverage.pointwise_coverage(lat, lon, keplerian_params, t_start, t_end, alt=0.0, el_min=0.0, propagator_type='twobody', max_step=np.timedelta64(30, 's'), batch_size=1000, fov_pointing_lvlh=None, fov_half_angle=None, sza_max=None, sza_min=None)[source]

Return the raw (N × M) visibility matrix for every timestep and ground point.

Unlike coverage_fraction() and revisit_time(), which reduce the visibility matrix to summary statistics, this function returns the full boolean matrix so callers can apply their own post-processing.

Parameters:
  • lat, lon (npt.NDArray[np.floating]) – Ground-point latitudes/longitudes (rad), shape (M,).

  • keplerian_params (dict) – Orbital elements dict.

  • t_start, t_end (np.datetime64) – Analysis window (datetime64[us]).

  • alt (float | np.floating, optional) – Ground-point altitude above WGS84 (m). Defaults to 0.

  • el_min (float | np.floating, optional) – Minimum elevation angle (rad). Defaults to 0 (horizon).

  • propagator_type (str, optional) – 'twobody' (default) or 'j2'.

  • max_step (np.timedelta64, optional) – Scan time step. Defaults to 30 s.

  • batch_size (int, optional) – Time steps per propagation batch. Defaults to 1 000.

  • fov_pointing_lvlh (npt.NDArray | None, optional) – Sensor pointing direction in LVLH frame. Must be paired with fov_half_angle.

  • fov_half_angle (float | None, optional) – FOV half-angle (rad). Must be paired with fov_pointing_lvlh.

  • sza_max (float | None, optional) – Maximum solar zenith angle (rad). Points where the SZA exceeds this value are considered invisible (daytime constraint).

  • sza_min (float | None, optional) – Minimum solar zenith angle (rad). Points where the SZA is below this value are considered invisible (nighttime constraint).

Returns:

dictt : (N,) datetime64[us] — sample timestamps.

lat : (M,) float — ground-point latitudes (rad), echoed from input.

lon : (M,) float — ground-point longitudes (rad), echoed from input.

alt : float — ground-point altitude (m), echoed from input.

visible : (N, M) bool — True where the satellite has line-of-sight to the ground point at that timestep.

Parameters:
Return type:

dict

Notes

Memory usage scales as N × M booleans. For a 30-day window at a 20 s step (N ≈ 130 000) with M = 5 000 points this is roughly 650 MB. Prefer coverage_fraction() or revisit_time() for summary statistics over large grids.

missiontools.coverage.access_pointwise(lat, lon, keplerian_params, t_start, t_end, alt=0.0, el_min=0.0, propagator_type='twobody', max_step=np.timedelta64(30, 's'), batch_size=1000, fov_pointing_lvlh=None, fov_half_angle=None, sza_max=None, sza_min=None)[source]

Return per-point access intervals over a time window.

Each element of the returned list corresponds to one ground point and contains a list of (AOS, LOS) pairs — the times at which the satellite acquired and lost line-of-sight to that point.

Note

Edge times are accurate to max_step. For sub-step accuracy on individual points of interest use earth_access_intervals().

Parameters:
  • lat, lon (npt.NDArray[np.floating]) – Ground-point latitudes/longitudes (rad), shape (M,).

  • keplerian_params (dict) – Orbital elements dict.

  • t_start, t_end (np.datetime64) – Analysis window.

  • alt (float | np.floating, optional) – Ground-point altitude above WGS84 (m). Defaults to 0.

  • el_min (float | np.floating, optional) – Minimum elevation angle (rad). Defaults to 0 (horizon).

  • propagator_type (str, optional) – 'twobody' or 'j2'.

  • max_step (np.timedelta64, optional) – Scan step. Defaults to 30 s.

  • batch_size (int, optional) – Time steps per propagation batch. Defaults to 1 000.

  • fov_pointing_lvlh (npt.NDArray | None, optional) – Sensor pointing direction in LVLH frame.

  • fov_half_angle (float | None, optional) – FOV half-angle (rad).

  • sza_max (float | None, optional) – Maximum solar zenith angle (rad).

  • sza_min (float | None, optional) – Minimum solar zenith angle (rad).

Returns:

list[list[tuple[datetime64, datetime64]]]result[m] is a list of (AOS, LOS) datetime64[us] pairs for point m. An interval still open at t_end is closed with t_end. Points with no access return an empty list.

Parameters:
Return type:

list[list[tuple[datetime64, datetime64]]]

missiontools.coverage.revisit_pointwise(lat, lon, keplerian_params, t_start, t_end, alt=0.0, el_min=0.0, propagator_type='twobody', max_step=np.timedelta64(30, 's'), batch_size=1000, fov_pointing_lvlh=None, fov_half_angle=None, sza_max=None, sza_min=None)[source]

Return per-point revisit gap arrays over a time window.

Each element of the returned list corresponds to one ground point and contains an array of timedelta64[us] values — one per gap between consecutive access windows (LOS of pass i to AOS of pass i+1).

Note

Accuracy is limited to max_step.

Parameters:
  • lat, lon (npt.NDArray[np.floating]) – Ground-point latitudes/longitudes (rad), shape (M,).

  • keplerian_params (dict) – Orbital elements dict.

  • t_start, t_end (np.datetime64) – Analysis window.

  • alt (float | np.floating, optional) – Ground-point altitude above WGS84 (m). Defaults to 0.

  • el_min (float | np.floating, optional) – Minimum elevation angle (rad). Defaults to 0 (horizon).

  • propagator_type (str, optional) – 'twobody' or 'j2'.

  • max_step (np.timedelta64, optional) – Scan step. Defaults to 30 s.

  • batch_size (int, optional) – Time steps per propagation batch. Defaults to 1 000.

  • fov_pointing_lvlh (npt.NDArray | None, optional) – Sensor pointing direction in LVLH frame.

  • fov_half_angle (float | None, optional) – FOV half-angle (rad).

  • sza_max (float | None, optional) – Maximum solar zenith angle (rad).

  • sza_min (float | None, optional) – Minimum solar zenith angle (rad).

Returns:

list[NDArray[timedelta64]]result[m] is an array of timedelta64[us] gaps for point m. Points with fewer than two access windows return an empty array.

Parameters:
Return type:

list[ndarray[tuple[Any, …], dtype[timedelta64]]]

missiontools.coverage.make_sensor_spec(keplerian_params, propagator_type, fov_pointing_lvlh, fov_half_angle)[source]

Convert per-sensor params into a compact spec tuple.

Returns (keplerian_params, propagator_type, use_fov, pointing_lvlh_norm, cos_fov).

Parameters:
Return type:

tuple

missiontools.coverage.coverage_fraction_multi(lat, lon, sensor_specs, t_start, t_end, alt, el_min, sza_max, sza_min, max_step, batch_size)[source]

Multi-sensor implementation of coverage_fraction().

Parameters:
Return type:

dict

missiontools.coverage.pointwise_coverage_multi(lat, lon, sensor_specs, t_start, t_end, alt, el_min, sza_max, sza_min, max_step, batch_size)[source]

Multi-sensor implementation of pointwise_coverage().

Parameters:
Return type:

dict

missiontools.coverage.collect_access_intervals_multi(lat, lon, sensor_specs, t_start, t_end, alt, el_min, sza_max, sza_min, max_step, batch_size, *, close_at_end)[source]

Collect per-point (AOS, LOS) intervals for multiple sensors.

Visibility at each timestep is the union of all sensor FOVs; SZA is applied globally after the union.

Parameters:

close_at_end (bool) – If True, any interval still open at t_end is closed with t_end. If False, open-ended intervals are discarded.

Parameters:
Return type:

list[list[tuple[datetime64, datetime64]]]

missiontools.coverage.load_shapefile_geometry(path, feature_index)[source]

Read an ESRI Shapefile and return a shapely geometry.

Returns:

  • geom (shapely geometry) – Union of all selected features (Polygon or MultiPolygon). Rings are unwrapped so antimeridian-crossing polygons have continuous (possibly out-of-[-180,180]) coordinates.

  • crosses_am (bool) – True if any ring required longitude unwrapping, indicating that the geometry may extend outside the [-180, 180] longitude range and requires shifted-point PIP tests.

missiontools.coverage.sample_from_geometry(geom, crosses_am, point_density)[source]

Fibonacci-sphere sampling inside a shapely geometry.

Parameters:
  • geom (shapely Polygon or MultiPolygon) – Target geometry in geographic degrees (may have extended longitudes if the polygon crosses the antimeridian).

  • crosses_am (bool) – If True, PIP tests are also performed at ±360° longitude shifts.

  • point_density (float) – Approximate area per sample point (m²). Must be positive.

Returns:

  • lat ((M,) float64, radians)

  • lon ((M,) float64, radians)

Parameters:
Return type:

tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]

missiontools.coverage.geography_geometry(geography)[source]

Return the Shapely geometry for a Natural Earth geography without sampling.

Parameters:

geography (str) – Same format as sample_geography() — country name, ISO code, 'Country/Subdivision', or ISO 3166-2 code.

Returns:

  • geom (shapely Polygon or MultiPolygon) – Geometry in geographic degrees. May use extended longitudes (> 180°) for antimeridian-crossing features (e.g. Russia).

  • crosses_am (bool) – True if the geometry uses unwrapped longitude coordinates.

Raises:

ValueError – If geography does not match any bundled feature.

Parameters:

geography (str)

Return type:

tuple[object, bool]