"""Try decoding body as 4-bit signed nibble deltas, 4-channel round-robin.""" import sys sys.path.insert(0, ".") from analysis.load_bundle import load_bundle CHANNELS = ("Tran", "Vert", "Long", "MicL") def s4(n): """Sign-extend a 4-bit unsigned to int (0..7 → 0..7, 8..F → -8..-1).""" return n if n < 8 else n - 16 def decode_nibbles(body: bytes, skip_bytes: int = 7, n_channels: int = 4): """Read body as 2 nibbles per byte; accumulate as deltas for n_channels round-robin.""" out = [[] for _ in range(n_channels)] cur = [0] * n_channels ch = 0 nibbles = [] for byte in body[skip_bytes:]: nibbles.append((byte >> 4) & 0xF) nibbles.append(byte & 0xF) for n in nibbles: cur[ch] += s4(n) out[ch].append(cur[ch]) ch = (ch + 1) % n_channels return out def cmp_to_truth(pred, truth, scale=16): """Compare predicted ints (in 16-count units) to truth (in 16-count units = txt * 200). Return (max_abs_err, mean_abs_err, n_compared). """ n = min(len(pred), len(truth)) errs = [] for i in range(n): p = pred[i] t = truth[i] errs.append(abs(p - t)) if not errs: return None return (max(errs), sum(errs) / len(errs), n) def main(): for name in ("event-a", "event-c"): b = load_bundle(name) # Convert TXT samples (in/s) to 16-count units (multiply by 200, since 0.005 in/s = 1) # WAIT: 0.005 in/s = 16 ADC counts. 1 count = 0.000305 in/s. # So in 1-count units: count = txt * (1/0.0003052) ≈ txt * 3276.7 # But TXT only has 0.005 resolution so equivalent to 16-count units = txt * 200. truth_in_16 = {ch: [round(v * 200) for v in b.samples[ch]] for ch in CHANNELS[:3]} # MicL is in dB, skip for now # Try decoder with skip_bytes = 7 decoded = decode_nibbles(b.body, skip_bytes=7, n_channels=4) print(f"\n=== {name} ===") print(f" body={len(b.body)}, nibbles={2*(len(b.body)-7)}, samples_per_ch={len(decoded[0])}") print(f" truth samples per ch: {len(truth_in_16['Tran'])}") # Print first 24 of each for i, chan in enumerate(CHANNELS): pred_first = decoded[i][:24] if chan in truth_in_16: truth_first = truth_in_16[chan][:24] print(f" {chan} pred: {pred_first}") print(f" {chan} truth: {truth_first}") else: print(f" {chan} pred: {pred_first} (truth in dB, skipped)") if __name__ == "__main__": main()