Skip to content

Events & Visibility

Event detection and visibility analysis.

Event Detection

Events are detected when a function crosses zero. The crossing property indicates the direction:

  • "up": Function crosses from negative to positive
  • "down": Function crosses from positive to negative

Visibility Analysis

The VisibilityAnalysis class computes visibility intervals between ground stations and spacecraft, accounting for elevation constraints and optional body occultation. A Scenario groups spacecraft, ground stations, and a time interval together.

Quick Example

import lox_space as lox

# Visibility analysis
gs = lox.GroundStation("ESOC", ground_location, elevation_mask)
sc = lox.Spacecraft("ISS", lox.SGP4(tle))
scenario = lox.Scenario(start, end, spacecraft=[sc], ground_stations=[gs])
analysis = lox.VisibilityAnalysis(
    scenario,
    step=lox.TimeDelta(60),
    min_pass_duration=lox.TimeDelta(300),
)
results = analysis.compute(spk)

for iv in results.intervals("ESOC", "ISS"):
    print(f"Interval: {iv.start()} to {iv.end()}")

for p in results.passes("ESOC", "ISS"):
    print(f"Pass: {p.interval().start()} to {p.interval().end()}")

Event

Represents a detected event (zero-crossing of a function).

Events are detected when a monitored function crosses zero. The crossing direction indicates "up" (negative to positive) or "down" (positive to negative).

Methods:

  • crossing –

    Return the crossing direction ("up" or "down").

  • time –

    Return the time of this event.

crossing

crossing() -> str

Return the crossing direction ("up" or "down").

time

time() -> Time

Return the time of this event.


Interval

Represents a time interval between two times.

Intervals represent periods when certain conditions are met, such as visibility intervals between a ground station and spacecraft.

Methods:

  • contains –

    Return whether this interval fully contains another interval.

  • contains_time –

    Return whether this interval contains the given time.

  • duration –

    Return the duration of this interval.

  • end –

    Return the end time of this interval.

  • intersect –

    Return the intersection of this interval with another.

  • is_empty –

    Return whether this interval is empty (start >= end).

  • linspace –

    Return a list of n evenly-spaced times within this interval.

  • overlaps –

    Return whether this interval overlaps with another.

  • start –

    Return the start time of this interval.

  • step_by –

    Return a list of times spaced by the given step within this interval.

contains

contains(other: Interval) -> bool

Return whether this interval fully contains another interval.

contains_time

contains_time(time: Time) -> bool

Return whether this interval contains the given time.

duration

duration() -> TimeDelta

Return the duration of this interval.

end

end() -> Time

Return the end time of this interval.

intersect

intersect(other: Interval) -> Interval

Return the intersection of this interval with another.

is_empty

is_empty() -> bool

Return whether this interval is empty (start >= end).

linspace

linspace(n: int) -> list[Time]

Return a list of n evenly-spaced times within this interval.

Raises:

overlaps

overlaps(other: Interval) -> bool

Return whether this interval overlaps with another.

start

start() -> Time

Return the start time of this interval.

step_by

step_by(step: TimeDelta) -> list[Time]

Return a list of times spaced by the given step within this interval.

Raises:


intersect_intervals builtin

intersect_intervals(a: list[Interval], b: list[Interval]) -> list[Interval]

Intersect two sorted lists of intervals.

Parameters:

Returns:

  • list[Interval] –

    List of intervals representing the intersection.


union_intervals builtin

union_intervals(a: list[Interval], b: list[Interval]) -> list[Interval]

Compute the union of two sorted lists of intervals.

Parameters:

Returns:

  • list[Interval] –

    List of merged intervals representing the union.


complement_intervals builtin

complement_intervals(intervals: list[Interval], bound: Interval) -> list[Interval]

Compute the complement of intervals within a bounding interval.

Parameters:

  • intervals

    (list[Interval]) –

    List of intervals to complement.

  • bound

    (Interval) –

    Bounding interval.

Returns:

  • list[Interval] –

    List of gap intervals within the bound.


GroundStation

A named ground station for visibility analysis.

Wraps a ground location with an identifier, an optional operational minimum-elevation floor, and an optional measured horizon mask. Visibility tests elevation against the maximum of both.

Parameters:

  • id

    –

    Unique identifier for this ground station.

  • location

    –

    Ground station location.

  • min_elevation

    –

    Optional minimum-elevation floor (unconstrained when omitted).

  • horizon_mask

    –

    Optional measured horizon profile (flat 0° horizon when omitted).

  • tx_terminals

    –

    Optional dict of named transmit terminals (TxChain or EirpModel).

  • rx_terminals

    –

    Optional dict of named receive terminals (RxChain or GtModel).

Examples:

>>> gs = lox.GroundStation("ESOC", ground_location, min_elevation=5 * lox.deg)

Methods:

  • horizon_mask –

    Return the horizon mask, if set.

  • id –

    Return the asset identifier.

  • location –

    Return the ground location.

  • min_elevation –

    Return the minimum-elevation floor, if set.

  • network_id –

    Return the network identifier, if assigned.

  • rx_terminals –

    Return the named receive terminals as a dict.

  • threshold_at –

    Return the effective elevation threshold at the given azimuth.

  • tx_terminals –

    Return the named transmit terminals as a dict.

horizon_mask

horizon_mask() -> HorizonMask | None

Return the horizon mask, if set.

id

id() -> str

Return the asset identifier.

location

location() -> EllipsoidLocation

Return the ground location.

min_elevation

min_elevation() -> Angle | None

Return the minimum-elevation floor, if set.

network_id

network_id() -> str | None

Return the network identifier, if assigned.

rx_terminals

rx_terminals() -> dict[str, RxTerminal]

Return the named receive terminals as a dict.

threshold_at

threshold_at(azimuth: Angle) -> Angle

Return the effective elevation threshold at the given azimuth.

The threshold is the maximum of the horizon profile (0° when no horizon mask is set) and the minimum-elevation floor.

tx_terminals

tx_terminals() -> dict[str, TxTerminal]

Return the named transmit terminals as a dict.


Spacecraft

A named spacecraft for visibility analysis.

Wraps an orbit source (propagator or pre-computed trajectory) with an identifier.

Parameters:

  • id

    –

    Unique identifier for this spacecraft.

  • orbit

    –

    Orbit source — an SGP4, Vallado, J2, J4, Numerical propagator, or a pre-computed Trajectory.

  • max_slew_rate

    –

    Optional maximum slew rate.

  • tx_terminals

    –

    Optional dict of named transmit terminals (TxChain or EirpModel).

  • rx_terminals

    –

    Optional dict of named receive terminals (RxChain or GtModel).

Examples:

>>> sc = lox.Spacecraft("ISS", lox.SGP4(tle))
>>> sc = lox.Spacecraft("SAT", trajectory)

Methods:

constellation_id

constellation_id() -> str | None

Return the constellation identifier, if assigned.

id

id() -> str

Return the asset identifier.

max_slew_rate

max_slew_rate() -> AngularRate | None

Return the maximum slew rate, if set.

optical_payload

optical_payload() -> OpticalPayload | None

Return the optical payload, if set.

rx_terminals

rx_terminals() -> dict[str, RxTerminal]

Return the named receive terminals as a dict.

sar_payload

sar_payload() -> SarPayload | None

Return the SAR payload, if set.

tx_terminals

tx_terminals() -> dict[str, TxTerminal]

Return the named transmit terminals as a dict.


Scenario

A scenario grouping spacecraft, ground stations, and a time interval.

Parameters:

  • start

    –

    Start time of the scenario.

  • end

    –

    End time of the scenario.

  • spacecraft

    –

    List of Spacecraft objects.

  • ground_stations

    –

    List of GroundStation objects.

Examples:

>>> scenario = lox.Scenario(t0, t1, spacecraft=[sc], ground_stations=[gs])

