Analysis#
sidescanpy.analysis measures a dataset. Each function takes data and
returns a dataclass with a to_dict(); none of them writes files, plots
or decides what to do next. Plots for each result are in
sidescanpy.viz (Visualization). sidescan-analyze investigate
runs them all on one file and writes a report, and
Investigating an unknown survey
walks through them on a public recording.
Function |
Answers |
|---|---|
|
data type, shape and distribution of a variable |
|
raw counts, dB, volts or normalized, from the value range |
|
distribution before and after |
|
nadir type (gap, bright spike, noisy, clean), altitude sample and first bottom return |
|
near-edge and far-edge beam angles, beam width |
|
where the signal falls into the noise floor (the noise knee by default, or the SNR rule) |
|
peak, noise floor and noise knee of a level-vs-range profile |
|
the TVG to apply: which spreading law (none, 20, 30 or 40 log R, or free) and whether absorption, fitted to the median level |
|
how flat a TVG recipe leaves the median level over a window |
|
deprecated (removal in 0.12): the earlier candidate classifier; use |
|
raw and TVG-corrected backscatter side by side |
|
pings split into equal-count altitude bins |
|
per-field navigation/attitude statistics and a heading-convention check |
|
median ping spacing, swath width and sample interval |
|
object proposal boxes (native ping, sample, side) from acoustic shadows and the highlight in front of them, with sizes, contrast, estimated height and a score |
Analysis that needs the uncorrected signal recovers it with
processing.uncorrected_backscatter, so it works on corrected files.
Fitting the TVG#
fit_tvg_models(ds) works on raw data (undo a recorded TVG with
processing.invert first) with slant ranges:
Profile. All samples past the median altitude, both sides pooled, binned by slant range in 1 m bins; the median of each bin’s linear amplitude, in dB re 1 recorded unit. Integer samples (many recorders store whole numbers) are first spread over their unit interval by a fixed random offset, so the medians do not stick to whole numbers.
Window. From 5 m past the profile’s peak (inside it the beam pattern dominates; the peak is searched in the near half of the range) to the noise knee, the first range past the peak within 3 dB of the lowest level. Beyond the knee the level is noise. When the level never falls to a floor, as on data the recorder has already levelled, there is no knee: the window runs to the end of the record and
window_sourcesays"end_of_record".window_m=(min, max)sets it by hand.Models.
L(R) = L0 - n log10 R - 2 alpha Rwithn= 0, 20, 30 or 40 and absorption (Francois-Garrison at the channel’s center frequency) off or on: eight models, from “flat” (no TVG) and “absorption only” to “40 log R + abs”. Each has its constantL0fitted by least squares; they are ranked by RMS residual in the window. A freenis fitted too, with and without absorption.Sides. Each side is fitted alone on the same window;
sides_disagreeflags sides whose levels differ by more than 15 dB or whose shapes want different models.
The best model is the TVG to apply: fit.tvg_params holds its
spreading_loss_db and absorption_db_per_m for apply_tvg or the
tvg step. fit.tvg_status names what the recorder has already
removed, derived from that model: none (n and absorption still in the
data), absorption_only (n only), spreading_only (absorption only),
full (flat).
from sidescanpy.analysis import check_tvg, fit_tvg_models
from sidescanpy.viz import plot_tvg_fit
fit = fit_tvg_models(ds)
check = check_tvg(ds, fit.tvg_params, fit.window_m)
print(fit.best, fit.best_model.rms_db, fit.free_n, check.spread_db, check.trend_db_per_10m)
fig, _ = plot_tvg_fit(fit, check)
check_tvg crops the data at the window’s end, applies the recipe with
apply_tvg, and measures the corrected median level over the window:
its spread (standard deviation), trend (dB per 10 m) and end-to-end
change. Pass any recipe, such as a config’s tvg block, to compare it
with the fit.
Reading the results#
A best fit is a hypothesis. Apply it with
check_tvgand check that the corrected level is flat over the same window before trusting it.Over short windows (under about 20 m) 20 log R with absorption, 30 log R and 40 log R differ by tenths of a dB, so the label means little; read the free
nand the runner-up. For a survey, compare several lines (or take the median freen) and pick one model rather than one per line.low_contrast(the level falls less than 6 dB from peak to floor) and an"end_of_record"window mean there is little range dependence left: the recorder levelled it, or there is little seabed signal.The altitude is trusted: samples before it are dropped. A WARNING says when the profile peak lies far past the altitude; a recorded altitude that is too large hides the real peak and is not detected.
A smooth per-ping boundary is not proof of a correct one: a detector stuck at a floor value is also smooth. Compare port and starboard, or two frequencies, when a result looks too clean.