예제 #1
0
    def prompt_parameters(self, xml):
        logging.debug('got back XML from server:\n%s', xml)
        # Edited by Olof 2013/04/16: Temporary fix for handling messages containing
        # XML markup
        #xml_root = etree.fromstring(xml)
        xml_root = etree.fromstring(xml, parser=etree.XMLParser(recover=True))

        # Special case until Olof implements the saner XML format on the server side
        if xml_root.tag == 'message':
            message = dict(type='message', level='info', text='no message')
            for node in xml_root:
                option = node.tag.strip()
                # rename type to level, as type is used for the type
                # this is unfortunate
                if option == 'type':
                    option = 'level'
                message[option] = node.text.strip()
            fields = [message]
        else:
            containers = get_field_containers(xml_root)
            if len(containers) == 0: return
            fields = get_fields(containers[0])
        if self.params_widget is not None:
            self.layout().removeChild(self.params_widget)
        self.params_widget = FieldsWidget(fields, self)

        current_values = self.workflow.get_values_map()
        logging.debug('current values are: %s', current_values)
        self.params_widget.set_values(current_values)
        self.layout().addMultiCellWidget(self.params_widget, 1, 1, 0, 1,
                                         Qt.AlignBottom | Qt.AlignLeft)
        self.params_widget.show()
        self.ok_button.setEnabled(True)
예제 #2
0
    def prompt_parameters(self, xml):
        logging.debug("got back XML from server:\n%s", xml)
        # Edited by Olof 2013/04/16: Temporary fix for handling messages containing
        # XML markup
        # xml_root = etree.fromstring(xml)
        xml_root = etree.fromstring(xml, parser=etree.XMLParser(recover=True))

        # Special case until Olof implements the saner XML format on the server side
        if xml_root.tag == "message":
            message = dict(type="message", level="info", text="no message")
            for node in xml_root:
                option = node.tag.strip()
                # rename type to level, as type is used for the type
                # this is unfortunate
                if option == "type":
                    option = "level"
                message[option] = node.text.strip()
            fields = [message]
        else:
            containers = get_field_containers(xml_root)
            if len(containers) == 0:
                return
            fields = get_fields(containers[0])
        if self.params_widget is not None:
            self.layout().removeChild(self.params_widget)
        self.params_widget = FieldsWidget(fields, self)

        current_values = self.workflow.get_values_map()
        logging.debug("current values are: %s", current_values)
        self.params_widget.set_values(current_values)
        self.layout().addMultiCellWidget(
            self.params_widget, 1, 1, 0, 1, Qt.AlignBottom | Qt.AlignLeft
        )
        self.params_widget.show()
        self.ok_button.setEnabled(True)
예제 #3
0
class GphlDataDialog(qt.QDialog):
    def __init__(self, parent=None, name=None, fl=0):
        qt.QWidget.__init__(self, parent, name, fl)

        # AsyncResult to return values
        self._async_result = None

        # Layout
        qt.QVBoxLayout(self)
        main_layout = self.layout()
        main_layout.setSpacing(10)
        main_layout.setMargin(6)
        self.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)

        self.setCaption("GPhL Workflow parameters")

        # Info box
        self.info_gbox = qt.QVGroupBox("Info", self, "info_gbox")
        main_layout.addWidget(self.info_gbox)
        self.info_text = qt.QTextEdit(self.info_gbox, "info_text")
        self.info_text.setTextFormat(0)  # PlainText
        self.info_text.setFont(qt.QFont("Courier"))
        self.info_text.setReadOnly(True)

        # Special parameter box
        self.cplx_gbox = qt.QVGroupBox("Indexing solution", self, "cplx_gbox")
        main_layout.addWidget(self.cplx_gbox)
        self.cplx_widget = None

        # Parameter box
        self.parameter_gbox = qt.QVGroupBox("Parameters", self,
                                            "parameter_gbox")
        main_layout.addWidget(self.parameter_gbox)
        self.params_widget = None

        # Button bar
        button_layout = qt.QHBoxLayout(None, 0, 6, "button_layout")
        hspacer = qt.QSpacerItem(1, 20, qt.QSizePolicy.Expanding,
                                 qt.QSizePolicy.Minimum)
        button_layout.addItem(hspacer)
        self.continue_button = qt.QPushButton("Continue", self,
                                              "continue_button")
        button_layout.addWidget(self.continue_button)
        self.cancel_button = qt.QPushButton("Abort", self, "cancel_button")
        button_layout.addWidget(self.cancel_button)
        main_layout.addLayout(button_layout)

        qt.QObject.connect(self.continue_button, qt.SIGNAL("clicked()"),
                           self.continue_button_click)

        qt.QObject.connect(self.cancel_button, qt.SIGNAL("clicked()"),
                           self.cancel_button_click)

        self.resize(qt.QSize(1018, 472).expandedTo(self.minimumSizeHint()))
        self.clearWState(qt.Qt.WState_Polished)

    def continue_button_click(self):
        result = {}
        if self.parameter_gbox.isVisible():
            result.update(self.params_widget.get_parameters_map())
        if self.cplx_gbox.isVisible():
            result["_cplx"] = self.cplx_widget.get_value()
        self.accept()
        self._async_result.set(result)
        self._async_result = None

    def cancel_button_click(self):
        self.reject()
        self.parent.workflow_model.workflow_hwobj.abort("Manual abort")

    def open_dialog(self, field_list, async_result):

        self._async_result = async_result

        # get special parameters
        parameters = []
        info = None
        cplx = None
        for dd0 in field_list:
            if info is None and dd0.get("variableName") == "_info":
                # Info text - goes to info_gbox
                info = dd0
            elif cplx is None and dd0.get("variableName") == "_cplx":
                # Complex parameter - goes to cplx_gbox
                cplx = dd0
            else:
                parameters.append(dd0)

        # Info box
        if info is None:
            self.info_text.setText("")
            self.info_gbox.setTitle("Info")
            self.info_gbox.hide()
        else:
            self.info_text.setText(info.get("defaultValue"))
            self.info_gbox.setTitle(info.get("uiLabel"))
            self.info_gbox.show()

        # Complex box
        if self.cplx_widget:
            self.cplx_widget.close()
        if cplx is None:
            self.cplx_gbox.hide()
        else:
            if cplx.get("type") == "selection_table":
                self.cplx_widget = SelectionTable(self.cplx_gbox,
                                                  "cplx_widget",
                                                  cplx["header"])
                self.cplx_gbox.setTitle(cplx.get("uiLabel"))
                for ii, values in enumerate(cplx["defaultValue"]):
                    self.cplx_widget.populateColumn(
                        ii, values, colours=cplx.get("colours"))
                self.cplx_gbox.show()

            else:
                raise NotImplementedError(
                    "GPhL complex widget type %s not recognised for parameter _cplx"
                    % repr(cplx.get("type")))

        # parameters widget
        if self.params_widget is not None:
            self.params_widget.close()
            self.params_widget = None
        if parameters:
            self.params_widget = FieldsWidget(fields=parameters,
                                              parent=self.parameter_gbox)

            values = {}
            for dd0 in field_list:
                name = dd0["variableName"]
                value = dd0.get("defaultValue")
                if value is not None:
                    dd0[name] = value
            self.params_widget.set_values(values)
            self.parameter_gbox.show()
        else:
            self.parameter_gbox.hide()

        self.show()
        self.setEnabled(True)
