diff --git a/src/aare/gui/main_window.py b/src/aare/gui/main_window.py index caad5ee8..f73f5a49 100644 --- a/src/aare/gui/main_window.py +++ b/src/aare/gui/main_window.py @@ -252,6 +252,7 @@ class MainWindow(QMainWindow): self.camera_thread = SampleCameraThread(zmq_url=zmq_addr) self.camera_thread.camera_image.connect(self.sample_camera.update_pixmap) self.camera_thread.start() + self.camera_thread.focus_measure.connect(self.status_bar.update_sharpness) else: self.camera_thread = None diff --git a/src/aare/gui/threads/camera_thread.py b/src/aare/gui/threads/camera_thread.py index d14bc9d4..f1a61707 100644 --- a/src/aare/gui/threads/camera_thread.py +++ b/src/aare/gui/threads/camera_thread.py @@ -3,13 +3,14 @@ import json import cv2 import numpy as np import zmq -from PySide6.QtCore import QThread, Signal +from PySide6.QtCore import QThread, Signal, Slot from PySide6.QtGui import QImage, QPixmap class SampleCameraThread(QThread): # Define a signal to communicate messages from the thread to the main GUI camera_image = Signal(QPixmap) + focus_measure = Signal(float) # Emits Laplacian variance (higher = sharper) def __init__(self, zmq_url: str, parent=None): super().__init__(parent) @@ -20,6 +21,12 @@ class SampleCameraThread(QThread): self.__socket.connect(zmq_url) self.running = True + self.__measure_focus = True + + @Slot(bool) + def enable_focus_measurement(self, enabled: bool = True): + """Enable or disable focus measurement.""" + self.__measure_focus = enabled def run(self): while self.running: @@ -36,6 +43,12 @@ class SampleCameraThread(QThread): rgb_image = cv2.cvtColor(bayer_image, cv2.COLOR_BAYER_GB2RGB) #cv2.COLOR_BAYER_GB2RGB for ethernet connection rgb_image = rgb_image[:, ::-1, :].copy() + + if self.__measure_focus: + gray = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2GRAY) + laplacian = cv2.Laplacian(gray, cv2.CV_64F) + self.focus_measure.emit(float(laplacian.var())) + qimage = QImage(rgb_image.data, header_shape[1], header_shape[0], #For ethernet need header_shape[0], header_shape[1], header_shape[0]*3, QImage.Format.Format_RGB888) self.camera_image.emit(QPixmap.fromImage(qimage)) diff --git a/src/aare/gui/widgets/status_bar.py b/src/aare/gui/widgets/status_bar.py index 2075de40..0e0f037b 100644 --- a/src/aare/gui/widgets/status_bar.py +++ b/src/aare/gui/widgets/status_bar.py @@ -32,6 +32,7 @@ class StatusBar(QStatusBar): self.__is_staff = self.__decoded_token.staff self.__allowed_pgroups = self.__decoded_token.pgroups + self.sharpness = ValueLabel("Samcam image sharpness", "", self) self.flux = ValueLabel("Flux", "x 109 ph/s", self) self.transmission = ValueLabel("Transmission", "", self) self.ring_current = ValueLabel("Ring current", "mA", self) @@ -53,6 +54,7 @@ class StatusBar(QStatusBar): self.shutter_label.clicked.connect(self.show_shutter_menu) self.exp_shutter_label = ValueLabel("ExpHutch Shutter", "", self) + self.addPermanentWidget(self.sharpness) self.addPermanentWidget(self.flux) self.addPermanentWidget(self.transmission) self.addPermanentWidget(self.ring_current) @@ -66,6 +68,10 @@ class StatusBar(QStatusBar): self.addPermanentWidget(self.busy_label) self.addPermanentWidget(self.session_label) + @Slot(float) + def update_sharpness(self, val: float): + self.sharpness.set_value(f"{val:.3f}") + @Slot(DAQStatusModel) def update_daq_status(self, status: DAQStatusModel): self.__status = status