Fix/sticky filters #252
No files matched your search
@@ -1,21 +0,0 @@
|
||||
from aarecommon.config.beamline import mx_beamline
|
||||
|
||||
from aare.daq.aaredb import AareWrapper
|
||||
from aare.daq.config import BeamlineConfig
|
||||
from aare.daq.daq import AareDAQ
|
||||
from aare.daq.devices import BeamlineDevices
|
||||
from aare.devices.jfjoch import JFJochWrapper
|
||||
|
||||
bl = mx_beamline()
|
||||
j = JFJochWrapper(bl)
|
||||
a = AareWrapper(bl)
|
||||
c = BeamlineConfig(bl)
|
||||
d = BeamlineDevices(bl)
|
||||
daq = AareDAQ(bl=bl, cfg=c)
|
||||
result = j.wait_till_done(60)
|
||||
a.ingest_scan(
|
||||
sample=c.current_sample,
|
||||
result=result,
|
||||
geom=daq.sample_geometry,
|
||||
beam_mark_pxl=c.get_beam_mark(d.zoom),
|
||||
)
|
||||
@@ -20,17 +20,17 @@ 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,
|
||||
from pxii_bec.macros.flux_macros import ( # pyright: ignore[reportMissingImports, reportMissingModuleSource]
|
||||
bpm2flux,
|
||||
)
|
||||
from pxii_bec.macros.pxii_energy import ( # pyright: ignore[reportMissingImports, reportMissingModuleSource]
|
||||
bl_energy,
|
||||
get_current_energy,
|
||||
mono_pitch_scan,
|
||||
)
|
||||
from pxii_bec.macros.pxii_setup import ( # pyright: ignore[reportMissingImports, reportMissingModuleSource]
|
||||
auto_exposure,
|
||||
)
|
||||
from pxii_bec.scripts.init_beamline import ( # pyright: ignore[reportMissingImports, reportMissingModuleSource]
|
||||
init_beamline_environment,
|
||||
)
|
||||
|
||||
+4
-1
@@ -291,7 +291,7 @@ class AareDAQ:
|
||||
self.last_time = 0.0
|
||||
self._dispatch = dispatch
|
||||
self._cfg = cfg
|
||||
self._devs = BeamlineDevices(bl, dispatch)
|
||||
self._devs = BeamlineDevices(bl, dispatch, cfg)
|
||||
self._mlbox = MlBox(bl)
|
||||
self._jfjoch = JFJochWrapper(bl)
|
||||
self._bl = bl.value.upper()
|
||||
@@ -1978,6 +1978,9 @@ class AareDAQ:
|
||||
# on completion correctly
|
||||
logger.debug("Sleeping to ensure transmission set completes due to IOC issues")
|
||||
time.sleep(2)
|
||||
if self._devs.transmission == 0:
|
||||
logger.warning("Transmission move still not completed, sleeping another 2s")
|
||||
time.sleep(2)
|
||||
|
||||
start_pos = getattr(request, "start", None)
|
||||
if start_pos is not None:
|
||||
|
||||
@@ -375,16 +375,3 @@ class BeamlineDevices:
|
||||
|
||||
def read_current_state_from_bec(self) -> BeamlineStateEnum:
|
||||
return self.bec_worker.read_current_state()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from aarecommon.config.beamline import mx_beamline
|
||||
|
||||
beamline = mx_beamline()
|
||||
devs = BeamlineDevices(beamline)
|
||||
devs.bec_worker.scilog_msg(
|
||||
message="Testing DAQ hijack of BEC sci log communication channel", color="blue"
|
||||
)
|
||||
# devs.aerotech_pos = Coordinate(x=124.0, y=1.0, z=1.0)
|
||||
# print(devs.aerotech_pos)
|
||||
# devs.aerotech_omega = 0.0
|
||||
@@ -3,6 +3,7 @@ import time
|
||||
from aarecommon.config.logger import setup_logger
|
||||
from aarecommon.models.models import SampleCameraSettings
|
||||
|
||||
from aare.beamline_dispatch.beamline_dispatch import get_beamline_dispatch
|
||||
from aare.daq.config import ABR_OMEGA_MOUNT, ABR_POS_MOUNT, BeamlineConfig
|
||||
from aare.daq.devices import BeamlineDevices
|
||||
from aare.devices.area_detector import AutoEnum
|
||||
@@ -284,7 +285,7 @@ if __name__ == "__main__":
|
||||
|
||||
beamline = mx_beamline()
|
||||
config = BeamlineConfig(beamline)
|
||||
devices = BeamlineDevices(beamline)
|
||||
devices = BeamlineDevices(beamline, get_beamline_dispatch(), config)
|
||||
common_2rse(devices, config)
|
||||
time.sleep(10.0)
|
||||
rse2sa(devices, config)
|
||||
@@ -876,11 +876,6 @@ class MainWindow(QMainWindow):
|
||||
for locked_banner in self._locked_beamline_banners:
|
||||
locked_banner.installEventFilter(self)
|
||||
|
||||
self._idle_timer = QTimer(self)
|
||||
self._idle_timer.setInterval(60_000)
|
||||
self._idle_timer.timeout.connect(self._check_idle_timeout)
|
||||
self._idle_timer.start()
|
||||
|
||||
self._remote_close_timer = QTimer(self)
|
||||
self._remote_close_timer.setInterval(1000)
|
||||
self._remote_close_timer.timeout.connect(self._check_remote_close_deadline)
|
||||
@@ -3190,18 +3185,3 @@ class MainWindow(QMainWindow):
|
||||
|
||||
logger.warning("Closing GUI due to remote close request.")
|
||||
self.close()
|
||||
|
||||
@Slot()
|
||||
def _check_idle_timeout(self) -> None:
|
||||
idle_for_s = time.time() - self._last_user_interaction_ts
|
||||
if idle_for_s < self._idle_close_timeout_s:
|
||||
return
|
||||
|
||||
if not self._can_close_for_idle_or_remote():
|
||||
logger.info(
|
||||
"Idle timeout reached, but GUI remains open because beamline is busy or automation is active."
|
||||
)
|
||||
return
|
||||
# TODO deny communication from GUI to DAQ while IDLE for too long rather than kill the GUI
|
||||
logger.warning("Closing GUI after inactivity timeout.")
|
||||
self.close()
|
||||
@@ -110,8 +110,8 @@ class SampleQueuePanel(QFrame):
|
||||
self.pause_on_conditions_cb.setChecked(True)
|
||||
self.pause_on_conditions_cb.setToolTip(
|
||||
"When on, automation refuses to start and pauses between samples if the beam, "
|
||||
"experiment shutter, hutch doors or robot are not ready, auto-resuming when they "
|
||||
"recover. Uncheck for testing to run straight through."
|
||||
"experiment shutter, hutch doors or robot are not ready. Uncheck for testing "
|
||||
"to run straight through."
|
||||
)
|
||||
|
||||
button_layout.addWidget(self.play_button)
|
||||
@@ -426,8 +426,8 @@ class SampleQueuePanel(QFrame):
|
||||
logger.warning(f"Automation paused; beamline not ready: {bad}")
|
||||
msg = "Automation paused — beamline not ready:\n- " + "\n- ".join(bad)
|
||||
|
||||
if conditions_auto_check(self, msg, self._conditions_ok):
|
||||
logger.debug("Conditions recovered or user chose to continue; resuming automation")
|
||||
if conditions_auto_check(self, msg):
|
||||
logger.debug("User chose to continue; resuming automation")
|
||||
self.table_model.set_running(True)
|
||||
self._pause = False
|
||||
self.play_button.setText("⏸ Pause")
|
||||
|
||||
@@ -89,40 +89,12 @@ def reply_box(parent, title: str = "Warning", msg: str = "Warning."):
|
||||
)
|
||||
|
||||
|
||||
def timer_box(
|
||||
parent, title: str = "Warning", msg: str = "Warning.", condition_func=None
|
||||
) -> QMessageBox:
|
||||
def continue_msg_box(parent, title: str = "Warning", msg: str = "Warning.") -> QMessageBox:
|
||||
box = QMessageBox(parent)
|
||||
box.setWindowTitle(title)
|
||||
box.setText(f"{msg} Do you wish to continue?")
|
||||
box.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
|
||||
box.show()
|
||||
|
||||
timer = QTimer(box)
|
||||
timer.setInterval(300)
|
||||
|
||||
def stop_timer():
|
||||
if timer.isActive():
|
||||
timer.stop()
|
||||
|
||||
def check():
|
||||
if not box.isVisible():
|
||||
stop_timer()
|
||||
return
|
||||
try:
|
||||
if condition_func and condition_func():
|
||||
# Auto-accept (as if user pressed Yes)
|
||||
box.done(QMessageBox.StandardButton.Yes)
|
||||
stop_timer()
|
||||
except Exception:
|
||||
# Never let errors in condition_func block UI
|
||||
logger.exception("Error in condition_func")
|
||||
|
||||
box.accepted.connect(stop_timer)
|
||||
box.rejected.connect(stop_timer)
|
||||
timer.timeout.connect(check)
|
||||
|
||||
timer.start()
|
||||
return box
|
||||
|
||||
|
||||
@@ -163,10 +135,10 @@ def ring_current_auto_check(parent, ring_current, check_func) -> bool:
|
||||
if ring_current is None
|
||||
else f"Ring current is low {round(ring_current, 2)} mA."
|
||||
)
|
||||
return conditions_auto_check(parent, msg, check_func, title="Ring current too low")
|
||||
return conditions_auto_check(parent, msg, title="Ring current too low")
|
||||
|
||||
|
||||
def conditions_auto_check(parent, msg: str, check_func, title: str = "Beamline not ready") -> bool:
|
||||
def conditions_auto_check(parent, msg: str, title: str = "Beamline not ready") -> bool:
|
||||
"""Pause-and-wait dialog that auto-resumes when ``check_func()`` becomes True.
|
||||
|
||||
Used to hold automation between samples until the beamline recovers. The
|
||||
@@ -174,7 +146,7 @@ def conditions_auto_check(parent, msg: str, check_func, title: str = "Beamline n
|
||||
can also click 'Yes' to continue now (override) or 'No' to stop automation.
|
||||
Returns True to resume, False to stop.
|
||||
"""
|
||||
box = timer_box(parent, title=title, msg=msg, condition_func=check_func)
|
||||
box = continue_msg_box(parent, title=title, msg=msg)
|
||||
loop = QEventLoop()
|
||||
|
||||
def finish(_=None):
|
||||
|
||||
@@ -352,85 +352,6 @@ def test_automation_activity_refreshes_idle_timestamp(qtbot, mock_ui_state):
|
||||
assert win._remote_close_deadline_ts is None
|
||||
|
||||
|
||||
def test_idle_timeout_closes_when_inactive_and_not_running(qtbot, mock_ui_state):
|
||||
with (
|
||||
patch("requests.get"),
|
||||
patch("aare.gui.main_window.DAQWorker"),
|
||||
patch("aare.gui.main_window.PredictionSubscriber"),
|
||||
patch("aare.gui.main_window.VideoThread"),
|
||||
patch("aare.gui.main_window.JFJochDBusClient"),
|
||||
patch("aare.gui.main_window.jwt.decode") as mock_jwt,
|
||||
):
|
||||
mock_jwt.return_value = {
|
||||
"sub": "testuser",
|
||||
"staff": True,
|
||||
"pgroups": ["p123"],
|
||||
"session": 15,
|
||||
}
|
||||
fake_token = "header.payload.signature"
|
||||
|
||||
win = MainWindow(
|
||||
base_url=None,
|
||||
token=fake_token,
|
||||
default_image=None,
|
||||
zmq_addr=None,
|
||||
pred_zmq_addr=None,
|
||||
beamline_cam_addr=None,
|
||||
gonio_cam_addr=None,
|
||||
gonio_cam_id=None,
|
||||
)
|
||||
qtbot.addWidget(win)
|
||||
|
||||
win._idle_close_timeout_s = 10
|
||||
win._last_user_interaction_ts = 100.0
|
||||
win.close = MagicMock()
|
||||
|
||||
with patch("aare.gui.main_window.time.time", return_value=111.0):
|
||||
win._check_idle_timeout()
|
||||
|
||||
win.close.assert_called_once()
|
||||
|
||||
|
||||
def test_idle_timeout_does_not_close_while_automation_active(qtbot, mock_ui_state):
|
||||
with (
|
||||
patch("requests.get"),
|
||||
patch("aare.gui.main_window.DAQWorker"),
|
||||
patch("aare.gui.main_window.PredictionSubscriber"),
|
||||
patch("aare.gui.main_window.VideoThread"),
|
||||
patch("aare.gui.main_window.JFJochDBusClient"),
|
||||
patch("aare.gui.main_window.jwt.decode") as mock_jwt,
|
||||
):
|
||||
mock_jwt.return_value = {
|
||||
"sub": "testuser",
|
||||
"staff": True,
|
||||
"pgroups": ["p123"],
|
||||
"session": 15,
|
||||
}
|
||||
fake_token = "header.payload.signature"
|
||||
|
||||
win = MainWindow(
|
||||
base_url=None,
|
||||
token=fake_token,
|
||||
default_image=None,
|
||||
zmq_addr=None,
|
||||
pred_zmq_addr=None,
|
||||
beamline_cam_addr=None,
|
||||
gonio_cam_addr=None,
|
||||
gonio_cam_id=None,
|
||||
)
|
||||
qtbot.addWidget(win)
|
||||
|
||||
win._idle_close_timeout_s = 10
|
||||
win._last_user_interaction_ts = 100.0
|
||||
win.job_list_panel.is_running = MagicMock(return_value=True)
|
||||
win.close = MagicMock()
|
||||
|
||||
with patch("aare.gui.main_window.time.time", return_value=111.0):
|
||||
win._check_idle_timeout()
|
||||
|
||||
win.close.assert_not_called()
|
||||
|
||||
|
||||
def _make_window(qtbot):
|
||||
win = MainWindow(
|
||||
base_url=None,
|
||||
|
||||
@@ -8,7 +8,6 @@ from aare.gui.widgets.message_box import (
|
||||
reply_box,
|
||||
ring_current_auto_check,
|
||||
ring_current_low_check,
|
||||
timer_box,
|
||||
)
|
||||
|
||||
|
||||
@@ -21,19 +20,6 @@ def test_reply_box(qtbot):
|
||||
mock_question.assert_called_once()
|
||||
|
||||
|
||||
def test_timer_box_auto_accept(qtbot):
|
||||
parent = None
|
||||
condition_func = MagicMock(return_value=True)
|
||||
|
||||
# We need to process events for timer to fire
|
||||
box = timer_box(parent, condition_func=condition_func)
|
||||
|
||||
# Wait until box is closed by check()
|
||||
qtbot.waitUntil(lambda: not box.isVisible(), timeout=2000)
|
||||
|
||||
assert box.result() == QMessageBox.StandardButton.Yes
|
||||
|
||||
|
||||
@pytest.mark.timeout(10)
|
||||
def test_ring_current_low_check_ok(qtbot):
|
||||
# Should return True immediately if current is high enough
|
||||
|
||||
Reference in new issue
Block a user