Skip to content

HydroPlot: rating workshop, dynamic metrics, climate/SPI fixes, mobile UX#2

Open
abstractionisms wants to merge 65 commits into
mainfrom
feature/hydroplot-groundwater-reach-validation
Open

HydroPlot: rating workshop, dynamic metrics, climate/SPI fixes, mobile UX#2
abstractionisms wants to merge 65 commits into
mainfrom
feature/hydroplot-groundwater-reach-validation

Conversation

@abstractionisms

Copy link
Copy Markdown
Owner

Summary

Ships a large HydroPlot dashboard upgrade: more reliable climate/SPI, better rating curves, automated plot narrative, site-specific metric relevance, an interactive stage–discharge workshop, and mobile-friendly tile help / layout.

Highlights

  • Climate / SPI: Open-Meteo + multi-station Meteostat fallback when single stations are dead
  • FDC / hydrograph axes: data-driven linear vs log scaling
  • Rating curve: offset power-law selection, seasonal points, interactive A/B/H₀ workshop with live R²/RMSE/NSE
  • Interpretation: post-plot automated analysis text; Q10/Q50/Q90/mean relevance driven by each gage’s hydrology
  • UX layout: duration stats (Q10/Q50/Q90) sit with the FDC; record length stays in the header strip
  • Tiles: hover (desktop) / tap (mobile) help popups on insight + readiness cards
  • Mobile: stack columns under 768px, tips open below cards, touch-friendly targets

Test plan

  • Unit tests: interpretation, stage_discharge, visual shell CSS tokens
  • Streamlit Single Analysis on a stage gage (e.g. 14018500): hydrograph, FDC + duration stats, rating workshop
  • SPI/climate loads without hard failure on sparse stations
  • Phone / narrow browser: tiles tap for tips, rating workshop stacks, charts usable
  • Resolve any merge conflicts with current main if CI reports them

Notes

Deployed/smoked on Pi (:8501) during development; branch tip 253300d.

…sh, and reduced-motion support

- Extended custom CSS with @Keyframes (fadeInUp, cardPop, subtlePulse) and enhanced transitions on .workspace-panel, .action-card, .plot-card, .insight-card, buttons, nav, etc.
- Added prefers-reduced-motion guard and stronger interactive feedback.
- Lightly wrapped Reach Analysis summary + Baseflow sections and Overview regional conditions using existing render_workspace_panel for consistent motion.
- Added apply_hydro_theme() helper (wired into baseflow waterfall) for cohesive Plotly styling.
- Extended visual shell test with motion assertions.
- References modern animated web UI patterns from https://x.com/twetsfyp/status/2065283731833651709

This elevates the visual frontend while preserving all existing behavior, reach logic, and responsive design.

Builds on prior visual UX upgrade and map-centered reach redesign.
…ronger lifts/scales, pulsing primary CTA button (the 'Run Analysis' button now has a repeating subtle teal glow so it's obvious the new animations are active)
Refine Streamlit CSS injection and design system. Prefer Meteostat for SPI precip, skip Daymet without Earthdata credentials, extend SPI climate window, and improve per-site readiness messaging.
Stop forcing a flat log scale. Use linear when discharge spans a moderate range, and clamp log range to the data envelope when multi-order behavior is real.
For sites like 14018500, simple Q=A*H^B fails (negative R2). Prefer Q=A*(H-H0)^B when better, and color stage-discharge points by season.
Nearest Meteostat stations can be historical-only (e.g. Walla Walla ends 1988), leaving sites like 14018500 with no climate. Prefer Open-Meteo archive, then multi-station Meteostat with coverage filtering.
Add plain-language narrative for interactive charts and Guided Plot Builder output: flow duration, seasons, climate, rating curve, with markdown download.
Add Q10/Q50/Q90 metrics with tooltips, expander explaining why each metric matters, and a Metric relevance section in the automated post-plot narrative.
Tooltips, expander table, and post-plot narrative now use
compute_hydrologic_profile (regime, Q10/Q50/Q90, seasons, rating, climate)
instead of static catalog blurbs. Falls back to catalog when no discharge.
Live Plotly rating curve with A/B/H0 sliders, auto-fit reference,
season/year point coloring, residual pane, and live R2/RMSE/NSE/bias.
Adds evaluate_rating_params helper and Pi Streamlit restart script.
HTML insight/readiness tiles show i-popups on hover. Q10/Q50/Q90 and
mean/peak sit with the flow-duration section instead of the page top;
record length stays in the header strip.
Stack Streamlit columns under 768px, open tile tips below cards on
narrow screens, support tap/focus for help popups on touch devices,
and keep Plotly charts usable on phones.
main added Open-Meteo and dynamic climate metadata; this branch already
had Open-Meteo-first + multi-station Meteostat + richer cached results.
Keep branch climate implementation; record merge with main.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 253300d807

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


b1, b2 = st.columns(2)
with b1:
if st.button("↩ Auto-fit", key=f"{state_key}_reset", use_container_width=True):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Replace the stale button width argument

This new button is the only remaining use_container_width use under hydrology, while the commit adds tests/test_streamlit_cloud_compat.py asserting that no hydrology file contains that argument. Any CI run including that test fails even though the app otherwise standardizes on width="stretch"; use the supported width argument here as well.

Useful? React with 👍 / 👎.

Comment thread scripts/run_case_study.py
site_ids = config.get("site_ids", [])
if not site_ids:
return None
df = fetch_discharge_data(str(site_ids[0]), config.get("start_date"), config.get("end_date"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle reach-case site mappings in the case runner

The new docs/cases/spokane_reach_gain_loss/case.yml defines site_ids as a mapping with upstream and downstream, but this loader unconditionally indexes site_ids[0]. Running the advertised case study with python scripts/run_case_study.py docs/cases/spokane_reach_gain_loss/case.yml therefore raises KeyError: 0 before producing any summary; branch on dict-shaped reach configs or validate them explicitly.

Useful? React with 👍 / 👎.

Comment thread hydrology/data/climate.py
Comment on lines +91 to +92
if usable < 30:
return None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Allow complete short Meteostat windows

This absolute usable < 30 cutoff rejects valid short Meteostat requests: a complete 7- or 14-day climate window has fewer than 30 daily values, so fetch_climate_data() returns None despite full coverage. That regresses short analysis periods, especially whenever Open-Meteo is unavailable and the app/public API falls back to Meteostat; compare against the requested window length or a coverage ratio instead.

Useful? React with 👍 / 👎.

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