Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added back the shutter selector to the voltmeters display. #323

Merged
merged 5 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 70 additions & 3 deletions src/firefly/tests/test_voltmeters.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -28,6 +31,19 @@ async def ion_chambers(sim_registry):
return devices


@pytest.fixture()
async def shutters(sim_registry):
shutters = [
Device(name="front_end_shutter"),
Device(name="enstation_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()
Expand Down Expand Up @@ -151,14 +167,65 @@ 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" in combobox_items
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we decided to remove front end shutter, the test should be modified too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.



@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()
Expand Down
21 changes: 18 additions & 3 deletions src/firefly/voltmeters.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,20 @@ 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)
# Add the shutters to the shutter combobox
shutters = registry.findall("shutters", allow_none=True)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like explicitly remove 'front end shutter' from the list because it happens very often that ppl accidentally choose front end shutter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the FES should not be available.

Instead of hard-coding the name "front_end_shutter", though, I used the existing allow_close and allow_open attributes on the shutter devices. The shutter will only be present if both are not False. A corollary is that shutters without those attributes will still be allowed.

has_shutters = bool(len(shutters))
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)
Expand Down Expand Up @@ -104,12 +118,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)

Expand Down
28 changes: 26 additions & 2 deletions src/firefly/voltmeters.ui
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
<item>
<widget class="QCheckBox" name="shutter_checkbox">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Close the experimental experimental hutch shutter prior to recording dark current. &lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;This feature is disabled pending availability of shutter controls.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
Expand All @@ -103,6 +103,13 @@
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="shutter_combobox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
Expand Down Expand Up @@ -224,5 +231,22 @@
</customwidget>
</customwidgets>
<resources/>
<connections/>
<connections>
<connection>
<sender>shutter_checkbox</sender>
<signal>toggled(bool)</signal>
<receiver>shutter_combobox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>157</x>
<y>53</y>
</hint>
<hint type="destinationlabel">
<x>249</x>
<y>53</y>
</hint>
</hints>
</connection>
</connections>
</ui>