Methods:

  • end –

    Return the end time.

  • propagate –

    Propagate all spacecraft, returning an Ensemble.

  • start –

    Return the start time.

  • with_constellation –

    Add a constellation to the scenario.

end

end() -> Time

Return the end time.

propagate

propagate() -> Ensemble

Propagate all spacecraft, returning an Ensemble.

Trajectories are transformed to ICRF using the default rotation provider.

start

start() -> Time

Return the start time.

with_constellation

with_constellation(constellation: Constellation) -> Scenario

Add a constellation to the scenario.

Converts each satellite into a Spacecraft using the constellation's selected propagator.


Ensemble

A collection of propagated trajectories keyed by spacecraft id.

Examples:

>>> ensemble = scenario.propagate()
>>> traj = ensemble.get("ISS")

Methods:

  • get –

    Return the trajectory for a given spacecraft id.

get

get(id: str) -> Trajectory | None

Return the trajectory for a given spacecraft id.


VisibilityAnalysis

Computes ground-station-to-spacecraft and inter-satellite visibility.

Ground-to-space pairs are always computed when ground assets are present. Inter-satellite pairs are additionally computed when inter_satellite is set to True.

Parameters:

  • scenario

    –

    Scenario containing spacecraft, ground stations, and time interval.

  • ensemble

    –

    Optional pre-computed Ensemble. If not provided, the scenario is propagated automatically.

  • occulting_bodies

    –

    Optional list of additional occulting bodies for line-of-sight checking. For inter-satellite visibility, the scenario's central body is always checked automatically.

  • step

    –

    Optional time step for event detection (default: 60s).

  • min_pass_duration

    –

    Optional minimum pass duration. Passes shorter than this value may be missed. Enables two-level stepping for faster detection.

  • inter_satellite

    –

    If True, also compute inter-satellite visibility for all unique spacecraft pairs (default: False).

  • ground_space_filter

    –

    Optional callable (GroundStation, Spacecraft) -> bool that receives a ground station and a spacecraft and returns whether the pair should be evaluated. Called once per candidate pair before the parallel phase.

  • inter_satellite_filter

    –

    Optional callable (Spacecraft, Spacecraft) -> bool that receives two spacecraft and returns whether the pair should be evaluated. Called once per candidate pair before the parallel phase. When provided, inter-satellite visibility is automatically enabled.

  • min_range

    –

    Optional minimum range constraint for inter-satellite pairs.

  • max_range

    –

    Optional maximum range constraint for inter-satellite pairs.

Examples:

>>> scenario = lox.Scenario(t0, t1, spacecraft=[sc], ground_stations=[gs])
>>> analysis = lox.VisibilityAnalysis(scenario, step=lox.TimeDelta(60))
>>> results = analysis.compute(spk)

Methods:

  • compute –

    Compute visibility intervals for all pairs.

compute

Compute visibility intervals for all pairs.

If no ensemble was provided at construction, the scenario is propagated automatically (trajectories transformed to ICRF).

Parameters:

  • ephemeris

    (SPK) –

    SPK ephemeris data.

Returns:


VisibilityResults

Results of a visibility analysis.

Provides access to visibility intervals and passes. Intervals (time windows) are computed eagerly; observables-rich Pass objects are computed on demand.

Methods:

all_intervals

all_intervals() -> dict[tuple[str, str], list[Interval]]

Return all intervals for all pairs.

Returns:

all_passes

all_passes() -> dict[tuple[str, str], list[Pass]]

Compute passes for all ground-to-space pairs.

Inter-satellite pairs are skipped.

Returns:

ground_space_intervals

ground_space_intervals() -> dict[tuple[str, str], list[Interval]]

Return intervals for ground-to-space pairs only.

Returns:

ground_space_pair_ids

ground_space_pair_ids() -> list[tuple[str, str]]

Return pair identifiers for ground-to-space pairs only.

inter_satellite_intervals

inter_satellite_intervals() -> dict[tuple[str, str], list[Interval]]

Return intervals for inter-satellite pairs only.

Returns:

inter_satellite_pair_ids

inter_satellite_pair_ids() -> list[tuple[str, str]]

Return pair identifiers for inter-satellite pairs only.

intervals

intervals(id1: str, id2: str) -> list[Interval]

Return visibility intervals for a specific pair.

Parameters:

  • id1

    (str) –

    First asset identifier (ground or space).

  • id2

    (str) –

    Second asset identifier (space).

Returns:

  • list[Interval] –

    List of Interval objects, or empty list if pair not found.

num_pairs

num_pairs() -> int

Return the total number of pairs.

pair_ids

pair_ids() -> list[tuple[str, str]]

Return all pair identifiers.

passes

passes(ground_id: str, space_id: str) -> list[Pass]

Compute passes with observables for a specific ground-to-space pair.

This is more expensive than intervals() as it computes azimuth, elevation, range, and range rate for each time step.

Raises:

  • ValueError –

    If the pair is an inter-satellite pair.

Parameters:

  • ground_id

    (str) –

    Ground asset identifier.

  • space_id

    (str) –

    Space asset identifier.

Returns:

  • list[Pass] –

    List of Pass objects, or empty list if pair not found.

total_intervals

total_intervals() -> int

Return the total number of visibility intervals across all pairs.


PowerBudgetAnalysis

Power budget analysis for spacecraft in a scenario.

Computes eclipse intervals, sun beta angle, and solar flux for each spacecraft. The shadow model is cylindrical (umbra only) — penumbra is not modelled.

Parameters:

  • scenario

    –

    Scenario containing spacecraft and time interval.

  • ensemble

    –

    Optional pre-computed Ensemble.

  • step

    –

    Optional time step for sampling / event detection (default: 60s).

  • spacecraft_ids

    –

    Optional list of spacecraft ids to restrict the analysis.

Examples:

>>> analysis = lox.PowerBudgetAnalysis(scenario)
>>> results = analysis.compute()          # analytical Sun
>>> results = analysis.compute(ephemeris)  # SPK Sun

Methods:

  • compute –

    Compute the power budget analysis.

compute

compute(ephemeris: SPK | None = None) -> PowerBudgetResults

Compute the power budget analysis.

Parameters:

  • ephemeris

    (SPK | None, default: None ) –

    Optional SPK ephemeris for Sun position. When omitted, an analytical model is used (valid for Earth-centred scenarios).

Returns:


PowerBudgetResults

Results of a power budget analysis.

Provides access to eclipse intervals, eclipse/sunlit fractions, beta-angle time series, and solar-flux time series for each spacecraft.

Methods:

beta_angles

beta_angles(id: str) -> TimeSeries | None

Return beta-angle time series (radians).

Parameters:

  • id

    (str) –

    Spacecraft identifier.

Returns:

  • TimeSeries | None –

    TimeSeries of beta angles in radians, or None if id not found.

eclipse_fraction

eclipse_fraction(id: str) -> float | None

Return eclipse fraction (0 = fully sunlit, 1 = always eclipsed).

Parameters:

  • id

    (str) –

    Spacecraft identifier.

Returns:

  • float | None –

    Eclipse fraction, or None if id not found.

eclipse_intervals

eclipse_intervals(id: str) -> list[Interval]

Return eclipse intervals for a specific spacecraft.

Parameters:

  • id

    (str) –

    Spacecraft identifier.

Returns:

  • list[Interval] –

    List of Interval objects, or empty list if id not found.

solar_flux

solar_flux(id: str) -> TimeSeries | None

Return solar-flux time series (W/m²).

Parameters:

  • id

    (str) –

    Spacecraft identifier.

Returns:

  • TimeSeries | None –

    TimeSeries of solar flux in W/m², or None if id not found.

sunlit_fraction

sunlit_fraction(id: str) -> float | None

Return sunlit fraction (1 - eclipse_fraction).

Parameters:

  • id

    (str) –

    Spacecraft identifier.

Returns:

  • float | None –

    Sunlit fraction, or None if id not found.