sidescanpy.export.orientation#

Display orientation for exported windows, and a display-only range detrend.

Every exported image is oriented to one display convention: pings run bottom-to-top (the newest ping at the top, matching EdgeTech Discover’s target thumbnails), and a single port channel is mirrored so near range sits next to nadir on the same side as the starboard view’s mirror image. Each function moves the annotated target positions (Target.sample = column, extra_attributes["window_row"] = row) together with the pixels.

2026 rshomberg@uri.edu

Contents

detrend_by_range

Subtract each column's median across all pings (display only).

orient_for_display

Orient a decoded target window to the export display convention.

orient_pixel_window

Orient a sample/ping-space export window and every target in it.

flip_geo_vertical

Reverse the along-track axis of a geometric window.

orient_geo_window

Orient a geometric (along/across meters) window and its targets.

sidescanpy.export.orientation.detrend_by_range(window)#

Subtract each column’s median across all pings (display only).

A flat-field-style correction: removes the typical level at each range so only deviations from it (targets, local texture) remain visible. It hides a left-to-right brightness gradient, such as a residual left by an imperfect TVG model, without correcting it – not physically grounded and not a substitute for radiometric correction.

Parameters:
windownp.ndarray

(n_pings, n_samples) array, sample axis last.

Returns:
np.ndarray

Same shape, centered near 0 rather than in the input units; render with percentile-based limits, not a fixed absolute scale.

sidescanpy.export.orientation.orient_for_display(window, target)#

Orient a decoded target window to the export display convention.

Both flips match EdgeTech Discover’s own target images (established by visual comparison, not from vendor documentation):

  • Vertical (always): decoded rows run in ascending ping order; the ping axis is reversed so the newest ping is at the top.

  • Horizontal (port only): a port window (target.channel == 0) is mirrored along the sample axis, matching the waterfall sign convention (port negative, starboard positive).

Parameters:
windownp.ndarray

(n_pings, n_samples) decoded window, sample axis last.

targetTarget

.channel controls the horizontal flip (anything but 0 skips it). extra_attributes["window_row"] is remapped if present.

Returns:
(window, target)

Oriented window, and a copy of target with .sample and extra_attributes["window_row"] remapped to match.

sidescanpy.export.orientation.orient_pixel_window(window, targets, channel_idx, style)#

Orient a sample/ping-space export window and every target in it.

Same two conventions as orient_for_display(), applied to a window that can carry several co-located targets:

  • Vertical (always): row 0 of an extracted window is the earliest ping; the ping axis is reversed.

  • Horizontal (single port channel only): channel_idx == 0 and style != "dual-swath" mirrors the sample axis. A dual-swath window is already port-mirrored by combine_channels_mirrored().

Targets use integer pixel-center coordinates, so a flip maps x -> n - 1 - x.

Parameters:
windownp.ndarray

(n_rows, n_cols) window, rows = pings.

targetslist of Target

Window-local positions (sample = column, extra_attributes["window_row"] = row).

channel_idxint

Physical channel the window was cut from (0 = port).

stylestr

Export style ("chip", "single-swath" or "dual-swath").

Returns:
(window, targets)
sidescanpy.export.orientation.flip_geo_vertical(grid, targets, along_size_px)#

Reverse the along-track axis of a geometric window.

extract_geometric_window* build row 0 at the minimum along-track distance (earliest ping); this applies the same newest-ping-on-top convention as orient_pixel_window(). Target rows are continuous pixel-edge coordinates (see locate_point()), so a row maps to along_size_px - row.

Parameters:
gridnp.ndarray

(along_size_px, n_cols) resampled window.

targetslist of Target

Window-local positions (see orient_pixel_window()).

along_size_pxint

The grid’s row count (not its column count – they differ for a non-square grid).

Returns:
(grid, targets)
sidescanpy.export.orientation.orient_geo_window(grid, targets, size_px, *, combine, channel_idx, along_size_px=None)#

Orient a geometric (along/across meters) window and its targets.

Always applies flip_geo_vertical(). A single port channel’s window (combine=False, channel_idx == 0) is also mirrored horizontally: columns are built in ascending across_track_m, which is negative on port, so unmirrored port windows put near range on the right while starboard windows put it on the left. A combined (dual-swath) window spans both signs and already has nadir in the middle, so it is never mirrored.

The horizontal flip uses n - 1 - x on the target column, matching the long-standing export output.

Parameters:
gridnp.ndarray

Resampled window, rows = along-track.

targetslist of Target

Window-local positions.

size_pxint

Column count; also the row count unless along_size_px is given.

combinebool

Whether the window pools both channels.

channel_idxint or None

Channel of a single-channel window (None when combine).

along_size_pxint, optional

Row count, when it differs from size_px.

Returns:
(grid, targets)