예제 #4
0
    def open_dialog(self, field_list, async_result):

        self._async_result = async_result

        # get special parameters
        parameters = []
        info = None
        cplx = None
        for dd0 in field_list:
            if info is None and dd0.get("variableName") == "_info":
                # Info text - goes to info_gbox
                info = dd0
            elif cplx is None and dd0.get("variableName") == "_cplx":
                # Complex parameter - goes to cplx_gbox
                cplx = dd0
            else:
                parameters.append(dd0)

        # Info box
        if info is None:
            self.info_text.setText("")
            self.info_gbox.setTitle("Info")
            self.info_gbox.hide()
        else:
            self.info_text.setText(info.get("defaultValue"))
            self.info_gbox.setTitle(info.get("uiLabel"))
            self.info_gbox.show()

        # Complex box
        if self.cplx_widget:
            self.cplx_widget.close()
        if cplx is None:
            self.cplx_gbox.hide()
        else:
            if cplx.get("type") == "selection_table":
                self.cplx_widget = SelectionTable(self.cplx_gbox,
                                                  "cplx_widget",
                                                  cplx["header"])
                self.cplx_gbox.setTitle(cplx.get("uiLabel"))
                for ii, values in enumerate(cplx["defaultValue"]):
                    self.cplx_widget.populateColumn(
                        ii, values, colours=cplx.get("colours"))
                self.cplx_gbox.show()

            else:
                raise NotImplementedError(
                    "GPhL complex widget type %s not recognised for parameter _cplx"
                    % repr(cplx.get("type")))

        # parameters widget
        if self.params_widget is not None:
            self.params_widget.close()
            self.params_widget = None
        if parameters:
            self.params_widget = FieldsWidget(fields=parameters,
                                              parent=self.parameter_gbox)

            values = {}
            for dd0 in field_list:
                name = dd0["variableName"]
                value = dd0.get("defaultValue")
                if value is not None:
                    dd0[name] = value
            self.params_widget.set_values(values)
            self.parameter_gbox.show()
        else:
            self.parameter_gbox.hide()

        self.show()
        self.setEnabled(True)
예제 #5
0
class GphlDataDialog(qt.QDialog):

    def __init__(self, parent = None, name = None, fl = 0):
        qt.QWidget.__init__(self, parent, name, fl)

        # AsyncResult to return values
        self._async_result = None
        
        # Layout
        qt.QVBoxLayout(self)
        main_layout = self.layout()
        main_layout.setSpacing(10)
        main_layout.setMargin(6)
        self.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)

        self.setCaption('GPhL Workflow parameters')

        # Info box
        self.info_gbox = qt.QVGroupBox('Info', self, "info_gbox")
        main_layout.addWidget(self.info_gbox)
        self.info_text = qt.QTextEdit(self.info_gbox, 'info_text')
        self.info_text.setTextFormat(0) # PlainText
        self.info_text.setFont(qt.QFont("Courier"))
        self.info_text.setReadOnly(True)

        # Special parameter box
        self.cplx_gbox = qt.QVGroupBox('Indexing solution', self,
                                         "cplx_gbox")
        main_layout.addWidget(self.cplx_gbox)
        self.cplx_widget = None

        # Parameter box
        self.parameter_gbox = qt.QVGroupBox('Parameters', self,
                                           "parameter_gbox")
        main_layout.addWidget(self.parameter_gbox)
        self.params_widget = None

        # Button bar
        button_layout = qt.QHBoxLayout(None,0,6,"button_layout")
        hspacer = qt.QSpacerItem(1,20,qt.QSizePolicy.Expanding,qt.QSizePolicy.Minimum)
        button_layout.addItem(hspacer)
        self.continue_button = qt.QPushButton('Continue', self,
                                              'continue_button')
        button_layout.addWidget(self.continue_button)
        self.cancel_button = qt.QPushButton('Abort', self, "cancel_button")
        button_layout.addWidget(self.cancel_button)
        main_layout.addLayout(button_layout)

        qt.QObject.connect(self.continue_button, qt.SIGNAL("clicked()"),
                           self.continue_button_click)

        qt.QObject.connect(self.cancel_button, qt.SIGNAL("clicked()"),
                           self.cancel_button_click)

        self.resize(qt.QSize(1018,472).expandedTo(self.minimumSizeHint()))
        self.clearWState(qt.Qt.WState_Polished)

    def continue_button_click(self):
        result = {}
        if self.parameter_gbox.isVisible():
            result.update(self.params_widget.get_parameters_map())
        if self.cplx_gbox.isVisible():
            result['_cplx'] = self.cplx_widget.get_value()
        self.accept()
        self._async_result.set(result)
        self._async_result = None

    def cancel_button_click(self):
        self.reject()
        self.parent.workflow_model.workflow_hwobj.abort("Manual abort")

    def open_dialog(self, field_list, async_result):

        self._async_result = async_result

        # get special parameters
        parameters = []
        info = None
        cplx = None
        for dd in field_list:
            if info is None and dd.get('variableName') == '_info':
                # Info text - goes to info_gbox
                info = dd
            elif cplx is None and dd.get('variableName') == '_cplx':
                # Complex parameter - goes to cplx_gbox
                cplx = dd
            else:
                parameters.append(dd)

        # Info box
        if info is None:
            self.info_text.setText('')
            self.info_gbox.setTitle('Info')
            self.info_gbox.hide()
        else:
            self.info_text.setText(info.get('defaultValue'))
            self.info_gbox.setTitle(info.get('uiLabel'))
            self.info_gbox.show()

        # Complex box
        if self.cplx_widget:
            self.cplx_widget.close()
        if cplx is None:
            self.cplx_gbox.hide()
        else:
            if cplx.get('type') == 'selection_table':
                self.cplx_widget = SelectionTable(self.cplx_gbox, 'cplx_widget',
                                                cplx['header'])
                self.cplx_gbox.setTitle(cplx.get('uiLabel'))
                for ii,values in enumerate(cplx['defaultValue']):
                    self.cplx_widget.populateColumn(ii, values,
                                                    colours=cplx.get('colours'))
                self.cplx_gbox.show()

            else:
                raise NotImplementedError(
                    "GPhL complex widget type %s not recognised for parameter _cplx"
                    % repr(cplx.get('type'))
                )

        # parameters widget
        if self.params_widget is not None:
            self.params_widget.close()
            self.params_widget = None
        if parameters:
            self.params_widget = FieldsWidget(fields=parameters,
                                              parent=self.parameter_gbox)

            values ={}
            for dd in field_list:
                name = dd['variableName']
                value = dd.get('defaultValue')
                if value is not None:
                    dd[name] = value
            self.params_widget.set_values(values)
            self.parameter_gbox.show()
        else:
            self.parameter_gbox.hide()

        self.show()
        self.setEnabled(True)
예제 #6
0
    def open_dialog(self, field_list, async_result):

        self._async_result = async_result

        # get special parameters
        parameters = []
        info = None
        cplx = None
        for dd in field_list:
            if info is None and dd.get('variableName') == '_info':
                # Info text - goes to info_gbox
                info = dd
            elif cplx is None and dd.get('variableName') == '_cplx':
                # Complex parameter - goes to cplx_gbox
                cplx = dd
            else:
                parameters.append(dd)

        # Info box
        if info is None:
            self.info_text.setText('')
            self.info_gbox.setTitle('Info')
            self.info_gbox.hide()
        else:
            self.info_text.setText(info.get('defaultValue'))
            self.info_gbox.setTitle(info.get('uiLabel'))
            self.info_gbox.show()

        # Complex box
        if self.cplx_widget:
            self.cplx_widget.close()
        if cplx is None:
            self.cplx_gbox.hide()
        else:
            if cplx.get('type') == 'selection_table':
                self.cplx_widget = SelectionTable(self.cplx_gbox, 'cplx_widget',
                                                cplx['header'])
                self.cplx_gbox.setTitle(cplx.get('uiLabel'))
                for ii,values in enumerate(cplx['defaultValue']):
                    self.cplx_widget.populateColumn(ii, values,
                                                    colours=cplx.get('colours'))
                self.cplx_gbox.show()

            else:
                raise NotImplementedError(
                    "GPhL complex widget type %s not recognised for parameter _cplx"
                    % repr(cplx.get('type'))
                )

        # parameters widget
        if self.params_widget is not None:
            self.params_widget.close()
            self.params_widget = None
        if parameters:
            self.params_widget = FieldsWidget(fields=parameters,
                                              parent=self.parameter_gbox)

            values ={}
            for dd in field_list:
                name = dd['variableName']
                value = dd.get('defaultValue')
                if value is not None:
                    dd[name] = value
            self.params_widget.set_values(values)
            self.parameter_gbox.show()
        else:
            self.parameter_gbox.hide()

        self.show()
        self.setEnabled(True)
