update main to v0.10.0 #48
@@ -548,7 +548,14 @@ def _empty_stats() -> dict:
|
|||||||
|
|
||||||
|
|
||||||
def _compute_stats(events: list[dict]) -> 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:
|
if not events:
|
||||||
return _empty_stats()
|
return _empty_stats()
|
||||||
|
|
||||||
@@ -559,19 +566,22 @@ def _compute_stats(events: list[dict]) -> dict:
|
|||||||
false_trigger_count = 0
|
false_trigger_count = 0
|
||||||
|
|
||||||
for ev in events:
|
for ev in events:
|
||||||
pvs = ev.get("peak_vector_sum")
|
is_false_trigger = bool(ev.get("false_trigger"))
|
||||||
if pvs is not None and (peak_pvs is None or pvs > peak_pvs):
|
if is_false_trigger:
|
||||||
peak_pvs = pvs
|
false_trigger_count += 1
|
||||||
peak_pvs_at = ev.get("timestamp")
|
|
||||||
peak_pvs_serial = ev.get("serial")
|
# 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")
|
ts = ev.get("timestamp")
|
||||||
if ts and (last_event is None or ts > last_event):
|
if ts and (last_event is None or ts > last_event):
|
||||||
last_event = ts
|
last_event = ts
|
||||||
|
|
||||||
if ev.get("false_trigger"):
|
|
||||||
false_trigger_count += 1
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"event_count": len(events),
|
"event_count": len(events),
|
||||||
"peak_pvs": peak_pvs,
|
"peak_pvs": peak_pvs,
|
||||||
|
|||||||
@@ -134,6 +134,17 @@
|
|||||||
Projects
|
Projects
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
{# 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. #}
|
||||||
|
<a href="/sfm" class="flex items-center px-4 py-3 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 {% if request.url.path == '/sfm' %}bg-gray-100 dark:bg-gray-700{% endif %}">
|
||||||
|
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
|
||||||
|
</svg>
|
||||||
|
Events
|
||||||
|
</a>
|
||||||
|
|
||||||
{# Tools — operator workflow hub. Active when on /tools
|
{# Tools — operator workflow hub. Active when on /tools
|
||||||
itself or any of the workflow pages it links into
|
itself or any of the workflow pages it links into
|
||||||
(project tidy, metadata backfill, pair devices). #}
|
(project tidy, metadata backfill, pair devices). #}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<span class="text-2xl font-bold text-gray-900 dark:text-white mt-1">{{ "{:,}".format(summary.total_events) }}</span>
|
<span class="text-2xl font-bold text-gray-900 dark:text-white mt-1">{{ "{:,}".format(summary.total_events) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gray-50 dark:bg-slate-900/50 rounded-lg p-3 flex flex-col">
|
<div class="bg-gray-50 dark:bg-slate-900/50 rounded-lg p-3 flex flex-col">
|
||||||
<span class="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wider">Peak PVS</span>
|
<span class="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wider">Overall Peak</span>
|
||||||
{% if summary.peak_pvs is not none %}
|
{% if summary.peak_pvs is not none %}
|
||||||
<span class="text-2xl font-bold text-gray-900 dark:text-white mt-1">{{ "%.4f"|format(summary.peak_pvs) }} <span class="text-sm font-normal">in/s</span></span>
|
<span class="text-2xl font-bold text-gray-900 dark:text-white mt-1">{{ "%.4f"|format(summary.peak_pvs) }} <span class="text-sm font-normal">in/s</span></span>
|
||||||
<a href="/projects/{{ summary.project_id }}/nrl/{{ summary.peak_pvs_location_id }}"
|
<a href="/projects/{{ summary.project_id }}/nrl/{{ summary.peak_pvs_location_id }}"
|
||||||
|
|||||||
+1
-13
@@ -561,19 +561,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- SFM Admin (raw event database) -->
|
{# SFM Admin moved back to main nav as "Events" — see sidebar. #}
|
||||||
<div class="flex items-center justify-between p-4 bg-gray-50 dark:bg-slate-700 rounded-lg">
|
|
||||||
<div>
|
|
||||||
<div class="font-medium text-gray-900 dark:text-white">SFM Admin</div>
|
|
||||||
<div class="text-sm text-gray-500 dark:text-gray-400 mt-0.5">
|
|
||||||
Raw event database from SFM — cross-project event search, file downloads, debug view. Day-to-day event browsing lives on project / location / unit pages.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a href="/sfm"
|
|
||||||
class="ml-6 px-4 py-2 bg-seismo-orange hover:bg-orange-600 text-white text-sm font-medium rounded-lg transition-colors whitespace-nowrap">
|
|
||||||
Open
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Metadata Backfill + Project Tidy moved to Tools (they're
|
{# Metadata Backfill + Project Tidy moved to Tools (they're
|
||||||
operator workflows, not admin/dev surfaces). Find them
|
operator workflows, not admin/dev surfaces). Find them
|
||||||
|
|||||||
+2
-2
@@ -5,8 +5,8 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="mb-6 flex items-center justify-between">
|
<div class="mb-6 flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">SFM Event Data</h1>
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">Events</h1>
|
||||||
<p class="text-gray-600 dark:text-gray-400 mt-1">Blastware ACH events forwarded by series3-watcher</p>
|
<p class="text-gray-600 dark:text-gray-400 mt-1">Fleet-wide event database. Filter by serial, date, false-trigger, or browse the units roster.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<span id="sfm-status-badge" class="px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400">
|
<span id="sfm-status-badge" class="px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400">
|
||||||
|
|||||||
@@ -313,7 +313,7 @@
|
|||||||
<span class="text-xs text-gray-500 dark:text-gray-400 mt-1">outside any assignment window</span>
|
<span class="text-xs text-gray-500 dark:text-gray-400 mt-1">outside any assignment window</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gray-50 dark:bg-slate-900/50 rounded-lg p-3 flex flex-col">
|
<div class="bg-gray-50 dark:bg-slate-900/50 rounded-lg p-3 flex flex-col">
|
||||||
<span class="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wider">Peak PVS</span>
|
<span class="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wider">Overall Peak</span>
|
||||||
<span id="ue-stat-peak" class="text-2xl font-bold text-gray-900 dark:text-white mt-1">—</span>
|
<span id="ue-stat-peak" class="text-2xl font-bold text-gray-900 dark:text-white mt-1">—</span>
|
||||||
<span id="ue-stat-peak-when" class="text-xs text-gray-500 dark:text-gray-400 mt-1">—</span>
|
<span id="ue-stat-peak-when" class="text-xs text-gray-500 dark:text-gray-400 mt-1">—</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -199,7 +199,7 @@
|
|||||||
<span id="ev-stat-count" class="text-3xl font-bold text-gray-900 dark:text-white mt-1">—</span>
|
<span id="ev-stat-count" class="text-3xl font-bold text-gray-900 dark:text-white mt-1">—</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg p-4 flex flex-col">
|
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg p-4 flex flex-col">
|
||||||
<span class="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wider">Peak PVS</span>
|
<span class="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wider">Overall Peak</span>
|
||||||
<span id="ev-stat-peak" class="text-3xl font-bold text-gray-900 dark:text-white mt-1">—</span>
|
<span id="ev-stat-peak" class="text-3xl font-bold text-gray-900 dark:text-white mt-1">—</span>
|
||||||
<span id="ev-stat-peak-when" class="text-xs text-gray-500 dark:text-gray-400 mt-1">—</span>
|
<span id="ev-stat-peak-when" class="text-xs text-gray-500 dark:text-gray-400 mt-1">—</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user