sidescanpy.processing.interpolate#
Interpolate auxiliary records onto per-ping timestamps.
The converter populates per-ping fields (latitude, heading_deg, etc.) on each SideScanFrequencyChannel from the embedded values in SonarDataMessage. For many quantities those embedded values are stale — they’re the most-recent auxiliary reading at the moment the ping was recorded, not interpolated to the ping’s exact timestamp.
This module provides higher-precision per-ping values by interpolating each frequency channel’s ping times against the survey’s auxiliary records.
Aux records are themselves often sample-and-hold (each entry repeats the
latest sensor value until the sensor updates). By default
(held_values="fixes") each record is first reduced to its real fixes
with held_value_fixes(), so the
interpolated track is smooth instead of stair-stepped. When a field has no
usable aux source, the channel’s own per-ping values (also typically held)
are reduced the same way and interpolated (per_ping_fallback).
Two layers:
interpolate_aux_onto_pings(survey, ...)— top-level entrypoint. Iterates the default field-to-aux mapping (or a user override) and applies interpolation per channel.interpolate_onto_channel(channel, source, field_map, ...)— lower level. Takes any xr.Dataset with atimecoordinate as the source, enabling external data (e.g. a separately recorded GPS log) to drive per-ping field updates.
2026 rshomberg@uri.edu
Contents
frozenset() -> empty frozenset object frozenset(iterable) -> frozenset object |
|
Update per-ping fields on every frequency channel by interpolating the survey's auxiliary records onto each ping's timestamp. |
|
One frequency channel dataset's per-ping fields, interpolated from |
|
Interpolate variables from an arbitrary source dataset onto one frequency channel's ping times. |
- sidescanpy.processing.interpolate.DEFAULT_FIELD_SOURCES#
- sidescanpy.processing.interpolate.CIRCULAR_FIELDS = frozenset({'course_deg', 'heading_deg'})#
frozenset() -> empty frozenset object frozenset(iterable) -> frozenset object
Build an immutable unordered collection of unique elements.
- sidescanpy.processing.interpolate.interpolate_aux_onto_pings(survey, *, fields=None, method='linear', extrapolation='clamp', drop_invalid=True, force=False, in_place=False, held_values='fixes', max_hold_s=2.0, per_ping_fallback=True, groups=None, merge_window_s=None)#
Update per-ping fields on every frequency channel by interpolating the survey’s auxiliary records onto each ping’s timestamp.
- Parameters:
- surveySideScanSurvey
Survey to operate on.
- fieldsdict, optional
Mapping
{per_ping_field: (aux_name, aux_var)}. Overrides the default inDEFAULT_FIELD_SOURCES. Use this to interpolate only a subset of fields, or to point a field at a non-default source.- methodstr, default “linear”
Interpolation method passed to
xarray.Dataset.interp—"linear","nearest","cubic", etc.- extrapolation{“clamp”, “linear”, “nan”}, default “clamp”
Behavior when a ping’s timestamp falls outside the aux record’s time range.
"clamp"holds the boundary value;"linear"extrapolates the slope;"nan"writes NaN.- drop_invalidbool, default True
If True, drop rows where the aux source variable is NaN before interpolating. Avoids NaN propagation through the interpolated result. Set False to require the source be clean. With
held_values="fixes"NaN entries are never fixes and are always dropped.- forcebool, default False
If True, attempt interpolation even when the aux record is empty or absent and no per-ping fallback applies: the per-ping field receives NaN. If False (default), the field is left unchanged and a warning is logged.
- in_placebool, default False
If True, mutate
surveyin place and return it. If False, return a new SideScanSurvey leaving the input untouched.- held_values{“fixes”, “raw”}, default “fixes”
"fixes"reduces each aux record to its real fixes first (held_value_fixes()): many recorders log the latest GPS or attitude value at every ping or packet, and interpolating between those repeated entries keeps the stair-steps (consecutive pings stack on one position, then jump)."raw"interpolates the entries as logged (the only behavior up to 0.7.2).- max_hold_sfloat, default 2.0
With
held_values="fixes": a value unchanged for longer than this is kept flat across the hold (a stop, or a sensor dropout) rather than ramped through it. Seeheld_value_fixes().- per_ping_fallbackbool, default True
With
held_values="fixes": when a field’s aux record is absent or empty, or its variable is missing or all NaN, reduce the channel’s own per-ping values of that field (against the ping times) to fixes and interpolate those instead. Per-ping values that never repeat are returned unchanged. The fields filled this way are recorded in the history entry. No effect withheld_values="raw".- groupssequence of sequence of str, optional
With
held_values="fixes": variables that update together, passed toheld_value_fixes()for each record (by aux variable name; for the per-ping fallback, by per-ping field name). A group applies to a record only when all its variables are in it, sogroups=[POSITION_GROUP]joins latitude and longitude in the navigation record and leaves attitude alone. Default: every variable is its own group.- merge_window_sfloat or mapping of str to float, optional
With
held_values="fixes": merge changes at most this many seconds apart into one update event, for recorders that log one sensor update over consecutive entries. A float applies to every group of every record; a mapping by aux variable name (for the per-ping fallback, by per-ping field name), such as{"latitude": 0.15, "longitude": 0.15}, only to those variables’ groups. Seeheld_value_fixes(). DefaultNone: no merging.
- Returns:
- SideScanSurvey
Survey with updated per-ping fields. Each touched frequency channel gets a new processing_history entry.
- Raises:
- ValueError
If
fieldsreferences an unknown aux record name. Ifextrapolationorheld_valuesis not one of the supported values, ormax_hold_sormerge_window_sis out of range.
- sidescanpy.processing.interpolate.interpolate_aux_onto_dataset(ds, aux, *, fields=None, method='linear', extrapolation='clamp', drop_invalid=True, force=False, held_values='fixes', max_hold_s=2.0, per_ping_fallback=True, groups=None, merge_window_s=None)#
One frequency channel dataset’s per-ping fields, interpolated from
aux’s auxiliary records (the"interpolate_aux"step).Same parameters as
interpolate_aux_onto_pings(), but for a single dataset (or a ping slice of one) with the survey supplying the aux records. Always appends an"interpolate_aux"history record (with the fields actually updated, possibly none,held_values,max_hold_s,per_ping_fallback,groups,merge_window_sand the fields filled from per-ping values asper_ping_fallback_fields) so the step is not re-run.For the per-ping fallback on a ping slice, the per-ping values come from the matching whole channel in
aux(samefreq_hz_start, same times at the slice’spingcoordinates) when there is one, so a chunked run gives the same result as an unchunked one.
- sidescanpy.processing.interpolate.interpolate_onto_channel(channel, source, *, field_map, method='linear', extrapolation='clamp', drop_invalid=True, record_history=True)#
Interpolate variables from an arbitrary source dataset onto one frequency channel’s ping times.
The source entries are used as given. For a sample-and-hold source (the latest value repeated until the sensor updates), pass
held_value_fixes(source)to interpolate between real fixes.- Parameters:
- channelSideScanFrequencyChannel
Target channel.
- sourcexr.Dataset
Source dataset. Must have a
timecoordinate (datetime64-typed) and a single non-time dimension over which the variables are defined. Variables named infield_mapvalues must exist.- field_mapdict
{per_ping_field: source_var_name}.- methodstr, default “linear”
Interpolation method passed to
xarray.Dataset.interp.- extrapolation{“clamp”, “linear”, “nan”}, default “clamp”
- drop_invalidbool, default True
Drop NaN rows from each source variable before interpolating.
- record_historybool, default True
If True, append a processing_history entry to the resulting dataset. Set False when called as part of a higher-level pipeline that records history once.
- Returns:
- SideScanFrequencyChannel
New channel with updated per-ping fields. Original is not modified.