from __future__ import annotations import os, sys, sqlite3 from pathlib import Path import pytest sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from sfm.database import SeismoDb ZC_COLS = ["tran_zc_freq", "vert_zc_freq", "long_zc_freq", "mic_zc_freq", "tran_zc_above_range", "vert_zc_above_range", "long_zc_above_range", "mic_zc_above_range"] def test_fresh_db_has_zc_freq_columns(tmp_path: Path): db = SeismoDb(tmp_path / "seismo_relay.db") with sqlite3.connect(str(tmp_path / "seismo_relay.db")) as conn: cols = {r[1] for r in conn.execute("PRAGMA table_info(events)").fetchall()} for c in ZC_COLS: assert c in cols, f"missing column {c}" def test_migration_adds_zc_freq_columns_to_legacy_db(tmp_path: Path): db_path = tmp_path / "old.db" # A "modern-minus-zc" events table (has blastware_* but not the zc columns). with sqlite3.connect(str(db_path)) as conn: conn.executescript(""" CREATE TABLE events ( id TEXT PRIMARY KEY, serial TEXT NOT NULL, waveform_key TEXT NOT NULL, session_id TEXT, timestamp TEXT, tran_ppv REAL, vert_ppv REAL, long_ppv REAL, peak_vector_sum REAL, mic_ppv REAL, project TEXT, client TEXT, operator TEXT, sensor_location TEXT, sample_rate INTEGER, record_type TEXT, false_trigger INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), UNIQUE(serial, timestamp) ); INSERT INTO events (id, serial, waveform_key, timestamp) VALUES ('legacy-id', 'BE11529', '01110000', '2026-04-01T12:00:00'); """) db = SeismoDb(db_path) # triggers _migrate rows = db.query_events(serial="BE11529") assert len(rows) == 1 for c in ZC_COLS: assert c in rows[0] # present assert rows[0][c] is None # NULL for the legacy row from minimateplus.models import PeakValues, Event from minimateplus import event_file_io from minimateplus.bw_ascii_report import BwAsciiReport, ChannelStats, MicStats def _report_with_freqs(): r = BwAsciiReport() r.channels["Tran"] = ChannelStats(ppv_ips=0.075, zc_freq_hz=100.0, zc_freq_above_range=True) r.channels["Vert"] = ChannelStats(ppv_ips=0.220, zc_freq_hz=85.0) r.channels["Long"] = ChannelStats(ppv_ips=0.045, zc_freq_hz=73.0) r.mic = MicStats(zc_freq_hz=51.0) return r def test_apply_report_copies_zc_freq_onto_peakvalues(): ev = Event(index=0) event_file_io.apply_report_to_event(ev, _report_with_freqs()) pv = ev.peak_values assert pv.vert_zc_freq == 85.0 assert pv.tran_zc_freq == 100.0 assert pv.tran_zc_above_range is True assert pv.vert_zc_above_range is False assert pv.mic_zc_freq == 51.0 def test_apply_bw_report_dict_copies_zc_freq(): ev = Event(index=0) bw = { "peaks": { "tran": {"ppv_ips": 0.075, "zc_freq_hz": 100.0, "zc_freq_above_range": True}, "vert": {"ppv_ips": 0.220, "zc_freq_hz": 85.0}, "long": {"ppv_ips": 0.045, "zc_freq_hz": 73.0}, }, "mic": {"zc_freq_hz": 51.0, "zc_freq_above_range": False}, } event_file_io.apply_bw_report_dict_to_event(ev, bw) pv = ev.peak_values assert pv.vert_zc_freq == 85.0 assert pv.tran_zc_above_range is True assert pv.mic_zc_freq == 51.0