feat: Wafer Map integration
## Backend — Session & playback - Add SessionController (QML-facing live/review controller) with loadedFile property for active-file highlight binding - Add SessionModel, FramePlayer, and CsvRecorder for state machine, frame seek/step/speed, and CSV recording - Add SensorEditor for per-sensor value overrides (replace + offset)
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
"""Append live frames"""
|
||||
from __future__ import annotations
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Optional, TextIO
|
||||
|
||||
|
||||
from pygui.backend.frame import Frame
|
||||
from pygui.backend.zwafer_models import Sensor
|
||||
|
||||
class CsvRecorder:
|
||||
def __init__(self) -> None:
|
||||
self._file_handle: Optional[TextIO] = None
|
||||
self._oath: Optional[str] = None
|
||||
|
||||
|
||||
@property
|
||||
def is_recording(self) -> bool:
|
||||
return self._file_handle is not None
|
||||
|
||||
|
||||
def start(self, path: str, sensors:list[Sensor], serial: str = "") -> None:
|
||||
Path(path).parent.mkdir(parents=True, exist_ok=True)
|
||||
file_handle = open(path, "w", encoding="utf-8", newline ="")
|
||||
file_handle.write(f"Wafer ID={serial}\n")
|
||||
file_handle.write(f"Acquisition Date={datetime.now():%m/%d/%Y}\n")
|
||||
file_handle.write("Label," + ",".join(s.label for s in sensors) + "\n")
|
||||
file_handle.write("X (mm)," + ",".join(str(s.x) for s in sensors) + "\n")
|
||||
file_handle.write("Y (mm)," + ",".join(str(s.y) for s in sensors) + "\n")
|
||||
file_handle.write("data\n")
|
||||
file_handle.flush()
|
||||
self._file_handle, self._path = file_handle, path
|
||||
|
||||
def write(self, frame: Frame) -> None:
|
||||
if self._file_handle is None:
|
||||
return
|
||||
row = [f"{frame.time:.3f}"] + [f"{v:.3f}" for v in frame.values]
|
||||
self._file_handle.write(",".join(row) + "\n")
|
||||
self._file_handle.flush()
|
||||
|
||||
def stop(self) -> Optional[str]:
|
||||
if self._file_handle is None:
|
||||
return None
|
||||
self._file_handle.close()
|
||||
path, self._file_handle, self._path = self._path, None, None
|
||||
return path
|
||||
Reference in New Issue
Block a user