fix: peak0c scope bug and strt cross check fix
This commit is contained in:
+34
-12
@@ -1397,29 +1397,51 @@ def _decode_a5_waveform(
|
|||||||
total_samples = struct.unpack_from(">H", strt, 14)[0]
|
total_samples = struct.unpack_from(">H", strt, 14)[0]
|
||||||
pretrig_samples = struct.unpack_from(">H", strt, 16)[0]
|
pretrig_samples = struct.unpack_from(">H", strt, 16)[0]
|
||||||
|
|
||||||
# Sanity check: pretrig must be less than total_samples.
|
# ── STRT sanity checks ───────────────────────────────────────────────────
|
||||||
# If not, the STRT layout is suspect (DLE-stuffing shift, different record variant, etc.).
|
# Check 1: pretrig must be strictly less than total_samples.
|
||||||
# Log the raw bytes for diagnosis and clamp pretrig to 0 for now — will try to derive
|
# Check 2 (cross-check): if compliance_config is available, the STRT-derived
|
||||||
# a better value from the compliance config after the full waveform is decoded.
|
# 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
|
_strt_invalid = False
|
||||||
|
_sample_rate_default = 1024
|
||||||
|
|
||||||
if pretrig_samples >= total_samples:
|
if pretrig_samples >= total_samples:
|
||||||
log.warning(
|
log.warning(
|
||||||
"_decode_a5_waveform: pretrig_samples=%d >= total_samples=%d — "
|
"_decode_a5_waveform: STRT check1 FAIL — pretrig_samples=%d >= "
|
||||||
"STRT layout suspect. Raw strt[0:21]: %s "
|
"total_samples=%d. Raw strt[0:21]: %s "
|
||||||
"Will attempt to derive pretrig from compliance config after decode.",
|
"Will derive pretrig from compliance config.",
|
||||||
pretrig_samples, total_samples, strt[0:21].hex(' '),
|
pretrig_samples, total_samples, strt[0:21].hex(' '),
|
||||||
)
|
)
|
||||||
pretrig_samples = 0
|
pretrig_samples = 0
|
||||||
total_samples = 0 # also invalid; will be filled from decoded count below
|
total_samples = 0
|
||||||
_strt_invalid = True
|
_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.
|
# strt[18] is a record-mode/type byte, NOT rectime in seconds.
|
||||||
# Confirmed from analysis of 4-9-26 ACH capture (15 distinct events):
|
# Confirmed from analysis of 4-9-26 ACH capture (15 distinct events):
|
||||||
# flags=0xFFFE (single-shot) → strt[18]=0x46 ('F') for all events regardless of duration
|
# 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
|
# 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.
|
# 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(
|
rectime_seconds = int(round(
|
||||||
max(0, total_samples - pretrig_samples) / _sample_rate_default
|
max(0, total_samples - pretrig_samples) / _sample_rate_default
|
||||||
))
|
))
|
||||||
@@ -1428,9 +1450,9 @@ def _decode_a5_waveform(
|
|||||||
event.pretrig_samples = pretrig_samples
|
event.pretrig_samples = pretrig_samples
|
||||||
event.rectime_seconds = rectime_seconds
|
event.rectime_seconds = rectime_seconds
|
||||||
|
|
||||||
log.debug(
|
log.info(
|
||||||
"_decode_a5_waveform: STRT total_samples=%d pretrig=%d "
|
"_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",
|
"raw strt[0:21]: %s",
|
||||||
total_samples, pretrig_samples, strt[18], rectime_seconds,
|
total_samples, pretrig_samples, strt[18], rectime_seconds,
|
||||||
strt[0:21].hex(' '),
|
strt[0:21].hex(' '),
|
||||||
|
|||||||
@@ -527,6 +527,10 @@
|
|||||||
? samples.slice(0, displayCount)
|
? samples.slice(0, displayCount)
|
||||||
: samples;
|
: 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) {
|
if (isGeo) {
|
||||||
// Geo channels: counts × (range / 32767) → in/s
|
// Geo channels: counts × (range / 32767) → in/s
|
||||||
// Scale factor for the waveform shape (may need calibration per unit)
|
// 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).
|
// Use the device-computed 0C record peak for the label (authoritative).
|
||||||
// The raw-sample-computed peak can be inflated by frame-boundary artifacts.
|
// 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)
|
const peakIns = (peak0C !== null && peak0C !== undefined)
|
||||||
? peak0C
|
? peak0C
|
||||||
: Math.max(...plotSamples.map(Math.abs));
|
: Math.max(...plotSamples.map(Math.abs));
|
||||||
|
|||||||
Reference in New Issue
Block a user