ae0e17b5dc
Three things to make pickup smoother: 1. analysis/README.md (NEW): catalogues the ~25 scratch scripts. Categorizes them as "still useful" / "superseded — keep for archaeology" / "pure exploration". Tells a fresh engineer which files to read first and which to ignore. 2. scratch/next_experiment_skeleton.py (NEW): stub + spec for the segment-channel scoring analyzer. Includes the fixture loader, block walker, and decode-segment-as-channel helper — just enough scaffolding that the next pass starts from "fill in score_segment_against_all_channels()" rather than from scratch. Already runs and confirms 13 segments per 3-sec event with sample starts going to 6590 (way past the 3328 actual samples) — strong evidence that not all segments carry Tran. 3. Removed decode-re/ duplicate. It was a mirror of tests/fixtures/. Analysis scripts that hardcoded decode-re/ paths updated to point at tests/fixtures/. CLAUDE.md note updated: future event uploads go directly into a dated subdirectory under tests/fixtures/. All 40 tests still pass. Skeleton runs.
87 lines
2.7 KiB
Python
87 lines
2.7 KiB
Python
"""Test: 00 NN markers might be RLE for zero-deltas in current channel."""
|
|
import sys
|
|
sys.path.insert(0, ".")
|
|
from analysis.load_bundle import _parse_txt
|
|
from minimateplus.waveform_codec import walk_body, find_data_start
|
|
|
|
|
|
def s4(n):
|
|
return n if n < 8 else n - 16
|
|
|
|
|
|
def i8(b):
|
|
return b if b < 128 else b - 256
|
|
|
|
|
|
def decode_with_rle(body):
|
|
"""Decode Tran assuming:
|
|
- preamble[3:5], [5:7] = T[0], T[1]
|
|
- All 10 NN / 20 NN blocks until segment_header (40 02) are Tran deltas
|
|
- 00 NN markers are RLE: NN/4 zero T deltas (or NN, or NN/2 — try them)
|
|
"""
|
|
if len(body) < 9 or body[0:3] != b"\x00\x02\x00":
|
|
return None, None, None
|
|
T0 = int.from_bytes(body[3:5], "big", signed=True)
|
|
T1 = int.from_bytes(body[5:7], "big", signed=True)
|
|
|
|
# Find first tag (might be 00 NN, 10 NN, or 20 NN)
|
|
i = 7
|
|
while i + 1 < len(body):
|
|
if body[i] in (0x00, 0x10, 0x20):
|
|
break
|
|
i += 1
|
|
start = i
|
|
|
|
blocks = walk_body(body, start)
|
|
|
|
results = {}
|
|
for rle_div in (4, 2, 1): # try different RLE interpretations
|
|
T = [T0, T1]
|
|
cur = T1
|
|
for blk in blocks:
|
|
if blk.tag_hi == 0x40:
|
|
break
|
|
if blk.tag_hi == 0x10:
|
|
for byte in blk.data:
|
|
for nib in ((byte >> 4) & 0xF, byte & 0xF):
|
|
cur += s4(nib)
|
|
T.append(cur)
|
|
elif blk.tag_hi == 0x20:
|
|
for byte in blk.data:
|
|
cur += i8(byte)
|
|
T.append(cur)
|
|
elif blk.tag_hi == 0x00:
|
|
# RLE of zero deltas
|
|
n_zeros = blk.tag_lo // rle_div
|
|
for _ in range(n_zeros):
|
|
T.append(cur)
|
|
# 30 NN: skip for now
|
|
results[rle_div] = T
|
|
return results, T0, T1
|
|
|
|
|
|
def main():
|
|
for stem in ("M529LL1L.V70", "M529LL1L.JQ0", "M529LL1A.SP0", "M529LL1A.SS0", "M529LL1A.SV0"):
|
|
path = f"tests/fixtures/5-11-26/{stem}"
|
|
with open(path, "rb") as f:
|
|
body = f.read()[43:-26]
|
|
_, samples = _parse_txt(path + ".TXT")
|
|
truth_T = [round(v*200) for v in samples["Tran"]]
|
|
|
|
results, T0, T1 = decode_with_rle(body)
|
|
print(f"\n=== {stem} (T[0]={T0}, T[1]={T1}) ===")
|
|
for rle_div, T in results.items():
|
|
n = min(len(T), len(truth_T))
|
|
matches = sum(1 for i in range(n) if T[i] == truth_T[i])
|
|
# Find first divergence
|
|
div_at = -1
|
|
for i in range(n):
|
|
if T[i] != truth_T[i]:
|
|
div_at = i
|
|
break
|
|
print(f" rle_div={rle_div}: decoded {len(T)}, matches {matches}/{n}, first div at sample {div_at}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|