fix: peak0c scope bug and strt cross check fix
This commit is contained in:
+34
-12
@@ -1397,20 +1397,44 @@ def _decode_a5_waveform(
|
||||
total_samples = struct.unpack_from(">H", strt, 14)[0]
|
||||
pretrig_samples = struct.unpack_from(">H", strt, 16)[0]
|
||||
|
||||
# Sanity check: pretrig must be less than total_samples.
|
||||
# If not, the STRT layout is suspect (DLE-stuffing shift, different record variant, etc.).
|
||||
# Log the raw bytes for diagnosis and clamp pretrig to 0 for now — will try to derive
|
||||
# a better value from the compliance config after the full waveform is decoded.
|
||||
# ── STRT sanity checks ───────────────────────────────────────────────────
|
||||
# Check 1: pretrig must be strictly less than total_samples.
|
||||
# Check 2 (cross-check): if compliance_config is available, the STRT-derived
|
||||
# post-trigger record time must be within 2× of the configured record_time.
|
||||
# A 3-second record at 1024 sps = 3072 post-trig samples; if STRT gives
|
||||
# e.g. 21 s, something is wrong with the byte offsets.
|
||||
#
|
||||
# Both failures trigger the same fallback: derive pretrig from the compliance
|
||||
# monitoring standard (0.25 s) and total from compliance record_time.
|
||||
_strt_invalid = False
|
||||
_sample_rate_default = 1024
|
||||
|
||||
if pretrig_samples >= total_samples:
|
||||
log.warning(
|
||||
"_decode_a5_waveform: pretrig_samples=%d >= total_samples=%d — "
|
||||
"STRT layout suspect. Raw strt[0:21]: %s "
|
||||
"Will attempt to derive pretrig from compliance config after decode.",
|
||||
"_decode_a5_waveform: STRT check1 FAIL — pretrig_samples=%d >= "
|
||||
"total_samples=%d. Raw strt[0:21]: %s "
|
||||
"Will derive pretrig from compliance config.",
|
||||
pretrig_samples, total_samples, strt[0:21].hex(' '),
|
||||
)
|
||||
pretrig_samples = 0
|
||||
total_samples = 0 # also invalid; will be filled from decoded count below
|
||||
total_samples = 0
|
||||
_strt_invalid = True
|
||||
elif compliance_config is not None and compliance_config.record_time:
|
||||
cc_rt = compliance_config.record_time
|
||||
cc_sr = compliance_config.sample_rate or _sample_rate_default
|
||||
strt_post_trig = (total_samples - pretrig_samples) / cc_sr
|
||||
# Allow up to 2× tolerance to account for zero-padding beyond the window.
|
||||
# Anything more than that is a layout error, not zero-padding.
|
||||
if strt_post_trig > cc_rt * 2.0 or strt_post_trig < cc_rt * 0.5:
|
||||
log.warning(
|
||||
"_decode_a5_waveform: STRT check2 FAIL — STRT-derived rectime "
|
||||
"%.1fs is implausible vs compliance record_time=%.1fs (ratio=%.1f×). "
|
||||
"Raw strt[0:21]: %s Falling back to compliance-config values.",
|
||||
strt_post_trig, cc_rt, strt_post_trig / cc_rt,
|
||||
strt[0:21].hex(' '),
|
||||
)
|
||||
pretrig_samples = 0
|
||||
total_samples = 0
|
||||
_strt_invalid = True
|
||||
|
||||
# strt[18] is a record-mode/type byte, NOT rectime in seconds.
|
||||
@@ -1418,8 +1442,6 @@ def _decode_a5_waveform(
|
||||
# flags=0xFFFE (single-shot) → strt[18]=0x46 ('F') for all events regardless of duration
|
||||
# flags=0xFFFD (continuous) → strt[18]=0x0E for all events regardless of duration
|
||||
# The actual post-trigger record time must be derived from total_samples and pretrig_samples.
|
||||
# Default sample rate of 1024 is used here; the server overrides with compliance config sr.
|
||||
_sample_rate_default = 1024
|
||||
rectime_seconds = int(round(
|
||||
max(0, total_samples - pretrig_samples) / _sample_rate_default
|
||||
))
|
||||
@@ -1428,9 +1450,9 @@ def _decode_a5_waveform(
|
||||
event.pretrig_samples = pretrig_samples
|
||||
event.rectime_seconds = rectime_seconds
|
||||
|
||||
log.debug(
|
||||
log.info(
|
||||
"_decode_a5_waveform: STRT total_samples=%d pretrig=%d "
|
||||
"strt[18]=0x%02X (mode byte, not seconds) computed_rectime=%ds "
|
||||
"strt[18]=0x%02X (mode byte) computed_rectime=%ds "
|
||||
"raw strt[0:21]: %s",
|
||||
total_samples, pretrig_samples, strt[18], rectime_seconds,
|
||||
strt[0:21].hex(' '),
|
||||
|
||||
@@ -527,6 +527,10 @@
|
||||
? samples.slice(0, displayCount)
|
||||
: samples;
|
||||
|
||||
// peak0C declared here (function scope) so it is visible in the Chart.js
|
||||
// config block below (which lives outside the if(isGeo) block).
|
||||
let peak0C = null;
|
||||
|
||||
if (isGeo) {
|
||||
// Geo channels: counts × (range / 32767) → in/s
|
||||
// Scale factor for the waveform shape (may need calibration per unit)
|
||||
@@ -535,7 +539,7 @@
|
||||
|
||||
// Use the device-computed 0C record peak for the label (authoritative).
|
||||
// The raw-sample-computed peak can be inflated by frame-boundary artifacts.
|
||||
const peak0C = peakValues0C[ch];
|
||||
peak0C = peakValues0C[ch];
|
||||
const peakIns = (peak0C !== null && peak0C !== undefined)
|
||||
? peak0C
|
||||
: Math.max(...plotSamples.map(Math.abs));
|
||||
|
||||
Reference in New Issue
Block a user