WEPPcloud

← Back to usersum index

SBS Controls Behavior Documentation

Date: October 25, 2025
Context: BAER/Disturbed SBS upload and uniform generation controls

Overview

The SBS (Soil Burn Severity) controls coordinate the Disturbed, Baer, and Map controllers so users can upload a custom raster or generate a uniform severity map while keeping the Leaflet overlay and summary panel in sync.

Mode System

Two Modes (Persisted)

  1. Upload Mode (sbs_mode = 0): Upload custom .tif or .img raster
  2. Uniform Mode (sbs_mode = 1): Generate uniform low/moderate/high severity raster (uniform_severity stores the chosen level)

File Structure

Frontend

  • Controller: wepppy/weppcloud/controllers_js/disturbed.js

    • Handles upload, uniform generation, removal
    • Syncs with baer.js controller for map display
    • Manages "Current SBS map" filename display
  • Template: wepppy/weppcloud/templates/controls/disturbed_sbs_pure.htm

    • Two control sections: #sbs_mode0_controls (upload), #sbs_mode1_controls (uniform)
    • Radio buttons to switch modes (persisted via sbs_mode)
    • Summary panel (#info) is filled by the BAER controller via load_modify_class()
  • Summary Template: wepppy/weppcloud/templates/mods/baer/classify.htm

    • Rendered by view/modify_burn_class
    • Injected into the SBS summary panel after uploads or uniform builds
    • Shows the active uniform severity when sbs_mode is 1
  • Map Controller: wepppy/weppcloud/controllers_js/map.js

    • Provides MapController.getInstance() which Disturbed/Baer use to add or remove the "Burn Severity Map" overlay
    • Keeps the Leaflet control (map.ctrls) in sync to avoid duplicate or orphaned legend entries

Backend

  • Routes: wepppy/weppcloud/routes/nodb_api/disturbed_bp.py

    • task_upload_sbs: Upload and validate raster
    • task_build_uniform_sbs: Generate uniform severity raster
    • task_remove_sbs: Remove SBS raster
    • Upload/uniform responses include { Content: { disturbed_fn: ... } } (no HTML payload today)
    • view/modify_burn_class: Returns HTML summary used in the SBS panel
  • NoDb: wepppy/nodb/mods/baer/baer.py and wepppy/nodb/mods/disturbed/disturbed.py

    • Stores: baer_fn (filename), has_map (boolean), sbs_mode, uniform_severity

Tested Behaviors

✅ Upload Mode

  1. Initial state: No SBS, Upload mode selected by default
  2. File selection triggers auto-upload: No separate "Upload" button
  3. Success:
    • Map appears on Leaflet with "Burn Severity Map" layer
    • "Current SBS map" display shows filename
  4. Remove button: Removes map layer and legend; filename display currently remains populated

✅ Uniform Mode

  1. Switch to Uniform mode: Radio button hides upload controls, shows 4 buttons
  2. Four buttons (all same 240px width):
    • Use Uniform Low SBS
    • Use Uniform Moderate SBS
    • Use Uniform High SBS
    • Remove SBS
  3. Success:
    • Map appears on Leaflet with "Burn Severity Map" layer
    • BAER summary panel calls out the selected uniform severity
  4. Remove button: Same behavior as upload mode (map + legend cleared, filename display persists)

✅ Re-upload / Regenerate

  1. Multiple uploads: Old layer removed before new one added (no accumulation)
  2. Multiple uniform generations: Same behavior, replaces existing
  3. Switch modes: Can upload, then generate uniform, or vice versa - last one wins

✅ Reload Behavior

  1. After upload: Page reloads → Upload mode selected with filename restored
  2. After uniform: Page reloads → Uniform mode selected with BAER summary showing the stored severity
  3. Bootstrap: disturbed.bootstrap() calls baer.bootstrap() which calls baer.show_sbs() to render map

Bootstrap & State Restoration

  1. Run bootstrap JSON injects controllers.disturbed/controllers.baer with mode and uniformSeverity (run_page_bootstrap.js.j2).
  2. Disturbed.bootstrap(ctx) seeds the cached has_sbs flag, applies the controller context (radio buttons + cached severity), and replays Baer.bootstrap(ctx) when an SBS exists.
  3. Baer.bootstrap binds event listeners and issues an initial show_sbs() / load_modify_class() so map overlays and summary content match the persisted state.

Summary Refresh Flow

  1. Upload/uniform build responses trigger disturbed:uniform:completed / SBS_UPLOAD_TASK_COMPLETE.
  2. Disturbed schedules baer.show_sbs() + baer.load_modify_class() to redraw the map overlay and re-render mods/baer/classify.htm.
  3. The template highlights the active uniform severity (when sbs_mode == 1), keeping the info panel aligned with backend state.

Event Flow

Upload Flow

1. User selects file → auto-upload triggered
2. disturbed.uploadSbs()
   - Clear hints
   - POST /tasks/upload-sbs with FormData (use `/rq-engine/api` via `url_for_run(..., { prefix: "/rq-engine/api" })`)
3. Backend validates, saves to baer_dir
4. Response: { result: { disturbed_fn: "..." } }
5. Frontend:
   - Updates "Current SBS map" display
   - Triggers SBS_UPLOAD_TASK_COMPLETE event
   - Calls baer.show_sbs() to render map
   - Calls baer.load_modify_class() to refresh the summary/classification panel

Uniform Flow

1. User clicks "Use Uniform [Low|Moderate|High] SBS"
2. disturbed.buildUniformSbs(severity)
   - Clear hints
   - POST /tasks/build_uniform_sbs with {value: severity}
3. Backend generates uniform raster
4. Response: { result: { disturbed_fn: "..." } }
5. Frontend: (same as upload flow with BAER summary reflecting uniform severity)

Remove Flow

1. User clicks "Remove SBS" (in either mode)
2. disturbed.removeSbs()
   - POST /tasks/remove_sbs
3. Backend deletes raster file
4. Response: {}
5. Frontend:
   - Removes map layer directly via MapController
   - Removes layer from control
   - Clears SBS legend
   - Clears the SBS summary panel (`infoAdapter.html("")`)
   - Leaves "Current SBS map" display populated (needs follow-up if we want clearing)
   - Mode selection remains unchanged
   - Updates has_sbs flag

Cross-Controller Communication

Disturbed ↔ Baer

  • Two separate forms: #sbs_upload_form (Disturbed) and #baer_form (Baer)
  • Event bridge: Disturbed emits SBS_UPLOAD_TASK_COMPLETE / SBS_REMOVE_TASK_COMPLETE; Baer listens and re-renders the summary panel via load_modify_class().
  • Direct calls: Disturbed invokes baer.show_sbs()/load_modify_class() to refresh the overlay and classification UI after uploads or uniform builds.
  • Timing guard: A 100 ms setTimeout ensures the Baer form has mounted before dispatching map refresh calls.

Map Controller Integration

  • Overlay lifecycle: Disturbed and Baer both call MapController.getInstance(); when unavailable the code guards with try/catch so backend state still updates.
  • Legend hygiene: baer.show_sbs() clears existing "Burn Severity Map" entries from both the map and control before adding the new overlay to prevent duplicates.
  • Removal path: Disturbed explicitly removes the overlay and legend during remove_sbs so the UI immediately reflects the cleared state.

Cross-Controller Communication

Disturbed ↔ Baer

  • Two separate forms: #sbs_upload_form (disturbed) and #baer_form (baer)
  • Communication: Via events and direct method calls
    • disturbed.triggerEvent('SBS_UPLOAD_TASK_COMPLETE', data)
    • Direct calls: baer.show_sbs(), baer.load_modify_class()
  • Timing: 100ms setTimeout to ensure baer form is ready

Map Layer Management

  • Layer name: "Burn Severity Map"
  • Cleanup: Must remove both from map (map.removeLayer) and control (map.ctrls.removeLayer)
  • Orphaned layers: baer.showSbs() checks for existing layer and removes before adding new
  • Legend: Separate element #sbs_legend, must be cleared on remove

CSS Styling

Button Widths

#sbs_mode1_controls .wc-button-row {
  margin-bottom: var(--wc-space-md);
}

#sbs_mode1_controls .wc-button-row .pure-button {
  min-width: 240px;  /* Ensures all 4 buttons same width */
  justify-content: center;
}

Table Formatting (Classification UI)

.wc-baer-classify__table--breaks {
  max-width: 600px;
}

.wc-text-right {
  text-align: right;
}

.wc-text-bold {
  font-weight: bold;
}

Testing Checklist

Upload Mode

  • File selection auto-triggers upload
  • Success: Map appears with correct bounds
  • Success: "Current SBS map" displays filename
  • Summary panel renders BAER classification content
  • Error: Error message shown in Status panel
  • Re-upload: Old layer removed, new one appears
  • Remove: Map and legend disappear; filename display stays populated

Uniform Mode

  • All 4 buttons same width (240px)
  • Low/Moderate/High generate different files
  • Success: Map appears with correct bounds
  • Multiple generations: No layer accumulation
  • Summary panel updates to reflect uniform severity controls
  • Remove: Map disappears, legend clears, mode/filename remain

Reload Scenarios

  • After upload: Map reappears via bootstrap
  • After uniform: Map reappears via bootstrap
  • Mode selector reflects persisted sbs_mode
  • Summary content matches persisted state

Cross-Browser

  • Safari (macOS)
  • Chrome
  • Firefox

Frontend

  • wepppy/weppcloud/controllers_js/disturbed.js
  • wepppy/weppcloud/controllers_js/baer.js
  • wepppy/weppcloud/templates/controls/disturbed_sbs_pure.htm
  • wepppy/weppcloud/templates/mods/baer/classify.htm
  • wepppy/weppcloud/static/css/ui-foundation.css

Backend

  • wepppy/weppcloud/routes/nodb_api/disturbed_bp.py
  • wepppy/nodb/mods/baer/baer.py
  • wepppy/nodb/mods/disturbed/disturbed.py
  • wepppy/nodb/mods/baer/baer.pyi

Documentation

  • wepppy/weppcloud/controllers_js/README.md
  • wepppy/AGENTS.md
  • docs/dev-notes/sbs_controls_behavior.md (this file)

Changelog

October 25, 2025

  • ✅ Fixed duplicate "Burn Severity Map" entries on reload
  • ✅ Fixed form value capture bug (read before startTask clears)
  • ✅ Removed Upload SBS button, added auto-upload on file select
  • ✅ Fixed layer accumulation on re-upload
  • ✅ Fixed filename display update after upload
  • ✅ Fixed remove functionality (map + legend)
  • ✅ Made uniform buttons consistent width (240px)
  • ✅ Persists both the sbs_mode and uniform_severity for reload
  • ✅ classify.htm is sbs_mode aware