diff --git a/pyproject.toml b/pyproject.toml
index 5e9b1cdf..c61e8620 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"uv",
- "aarecommon>=0.7.3",
+ "aarecommon>=0.8.0",
"pydantic>=2.11",
"numpy",
"jfjoch_client>=1.0.0rc165",
diff --git a/src/aare/beamline_dispatch/protocols.py b/src/aare/beamline_dispatch/protocols.py
index b833dda8..fbd1f111 100644
--- a/src/aare/beamline_dispatch/protocols.py
+++ b/src/aare/beamline_dispatch/protocols.py
@@ -31,6 +31,9 @@ class BecMacros(ABC):
@staticmethod
@abstractmethod
def auto_exposure(): ...
+ @staticmethod
+ @abstractmethod
+ def full_flux_ph_per_s() -> float: ...
class Geometry(ABC):
diff --git a/src/aare/beamline_dispatch/simulated/beamline_dispatch.py b/src/aare/beamline_dispatch/simulated/beamline_dispatch.py
index ed14548e..fe06ba2f 100644
--- a/src/aare/beamline_dispatch/simulated/beamline_dispatch.py
+++ b/src/aare/beamline_dispatch/simulated/beamline_dispatch.py
@@ -17,8 +17,8 @@ class SimulatedBecMacros(BecMacros):
@staticmethod
def save_current_position(device, position, axis=None, force=False, max_delta=0.5) -> None: ...
@staticmethod
- def init_beamline_environment() -> tuple[Any, Any, Any]:
- return (None, None, None)
+ def init_beamline_environment() -> tuple[Any, Any]:
+ return (None, None)
@staticmethod
def bl_energy(energy_ev, move_gap=True, mono_scan=True, plot=True): ...
@@ -28,6 +28,9 @@ class SimulatedBecMacros(BecMacros):
def mono_pitch_scan(plot=True): ...
@staticmethod
def auto_exposure(): ...
+ @staticmethod
+ def full_flux_ph_per_s() -> float:
+ return 42
class SimulatedDispatch(DefaultDispatch):
diff --git a/src/aare/beamline_dispatch/x06da/beamline_dispatch.py b/src/aare/beamline_dispatch/x06da/beamline_dispatch.py
index 89cec67c..e88448d7 100644
--- a/src/aare/beamline_dispatch/x06da/beamline_dispatch.py
+++ b/src/aare/beamline_dispatch/x06da/beamline_dispatch.py
@@ -36,6 +36,11 @@ class X06daBecMacros(BecMacros):
self.mono_pitch_scan = mono_pitch_scan
self.auto_exposure = auto_exposure
+ def full_flux_ph_per_s():
+ return 400_000_000_000
+
+ self.full_flux_ph_per_s = full_flux_ph_per_s
+
@staticmethod
def save_and_reload() -> tuple[Any, Any]: ...
@staticmethod
@@ -50,6 +55,8 @@ class X06daBecMacros(BecMacros):
def mono_pitch_scan(plot=True): ...
@staticmethod
def auto_exposure(): ...
+ @staticmethod
+ def full_flux_ph_per_s() -> float: ...
class X06daGeometry(DefaultGeometry):
diff --git a/src/aare/beamline_dispatch/x10sa/beamline_dispatch.py b/src/aare/beamline_dispatch/x10sa/beamline_dispatch.py
index c721a7cb..fea4fe19 100644
--- a/src/aare/beamline_dispatch/x10sa/beamline_dispatch.py
+++ b/src/aare/beamline_dispatch/x10sa/beamline_dispatch.py
@@ -20,6 +20,9 @@ class X10SaBecMacros(BecMacros):
save_and_reload,
save_current_position,
)
+ from pxii_bec.macros.flux_macros import (
+ bpm2flux, # pyright: ignore[reportMissingImports, reportMissingModuleSource]
+ )
from pxii_bec.macros.katscripts import ( # pyright: ignore[reportMissingImports, reportMissingModuleSource]
auto_exposure,
)
@@ -53,6 +56,11 @@ class X10SaBecMacros(BecMacros):
self.auto_exposure = _auto_exposure
+ def full_flux_ph_per_s():
+ return bpm2flux()[1]
+
+ self.full_flux_ph_per_s = full_flux_ph_per_s
+
@staticmethod
def save_and_reload() -> tuple[Any, Any]: ...
@staticmethod
@@ -67,6 +75,8 @@ class X10SaBecMacros(BecMacros):
def mono_pitch_scan(plot=True): ...
@staticmethod
def auto_exposure(): ...
+ @staticmethod
+ def full_flux_ph_per_s() -> float: ...
class _1dModel(BeamCenterModel):
diff --git a/src/aare/daq/devices.py b/src/aare/daq/devices.py
index c655169d..7a2416ab 100644
--- a/src/aare/daq/devices.py
+++ b/src/aare/daq/devices.py
@@ -4,6 +4,7 @@ import time
from aarecommon.config.beamline import cfg_get
from aarecommon.config.logger import setup_logger
from aarecommon.config.logger_events import log_timing
+from aarecommon.config.util import suppress_output
from aarecommon.math.coordinate import AerotechCoordinate, SmargonCoordinate
from aarecommon.models.beamline import MXBeamline
from aarecommon.models.models import BeamlineStateEnum, SampleCameraSettings, StagePositionEnum
@@ -206,18 +207,16 @@ class BeamlineDevices:
@property
def flux(self) -> float:
- # TODO FLUX
- if self._beamline == MXBeamline.X10SA:
- return self.bec_worker.get_flux_x10sa()
return self.transmission * self.full_flux
@property
def full_flux(self) -> float:
- # TODO wire real flux - i0 needed
- max_flux = cfg_get("daq.maximum_flux")
- if max_flux is None:
- return 0.0
- return max_flux
+ try:
+ with suppress_output():
+ return self._dispatch.bec_macros.full_flux_ph_per_s()
+ except Exception as e: # noqa
+ logger.error(f"Could not get flux from BEC macro {e}")
+ return 9.99e12
# Cryojet
@property
diff --git a/src/aare/daq/server.py b/src/aare/daq/server.py
index 60b293af..13dbb7c5 100644
--- a/src/aare/daq/server.py
+++ b/src/aare/daq/server.py
@@ -1723,7 +1723,6 @@ async def set_smart_params(p: SimpleScanParameters, token: str = Depends(oauth2_
@app.post("/scan/cancel")
-@needs_hw_lock
async def cancel(token: str = Depends(oauth2_scheme)):
"""
Cancel the currently running scan or automation.
diff --git a/src/aare/gui/threads/daq_worker.py b/src/aare/gui/threads/daq_worker.py
index a5989aa7..d395fe07 100644
--- a/src/aare/gui/threads/daq_worker.py
+++ b/src/aare/gui/threads/daq_worker.py
@@ -672,10 +672,7 @@ class DAQWorker(QObject):
elif status in (404, 410, 417):
self.sample_missing.emit(error_info.message)
elif error_info.code in QUIET_OPERATION_ERROR_CODES:
- # Blocking-but-benign (e.g. "Beamline is busy"): inform quietly,
- # no modal pop-up and no automation pause.
- logger.info(f"Action unavailable: {error_info.message}")
- self.status_message.emit(error_info.message, True)
+ pass
else:
logger.error(f"{error_info.message}")
title = self._operation_error_title(error_info.exception_class)
diff --git a/src/aare/gui/widgets/status_bar.py b/src/aare/gui/widgets/status_bar.py
index e235453a..5fe1b790 100644
--- a/src/aare/gui/widgets/status_bar.py
+++ b/src/aare/gui/widgets/status_bar.py
@@ -67,7 +67,7 @@ class StatusBar(QStatusBar):
self.sharpness = ValueLabel("Samcam image sharpness", "", self)
self.samcam_fps = ValueLabel("Samcam FPS", "fps", self)
- self.flux = ValueLabel("Flux", "x 109 ph/s", self)
+ self.flux = ValueLabel("Flux", "ph/s", self)
self.transmission = ValueLabel("Transmission", "", self)
self.ring_current = ValueLabel("Ring current", "mA", self)
self.wvl = ValueLabel("Wavelength", "Å", self)
@@ -169,10 +169,16 @@ class StatusBar(QStatusBar):
def update_daq_status(self, status: DAQStatusModel):
try:
self._status = status
- if status.bl.flux_ph_s is None:
+ if status.bl.flux_ph_s is None or status.bl.transmission is None:
self.flux.set_value("0")
else:
- self.flux.set_value(f"{(status.bl.flux_ph_s / 1e9):.0f}")
+ try:
+ num = f"{(status.bl.flux_ph_s / status.bl.transmission):.2E}"
+ mod, exp = num.split("E")
+ self.flux.set_value(f"{mod} x 10{int(exp)}")
+ except Exception as e: # noqa
+ logger.error(f"Error parsing flux result: {e}")
+ self.flux.set_value(f"{status.bl.flux_ph_s:.2E}")
if status.bl.transmission is None:
self.transmission.set_value("(moving)")