Skip to content

Add layer masking, profile tool, theme toggle, buffer visualization, and prepare-disp-s1 fixes#23

Open
mgovorcin wants to merge 4 commits intoopera-adt:mainfrom
mgovorcin:main
Open

Add layer masking, profile tool, theme toggle, buffer visualization, and prepare-disp-s1 fixes#23
mgovorcin wants to merge 4 commits intoopera-adt:mainfrom
mgovorcin:main

Conversation

@mgovorcin
Copy link
Copy Markdown

@mgovorcin mgovorcin commented Apr 9, 2026

Summary

New map tools

  • MeasureTool: click-to-measure polyline with cumulative distance display
  • ProfileTool: draw a line on the map, extract raster values along it; draggable vertices; radius (m) input samples a buffer — chart shows bold median + faint random sample lines; orange corridor polygon drawn on map
  • RefPointChart: floating chart of all pixels within the reference-point buffer (median + random samples ± 1σ fill)
  • Histogram: value-distribution for the current time step with p2/p98 and p16/p84 markers; ±0 centering button

Sidebar / UI additions

  • Point-picking, re-referencing, and reference-buffer ON/OFF toggles
  • Reference Buffer: radius slider; median within buffer used for tile shift and time-series re-referencing
  • Layer masking: flexible multi-mask UI — pick any loaded dataset, choose ≥ or ≤ mode, set threshold in real data units (p2–p98 range fetched from /dataset_range); replaces fixed coherence/similarity/residual sliders
  • Dark/light theme toggle: all chart colours, panel backgrounds, and mouse-position control use CSS custom properties; useThemeVersion() MutationObserver hook rebuilds Chart.js options on switch
  • Colormap persistence per dataset in localStorage
  • Radius circles: dashed L.circle rings around TS points and reference marker when buffer is active

Backend

  • /profile: new radius / n_random params; returns {centre, median, samples} for buffer mode
  • /dataset_range/{dataset_name}: min/max/p2/p98 for mask threshold UI
  • Generic layer_masks list replaces fixed masking params across tile and time-series endpoints; thresholds are absolute data-unit values
  • Per-variable data-range cache to avoid repeated nanmin/nanmax on every tile request
  • Reference buffer median re-referencing in both MD and COG modes
  • readers.py: patch rasterio dtype_fwd for GDAL 3.12 Float16 (type code 15) at import time
  • utils.py: register cfastie/rplumbo/schwarzwald _r reversed variants into rio_tiler.cmap.data before titiler imports — fixes 422 when invert toggle is active

prepare-disp-s1 CLI

  • S3 path fix: Path.resolve() on s3:// mangled the double-slash so /vsis3/ mapping never matched; S3 inputs now mapped directly without resolve()TODO: verify with a real S3 file that AWS env vars (AWS_PROFILE, AWS_DEFAULT_REGION) are set
  • Force Float32 in gdal.Translate — Float64 VRTs break PNG tile rendering in titiler
  • Inline gdal.BuildOverviews() replacing removed add_overviews() helper
  • VRT glob results use .resolve() for absolute paths (portable across working dirs)
  • CLI accepts directories as input and globs *.nc inside them
  • New prepare-amplitude command: SLC complex GeoTIFF → 20·log10(|z|) Cloud-Optimised GeoTIFF

Test plan

  • Toggle dark/light theme — chart axes, legend labels, panel backgrounds all switch
  • Draw a profile line, set radius > 0 — corridor polygon on map, median + sample lines in chart
  • Enable point/ref buffer — dashed radius circles appear and follow marker drag
  • Select cfastie/schwarzwald/rplumbo with invert active — tiles render (no 422)
  • Add a layer mask — slider range matches actual data values; masking visible on map
  • prepare-disp-s1 with S3 NetCDF — /vsis3/ VRT created correctly
image

Custom masking on-the-fly
image

mgovorcin and others added 4 commits April 2, 2026 19:36
…setup-dolphin fixes

## GUI changes

### New components
- **MeasureTool**: click-to-measure polyline tool on the map with cumulative
  distance display; toggled from the sidebar footer.
- **ProfileTool**: draw a line/polyline on the map and extract a raster value
  profile along it; persistent line while the button is active; draggable
  vertex adjustment; profile chart shown/hidden from the sidebar footer.
- **RefPointChart**: floating chart showing time series of all pixels within
  the reference-point buffer (median + random samples ± 1σ fill); labels
  match the main time-series x-axis timestamps.
- **Histogram**: value-distribution histogram for the current time step,
  shown in the sidebar under "Value Distribution".

### Sidebar additions
- **Point Picking ON/OFF** pill (footer) — disables map-click point picking
  to prevent conflicts with Measure/Profile tools.
- **Re-referencing ON/OFF** pill (footer) — enables/disables spatial
  re-referencing for all datasets and charts.
- **Show/Hide Profile** button (footer) — toggles the profile chart panel.
- **Show/Hide Ref Buffer Chart** button (footer, visible when buffer is ON).
- **Reference Buffer** section — ON/OFF toggle + radius slider; when ON the
  median within the radius is used for re-referencing instead of a single
  pixel; updates tile shift and time-series simultaneously.
- **Layer Masking** section — replaces fixed coherence/phase-similarity/
  inversion-residual sliders with a flexible multi-mask UI: pick any loaded
  raster group, choose ≥ or ≤ mode, set a 0–1 normalised threshold (scaled
  server-side to the layer's actual data range); add/remove multiple masks
  that are combined with AND logic; custom GeoTIFF upload preserved.
- **Colormap panel** — added Grays and Jet options; colormap now persists
  per-dataset in localStorage and is restored on dataset switch.
- **Value Distribution** section — inline histogram with p2/p98 and p16/p84
  percentile markers.

### Time-series chart improvements
- Multi-point time series with per-point colour-coded lines.
- Legend label colour changed to white for readability.
- Masking thresholds (layer masks) applied to all API calls.
- Reference buffer radius passed to /multi_point for median re-referencing.
- Trend lines and residuals toggleable.

### Map display
- Tile shift (re-referencing) uses buffer median when Reference Buffer is ON.
- Ref values re-fetched automatically when buffer toggle or radius changes,
  and on ref-marker drag-end.
- Layer masks sent as JSON to both COG and MD tile endpoints.

## Backend masking
- Replace fixed coherence/phase-similarity/inversion-residual params with a
  generic layer_masks list [{dataset, threshold, mode}] in /multi_point,
  /buffer_timeseries, InputDependency (COG tiles), XarrayPathDependency (MD).
- Threshold normalised 0–1 and scaled to each layer's actual data range;
  per-variable range cached at startup to avoid repeated nanmin/nanmax.

## Reference buffer re-referencing
- _get_ref_median(): computes nanmedian within circular buffer in MD mode;
  falls back to single pixel when buffer_m=0 or COG mode.
- Tile shift and time-series both use buffer median when buffer is ON.
- Buffer median re-aligned to full-length index array (NaN for missing steps).

## Float16 / GDAL type-15 support (readers.py)
- RasterReader.from_file: catches KeyError when rasterio does not recognise
  the GDAL dtype (Float16 = type 15, new in GDAL 3.7+); falls back to GDAL
  directly for shape/transform/nodata, treats dtype as float32.
- RasterReader.bounds: same fallback using rasterio.transform.array_bounds.

## setup-dolphin fixes (cli.py)
- _glob() validates each file is openable (skips truly unreadable files,
  includes Float16 files via KeyError catch).
- _glob_first() tries alternate glob patterns in order.
- velocity and Filtered velocity use _glob() instead of bare string literals.
- Groups with empty file_list silently skipped before RasterGroup().
- Temporal coherence and Phase cosine similarity fall back to broader globs
  to handle date-range-suffixed filenames (e.g. similarity_20251025_20260117).

## prepare_amplitude CLI command
- New bowser prepare-amplitude command: reads complex SLC GeoTIFFs, computes
  20·log10(|z|), writes Cloud-Optimised GeoTIFF (float32, DEFLATE, 512×512).
- -m/--mask option: pre-loads combined_mask.tif once, applies per window.
- -j/--workers option (default 4): parallel processing via ThreadPoolExecutor.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…ute thresholds, custom colormaps

- ProfileTool: remove redundant hide button; add radius (m) input with buffer
  corridor polygon on map; backend /profile returns centre/median/samples when
  radius > 0; chart renders median (bold) + random sample lines (faint)
- MapContainer: RadiusCircles component draws dashed L.circle around TS points
  (bufferRadius) and reference marker (refBufferRadius) when enabled
- Theme-aware charts: useThemeVersion() MutationObserver hook triggers useMemo
  rebuild of chartOptions on data-theme toggle; chart/profile panel backgrounds
  use var(--sb-surface) instead of hardcoded dark rgba
- Colormaps: register cfastie_r / schwarzwald_r / rplumbo_r into rio_tiler's
  cmap.data *before* titiler imports so Literal validation accepts _r variants;
  fixes 422 when selecting these colormaps with inverted toggle active
- Layer masks: threshold is now absolute (real data units); /dataset_range
  endpoint returns min/max/p2/p98; slider range and number input show actual
  values; backend _apply_layer_masks_md and InputDependency pass threshold
  directly without _scale_threshold normalization
- Histogram: ±0 centering button (symmetric around zero)
- CSS: mouseposition uses var(--sb-surface) + border for light theme;
  profile-panel uses var(--sb-surface); profile-radius-input styles added

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
… dir input

- _prepare_utils.py: fix S3 path bug — Path.resolve() on s3:// mangles the
  double-slash (e.g. s3://bucket → /cwd/s3:/bucket), so the subsequent
  .replace('s3://', '/vsis3/') never matched. Now detect s3:// first and
  map directly to /vsis3/ without calling resolve(); local paths still go
  through resolve() for portability.
  TODO: verify /vsis3/ access works with the current AWS credentials/env when
  input NetCDF files live in S3 — boto3/GDAL env vars (AWS_PROFILE,
  AWS_DEFAULT_REGION) must be set before calling gdal.Translate on /vsis3/ paths.
- _prepare_utils.py: force Float32 output in gdal.Translate — Float64 VRTs
  cause titiler to fail PNG tile rendering
- _prepare_utils.py: inline gdal.BuildOverviews() replacing removed
  add_overviews() helper import
- _prepare_disp_s1.py: use .resolve() on glob results so VRT paths are
  absolute (portable when bowser launched from a different cwd)
- cli.py: prepare-disp-s1 accepts directories as input; globs *.nc inside them

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@mgovorcin mgovorcin requested a review from scottstanie April 9, 2026 07:10
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.

1 participant