From 90be573e6d84266225fc46d9bb47e2eef64fae13 Mon Sep 17 00:00:00 2001 From: Ty Tuff Date: Sat, 28 Mar 2026 16:15:25 -0600 Subject: [PATCH] Clarify fire visualization architecture and transition guidance --- AGENTS.md | 15 ++++++++++ docs/api/verbs.md | 3 +- docs/dev/fire_plot_architecture.md | 45 ++++++++++++++++++++++++++++ docs/recipes/fire_event_vase_hull.md | 7 +++++ docs/viz/cube_viewer.md | 3 ++ mkdocs.yml | 1 + src/cubedynamics/verbs/fire.py | 4 ++- 7 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 docs/dev/fire_plot_architecture.md diff --git a/AGENTS.md b/AGENTS.md index fd4f967..9e5bcac 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -179,3 +179,18 @@ Docs checks: - Preserve backward compatibility unless explicitly instructed otherwise. - Add a focused regression test for every bug fix. - Use synthetic small cubes for deterministic unit tests. + +## 13) Visualization architecture and fire plot recovery plan + +The repository currently contains more than one visualization backend. Treat this as a transition state, not as permission to let them drift further apart. The custom HTML/CSS/JS cube viewer exposed through v.plot() is the canonical interactive viewer for general cube rendering. The fire-specific v.fire_plot() workflow currently still exposes a Plotly-based hull figure as its primary interactive display. Future work should move toward shared space-time semantics and clearer renderer boundaries, not ad hoc backend switching. + +When touching visualization code, separate four concerns: (1) event or cube data construction, (2) geometry generation, (3) scene or adapter packaging, and (4) rendering backend. Changes that blur those layers tend to create regressions and make migration harder. + +Implementation rules for agents: +- Do not silently replace one viewer system with another without also updating docs, tests, and architectural notes. +- If you touch axis placement, time-depth direction, cube-attached labels, or camera semantics, read `docs/dev/cube_viewer_invariants.md` first and keep those invariants aligned. +- Fire-plot work must preserve separation between event geometry generation, climate/event data fusion, and rendering backend. +- Do not claim fire_plot is fully migrated unless rendering actually runs through the custom cube-viewer path. +- Do not update screenshots/docs only while leaving contradictory code behavior. +- Do not change coordinate conventions without updating `docs/dev/cube_viewer_invariants.md` and relevant tests together. +- When in doubt, prefer an adapter layer over duplicating geometry logic in two renderers. diff --git a/docs/api/verbs.md b/docs/api/verbs.md index 66cd033..f240fb4 100644 --- a/docs/api/verbs.md +++ b/docs/api/verbs.md @@ -74,8 +74,7 @@ Plot inside/outside climate distributions for a fire event; side-effecting viewer verb. ### ``fire_plot(...)`` -High-level convenience verb that renders time-hull geometry and climate fields -as a multi-panel visualization. +High-level fire workflow that returns event/hull/summary outputs and a Plotly-based interactive hull figure (`fig_hull`). ### ``fire_panel(...)`` Compact panel combining time-hull outlines and climate histograms. diff --git a/docs/dev/fire_plot_architecture.md b/docs/dev/fire_plot_architecture.md new file mode 100644 index 0000000..13da4e9 --- /dev/null +++ b/docs/dev/fire_plot_architecture.md @@ -0,0 +1,45 @@ +# Fire plot architecture and migration path + +## 1) Purpose + +This note documents the current fire-visualization architecture and gives a safe migration path toward shared viewer semantics. + +A successful migration will not begin by swapping plotting libraries. It will begin by making the fire-event products renderer-neutral enough that the same event geometry can drive either the existing Plotly hull figure or a future custom cube-viewer scene. + +## 2) Current state + +- `v.plot()` is the canonical custom HTML/CSS/JS cube viewer for general cube rendering. +- `v.fire_plot()` currently returns a fire-event analysis bundle and uses a Plotly hull figure (`fig_hull`) as the supported interactive fire-specific display. +- Fire geometry and climate sampling logic live in backend-agnostic parts of the fire workflow, while the final figure is currently Plotly-specific. + +## 3) Stable separations of concern + +Keep these layers distinct when modifying fire visualization: + +1. Event or cube data construction +2. Geometry generation +3. Scene/adapter packaging +4. Rendering backend + +This separation enables one event product to feed multiple renderers and reduces regression risk. + +## 4) Migration strategy + +1. Make docs and interfaces honest about current backend status. +2. Factor fire-event outputs into a renderer-neutral scene description or data adapter. +3. Implement a custom-viewer renderer for that adapter. +4. Only then consider changing the default fire viewer backend. + +## 5) Anti-patterns to avoid + +- Swapping rendering libraries before adapter/data boundaries are stable. +- Duplicating geometry logic independently in multiple renderers. +- Claiming migration is complete while `v.fire_plot()` still returns a Plotly-only interactive path. +- Changing coordinate or axis conventions without updating invariants and tests together. + +## 6) Recommended next incremental PRs + +- Introduce a thin renderer-neutral adapter object for fire scene payloads (without changing current return keys). +- Add tests that validate adapter payload shape and mapping from hull/summary outputs. +- Implement an experimental custom-viewer renderer behind a non-default option. +- Compare semantic parity (axes, time-depth direction, labels, camera defaults) before any default switch. diff --git a/docs/recipes/fire_event_vase_hull.md b/docs/recipes/fire_event_vase_hull.md index 7320fd6..91b28b8 100644 --- a/docs/recipes/fire_event_vase_hull.md +++ b/docs/recipes/fire_event_vase_hull.md @@ -75,6 +75,13 @@ print("Cube:", getattr(cube, "da", None).shape if hasattr(cube, "da") else type( `fire_plot` requests daily gridMET/PRISM data for event windows. Explicitly pass `freq="D"` to emphasize daily sampling or a different frequency if needed. + +## Current viewer status + +`fire_plot` currently returns a fire-event analysis bundle plus a Plotly-based interactive hull figure. This is the supported fire-specific viewer path today. It is not yet rendered through the same custom HTML/CSS/JS viewer backend used by `v.plot()`. The long-term goal is to align fire-event visualization with the cube viewer’s shared space-time conventions so that fire-specific displays and generic cube displays live in the same visual grammar. + +Developer note: `If you are working on fire visualization internals, treat event construction, hull generation, climate/event fusion, and rendering as separable layers. The safest near-term improvements are the ones that preserve those boundaries.` + ## What you get back `v.fire_plot` returns a dictionary with: diff --git a/docs/viz/cube_viewer.md b/docs/viz/cube_viewer.md index aeddd14..8f4fa3d 100644 --- a/docs/viz/cube_viewer.md +++ b/docs/viz/cube_viewer.md @@ -4,6 +4,9 @@ The cube viewer turns a 3D climate cube into an interactive HTML scene. Call `v.plot()` on an `xarray.DataArray` with dims like `(time, y, x)` to render the cube inline in Jupyter or export standalone HTML. + +> **Transition note:** `v.plot()` is the canonical custom viewer for general cubes. Some specialized visualization workflows may still expose separate rendering backends during the transition period (including the current fire hull path in `v.fire_plot()`). The intended direction is convergence on shared spatial and temporal conventions, not necessarily immediate backend unification. + The viewer is designed to: - show temporal slices along one axis and spatial slices on the other faces; diff --git a/mkdocs.yml b/mkdocs.yml index bca946b..0ad25f4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -53,6 +53,7 @@ nav: - Contributing: dev/contributing.md - CI and Testing: dev/ci_testing.md - Cube viewer invariants: dev/cube_viewer_invariants.md + - Fire plot architecture: dev/fire_plot_architecture.md - Figure backend (v.plot): dev/figure_backend.md - Viewer backend: dev/viewer_backend.md - Legacy reference: dev/legacy_reference.md diff --git a/src/cubedynamics/verbs/fire.py b/src/cubedynamics/verbs/fire.py index b988be7..eb1fd4f 100644 --- a/src/cubedynamics/verbs/fire.py +++ b/src/cubedynamics/verbs/fire.py @@ -47,9 +47,11 @@ def fire_plot( allow_synthetic: bool = False, prefer_streaming: bool = True, ) -> Dict[str, Any]: - """Fire time-hull + climate visualization verb. + """Fire time-hull + climate visualization workflow. Supports cube-first (preferred) and legacy fire-first invocation styles. + Returns a fire analysis bundle and a Plotly hull figure (`fig_hull`) as the + current interactive backend for fire-specific visualization. """ cube_first = da is not None