From b3502e722ac3105ed71f5c0a1afb4c1595ab6992 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Thu, 13 Nov 2025 11:31:29 +0100 Subject: [PATCH] GUI: Fluorescence further improvements --- common/src/aaredaqlib/models.py | 1 + daq/src/aaredaq/daq.py | 16 ++++++--- daq/src/aaredaq/workflows.py | 14 ++------ gui/src/aaregui/panels/fluorescence_panel.py | 37 ++++++++++++++++++-- gui/src/aaregui/widgets/status_bar.py | 2 ++ 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/common/src/aaredaqlib/models.py b/common/src/aaredaqlib/models.py index 0f91fdbb..18950147 100644 --- a/common/src/aaredaqlib/models.py +++ b/common/src/aaredaqlib/models.py @@ -438,6 +438,7 @@ class FluorescenceSpectrumOutputModel(BaseModel): bkg: list[float] | None = None spectrum: list[float] energy_eV: list[float] + average_dead_time: Annotated[float, Field(ge=0,le=1)] class MLBoxType(Enum): Loop_all = 0 diff --git a/daq/src/aaredaq/daq.py b/daq/src/aaredaq/daq.py index 196dc9f6..bbd36ad9 100644 --- a/daq/src/aaredaq/daq.py +++ b/daq/src/aaredaq/daq.py @@ -1522,8 +1522,11 @@ class AareDAQ: self.__cfg.state_busy = False def fluorimeter_take_spectrum(self, fm: FluorescenceSpectrumParameterModel) -> FluorescenceSpectrumOutputModel: - self.__cfg.set_busy(BeamlineStateEnum.SampleAlignment) + self.__cfg.try_set_busy(timeout=360) + try: + self.__set_state(BeamlineStateEnum.XrayFluorescence) + if fm.transmission is not None: self.__devs.transmission.set(fm.transmission, wait=True) @@ -1538,12 +1541,15 @@ class AareDAQ: offset = self.__devs.fluorimeter.offset slope = self.__devs.fluorimeter.slope # slope is in keV! energy = [slope * 1000.0 * i + offset for i in range(len(spectrum))] - + fluo_output = FluorescenceSpectrumOutputModel(spectrum=spectrum, + bkg=self.__devs.fluorimeter.get_current_background(), + energy_eV=energy, + average_dead_time=self.__devs.fluorimeter.average_dead_time() / 100.0) + self.__set_state(BeamlineStateEnum.SampleAlignment) self.__cfg.state_busy = False - return FluorescenceSpectrumOutputModel(spectrum=spectrum, - bkg=self.__devs.fluorimeter.get_current_background(), - energy_eV=energy) + return fluo_output except Exception as e: + self.__set_state(BeamlineStateEnum.SampleAlignment) self.__cfg.state_busy = False raise e diff --git a/daq/src/aaredaq/workflows.py b/daq/src/aaredaq/workflows.py index c4da5a3e..42f1c8ed 100644 --- a/daq/src/aaredaq/workflows.py +++ b/daq/src/aaredaq/workflows.py @@ -198,22 +198,12 @@ def dc2sa(devs: BeamlineDevices, cfg: BeamlineConfig): def sa2xrf(devs: BeamlineDevices, cfg: BeamlineConfig): """sample alignment to XrfCollection""" - if devs.dtz.position < 150.0: - devs.dtz.move(150.0) - devs.reflector_up = False - # devs.xrf_stage.move("measure") - devs.beamstop_stage_up = True - move_bsz(devs, 70.0) + pass def xrf2sa(devs: BeamlineDevices, cfg: BeamlineConfig): """XrfCollection to sample alignment""" - if devs.dtz.position < 150.0: - devs.dtz.move(150.0) - devs.reflector_up = False - # devs.xrf_stage.move("measure") - devs.beamstop_stage_up = True - move_bsz(devs, 70.0) + pass def sa2ws(devs: BeamlineDevices, cfg: BeamlineConfig): diff --git a/gui/src/aaregui/panels/fluorescence_panel.py b/gui/src/aaregui/panels/fluorescence_panel.py index 7ebb9722..7efe64e0 100644 --- a/gui/src/aaregui/panels/fluorescence_panel.py +++ b/gui/src/aaregui/panels/fluorescence_panel.py @@ -2,10 +2,10 @@ import numpy as np from PySide6.QtCharts import QChart, QChartView, QLineSeries, QValueAxis from PySide6.QtCore import QPointF, Qt, Slot, Signal, QEvent from PySide6.QtGui import QPainter, QColor, QPen -from PySide6.QtWidgets import QWidget, QGridLayout, QGraphicsSimpleTextItem +from PySide6.QtWidgets import QWidget, QGridLayout, QGraphicsSimpleTextItem, QLabel from aaredaqlib.logger_config import setup_logger -from aaredaqlib.models import FluorescenceSpectrumParameterModel, FluorescenceSpectrumOutputModel +from aaredaqlib.models import FluorescenceSpectrumOutputModel logger = setup_logger(__name__) @@ -38,6 +38,16 @@ class FluorescencePanel(QWidget): self.chart_view.setRenderHint(QPainter.Antialiasing) grid.addWidget(self.chart_view, 0, 0) + # Average dead time label + self.avg_dead_label = QLabel("Average dead time: -") + self.avg_dead_label.setAlignment(Qt.AlignLeft) + grid.addWidget(self.avg_dead_label, 1, 0) + + # Peak info label (energy/counts for highest value) + self.peak_info_label = QLabel("Peak: -") + self.peak_info_label.setAlignment(Qt.AlignLeft) + grid.addWidget(self.peak_info_label, 2, 0) + # Popup label for clicked point (use scene item instead of chart.addText) self._marker = QGraphicsSimpleTextItem("") self._marker.setVisible(False) @@ -136,18 +146,39 @@ class FluorescencePanel(QWidget): self._vline.setVisible(False) self._vline.clear() + # Update average dead time label (if provided) + try: + if hasattr(f, "average_dead_time") and f.average_dead_time is not None: + self.avg_dead_label.setText(f"Average dead time: {f.average_dead_time*100.0:.3f}%") + else: + self.avg_dead_label.setText("Average dead time: -") + except Exception: + self.avg_dead_label.setText("Average dead time: -") + + # Default peak label + self.peak_info_label.setText("Peak: -") + if len(f.spectrum) > 0 and len(f.spectrum) == len(f.energy_eV): x = np.array(f.energy_eV, dtype=float) / 1000.0 # keV y = np.array(f.spectrum, dtype=float) - # Ensure sorted by X for binary search + # Ensure sorted by X for binary search and consistent series order order = np.argsort(x) x = x[order] y = y[order] + # Append data for xi, yi in zip(x, y): self.series.append(float(xi), float(yi)) + # Peak info (highest Y) + if y.size: + max_idx = int(np.argmax(y)) + peak_keV = float(x[max_idx]) + peak_counts = float(y[max_idx]) + self.peak_info_label.setText(f"Peak: {peak_keV:.3f} keV, {peak_counts:.3f} counts") + + # Axes xmin = float(np.min(x)) if x.size else -1.0 xmax = float(np.max(x)) if x.size else 1.0 ymin = float(np.min(y)) if y.size else 0.0 diff --git a/gui/src/aaregui/widgets/status_bar.py b/gui/src/aaregui/widgets/status_bar.py index f4b1902a..287aa0ab 100644 --- a/gui/src/aaregui/widgets/status_bar.py +++ b/gui/src/aaregui/widgets/status_bar.py @@ -110,6 +110,8 @@ class StatusBar(QStatusBar): state = "Sample alignment" elif stateEnum == BeamlineStateEnum.DataCollection: state = "Data collection" + elif stateEnum == BeamlineStateEnum.XrayFluorescence: + state = "X-ray fluorescence" elif stateEnum == BeamlineStateEnum.DewarTransfer: state = "Dewar transfer" elif stateEnum == BeamlineStateEnum.Maintenance: