Phase 2: extract headless core modules (sras_format, scan_geometry, config)
- core/sras_format.py: THE v6 implementation — create_scan_file (writer, byte-identical to the old one, enforced against the Phase-0 goldens), SrasFile parser with frontier/truncation walk, and zero-copy mmap load_angle/load_row views for multi-GB files - core/scan_geometry.py: ScanPlan/AngleGeometry dataclasses, build_plan (rotated-bbox trig from MainWindow._build_scan_params), travel-limit validate_plan (limits now a StageLimits dataclass, not literals buried in the worker), format_eta + EtaEstimator (bounded deque) - core/config.py: ScanDefaults dataclass replaces the module-import-time dict globals. FIXES: editing any main-window port used to rewrite aui_defaults.json without helios_port, silently reverting the Helios port every time (test_helios_port_survives_partial_update covers it). Also drops the inert laser_freq_hz plumbing — scans always used the LASER_FREQ_HZ constant. - hardware/serial_util.py: shared 8N1 open + scored port enumeration (promoted from t3r_control_panel); helios_laser and the panel use it - sc3_aui_app.py and sras_scan_manager.py migrated onto core (three format implementations down to one); ScanWorker now takes a ScanPlan - tests: byte-identical writer vs golden, frontier over every truncation variant, mmap==eager, geometry vs golden fixtures + invariants, config round-trip. 28 passing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+3
-11
@@ -28,8 +28,8 @@ from PyQt6.QtWidgets import (
|
||||
)
|
||||
|
||||
from hardware.t3r_driver import T3RDriver
|
||||
from hardware.serial_util import scored_ports
|
||||
import hardware.t3r_protocol as proto
|
||||
import serial.tools.list_ports
|
||||
|
||||
|
||||
# ── Utilities ─────────────────────────────────────────────────────────────────
|
||||
@@ -613,16 +613,8 @@ class T3RControlPanel(QDialog):
|
||||
def _refresh_ports(self):
|
||||
current = self.port_combo.currentText()
|
||||
self.port_combo.clear()
|
||||
ports = list(serial.tools.list_ports.comports())
|
||||
|
||||
def score(p):
|
||||
text = f"{p.description} {p.manufacturer or ''} {p.product or ''}".lower()
|
||||
hints = ("esp32", "jtag", "espressif", "usb serial", "cp210", "ch340", "cdc")
|
||||
return -sum(h in text for h in hints)
|
||||
|
||||
ports.sort(key=score)
|
||||
for p in ports:
|
||||
self.port_combo.addItem(f"{p.device} — {p.description or p.device}", p.device)
|
||||
for device, label in scored_ports():
|
||||
self.port_combo.addItem(label, device)
|
||||
if self.port_combo.count() == 0:
|
||||
self.port_combo.addItem("(no serial ports found)", None)
|
||||
elif current:
|
||||
|
||||
Reference in New Issue
Block a user