Skip to content

Commit

Permalink
Merge pull request #369 from vshekar/fmx-setenergy-ui
Browse files Browse the repository at this point in the history
Fmx setenergy UI changes and cleanup
  • Loading branch information
vshekar authored Apr 29, 2024
2 parents 3a53fbf + 5ffca9c commit eaaa2f3
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 25 deletions.
1 change: 1 addition & 0 deletions config_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
# GUI default configuration
BEAM_CHECK = "beamCheck"
UNMOUNT_COLD_CHECK = "unmountColdCheck"
SET_ENERGY_CHECK = "setEnergyCheck"


# raster request status updates
Expand Down
9 changes: 9 additions & 0 deletions daq_macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import bluesky.plans as bp
from bluesky.preprocessors import finalize_wrapper
from fmx_annealer import govStatusGet, govStateSet, fmxAnnealer, amxAnnealer # for using annealer specific to FMX and AMX
from setenergy_lsdc import setELsdc

try:
import ispybLib
Expand Down Expand Up @@ -85,6 +86,14 @@ def abortBS():
RE.abort()
except super_state_machine.errors.TransitionError:
logger.error("caught BS")

def set_energy(energy):
try:
daq_lib.set_field("program_state","Setting Energy")
RE(setELsdc(energy))
except Exception as e:
logger.error(f"Exception while running set_energy: {e}")
daq_lib.set_field("program_state","Program Ready")

def move_omega(omega, relative=True):
"""Moves omega by a certain amount"""
Expand Down
3 changes: 2 additions & 1 deletion daq_main_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ def setGovState(state):
unlatchGov,
backoffDetector,
enableMount,
robotOn
robotOn,
set_energy
]

whitelisted_functions: "Dict[str, Callable]" = {
Expand Down
39 changes: 32 additions & 7 deletions gui/control_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
RASTER_GUI_XREC_FILL_DELAY,
SAMPLE_TIMER_DELAY,
SERVER_CHECK_DELAY,
SET_ENERGY_CHECK,
VALID_DET_DIST,
VALID_EXP_TIMES,
VALID_TOTAL_EXP_TIMES,
Expand All @@ -48,6 +49,7 @@
PuckDialog,
RasterExploreDialog,
ScreenDefaultsDialog,
SetEnergyDialog,
SnapCommentDialog,
StaffScreenDialog,
UserScreenDialog,
Expand Down Expand Up @@ -562,13 +564,20 @@ def createSampleTab(self):
)
self.energy_ledit = self.energyMoveLedit.getEntry()
self.energy_ledit.setValidator(QtGui.QDoubleValidator())
self.energy_ledit.returnPressed.connect(self.moveEnergyCB)
self.energy_ledit.returnPressed.connect(self.moveEnergyMaxDeltaCB)
moveEnergyButton = QtWidgets.QPushButton("Move Energy")
moveEnergyButton.clicked.connect(self.moveEnergyCB)
hBoxColParams3.addWidget(colEnergyLabel)
hBoxColParams3.addWidget(self.energyReadback)
hBoxColParams3.addWidget(energySPLabel)
hBoxColParams3.addWidget(self.energy_ledit)
if daq_utils.beamline == "fmx":
if getBlConfig(SET_ENERGY_CHECK):
hBoxColParams3.addWidget(moveEnergyButton)
else:
hBoxColParams3.addWidget(self.energy_ledit)
else:
hBoxColParams3.addWidget(self.energy_ledit)

hBoxColParams22.addWidget(colTransmissionLabel)
hBoxColParams22.addWidget(self.transmissionReadback_ledit)
hBoxColParams22.addWidget(transmisionSPLabel)
Expand Down Expand Up @@ -2702,13 +2711,24 @@ def moveOmegaCB(self):
{"relative": False}
)

def moveEnergyCB(self):
def moveEnergyMaxDeltaCB(self, max_delta=10.0):
energyRequest = float(str(self.energy_ledit.text()))
if abs(energyRequest - self.energy_pv.get()) > 10.0:
self.popupServerMessage("Energy change must be less than 10 ev")
return
if self.controlEnabled():
if abs(energyRequest - self.energy_pv.get()) > max_delta:
self.popupServerMessage(f"Energy change must be less than or equal to {max_delta:.2f} ev")
return
else:
self.send_to_server("mvaDescriptor", ["energy", float(self.energy_ledit.text())])
comm_s = 'mvaDescriptor("energy",' + str(self.energy_ledit.text()) + ")"
logger.info(comm_s)
else:
self.send_to_server("mvaDescriptor", ["energy", float(self.energy_ledit.text())])
self.popupServerMessage("You don't have control")

def moveEnergyCB(self):
if self.controlEnabled():
set_energy = SetEnergyDialog(parent=self)
else:
self.popupServerMessage("You don't have control")

def setLifetimeCB(self, lifetime):
if hasattr(self, "sampleLifetimeReadback_ledit"):
Expand Down Expand Up @@ -5167,6 +5187,11 @@ def printServerMessage(self, message_s):
print(message_s)

def colorProgramState(self, programState_s):
if programState_s == "Setting Energy":
self.setEnabled(False)
else:
self.setEnabled(True)

if programState_s.find("Ready") == -1:
self.statusLabel.setColor("yellow")
else:
Expand Down
1 change: 1 addition & 0 deletions gui/dialog/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
from .puck_dialog import PuckDialog
from .dewar import DewarDialog
from .screen_defaults import ScreenDefaultsDialog
from .set_energy import SetEnergyDialog
138 changes: 138 additions & 0 deletions gui/dialog/set_energy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import logging
import typing

from ophyd import Component as Cpt
from ophyd import Device, EpicsMotor
from qtpy import QtCore, QtGui, QtWidgets
from qtpy.QtCore import Qt

import daq_utils
import db_lib

if typing.TYPE_CHECKING:
from lsdcGui import ControlMain

logger = logging.getLogger()


class DCM(Device):
b = Cpt(EpicsMotor, "-Ax:B}Mtr", labels=["fmx"])
g = Cpt(EpicsMotor, "-Ax:G}Mtr", labels=["fmx"])
p = Cpt(EpicsMotor, "-Ax:P}Mtr", labels=["fmx"])
r = Cpt(EpicsMotor, "-Ax:R}Mtr", labels=["fmx"])
e = Cpt(EpicsMotor, "-Ax:E}Mtr", labels=["fmx"])


class SetEnergyDialog(QtWidgets.QDialog):
energy_changed_signal = QtCore.Signal(object)

def __init__(self, parent: "ControlMain"):
self.hdcm = DCM("XF:17IDA-OP:FMX{Mono:DCM", name="hdcm")
super().__init__(parent)
self._parent = parent
self.initUI()

def initUI(self):
layout = QtWidgets.QGridLayout()
self.current_energy_label = QtWidgets.QLabel("Current Energy: ")
self.current_energy_value_label = QtWidgets.QLabel(
f"{self.hdcm.e.user_readback.get():.2f} eV"
)
layout.addWidget(self.current_energy_label, 0, 0)
layout.addWidget(self.current_energy_value_label, 0, 1)

self.setpoint_label = QtWidgets.QLabel("Energy setpoint: ")
validator = QtGui.QDoubleValidator()
validator.setBottom(5000)
validator.setTop(15000)
self.setpoint_edit = QtWidgets.QLineEdit()
self.setpoint_edit.setValidator(validator)
self.setpoint_edit.returnPressed.connect(self.check_value)
layout.addWidget(self.setpoint_label, 1, 0)
layout.addWidget(self.setpoint_edit, 1, 1)

self.message = QtWidgets.QLabel("")
layout.addWidget(self.message, 2, 0, 1, 2)

self.monochromator_button = QtWidgets.QPushButton("Monochromator")
self.monochromator_button.setAutoDefault(False)
self.monochromator_button.clicked.connect(self.set_monochromator_energy)

self.full_alignment_button = QtWidgets.QPushButton("Full Alignment")
self.full_alignment_button.setAutoDefault(False)
self.full_alignment_button.clicked.connect(self.set_full_alignment_energy)

self.close_button = QtWidgets.QPushButton("Close")
self.close_button.clicked.connect(self.close)
self.close_button.setAutoDefault(False)

layout.addWidget(self.monochromator_button, 3, 0)
layout.addWidget(self.full_alignment_button, 3, 1)
layout.addWidget(self.close_button, 4, 0, 1, 2)

self.hdcm.e.user_readback.subscribe(self.update_energy, run=True)

self.energy_changed_signal.connect(
lambda value: self.current_energy_value_label.setText(f"{value:.2f}")
)

self.setLayout(layout)
self.setModal(True)
self.show()

def update_energy(self, value, old_value, **kwargs):
self.energy_changed_signal.emit(value)

def check_value(self):
if abs(float(self.setpoint_edit.text()) - self.hdcm.e.user_readback.get()) > 10:
self.message.setText(
"Energy change is greater than 10 eV.\nMonochromator cannot be used for alignment"
)
self.monochromator_button.setDisabled(True)
else:
self.message.setText("Energy change less than 10 eV")
self.monochromator_button.setDisabled(False)

if float(self.setpoint_edit.text()) <= 10000:
self.message.setText(
f"{self.message.text()} \n Beam shape not automatically optimized \nfor energies between 5 keV and 10 keV"
)

def unmount_cold_dialog(self):
msg_box = QtWidgets.QMessageBox()
msg_box.setText("A sample is mounted. Unmount cold?")
msg_box.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok | QtWidgets.QMessageBox.StandardButton.Cancel) # type: ignore
msg_box.setDefaultButton(QtWidgets.QMessageBox.StandardButton.Ok)
return msg_box

def set_full_alignment_energy(self):
if self._parent.mountedPin_pv.get():
# If sample is mounted, ask user to unmount cold
response = self.unmount_cold_dialog().exec_()

if response == QtWidgets.QMessageBox.Ok:
self._parent.send_to_server("unmountCold")
else:
return

if self._parent.governorMessage.getEntry().text() not in [
"state SE",
"state BA",
"state BL",
"state XF",
"state SA",
]:
self.message.setText("Governor not in a valid state, call staff!")
return
else:
self._parent.send_to_server("setGovState", ['SA'])

self._parent.send_to_server(f"set_energy", [float(self.setpoint_edit.text())])

def set_monochromator_energy(self):
if abs(float(self.setpoint_edit.text()) - self.hdcm.e.user_readback.get()) > 10:
self.message.setText(
"Energy change is greater than 10 eV.\nMonochromator cannot be used for alignment"
)
else:
self._parent.send_to_server("mvaDescriptor", ["energy", float(self.setpoint_edit.text())])
32 changes: 30 additions & 2 deletions gui/dialog/staff_screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@
from qtpy import QtCore, QtWidgets
from qtpy.QtWidgets import QCheckBox

from config_params import BEAM_CHECK, TOP_VIEW_CHECK, UNMOUNT_COLD_CHECK
from config_params import (
BEAM_CHECK,
SET_ENERGY_CHECK,
TOP_VIEW_CHECK,
UNMOUNT_COLD_CHECK,
)
from daq_utils import getBlConfig, setBlConfig
import db_lib
import daq_utils

if typing.TYPE_CHECKING:
from lsdcGui import ControlMain
Expand Down Expand Up @@ -65,6 +70,17 @@ def __init__(self, parent: "ControlMain", **kwargs):
self.gripperUnmountColdCheckBox.setEnabled(False)
self.gripperUnmountColdCheckBox.setChecked(False)

# Set energy checkbox
if daq_utils.beamline == "fmx":
self.set_energy_checkbox = QCheckBox("Set Energy")
hBoxColParams1.addWidget(self.set_energy_checkbox)
if getBlConfig(SET_ENERGY_CHECK) == 1:
self.set_energy_checkbox.setChecked(True)
else:
self.set_energy_checkbox.setChecked(False)
self.set_energy_checkbox.stateChanged.connect(self.set_energy_check_cb)


self.queueCollectOnCheckBox = QCheckBox("Queue Collect")
hBoxColParams1.addWidget(self.queueCollectOnCheckBox)
self.checkQueueCollect()
Expand Down Expand Up @@ -297,6 +313,18 @@ def beamCheckOnCheckCB(self, state):
setBlConfig(BEAM_CHECK, 0)
logger.debug(f"{BEAM_CHECK} off")

def set_energy_check_cb(self, state):
if state == QtCore.Qt.Checked:
setBlConfig(SET_ENERGY_CHECK, 1)
logger.debug(f"{SET_ENERGY_CHECK} on")
else:
setBlConfig(SET_ENERGY_CHECK, 0)
logger.debug(f"{SET_ENERGY_CHECK} off")
msg_box = QtWidgets.QMessageBox()
msg_box.setText("Set Energy state changed, please restart the GUI to access feature")
msg_box.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok) # type: ignore
msg_box.setDefaultButton(QtWidgets.QMessageBox.StandardButton.Ok)

def unmountColdCheckCB(self, state):
if state == QtCore.Qt.Checked:
logger.info("unmountColdCheckCB On")
Expand Down
Loading

0 comments on commit eaaa2f3

Please sign in to comment.