refactor(backend): clean up package re-exports, settings model properties, and unused signals

This commit is contained in:
jack
2026-07-09 12:49:33 -07:00
parent ca158a7946
commit ac4448ed44
34 changed files with 372 additions and 337 deletions
@@ -14,7 +14,7 @@ from pygui.backend.models.frame import Frame
from pygui.backend.models.frame_player import FramePlayer, frames_from_wafer_data
from pygui.backend.models.replay_stats import ReplayStatsTracker
from pygui.backend.models.sensor_editor import SensorEditor
from pygui.backend.models.session_model import SessionModel
from pygui.backend.models.session_model import SessionModel, SessionUpdate
from pygui.backend.models.threshold_classifier import ThresholdConfig
from pygui.backend.utils import slot_error_boundary
from pygui.backend.wafer.zwafer_models import Sensor
@@ -37,7 +37,6 @@ class SessionController(QObject):
loadedFileChanged = Signal()
loadFileError = Signal(str)
clusterAveragingEnabledChanged = Signal()
settingsChanged = Signal() # emitted when session state changes that should be persisted
liveStatsChanged = Signal() # emitted when receivedCount or errorCount change
# trend: per-frame avg for live graph
trendData = Signal(str) # JSON array of floats
@@ -50,8 +49,7 @@ class SessionController(QObject):
_liveFrame = Signal(object) # Frame
_liveError = Signal() # worker-thread error ping
def __init__(self, parent: QObject | None = None,
settings: dict | None = None) -> None:
def __init__(self, parent: QObject | None = None) -> None:
super().__init__(parent)
self._mode = MODE_REVIEW
self._model = SessionModel()
@@ -59,7 +57,7 @@ class SessionController(QObject):
self._reader: Optional[StreamReader] = None
self._recorder = CsvRecorder()
self._sensors: list[Sensor] = []
self._last = None # last SessionUpdate
self._last: Optional[SessionUpdate] = None
self._elapsed = 0.0
self._trend_buffer: list[float] = [] # rolling window
self._trend_timestamps: list[float] = [] # monotonic timestamps
@@ -96,21 +94,6 @@ class SessionController(QObject):
self._compare_recs_b: list = []
self._compare_alignment_map: dict[int, int] = {}
# Restore persisted state if available
self._load_settings(settings or {})
# ---- persisted settings ----
def _load_settings(self, settings: dict) -> None:
"""Restore session state from persisted settings dict."""
# Do NOT auto-restore the last session file — always start fresh.
def collect_settings(self) -> dict:
"""Return a dict of session state to persist."""
return {
"session_last_file": self._loaded_file,
}
# ---- properties QML binds to ----
@Property(str, notify=modeChanged)
def mode(self) -> str: return self._mode
@@ -150,7 +133,7 @@ class SessionController(QObject):
"value": round(v, 2), "band": band, "index": i})
return out
@Property("QVariantList", notify=sensorsChanged)
@Property("QVariantList", notify=sensorsChanged) # type: ignore[arg-type]
def sensorLayout(self) -> list:
"""[{label, x, y, side, offset_x, offset_y}] for WaferMapItem.sensors."""
return [
@@ -175,14 +158,14 @@ class SessionController(QObject):
"""Wafer size in mm."""
return getattr(self._sensors, "size", 300.0)
@Property("QVariantList", notify=frameUpdated)
@Property("QVariantList", notify=frameUpdated) # type: ignore[arg-type]
def sensorValues(self) -> list:
"""[float] in sensor order."""
if not self._last:
return []
return [round(v, 3) for v in self._last.values]
@Property("QVariantList", notify=frameUpdated)
@Property("QVariantList", notify=frameUpdated) # type: ignore[arg-type]
def sensorBands(self) -> list:
"""['in_range'|'high'|'low'] in sensor order."""
if not self._last:
@@ -212,7 +195,7 @@ class SessionController(QObject):
@Property(str, notify=loadedFileChanged)
def loadedFile(self) -> str: return self._loaded_file
@Property("QVariantList", notify=frameUpdated)
@Property("QVariantList", notify=frameUpdated) # type: ignore[arg-type]
def overriddenSensors(self) -> list[int]:
"""Indices of sensors that currently have a replacement or offset."""
return self._sensor_editor.active_indices()
@@ -221,7 +204,7 @@ class SessionController(QObject):
def clusterAveragingEnabled(self) -> bool:
return self._cluster_averaging_enabled
@clusterAveragingEnabled.setter
@clusterAveragingEnabled.setter # type: ignore[no-redef]
def clusterAveragingEnabled(self, value: bool) -> None:
if self._cluster_averaging_enabled == value:
return
@@ -319,7 +302,6 @@ class SessionController(QObject):
for frame in self._player._frames:
self._stats_tracker.track(frame.seq, frame.values)
self.trendData.emit(json.dumps(self._stats_tracker.get_trend()))
self.settingsChanged.emit()
@Slot()
@slot_error_boundary
@@ -331,7 +313,6 @@ class SessionController(QObject):
self._loaded_file = ""
self.loadedFileChanged.emit()
self.sensorsChanged.emit()
self.settingsChanged.emit()
# ---- comparison: DTW between two CSV files ----
@Slot(str, str)
@@ -475,7 +456,7 @@ class SessionController(QObject):
"""Return the per-sensor temp diff (Run B - Run A) at the given scrub frame index of Run A, using DTW alignment."""
if not self._compare_recs_a or not self._compare_recs_b:
return []
idx_a = min(max(0, scrub_idx), len(self._compare_recs_a) - 1)
if idx_a not in self._compare_alignment_map:
# DTW path only covers indices up to the shorter run's length —
@@ -485,7 +466,7 @@ class SessionController(QObject):
values_a = self._compare_recs_a[idx_a].values
values_b = self._compare_recs_b[idx_b].values
n = min(len(values_a), len(values_b))
return [round(values_b[i] - values_a[i], 3) for i in range(n)]