예제 #7
0
    def open_dialog(self, field_list, async_result):

        self._async_result = async_result

        # get special parameters
        parameters = []
        info = None
        cplx = None
        for dd0 in field_list:
            if info is None and dd0.get("variableName") == "_info":
                # Info text - goes to info_gbox
                info = dd0
            elif cplx is None and dd0.get("variableName") == "_cplx":
                # Complex parameter - goes to cplx_gbox
                cplx = dd0
            else:
                parameters.append(dd0)

        # Info box
        if info is None:
            self.info_text.setText("")
            self.info_gbox.setTitle("Info")
            self.info_gbox.hide()
        else:
            self.info_text.setText(info.get("defaultValue"))
            self.info_gbox.setTitle(info.get("uiLabel"))
            self.info_gbox.show()

        # Complex box
        if self.cplx_widget:
            self.cplx_widget.close()
        if cplx is None:
            self.cplx_gbox.hide()
        else:
            if cplx.get("type") == "selection_table":
                self.cplx_widget = SelectionTable(
                    self.cplx_gbox, "cplx_widget", cplx["header"]
                )
                self.cplx_gbox.setTitle(cplx.get("uiLabel"))
                for ii, values in enumerate(cplx["defaultValue"]):
                    self.cplx_widget.populateColumn(
                        ii, values, colours=cplx.get("colours")
                    )
                self.cplx_gbox.show()

            else:
                raise NotImplementedError(
                    "GPhL complex widget type %s not recognised for parameter _cplx"
                    % repr(cplx.get("type"))
                )

        # parameters widget
        if self.params_widget is not None:
            self.params_widget.close()
            self.params_widget = None
        if parameters:
            self.params_widget = FieldsWidget(
                fields=parameters, parent=self.parameter_gbox
            )

            values = {}
            for dd0 in field_list:
                name = dd0["variableName"]
                value = dd0.get("defaultValue")
                if value is not None:
                    dd0[name] = value
            self.params_widget.set_values(values)
            self.parameter_gbox.show()
        else:
            self.parameter_gbox.hide()

        self.show()
        self.setEnabled(True)
예제 #8
0
class EDNAParameters(BlissWidget):
    def __init__(self, *args):
        BlissWidget.__init__(self, *args)

        self.addProperty('mnemonic', 'string', '')
        self.addProperty('edna object', 'string', '')
        self.addProperty('workflows base dir', 'string', '')

        #when starting a workflow we emit this signal and expect
        #to get the beamline params through the slot
        self.defineSlot('updateBeamlineParameters', ())
        self.defineSignal('beamlineParametersNeeded', ())
        self.defineSignal('workflowAvailable', ())

        #we need the session id
        self.defineSlot('login_changed', ())

        self.beamline_params = dict()

        self.session_id = None
        self.params_widget = None
        self.workflow = None
        self.edna = None
        self.previous_workflow_state = None
        self.workflow_output_file = None
        self.process_dir = None
        QGridLayout(self, 4, 2)
        self.workflows_box = QHBoxLayout()
        self.ok_button = QPushButton('Continue', self)
        #self.abort_button = QPushButton('Abort', self)

        self.workflow_list = QComboBox(self)
        self.workflow_list.hide()
        self.start_button = QPushButton('Start', self)
        self.start_button.hide()
        self.workflows_box.addWidget(self.workflow_list)
        self.workflows_box.addWidget(self.start_button)

        self.layout().addMultiCellLayout(self.workflows_box, 0, 0, 0, 1)

        # UGLY DIRTY HACK, (c) Thomas:
        # We want the params and continue to be on the bottom left
        # Make it so the first row takes all space. The row is empty now
        # since someone modified the brick to not display the workflow list anymore
        self.layout().setRowStretch(0, 10)

        #self.info_label = QLabel(self)
        #self.info_label.setSizePolicy(QSizePolicy.MinimumExpanding,
        #                              QSizePolicy.Fixed)

        # Hack to get some space between the parameters and the continue button
        self.layout().addWidget(self.ok_button, 3, 0,
                                Qt.AlignLeft | Qt.AlignBottom)
        # second row is empty but should take at least 10 px
        self.layout().setRowSpacing(2, 10)
        #self.layout().addWidget(self.abort_button, 2, 1)
        #self.layout().addMultiCellWidget(self.info_label, 3, 3, 0, 1)

        QObject.connect(self.ok_button, SIGNAL('clicked()'),
                        self.send_parameters)
        #QObject.connect(self.abort_button, SIGNAL('clicked()'),
        #                self.abort_workflow)
        QObject.connect(self.start_button, SIGNAL('clicked()'),
                        self.start_workflow)
        # name -> model path mapping
        self.workflows = dict()

    def init(self):
        pass

    def setExpertMode(self, expert):
        self.setEnabled(True)
        self.emit(PYSIGNAL('workflowAvailable'), (True, ))
        #self.setEnabled(expert)
        #self.emit(PYSIGNAL('workflowAvailable'), (expert, ))

    def propertyChanged(self, prop, old_val, new_val):
        if prop == 'mnemonic':
            if self.workflow is not None:
                self.disconnect(self.workflow, PYSIGNAL('parametersNeeded'),
                                self.prompt_parameters)
            self.workflow = self.getHardwareObject(new_val)
            if self.workflow is not None:
                #get the state
                state = self.workflow.state.getValue()
                self.workflow_state_changed((state, ))
                self.connect(self.workflow, PYSIGNAL('parametersNeeded'),
                             self.prompt_parameters)
                self.connect(self.workflow, PYSIGNAL('stateChanged'),
                             self.workflow_state_changed)
                #populate the available workflows list
                self.refresh_workflows()
        if prop == 'edna object':
            self.edna = self.getHardwareObject(new_val)
            logging.debug('%r: Edna object is now %s (%r)', self, new_val,
                          self.edna)

    def prompt_parameters(self, xml):
        logging.debug('got back XML from server:\n%s', xml)
        # Edited by Olof 2013/04/16: Temporary fix for handling messages containing
        # XML markup
        #xml_root = etree.fromstring(xml)
        xml_root = etree.fromstring(xml, parser=etree.XMLParser(recover=True))

        # Special case until Olof implements the saner XML format on the server side
        if xml_root.tag == 'message':
            message = dict(type='message', level='info', text='no message')
            for node in xml_root:
                option = node.tag.strip()
                # rename type to level, as type is used for the type
                # this is unfortunate
                if option == 'type':
                    option = 'level'
                message[option] = node.text.strip()
            fields = [message]
        else:
            containers = get_field_containers(xml_root)
            if len(containers) == 0: return
            fields = get_fields(containers[0])
        if self.params_widget is not None:
            self.layout().removeChild(self.params_widget)
        self.params_widget = FieldsWidget(fields, self)

        current_values = self.workflow.get_values_map()
        logging.debug('current values are: %s', current_values)
        self.params_widget.set_values(current_values)
        self.layout().addMultiCellWidget(self.params_widget, 1, 1, 0, 1,
                                         Qt.AlignBottom | Qt.AlignLeft)
        self.params_widget.show()
        self.ok_button.setEnabled(True)

    def send_parameters(self):
        if self.params_widget is not None:
            params_map = self.params_widget.get_parameters_map()
            logging.debug('setting values %r', params_map)
            self.workflow.set_values_map(params_map)
        # Try to change back to sample centering tab
        try:
            tabWidget = self.parent().parent().parent().parent().parent()
            tabWidget.setCurrentPage(0)
        except:
            # We don't care if it doesn't work..
            pass

    def refresh_workflow_state(self, new_state, actor):
        #abort button should never be disabled
        new_state = str(new_state)  #convert from DevState to string
        if self.params_widget is not None:
            self.params_widget.setEnabled(new_state == "OPEN")
        self.ok_button.setEnabled(new_state == "OPEN")

        # only available when engine is idle
        self.start_button.setEnabled(new_state == "ON")
        self.workflow_list.setEnabled(new_state == "ON")

        if new_state == "RUNNING":
            message = 'Workflow engine running'
        elif new_state == "STANDBY":
            message = 'Workflow engine paused'
        elif new_state == "ON":
            self.refresh_workflows()
            message = 'Workflow engine idle'
        elif new_state == "OPEN":
            message = 'Waiting for parameters'
        elif new_state == "None":
            message = 'Workflow engine is offline'
        else:
            message = 'Workflow engine is in a state it should not be in (%r)' % (
                new_state, )
            #self.start_button.setEnabled(new_state == "ON")
            #self.workflow_list.setEnabled(new_state == "ON")
        #self.info_label.setText(message)
        logging.info(message)

    def workflow_state_changed(self, new_state):
        logging.debug('%s: new workflow state is %r', self.name(), new_state)
        if type(new_state) == list or type(new_state) == tuple:
            new_state = str(new_state[0])
        if new_state == "ON" and self.previous_workflow_state == "RUNNING":
            # workflow finished, open the output file and use an EDNACaracterize method to
            # continue the work
            if self.workflow_output_file is not None and os.path.exists(
                    self.workflow_output_file):
                logging.debug('Workflow finished, sending the results to %r',
                              self.edna)
                logging.debug('Workflow file is %s', self.workflow_output_file)
                try:
                    data = XSDataResultMXCuBE.parseFile(
                        self.workflow_output_file)
                    self.edna.readEDNAResults(
                        data.getCharacterisationResult(),
                        self.workflow_output_file,
                        self.beamline_params['directory'],
                        self.beamline_params['prefix'],
                        int(self.beamline_params['run_number']),
                        process_dir=self.process_dir,
                        do_inducedraddam=False)
                    logging.debug('Results sent')
                except:
                    logging.debug('Malformed or empty results file')
            else:
                logging.debug('Workflow finished, no result file')
            # then remove the current widget with the parameters
            if self.params_widget is not None:
                self.layout().removeChild(self.params_widget)
        self.previous_workflow_state = new_state

    def abort_workflow(self):
        if self.workflow is not None:
            self.workflow.abort()

    def refresh_workflows(self):
        # keep the name of the current workflow so we can reselect it
        # by default
        previous_workflow = str(self.workflow_list.currentText())
        previous_workflow_index = None
        self.workflows.clear()
        workflows = self.workflow.get_available_workflows()
        self.workflow_list.clear()
        for (w, i) in zip(workflows, list(range(len(workflows)))):
            path = w['path']
            name = w['name']
            if name == previous_workflow:
                previous_workflow_index = i
            self.workflow_list.insertItem(name)
            self.workflows[name] = w
        if previous_workflow_index is not None:
            self.workflow_list.setCurrentItem(previous_workflow_index)

    def start_workflow(self):
        #get the beamline params
        logging.debug('requesting beamline parameters')
        self.emit(PYSIGNAL('beamlineParametersNeeded'), ())
        name = str(self.workflow_list.currentText())
        params = ['modelpath', self.workflows[name]['path']]
        #blparams = XSDataMXCuBEParameters()
        for k, v in self.beamline_params.items():
            # we'll have to lookup how those are specified someday
            # it's a (bool, string, string) tuple
            if k in [
                    'mad_1_energy', 'mad_2_energy', 'mad_3_energy',
                    'mad_4_energy'
            ]:
                if v[0] is False:
                    param = None
                else:
                    param = v[1]
            elif k == 'sum_images':
                param = v[0]
            elif k == 'inverse_beam':
                param = v[0]
            else:
                param = v
            logging.debug('setting %s to %r', k, param)
            #setattr(blparams, k, param)
            params.append(k)
            params.append(str(param))
        # we also need the session id
        #blparams.sessionId = self.session_id
        #output_dir = self.beamline_params['directory'].replace('RAW_DATA', 'PROCESSED_DATA')
        # we'll need that one later to pass to the edna characterise HO
        #self.process_dir = output_dir
#if not os.path.exists(output_dir):
#    os.makedirs(output_dir)
#(handle, filename) = tempfile.mkstemp(suffix='.xml', prefix='edna_output_', dir=output_dir)
#blparams.output_file = filename

# convert that stuff to xml
#params.append('mxcube_parameters')
#params.append(blparams.marshal())
#self.workflow_output_file = filename
        logging.debug('starting workflow %s with params %r', name, params)
        #self.workflow.start(params)
        return params

    def updateBeamlineParameters(self, params):
        logging.debug('got beamline param update, new values: %r', params)
        self.beamline_params = dict()
        # as XSDataSomethingSomething marshalling routing uses format string
        # BUT does not enforces its arg type, we have to do some type
        # conversion, lest it will explode when we call marshal() on it
        floats = [
            'exposure_time', 'resolution', 'resolution_at_corner', 'x_beam',
            'y_beam', 'beam_size_x', 'beam_size_y', 'overlap', 'osc_start',
            'osc_range', 'kappaStart', 'current_detdistance',
            'current_wavelength', 'phiStart', 'current_energy',
            'current_osc_start'
        ]
        ints = [
            'sessionId', 'blSampleId', 'first_image', 'number_images',
            'run_number', 'number_passes'
        ]
        for k, v in params.items():
            value = v
            if k in floats:
                logging.debug('converting %s (%r) to float', k, v)
                value = float(v)
            if k in ints:
                logging.debug('converting %s (%r) to int', k, v)
                value = int(v)
            self.beamline_params[k] = value

    def login_changed(self, *login_infos):
        logging.debug('user logged in, logins_info: %r', login_infos)
        if len(login_infos) == 1 and login_infos[0] == None:
            self.session_id = None
        else:
            self.session_id = int(login_infos[0])
예제 #9
0
    def open_dialog(self, field_list, async_result):

        self._async_result = async_result

        # get special parameters
        parameters = []
        info = None
        cplx = None
        for dd in field_list:
            if info is None and dd.get('variableName') == '_info':
                # Info text - goes to info_gbox
                info = dd
            elif cplx is None and dd.get('variableName') == '_cplx':
                # Complex parameter - goes to cplx_gbox
                cplx = dd
            else:
                parameters.append(dd)

        # Info box
        if info is None:
            self.info_text.setText('')
            self.info_gbox.setTitle('Info')
            self.info_gbox.hide()
        else:
            self.info_text.setText(info.get('defaultValue'))
            self.info_gbox.setTitle(info.get('uiLabel'))
            self.info_gbox.show()

        # Complex box
        if self.cplx_widget:
            self.cplx_widget.close()
        if cplx is None:
            self.cplx_gbox.hide()
        else:
            if cplx.get('type') == 'selection_table':
                self.cplx_widget = SelectionTable(self.cplx_gbox,
                                                  'cplx_widget',
                                                  cplx['header'])
                self.cplx_gbox.setTitle(cplx.get('uiLabel'))
                for ii, values in enumerate(cplx['defaultValue']):
                    self.cplx_widget.populateColumn(
                        ii, values, colours=cplx.get('colours'))
                self.cplx_gbox.show()

            else:
                raise NotImplementedError(
                    "GPhL complex widget type %s not recognised for parameter _cplx"
                    % repr(cplx.get('type')))

        # parameters widget
        if self.params_widget is not None:
            self.params_widget.close()
            self.params_widget = None
        if parameters:
            self.params_widget = FieldsWidget(fields=parameters,
                                              parent=self.parameter_gbox)

            values = {}
            for dd in field_list:
                name = dd['variableName']
                value = dd.get('defaultValue')
                if value is not None:
                    dd[name] = value
            self.params_widget.set_values(values)
            self.parameter_gbox.show()
        else:
            self.parameter_gbox.hide()

        self.show()
        self.setEnabled(True)
예제 #10
0
class EDNAParameters(BlissWidget):
    def __init__(self, *args):
        BlissWidget.__init__(self, *args)

        self.addProperty("mnemonic", "string", "")
        self.addProperty("edna object", "string", "")
        self.addProperty("workflows base dir", "string", "")

        # when starting a workflow we emit this signal and expect
        # to get the beamline params through the slot
        self.defineSlot("updateBeamlineParameters", ())
        self.defineSignal("beamlineParametersNeeded", ())
        self.defineSignal("workflowAvailable", ())

        # we need the session id
        self.defineSlot("login_changed", ())

        self.beamline_params = dict()

        self.session_id = None
        self.params_widget = None
        self.workflow = None
        self.edna = None
        self.previous_workflow_state = None
        self.workflow_output_file = None
        self.process_dir = None
        QGridLayout(self, 4, 2)
        self.workflows_box = QHBoxLayout()
        self.ok_button = QPushButton("Continue", self)
        # self.abort_button = QPushButton('Abort', self)

        self.workflow_list = QComboBox(self)
        self.workflow_list.hide()
        self.start_button = QPushButton("Start", self)
        self.start_button.hide()
        self.workflows_box.addWidget(self.workflow_list)
        self.workflows_box.addWidget(self.start_button)

        self.layout().addMultiCellLayout(self.workflows_box, 0, 0, 0, 1)

        # UGLY DIRTY HACK, (c) Thomas:
        # We want the params and continue to be on the bottom left
        # Make it so the first row takes all space. The row is empty now
        # since someone modified the brick to not display the workflow list anymore
        self.layout().setRowStretch(0, 10)

        # self.info_label = QLabel(self)
        # self.info_label.setSizePolicy(QSizePolicy.MinimumExpanding,
        #                              QSizePolicy.Fixed)

        # Hack to get some space between the parameters and the continue button
        self.layout().addWidget(self.ok_button, 3, 0, Qt.AlignLeft | Qt.AlignBottom)
        # second row is empty but should take at least 10 px
        self.layout().setRowSpacing(2, 10)
        # self.layout().addWidget(self.abort_button, 2, 1)
        # self.layout().addMultiCellWidget(self.info_label, 3, 3, 0, 1)

        QObject.connect(self.ok_button, SIGNAL("clicked()"), self.send_parameters)
        # QObject.connect(self.abort_button, SIGNAL('clicked()'),
        #                self.abort_workflow)
        QObject.connect(self.start_button, SIGNAL("clicked()"), self.start_workflow)
        # name -> model path mapping
        self.workflows = dict()

    def init(self):
        pass

    def setExpertMode(self, expert):
        self.setEnabled(True)
        self.emit(PYSIGNAL("workflowAvailable"), (True,))
        # self.setEnabled(expert)
        # self.emit(PYSIGNAL('workflowAvailable'), (expert, ))

    def propertyChanged(self, prop, old_val, new_val):
        if prop == "mnemonic":
            if self.workflow is not None:
                self.disconnect(
                    self.workflow, PYSIGNAL("parametersNeeded"), self.prompt_parameters
                )
            self.workflow = self.getHardwareObject(new_val)
            if self.workflow is not None:
                # get the state
                state = self.workflow.state.getValue()
                self.workflow_state_changed((state,))
                self.connect(
                    self.workflow, PYSIGNAL("parametersNeeded"), self.prompt_parameters
                )
                self.connect(
                    self.workflow, PYSIGNAL("stateChanged"), self.workflow_state_changed
                )
                # populate the available workflows list
                self.refresh_workflows()
        if prop == "edna object":
            self.edna = self.getHardwareObject(new_val)
            logging.debug("%r: Edna object is now %s (%r)", self, new_val, self.edna)

    def prompt_parameters(self, xml):
        logging.debug("got back XML from server:\n%s", xml)
        # Edited by Olof 2013/04/16: Temporary fix for handling messages containing
        # XML markup
        # xml_root = etree.fromstring(xml)
        xml_root = etree.fromstring(xml, parser=etree.XMLParser(recover=True))

        # Special case until Olof implements the saner XML format on the server side
        if xml_root.tag == "message":
            message = dict(type="message", level="info", text="no message")
            for node in xml_root:
                option = node.tag.strip()
                # rename type to level, as type is used for the type
                # this is unfortunate
                if option == "type":
                    option = "level"
                message[option] = node.text.strip()
            fields = [message]
        else:
            containers = get_field_containers(xml_root)
            if len(containers) == 0:
                return
            fields = get_fields(containers[0])
        if self.params_widget is not None:
            self.layout().removeChild(self.params_widget)
        self.params_widget = FieldsWidget(fields, self)

        current_values = self.workflow.get_values_map()
        logging.debug("current values are: %s", current_values)
        self.params_widget.set_values(current_values)
        self.layout().addMultiCellWidget(
            self.params_widget, 1, 1, 0, 1, Qt.AlignBottom | Qt.AlignLeft
        )
        self.params_widget.show()
        self.ok_button.setEnabled(True)

    def send_parameters(self):
        if self.params_widget is not None:
            params_map = self.params_widget.get_parameters_map()
            logging.debug("setting values %r", params_map)
            self.workflow.set_values_map(params_map)
        # Try to change back to sample centering tab
        try:
            tabWidget = self.parent().parent().parent().parent().parent()
            tabWidget.setCurrentPage(0)
        except BaseException:
            # We don't care if it doesn't work..
            pass

    def refresh_workflow_state(self, new_state, actor):
        # abort button should never be disabled
        new_state = str(new_state)  # convert from DevState to string
        if self.params_widget is not None:
            self.params_widget.setEnabled(new_state == "OPEN")
        self.ok_button.setEnabled(new_state == "OPEN")

        # only available when engine is idle
        self.start_button.setEnabled(new_state == "ON")
        self.workflow_list.setEnabled(new_state == "ON")

        if new_state == "RUNNING":
            message = "Workflow engine running"
        elif new_state == "STANDBY":
            message = "Workflow engine paused"
        elif new_state == "ON":
            self.refresh_workflows()
            message = "Workflow engine idle"
        elif new_state == "OPEN":
            message = "Waiting for parameters"
        elif new_state == "None":
            message = "Workflow engine is offline"
        else:
            message = "Workflow engine is in a state it should not be in (%r)" % (
                new_state,
            )
            # self.start_button.setEnabled(new_state == "ON")
            # self.workflow_list.setEnabled(new_state == "ON")
        # self.info_label.setText(message)
        logging.info(message)

    def workflow_state_changed(self, new_state):
        logging.debug("%s: new workflow state is %r", self.name(), new_state)
        if isinstance(new_state, types.ListType) or isinstance(
            new_state, types.TupleType
        ):
            new_state = str(new_state[0])
        if new_state == "ON" and self.previous_workflow_state == "RUNNING":
            # workflow finished, open the output file and use an EDNACaracterize method to
            # continue the work
            if self.workflow_output_file is not None and os.path.exists(
                self.workflow_output_file
            ):
                logging.debug("Workflow finished, sending the results to %r", self.edna)
                logging.debug("Workflow file is %s", self.workflow_output_file)
                try:
                    data = XSDataResultMXCuBE.parseFile(self.workflow_output_file)
                    self.edna.readEDNAResults(
                        data.getCharacterisationResult(),
                        self.workflow_output_file,
                        self.beamline_params["directory"],
                        self.beamline_params["prefix"],
                        int(self.beamline_params["run_number"]),
                        process_dir=self.process_dir,
                        do_inducedraddam=False,
                    )
                    logging.debug("Results sent")
                except BaseException:
                    logging.debug("Malformed or empty results file")
            else:
                logging.debug("Workflow finished, no result file")
            # then remove the current widget with the parameters
            if self.params_widget is not None:
                self.layout().removeChild(self.params_widget)
        self.previous_workflow_state = new_state

    def abort_workflow(self):
        if self.workflow is not None:
            self.workflow.abort()

    def refresh_workflows(self):
        # keep the name of the current workflow so we can reselect it
        # by default
        previous_workflow = str(self.workflow_list.currentText())
        previous_workflow_index = None
        self.workflows.clear()
        workflows = self.workflow.get_available_workflows()
        self.workflow_list.clear()
        for (w, i) in zip(workflows, range(len(workflows))):
            path = w["path"]
            name = w["name"]
            if name == previous_workflow:
                previous_workflow_index = i
            self.workflow_list.insertItem(name)
            self.workflows[name] = w
        if previous_workflow_index is not None:
            self.workflow_list.setCurrentItem(previous_workflow_index)

    def start_workflow(self):
        # get the beamline params
        logging.debug("requesting beamline parameters")
        self.emit(PYSIGNAL("beamlineParametersNeeded"), ())
        name = str(self.workflow_list.currentText())
        params = ["modelpath", self.workflows[name]["path"]]
        # blparams = XSDataMXCuBEParameters()
        for k, v in self.beamline_params.iteritems():
            # we'll have to lookup how those are specified someday
            # it's a (bool, string, string) tuple
            if k in ["mad_1_energy", "mad_2_energy", "mad_3_energy", "mad_4_energy"]:
                if v[0] is False:
                    param = None
                else:
                    param = v[1]
            elif k == "sum_images":
                param = v[0]
            elif k == "inverse_beam":
                param = v[0]
            else:
                param = v
            logging.debug("setting %s to %r", k, param)
            # setattr(blparams, k, param)
            params.append(k)
            params.append(str(param))
        # we also need the session id
        # blparams.sessionId = self.session_id
        # output_dir = self.beamline_params['directory'].replace('RAW_DATA', 'PROCESSED_DATA')
        # we'll need that one later to pass to the edna characterise HO
        # self.process_dir = output_dir
        # if not os.path.exists(output_dir):
        #    os.makedirs(output_dir)
        # (handle, filename) = tempfile.mkstemp(suffix='.xml', prefix='edna_output_', dir=output_dir)
        # blparams.output_file = filename

        # convert that stuff to xml
        # params.append('mxcube_parameters')
        # params.append(blparams.marshal())
        # self.workflow_output_file = filename
        logging.debug("starting workflow %s with params %r", name, params)
        # self.workflow.start(params)
        return params

    def updateBeamlineParameters(self, params):
        logging.debug("got beamline param update, new values: %r", params)
        self.beamline_params = dict()
        # as XSDataSomethingSomething marshalling routing uses format string
        # BUT does not enforces its arg type, we have to do some type
        # conversion, lest it will explode when we call marshal() on it
        floats = [
            "exposure_time",
            "resolution",
            "resolution_at_corner",
            "x_beam",
            "y_beam",
            "beam_size_x",
            "beam_size_y",
            "overlap",
            "osc_start",
            "osc_range",
            "kappaStart",
            "current_detdistance",
            "current_wavelength",
            "phiStart",
            "current_energy",
            "current_osc_start",
        ]
        ints = [
            "sessionId",
            "blSampleId",
            "first_image",
            "number_images",
            "run_number",
            "number_passes",
        ]
        for k, v in params.iteritems():
            value = v
            if k in floats:
                logging.debug("converting %s (%r) to float", k, v)
                value = float(v)
            if k in ints:
                logging.debug("converting %s (%r) to int", k, v)
                value = int(v)
            self.beamline_params[k] = value

    def login_changed(self, *login_infos):
        logging.debug("user logged in, logins_info: %r", login_infos)
        if len(login_infos) == 1 and login_infos[0] is None:
            self.session_id = None
        else:
            self.session_id = int(login_infos[0])