From e15481884ae734b64e0485c4cf15a1faa3619198 Mon Sep 17 00:00:00 2001 From: serversdown Date: Wed, 13 May 2026 16:13:37 +0000 Subject: [PATCH] feat(nav,stats): Events sidebar entry + 'Overall Peak' excludes false triggers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two related operator-facing improvements after the nav reorg. 1) Events as a top-level sidebar entry. The /sfm page (fleet-wide event database) was demoted to Settings → Developer in the previous reorg. Bringing it back to main nav as "Events" — operators do reach for the cross-project, sortable event list, so it earns a top-level slot. Sidebar now (7 items): Dashboard · Devices · Projects · Events · Tools · Job Planner · Settings Settings → Developer card pointing at /sfm is removed. /sfm page title/subtitle updated from "SFM Event Data" to just "Events". URL unchanged. 2) "Peak PVS" KPI tile becomes "Overall Peak" and excludes false triggers from the calculation. When operators ask "what's the biggest event at this location/unit/ project?" they mean the biggest REAL event, not the biggest sensor glitch. A single mis-flagged false trigger could otherwise dominate the tile (the 14.13 in/s spike at Loc 1 was a prime example). backend/services/sfm_events.py: - _compute_stats() skips false_trigger=True events when computing peak_pvs / peak_pvs_at / peak_pvs_serial. Continues counting them in false_trigger_count so the separate "False Triggers" tile still reflects what got filtered out. last_event unchanged (recency, not magnitude). - Same change automatically propagates to events_for_unit() and vibration_summary_for_project() — both call _compute_stats(). Templates: "Peak PVS" → "Overall Peak" in 3 KPI tile locations (vibration_location_detail.html, partials/projects/vibration_summary .html, unit_detail.html). The physical-quantity name "Peak Vector Sum" in the event-detail modal stays — that's the actual physics term, not a summary stat. Verified end-to-end: Overall Peak renders on real data; peak event false_trigger flag confirmed False. Co-Authored-By: Claude Opus 4.7 --- backend/services/sfm_events.py | 28 +++++++++++++------ templates/base.html | 11 ++++++++ .../partials/projects/vibration_summary.html | 2 +- templates/settings.html | 14 +--------- templates/sfm.html | 4 +-- templates/unit_detail.html | 2 +- templates/vibration_location_detail.html | 2 +- 7 files changed, 36 insertions(+), 27 deletions(-) diff --git a/backend/services/sfm_events.py b/backend/services/sfm_events.py index 3430266..b866818 100644 --- a/backend/services/sfm_events.py +++ b/backend/services/sfm_events.py @@ -548,7 +548,14 @@ def _empty_stats() -> dict: def _compute_stats(events: list[dict]) -> dict: - """Roll up summary stats from a merged event list. Cheap O(N) pass.""" + """Roll up summary stats from a merged event list. Cheap O(N) pass. + + The "Overall Peak" stat (peak_pvs) EXCLUDES events flagged as false + triggers — operators care about the highest REAL event, not the + biggest sensor glitch. false_trigger_count still includes them so + operators can see how many were filtered out. last_event uses + every event regardless (it's about activity recency, not magnitude). + """ if not events: return _empty_stats() @@ -559,19 +566,22 @@ def _compute_stats(events: list[dict]) -> dict: false_trigger_count = 0 for ev in events: - pvs = ev.get("peak_vector_sum") - if pvs is not None and (peak_pvs is None or pvs > peak_pvs): - peak_pvs = pvs - peak_pvs_at = ev.get("timestamp") - peak_pvs_serial = ev.get("serial") + is_false_trigger = bool(ev.get("false_trigger")) + if is_false_trigger: + false_trigger_count += 1 + + # Peak calculation: skip flagged false triggers. + if not is_false_trigger: + pvs = ev.get("peak_vector_sum") + if pvs is not None and (peak_pvs is None or pvs > peak_pvs): + peak_pvs = pvs + peak_pvs_at = ev.get("timestamp") + peak_pvs_serial = ev.get("serial") ts = ev.get("timestamp") if ts and (last_event is None or ts > last_event): last_event = ts - if ev.get("false_trigger"): - false_trigger_count += 1 - return { "event_count": len(events), "peak_pvs": peak_pvs, diff --git a/templates/base.html b/templates/base.html index cfdf4e0..d4b9ccf 100644 --- a/templates/base.html +++ b/templates/base.html @@ -134,6 +134,17 @@ Projects + {# Events — fleet-wide event database (SFM). Cross-project + sortable/filterable event list. Day-to-day event browsing + for a specific location or unit lives on those detail + pages; this is the firehose for cross-cutting queries. #} + + + + + Events + + {# Tools — operator workflow hub. Active when on /tools itself or any of the workflow pages it links into (project tidy, metadata backfill, pair devices). #} diff --git a/templates/partials/projects/vibration_summary.html b/templates/partials/projects/vibration_summary.html index fb7b1df..4197af9 100644 --- a/templates/partials/projects/vibration_summary.html +++ b/templates/partials/projects/vibration_summary.html @@ -23,7 +23,7 @@ {{ "{:,}".format(summary.total_events) }}
- Peak PVS + Overall Peak {% if summary.peak_pvs is not none %} {{ "%.4f"|format(summary.peak_pvs) }} in/s
- - + {# SFM Admin moved back to main nav as "Events" — see sidebar. #} {# Metadata Backfill + Project Tidy moved to Tools (they're operator workflows, not admin/dev surfaces). Find them diff --git a/templates/sfm.html b/templates/sfm.html index 68d4558..a9123ee 100644 --- a/templates/sfm.html +++ b/templates/sfm.html @@ -5,8 +5,8 @@ {% block content %}
-

SFM Event Data

-

Blastware ACH events forwarded by series3-watcher

+

Events

+

Fleet-wide event database. Filter by serial, date, false-trigger, or browse the units roster.

diff --git a/templates/unit_detail.html b/templates/unit_detail.html index a076499..aa39df4 100644 --- a/templates/unit_detail.html +++ b/templates/unit_detail.html @@ -313,7 +313,7 @@ outside any assignment window
- Peak PVS + Overall Peak
diff --git a/templates/vibration_location_detail.html b/templates/vibration_location_detail.html index dac19f0..452447b 100644 --- a/templates/vibration_location_detail.html +++ b/templates/vibration_location_detail.html @@ -199,7 +199,7 @@
- Peak PVS + Overall Peak