update to 0.26.0. Big chonking update including 0.23, 0.24, and 0.25 as well. #33
+7
-4
@@ -24,13 +24,16 @@ window).
|
||||
`SeismoDb()` construction, no manual migration). `query_events` /
|
||||
`get_event` (and thus `/db/events`) return it automatically (`SELECT *`).
|
||||
- **Mutual exclusivity with `false_trigger`** — setting `reviewed_real=1`
|
||||
clears `false_trigger`, and vice versa, both via `set_false_trigger` /
|
||||
the sidecar review PATCH path.
|
||||
clears `false_trigger`, and vice versa, enforced on both review paths:
|
||||
the sidecar review PATCH (`update_event_review`) and the quick
|
||||
`PATCH /db/events/{id}/false_trigger` endpoint (`set_false_trigger`).
|
||||
- **`find_twins`** — matches an event's histogram/waveform twins by serial +
|
||||
identical peak-vector-sum + a timestamp window.
|
||||
- **`propagate_review_to_twins`** — copies an event's `false_trigger`/
|
||||
`reviewed_real` state onto its twins, wired into the
|
||||
`PATCH /db/events/{id}/sidecar` review path so flagging one flags both.
|
||||
`reviewed_real` state onto its twins, wired into both the
|
||||
`PATCH /db/events/{id}/sidecar` review path and the quick
|
||||
`PATCH /db/events/{id}/false_trigger` path, so flagging one flags both
|
||||
regardless of which endpoint made the change.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+28
-5
@@ -610,6 +610,16 @@ class SeismoDb:
|
||||
within ``window_seconds`` of this event's timestamp. Excludes the
|
||||
event itself. Returns [] if the event or any required field
|
||||
(serial / peak_vector_sum / timestamp) is missing.
|
||||
|
||||
Caveat: identical-PVS matching is a proxy for "same physical event
|
||||
recorded twice," not a guarantee. In the rare case where the device
|
||||
clamps/saturates PVS (clamped to sqrt(3) * geo_range), two distinct
|
||||
saturated events on the same serial within the window can share the
|
||||
same clamped PVS value and be matched as twins even though they are
|
||||
different events. This is harmless in practice — false_trigger/
|
||||
reviewed_real are derived/index columns re-derivable from the
|
||||
sidecar source of truth — but worth knowing if twin counts look
|
||||
surprising on a saturated/clamped run.
|
||||
"""
|
||||
row = self.get_event(event_id)
|
||||
if not row:
|
||||
@@ -652,12 +662,25 @@ class SeismoDb:
|
||||
return moved
|
||||
|
||||
def set_false_trigger(self, event_id: str, value: bool) -> bool:
|
||||
"""Set or clear the false_trigger flag on an event. Returns True if found."""
|
||||
"""
|
||||
Set or clear the false_trigger flag on an event. Returns True if found.
|
||||
|
||||
Mirrors the 3-state exclusivity enforced by `update_event_review`:
|
||||
setting false_trigger true also clears `reviewed_real` (a false
|
||||
trigger can't also be a confirmed-real event). Clearing false_trigger
|
||||
leaves `reviewed_real` untouched.
|
||||
"""
|
||||
with self._connect() as conn:
|
||||
cur = conn.execute(
|
||||
"UPDATE events SET false_trigger=? WHERE id=?",
|
||||
(1 if value else 0, event_id),
|
||||
)
|
||||
if value:
|
||||
cur = conn.execute(
|
||||
"UPDATE events SET false_trigger=1, reviewed_real=0 WHERE id=?",
|
||||
(event_id,),
|
||||
)
|
||||
else:
|
||||
cur = conn.execute(
|
||||
"UPDATE events SET false_trigger=0 WHERE id=?",
|
||||
(event_id,),
|
||||
)
|
||||
return cur.rowcount > 0
|
||||
|
||||
def delete_event(self, event_id: str) -> Optional[dict]:
|
||||
|
||||
+10
-1
@@ -1957,7 +1957,10 @@ def db_set_false_trigger(
|
||||
value: bool = Query(..., description="True to flag as false trigger, False to clear"),
|
||||
) -> dict:
|
||||
"""
|
||||
Set or clear the false_trigger flag on a single event.
|
||||
Set or clear the false_trigger flag on a single event. Enforces the
|
||||
same 3-state exclusivity as the sidecar review PATCH (flagging false_trigger
|
||||
clears reviewed_real) and propagates the resulting flags to the event's
|
||||
histogram/waveform twin(s), same as the sidecar path.
|
||||
|
||||
Used by the terra-view event review UI.
|
||||
Returns 404 if the event_id is not found.
|
||||
@@ -1965,6 +1968,12 @@ def db_set_false_trigger(
|
||||
found = _get_db().set_false_trigger(event_id, value)
|
||||
if not found:
|
||||
raise HTTPException(status_code=404, detail=f"Event {event_id} not found")
|
||||
|
||||
try:
|
||||
_get_db().propagate_review_to_twins(event_id)
|
||||
except Exception as exc:
|
||||
log.warning("twin review-propagation failed for %s: %s", event_id, exc)
|
||||
|
||||
return {"status": "ok", "event_id": event_id, "false_trigger": value}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
from sfm.database import SeismoDb
|
||||
from minimateplus.models import Event
|
||||
|
||||
|
||||
def _ins(db, eid_key="01110000", serial="BE1"):
|
||||
ev = Event(index=0); ev._waveform_key = bytes.fromhex(eid_key)
|
||||
db.insert_events([ev], serial=serial)
|
||||
return db.query_events(serial=serial)[0]["id"]
|
||||
|
||||
|
||||
def test_set_false_trigger_clears_reviewed_real(tmp_path):
|
||||
db = SeismoDb(tmp_path / "s.db"); eid = _ins(db)
|
||||
db.update_event_review(eid, {"reviewed_real": True})
|
||||
assert db.get_event(eid)["reviewed_real"] == 1
|
||||
|
||||
db.set_false_trigger(eid, True)
|
||||
row = db.get_event(eid)
|
||||
assert row["false_trigger"] == 1 and row["reviewed_real"] == 0
|
||||
|
||||
|
||||
def test_clearing_false_trigger_leaves_reviewed_real_untouched(tmp_path):
|
||||
db = SeismoDb(tmp_path / "s.db"); eid = _ins(db)
|
||||
db.update_event_review(eid, {"false_trigger": True})
|
||||
db.set_false_trigger(eid, False)
|
||||
row = db.get_event(eid)
|
||||
assert row["false_trigger"] == 0
|
||||
# reviewed_real was never set true, so it stays 0 either way; the point
|
||||
# is set_false_trigger(False) does not touch the column at all.
|
||||
assert row["reviewed_real"] == 0
|
||||
Reference in New Issue
Block a user