Skip to content
This documentation describes version 4.0.0, which is not released yet. The current version on PyPI is 3.3.0 and does not carry everything described here.

underwater.sonar_equation

The sonar equation (passive and active), in decibels.

Combines the sonar performance terms — source level SL, propagation loss PL, noise level NL, directivity index DI, detection threshold DT, target strength TS and reverberation level RL — into the signal excess SE, the signal-to-noise ratio and the figure of merit (the maximum allowable propagation loss at the detection limit ):

  • passive_sonar_equation.
  • active_sonar_equation — monostatic, noise-limited or, when a reverberation level is given, reverberation-limited .

Two of those terms have their own model here rather than having to be supplied from outside: array_directivity_index gives DI from the length of a line array and the wavelength, which is also its array gain when the noise is isotropic, and detection_threshold gives DT from the false-alarm probability alone. Both are Ainslie (2010).

All quantities are in dB (levels re a plane wave of 1 µPa rms; the terms are spectrum levels, i.e. referred to a 1 Hz band). Source: Urick, Principles of Underwater Sound, via Etter (2003), Table 10.2. The loss term is the propagation loss of ISO 18405:2017, 3.4.1.4, which is also the term its own passive and active sonar equations (3.6.2.7 and 3.6.2.11) are written with.

The figure of merit is the maximum allowable propagation loss, so inverting a propagation-loss law at gives the detection range, the range at which the detection probability is 50 %:

  • detection_range inverts the closed-form loss of phonometry.underwater.propagation.closed_form (spreading plus volume absorption), which is strictly increasing with range and therefore has a single crossing;
  • detection_range_from_curve reads the crossing off any computed loss curve — a normal-mode, parabolic-equation or Weston-regime prediction — where the oscillatory loss of a real waveguide can cross the figure of merit more than once (Ainslie, Principles of Sonar Performance Modelling, §11.2.8 makes exactly that point about convergence zones).

Auto-generated from the source docstrings by scripts/generate_api_docs.py (make api-docs). Do not edit by hand.

active_sonar_equation(
source_level: float,
propagation_loss: NDArray[np.float64] | list[float] | float,
target_strength: float,
noise_level: float,
*,
directivity_index: float = 0.0,
detection_threshold: float = 0.0,
reverberation_level: float | None = None,
) -> SonarEquationResult

Monostatic active sonar equation with a two-way propagation loss.

Noise-limited: . When reverberation_level is given, reverberation-limited: (DI does not apply to reverberation).

Parameters

NameDescription
source_levelSource level SL, in dB.
propagation_lossOne-way propagation loss PL, in dB (scalar or array); the equation applies .
target_strengthTarget strength TS, in dB.
noise_levelBackground noise level NL, in dB.
directivity_indexReceiver directivity index DI, in dB.
detection_thresholdDetection threshold DT, in dB.
reverberation_levelReverberation level RL in dB; when given, the case is reverberation-limited.

Returns: A SonarEquationResult.

Raises

ExceptionWhen
ValueErrorIf an input is not finite.
array_directivity_index(
array_length_m: float,
wavelength_m: float,
*,
steer_angle_rad: float = 0.0,
) -> float

Directivity index of an unshaded line array (Ainslie 2010, Eq. (6.49)).

with the directivity factor the reciprocal of the solid-angle footprint of the beam. For a steered unshaded line array, Equation (6.56) on printed folio 267 gives that footprint in closed form:

with (Eq. (6.54)) and (Eq. (6.57)), the high-frequency limit of the broadside directivity factor.

This is the array gain whenever the noise is isotropic and the signal a plane wave, which is the case the sonar equation is written for (Section 6.1.3.1): the two coincide in that limit, so this is what passive_sonar_equation wants for its directivity_index.

The book states three limits, and they are what the implementation is checked against: at high frequency for every steer direction but endfire, near endfire, where the footprint halves, and 0 dB as , where the array stops resolving anything. That last one is a limit and not a cutoff: a finite array a wavelength long still returns 3.45 dB, and half a wavelength 1.11 dB. It is reached exactly only where the ratio itself underflows, and the value there is 0 dB rather than an error.

Parameters

NameDescription
array_length_mArray length L, in metres (> 0).
wavelength_mAcoustic wavelength lambda, in metres (> 0).
steer_angle_radSteer angle psi from broadside, in radians (Default: 0, broadside). Only its sine enters, so the two sides of broadside give the same index.

Returns: The directivity index DI, in dB (>= 0).

Raises

ExceptionWhen
ValueErrorfor a non-positive or non-finite length or wavelength, or a non-finite steer angle.
detection_range(
figure_of_merit: float,
frequency_hz: float,
*,
law: str = 'spherical',
transition_range: float | None = None,
temperature: float = 10.0,
salinity: float = 35.0,
depth: float = 0.0,
ph: float = 8.0,
model: str = 'francois-garrison',
max_range: float = 500000.0,
n_points: int = 400,
) -> DetectionRangeResult

Range at which the closed-form propagation loss equals the figure of merit.

Solves for the loss of propagation_loss, which is strictly increasing in range, so the root is unique. A one-way figure of merit works for both sonar modes: the active figure of merit returned by active_sonar_equation is already the maximum allowable one-way loss.

Parameters

NameDescription
figure_of_meritMaximum allowable one-way propagation loss, in dB.
frequency_hzAcoustic frequency, in Hz.
lawSpreading law (see spreading_loss).
transition_rangeTransition range for the "practical" law, in m.
temperatureTemperature T, in degrees Celsius.
salinitySalinity S, in parts per thousand.
depthDepth, in metres.
phAcidity (default 8).
modelAbsorption model (see seawater_absorption).
max_rangeUpper bound of the search, in metres.
n_pointsNumber of ranges kept on the returned loss curve.

Returns: A DetectionRangeResult.

Raises

ExceptionWhen
ValueErrorIf an input is invalid.
detection_range_from_curve(
figure_of_merit: float,
range_m: NDArray[np.float64] | list[float],
propagation_loss: NDArray[np.float64] | list[float],
*,
crossing: str = 'first',
) -> float

Detection range read off a computed propagation-loss curve.

Finds where PL(r) crosses the figure of merit from below, interpolating linearly between the two bracketing samples. Real waveguides oscillate, so crossing selects which crossing to report.

Parameters

NameDescription
figure_of_meritMaximum allowable propagation loss, in dB.
range_mRanges, in metres (1-D, strictly increasing).
propagation_lossLoss at each range, in dB (same length).
crossing"first" (default) or "last" upward crossing.

Returns: The detection range, in metres. Two limiting cases carry no crossing and are distinguished by the loss at the last sample: inf when the loss is still below the figure of merit there (the target stays detectable past the end of the grid) and 0.0 when the loss exceeds it there, which without an upward crossing means it exceeded it at every sample and the target is detectable nowhere. detection_range returns the same two values for the same two situations.

Raises

ExceptionWhen
ValueErrorIf the inputs are invalid.
detection_threshold(false_alarm_probability: float) -> float

Detection threshold at 50 % detection probability (Ainslie Eq. (11.22)).

printed on folio 581. DT is , the signal-to-noise ratio after all processing that a 50 % detection probability needs (Eq. (3.31)); this closed form estimates it from the false-alarm probability alone.

The logarithm inside is base two, not a square. The book states the approximation is accurate to +/- 0.1 dB for with one-dominant-plus-Rayleigh signal statistics, which is the intermediate choice to make when the target statistics are unknown, and that assuming those statistics anyway costs no more than 0.8 dB even for a stable signal or a fully Rayleigh one.

Parameters

NameDescription
false_alarm_probabilityp_fa, the probability of declaring a detection with no target present, in (0, 1/2).

Returns: The detection threshold DT, in dB.

Raises

ExceptionWhen
ValueErrorfor a non-finite p_fa, or one outside (0, 1/2). At the inner logarithm is zero and the threshold diverges: half the empty beams are already called detections.
DetectionRangeResult(
detection_range: float,
figure_of_merit: float,
frequency: float,
range_m: NDArray[np.float64],
propagation_loss: NDArray[np.float64],
absorption_coefficient: float,
law: str,
model: str,
)

Detection range obtained by inverting a propagation-loss law.

Attributes

NameDescription
detection_rangeRange at which PL equals the figure of merit, in metres. inf when the loss never reaches it inside max_range (detectable throughout) and 0.0 when it already exceeds it at the search floor (detectable nowhere).
figure_of_meritThe figure of merit inverted, in dB.
frequencyAcoustic frequency, in Hz.
range_mRange grid over which the loss was evaluated, in metres.
propagation_lossPropagation loss at each range, in dB.
absorption_coefficientAbsorption coefficient , in dB/km.
lawThe spreading law used.
modelThe absorption model used.
DetectionRangeResult.plot(
ax: Axes | None = None,
*,
language: str = 'en',
**kwargs: Any,
) -> Axes

Plot the propagation loss against the figure of merit.

passive_sonar_equation(
source_level: float,
propagation_loss: NDArray[np.float64] | list[float] | float,
noise_level: float,
*,
directivity_index: float = 0.0,
detection_threshold: float = 0.0,
) -> SonarEquationResult

Passive sonar equation .

Parameters

NameDescription
source_levelSource level SL (of the target), in dB.
propagation_lossOne-way propagation loss PL, in dB (scalar or array).
noise_levelBackground noise level NL, in dB.
directivity_indexReceiver directivity index DI, in dB.
detection_thresholdDetection threshold DT, in dB.

Returns: A SonarEquationResult.

Raises

ExceptionWhen
ValueErrorIf an input is not finite.
SonarEquationResult(
mode: str,
signal_excess: NDArray[np.float64],
snr: NDArray[np.float64],
figure_of_merit: float,
propagation_loss: NDArray[np.float64],
source_level: float,
noise_level: float,
directivity_index: float,
detection_threshold: float,
target_strength: float | None,
reverberation_limited: bool,
)

Sonar-equation solution.

Attributes

NameDescription
mode"passive" or "active".
signal_excessSignal excess SE per propagation loss, in dB (detection when SE >= 0).
snrSignal-to-noise (or signal-to-reverberation) ratio, in dB ().
figure_of_meritMaximum allowable (one-way) propagation loss at the detection limit , in dB.
propagation_lossThe propagation-loss values, in dB.
source_levelSource level SL, in dB.
noise_levelBackground noise level NL input, in dB. The masking term is , except when reverberation_limited is true, where the reverberation level RL masks instead.
directivity_indexReceiver directivity index DI, in dB.
detection_thresholdDetection threshold DT, in dB.
target_strengthTarget strength TS, in dB (None for passive).
reverberation_limitedWhether the active case is reverberation-limited.
SonarEquationResult.plot(
ax: Axes | None = None,
*,
language: str = 'en',
**kwargs: Any,
) -> Axes

Plot signal excess versus propagation loss with the detection limit.