Skip to content

Sopp Engine

Sopp

Sopp(
    configuration: Configuration,
    ephemeris_calculator_class: type[
        EphemerisCalculator
    ] = SkyfieldEphemerisCalculator,
    pointing_calculator_class: type[
        PointingCalculator
    ] = PointingCalculatorSkyfield,
)

Main entry point for satellite interference analysis.

Orchestrates trajectory computation, antenna pointing, and interference detection. Supports parallel execution for large satellite catalogs.

Source code in src/sopp/sopp.py
def __init__(
    self,
    configuration: Configuration,
    ephemeris_calculator_class: type[
        EphemerisCalculator
    ] = SkyfieldEphemerisCalculator,
    pointing_calculator_class: type[
        PointingCalculator
    ] = PointingCalculatorSkyfield,
):
    self.configuration = configuration
    self._pointing_calculator_class = pointing_calculator_class
    self._ephemeris_calculator_class = ephemeris_calculator_class

Functions

get_satellites_above_horizon

get_satellites_above_horizon() -> TrajectorySet

Returns trajectories for all satellites that rise above the minimum altitude.

Source code in src/sopp/sopp.py
def get_satellites_above_horizon(self) -> TrajectorySet:
    """
    Returns trajectories for all satellites that rise above the minimum altitude.
    """
    satellites = self.configuration.satellites
    concurrency = self.configuration.runtime_settings.concurrency_level

    if concurrency <= 1:
        results = find_satellites_above_horizon(
            reservation=self.configuration.reservation,
            satellites=satellites,
            ephemeris_calculator=self.ephemeris_calculator,
            min_altitude=self.configuration.runtime_settings.min_altitude,
        )
    else:
        results = self._compute_trajectories_parallel(satellites=satellites)

    return TrajectorySet(results)

get_satellites_crossing_main_beam

get_satellites_crossing_main_beam() -> TrajectorySet

Returns trajectories for satellites that cross the antenna's main beam.

Source code in src/sopp/sopp.py
def get_satellites_crossing_main_beam(self) -> TrajectorySet:
    """
    Returns trajectories for satellites that cross the antenna's main beam.
    """
    trajectories = self.get_satellites_above_horizon()
    results = self.analyze(trajectories, GeometricStrategy())
    return TrajectorySet([r.trajectory for r in results])

analyze

analyze(
    trajectories: TrajectorySet,
    strategy: InterferenceStrategy,
) -> list[InterferenceResult]

Apply an interference strategy to pre-computed trajectories.

Use this when trajectories have already been computed or loaded from disk and you want to run interference analysis without recalculating orbital positions.

Parameters:

Name Type Description Default
trajectories TrajectorySet

Pre-computed satellite trajectories.

required
strategy InterferenceStrategy

The interference detection strategy to apply.

required

Returns:

Type Description
list[InterferenceResult]

List of InterferenceResult for trajectories where interference

list[InterferenceResult]

was detected.

Example

from sopp.analysis.strategies import GeometricStrategy from sopp.io import load_trajectories

engine = Sopp(configuration) cached = load_trajectories("trajectories.arrow") results = engine.analyze(cached, GeometricStrategy())

Source code in src/sopp/sopp.py
def analyze(
    self,
    trajectories: TrajectorySet,
    strategy: InterferenceStrategy,
) -> list[InterferenceResult]:
    """Apply an interference strategy to pre-computed trajectories.

    Use this when trajectories have already been computed or loaded from
    disk and you want to run interference analysis without recalculating
    orbital positions.

    Args:
        trajectories: Pre-computed satellite trajectories.
        strategy: The interference detection strategy to apply.

    Returns:
        List of InterferenceResult for trajectories where interference
        was detected.

    Example:
        from sopp.analysis.strategies import GeometricStrategy
        from sopp.io import load_trajectories

        engine = Sopp(configuration)
        cached = load_trajectories("trajectories.arrow")
        results = engine.analyze(cached, GeometricStrategy())
    """
    if self.configuration.antenna_config is None:
        raise ValueError(
            "analyze() requires antenna_config. Set an observation target, "
            "static position, or custom trajectory in the configuration."
        )
    if self.configuration.reservation.frequency is None:
        raise ValueError(
            "analyze() requires frequency_range. Set it via "
            "ConfigurationBuilder.set_frequency_range()."
        )
    return analyze_interference(
        trajectories=trajectories,
        antenna_trajectory=self.antenna_trajectory,
        strategy=strategy,
        facility=self.configuration.reservation.facility,
        frequency=self.configuration.reservation.frequency,
    )

save_trajectories

save_trajectories(
    trajectories: TrajectorySet,
    path: str | Path,
    *,
    format: TrajectoryFormat | None = None,
) -> Path

Save computed trajectories to a file.

Convenience method that saves trajectories with observer information from the current configuration.

Parameters:

Name Type Description Default
trajectories TrajectorySet

List of trajectories to save (from get_satellites_above_horizon or get_satellites_crossing_main_beam).

required
path str | Path

Output file path.

required
format TrajectoryFormat | None

File format handler. Defaults to ArrowFormat.

None

Returns:

Type Description
Path

Path to the saved file.

Example

engine = Sopp(configuration) trajectories = engine.get_satellites_above_horizon() engine.save_trajectories(trajectories, "cache/trajectories.arrow")

Source code in src/sopp/sopp.py
def save_trajectories(
    self,
    trajectories: TrajectorySet,
    path: str | Path,
    *,
    format: TrajectoryFormat | None = None,
) -> Path:
    """Save computed trajectories to a file.

    Convenience method that saves trajectories with observer information
    from the current configuration.

    Args:
        trajectories: List of trajectories to save (from get_satellites_above_horizon
                     or get_satellites_crossing_main_beam).
        path: Output file path.
        format: File format handler. Defaults to ArrowFormat.

    Returns:
        Path to the saved file.

    Example:
        engine = Sopp(configuration)
        trajectories = engine.get_satellites_above_horizon()
        engine.save_trajectories(trajectories, "cache/trajectories.arrow")
    """
    facility = self.configuration.reservation.facility

    from sopp.io import save_trajectories

    return save_trajectories(
        trajectories,
        path,
        format=format,
        observer_name=facility.name,
        observer_lat=facility.coordinates.latitude,
        observer_lon=facility.coordinates.longitude,
    )