# `Sidereon.SourceLocalization`
[🔗](https://github.com/neilberkman/sidereon-ex/blob/main/lib/sidereon/source_localization.ex#L258)

Source localization from time of arrival or time difference of arrival.

Sensors are fixed 2D or 3D Cartesian positions in metres. Arrival times and
origin times are seconds. The propagation speed is metres per second, with an
optional per-sensor override for simple per-path timing differences.

# `source_error`

```elixir
@type source_error() ::
  {:invalid_input, String.t(), String.t()}
  | {:too_few_sensors, non_neg_integer(), pos_integer()}
  | :initializer_singular
  | {:geometry, term()}
  | {:solver, String.t()}
  | {:did_not_converge, integer()}
```

# `chan_ho_initial_guess`

```elixir
@spec chan_ho_initial_guess(
  [Sidereon.SourceLocalization.Sensor.t()],
  [number()],
  number(),
  Sidereon.SourceLocalization.Options.solve_mode()
) ::
  {:ok, Sidereon.SourceLocalization.InitialGuess.t()}
  | {:error, source_error() | :invalid_sensor | :invalid_mode}
```

Compute the closed-form Chan-Ho seed used by `locate_source/4`.

`mode` is `:toa` or `{:tdoa, reference_sensor_index}`.

# `locate_source`

```elixir
@spec locate_source(
  [Sidereon.SourceLocalization.Sensor.t()],
  [number()],
  number(),
  keyword() | Sidereon.SourceLocalization.Options.t()
) ::
  {:ok, Sidereon.SourceLocalization.Solution.t()}
  | {:error,
     source_error() | :invalid_sensor | :invalid_position | :invalid_options}
```

Locate a source from sensor arrival times.

`sensors` is a list of `Sensor` structs. `arrival_times_s` must have matching
length. `propagation_speed_m_s` is the default propagation speed in metres per
second. Options are a keyword list or `Sidereon.SourceLocalization.Options`.

# `sensor`

```elixir
@spec sensor([number()] | tuple(), number() | nil) ::
  Sidereon.SourceLocalization.Sensor.t()
```

Convenience constructor for `Sidereon.SourceLocalization.Sensor`.

# `source_crlb`

```elixir
@spec source_crlb(
  [Sidereon.SourceLocalization.Sensor.t()],
  [number()] | tuple(),
  number(),
  number()
) ::
  {:ok, Sidereon.SourceLocalization.Crlb.t()}
  | {:error, source_error() | :invalid_sensor | :invalid_position}
```

Compute a timing Cramer-Rao lower bound for a proposed source location.

`timing_sigma_s` is the timing standard deviation in seconds used to scale the
covariance.

# `source_dop`

```elixir
@spec source_dop(
  [Sidereon.SourceLocalization.Sensor.t()],
  [number()] | tuple(),
  number()
) ::
  {:ok, Sidereon.SourceLocalization.Crlb.dop()}
  | {:error, source_error() | :invalid_sensor | :invalid_position}
```

Compute timing DOP for a proposed source location.

The returned DOP values use the local Cartesian axes for horizontal and
vertical split. Position DOP values multiply timing sigma in seconds to
produce metres.

---

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