summaryrefslogtreecommitdiff
path: root/core/signal_processor.py
diff options
context:
space:
mode:
authorChristian Kolset <ckolset@colostate.edu>2026-08-03 15:32:56 -0600
committerChristian Kolset <ckolset@colostate.edu>2026-08-03 15:32:56 -0600
commit9bcad5d3af258eb72bc9c8ac87e3f1713e1b8b80 (patch)
treebd2b07ae968e3b422c536fab21f57a5b660d4b98 /core/signal_processor.py
parent68a0c5ba06f471d1d63aedfb61d708faa4b76565 (diff)
Fix acquisition pipeline stutter with many channels
Batches per-tick device readings into one signal emit instead of one per channel, evaluates derived channels once per tick instead of once per raw sample, and makes ChannelBuffer.window() cost scale with the window size instead of total buffer history. Strip chart X-range now scrolls on an independent ~30fps timer instead of only snapping when new data lands, which was the main visible cause of the stutter. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'core/signal_processor.py')
-rw-r--r--core/signal_processor.py18
1 files changed, 11 insertions, 7 deletions
diff --git a/core/signal_processor.py b/core/signal_processor.py
index bfb7ba3..8ab3937 100644
--- a/core/signal_processor.py
+++ b/core/signal_processor.py
@@ -380,7 +380,7 @@ class SignalProcessor(QObject):
Applies filter pipelines to raw channel data, then evaluates all
derived channels and emits processed_data for everything.
- Connect: engine.new_data → processor.on_raw_data
+ Connect: engine.new_data → processor.on_raw_batch
Connect: processor.processed_data → chart.on_new_data
"""
@@ -468,9 +468,16 @@ class SignalProcessor(QObject):
# ── Main data path ────────────────────────────────────────────────────
- def on_raw_data(self, device_id: str, channel_id: str,
- timestamp: float, value: float):
- """Slot: receive raw data, apply filters, emit processed, update derived."""
+ def on_raw_batch(self, timestamp: float, readings: List[Tuple[str, str, float]]):
+ """Slot: receive one tick's worth of raw readings, apply filters and
+ emit processed for each, then evaluate derived channels once for the
+ whole batch — not once per channel."""
+ for device_id, channel_id, value in readings:
+ self._process_one(device_id, channel_id, timestamp, value)
+ self._evaluate_derived(timestamp)
+
+ def _process_one(self, device_id: str, channel_id: str,
+ timestamp: float, value: float):
key = (device_id, channel_id)
# Apply filter pipeline
@@ -485,9 +492,6 @@ class SignalProcessor(QObject):
# Emit processed physical channel
self.processed_data.emit(device_id, channel_id, timestamp, processed)
- # Evaluate all derived channels whose sources include this channel
- self._evaluate_derived(timestamp)
-
def _evaluate_derived(self, timestamp: float):
with self._lock:
derived = list(self._derived)