added capture time for every sweep

This commit is contained in:
Ayzen
2026-09-03 17:30:19 +03:00
parent 8a52431bd3
commit 7997abe2d9
20 changed files with 271 additions and 17 deletions
+42 -3
View File
@@ -39,12 +39,19 @@ from python_app.orchestration.shm.ring_writer import ShmRingWriter
from python_app.storage.npz.serialize import serialize_result_collection, serialize_trace_collection
def _trace(in_pos: int, out_pos: int, n: int) -> TraceData:
def _trace(in_pos: int, out_pos: int, n: int, *, capture_ns: tuple[int, int] = (0, 0)) -> TraceData:
"""Build a trace with float32-exact data so round-trips compare exactly."""
freq = np.arange(n, dtype=np.float32) + 1.0
s11 = (np.arange(n, dtype=np.float32) + 0.5j * np.arange(n, dtype=np.float32)).astype(np.complex64)
s21 = (-np.arange(n, dtype=np.float32) + 2.0j * np.arange(n, dtype=np.float32)).astype(np.complex64)
return TraceData(combo=ComboKey(input=in_pos, output=out_pos), frequency_hz=freq, s11=s11, s21=s21)
return TraceData(
combo=ComboKey(input=in_pos, output=out_pos),
frequency_hz=freq,
s11=s11,
s21=s21,
capture_start_ns=capture_ns[0],
capture_end_ns=capture_ns[1],
)
class TraceCollectionRoundTripTest(unittest.TestCase):
@@ -52,7 +59,7 @@ class TraceCollectionRoundTripTest(unittest.TestCase):
collection = SweepCollection(
collection_id=7,
monotonic_ns=123,
traces=[_trace(0, 0, 4), _trace(3, 1, 2)],
traces=[_trace(0, 0, 4, capture_ns=(11, 13)), _trace(3, 1, 2, capture_ns=(15, 19))],
capture_start_ns=10,
capture_end_ns=20,
)
@@ -66,6 +73,10 @@ class TraceCollectionRoundTripTest(unittest.TestCase):
self.assertTrue(np.array_equal(got.frequency_hz, original.frequency_hz))
self.assertTrue(np.array_equal(got.s11, original.s11))
self.assertTrue(np.array_equal(got.s21, original.s21))
self.assertEqual(
(got.capture_start_ns, got.capture_end_ns),
(original.capture_start_ns, original.capture_end_ns),
)
def test_raw_round_trips(self) -> None:
self._assert_round_trips(RAW_MAGIC)
@@ -78,6 +89,34 @@ class TraceCollectionRoundTripTest(unittest.TestCase):
decoded = decode_trace_collection(serialize_trace_collection(collection, RAW_MAGIC), RAW_MAGIC)
self.assertEqual(decoded.traces, [])
def test_payload_without_per_trace_window_table_still_decodes(self) -> None:
# A producer built before per-trace timing stops after the collection
# window; its traces must still decode, with the timestamps left at zero.
collection = SweepCollection(
collection_id=4,
monotonic_ns=5,
traces=[_trace(1, 0, 3, capture_ns=(7, 9))],
capture_start_ns=6,
capture_end_ns=10,
)
full = serialize_trace_collection(collection, RAW_MAGIC)
legacy = full[: -(4 + 16 * len(collection.traces))]
decoded = decode_trace_collection(legacy, RAW_MAGIC)
self.assertEqual((decoded.capture_start_ns, decoded.capture_end_ns), (6, 10))
self.assertEqual(len(decoded.traces), 1)
self.assertEqual((decoded.traces[0].capture_start_ns, decoded.traces[0].capture_end_ns), (0, 0))
def test_per_trace_window_count_mismatch_is_rejected(self) -> None:
collection = SweepCollection(
collection_id=4, monotonic_ns=5, traces=[_trace(1, 0, 3, capture_ns=(7, 9))]
)
payload = serialize_trace_collection(collection, RAW_MAGIC)
# Overwrite the window-table count (u32 before the single 16-byte pair).
corrupt = payload[:-20] + struct.pack("<I", 2) + payload[-16:]
with self.assertRaises(ValueError):
decode_trace_collection(corrupt, RAW_MAGIC)
class ResultCollectionRoundTripTest(unittest.TestCase):
def test_all_payload_kinds_round_trip(self) -> None: