Skip to content

Commit

Permalink
Decoupled display and FireflyApplication for more displays.
Browse files Browse the repository at this point in the history
  • Loading branch information
canismarko committed Jun 17, 2024
1 parent d877d48 commit 01d306f
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 224 deletions.
3 changes: 2 additions & 1 deletion notes.org
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@
- [X] iocs_window_action
- [ ] App needs to pass actions to the window
- [ ] Apps needs to connect queue_status_changed to main_window.update_queue_controls

** TODO [/] Queue button
- [ ] App needs to pass queue_status_updated signal down to update_queue_style slot
1 change: 1 addition & 0 deletions src/firefly/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ def update_queue_controls(self, new_status):
super().update_queue_controls(new_status)
self.ui.navbar.setVisible(bool(new_status['in_use']))


# -----------------------------------------------------------------------------
# :author: Mark Wolfman
# :email: [email protected]
Expand Down
6 changes: 3 additions & 3 deletions src/firefly/plans/xafs_scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
float_accuracy = 4


# the energy resolution will not be better than 0.01 eV at S25, e.g., 0.01 eV /4000 eV -> 10-6 level, Si(311) is 10-5 level
# The energy resolution will not be better than 0.01 eV at S25
# e.g. 0.01 eV / 4000 eV -> 10^-6 level, Si(311) is 10-5 level
def wavenumber_to_energy_round(wavenumber):
return round(wavenumber_to_energy(wavenumber), 2)

Expand Down Expand Up @@ -503,11 +504,10 @@ def queue_plan(self, *args, **kwargs):
md=md,
)
# Submit the item to the queueserver
app = FireflyApplication.instance()
log.info(f"Adding XAFS scan to queue.")
# repeat scans
for i in range(repeat_scan_num):
app.add_queue_item(item)
self.queue_item_submitted.emit(item)

def ui_filename(self):
return "plans/xafs_scan.ui"
Expand Down
12 changes: 1 addition & 11 deletions src/firefly/queue_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
from qtpy import QtGui, QtWidgets
from strenum import StrEnum

from firefly import FireflyApplication


log = logging.getLogger(__name__)


Expand All @@ -22,15 +19,8 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Initially disable the button until the status of the queue can be determined
self.setDisabled(True)
# Listen for changes to the run engine
app = FireflyApplication.instance()
try:
app.queue_status_changed.connect(self.handle_queue_status_change)
except AttributeError:
log.warning("Application has no slot `handle_queue_status_change`. "
"Queue button will not respond to queue state changes.")

def handle_queue_status_change(self, status: dict):
def update_queue_style(self, status: dict):
if status["worker_environment_exists"]:
self.setEnabled(True)
else:
Expand Down
86 changes: 86 additions & 0 deletions src/firefly/tests/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,92 @@ def test_open_area_detector_viewer_actions(ffapp, qtbot, sim_camera):
list(ffapp.area_detector_actions.values())[0].trigger()
assert "FireflyMainWindow_area_detector_s255id-gige-A" in ffapp.windows.keys()


############
# From old src/firefly/tests/test_motor_menu.py


@pytest.fixture
def fake_motors(sim_registry):
motor_names = ["motorA", "motorB", "motorC"]
motors = []
for name in motor_names:
this_motor = make_fake_device(motor.HavenMotor)(
name=name, labels={"extra_motors"}
)
motors.append(this_motor)
return motors


def test_open_motor_window(fake_motors, qapp, qtbot):
# Simulate clicking on the menu action (they're in alpha order)
action = ffapp.motor_actions["motorC"]
action.trigger()
# See if the window was created
motor_3_name = "FireflyMainWindow_motor_motorC"
assert motor_3_name in ffapp.windows.keys()
macros = ffapp.windows[motor_3_name].display_widget().macros()
assert macros["MOTOR"] == "motorC"


def test_motor_menu(fake_motors, qapp, qtbot):
# Create the window
window = FireflyMainWindow()
qtbot.addWidget(window)
# Check that the menu items have been created
assert hasattr(window.ui, "positioners_menu")
assert len(ffapp.motor_actions) == 3
window.destroy()


##########################################
# From src/firefly/tests/test_queue_client.py


def test_queue_stopped(client):
"""Does the action respond to changes in the queue stopped pending?"""
assert not ffapp.queue_stop_action.isChecked()
client.queue_stop_changed.emit(True)
assert ffapp.queue_stop_action.isChecked()
client.queue_stop_changed.emit(False)
assert not ffapp.queue_stop_action.isChecked()


def test_autostart_changed(client, qtbot):
"""Does the action respond to changes in the queue autostart
status?
"""
ffapp.queue_autostart_action.setChecked(True)
assert ffapp.queue_autostart_action.isChecked()
with qtbot.waitSignal(client.autostart_changed, timeout=3):
client.autostart_changed.emit(False)
assert not ffapp.queue_autostart_action.isChecked()
with qtbot.waitSignal(client.autostart_changed, timeout=3):
client.autostart_changed.emit(True)
assert ffapp.queue_autostart_action.isChecked()



###############################################################
# From: src/firefly/tests/test_xrf_detector_display.py

def test_open_xrf_detector_viewer_actions(ffapp, qtbot, det_fixture, request):
sim_det = request.getfixturevalue(det_fixture)
# Get the area detector parts ready
ffapp._prepare_device_windows(
device_label="xrf_detectors",
attr_name="xrf_detector",
ui_file="xrf_detector.py",
device_key="DEV",
)
assert hasattr(ffapp, "xrf_detector_actions")
assert len(ffapp.xrf_detector_actions) == 1
# Launch an action and see that a window opens
list(ffapp.xrf_detector_actions.values())[0].trigger()
assert "FireflyMainWindow_xrf_detector_vortex_me4" in ffapp.windows.keys()


# -----------------------------------------------------------------------------
# :author: Mark Wolfman
# :email: [email protected]
Expand Down
53 changes: 1 addition & 52 deletions src/firefly/tests/test_cameras_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def cameras_display(qtbot, sim_camera):

@pytest.fixture()
def camera_display(qtbot, sim_camera):
display = CamerasDisplay()
display = CameraDisplay()
qtbot.addWidget(display)
return display

Expand All @@ -36,57 +36,6 @@ def test_embedded_displays(cameras_display, sim_camera):
assert json.loads(display._camera_displays[0].macros) == expected_macros


def test_camera_channel_status(camera_display):
"""Test that the camera status indicator responds to camera connection
status PV.
"""
display = camera_display
# Check that the pydm connections have been made to EPICS
assert isinstance(display.detector_state, PyDMChannel)
assert display.detector_state.address == "camera_ioc:cam1:DetectorState_RBV"


def test_set_status_byte(camera_display):
display = camera_display
display.show()
# All devices are disconnected
byte = display.camera_status_indicator
bit = byte._indicators[0]
label = display.camera_status_label
# Set the color to something else, then check that it gets set back to white
bit.setColor(QtGui.QColor(255, 0, 0))
# Simulated the IOC being disconnected
display.update_camera_connection(False)
assert bit._brush.color().getRgb() == (255, 255, 255, 255)
assert not label.isVisible(), "State label should be hidden by default"
# Make the signals connected and see that it's green
display.update_camera_connection(True)
display.update_camera_state(DetectorStates.IDLE)
assert bit._brush.color().getRgb() == (0, 255, 0, 255)
assert not label.isVisible(), "State label should be hidden by default"
# Make the camera be disconnected and see if it's red
display.update_camera_state(DetectorStates.DISCONNECTED)
assert bit._brush.color().getRgb() == (255, 0, 0, 255)
assert label.isVisible(), "State label should be visible when disconnected"
# Make the camera be acquiring and see if it's yellow
display.update_camera_state(DetectorStates.ACQUIRE)
assert bit._brush.color().getRgb() == (255, 255, 0, 255)
assert not label.isVisible(), "State label should be hidden by default"


@pytest.mark.xfail
def test_camera_viewer_button(qtbot, ffapp, ioc_area_detector, mocker):
action = QtWidgets.QAction(ffapp)
ffapp.camera_actions.append(action)
display = CameraDisplay(macros=macros)
display.show()
# Click the button
btn = display.ui.camera_viewer_button
with qtbot.waitSignal(action.triggered):
qtbot.mouseClick(btn, QtCore.Qt.LeftButton)


# -----------------------------------------------------------------------------
# :author: Mark Wolfman
# :email: [email protected]
Expand Down
68 changes: 0 additions & 68 deletions src/firefly/tests/test_motor_menu.py

This file was deleted.

6 changes: 3 additions & 3 deletions src/firefly/tests/test_queue_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def test_queue_button_style(qtbot):
"re_state": "idle",
"queue_autostart_enabled": False,
}
ffapp.queue_status_changed.emit(queue_state)
btn.update_queue_style(queue_state)
assert btn.isEnabled()
assert Colors.ADD_TO_QUEUE in btn.styleSheet()
assert btn.text() == "Add to Queue"
Expand All @@ -26,7 +26,7 @@ def test_queue_button_style(qtbot):
"re_state": "idle",
"queue_autostart_enabled": True,
}
btn.handle_queue_status_change(queue_state)
btn.update_queue_style(queue_state)
assert btn.isEnabled()
assert Colors.RUN_QUEUE in btn.styleSheet()
assert btn.text() == "Run"
Expand All @@ -37,7 +37,7 @@ def test_queue_button_style(qtbot):
"re_state": "running",
"queue_autostart_enabled": True,
}
btn.handle_queue_status_change(queue_state)
btn.update_queue_style(queue_state)
assert btn.isEnabled()
assert Colors.ADD_TO_QUEUE in btn.styleSheet()
assert btn.text() == "Add to Queue"
Expand Down
30 changes: 0 additions & 30 deletions src/firefly/tests/test_queue_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,6 @@ def client():
yield client


@pytest.fixture()
def ffapp(ffapp, client):
ffapp.prepare_queue_client(api=client.api, client=client)
return ffapp


def test_client_timer(client):
assert isinstance(client.timer, QTimer)

Expand Down Expand Up @@ -320,21 +314,6 @@ async def test_toggle_autostart(client, qtbot):
api.queue_autostart.assert_called_once_with(True)


def test_autostart_changed(client, ffapp, qtbot):
"""Does the action respond to changes in the queue autostart
status?
"""
ffapp.queue_autostart_action.setChecked(True)
assert ffapp.queue_autostart_action.isChecked()
with qtbot.waitSignal(client.autostart_changed, timeout=3):
client.autostart_changed.emit(False)
assert not ffapp.queue_autostart_action.isChecked()
with qtbot.waitSignal(client.autostart_changed, timeout=3):
client.autostart_changed.emit(True)
assert ffapp.queue_autostart_action.isChecked()


# def test_start_queue(ffapp, client, qtbot):
# ffapp.start_queue_action.trigger()
# qtbot.wait(1000)
Expand All @@ -356,15 +335,6 @@ async def test_stop_queue(client, qtbot):
api.queue_stop_cancel.assert_called_once()


def test_queue_stopped(client, ffapp):
"""Does the action respond to changes in the queue stopped pending?"""
assert not ffapp.queue_stop_action.isChecked()
client.queue_stop_changed.emit(True)
assert ffapp.queue_stop_action.isChecked()
client.queue_stop_changed.emit(False)
assert not ffapp.queue_stop_action.isChecked()


@pytest.mark.asyncio
async def test_check_queue_status(client, qtbot):
# Check that the queue length is changed
Expand Down
Loading

0 comments on commit 01d306f

Please sign in to comment.