sidescanpy.viz.waterfall#

Waterfall plotting for SideScan sonar.

Plots a port+starboard combined waterfall image with configurable x-axis (sample, ground_range, across_track, slant_range) and y-axis (ping, time, along_track) modes. Returns the matplotlib Axes for further customization.

2026 rshomberg@uri.edu

Contents

plot_waterfall

Plot a port+starboard combined waterfall.

resolve_waterfall_axes

Pick the waterfall x/y axis mode for a given correction's step set.

plot_survey_overview

Compressed, whole-survey waterfall overview.

sidescanpy.viz.waterfall.plot_waterfall(ds, *, start=0, stop=None, x_axis='sample', y_axis='ping', ping_offset=0, cmap='copper', vmin=None, vmax=None, vmin_pct=1.0, vmax_pct=99.0, gamma=1.0, show_colorbar=False, ax=None, title=None, value_var='backscatter_intensity')#

Plot a port+starboard combined waterfall.

Parameters:
dsxr.Dataset

Validated sidescan dataset.

value_varstr, default “backscatter_intensity”

Which backscatter variable to plot – the TVG-corrected default, or any other per-sample variable (e.g. one holding sidescanpy.processing.uncorrected_backscatter(ds) for an uncorrected view of a corrected dataset).

startint, default 0

First ping index to include.

stopint, optional

One past last ping index. Defaults to all pings.

x_axis{“sample”, “ground_range”, “across_track”, “slant_range”}

How to interpret the x-axis.

  • "sample": sample number, port mirrored (-N to +N). Always works.

  • "ground_range": across-bottom distance, signed by channel (port = negative). Requires ground_range_m from compute_geometric_ranges.

  • "across_track": signed across-track in platform frame (already negative for port). Requires across_track_m.

  • "slant_range": attitude-invariant time-of-flight range, signed by channel (port = negative) the same way as "ground_range". Unlike ground range, always finite (never NaN in the water column) — useful when the water column itself needs to stay visible/maskable by a caller rather than being NaN’d out by the range variable’s own geometry. Requires slant_range_m.

y_axis{“ping”, “time”, “along_track”}

How to interpret the y-axis.

  • "ping": ping number.

  • "time": ping timestamp.

  • "along_track": cumulative platform distance from first ping. Computed via pyproj.Geod.inv from per-ping latitude/ longitude.

ping_offsetint, default 0

Added to y_axis="ping" values (and to the title’s ping range). Use when ds is itself an already-extracted window of a larger survey (e.g. one segment of a multi-file concatenated channel) so the y-axis reports the segment’s true position in the full survey instead of 0-based local indices. Ignored for y_axis="time"/"along_track" — those are derived from ds’s own per-ping fields and need no external offset.

cmapstr or Colormap, default “copper”

Matplotlib colormap.

vmin, vmaxfloat, optional

Color scale bounds. If not given, computed from percentiles (vmin_pct and vmax_pct) of the finite values that are drawn: samples without an x coordinate (such as the water column in ground-range modes) are left out.

vmin_pct, vmax_pctfloat, default 1.0 and 99.0

Percentiles for auto color scaling. Ignored if vmin or vmax is given.

gammafloat, default 1.0

Display-only power-law contrast curve, applied via matplotlib.colors.PowerNorm(gamma, vmin, vmax) instead of a plain linear Normalize. The plotted array itself is never modified — only the value-to-color mapping is warped — so the backscatter stays real dB and (if show_colorbar=True) the colorbar keeps honest dB tick values, just non-uniformly spaced. gamma=1.0 (default) is a linear scale, identical to this function’s behavior before this parameter existed.

show_colorbarbool, default False

If True, add a colorbar labeled “Backscatter (dB)”.

axmatplotlib.axes.Axes, optional

Axes to plot on. If not given, creates a new figure with a single Axes.

titlestr, optional

Plot title. Default: ping range and processing level.

Returns:
Axes

The matplotlib Axes containing the plot.

Raises:
ValueError

If a required variable is missing for the chosen axis mode.

sidescanpy.viz.waterfall.resolve_waterfall_axes(steps, cli_x_axis, cli_y_axis)#

Pick the waterfall x/y axis mode for a given correction’s step set.

Corrections that include the “geometric” step always render in real-world distance (across_track x meters-in / along_track meters) rather than the caller’s chosen x/y axis — otherwise the geometric correction has no visible effect (sample-index and raw ping-count axes look identical whether or not ground/across-track ranges were computed, since only the color values change from TVG, not the pixel geometry). The caller’s axes remain in effect for corrections without “geometric” (raw, radiometric), where sample/ping/time are the only meaningful choices anyway.

sidescanpy.viz.waterfall.plot_survey_overview(ds, *, ping_stride=20, break_ping_indices=None, x_axis='sample', cmap='copper', vmin=None, vmax=None, vmin_pct=1.0, vmax_pct=99.0, gamma=1.0, show_colorbar=False, ax=None, title=None, value_var='backscatter_intensity')#

Compressed, whole-survey waterfall overview.

Strides the ping axis by ping_stride before rendering (via plot_waterfall), so a very long survey renders as one reasonably-sized image instead of one row of pixels per ping. Optionally draws a horizontal marker line + ping-number label at each index in break_ping_indices — useful for e.g. file boundaries in a multi-file concatenated survey. Nothing in SideScanSurvey/ .ss.h5 currently records per-ping source-file identity, so if you need break markers, compute the boundary ping indices yourself (e.g. while concatenating per-file datasets) and pass them in here.

Parameters:
dsxr.Dataset

Validated sidescan dataset (typically a whole survey/channel, not a pre-sliced segment).

ping_strideint, default 20

Vertical compression factor — every ping_stride-th ping is kept. Higher = more compressed. Must be >= 1.

break_ping_indiceslist[int], optional

Ping indices (in ds’s own, un-strided index space) at which to draw a break marker — e.g. where one source file ends and the next begins in a concatenated survey.

x_axis, cmap, vmin, vmax, vmin_pct, vmax_pct, gamma, show_colorbar, ax, title

Same meaning as in plot_waterfall. title defaults to a summary of the total ping count and compression factor.

Returns:
Axes

The matplotlib Axes containing the plot. The y-axis is labeled with true ping numbers (not the strided/local index), even though the underlying mesh is built from the strided data.

Raises:
ValueError

If ping_stride is not a positive integer, or (via plot_waterfall) if a required variable is missing for the chosen x_axis mode.