Skip to content

camp#142: per-layer colormap range override (PR1 — backend + numeric UI)#147

Merged
rolker merged 10 commits into
jazzyfrom
feature/issue-142
Jun 29, 2026
Merged

camp#142: per-layer colormap range override (PR1 — backend + numeric UI)#147
rolker merged 10 commits into
jazzyfrom
feature/issue-142

Conversation

@rolker

@rolker rolker commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Summary

PR1 of 2 for #142 — the backend + numeric UI for a per-layer colormap
range override. Lets an operator pin a manual colormap range when an outlier
skews the auto-range (the motivating case: backscatter band 2 with
Max=925 / Mean=0.16 collapses the auto colormap).

This is Part of #142; the issue stays open until PR2 lands the interactive
marine_colormap_widgets::ColormapLegendWidget (draggable colorbar).

What it does

  • Adds a marine_colormap::RangeModel range_model_ (Auto/Manual) to
    GggsTileLayer, RasterLayer, and SonarLiveCacheLayer; renders from
    range_model_.lo()/hi() and folds auto extents via update_auto() (a no-op
    while Manual, so outliers can't re-widen a pinned range).
  • Public API: setRangeOverride(lo, hi), resetRangeToAuto(), rangeMode().
  • Context-menu "Colormap range" submenu: Set range… (lo/hi numeric
    prompts, pre-filled with the current resolved range) + Reset to auto.
    Scalar layers only.
  • Persists range_mode/range_min/range_max per layer (under the key each
    layer's read/writeSettings already use — settingsKey() for GGGS/live,
    itemID() for raster).
  • New GL-free test/test_range_persist.cpp covering all three layers
    (default → override → reset, and manual/auto persistence round-trips).

Review fixes folded in (local review-code, 0 must-fix)

  • Restore honors Manual only when both extents are present, not just on
    range_mode=="manual" — a partial/corrupt entry falls back to Auto rather
    than snapping to the [0,1] read-defaults.
  • "Set range…" dialog decimals 4 → 6 so a pre-filled range (e.g. -73.2153 dB)
    isn't quantized on re-open.
  • *AutoRoundTrips tests now assert the restored extents, not just the mode.

Test

Host build clean; 151 tests, 0 errors, 0 failures, 1 skipped
(container can't build camp's lower-layer deps; host-verified).


Authored-By: Claude Code Agent
Model: Claude Opus 4.8

Claude Code Agent and others added 10 commits June 29, 2026 06:37
PR1: range-override backend via marine_colormap::RangeModel + numeric context-menu UI + persist/restore across all three raster layer types
Part of #142 (PR1). Add an operator-settable colormap range to each of the
three raster layers so an outlier band (e.g. backscatter max 925, mean 0.16)
no longer collapses the useful colour range under auto-scaling.

Each of GggsTileLayer, SonarLiveCacheLayer and RasterLayer now owns a
marine_colormap::RangeModel. renderImage() feeds range_model_.lo()/hi() into
the shared RasterGlRenderer's u_min/u_max instead of the raw data_min_/
data_max_. In Auto mode the model tracks the folded data extents
(update_auto() after each auto-range fold: tilesReady / foldAutoRange /
imageReady); in Manual mode it returns the operator override, untouched by
incoming data. The override is applied at render time and is transparent to
the auto-range accumulation (camp#138 coordination noted at each update_auto
call site).

Public API per layer: setRangeOverride(lo, hi) -> Manual + persist + re-render,
resetRangeToAuto() -> Auto, rangeMode()/rangeLo()/rangeHi() accessors. A
"Colormap range" context submenu ("Set range..." two QInputDialog prompts
pre-filled with the current range; "Reset to auto") is gated on scalar, the
same condition as the colormap submenu. Range mode + bounds persist per layer
(range_mode / range_min / range_max) under each layer's existing settings
group — settingsKey() for the two tile layers, itemID() for RasterLayer.

Because a marine_colormap type now appears in camp_map's public headers, link
marine_colormap PUBLIC on camp_map (was PRIVATE under camp#141) so the include
dir + symbols propagate to consumers (camp_map_ros, the executable, tests).

GL-free tests in test/test_range_persist.cpp cover all three layers: default
Auto, setRangeOverride -> Manual + lo/hi, Manual persist/restore round-trip,
Auto persist/restore, reset -> Auto.

Uncertainty-band auto-default is deferred to camp#145 (needs band semantics,
camp#104); PR1 delivers only the mechanism.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three minor review findings from the local review-code pass:

- Restore only honors a Manual range when both extents are present, not
  just when range_mode=="manual" — a partial/corrupt settings entry falls
  back to Auto rather than snapping to the [0,1] read-defaults
  (gggs_tile_layer, raster_layer, sonar_live_cache_layer).
- Raise the "Set range…" QInputDialog decimals 4 -> 6 so a pre-filled
  range (e.g. -73.2153 dB) is not quantized when re-opened.
- *AutoRoundTrips tests now assert the restored extents (0,1 default),
  not just rangeMode()==Auto, locking in that an Auto round-trip never
  pins a manual override.

Host build clean; 151 tests, 0 failures, 1 skipped.
Copilot AI review requested due to automatic review settings June 29, 2026 22:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@rolker rolker merged commit b6c33dc into jazzy Jun 29, 2026
1 check failed
@rolker rolker deleted the feature/issue-142 branch June 29, 2026 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants