diff --git a/mxcubeqt/bricks/aperture_brick.py b/mxcubeqt/bricks/aperture_brick.py
index cc7f390b1..3daee4f32 100644
--- a/mxcubeqt/bricks/aperture_brick.py
+++ b/mxcubeqt/bricks/aperture_brick.py
@@ -134,7 +134,7 @@ def init_aperture(self):
aperture_size_list = HWR.beamline.beam.aperture.get_diameter_size_list()
self.aperture_diameter_combo.clear()
for aperture_size in aperture_size_list:
- self.aperture_diameter_combo.addItem("%d%s" % (aperture_size, unichr(956)))
+ self.aperture_diameter_combo.addItem("%s%s" % (aperture_size, unichr(956)))
aperture_position_list = HWR.beamline.beam.aperture.get_position_list()
self.aperture_position_combo.clear()
diff --git a/mxcubeqt/bricks/desy/digital_zoom_brick.py b/mxcubeqt/bricks/desy/digital_zoom_brick.py
index b60500da6..c61e306e8 100644
--- a/mxcubeqt/bricks/desy/digital_zoom_brick.py
+++ b/mxcubeqt/bricks/desy/digital_zoom_brick.py
@@ -30,7 +30,6 @@
class DigitalZoomBrick(BaseWidget):
-
STATE_COLORS = (
colors.LIGHT_YELLOW, # INITIALIZING
colors.LIGHT_GREEN, # ON
@@ -129,16 +128,15 @@ def setToolTip(self, name=None, state=None):
self.label.setToolTip(tip)
def motor_state_changed(self, state):
-
# self.positions_combo.setEnabled(self.motor_hwobj.is_ready())
if self.motor_hwobj.is_ready:
colors.set_widget_color(
- self.positions_combo, colors.LIGHT_GREEN, qt_import.QPalette.Button,
+ self.positions_combo, colors.LIGHT_GREEN, qt_import.QPalette.Button
)
else:
colors.set_widget_color(
- self.positions_combo, colors.LIGHT_GRAY, qt_import.QPalette.Button,
+ self.positions_combo, colors.LIGHT_GRAY, qt_import.QPalette.Button
)
# self.setToolTip(state=state)
@@ -242,7 +240,6 @@ def position_selected(self, index):
self.previous_position_button.setEnabled(index >= 0)
def predefined_position_changed(self, position, offset):
-
if self.positions:
for index, item in enumerate(self.positions):
if position.name == item.name:
diff --git a/mxcubeqt/bricks/desy/p11_deice_brick.py b/mxcubeqt/bricks/desy/p11_deice_brick.py
deleted file mode 100644
index 029e8d981..000000000
--- a/mxcubeqt/bricks/desy/p11_deice_brick.py
+++ /dev/null
@@ -1,676 +0,0 @@
-#
-# Project: MXCuBE
-# https://github.com/mxcube
-#
-# This file is part of MXCuBE software.
-#
-# MXCuBE is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# MXCuBE is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with MXCuBE. If not, see .
-
-import re
-
-from mxcubeqt.utils import colors, icons, qt_import
-from mxcubeqt.base_components import BaseWidget
-
-from mxcubeqt.utils import colors, icons, qt_import
-from mxcubeqt.bricks.proposal_brick import DuoStateBrick, ProposalGUIEvent
-from mxcubecore import HardwareRepository as HWR
-import logging
-import os
-
-__category__ = "DESY"
-
-
-class P11DeiceBrick(DuoStateBrick):
-
- STATES = {
- "unknown": (colors.LIGHT_GRAY, True, True, False, False),
- "disabled": (colors.LIGHT_GRAY, False, False, False, False),
- "noperm": (colors.LIGHT_GRAY, False, False, False, False),
- "error": (colors.LIGHT_RED, False, False, False, False),
- "out": (colors.LIGHT_GREEN, True, False, False, True),
- "closed": (colors.LIGHT_GREEN, True, True, False, True),
- "moving": (colors.LIGHT_YELLOW, False, False, None, None),
- "in": (colors.LIGHT_GREEN, False, True, True, False),
- "opened": (colors.LIGHT_GREEN, True, True, True, False),
- "automatic": (colors.WHITE, True, True, False, False),
- }
-
- def __init__(self, *args):
- BaseWidget.__init__(self, *args)
-
- # Hardware objects ----------------------------------------------------
- self.wrapper_hwobj = None
-
- # Internal values -----------------------------------------------------
- self.__expertMode = False
-
- # Properties ----------------------------------------------------------
- self.add_property("mnemonic", "string", "")
- self.add_property("forceNoControl", "boolean", False)
- self.add_property("expertModeControlOnly", "boolean", False)
- self.add_property("icons", "string", "")
- self.add_property("in", "string", "in")
- self.add_property("out", "string", "out")
- self.add_property("setin", "string", "Set in")
- self.add_property("setout", "string", "Set out")
- self.add_property("username", "string", "")
-
- # Signals -------------------------------------------------------------
-
- # Slots ---------------------------------------------------------------
- self.define_slot("allowControl", ())
-
- # Graphic elements ----------------------------------------------------
- self.main_gbox = qt_import.QGroupBox("none", self)
- self.main_gbox.setAlignment(qt_import.Qt.AlignCenter)
- self.state_ledit = qt_import.QLineEdit("unknown", self.main_gbox)
-
- self.buttons_widget = qt_import.QWidget(self.main_gbox)
- self.set_in_button = qt_import.QPushButton("Set in", self.buttons_widget)
- self.set_in_button.setCheckable(True)
- self.set_out_button = qt_import.QPushButton("Set out", self.buttons_widget)
- self.set_out_button.setCheckable(True)
-
- # Layout --------------------------------------------------------------
- _buttons_widget_hlayout = qt_import.QHBoxLayout(self.buttons_widget)
- _buttons_widget_hlayout.addWidget(self.set_in_button)
- _buttons_widget_hlayout.addWidget(self.set_out_button)
- _buttons_widget_hlayout.setSpacing(0)
- _buttons_widget_hlayout.setContentsMargins(0, 0, 0, 0)
-
- _main_gbox_vlayout = qt_import.QVBoxLayout(self.main_gbox)
- _main_gbox_vlayout.addWidget(self.state_ledit)
- _main_gbox_vlayout.addWidget(self.buttons_widget)
- _main_gbox_vlayout.setSpacing(2)
- _main_gbox_vlayout.setContentsMargins(4, 4, 4, 4)
-
- _main_vlayout = qt_import.QVBoxLayout(self)
- _main_vlayout.addWidget(self.main_gbox)
- _main_vlayout.setSpacing(0)
- _main_vlayout.setContentsMargins(0, 0, 0, 0)
-
- # SizePolicies --------------------------------------------------------
-
- # Qt signal/slot connections ------------------------------------------
- self.set_in_button.toggled.connect(self.set_in)
- self.set_out_button.toggled.connect(self.set_out)
-
- # Other ---------------------------------------------------------------
- self.state_ledit.setAlignment(qt_import.Qt.AlignCenter)
- self.state_ledit.setToolTip("Shows the current control state")
- self.state_ledit.setFrame(False)
- bold_font = self.state_ledit.font()
- bold_font.setBold(True)
- self.state_ledit.setFont(bold_font)
- self.state_ledit.setFixedHeight(24)
-
- self.set_in_button.setToolTip("Changes the control state")
- self.set_out_button.setToolTip("Changes the control state")
-
- self.instance_synchronize("state_ledit")
-
- def setExpertMode(self, expert):
- self.__expertMode = expert
- self.buttons_widget.show()
-
- if not expert and self["expertModeControlOnly"]:
- self.buttons_widget.hide()
-
- def set_in(self, state):
- if state:
- self.set_in_button.setEnabled(False)
- self.wrapper_hwobj.setIn()
- else:
- self.set_in_button.blockSignals(True)
- # self.set_in_button.setState(QtGui.QPushButton.On)
- self.set_in_button.setDown(True)
- self.set_in_button.blockSignals(False)
-
- def set_out(self, state):
- if state:
- self.set_out_button.setEnabled(False)
- self.wrapper_hwobj.setOut()
- else:
- self.set_out_button.blockSignals(True)
- self.set_out_button.setDown(False)
- # self.set_out_button.setState(QtGui.QPushButton.On)
- self.set_out_button.blockSignals(False)
-
- def updateLabel(self, label):
- self.main_gbox.setTitle(label)
-
- def stateChanged(self, state, state_label=""):
- self.setEnabled(True)
- state = str(state)
- try:
- color = self.STATES[state][0]
- except KeyError:
- state = "unknown"
- color = self.STATES[state][0]
- if color is None:
- color = colors.GROUP_BOX_GRAY
-
- colors.set_widget_color(self.state_ledit, color, qt_import.QPalette.Base)
- # self.state_ledit.setPaletteBackgroundColor(QColor(color))
- if len(state_label) > 0:
- self.state_ledit.setText("%s" % state_label)
- else:
- label_str = state
- if state == "in":
- prop_label = self["in"].strip()
- if len(prop_label.strip()):
- label_str = prop_label
- if state == "out":
- prop_label = self["out"].strip()
- if prop_label:
- label_str = prop_label
- self.state_ledit.setText("%s" % label_str)
-
- if state in self.STATES:
- in_enable = self.STATES[state][1]
- out_enable = self.STATES[state][2]
- else:
- in_enable = False
- out_enable = False
-
- self.set_in_button.setEnabled(in_enable)
- self.set_out_button.setEnabled(out_enable)
-
- if state in self.STATES:
- in_state = self.STATES[state][3]
- out_state = self.STATES[state][4]
- else:
- in_state = True
- out_state = False
- if in_state is not None:
- self.set_in_button.blockSignals(True)
- self.set_in_button.setChecked(in_state)
- self.set_in_button.blockSignals(False)
- if out_state is not None:
- self.set_out_button.blockSignals(True)
- self.set_out_button.setChecked(out_state)
- self.set_out_button.blockSignals(False)
-
- """
- if state=='in':
- self.duoStateBrickMovingSignal.emit(False)
- self.duoStateBrickInSignal.emit(True)
- elif state=='out':
- self.duoStateBrickMovingSignal.emit(False)
- self.duoStateBrickOutSignal.emit(True)
- elif state=='moving':
- self.duoStateBrickMovingSignal.emit(True)
- elif state=='error' or state=='unknown' or state=='disabled':
- self.duoStateBrickMovingSignal.emit(False)
- self.duoStateBrickInSignal.emit(False)
- self.duoStateBrickOutSignal.emit(False)
- """
-
- def allowControl(self, enable):
- if self["forceNoControl"]:
- return
- if enable:
- self.buttons_widget.show()
- else:
- self.buttons_widget.hide()
-
- def property_changed(self, property_name, old_value, new_value):
- if property_name == "mnemonic":
- if self.wrapper_hwobj is not None:
- self.wrapper_hwobj.duoStateChangedSignal.disconnect(self.stateChanged)
-
- h_obj = self.get_hardware_object(new_value)
- if h_obj is not None:
- self.wrapper_hwobj = WrapperHO(h_obj)
- self.main_gbox.show()
-
- if self["username"] == "":
- self["username"] = self.wrapper_hwobj.username
-
- help_text = self["setin"] + " the " + self["username"].lower()
- self.set_in_button.setToolTip(help_text)
- help_text = self["setout"] + " the " + self["username"].lower()
- self.set_out_button.setToolTip(help_text)
- self.main_gbox.setTitle(self["username"])
- self.wrapper_hwobj.duoStateChangedSignal.connect(self.stateChanged)
- self.wrapper_hwobj.get_state()
- else:
- self.wrapper_hwobj = None
- # self.main_gbox.hide()
- elif property_name == "expertModeControlOnly":
- if new_value:
- if self.__expertMode:
- self.buttons_widget.show()
- else:
- self.buttons_widget.hide()
- else:
- self.buttons_widget.show()
- elif property_name == "forceNoControl":
- if new_value:
- self.buttons_widget.hide()
- else:
- self.buttons_widget.show()
- elif property_name == "icons":
- # w = self.fontMetrics().width("Set out")
- icons_list = new_value.split()
- try:
- self.set_in_button.setIcon(icons.load_icon(icons_list[0]))
- except IndexError:
- self.set_in_button.setText(self["setin"])
- # self.set_in_button.setMinimumWidth(w)
- try:
- self.set_out_button.setIcon(icons.load_icon(icons_list[1]))
- except IndexError:
- self.set_out_button.setText(self["setout"])
- # self.set_out_button.setMinimumWidth(w)
-
- # elif property_name=='in':
- # if self.wrapper_hwobj is not None:
- # self.stateChanged(self.wrapper_hwobj.get_state())
-
- # elif property_name=='out':
- # if self.wrapper_hwobj is not None:
- # self.stateChanged(self.wrapper_hwobj.get_state())
-
- elif property_name == "setin":
- # w=self.fontMetrics().width("Set out")
- icons_list = self["icons"]
- try:
- i = icons_list[0]
- except IndexError:
- self.set_in_button.setText(new_value)
- # self.set_in_button.setMinimumWidth(w)
- help_text = new_value + " the " + self["username"].lower()
- self.set_in_button.setToolTip(help_text)
- self.set_in_button.setText(self["setin"])
-
- elif property_name == "setout":
- # w=self.fontMetrics().width("Set out")
- icons_list = self["icons"].split()
- try:
- i = icons_list[1]
- except IndexError:
- self.set_out_button.setText(new_value)
- # self.set_out_button.setMinimumWidth(w)
- help_text = new_value + " the " + self["username"].lower()
- self.set_out_button.setToolTip(help_text)
- self.set_out_button.setText(self["setout"])
-
- elif property_name == "username":
- if new_value == "":
- if self.wrapper_hwobj is not None:
- name = self.wrapper_hwobj.username
- if name != "":
- self["username"] = name
- return
- help_text = self["setin"] + " the " + new_value.lower()
- self.set_in_button.setToolTip(help_text)
- help_text = self["setout"] + " the " + new_value.lower()
- self.set_out_button.setToolTip(help_text)
- self.main_gbox.setTitle(self["username"])
-
- else:
- BaseWidget.property_changed(self, property_name, old_value, new_value)
-
-
-###
-# Wrapper around different hardware objects, to make them have the
-# same behavior to the brick
-###
-
-
-class WrapperHO(qt_import.QObject):
- DEVICE_MAP = {
- "Device": "Procedure",
- "SOLEILGuillotine": "Shutter",
- "SoleilSafetyShutter": "Shutter",
- "TangoShutter": "Shutter",
- "ShutterEpics": "Shutter",
- "MD2v4_FastShutter": "Shutter",
- "TempShutter": "Shutter",
- "EMBLSafetyShutter": "Shutter",
- "MDFastShutter": "Shutter",
- "WagoPneu": "WagoPneu",
- "Shutter": "WagoPneu",
- "SpecMotorWSpecPositions": "WagoPneu",
- "Procedure": "WagoPneu",
- }
-
- WAGO_STATE = {"in": "in", "out": "out", "unknown": "unknown"}
-
- SHUTTER_STATE = {
- "fault": "error",
- "opened": "in",
- "noperm": "noperm",
- "closed": "out",
- "unknown": "unknown",
- "moving": "moving",
- "automatic": "automatic",
- "disabled": "disabled",
- "error": "error",
- }
- DOOR_INTERLOCK_STATE = {
- "locked": "out",
- "unlocked": "disabled",
- "locked_active": "out",
- "locked_inactive": "disabled",
- "error": "error",
- }
-
- MOTOR_WPOS = ("out", "in")
- MOTOR_WSTATE = ("disabled", "error", None, "moving", "moving", "moving")
-
- STATES = (
- "unknown",
- "disabled",
- "closed",
- "error",
- "out",
- "moving",
- "in",
- "automatic",
- "noperm",
- )
-
- duoStateChangedSignal = qt_import.pyqtSignal(str, str)
-
- def __init__(self, hardware_obj):
- qt_import.QObject.__init__(self)
-
- # self.setIn = new.instancemethod(lambda self: None, self)
- self.setIn = lambda self: None
- self.setOut = self.setIn
- # self.get-State = new.instancemethod(lambda self: "unknown", self)
- self.get_state = lambda self: "unknown"
- self.dev = hardware_obj
- try:
- sClass = str(self.dev.__class__)
- i, j = re.search("'.*'", sClass).span()
- except BaseException:
- dev_class = sClass
- else:
- dev_class = sClass[i + 1 : j - 1]
- self.devClass = dev_class.split(".")[-1]
-
- self.devClass = WrapperHO.DEVICE_MAP.get(self.devClass, "Shutter")
-
- initFunc = getattr(self, "init%s" % self.devClass)
- initFunc()
- self.setIn = getattr(self, "setIn%s" % self.devClass)
- self.setOut = getattr(self, "setOut%s" % self.devClass)
- self.get_state = getattr(self, "getState%s" % self.devClass)
-
- def __getstate__(self):
- dict = self.__dict__.copy()
- del dict["setIn"]
- del dict["setOut"]
- del dict["getState"]
- return dict
-
- def __setstate__(self, dict):
- self.__dict__ = dict.copy()
- try:
- # Python2
- import new
-
- self.setIn = new.instancemethod(lambda self: None, self)
- self.setOut = self.setIn
- self.get_state = new.instancemethod(lambda self: "unknown", self)
- except ImportError:
- import types
-
- self.setIn = types.MethodType(lambda self: None, self)
- self.setOut = self.setIn
- self.get_state = types.MethodType(lambda self: "unknown", self)
-
- def userName(self):
- return self.dev.username
-
- # WagoPneu HO methods
- def initWagoPneu(self):
- self.dev.connect(self.dev, "wagoStateChanged", self.stateChangedWagoPneu)
-
- def setInWagoPneu(self):
- self.duoStateChangedSignal.emit("moving")
- self.dev.wagoIn()
-
- def setOutWagoPneu(self):
- self.duoStateChangedSignal.emit("moving")
- self.dev.wagoOut()
-
- def stateChangedWagoPneu(self, state):
- try:
- state = WrapperHO.WAGO_STATE[state]
- except KeyError:
- state = "error"
- self.duoStateChangedSignal.emit(state)
-
- def getStateWagoPneu(self):
- state = self.dev.getWagoState()
- try:
- state = WrapperHO.WAGO_STATE[state]
- except KeyError:
- state = "error"
- return state
-
- # Shutter HO methods
- def initShutter(self):
- self.dev.connect(self.dev, "shutterStateChanged", self.stateChangedShutter)
-
- def setInShutter(self):
- self.dev.openShutter()
-
- def setOutShutter(self):
- self.dev.closeShutter()
-
- def stateChangedShutter(self, state, state_label=None):
- state = WrapperHO.SHUTTER_STATE.get(state, "unknown")
- if not state_label:
- state_label = ""
- self.duoStateChangedSignal.emit(state, state_label)
-
- def getStateShutter(self):
- state = self.dev.getShutterState()
- try:
- state = WrapperHO.SHUTTER_STATE[state]
- except KeyError:
- state = "error"
- return state
-
- # SpecMotorWSpecPositions HO methods
- def initSpecMotorWSpecPositions(self):
- self.positions = None
- self.dev.connect(
- self.dev,
- "predefinedPositionChanged",
- self.position_changed_spec_motor_wspec_positions,
- )
- self.dev.connect(
- self.dev, "stateChanged", self.stateChangedSpecMotorWSpecPositions
- )
- self.dev.connect(
- self.dev,
- "newPredefinedPositions",
- self.new_predefined_spec_motor_wspec_positions,
- )
-
- def setInSpecMotorWSpecPositions(self):
- if self.positions is not None:
- self.dev.moveToPosition(self.positions[1])
-
- def setOutSpecMotorWSpecPositions(self):
- if self.positions is not None:
- self.dev.moveToPosition(self.positions[0])
-
- def stateChangedSpecMotorWSpecPositions(self, state):
- # logging.info("stateChangedSpecMotorWSpecPositions %s" % state)
- try:
- state = WrapperHO.MOTOR_WSTATE[state]
- except IndexError:
- state = "error"
- if state is not None:
- self.duoStateChangedSignal.emit(state)
-
- def position_changed_spec_motor_wspec_positions(self, pos_name, pos):
- if self.dev.get_state() != self.dev.READY:
- return
- state = "error"
- if self.positions is not None:
- for i in range(len(self.positions)):
- if pos_name == self.positions[i]:
- state = WrapperHO.MOTOR_WPOS[i]
- self.duoStateChangedSignal.emit(state)
-
- def get_state_spec_motor_wspec_positions(self):
- if self.positions is None:
- return "error"
- curr_pos = self.dev.get_current_position_name()
- if curr_pos is None:
- state = self.dev.get_state()
- try:
- state = WrapperHO.MOTOR_WSTATE[state]
- except IndexError:
- state = "error"
- return state
- else:
- for i in range(len(self.positions)):
- if curr_pos == self.positions[i]:
- return WrapperHO.MOTOR_WPOS[i]
- return "error"
-
- def new_predefined_spec_motor_wspec_positions(self):
- self.positions = self.dev.get_predefined_positions_list()
- self.position_changed_spec_motor_wspec_positions(
- self.dev.get_current_position_name(), self.dev.get_value()
- )
-
- # Procedure HO methods
- def init_procedure(self):
- cmds = self.dev.get_commands()
-
- self.set_in_cmd = None
- self.set_out_cmd = None
-
- try:
- channel = self.dev.get_channel_object("dev_state")
- except KeyError:
- channel = None
- self.stateChannel = channel
- if self.stateChannel is not None:
- self.state_dict = {
- "OPEN": "in",
- "CLOSED": "out",
- "ERROR": "error",
- "1": "in",
- "0": "out",
- }
- self.stateChannel.connect_signal("update", self.channel_update)
- else:
- self.state_dict = {}
-
- for cmd in cmds:
- if cmd.name() == "set in":
- self.set_in_cmd = cmd
- if self.stateChannel is not None:
- self.set_in_cmd.connect_signal(
- "commandReplyArrived", self.procedureSetInEnded
- )
- self.set_in_cmd.connect_signal(
- "commandBeginWaitReply", self.procedure_started
- )
- self.set_in_cmd.connect_signal(
- "commandFailed", self.procedure_aborted
- )
- self.set_in_cmd.connect_signal(
- "commandAborted", self.procedure_aborted
- )
- elif cmd.name() == "set out":
- self.set_out_cmd = cmd
- if self.stateChannel is not None:
- self.set_out_cmd.connect_signal(
- "commandReplyArrived", self.procedure_set_out_ended
- )
- self.set_out_cmd.connect_signal(
- "commandBeginWaitReply", self.procedure_started
- )
- self.set_out_cmd.connect_signal(
- "commandFailed", self.procedure_aborted
- )
- self.set_out_cmd.connect_signal(
- "commandAborted", self.procedure_aborted
- )
-
- def channel_update(self, value):
- try:
- key = self.dev.statekey
- except AttributeError:
- pass
- else:
- try:
- state = value[key]
- except TypeError:
- state = "error"
- try:
- state = self.state_dict[state]
- except KeyError:
- pass
- self.duoStateChangedSignal.emit(state)
-
- def set_in_procedure(self):
- if self.set_in_cmd is not None:
- self.set_in_cmd()
-
- def set_out_procedure(self):
- if self.set_out_cmd is not None:
- self.set_out_cmd()
-
- """
- def stateChangedProcedure(self,state):
- pass
- """
-
- def get_state_procedure(self):
- if self.stateChannel is not None:
- try:
- state = self.stateChannel.get_value()
- except BaseException:
- state = "error"
- else:
- try:
- key = self.dev.statekey
- except AttributeError:
- pass
- else:
- try:
- state = state[key]
- except TypeError:
- state = "error"
- try:
- state = self.state_dict[state]
- except KeyError:
- pass
- return state
- return "unknown"
-
- def procedureSetInEnded(self, *args):
- self.duoStateChangedSignal.emit("in")
-
- def procedure_set_out_ended(self, *args):
- self.duoStateChangedSignal.emit("out")
-
- def procedure_started(self, *args):
- self.duoStateChangedSignal.emit("moving")
-
- def procedure_aborted(self, *args):
- self.duoStateChangedSignal.emit("error")
diff --git a/mxcubeqt/bricks/desy/p11_machine_info_brick.py b/mxcubeqt/bricks/desy/p11_machine_info_brick.py
new file mode 100644
index 000000000..1ac42e9b2
--- /dev/null
+++ b/mxcubeqt/bricks/desy/p11_machine_info_brick.py
@@ -0,0 +1,150 @@
+#
+# Project: MXCuBE
+# https://github.com/mxcube
+#
+# This file is part of MXCuBE software.
+#
+# MXCuBE is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# MXCuBE is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with MXCuBE. If not, see .
+
+from mxcubeqt.base_components import BaseWidget
+from mxcubeqt.utils import icons, colors, qt_import
+from mxcubeqt.widgets.matplot_widget import TwoAxisPlotWidget
+
+from mxcubecore import HardwareRepository as HWR
+import logging
+
+from PyQt5.QtWidgets import QLineEdit
+
+STATES = {"unknown": colors.GRAY, "ready": colors.LIGHT_BLUE, "error": colors.LIGHT_RED}
+
+
+__credits__ = ["MXCuBE collaboration"]
+__license__ = "LGPLv3+"
+__category__ = "DESY"
+
+from mxcubeqt.base_components import BaseWidget
+from mxcubeqt.utils import qt_import
+import logging
+from PyQt5.QtCore import QMetaObject, Qt
+from PyQt5.QtWidgets import (
+ QApplication,
+ QWidget,
+ QLabel,
+ QVBoxLayout,
+ QFormLayout,
+ QGroupBox,
+)
+
+
+class P11MachineInfoBrick(BaseWidget):
+ """Brick to display information about synchrotron and beamline as simple text lines."""
+
+ def __init__(self, *args):
+ super().__init__(*args)
+
+ self.current_label_text = qt_import.QLabel(self)
+ self.current_label = qt_import.QLabel(self)
+
+ self.message_label_text = qt_import.QLabel(self)
+ self.message_label = qt_import.QLabel(self)
+
+ self.lifetime_label_text = qt_import.QLabel(self)
+ self.lifetime_label = qt_import.QLabel(self)
+
+ self.energy_label_text = qt_import.QLabel(self)
+ self.energy_label = qt_import.QLabel(self)
+
+ # Set default values
+ self.current_label_text.setText("Machine current")
+ self.current_label.setText("N/A mA")
+ self.current_label.setStyleSheet("background-color: #6cb2f8;")
+ self.current_label.setAlignment(Qt.AlignCenter)
+
+ self.message_label_text.setText("Machine state")
+ self.message_label.setStyleSheet("background-color: #6cb2f8;")
+ self.message_label.setText("N/A")
+ self.message_label.setAlignment(Qt.AlignCenter)
+
+ self.lifetime_label_text.setText("Lifetime")
+ self.lifetime_label.setText("N/A hours")
+ self.lifetime_label.setStyleSheet("background-color: #6cb2f8;")
+ self.lifetime_label.setAlignment(Qt.AlignCenter)
+
+ self.energy_label_text.setText("Energy")
+ self.energy_label.setText("N/A GeV")
+ self.energy_label.setStyleSheet("background-color: #6cb2f8;")
+ self.energy_label.setAlignment(Qt.AlignCenter)
+
+ # Add labels to layout
+ self.main_layout = qt_import.QVBoxLayout(self)
+
+ self.main_layout.addWidget(self.current_label_text)
+ self.main_layout.addWidget(self.current_label)
+
+ self.main_layout.addWidget(self.message_label_text)
+ self.main_layout.addWidget(self.message_label)
+
+ self.main_layout.addWidget(self.lifetime_label_text)
+ self.main_layout.addWidget(self.lifetime_label)
+
+ self.main_layout.addWidget(self.energy_label_text)
+ self.main_layout.addWidget(self.energy_label)
+
+ def update_labels_in_ui_thread(self, current_value):
+ QMetaObject.invokeMethod(
+ self.current_label, "setText", Qt.QueuedConnection, f"{current_value} mA"
+ )
+
+ def run(self):
+ """Connect the signal from the hardware object."""
+ if HWR.beamline.machine_info is not None:
+ HWR.beamline.machine_info.valuesChanged.connect(self.set_value)
+ else:
+ logging.error("Machine info object not available")
+
+ def set_value(self, values_dict):
+ """Update the labels in the MachineInfoBrick with machine values."""
+ logging.info(f"Received machine info values: {values_dict}")
+
+ current_value = values_dict.get("current", {}).get("value", "N/A")
+ lifetime_value = values_dict.get("lifetime", {}).get("value", "N/A")
+ energy_value = values_dict.get("energy", {}).get("value", "N/A")
+ message_value = values_dict.get("message", {}).get("value", "N/A")
+
+ # Update the UI labels
+ self.current_label.setText(f"{current_value} mA")
+ self.lifetime_label.setText(f"{lifetime_value} hours")
+ self.energy_label.setText(f"{energy_value} GeV")
+ self.message_label.setText(f"{message_value}")
+
+ # Check if machine current is <= 99, change color
+ if current_value != "N/A" and float(current_value) <= 99:
+ self.set_all_labels_color("salmon")
+ else:
+ self.reset_all_labels_color()
+
+ def set_all_labels_color(self, color):
+ """Set all label backgrounds to the specified color."""
+ self.current_label.setStyleSheet(f"background-color: {color};")
+ self.message_label.setStyleSheet(f"background-color: {color};")
+ self.lifetime_label.setStyleSheet(f"background-color: {color};")
+ self.energy_label.setStyleSheet(f"background-color: {color};")
+
+ def reset_all_labels_color(self):
+ """Reset all label backgrounds to their default color."""
+ default_color = "#6cb2f8"
+ self.current_label.setStyleSheet(f"background-color: {default_color};")
+ self.message_label.setStyleSheet(f"background-color: {default_color};")
+ self.lifetime_label.setStyleSheet(f"background-color: {default_color};")
+ self.energy_label.setStyleSheet(f"background-color: {default_color};")
diff --git a/mxcubeqt/bricks/desy/p11_proposal_brick.py b/mxcubeqt/bricks/desy/p11_proposal_brick.py
index 5e75a356b..519093a0e 100644
--- a/mxcubeqt/bricks/desy/p11_proposal_brick.py
+++ b/mxcubeqt/bricks/desy/p11_proposal_brick.py
@@ -17,6 +17,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with MXCuBE. If not, see .
+__credits__ = ["MXCuBE collaboration"]
+__license__ = "LGPLv3+"
+__category__ = "DESY"
+
+
import logging
import os
@@ -24,6 +29,7 @@
from mxcubeqt.bricks.proposal_brick import ProposalBrick, ProposalGUIEvent
from mxcubecore import HardwareRepository as HWR
+
class P11ProposalBrick(ProposalBrick):
def __init__(self, *args):
super(P11ProposalBrick, self).__init__(*args)
@@ -89,25 +95,61 @@ def run(self):
qt_import.QApplication.postEvent(self, start_server_event)
def p11_login_as_proposal(self):
+ try:
+ if HWR.beamline.lims.simulated_proposal == 1:
+ proposal_code = HWR.beamline.lims.simulated_prop_code
+ proposal_number = HWR.beamline.lims.simulated_prop_number
+ else:
+ proposal_code = HWR.beamline.session.get_current_proposal_code()
+ proposal_number = HWR.beamline.session.get_current_proposal_number()
- if HWR.beamline.lims.simulated_proposal == 1:
- proposal_code = HWR.beamline.lims.simulated_prop_code
- proposal_number = HWR.beamline.lims.simulated_prop_number
- else:
- proposal_code = HWR.beamline.session.get_current_proposal_code()
- proposal_number = HWR.beamline.session.get_current_proposal_number()
+ logging.getLogger("HWR").debug(
+ " PROPOSAL BRICK - code is %s" % proposal_code
+ )
+ logging.getLogger("HWR").debug(
+ " PROPOSAL BRICK - number is %s" % proposal_number
+ )
+
+ # Fetch proposal data
+ prop = HWR.beamline.lims.get_proposal(proposal_code, proposal_number)
- logging.getLogger("HWR").debug(" PROPOSAL BRICK - code is %s" % proposal_code)
- logging.getLogger("HWR").debug(
- " PROPOSAL BRICK - number is %s" % proposal_number
- )
+ # Check for ISPyB connection error
+ if prop["status"]["code"] == "error":
+ self.message_widget.setText("ISPyB is not connected.")
+ self.message_widget.show()
- self._do_login_as_proposal(
- proposal_code, proposal_number, None, HWR.beamline.lims.beamline_name,
- )
+ # Display the available proposal info
+ self.show_selected_proposal(prop["Proposal"])
+
+ except Exception as e:
+ # Catch any errors and display them as warnings but proceed
+ logging.getLogger("HWR").error(f"Error logging in as proposal: {str(e)}")
+ self.message_widget.setText(f"Error: {str(e)}")
+ self.message_widget.show()
+ self.show_selected_proposal(
+ {"code": proposal_code, "number": proposal_number}
+ )
def show_selected_proposal(self, proposal):
+ """
+ Display the selected proposal information even if incomplete.
+ """
+ try:
+ beamtime_id = HWR.beamline.session.get_current_beamtime_id()
+ prop_code = str(proposal.get("code", "Unknown"))
+ prop_number = str(proposal.get("number", "Unknown"))
+
+ prop_info = f"ID: {prop_code}-{prop_number} - BT_ID: {beamtime_id}"
+ self.proposal_info.setText(prop_info)
+ self.proposal_info.show()
+
+ except KeyError as e:
+ logging.getLogger("HWR").error(f"Missing proposal information: {str(e)}")
+ self.proposal_info.setText(f"ID: {prop_code}-Unknown - BT_ID: Unknown")
+ self.proposal_info.show()
+
+ def show_selected_proposal(self, proposal):
beamtime_id = HWR.beamline.session.get_current_beamtime_id()
prop_number = str(proposal["number"])
prop_code = str(proposal["code"])
diff --git a/mxcubeqt/bricks/desy/p11_sample_changer_brick.py b/mxcubeqt/bricks/desy/p11_sample_changer_brick.py
index d41ef1313..aa9c8be99 100644
--- a/mxcubeqt/bricks/desy/p11_sample_changer_brick.py
+++ b/mxcubeqt/bricks/desy/p11_sample_changer_brick.py
@@ -17,6 +17,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with MXCuBE. If not, see .
+__credits__ = ["MXCuBE collaboration"]
+__license__ = "LGPLv3+"
+__category__ = "DESY"
+
+
from mxcubeqt.bricks.cats_simple_brick import CatsSimpleBrick
diff --git a/mxcubeqt/bricks/desy/p11_simple_brick.py b/mxcubeqt/bricks/desy/p11_simple_brick.py
index ef55e24cc..673acbf70 100644
--- a/mxcubeqt/bricks/desy/p11_simple_brick.py
+++ b/mxcubeqt/bricks/desy/p11_simple_brick.py
@@ -34,7 +34,12 @@
from mxcubeqt.base_components import BaseWidget
from mxcubeqt.utils import colors, qt_import
from mxcubeqt.utils import sample_changer_helper as sc_helper
-from mxcubeqt.bricks.sample_changer_brick import SampleChangerBrick, BasketView, VialView, StatusView
+from mxcubeqt.bricks.sample_changer_brick import (
+ SampleChangerBrick,
+ BasketView,
+ VialView,
+ StatusView,
+)
from mxcubecore import HardwareRepository as HWR
@@ -44,12 +49,10 @@
class P11SCStatusView(qt_import.QWidget):
-
# statusMsgChangedSignal = qt_import.pyqtSignal(str, qt_import.QColor)
# resetSampleChangerSignal = qt_import.pyqtSignal()
def __init__(self, parent, brick):
-
qt_import.QWidget.__init__(self, parent)
self._parent = brick
@@ -94,7 +97,6 @@ def __init__(self, parent, brick):
# Qt signal/slot connections ------------------------------------------
-
def set_expert_mode(self, expert):
pass
@@ -104,7 +106,6 @@ def setStatusMsg(self, status):
self.setToolTip(status)
def setState(self, state):
-
color = sc_helper.SC_STATE_COLOR.get(state, None)
if color is None:
@@ -121,10 +122,10 @@ def setState(self, state):
def setIcons(self, *args):
pass
+
class P11SimpleBrick(SampleChangerBrick):
def __init__(self, *args):
-
- super(P11SimpleBrick,self).__init__(*args)
+ super(P11SimpleBrick, self).__init__(*args)
self._powered_on = None
self.state = sc_helper.SampleChangerState.Ready
@@ -140,18 +141,18 @@ def __init__(self, *args):
self.double_click_loads_cbox.hide()
self.current_basket_view.hide()
- #self.current_sample_view.hide()
+ # self.current_sample_view.hide()
if HWR.beamline.sample_changer is not None:
- #self.connect(
- #HWR.beamline.sample_changer,
- #"runningStateChanged",
- #self._updatePathRunning,
- #)
+ # self.connect(
+ # HWR.beamline.sample_changer,
+ # "runningStateChanged",
+ # self._updatePathRunning,
+ # )
self.connect(
HWR.beamline.sample_changer,
"powerStateChanged",
- self._update_power_state
+ self._update_power_state,
)
self._powered_on = HWR.beamline.sample_changer.is_powered()
@@ -159,7 +160,7 @@ def __init__(self, *args):
def build_status_view(self, container):
return P11SCStatusView(container, self)
- #return StatusView(container)
+ # return StatusView(container)
def build_operations_widget(self):
self.buttons_layout = qt_import.QHBoxLayout()
@@ -168,16 +169,25 @@ def build_operations_widget(self):
self.load_button = qt_import.QPushButton("Load", self)
self.unload_button = qt_import.QPushButton("Unload", self)
self.wash_button = qt_import.QPushButton("Wash", self)
+ self.home_button = qt_import.QPushButton("Home position", self)
+ self.cool_button = qt_import.QPushButton("Cool position", self)
+ self.deice_button = qt_import.QPushButton("Deice", self)
self.abort_button = qt_import.QPushButton("Abort", self)
self.load_button.clicked.connect(self.load_selected_sample)
self.unload_button.clicked.connect(self.unload_sample)
self.wash_button.clicked.connect(self.wash_sample)
+ self.home_button.clicked.connect(self.home_robot)
+ self.cool_button.clicked.connect(self.cool_robot)
+ self.deice_button.clicked.connect(self.deice_robot)
self.abort_button.clicked.connect(self.abort_mounting)
self.buttons_layout.addWidget(self.load_button)
self.buttons_layout.addWidget(self.unload_button)
self.buttons_layout.addWidget(self.wash_button)
+ self.buttons_layout.addWidget(self.home_button)
+ self.buttons_layout.addWidget(self.cool_button)
+ self.buttons_layout.addWidget(self.deice_button)
self.operation_buttons_layout.addLayout(self.buttons_layout)
self.operation_buttons_layout.addWidget(self.abort_button)
self.operations_widget.setLayout(self.operation_buttons_layout)
@@ -217,6 +227,9 @@ def _update_buttons(self):
self.load_button.setEnabled(False)
self.unload_button.setEnabled(False)
self.wash_button.setEnabled(False)
+ self.home_button.setEnabled(False)
+ self.cool_button.setEnabled(False)
+ self.deice_button.setEnabled(False)
self.abort_button.setEnabled(False)
abort_color = colors.LIGHT_GRAY
elif ready:
@@ -245,8 +258,8 @@ def load_selected_sample(self):
logging.getLogger("GUI").info("Loading sample: %s / %s" % (basket, vial))
if basket is not None and vial is not None:
- sample_loc = "%d:%d" % (basket, vial)
- HWR.beamline.sample_changer.load(sample_loc, wait=False)
+ sample_loc = "%d:%d" % (basket, vial)
+ HWR.beamline.sample_changer.load(sample_loc, wait=False)
def unload_sample(self):
logging.getLogger("GUI").info("Unloading sample")
@@ -256,6 +269,17 @@ def wash_sample(self):
logging.getLogger("GUI").info("Washing sample")
HWR.beamline.sample_changer.wash()
+ def home_robot(self):
+ logging.getLogger("GUI").info("Home robot")
+ HWR.beamline.sample_changer.home()
+
+ def cool_robot(self):
+ logging.getLogger("GUI").info("Cool robot")
+ HWR.beamline.sample_changer.cool()
+
+ def deice_robot(self):
+ logging.getLogger("GUI").info("Deice robot")
+ HWR.beamline.sample_changer.deice()
def abort_mounting(self):
HWR.beamline.sample_changer._do_abort()
diff --git a/mxcubeqt/bricks/desy/value_state_brick.py b/mxcubeqt/bricks/desy/value_state_brick.py
index f573a4383..c30bf26a9 100644
--- a/mxcubeqt/bricks/desy/value_state_brick.py
+++ b/mxcubeqt/bricks/desy/value_state_brick.py
@@ -32,7 +32,6 @@
class ValueStateBrick(BaseWidget):
-
STATE_COLORS = (
colors.LIGHT_RED, # ALARM
colors.LIGHT_YELLOW, # WARNING
diff --git a/mxcubeqt/bricks/door_interlock_brick.py b/mxcubeqt/bricks/door_interlock_brick.py
index 3e1483f7b..bd1d0972a 100644
--- a/mxcubeqt/bricks/door_interlock_brick.py
+++ b/mxcubeqt/bricks/door_interlock_brick.py
@@ -84,12 +84,8 @@ def __init__(self, *args):
self.state_label.setToolTip("Shows the current door state")
self.unlock_door_button.setToolTip("Unlocks the doors")
- self.connect(
- HWR.beamline.hutch_interlock,
- "valueChanged",
- self.value_changed
- )
-
+ self.connect(HWR.beamline.hutch_interlock, "valueChanged", self.value_changed)
+
def unlock_doors(self):
self.unlock_door_button.setEnabled(False)
HWR.beamline.hutch_interlock.unlock()
diff --git a/mxcubeqt/bricks/machine_info_brick.py b/mxcubeqt/bricks/machine_info_brick.py
index 284c80326..c4604d93e 100644
--- a/mxcubeqt/bricks/machine_info_brick.py
+++ b/mxcubeqt/bricks/machine_info_brick.py
@@ -169,4 +169,3 @@ def update_info(self, info_dict):
self.value_plot.add_new_plot_value(value)
def open_history_view(self):
- self.value_plot.setVisible(not self.value_plot.isVisible())
diff --git a/mxcubeqt/bricks/multi_state_brick.py b/mxcubeqt/bricks/multi_state_brick.py
index e3ed53f36..e45f9c8cd 100644
--- a/mxcubeqt/bricks/multi_state_brick.py
+++ b/mxcubeqt/bricks/multi_state_brick.py
@@ -56,16 +56,13 @@
from mxcubecore.BaseHardwareObjects import HardwareObjectState
-
__credits__ = ["MXCuBE collaboration"]
__license__ = "LGPLv3+"
__category__ = "General"
class MultiStateBrick(BaseWidget):
- units = {
- "micron": u"\u03BC",
- }
+ units = {"micron": "\u03BC"}
def __init__(self, *args):
@@ -117,38 +114,37 @@ def __init__(self, *args):
def property_changed(self, property_name, old_value, new_value):
if property_name == "label":
- if new_value == "":
+ if new_value != "":
self.label.setText(new_value)
else:
- self.label.hide()
+ self.label.show()
+
elif property_name == "title":
if new_value != "":
self.main_gbox.setTitle(new_value)
+
elif property_name == "multibutton":
if new_value != "":
self.multibutton = new_value
- if len(self.positions):
+ if self.positions is not None and len(self.positions):
self.switch_multibutton_mode(self.multibutton)
- elif property_name == "mnemonic":
- if self.multi_hwobj is not None:
- self.disconnect(self.multi_hwobj, "stateChanged", self.state_changed)
- self.disconnect(
- self.multi_hwobj, "valueChanged", self.value_changed,
- )
+ elif property_name == "mnemonic":
+ # Get the new hardware object directly without using callbacks or signals
self.multi_hwobj = self.get_hardware_object(new_value)
if self.multi_hwobj is not None:
- self.connect(self.multi_hwobj, "stateChanged", self.state_changed)
- self.connect(
- self.multi_hwobj, "valueChanged", self.value_changed,
- )
-
+ # Set up the motor positions and buttons
self.fill_positions()
+
if self.multibutton:
self.switch_multibutton_mode(True)
- self.state_changed()
+
+ # Manually check the state of the motor and update the UI
+ self.state_changed(self.multi_hwobj.get_state())
+
else:
+ # Fall back to the base class method for other properties
BaseWidget.property_changed(self, property_name, old_value, new_value)
def switch_multibutton_mode(self, mode):
@@ -161,7 +157,8 @@ def switch_multibutton_mode(self, mode):
def get_position_label(self, posidx):
pos = self.positions[posidx]
- unit = self.multi_hwobj.get_property_value_by_index(posidx, "unit")
+ # Access the unit directly from self.multi_hwobj._positions
+ unit = self.multi_hwobj._positions.get(pos, {}).get("unit", "")
label = str(pos)
if unit:
label += self.units.get(unit, unit)
@@ -195,47 +192,101 @@ def fill_positions(self):
self.value_changed()
def change_value(self, index):
- if index >= 0:
- self.multi_hwobj.set_value(index)
+ """Change the hardware object to the selected value."""
+ # Check if positions is a list or dictionary
+ if isinstance(self.positions, list):
+ # If positions is a list, use the index directly
+ if 0 <= index < len(self.positions):
+ position_name = self.positions[index]
+ self.multi_hwobj.set_value(position_name)
+ else:
+ logging.error(f"Invalid index: {index}.")
+ elif isinstance(self.positions, dict):
+ # If positions is a dictionary, convert keys to a list and use the index
+ keys_list = list(self.positions.keys())
+ if 0 <= index < len(keys_list):
+ position_name = keys_list[index]
+ self.multi_hwobj.set_value(position_name)
+ else:
+ logging.error(f"Invalid index: {index}.")
+ else:
+ logging.error(f"Invalid type for positions: {type(self.positions)}")
def state_changed(self, state=None):
-
+ """Update the UI based on the current state of the hardware."""
if state is None:
state = self.multi_hwobj.get_state()
if state == HardwareObjectState.READY:
color = colors.LIGHT_GREEN
+ self.label.setText("Motor Ready")
self.setEnabled(True)
elif state == HardwareObjectState.BUSY:
color = colors.LIGHT_YELLOW
+ self.label.setText("Motor Busy")
self.setEnabled(False)
else:
color = colors.LIGHT_GRAY
+ self.label.setText("Motor Not Ready")
self.setEnabled(False)
+ # Update colors in the UI
colors.set_widget_color(
self.multi_position_combo, color, qt_import.QPalette.Button
)
-
- for but in self.multibuttons:
- colors.set_widget_color(but, color, qt_import.QPalette.Button)
+ for button in self.multibuttons:
+ colors.set_widget_color(button, color, qt_import.QPalette.Button)
def value_changed(self, value=None):
-
+ """This method is called when the hardware object's value changes."""
self.multi_position_combo.blockSignals(True)
if value is None:
+ # Get the current value from the hardware object
value = self.multi_hwobj.get_value()
- if value >= 0 and value < len(self.positions):
- self.multi_position_combo.setCurrentIndex(value)
+ # Check if positions exist and handle both list and dict cases
+ if isinstance(self.positions, dict):
+ positions_list = list(self.positions.keys())
+ elif isinstance(self.positions, list):
+ positions_list = self.positions
+ else:
+ logging.error(f"Invalid type for positions: {type(self.positions)}")
+ positions_list = []
+
+ # Handle string positions and index values
+ if isinstance(value, str):
+ if value in positions_list:
+ # Set the current index to the matching string position
+ self.multi_position_combo.setCurrentIndex(positions_list.index(value))
+ self.label.setText(f"Current Position: {value}")
+ else:
+ logging.error(f"Unknown position: {value}")
+ self.label.setText("Unknown Position")
+ self.multi_position_combo.setCurrentIndex(-1)
else:
- self.multi_position_combo.setCurrentIndex(-1)
+ try:
+ # If value is an index, convert it to an integer
+ value = int(value)
+ except (ValueError, TypeError):
+ logging.error(
+ f"Invalid value type: {value}. Expected an integer or string."
+ )
+ value = -1
+
+ if 0 <= value < len(positions_list):
+ # Set the current index based on the integer value
+ self.multi_position_combo.setCurrentIndex(value)
+ self.label.setText(f"Current Position: {positions_list[value]}")
+ else:
+ self.multi_position_combo.setCurrentIndex(-1)
+ self.label.setText("Unknown Position")
self.multi_position_combo.blockSignals(False)
- # value is index
+ # Update button states
for button in self.multibuttons:
button.setEnabled(True)
- self.multibuttons[value].setEnabled(False)
+ if isinstance(value, int) and 0 <= value < len(self.multibuttons):
+ self.multibuttons[value].setEnabled(False)
diff --git a/mxcubeqt/bricks/progress_bar_brick.py b/mxcubeqt/bricks/progress_bar_brick.py
index 931307f78..9835ac55c 100644
--- a/mxcubeqt/bricks/progress_bar_brick.py
+++ b/mxcubeqt/bricks/progress_bar_brick.py
@@ -76,7 +76,7 @@ def step_progress(self, step, msg=None):
# f self.use_dialog:
# BaseWidget.set_progress_dialog_step(step)
# lse:
- self.progress_bar.setValue(step)
+ self.progress_bar.setValue(int(step))
self.setEnabled(True)
# BaseWidget.set_progress_bar_step(step)
diff --git a/mxcubeqt/gui_builder.py b/mxcubeqt/gui_builder.py
index 76db7a48d..c676d89e7 100644
--- a/mxcubeqt/gui_builder.py
+++ b/mxcubeqt/gui_builder.py
@@ -1262,7 +1262,7 @@ def __init__(self, *args, **kwargs):
self.log_window.setWindowTitle("Log window")
sw = qt_import.QApplication.desktop().screen().width()
sh = qt_import.QApplication.desktop().screen().height()
- self.log_window.resize(qt_import.QSize(sw * 0.8, sh * 0.2))
+ self.log_window.resize(qt_import.QSize(int(sw * 0.8), int(sh * 0.2)))
self.property_editor_window = PropertyEditorWindow(None)
self.gui_preview_window = GUIPreviewWindow(None)
self.configuration = self.gui_editor_window.configuration
diff --git a/mxcubeqt/utils/gui_display.py b/mxcubeqt/utils/gui_display.py
index 5d7c8dd8f..942d57db4 100644
--- a/mxcubeqt/utils/gui_display.py
+++ b/mxcubeqt/utils/gui_display.py
@@ -477,18 +477,18 @@ def paintEvent(self, event):
if self.orientation == "horizontal":
height = self.height() / 2
- painter.drawLine(0, height, self.width(), height)
- painter.drawLine(0, height, 5, height - 5)
- painter.drawLine(0, height, 5, height + 5)
- painter.drawLine(self.width(), height, self.width() - 5, height - 5)
- painter.drawLine(self.width(), height, self.width() - 5, height + 5)
+ painter.drawLine(0, int(height), int(self.width()), int(height))
+ painter.drawLine(0,int(height), 5, int(height) - 5)
+ painter.drawLine(0, int(height), 5, int(height) + 5)
+ painter.drawLine(self.width(), int(height), self.width() - 5, int(height) - 5)
+ painter.drawLine(self.width(), int(height), self.width() - 5, int(height) + 5)
else:
width = self.width() / 2
- painter.drawLine(self.width() / 2, 0, self.width() / 2, self.height())
- painter.drawLine(width, 0, width - 5, 5)
- painter.drawLine(width, 0, width + 5, 5)
- painter.drawLine(width, self.height(), width - 5, self.height() - 5)
- painter.drawLine(width, self.height(), width + 5, self.height() - 5)
+ painter.drawLine(int(self.width() / 2), 0,int(self.width() / 2),int( self.height()))
+ painter.drawLine(int(width), 0, int(width) - 5, 5)
+ painter.drawLine(int(width), 0, int(width) + 5, 5)
+ painter.drawLine(int(width), self.height(), int(width) - 5, self.height() - 5)
+ painter.drawLine(int(width), self.height(), int(width) + 5, self.height() - 5)
class CustomFrame(qt_import.QFrame):
def __init__(self, *args, **kwargs):
diff --git a/mxcubeqt/widgets/acquisition_ssx_widget.py b/mxcubeqt/widgets/acquisition_ssx_widget.py
index f7fbdb8d2..fab973104 100644
--- a/mxcubeqt/widgets/acquisition_ssx_widget.py
+++ b/mxcubeqt/widgets/acquisition_ssx_widget.py
@@ -339,18 +339,20 @@ def update_energy_limits(self, limits):
def update_transmission_limits(self, limits):
"""
- Updates transmission limits
- :param limits: list of two floats
- :return: None
+ Updates transmission limits.
+
+ Args:
+ limits (tuple): A tuple containing the minimum and maximum transmission limits.
"""
- if limits:
+ if limits and limits[0] is not None and limits[1] is not None:
self.transmission_validator.setBottom(limits[0])
self.transmission_validator.setTop(limits[1])
self.acq_widget_layout.transmission_ledit.setToolTip(
"Transmission limits %0.2f : %0.2f %%\n" % (limits[0], limits[1])
- + "2 digits precision."
)
self._acquisition_mib.validate_all()
+ else:
+ self.acq_widget_layout.transmission_ledit.setToolTip(r"Invalid transmission limits: {}".format(limits))
def update_resolution_limits(self, limits):
"""
diff --git a/mxcubeqt/widgets/acquisition_widget.py b/mxcubeqt/widgets/acquisition_widget.py
index 27776e84b..2b731bd5b 100644
--- a/mxcubeqt/widgets/acquisition_widget.py
+++ b/mxcubeqt/widgets/acquisition_widget.py
@@ -498,9 +498,11 @@ def init_limits(self):
self.set_tunable_energy(HWR.beamline.tunable_wavelength)
has_shutter_less = HWR.beamline.detector.has_shutterless()
- self.acq_widget_layout.shutterless_cbx.setEnabled(has_shutter_less)
+ self.acq_widget_layout.shutterless_cbx.setEnabled(False)
self.acq_widget_layout.shutterless_cbx.setChecked(has_shutter_less)
+
+
if HWR.beamline.disable_num_passes:
num_passes = self.acq_widget_layout.findChild(
qt_import.QLineEdit, "num_passes_ledit"
@@ -660,7 +662,13 @@ def update_energy_limits(self, limits):
self._acquisition_mib.validate_all()
def update_transmission_limits(self, limits):
- if limits:
+ """
+ Updates the transmission limits in the validator.
+
+ Args:
+ limits (tuple): A tuple containing the minimum and maximum transmission limits.
+ """
+ if limits and limits[0] is not None and limits[1] is not None:
self.transmission_validator.setBottom(limits[0])
self.transmission_validator.setTop(limits[1])
self.acq_widget_layout.transmission_ledit.setToolTip(
@@ -668,6 +676,8 @@ def update_transmission_limits(self, limits):
+ "2 digits precision."
)
self._acquisition_mib.validate_all()
+ else:
+ self.acq_widget_layout.transmission_ledit.setToolTip("Invalid transmission limits received: {}".format(limits))
def update_resolution_limits(self, limits):
if limits:
diff --git a/mxcubeqt/widgets/acquisition_widget_simple.py b/mxcubeqt/widgets/acquisition_widget_simple.py
index e67060b2e..15ec06211 100644
--- a/mxcubeqt/widgets/acquisition_widget_simple.py
+++ b/mxcubeqt/widgets/acquisition_widget_simple.py
@@ -294,13 +294,21 @@ def update_energy_limits(self, limits):
self._acquisition_mib.validate_all()
def update_transmission_limits(self, limits):
- if limits:
+ """
+ Updates the transmission limits in the validator.
+
+ Args:
+ limits (tuple): A tuple containing the minimum and maximum transmission limits.
+ """
+ if limits and limits[0] is not None and limits[1] is not None:
self.transmission_validator.setBottom(limits[0])
self.transmission_validator.setTop(limits[1])
self.acq_widget_layout.transmission_ledit.setToolTip(
"Transmission limits %0.3f : %0.3f" % (limits[0], limits[1])
)
self._acquisition_mib.validate_all()
+ else:
+ self.acq_widget_layout.transmission_ledit.setToolTip(r"Invalid transmission limits received: {}".format(limits))
def update_resolution_limits(self, limits):
if limits: