From c3e454a5043ef71c0103b58aa3cf5ffe4e14c602 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Fri, 26 Sep 2025 13:55:46 +0200 Subject: [PATCH] Prediction (WIP) --- daq/src/aaredaq/workflows.py | 1 + gui/src/aaregui/gui.py | 1 + gui/src/aaregui/main_window.py | 1 + gui/src/aaregui/panels/samcam_panel.py | 11 +++++- gui/src/aaregui/widgets/camera_image.py | 48 +++++++++++++++++-------- 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/daq/src/aaredaq/workflows.py b/daq/src/aaredaq/workflows.py index dddd2a22..5c49b82d 100644 --- a/daq/src/aaredaq/workflows.py +++ b/daq/src/aaredaq/workflows.py @@ -64,6 +64,7 @@ def common_2rse(devs: BeamlineDevices, cfg: BeamlineConfig): devs.reflector_up = False print(time.ctime(), " LOCKING AEROTERCH") devs.aerotech.lock() + print(time.ctime(), f" Smargon position in RSE: {devs.smargon.readback} ABS: {devs.abr_pos.x} {devs.abr_pos.y} {devs.abr_pos.z}") def m2se(devs: BeamlineDevices, cfg: BeamlineConfig): diff --git a/gui/src/aaregui/gui.py b/gui/src/aaregui/gui.py index fd9784af..ca794750 100644 --- a/gui/src/aaregui/gui.py +++ b/gui/src/aaregui/gui.py @@ -6,6 +6,7 @@ from PySide6.QtWidgets import QApplication, QDialog from aaregui.main_window import MainWindow from aaregui.widgets.login import LoginDialog from aaredaqlib.beamline import MXBeamline, mx_beamline +from aaregui.auth import auth if __name__ == "__main__": app = QApplication(sys.argv) diff --git a/gui/src/aaregui/main_window.py b/gui/src/aaregui/main_window.py index d7c768c3..41cfdee5 100644 --- a/gui/src/aaregui/main_window.py +++ b/gui/src/aaregui/main_window.py @@ -193,6 +193,7 @@ class MainWindow(QMainWindow): self.beamline.beam_size.beam_size.connect(self.daq.beam_size_mm) self.sample_camera.load_image.connect(self.raster.load_image) self.sample_camera.switch_raster_grid.connect(self.data_collection.switch_to_raster) + self.beamline.samcam.show_detections_changed.connect(self.sample_camera.set_show_detections) if zmq_addr is not None: self.camera_thread = SampleCameraThread(zmq_url=zmq_addr) diff --git a/gui/src/aaregui/panels/samcam_panel.py b/gui/src/aaregui/panels/samcam_panel.py index afc261d9..abeebc78 100644 --- a/gui/src/aaregui/panels/samcam_panel.py +++ b/gui/src/aaregui/panels/samcam_panel.py @@ -1,4 +1,4 @@ -from PySide6.QtWidgets import QWidget, QSpinBox, QVBoxLayout, QHBoxLayout, QLabel, QDoubleSpinBox +from PySide6.QtWidgets import QWidget, QSpinBox, QVBoxLayout, QHBoxLayout, QLabel, QDoubleSpinBox, QCheckBox from PySide6.QtCore import Signal, Slot from aaredaqlib.models import SampleCameraSettings, DAQStatusModel @@ -8,6 +8,7 @@ from aaregui.widgets.title_label import TitleLabel class SamcamPanel(QWidget): # Signals for when exposure or gain values change changed = Signal(SampleCameraSettings) + show_detections_changed = Signal(bool) old_settings = SampleCameraSettings(gain=100, exposure=0.001) def __init__(self, parent=None): @@ -43,9 +44,17 @@ class SamcamPanel(QWidget): gain_layout.addWidget(gain_label) gain_layout.addWidget(self.gain_spinbox) + # Show detections checkbox + detections_layout = QHBoxLayout() + self.show_detections_checkbox = QCheckBox("Show ML detections") + self.show_detections_checkbox.setChecked(True) # Default to checked + self.show_detections_checkbox.toggled.connect(self.show_detections_changed.emit) + detections_layout.addWidget(self.show_detections_checkbox) + # Add controls to main layout layout.addLayout(exposure_layout) layout.addLayout(gain_layout) + layout.addLayout(detections_layout) self.setLayout(layout) def __changed(self): diff --git a/gui/src/aaregui/widgets/camera_image.py b/gui/src/aaregui/widgets/camera_image.py index 66083dfc..d4192ae0 100644 --- a/gui/src/aaregui/widgets/camera_image.py +++ b/gui/src/aaregui/widgets/camera_image.py @@ -75,6 +75,7 @@ class SampleCameraImageLabel(QGraphicsView): self.__helical_end = SmargonCoordinate() self.__raster_alpha = 127 self.__bounding_box = None + self.__show_detections = True self.start_point = None # Starting point of the rectangle self.end_point = None # Ending point of the rectangle @@ -114,12 +115,21 @@ class SampleCameraImageLabel(QGraphicsView): @Slot(dict) def update_detections(self, payload: dict): # payload: { 'time', 'frame_id', 'shape':[h,w], 'boxes':[{'x1',...,'label','conf'}] } + #print(f"DEBUG: Full payload received: {payload}") try: self.__det_shape = payload.get('shape', None) self.__detections = payload.get('boxes', []) or [] - except Exception: + #print(f"DEBUG: Received {len(self.__detections)} detections, shape: {self.__det_shape}") + #if self.__detections: + # print(f"DEBUG: First detection: {self.__detections[0]}") + + # Check for other possible keys in the payload + #print(f"DEBUG: Available keys in payload: {list(payload.keys())}") + + except Exception as e: + #print(f"DEBUG: Exception in update_detections: {e}") self.__detections = [] - self.update() # trigger redraw + self.update() def __draw_busy_overlay(self, painter: QPainter, rect): """Draw 'BEAMLINE BUSY' text overlay when DAQ is in busy state.""" @@ -419,7 +429,9 @@ class SampleCameraImageLabel(QGraphicsView): ) self.smargon.emit(smargon_coord) - def __draw_detections(self, painter: QPainter): + def __draw_detections(self, painter: QPainter, rect): + if not self.__show_detections: + return if not getattr(self, "_SampleCameraImageLabel__detections", None): return if self.pixmap_item is None: @@ -448,10 +460,6 @@ class SampleCameraImageLabel(QGraphicsView): 'crystal': QColor('blue'), } - pen = QPen() - pen.setWidth(2) - painter.setBrush(Qt.BrushStyle.NoBrush) - for det in self.__detections: try: x1 = det['x1'] * sx @@ -464,18 +472,28 @@ class SampleCameraImageLabel(QGraphicsView): continue color = color_map.get(label, QColor('magenta')) - pen.setColor(color) + + # Draw only the rectangle outline (no fill) + pen = QPen(color, 3) painter.setPen(pen) - rect = QRect(int(x1), int(y1), int(max(1, x2 - x1)), int(max(1, y2 - y1))) - painter.drawRect(rect) - # label text background for readability - painter.setPen(QPen(QColor(0, 0, 0), 0)) + painter.setBrush(Qt.BrushStyle.NoBrush) + detection_rect = QRect(int(x1), int(y1), int(max(1, x2 - x1)), int(max(1, y2 - y1))) + painter.drawRect(detection_rect) + + # Draw label text with white text on colored background + painter.setPen(QPen(QColor(255, 255, 255), 1)) painter.setBrush(color) - # draw small background rectangle then label text - painter.drawRect(QRect(int(x1), int(y1 - 16), int(8 + 7 * len(label)), 16)) - painter.setPen(QPen(QColor(0, 0, 0))) + text_bg_rect = QRect(int(x1), int(y1 - 16), int(8 + 7 * len(label)), 16) + painter.drawRect(text_bg_rect) + painter.setPen(QPen(QColor(255, 255, 255))) painter.drawText(QPoint(int(x1) + 2, int(y1 - 4)), f"{label} {conf:.2f}") + @Slot(bool) + def set_show_detections(self, show: bool): + """Slot to enable/disable showing ML detections""" + self.__show_detections = show + self.update() # Trigger redraw + def __draw_ml_bounding_box(self, painter: QPainter): if self.__bounding_box is None: return