# `Sidereon.Passes`
[🔗](https://github.com/neilberkman/sidereon-ex/blob/main/lib/sidereon/passes.ex#L1)

Satellite pass prediction over a ground station.

Finds time windows when a satellite is above the local horizon (or a
minimum elevation threshold) as seen from a ground station. The pass-search
orchestration and coordinate math live in the Rust core; this module keeps
the public Sidereon API shape.

# `ground_station`

```elixir
@type ground_station() :: %{
  latitude: float(),
  longitude: float(),
  altitude_m: float()
}
```

# `pass`

```elixir
@type pass() :: Sidereon.Pass.t()
```

# `predict_error`

```elixir
@type predict_error() ::
  Sidereon.SGP4.element_error()
  | {:missing_field, atom()}
  | {:invalid_field, atom(), term()}
  | {:invalid_option, atom()}
  | {:nif_error, String.t()}
```

# `predict`

```elixir
@spec predict(
  Sidereon.Elements.t(),
  ground_station(),
  DateTime.t(),
  DateTime.t(),
  keyword()
) ::
  {:ok, [pass()]} | {:error, predict_error()}
```

Predict visible passes of a satellite over a ground station.

## Parameters

  * `tle` - parsed `%Sidereon.Elements{}` struct
  * `ground_station` - `%{latitude: deg, longitude: deg, altitude_m: m}`
  * `start_time` - `DateTime.t()` beginning of the search window
  * `end_time` - `DateTime.t()` end of the search window
  * `opts` - keyword list
    * `:min_elevation` - minimum peak elevation in degrees to keep a pass
      (default `0.0`)
    * `:step_seconds` - coarse propagation step in seconds (default `60`)
    * `:opsmode` - SGP4 operation mode, `:afspc` (default) or `:improved`.
      The pass search builds the satellite with this opsmode, so passes are
      consistent with `Sidereon.look_angle/4` under the same opsmode.

## Returns

`{:ok, passes}` with pass structs sorted by rise time:

    {:ok, [%Sidereon.Pass{
      rise: DateTime.t(),
      set: DateTime.t(),
      max_elevation: float(),       # degrees
      max_elevation_time: DateTime.t(),
      duration_seconds: float()
    }]}

Returns `{:error, reason}` for malformed elements, station fields, options,
or NIF boundary failures. Use `predict!/5` for the raising form.

# `predict!`

```elixir
@spec predict!(
  Sidereon.Elements.t(),
  ground_station(),
  DateTime.t(),
  DateTime.t(),
  keyword()
) :: [
  pass()
]
```

Predict visible passes, raising `ArgumentError` on errors.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
