diff --git a/environment.yml b/environment.yml index 325f1dc2..ab545c1d 100644 --- a/environment.yml +++ b/environment.yml @@ -41,7 +41,7 @@ dependencies: - aioca - aiokafka - asynctest - - apsbss + - apsbss < 2.0 - time-machine - rich - autoapi diff --git a/src/firefly/tests/test_voltmeters.py b/src/firefly/tests/test_voltmeters.py index a1b2fc57..afd68b30 100644 --- a/src/firefly/tests/test_voltmeters.py +++ b/src/firefly/tests/test_voltmeters.py @@ -1,5 +1,8 @@ +import asyncio + import pytest from bluesky_queueserver_api import BPlan +from ophyd_async.core import Device from pydm import widgets as PyDMWidgets from pydm.widgets.analog_indicator import PyDMAnalogIndicator from qtpy import QtWidgets @@ -28,6 +31,19 @@ async def ion_chambers(sim_registry): return devices +@pytest.fixture() +async def shutters(sim_registry): + front_end_shutter = Device(name="front_end_shutter") + front_end_shutter.allow_close = False + endstation_shutter = Device(name="endstation_shutter") + shutters = [front_end_shutter, endstation_shutter] + await asyncio.gather(*[d.connect(mock=True) for d in shutters]) + for shutter in shutters: + shutter._ophyd_labels_ = {"shutters"} + sim_registry.register(shutter) + return shutters + + @pytest.fixture() async def voltmeters_display(qtbot, ion_chambers, sim_registry): vms_display = VoltmetersDisplay() @@ -151,14 +167,66 @@ def check_item(item): display.ui.auto_gain_button.click() +async def test_shutters_checkbox_no_shutters(voltmeters_display, sim_registry): + display = voltmeters_display + combobox = display.ui.shutter_combobox + checkbox = display.ui.shutter_checkbox + checkbox.setChecked(True) + # Update the state of the UI with no shutters + await display.update_devices(sim_registry) + # Ensure checkbox has been disabled + assert not checkbox.isEnabled() + assert not checkbox.checkState() + assert not display.ui.shutter_checkbox.setChecked(True) + combobox_items = [combobox.itemText(idx) for idx in range(combobox.count())] + assert len(combobox_items) == 0 + + +async def test_shutters_checkbox_with_shutters( + voltmeters_display, + sim_registry, + shutters, +): + display = voltmeters_display + checkbox = display.ui.shutter_checkbox + combobox = display.ui.shutter_combobox + # Update the state of the UI with no shutters + await display.update_devices(sim_registry) + # Ensure checkbox has been enabled + assert checkbox.isEnabled() + # Check that shutters were added to the combobox + combobox_items = [combobox.itemText(idx) for idx in range(combobox.count())] + assert "front_end_shutter" not in combobox_items + assert "endstation_shutter" in combobox_items + + @pytest.mark.asyncio async def test_read_dark_current_plan(voltmeters_display, qtbot): + display = voltmeters_display + display.ui.shutter_checkbox.setChecked(False) + # Check that the correct plan was sent + expected_item = BPlan("record_dark_current", ["I0", "It"]) + + def check_item(item): + return item.to_dict() == expected_item.to_dict() + + # Click the run button and see if the plan is queued + with qtbot.waitSignal( + display.queue_item_submitted, timeout=1000, check_params_cb=check_item + ): + # Simulate clicking on the dark_current button + # display.ui.dark_current_button.click() + display.ui.record_dark_current() + + +@pytest.mark.asyncio +async def test_read_dark_current_plan_with_shutters(voltmeters_display, qtbot): display = voltmeters_display display.ui.shutter_checkbox.setChecked(True) + display.ui.shutter_combobox.setCurrentIndex(1) # Check that the correct plan was sent - expected_item = BPlan( - "record_dark_current", ["I0", "It"], shutters=["experiment_shutter"] - ) + shutter_name = display.ui.shutter_combobox.itemText(1) + expected_item = BPlan("record_dark_current", ["I0", "It"], shutters=[shutter_name]) def check_item(item): return item.to_dict() == expected_item.to_dict() diff --git a/src/firefly/voltmeters.py b/src/firefly/voltmeters.py index 15772899..e0e56fba 100644 --- a/src/firefly/voltmeters.py +++ b/src/firefly/voltmeters.py @@ -71,6 +71,28 @@ async def update_devices(self, registry): # Connect the details button signal details_slot = partial(self.details_window_requested.emit, ic.name) row.details_button.clicked.connect(details_slot) + # Remove old shutters from the combobox + for idx in range(self.ui.shutter_combobox.count()): + self.ui.shutter_combobox.removeItem(idx) + + # Decide which shutters we should show (only those that can be opened/closed) + def is_controllable(shtr): + can_open = getattr(shtr, "allow_open", True) + can_close = getattr(shtr, "allow_close", True) + return can_open and can_close + + shutters = registry.findall("shutters", allow_none=True) + shutters = [shtr for shtr in shutters if is_controllable(shtr)] + has_shutters = bool(len(shutters)) + # Add the shutters to the shutter combobox + if has_shutters: + self.ui.shutter_checkbox.setEnabled(True) + for shutter in shutters: + self.ui.shutter_combobox.addItem(shutter.name) + else: + log.warning("No shutters found, disabling checkbox.") + self.ui.shutter_checkbox.setEnabled(False) + self.ui.shutter_checkbox.setCheckState(False) def update_queue_status(self, status): super().update_queue_status(status) @@ -104,12 +126,13 @@ def record_dark_current(self): """ # Determine which shutters to close - shutters = [] + kwargs = {} if self.ui.shutter_checkbox.isChecked(): - shutters.append("experiment_shutter") + shutter_name = self.ui.shutter_combobox.currentText() + kwargs["shutters"] = [shutter_name] # Construct the plan ic_names = [ic.name for ic in self.ion_chambers] - item = BPlan("record_dark_current", ic_names, shutters=shutters) + item = BPlan("record_dark_current", ic_names, **kwargs) # Send it to the queue server self.queue_item_submitted.emit(item) diff --git a/src/firefly/voltmeters.ui b/src/firefly/voltmeters.ui index c391a414..89b786a4 100644 --- a/src/firefly/voltmeters.ui +++ b/src/firefly/voltmeters.ui @@ -87,7 +87,7 @@ - false + true <html><head/><body><p>Close the experimental experimental hutch shutter prior to recording dark current. </p><p><br/></p><p><span style=" font-weight:600;">This feature is disabled pending availability of shutter controls.</span></p></body></html> @@ -103,6 +103,13 @@ + + + + false + + + @@ -224,5 +231,22 @@ - + + + shutter_checkbox + toggled(bool) + shutter_combobox + setEnabled(bool) + + + 157 + 53 + + + 249 + 53 + + + +