Ejemplo n.º 1
0
class PX2MultiCollect(SOLEILMultiCollect):
    def __init__(self, name):

        SOLEILMultiCollect.__init__(self, name, LimaAdscDetector(), TunableEnergy())
        #SOLEILMultiCollect.__init__(self, name, DummyDetector(), TunableEnergy())

    def init(self):

        logging.info("headername is %s" % self.headername )

        self.headerdev     = DeviceProxy( self.headername )
        self.mono1dev      = DeviceProxy( self.mono1name )
        self.det_mt_ts_dev = DeviceProxy( self.detmttsname )
        self.det_mt_tx_dev = DeviceProxy( self.detmttxname )
        self.det_mt_tz_dev = DeviceProxy( self.detmttzname )

        self._detector.prepareHeader = self.prepareHeader
        SOLEILMultiCollect.init(self)
       
    def prepareHeader(self):
        '''Will set up header given the actual values of beamline energy, mono and detector distance'''
        X, Y = self.beamCenter()

        BeamCenterX = str(round(X, 3))
        BeamCenterY = str(round(Y, 3))
        head = self.headerdev.read_attribute('header').value
        head = re.sub('BEAM_CENTER_X=\d\d\d\.\d', 'BEAM_CENTER_X=' + BeamCenterX, head)
        head = re.sub('BEAM_CENTER_Y=\d\d\d\.\d', 'BEAM_CENTER_Y=' + BeamCenterY, head)
        return head

    def beamCenter(self):
        '''Will calculate beam center coordinates'''

        # Useful values
        tz_ref = -6.5     # reference tz position for linear regression
        tx_ref = -17.0    # reference tx position for linear regression
        q = 0.102592  # pixel size in milimeters

        wavelength = self.mono1dev.read_attribute('lambda').value
        distance   = self.det_mt_ts_dev.read_attribute('position').value
        tx         = self.det_mt_tx_dev.read_attribute('position').value
        tz         = self.det_mt_tz_dev.read_attribute('position').value

        zcor = tz - tz_ref
        xcor = tx - tx_ref

        Theta = numpy.matrix([[1.55557116e+03,  1.43720063e+03],
                              [-8.51067454e-02, -1.84118001e-03],
                              [-1.99919592e-01,  3.57937064e+00]])  # values from 16.05.2013

        X = numpy.matrix([1., distance, wavelength])

        Origin = Theta.T * X.T
        Origin = Origin * q

        return Origin[1] + zcor, Origin[0] + xcor
Ejemplo n.º 2
0
    def make_test(self, attr=None):
        """
        Performs a full test of the tango server device
        If the attribute is given - trying to read it as well
        :param attr:
        :return:
        """
        #@TODO : test database
        res = True
        try:
            d = DeviceProxy(self.device)
            self.debug("Device ({}) ping value ({})".format(
                self.device, d.ping()))

            state = d.state()

            if state == DevState.FAULT or state == DevState.UNKNOWN:
                raise DevFailed

            if self.testString(attr):
                v = d.read_attribute(attr)

        except (DevFailed, AttributeError) as e:
            res = False

        return res
Ejemplo n.º 3
0
    def read_attribute(self, attr):
        """
        Reads attribute value, returns none in case of na error
        :param attr:
        :return:
        """
        res = None
        try:
            if not self.test(self.device):
                raise ValueError

            d = DeviceProxy(self.device)
            d.ping()

            self.debug("Device ({}) is online".format(self.device))

            state = d.state()
            value = None

            # read value only if the state is fine
            if state != DevState.FAULT and state != DevState.UNKNOWN:
                try:
                    value = d.read_attribute(attr).value
                except AttributeError:
                    value = None
            self.debug("Attribute value ({}/{}/{})".format(state, attr, value))
            res = (state, value)
        except DevFailed:
            self.error(
                "There is an error with access to the device ({})".format(
                    self.device))
        except ValueError:
            self.error("User has not provided a valid device name")

        return res
Ejemplo n.º 4
0
    def show_device_info(self, device):
        """
        Displays basic device attribute properties (status, state, etc.). It creates
        QWidget with GridLayout.
        """
        #czyszczenie grida
        for i in reversed(range(self.grid.count())):
            self.grid.itemAt(i).widget().setParent(None)

        t = DeviceProxy(device)

        try:
            attr_list = t.get_attribute_list()

            i = 0

            attr_device = [t.read_attribute(j) for j in attr_list]
            attr_device = [x for x in attr_device if x.data_format == PyTango._PyTango.AttrDataFormat.SCALAR]

            for p in self.pos:
                if not attr_device:
                    break
                else:
                    name = attr_device[0].name
                    value = attr_device[0].value
                    del attr_device[0]
                    l = QtGui.QLabel("%s : %s" % (name, value))
                    l.setAlignment(QtCore.Qt.AlignCenter)
                    self.grid.addWidget(l, p[0], p[1])

        except DevFailed:
            ret = QtGui.QMessageBox.warning(self.centralwidget,
                                            "Warning",
                                            '''Retrieving attribute list failed''',
                                            QtGui.QMessageBox.Ok)
Ejemplo n.º 5
0
    def run(self):
        """
        Starts a process
        :return:
        """
        self.debug("Starting a door command ({}, {})".format(
            self.door, self.args))

        info, error, output = "", "", ""

        try:
            # connect to the door, run macro
            d = DeviceProxy(self.door)
            state = d.state()

            d.RunMacro(self.args)

            state = d.state()
            while (True):
                time.sleep(0.2)
                if state == DevState.ON or state == DevState.ALARM:
                    break
                state = d.state()

            output = d.read_attribute("output").value
            info = d.read_attribute("info").value
            error = d.read_attribute("error").value
        except (DevFailed, AttributeError) as e:
            output = "Door connection error ({})".format(self.door)
            self.error(output)

        self.debug(
            "Received information from the door \nOutput: {}\nInfo: {}\nError: {}"
            .format(output, info, error))

        if output is None:
            output = []
        if info is None:
            info = []
        if error is None:
            error = []

        if self.bresponse:
            self.emitter.emitSignal(output, info, error)
Ejemplo n.º 6
0
def read_attribute(attribute):
    if app.testing:
        print("in read_attribute")
    try:
        p = DeviceProxy("sys/tg_test/1")
        redAttribute = p.read_attribute(attribute)
        response = parseAttribute(redAttribute)
        return jsonify(response)
    except (CommunicationFailed, ConnectionFailed, DevFailed) as e:
        return jsonify(handleException(e))
Ejemplo n.º 7
0
def read_attribute(attribute):
    if app.testing:
        Log("in read_attribute", 'd')
    try:
        global disable_Pytango
        if disable_Pytango:
            p = DeviceProxy("sys/tg_test/1")
            redAttribute = p.read_attribute(attribute)
            response = parseAttribute(redAttribute)
        else:
            response = ""
        return jsonify(response)
    except (CommunicationFailed, ConnectionFailed, DevFailed) as e:
        return jsonify(handleException(e))
Ejemplo n.º 8
0
def runTest():
    p = DeviceProxy("sys/tg_test/1")
    list = p.get_attribute_list()
    v = []i
    types = []
    result = {}
    atts = []
    for a in list:
        try :
            att = p.read_attribute(a)
            t = type(att.value)
            atts.append(att)
            v.append({'name' : a , 'type' : t})
            types.append(t)
        except:
            v.append({'name' : a , 'type' : 'error'})
    result['types'] = types
    result['att_to_types'] = v
    result['atts'] = atts
    result[]
    return result
Ejemplo n.º 9
0
class CatsMaint(Equipment):

    __TYPE__ = "CATS"
    NO_OF_LIDS = 3

    """
    Actual implementation of the CATS Sample Changer, MAINTENANCE COMMANDS ONLY
    BESSY BL14.1 installation with 3 lids
    """

    def __init__(self, *args, **kwargs):
        Equipment.__init__(self, *args, **kwargs)

        self._state = None
        self._running = None
        self._powered = None
        self._toolopen = None
        self._message = None
        self._regulating = None
        self._lid1state = None
        self._lid2state = None
        self._lid3state = None
        self._charging = None

    def init(self):

        self.cats_device = DeviceProxy(self.tangoname)

        try:
            self.cats_model = self.cats_device.read_attribute("CatsModel").value
        except BaseException:
            self.cats_model = "CATS"

        if self.is_isara():
            self.nb_of_lids = 1
        else:
            self.nb_of_lids = 3

        self._chnState = self.addChannel(
            {
                "type": "tango",
                "name": "_chnState",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "State",
        )

        self._chnPathRunning = self.addChannel(
            {
                "type": "tango",
                "name": "_chnPathRunning",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "PathRunning",
        )
        self._chnPowered = self.addChannel(
            {
                "type": "tango",
                "name": "_chnPowered",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "Powered",
        )
        self._chnMessage = self.addChannel(
            {
                "type": "tango",
                "name": "_chnMessage",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "Message",
        )
        self._chnToolOpenClose = self.addChannel(
            {
                "type": "tango",
                "name": "_chnToolOpenClose",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "di_ToolOpen",
        )
        self._chnLN2Regulation = self.addChannel(
            {
                "type": "tango",
                "name": "_chnLN2Regulation",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "LN2Regulating",
        )
        self._chnBarcode = self.addChannel(
            {
                "type": "tango",
                "name": "_chnBarcode",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "Barcode",
        )

        self._chnLid1State = self.addChannel(
            {
                "type": "tango",
                "name": "_chnLid1State",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "di_Lid1Open",
        )
        self._chnLid1State.connectSignal("update", self._updateLid1State)

        if self.nb_of_lids > 1:
            self._chnLid2State = self.addChannel(
                {
                    "type": "tango",
                    "name": "_chnLid2State",
                    "tangoname": self.tangoname,
                    "polling": 1000,
                },
                "di_Lid2Open",
            )
            self._chnLid2State.connectSignal("update", self._updateLid2State)

        if self.nb_of_lids > 2:
            self._chnLid3State = self.addChannel(
                {
                    "type": "tango",
                    "name": "_chnLid3State",
                    "tangoname": self.tangoname,
                    "polling": 1000,
                },
                "di_Lid3Open",
            )
            self._chnLid3State.connectSignal("update", self._updateLid3State)

        self._chnState.connectSignal("update", self._updateState)
        self._chnPathRunning.connectSignal("update", self._updateRunningState)
        self._chnPowered.connectSignal("update", self._updatePoweredState)
        self._chnToolOpenClose.connectSignal("update", self._updateToolState)
        self._chnMessage.connectSignal("update", self._updateMessage)
        self._chnLN2Regulation.connectSignal("update", self._updateRegulationState)
        self._chnBarcode.connectSignal("update", self._updateBarcode)

        self._chnCurrentTool = self.addChannel(
            {"type": "tango", "name": "_chnCurrentTool", "tangoname": self.tangoname},
            "Tool",
        )
        #
        self._cmdPowerOn = self.addCommand(
            {"type": "tango", "name": "_cmdPowerOn", "tangoname": self.tangoname},
            "powerOn",
        )
        self._cmdPowerOff = self.addCommand(
            {"type": "tango", "name": "_cmdPowerOff", "tangoname": self.tangoname},
            "powerOff",
        )
        self._cmdOpenTool = self.addCommand(
            {"type": "tango", "name": "_cmdOpenTool", "tangoname": self.tangoname},
            "opentool",
        )
        self._cmdCloseTool = self.addCommand(
            {"type": "tango", "name": "_cmdCloseTool", "tangoname": self.tangoname},
            "closetool",
        )
        self._cmdMagnetOn = self.addCommand(
            {"type": "tango", "name": "_cmdMagnetOn", "tangoname": self.tangoname},
            "magnetOn",
        )
        self._cmdMagnetOff = self.addCommand(
            {"type": "tango", "name": "_cmdMagnetOff", "tangoname": self.tangoname},
            "magnetOff",
        )

        # LIDs
        self._cmdOpenLid1 = self.addCommand(
            {"type": "tango", "name": "_cmdOpenLid1", "tangoname": self.tangoname},
            "openlid1",
        )
        self._cmdCloseLid1 = self.addCommand(
            {"type": "tango", "name": "_cmdCloseLid1", "tangoname": self.tangoname},
            "closelid1",
        )

        if self.nb_of_lids > 1:
            self._cmdOpenLid2 = self.addCommand(
                {"type": "tango", "name": "_cmdOpenLid1", "tangoname": self.tangoname},
                "openlid2",
            )
            self._cmdCloseLid2 = self.addCommand(
                {"type": "tango", "name": "_cmdCloseLid1", "tangoname": self.tangoname},
                "closelid2",
            )

        if self.nb_of_lids > 2:
            self._cmdOpenLid3 = self.addCommand(
                {"type": "tango", "name": "_cmdOpenLid1", "tangoname": self.tangoname},
                "openlid3",
            )
            self._cmdCloseLid3 = self.addCommand(
                {"type": "tango", "name": "_cmdCloseLid1", "tangoname": self.tangoname},
                "closelid3",
            )

        self._cmdRegulOn = self.addCommand(
            {"type": "tango", "name": "_cmdRegulOn", "tangoname": self.tangoname},
            "regulon",
        )
        self._cmdRegulOff = self.addCommand(
            {"type": "tango", "name": "_cmdRegulOff", "tangoname": self.tangoname},
            "reguloff",
        )

        self._cmdToolOpen = self.addCommand(
            {"type": "tango", "name": "_cmdToolOpen", "tangoname": self.tangoname},
            "opentool",
        )
        self._cmdToolClose = self.addCommand(
            {"type": "tango", "name": "_cmdToolClose", "tangoname": self.tangoname},
            "closetool",
        )

        # Paths
        self._cmdAbort = self.addCommand(
            {"type": "tango", "name": "_cmdAbort", "tangoname": self.tangoname}, "abort"
        )
        self._cmdDry = self.addCommand(
            {"type": "tango", "name": "_cmdDry", "tangoname": self.tangoname}, "dry"
        )
        self._cmdSafe = self.addCommand(
            {"type": "tango", "name": "_cmdSafe", "tangoname": self.tangoname}, "safe"
        )
        self._cmdHome = self.addCommand(
            {"type": "tango", "name": "_cmdHome", "tangoname": self.tangoname}, "home"
        )
        self._cmdSoak = self.addCommand(
            {"type": "tango", "name": "_cmdSoak", "tangoname": self.tangoname}, "soak"
        )
        self._cmdBack = self.addCommand(
            {"type": "tango", "name": "_cmdBack", "tangoname": self.tangoname}, "back"
        )
        self._cmdCalibration = self.addCommand(
            {"type": "tango", "name": "_cmdCalibration", "tangoname": self.tangoname},
            "toolcalibration",
        )

        self._cmdClearMemory = self.addCommand(
            {"type": "tango", "name": "_cmdClearMemory", "tangoname": self.tangoname},
            "clear_memory",
        )
        self._cmdReset = self.addCommand(
            {"type": "tango", "name": "_cmdReset", "tangoname": self.tangoname}, "reset"
        )
        self._cmdResetParameters = self.addCommand(
            {
                "type": "tango",
                "name": "_cmdResetParameters",
                "tangoname": self.tangoname,
            },
            "reset_parameters",
        )

        self._cmdRecoverFailure = self.addCommand(
            {
                "type": "tango",
                "name": "_cmdRecoverFailure",
                "tangoname": self.tangoname,
            },
            "recoverFailure",
        )

        self._cmdResetMotion = self.addCommand(
            {"type": "tango", "name": "_cmdResetMotion", "tangoname": self.tangoname},
            "resetmotion",
        )

        self._cmdSetOnDiff = self.addCommand(
            {"type": "tango", "name": "_cmdSetOnDiff", "tangoname": self.tangoname},
            "setondiff",
        )
        self._cmdSetOnTool = self.addCommand(
            {"type": "tango", "name": "_cmdSetOnTool", "tangoname": self.tangoname},
            "settool",
        )
        self._cmdSetOnTool2 = self.addCommand(
            {"type": "tango", "name": "_cmdSetOnTool2", "tangoname": self.tangoname},
            "settool2",
        )

        self.state_actions = {
            "power": {
                "in_open": self._cmdPowerOn,
                "out_close": self._cmdPowerOff,
                "state": self._chnPowered,
            }
        }

    def is_isara(self):
        return self.cats_model == "ISARA"

    def is_cats(self):
        return self.cats_model != "ISARA"

    def get_current_tool(self):
        current_value = self._chnCurrentTool.getValue()

        tool = TOOL_TO_STR.get(current_value, None)

        return tool

    ################################################################################

    def backTraj(self):
        """
        Moves a sample from the gripper back into the dewar to its logged position.
        """
        return self._executeTask(False, self._doBack)

    def safeTraj(self):
        """
        Safely Moves the robot arm and the gripper to the home position
        """
        return self._executeTask(False, self._doSafe)

    def _doAbort(self):
        """
        Launch the "abort" trajectory on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdAbort()

    def _doHome(self):
        """
        Launch the "abort" trajectory on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        tool = self.get_current_tool()
        self._cmdHome(tool)

    def _doReset(self):
        """
        Launch the "reset" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        logging.getLogger("HWR").debug("CatsMaint. doing reset")
        return
        self._cmdReset()

    def _doResetMemory(self):
        """
        Launch the "reset memory" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdClearMemory()
        time.sleep(1)
        self._cmdResetParameters()
        time.sleep(1)

    def _doResetMotion(self):
        """
        Launch the "reset_motion" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdResetMotion()

    def _doRecoverFailure(self):
        """
        Launch the "recoverFailure" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdRecoverFailure()

    def _doCalibration(self):
        """
        Launch the "toolcalibration" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        tool = self.get_current_tool()
        self._cmdCalibration(tool)

    def _doOpenTool(self):
        """
        Launch the "opentool" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdOpenTool()

    def _doCloseTool(self):
        """
        Launch the "closetool" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdCloseTool()

    def _doDryGripper(self):
        """
        Launch the "dry" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        tool = self.get_current_tool()
        self._cmdDry(tool)

    def _doSetOnDiff(self, sample):
        """
        Launch the "setondiff" command on the CATS Tango DS, an example of sample value is 2:05

        :returns: None
        :rtype: None
        """

        if sample is None:
            raise Exception("No sample selected")
        else:
            str_tmp = str(sample)
            sample_tmp = str_tmp.split(":")
            # calculate CATS specific lid/sample number
            lid = (int(sample_tmp[0]) - 1) / 3 + 1
            puc_pos = ((int(sample_tmp[0]) - 1) % 3) * 10 + int(sample_tmp[1])
            argin = [str(lid), str(puc_pos), "0"]
            logging.getLogger().info("to SetOnDiff %s", argin)
            self._executeServerTask(self._cmdSetOnDiff, argin)

    def _doBack(self):
        """
        Launch the "back" trajectory on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        tool = self.get_current_tool()
        argin = [str(tool), "0"]  # to send string array with two arg...
        self._executeServerTask(self._cmdBack, argin)

    def _doSafe(self):
        """
        Launch the "safe" trajectory on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        argin = self.get_current_tool()
        self._executeServerTask(self._cmdSafe, argin)

    def _doPowerState(self, state=False):
        """
        Switch on CATS power if >state< == True, power off otherwise

        :returns: None
        :rtype: None
        """
        logging.getLogger("HWR").debug("   running power state command ")
        if state:
            self._cmdPowerOn()
        else:
            self._cmdPowerOff()

        self.do_state_action("power", state)

    def _doEnableRegulation(self):
        """
        Switch on CATS regulation

        :returns: None
        :rtype: None
        """
        self._cmdRegulOn()

    def _doDisableRegulation(self):
        """
        Switch off CATS regulation

        :returns: None
        :rtype: None
        """
        self._cmdRegulOff()

    def _doLid1State(self, state=True):
        """
        Opens lid 1 if >state< == True, closes the lid otherwise

        :returns: None
        :rtype: None
        """
        if state:
            self._executeServerTask(self._cmdOpenLid1)
        else:
            self._executeServerTask(self._cmdCloseLid1)

    def _doLid2State(self, state=True):
        """
        Opens lid 2 if >state< == True, closes the lid otherwise

        :returns: None
        :rtype: None
        """
        if state:
            self._executeServerTask(self._cmdOpenLid2)
        else:
            self._executeServerTask(self._cmdCloseLid2)

    def _doLid3State(self, state=True):
        """
        Opens lid 3 if >state< == True, closes the lid otherwise

        :returns: None
        :rtype: None
        """
        if state:
            self._executeServerTask(self._cmdOpenLid3)
        else:
            self._executeServerTask(self._cmdCloseLid3)

    def _doMagnetOn(self):
        self._executeServerTask(self._cmdMagnetOn)

    def _doMagnetOff(self):
        self._executeServerTask(self._cmdMagnetOff)

    def _doToolOpen(self):
        self._executeServerTask(self._cmdToolOpen)

    def _doToolClose(self):
        self._executeServerTask(self._cmdToolClose)

    # ########################          PROTECTED          #########################

    def _executeTask(self, wait, method, *args):
        ret = self._run(method, wait=False, *args)
        if wait:
            return ret.get()
        else:
            return ret

    @task
    def _run(self, method, *args):
        exception = None
        ret = None
        try:
            ret = method(*args)
        except Exception as ex:
            exception = ex
        if exception is not None:
            raise exception
        return ret

    # ########################           PRIVATE           #########################

    def _updateRunningState(self, value):
        self._running = value
        self.emit("runningStateChanged", (value,))
        self._updateGlobalState()

    def _updatePoweredState(self, value):
        self._powered = value
        self.emit("powerStateChanged", (value,))
        self._updateGlobalState()

    def _updateToolState(self, value):
        self._toolopen = value
        self.emit("toolStateChanged", (value,))
        self._updateGlobalState()

    def _updateMessage(self, value):
        self._message = value
        self.emit("messageChanged", (value,))
        self._updateGlobalState()

    def _updateRegulationState(self, value):
        self._regulating = value
        self.emit("regulationStateChanged", (value,))
        self._updateGlobalState()

    def _updateBarcode(self, value):
        self._barcode = value
        self.emit("barcodeChanged", (value,))

    def _updateState(self, value):
        self._state = value
        self._updateGlobalState()

    def _updateLid1State(self, value):
        self._lid1state = value
        self.emit("lid1StateChanged", (value,))
        self._updateGlobalState()

    def _updateLid2State(self, value):
        self._lid2state = value
        self.emit("lid2StateChanged", (value,))
        self._updateGlobalState()

    def _updateLid3State(self, value):
        self._lid3state = value
        self.emit("lid3StateChanged", (value,))
        self._updateGlobalState()

    def _updateOperationMode(self, value):
        self._charging = not value

    def _updateGlobalState(self):
        state_dict, cmd_state, message = self.get_global_state()
        self.emit("globalStateChanged", (state_dict, cmd_state, message))

    def get_global_state(self):
        """
           Update clients with a global state that
           contains different:

           - first param (state_dict):
               collection of state bits

           - second param (cmd_state):
               list of command identifiers and the
               status of each of them True/False
               representing whether the command is
               currently available or not

           - message
               a message describing current state information
               as a string
        """
        _ready = str(self._state) in ("READY", "ON")

        if self._running:
            state_str = "MOVING"
        elif not (self._powered) and _ready:
            state_str = "DISABLED"
        elif _ready:
            state_str = "READY"
        else:
            state_str = str(self._state)

        state_dict = {
            "toolopen": self._toolopen,
            "powered": self._powered,
            "running": self._running,
            "regulating": self._regulating,
            "lid1": self._lid1state,
            "lid2": self._lid2state,
            "lid3": self._lid3state,
            "state": state_str,
        }

        cmd_state = {
            "powerOn": (not self._powered) and _ready,
            "powerOff": (self._powered) and _ready,
            "regulon": (not self._regulating) and _ready,
            "openlid1": (not self._lid1state) and self._powered and _ready,
            "closelid1": self._lid1state and self._powered and _ready,
            "dry": (not self._running) and self._powered and _ready,
            "soak": (not self._running) and self._powered and _ready,
            "home": (not self._running) and self._powered and _ready,
            "back": (not self._running) and self._powered and _ready,
            "safe": (not self._running) and self._powered and _ready,
            "clear_memory": True,
            "reset": True,
            "abort": True,
        }

        message = self._message

        return state_dict, cmd_state, message

    def get_cmd_info(self):
        """ return information about existing commands for this object
           the information is organized as a list
           with each element contains
           [ cmd_name,  display_name, category ]
        """
        """ [cmd_id, cmd_display_name, nb_args, cmd_category, description ] """
        cmd_list = [
            [
                "Power",
                [
                    ["powerOn", "PowerOn", "Switch Power On"],
                    ["powerOff", "PowerOff", "Switch Power Off"],
                    ["regulon", "Regulation On", "Swich LN2 Regulation On"],
                ],
            ],
            [
                "Lid",
                [
                    ["openlid1", "Open Lid", "Open Lid"],
                    ["closelid1", "Close Lid", "Close Lid"],
                ],
            ],
            [
                "Actions",
                [
                    ["home", "Home", "Actions", "Home (trajectory)"],
                    ["dry", "Dry", "Actions", "Dry (trajectory)"],
                    ["soak", "Soak", "Actions", "Soak (trajectory)"],
                ],
            ],
            [
                "Recovery",
                [
                    [
                        "clear_memory",
                        "Clear Memory",
                        "Clear Info in Robot Memory "
                        " (includes info about sample on Diffr)",
                    ],
                    ["reset", "Reset Message", "Reset Cats State"],
                    ["back", "Back", "Reset Cats State"],
                    ["safe", "Safe", "Reset Cats State"],
                ],
            ],
            ["Abort", [["abort", "Abort", "Abort Execution of Command"]]],
        ]
        return cmd_list

    def _executeServerTask(self, method, *args):
        task_id = method(*args)
        ret = None
        # introduced wait because it takes some time before the attribute PathRunning is set
        # after launching a transfer
        # after setting refresh in the Tango DS to 0.1 s a wait of 1s is enough
        time.sleep(1.0)
        while str(self._chnPathRunning.getValue()).lower() == "true":
            gevent.sleep(0.1)
        ret = True
        return ret

    def send_command(self, cmdname, args=None):

        #
        lid = 1
        toolcal = 0
        tool = self.get_current_tool()

        if cmdname in ["dry", "safe", "home"]:
            if tool is not None:
                args = [tool]
            else:
                raise Exception("Cannot detect type of TOOL in Cats. Command ignored")

        if cmdname == "soak":
            if tool in [TOOL_DOUBLE, TOOL_UNIPUCK]:
                args = [str(tool), str(lid)]
            else:
                raise Exception("Can SOAK only when UNIPUCK tool is mounted")

        if cmdname == "back":
            if tool is not None:
                args = [tool, toolcal]
            else:
                raise Exception("Cannot detect type of TOOL in Cats. Command ignored")

        cmd = getattr(self.cats_device, cmdname)

        try:
            if args is not None:
                if len(args) > 1:
                    ret = cmd(map(str, args))
                else:
                    ret = cmd(*args)
            else:
                ret = cmd()
            return ret
        except Exception as exc:
            import traceback

            traceback.print_exc()
            msg = exc[0].desc
            raise Exception(msg)
Ejemplo n.º 10
0
class PX2MultiCollect(SOLEILMultiCollect):
    def __init__(self, name):

        SOLEILMultiCollect.__init__(self, name, LimaAdscDetector(), TunableEnergy())
        #SOLEILMultiCollect.__init__(self, name, DummyDetector(), TunableEnergy())
        self.motors = ['sampx', 'sampy', 'phiz', 'phiy']
        
    def init(self):

        logging.info("headername is %s" % self.headername )

        self.headerdev     = DeviceProxy( self.headername )
        self.mono1dev      = DeviceProxy( self.mono1name )
        self.det_mt_ts_dev = DeviceProxy( self.detmttsname )
        self.det_mt_tx_dev = DeviceProxy( self.detmttxname )
        self.det_mt_tz_dev = DeviceProxy( self.detmttzname )
        
        self.helical = False
        self.linear = False
        self.grid = False
        self.translational = False
        
        self._detector.prepareHeader = self.prepareHeader
        SOLEILMultiCollect.init(self)
       
    def prepareHeader(self):
        '''Will set up header given the actual values of beamline energy, mono and detector distance'''
        X, Y = self.beamCenter()

        BeamCenterX = str(round(X, 3))
        BeamCenterY = str(round(Y, 3))
        head = self.headerdev.read_attribute('header').value
        head = re.sub('BEAM_CENTER_X=\d\d\d\.\d', 'BEAM_CENTER_X=' + BeamCenterX, head)
        head = re.sub('BEAM_CENTER_Y=\d\d\d\.\d', 'BEAM_CENTER_Y=' + BeamCenterY, head)
        return head

    def beamCenter(self):
        '''Will calculate beam center coordinates'''

        # Useful values
        tz_ref = -6.5     # reference tz position for linear regression
        tx_ref = -17.0    # reference tx position for linear regression
        q = 0.102592  # pixel size in milimeters

        wavelength = self.mono1dev.read_attribute('lambda').value
        distance   = self.det_mt_ts_dev.read_attribute('position').value
        tx         = self.det_mt_tx_dev.read_attribute('position').value
        tz         = self.det_mt_tz_dev.read_attribute('position').value

        zcor = tz - tz_ref
        xcor = tx - tx_ref

        Theta = numpy.matrix([[1.55557116e+03,  1.43720063e+03],
                              [-8.51067454e-02, -1.84118001e-03],
                              [-1.99919592e-01,  3.57937064e+00]])  # values from 16.05.2013

        X = numpy.matrix([1., distance, wavelength])

        Origin = Theta.T * X.T
        Origin = Origin * q

        return Origin[1] + zcor, Origin[0] + xcor
        
    def set_helical(self, onmode, positions=None):
        logging.info("<PX2 MultiCollect> set helical")
        self.helical = onmode
        logging.info("<PX2 MultiCollect> set helical pos1 %s pos2 %s" % (positions['1'], positions['2']))
        self.helicalStart = positions['1']
        self.helicalFinal = positions['2']
        
    def set_translational(self, onmode, positions=None, step=None):
        logging.info("<PX2 MultiCollect> set translational")
        self.translational = onmode
        self.translationalStart = positions['1']
        self.translationalFinal = positions['2']
        if step is not None:
            self.translationalStep = step
        
    def set_linear(self, onmode, positions=None, step=None):
        logging.info("<PX2 MultiCollect> set linear")
        self.linear = onmode
        self.linearStart = positions['1']
        self.linearFinal = positions['2']
        if step is not None:
            self.linearStep = step
        
    def set_grid(self, onmode, positions=None):
        logging.info("<PX2 MultiCollect> set grid")
        

    def calculateLinearCollectPosition(self, n, start, final, nPositions):
        '''Calculate the n th position out of the total number of equidistant positions between start and final. '''
        displacements = {}
        for motor in self.motors:
            displacements[motor] = final[motor] - start[motor]
        
        position = {}
        for motor in self.motors:
            position[motor] = start[motor] + displacements[motor] * float(n)/(nPositions-1)
            
        return position
    
    def getPoints(self, start, final, nbSteps):
        logging.info("<PX2 MultiCollect> getPoints start %s, final %s" % (start, final))
        step = 1./ (nbSteps - 1)
        points = numpy.arange(0., 1.+(0.5*step), step)
        Positions = {}
        positions = []
        for motor in self.motors:
            scanRange = final[motor] - start[motor]
            Positions[motor] = start[motor] + points * scanRange
            positions.append(Positions[motor])
            
        positions = numpy.array(positions)
        return [dict(zip(self.motors, p)) for p in positions.T]
    
    def calculateHelicalCollectPositions(self, start, final, nImages):
        positions = self.getPoints(start, final, nImages)
        return positions

    def calculateTranslationalCollectPositions(self, start, final, nImages):
        '''take into account the beam size and spread the positions optimally between start and final positions.'''
        positions = []
        horizontal_beam_size = self.get_horizontal_beam_size()
        totalHorizontalDistance = abs(final['phiy'] - start['phiy'])
        freeHorizontalSpace = totalHorizontalDistance - horizontal_beam_size
        # Due to our rotational axis being horizontal we take the horizontal beam size as the basic step size
        nPositions = int(freeHorizontalSpace // horizontal_beam_size) + 2
        nImagesPerPosition, remainder = divmod(nImages, nPositions)
        
        positions = self.getPoints(start, final, nPositions)
        #positions = [self.calculateLinearCollectPosition(n, start, final, nPositions) for n in range(nPositions)]
        explicit_positions = []
        k = 0
        for p in positions:
            k += 1
            to_add = [p] * (nImagesPerPosition)
            if k <= remainder:
                to_add += [p]
            explicit_positions += to_add
        return explicit_positions
        
    def getCollectPositions(self, nImages):
        logging.info("<PX2 MultiCollect> get collect positions")
        logging.info("getCollectPositions nImages %s" % nImages)
        positions = []
        if self.helical:
            start, final = self.helicalStart, self.helicalFinal
            positions = self.calculateHelicalCollectPositions(start, final, nImages)
        elif self.linear:
            start, final = self.linearStart, self.linearFinal
            positions = self.getPoints(start, final, nImages)
        elif self.translational:
            start, final = self.translationalStart, self.translationalFinal
            positions = self.calculateTranslationalCollectPositions(start, final, nImages)
        elif self.grid:
            positions = self.calculateGridPositions(self.grid_start, self.grid_nbsteps, self.grid_lengths)
        else:
            positions = [{} for k in range(nImages)]
        return positions
        
    def newWedge(self, imageNums, ScanStartAngle, template, positions):
        return {'imageNumbers': imageNums, 
                'startAtAngle': ScanStartAngle, 
                'template': template, 
                'positions': positions}
    
    def prepareWedges(self, firstImage, 
                            nbFrames, 
                            ScanStartAngle, 
                            ScanRange, 
                            wedgeSize, 
                            inverse, 
                            ScanOverlap, 
                            template):
        '''Based on collect parameters will prepare all the wedges to be collected.'''
        logging.info('Preparing wedges')
        wedges = []
        
        imageNums = range(firstImage, nbFrames + firstImage)
        positions = self.getCollectPositions(nbFrames)
        
        wedges = self.newWedge(imageNums, ScanStartAngle, template, positions)
        if inverse is True:
            inv_wedge = self.newWedge(imageNums, ScanStartAngle, template_inv, positions)
            wedgeSize = int(reference_interval)
            numberOfFullWedges, lastWedgeSize = divmod(nbFrames, wedgeSize)
            for k in range(0, numberOfFullWedges):
                start = k * numberOfFullWedges
                stop = (k+1) * numberOfFullWedges
                wedges.append(wedge[start: stop] + inv_wedge[start: stop])
            wedges.append(wedge[stop:] + inv_wedge[stop:])
        print 'Wedges to collect:'
        print wedges
        logging.info('Wedges to collect %s' % wedges)
        return wedges
           

    @task
    def do_collect(self, owner, data_collect_parameters, in_multicollect=False):
        # reset collection id on each data collect
        logging.info("<SOLEIL do_collect>  data_collect_parameters %s" % data_collect_parameters)
        self.collection_id = None

        # Preparing directory path for images and processing files
        # creating image file template and jpegs files templates
        file_parameters = data_collect_parameters["fileinfo"]

        file_parameters["suffix"] = self.bl_config.detector_fileext
        image_file_template = "%(prefix)s_%(run_number)s_%%04d.%(suffix)s" % file_parameters
        file_parameters["template"] = image_file_template

        archive_directory = self.get_archive_directory(file_parameters["directory"])
        data_collect_parameters["archive_dir"] = archive_directory

        if archive_directory:
            jpeg_filename="%s.jpeg" % os.path.splitext(image_file_template)[0]
            thumb_filename="%s.thumb.jpeg" % os.path.splitext(image_file_template)[0]
            jpeg_file_template = os.path.join(archive_directory, jpeg_filename)
            jpeg_thumbnail_file_template = os.path.join(archive_directory, thumb_filename)
        else:
            jpeg_file_template = None
            jpeg_thumbnail_file_template = None
        # database filling
        logging.info("<AbstractMultiCollect> - LIMS is %s" % str(self.bl_control.lims))
        if self.bl_control.lims:
            data_collect_parameters["collection_start_time"] = time.strftime("%Y-%m-%d %H:%M:%S")
            if self.bl_control.machine_current is not None:
                data_collect_parameters["synchrotronMode"] = self.get_machine_fill_mode()
            data_collect_parameters["status"] = "failed"

            (self.collection_id, detector_id) = \
                                 self.bl_control.lims.store_data_collection(data_collect_parameters, self.bl_config)
              
            data_collect_parameters['collection_id'] = self.collection_id

            if detector_id:
                data_collect_parameters['detector_id'] = detector_id
              
        # Creating the directory for images and processing information
        self.create_directories(file_parameters['directory'],  file_parameters['process_directory'])
        self.xds_directory, self.mosflm_directory = self.prepare_input_files(file_parameters["directory"], file_parameters["prefix"], file_parameters["run_number"], file_parameters['process_directory'])
        data_collect_parameters['xds_dir'] = self.xds_directory

        sample_id, sample_location, sample_code = self.get_sample_info_from_parameters(data_collect_parameters)
        data_collect_parameters['blSampleId'] = sample_id

        if self.bl_control.sample_changer is not None:
            data_collect_parameters["actualSampleBarcode"] = \
                self.bl_control.sample_changer.getLoadedSampleDataMatrix()
            data_collect_parameters["actualContainerBarcode"] = \
                self.bl_control.sample_changer.currentBasketDataMatrix

            basket, vial = (self.bl_control.sample_changer.currentBasket,
                        self.bl_control.sample_changer.currentSample)

            data_collect_parameters["actualSampleSlotInContainer"] = vial
            data_collect_parameters["actualContainerSlotInSC"] = basket

        else:
            data_collect_parameters["actualSampleBarcode"] = None
            data_collect_parameters["actualContainerBarcode"] = None

        try:
            # why .get() is not working as expected?
            # got KeyError anyway!
            if data_collect_parameters["take_snapshots"]:
              self.take_crystal_snapshots()
        except KeyError:
            pass

        centring_info = {}
        try:
            centring_status = self.diffractometer().getCentringStatus()
        except:
            pass
        else:
            centring_info = dict(centring_status)

        #Save sample centring positions
        motors = centring_info.get("motors", {})
        logging.info('do_collect motors %s' % motors)
        extra_motors = centring_info.get("extraMotors", {})

        positions_str = ""

        motors_to_move_before_collect = data_collect_parameters.setdefault("motors", {})
        
        for motor in motors:
          positions_str = "%s %s=%f" % (positions_str, motor, motors[motor])
          # update 'motors' field, so diffractometer will move to centring pos.
          motors_to_move_before_collect.update({motor: motors[motor]})
        for motor in extra_motors:
          positions_str = "%s %s=%f" % (positions_str, motor, extra_motors[motor])
          motors_to_move_before_collect.update({motor: extra_motors[motor]})
          
        data_collect_parameters['actualCenteringPosition'] = positions_str

        if self.bl_control.lims:
          try:
            if self.current_lims_sample:
              self.current_lims_sample['lastKnownCentringPosition'] = positions_str
              self.bl_control.lims.update_bl_sample(self.current_lims_sample)
          except:
            logging.getLogger("HWR").exception("Could not update sample infromation in LIMS")

        if 'images' in centring_info:
          # Save snapshots
          snapshot_directory = self.get_archive_directory(file_parameters["directory"])
          logging.getLogger("HWR").debug("Snapshot directory is %s" % snapshot_directory)

          try:
            self.create_directories(snapshot_directory)
          except:
              logging.getLogger("HWR").exception("Error creating snapshot directory")
          else:
              snapshot_i = 1
              snapshots = []
              for img in centring_info["images"]:
                img_phi_pos = img[0]
                img_data = img[1]
                snapshot_filename = "%s_%s_%s.snapshot.jpeg" % (file_parameters["prefix"],
                                                                file_parameters["run_number"],
                                                                snapshot_i)
                full_snapshot = os.path.join(snapshot_directory,
                                             snapshot_filename)

                try:
                  f = open(full_snapshot, "w")
                  f.write(img_data)
                except:
                  logging.getLogger("HWR").exception("Could not save snapshot!")
                  try:
                    f.close()
                  except:
                    pass

                data_collect_parameters['xtalSnapshotFullPath%i' % snapshot_i] = full_snapshot

                snapshots.append(full_snapshot)
                snapshot_i+=1

          try:
            data_collect_parameters["centeringMethod"] = centring_info['method']
          except:
            data_collect_parameters["centeringMethod"] = None

        if self.bl_control.lims:
            try:
                self.bl_control.lims.update_data_collection(data_collect_parameters)
            except:
                logging.getLogger("HWR").exception("Could not update data collection in LIMS")
        #import pdb;pdb.set_trace()
        oscillation_parameters = data_collect_parameters["oscillation_sequence"][0]
        sample_id = data_collect_parameters['blSampleId']
        inverse_beam = "reference_interval" in oscillation_parameters
        reference_interval = oscillation_parameters.get("reference_interval", 1)
        
        firstImage = oscillation_parameters["start_image_number"] 
        nbFrames = oscillation_parameters["number_of_images"]
        ScanStartAngle = oscillation_parameters["start"]
        ScanRange = oscillation_parameters["range"]
        wedgeSize = reference_interval
        inverse = inverse_beam
        ScanOverlap = oscillation_parameters["overlap"]
        template = image_file_template
        myWedges = self.prepareWedges(firstImage, 
                                      nbFrames, 
                                      ScanStartAngle, 
                                      ScanRange, 
                                      wedgeSize, 
                                      inverse, 
                                      ScanOverlap, 
                                      template)
        positions = myWedges['positions']
        wedges_to_collect = self.prepare_wedges_to_collect(oscillation_parameters["start"],
                                                           oscillation_parameters["number_of_images"],
                                                           oscillation_parameters["range"],
                                                           reference_interval,
                                                           inverse_beam,
                                                           oscillation_parameters["overlap"])
        logging.info('do_collect wedges_to_collect %s' % wedges_to_collect)
        nframes = len(wedges_to_collect)
        self.emit("collectNumberOfFrames", nframes) 

        start_image_number = oscillation_parameters["start_image_number"]    
        if data_collect_parameters["skip_images"]:
            for start, wedge_size in wedges_to_collect[:]:
              filename = image_file_template % start_image_number
              file_location = file_parameters["directory"]
              file_path  = os.path.join(file_location, filename)
              if os.path.isfile(file_path):
                logging.info("Skipping existing image %s", file_path)
                del wedges_to_collect[0]
                start_image_number += 1
                nframes -= 1
              else:
                # images have to be consecutive
                break

        if nframes == 0:
            return
            
        # write back to the dictionary to make macros happy... TODO: remove this once macros are removed!
        oscillation_parameters["start_image_number"] = start_image_number
        oscillation_parameters["number_of_images"] = nframes
        data_collect_parameters["skip_images"] = 0
 
        # data collection
        self.data_collection_hook(data_collect_parameters)
        
        if 'transmission' in data_collect_parameters:
          self.set_transmission(data_collect_parameters["transmission"])

        if 'wavelength' in data_collect_parameters:
          self.set_wavelength(data_collect_parameters["wavelength"])
        elif 'energy' in data_collect_parameters:
          self.set_energy(data_collect_parameters["energy"])
        
        if 'resolution' in data_collect_parameters:
          resolution = data_collect_parameters["resolution"]["upper"]
          self.set_resolution(resolution)
        elif 'detdistance' in oscillation_parameters:
          self.move_detector(oscillation_parameters["detdistance"])
          
        self.close_fast_shutter()

        self.move_motors(motors_to_move_before_collect)

        with cleanup(self.data_collection_cleanup):
            self.open_safety_shutter(timeout=10)

            self.prepare_intensity_monitors()
           
            frame = start_image_number
            osc_range = oscillation_parameters["range"]
            exptime = oscillation_parameters["exposure_time"]
            npass = oscillation_parameters["number_of_passes"]

            # update LIMS
            if self.bl_control.lims:
                  try:
                    data_collect_parameters["flux"] = self.get_flux()
                    data_collect_parameters["flux_end"] = data_collect_parameters["flux"]
                    data_collect_parameters["wavelength"]= self.get_wavelength()
                    data_collect_parameters["detectorDistance"] =  self.get_detector_distance()
                    data_collect_parameters["resolution"] = self.get_resolution()
                    data_collect_parameters["transmission"] = self.get_transmission()
                    gap1, gap2, gap3 = self.get_undulators_gaps()
                    data_collect_parameters["undulatorGap1"] = gap1
                    data_collect_parameters["undulatorGap2"] = gap2
                    data_collect_parameters["undulatorGap3"] = gap3
                    data_collect_parameters["resolutionAtCorner"] = self.get_resolution_at_corner()
                    beam_size_x, beam_size_y = self.get_beam_size()
                    data_collect_parameters["beamSizeAtSampleX"] = beam_size_x
                    data_collect_parameters["beamSizeAtSampleY"] = beam_size_y
                    data_collect_parameters["beamShape"] = self.get_beam_shape()
                    hor_gap, vert_gap = self.get_slit_gaps()
                    data_collect_parameters["slitGapHorizontal"] = hor_gap
                    data_collect_parameters["slitGapVertical"] = vert_gap
                    beam_centre_x, beam_centre_y = self.get_beam_centre()
                    data_collect_parameters["xBeam"] = beam_centre_x
                    data_collect_parameters["yBeam"] = beam_centre_y

                    logging.info("Updating data collection in ISPyB")
                    self.bl_control.lims.update_data_collection(data_collect_parameters, wait=True)
                    logging.info("Done")
                  except:
                    logging.getLogger("HWR").exception("Could not store data collection into LIMS")

            if self.bl_control.lims and self.bl_config.input_files_server:
                self.write_input_files(self.collection_id, wait=False) 

            self.prepare_acquisition(1 if data_collect_parameters.get("dark", 0) else 0,
                                     wedges_to_collect[0][0],
                                     osc_range,
                                     exptime,
                                     npass,
                                     nframes,
                                     data_collect_parameters["comment"])
            data_collect_parameters["dark"] = 0

            # at this point input files should have been written           
            if self.bl_control.lims and self.bl_config.input_files_server:
              if data_collect_parameters.get("processing", False)=="True":
                self.trigger_auto_processing("before",
                                       self.xds_directory,
                                       data_collect_parameters["EDNA_files_dir"],
                                       data_collect_parameters["anomalous"],
                                       data_collect_parameters["residues"],
                                       inverse_beam,
                                       data_collect_parameters["do_inducedraddam"],
                                       in_multicollect,
                                       data_collect_parameters.get("sample_reference", {}).get("spacegroup", ""),
                                       data_collect_parameters.get("sample_reference", {}).get("cell", ""))
            
            k = 0
            for start, wedge_size in wedges_to_collect:
                k += 1
                end = start + osc_range
                collect_position = positions[k-1]
                filename = image_file_template % frame
                try:
                  jpeg_full_path = jpeg_file_template % frame
                  jpeg_thumbnail_full_path = jpeg_thumbnail_file_template % frame
                except:
                  jpeg_full_path = None
                  jpeg_thumbnail_full_path = None
                file_location = file_parameters["directory"]
                file_path  = os.path.join(file_location, filename)
                
                logging.info("Frame %d, %7.3f to %7.3f degrees", frame, start, end)

                self.set_detector_filenames(frame, start, file_path, jpeg_full_path, jpeg_thumbnail_full_path)
                
                osc_start, osc_end = self.prepare_oscillation(start, osc_range, exptime, npass)
                
                with error_cleanup(self.reset_detector):
                    self.move_motors(collect_position)
                    self.start_acquisition(exptime, npass, frame==start_image_number)
                    if osc_end - osc_start < 1E-4:
                       self.open_fast_shutter()
                       time.sleep(exptime)
                       self.close_fast_shutter()
                    else:
                       self.do_oscillation(osc_start, osc_end, exptime, npass)
                    self.stop_acquisition()
                    last_frame = start_image_number + nframes - 1
                    self.write_image(frame == last_frame)
                    
                    # Store image in lims
                    if self.bl_control.lims:
                      if self.store_image_in_lims(frame, frame == start_image_number, frame == last_frame):
                        lims_image={'dataCollectionId': self.collection_id,
                                    'fileName': filename,
                                    'fileLocation': file_location,
                                    'imageNumber': frame,
                                    'measuredIntensity': self.get_measured_intensity(),
                                    'synchrotronCurrent': self.get_machine_current(),
                                    'machineMessage': self.get_machine_message(),
                                    'temperature': self.get_cryo_temperature()}

                        if archive_directory:
                          lims_image['jpegFileFullPath'] = jpeg_full_path
                          lims_image['jpegThumbnailFileFullPath'] = jpeg_thumbnail_full_path

                        try:
                          self.bl_control.lims.store_image(lims_image)
                        except:
                          logging.getLogger("HWR").exception("Could not store store image in LIMS")
                                              
                    self.emit("collectImageTaken", frame)
                        
                    if self.bl_control.lims and self.bl_config.input_files_server:
                      if data_collect_parameters.get("processing", False)=="True":
                         self.trigger_auto_processing("image",
                                                   self.xds_directory, 
                                                   data_collect_parameters["EDNA_files_dir"],
                                                   data_collect_parameters["anomalous"],
                                                   data_collect_parameters["residues"],
                                                   inverse_beam,
                                                   data_collect_parameters["do_inducedraddam"],
                                                   in_multicollect,
                                                   data_collect_parameters.get("sample_reference", {}).get("spacegroup", ""),
                                                   data_collect_parameters.get("sample_reference", {}).get("cell", ""))
                frame += 1

            self.finalize_acquisition()
Ejemplo n.º 11
0
class BLEnergy (Device) :
    
    stateEnergy = {'ALARM': 'error',
                   'FAULT': 'error',
                   'RUNNING': 'moving',
                   'MOVING' : 'moving',
                   'STANDBY' : 'ready',
                   'UNKNOWN': 'unknown',
                   'EXTRACT': 'outlimits'}

    def init(self):
        
        self.moving = None
        self.deviceOk = True
        self.prev_state = None
        self.doBacklashCompensation = False

        # Channel and commands for monochormator pitch.
        #    it will be used here to make sure it is on before moving energy (PX2)
        #    not needed on PX1
        self.mono_mt_rx_statech = None
        self.mono_mt_rx_oncmd = None
        
        # Connect to device BLEnergy defined "tangoname" in the xml file 
        try :
            self.BLEnergydevice = DeviceProxy(self.getProperty("tangoname"))
        except :
            self.errorDeviceInstance(self.getProperty("tangoname"))
            
        # Connect to device mono defined "tangoname2" in the xml file 
        # used for conversion in wavelength
        try :    
            self.monodevice = DeviceProxy(self.getProperty("tangoname2"))
        except :    
            self.errorDeviceInstance(self.getProperty("tangoname2"))

        # Nom du device bivu (Energy to gap) : necessaire pour amelioration du positionnement de l'onduleur (Backlash)
        try :    
#            self.U20Energydevice = DeviceProxy(self.getProperty("tangoname3"), movingState="RUNNING")
# Modif suite a changement par ICA de l etat du device U20 RUNNING devient MOVING
            self.U20Energydevice = DeviceProxy(self.getProperty("tangoname3"))
        except :    
            self.errorDeviceInstance(self.getProperty("tangoname3"))
            
        self.doBacklashCompensation = self.getProperty("backlash")
#        print self.doBacklashCompensation

        try:
            self.mono_mt_rx_statech = self.getChannelObject("mono_mt_rx_state")
            self.mono_mt_rx_oncmd = self.getCommandObject("mono_mt_rx_on")
        except KeyError:
            logging.info("Beware that mt_rx control is not properly defined for BLEnergy")
 
        
        # parameters for polling     
        if self.deviceOk :
            self.is_connected()
            self.prev_state = str( self.BLEnergydevice.State() )

            energyChan = self.getChannelObject("energy") 
            energyChan.connectSignal("update", self.energyChanged)

            stateChan = self.getChannelObject("state") # utile seulement si statechan n'est pas defini dans le code
            stateChan.connectSignal("update", self.stateChanged)

    def stateChanged(self,value):
        if (str(value) == 'MOVING') :
            self.move_energy_cmd_started()
        if self.prev_state == 'MOVING' or self.moving == True:
            if str(value) != 'MOVING' :
                self.move_energy_cmd_finished() 
                     
        self.prev_state = str(value)
        
        self.emit('stateChanged', BLEnergy.stateEnergy[str(value)])
        
    # function called during polling
    def energyChanged(self,value):
        #logging.getLogger("HWR").debug("%s: BLEnergy.energyChanged: %.3f", self.name(), value)
        wav = self.monodevice.read_attribute("lambda").value
        if wav is not None:
            self.emit('energyChanged', (value,wav))
            
            
    def connectNotify(self, signal):
        #logging.getLogger("HWR").info("%s: BLEnergy.connectNotify, : %s", self.name(), signal)           
        if signal == 'energyChanged':
            self.energyChanged(self.BLEnergydevice.energy)
        if signal == 'stateChanged' :    
            self.stateChanged( str(self.BLEnergydevice.State()) )            
        self.setIsReady(True)
         
    # called by brick : not useful      
    def isSpecConnected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.isSpecConnected", self.name())
        return True
    
    def is_connected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.is_connected", self.name())
        return True

    def sConnected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.sConnected", self.name())
        self.deviceOk = True
        self.emit('connected', ())
      
    def sDisconnected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.sDisconnected", self.name())
        self.deviceOk = False
        self.emit('disconnected', ())
    
    def isDisconnected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.isDisconnected", self.name())
        return True
        
    # Definit si la beamline est a energie fixe ou variable      
    def can_move_energy(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.can_move_energy", self.name())
        return  True
       
    def getPosition(self):
        return self.get_current_energy()
        
    def get_current_energy(self):
        if self.deviceOk :           
            return self.BLEnergydevice.energy
        else : 
            return None
    
    def getState(self):
        return self.BLEnergydevice.State().name
        
    def getEnergyComputedFromCurrentGap(self):
        #logging.getLogger("HWR").debug("%s: BLEnergy.get_current_energy", self.name())
        if self.deviceOk:
            # PL. Rq: if the device is not redy, it send a NaN...
            return self.U20Energydevice.energy
        else : 
            return None
    
    def getCurrentUndulatorGap(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.get_current_energy", self.name())
        if self.deviceOk :           
            return self.U20Energydevice.gap
        else : 
            return None
            
    def get_current_wavelength(self):
        #logging.getLogger("HWR").debug("%s: BLEnergy.get_current_wavelength", self.name())
        # Pb with the attribute name "lamdda" which is a keyword for python
        if self.deviceOk :           
            # using calculation of the device mono
            return self.monodevice.read_attribute("lambda").value
        else :
            return None
    
        
    def get_energy_limits(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.get_energy_limits", self.name())
        if self.deviceOk :          
            # limits defined in tango 
            enconfig = self.BLEnergydevice.get_attribute_config("energy")
            max = float(enconfig.max_value)
            min = float(enconfig.min_value)
            lims = (min, max)

            logging.getLogger("HWR").info("HOS : energy Limits: %.4f %.4f" % lims)       
            return lims
        else :
            return None
    
    def get_wavelength_limits(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.get_wavelength_limits", self.name())
        if self.deviceOk :
            lims=[]
            # Recuperation des limites en energie
            energylims = self.get_energy_limits()
            # Conversion de la limite inferieure en wavelength superieure (Utilisation des fonctions de conversion du device mono)
            self.monodevice.simEnergy = energylims[1]
            lims.append(self.monodevice.simLambda)
            # Conversion de la limite superieure en wavelength inferieure (Utilisation des fonctions de conversion du device mono)       
            self.monodevice.simEnergy = energylims[0]
            lims.append(self.monodevice.simLambda)      
    #        logging.getLogger("HWR").info("HOS : wavelength Limits: %.4f %.4f" % lims)       
            logging.getLogger("HWR").info("HOS : wavelength Limits: %s" % lims)       
            return lims   
        else :
            return None    
            
    def start_move_energy(self, value, wait=False):   
        logging.getLogger("HWR").debug("%s: BLEnergy.start_move_energy: %.3f", self.name(), float(value))
    
        # MODIFICATION DE CETTE FONCTION POUR COMPENSER LE PROBLEME D'HYSTERESIS DE L"ONDULEUR
        # PAR CETTE METHODE ON APPLIQUE TOUJOURS UN GAP CROISSANT
        backlash = 0.1 # en mm
        gaplimite = 5.5  # en mm
        
        if self.mono_mt_rx_statech is not None and self.mono_mt_rx_oncmd is not None:
            while str(self.mono_mt_rx_statech.getValue()) == 'OFF':
                logging.getLogger("HWR").info("BLEnergy : turning mono1-mt_rx on") 
                self.mono_mt_rx_oncmd()
                time.sleep(0.2)
            
        if (  str( self.BLEnergydevice.State() ) != "MOVING" and self.deviceOk) :
            if self.doBacklashCompensation :
                try : 
                    # Recuperation de la valeur de gap correspondant a l'energie souhaitee
                    self.U20Energydevice.autoApplyComputedParameters = False
                    self.U20Energydevice.energy = value
                    newgap = self.U20Energydevice.computedGap
                    actualgap = self.U20Energydevice.gap

                    self.U20Energydevice.autoApplyComputedParameters = True
                
                    # On applique le backlash que si on doit descendre en gap	    
                    if newgap < actualgap + backlash:
                        # Envoi a un gap juste en dessous (backlash)    
                        if newgap-backlash > gaplimite :
                            self.U20Energydevice.gap = newgap - backlash
                        else :
                            self.U20Energydevice.gap = gaplimite
                            self.U20Energydevice.gap = newgap + backlash
                        time.sleep(1)
                except :           
                    logging.getLogger("HWR").error("%s: Cannot move undulator U20 : State device = %s", self.name(), str(self.U20Energydevice.State()))

            try :
                # Envoi a l'energie desiree    
                self.BLEnergydevice.energy = value
            except :           
                logging.getLogger("HWR").error("%s: Cannot move BLEnergy : State device = %s", self.name(), str( self.BLEnergydevice.State() ))
        
        else : 
            statusBLEnergydevice = self.BLEnergydevice.Status()
            logging.getLogger("HWR").error("%s: Cannot move : State device = %s", self.name(), str( self.BLEnergydevice.State()))

            for i in statusBLEnergydevice.split("\n") :
                logging.getLogger().error("\t%s\n" % i)
            logging.getLogger().error("\tCheck devices")
    

    def start_move_wavelength(self, value, wait=False):
        logging.getLogger("HWR").debug("%s: BLEnergy.start_move_wavelength: %.3f", self.name(), value)
        self.monodevice.simLambda = value
        self.start_move_energy(self.monodevice.simEnergy)
#        return self.start_move_energy(energy_val)
    
    def cancel_move_energy(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.cancel_move_energy", self.name())
        self.BLEnergydevice.Stop()
        self.moving = False
            
    def energyLimitsChanged(self,limits):
        logging.getLogger("HWR").debug("%s: BLEnergy.energyLimitsChanged: %.3f", self.name(), value)
        self.monodevice.simEnergy = limits[0]
        wav_limits.append[self.monodevice.simLambda]
        self.monodevice.simEnergy = limits[1]
        wav_limits.append[self.monodevice.simLambda]
        self.emit('energyLimitsChanged', (limits,))
        if wav_limits[0]!=None and wav_limits[1]!=None:
            self.emit('wavelengthLimitsChanged', (wav_limits,))
        else:
            self.emit('wavelengthLimitsChanged', (None,))
            
    def moveEnergyCmdReady(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.moveEnergyCmdReady", self.name())
        if not self.moving :
            self.emit('moveEnergyReady', (True,))
            
    def moveEnergyCmdNotReady(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.moveEnergyCmdNotReady", self.name())
        if not self.moving :
            self.emit('moveEnergyReady', (False,))
            
    def move_energy_cmd_started(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.move_energy_cmd_started", self.name())
        self.moving = True
        #self.emit('moveEnergyStarted',(BLEnergy.stateEnergy[str(self.BLEnergydevice.State())]))
        self.emit('moveEnergyStarted', ())
        
    def move_energy_cmd_failed(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.move_energy_cmd_failed", self.name())
        self.moving = False
        self.emit('moveEnergyFailed', ())
        
    def move_energy_cmd_aborted(self):
        self.moving = False
        logging.getLogger("HWR").debug("%s: BLEnergy.move_energy_cmd_aborted", self.name())
    
    def move_energy_cmd_finished(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.move_energy_cmd_finished", self.name())
        self.moving = False
        print 'moveEnergyFinished'
        #self.emit('moveEnergyFinished',(BLEnergy.stateEnergy[str(self.BLEnergydevice.State())]))
        self.emit('moveEnergyFinished',())
        
    def getPreviousResolution(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.getPreviousResolution", self.name())
        return (None, None)
        
    def restoreResolution(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.restoreResolution", self.name())
        return (False,"Resolution motor not defined")
    
    def errorDeviceInstance(self,device) :
        logging.getLogger("HWR").debug("%s: BLEnergy.errorDeviceInstance: %s", self.name(), device)
        db = DeviceProxy("sys/database/dbds1")
        logging.getLogger().error("Check Instance of Device server %s" % db.DbGetDeviceInfo(device)[1][3])
        self.sDisconnected()
Ejemplo n.º 12
0
class BLEnergy(Device):

    stateEnergy = {
        'ALARM': 'error',
        'FAULT': 'error',
        'RUNNING': 'moving',
        'MOVING': 'moving',
        'STANDBY': 'ready',
        'UNKNOWN': 'unknown',
        'DISABLE': 'disable',
        'EXTRACT': 'outlimits'
    }

    def init(self):

        self.moving = None
        self.deviceOk = True
        self.prev_state = None
        self.doBacklashCompensation = False

        # Channel and commands for monochormator pitch.
        #    it will be used here to make sure it is on before moving energy (PX2)
        #    not needed on PX1
        self.mono_mt_rx_statech = None
        self.mono_mt_rx_oncmd = None

        # Connect to device BLEnergy defined "tangoname" in the xml file
        try:
            self.BLEnergydevice = DeviceProxy(self.getProperty("tangoname"))
        except:
            self.errorDeviceInstance(self.getProperty("tangoname"))

        # Connect to device mono defined "tangoname2" in the xml file
        # used for conversion in wavelength
        try:
            self.monodevice = DeviceProxy(self.getProperty("tangoname2"))
        except:
            self.errorDeviceInstance(self.getProperty("tangoname2"))

        # Nom du device bivu (Energy to gap) : necessaire pour amelioration du positionnement de l'onduleur (Backlash)
        try:
            #            self.U20Energydevice = DeviceProxy(self.getProperty("tangoname3"), movingState="RUNNING")
            # Modif suite a changement par ICA de l etat du device U20 RUNNING devient MOVING
            self.U20Energydevice = DeviceProxy(self.getProperty("tangoname3"))
        except:
            self.errorDeviceInstance(self.getProperty("tangoname3"))

        self.doBacklashCompensation = self.getProperty("backlash")
        #        print self.doBacklashCompensation

        try:
            self.mono_mt_rx_statech = self.getChannelObject("mono_mt_rx_state")
            self.mono_mt_rx_oncmd = self.getCommandObject("mono_mt_rx_on")
        except KeyError:
            logging.info(
                "Beware that mt_rx control is not properly defined for BLEnergy"
            )

        try:
            self.mono_mt_rx_fine_statech = self.getChannelObject(
                "mono_mt_rx_fine_state")
            self.mono_mt_rx_fine_oncmd = self.getCommandObject(
                "mono_mt_rx_fine_on")
        except KeyError:
            logging.info(
                "Beware that mt_rx control is not properly defined for BLEnergy"
            )

        self.get_energy_limits = self.getEnergyLimits
        self.get_wavelength_limits = self.getWavelengthLimits
        # parameters for polling
        if self.deviceOk:
            self.isConnected()
            self.prev_state = str(self.BLEnergydevice.State())

            energyChan = self.getChannelObject("energy")
            energyChan.connectSignal("update", self.energyChanged)

            stateChan = self.getChannelObject(
                "state"
            )  # utile seulement si statechan n'est pas defini dans le code
            stateChan.connectSignal("update", self.stateChanged)
        self.can_move_energy = self.canMoveEnergy
        self.move_energy = self.startMoveEnergy
        self.move_wavelength = self.startMoveWavelength

    def stateChanged(self, value):
        if (str(value) == 'MOVING'):
            self.moveEnergyCmdStarted()
        if self.prev_state == 'MOVING' or self.moving == True:
            if str(value) != 'MOVING':
                self.moveEnergyCmdFinished()

        self.prev_state = str(value)

        self.emit('stateChanged', BLEnergy.stateEnergy[str(value)])

    # function called during polling
    def energyChanged(self, value):
        #logging.getLogger("HWR").debug("%s: BLEnergy.energyChanged: %.3f", self.name(), value)
        #logging.info(">>>>>>>>  %s: BLEnergy.energyChanged: %.3f", self.name(), value)
        wav = self.monodevice.read_attribute("lambda").value
        if wav is not None:
            self.emit('energyChanged', (value, wav))

    def connectNotify(self, signal):
        logging.getLogger("HWR").info("%s: BLEnergy.connectNotify, : %s",
                                      self.name(), signal)
        if signal == 'energyChanged':
            self.energyChanged(self.BLEnergydevice.energy)
        if signal == 'stateChanged':
            self.stateChanged(str(self.BLEnergydevice.State()))
        self.setIsReady(True)

    # called by brick : not useful
    def isSpecConnected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.isSpecConnected",
                                       self.name())
        return True

    def isConnected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.isConnected", self.name())
        return True

    def sConnected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.sConnected", self.name())
        self.deviceOk = True
        self.emit('connected', ())

    def sDisconnected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.sDisconnected",
                                       self.name())
        self.deviceOk = False
        self.emit('disconnected', ())

    def isDisconnected(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.isDisconnected",
                                       self.name())
        return True

    # Definit si la beamline est a energie fixe ou variable
    def canMoveEnergy(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.canMoveEnergy",
                                       self.name())
        return True

    def getPosition(self):
        return self.getCurrentEnergy()

    def getCurrentEnergy(self):
        if self.deviceOk:
            return self.BLEnergydevice.energy
        else:
            return None

    def getState(self):
        return self.BLEnergydevice.State().name

    def getEnergyComputedFromCurrentGap(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.getCurrentEnergy",
                                       self.name())
        if self.deviceOk:
            # PL. Rq: if the device is not redy, it send a NaN...
            return self.U20Energydevice.energy
        else:
            return None

    def getCurrentUndulatorGap(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.getCurrentEnergy",
                                       self.name())
        if self.deviceOk:
            return self.U20Energydevice.gap
        else:
            return None

    def getCurrentWavelength(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.getCurrentWavelength",
                                       self.name())
        # Pb with the attribute name "lamdda" which is a keyword for python
        if self.deviceOk:
            # using calculation of the device mono
            return self.monodevice.read_attribute("lambda").value
        else:
            return None

    def getEnergyLimits(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.getEnergyLimits",
                                       self.name())
        if self.deviceOk:
            # limits defined in tango
            enconfig = self.BLEnergydevice.get_attribute_config("energy")
            max = float(enconfig.max_value)
            min = float(enconfig.min_value)
            lims = (min, max)

            logging.getLogger("HWR").info("HOS : energy Limits: %.4f %.4f" %
                                          lims)
            return lims
        else:
            return None

    def getWavelengthLimits(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.getWavelengthLimits",
                                       self.name())
        if self.deviceOk:
            lims = []
            # Recuperation des limites en energie
            energylims = self.getEnergyLimits()
            # Conversion de la limite inferieure en wavelength superieure (Utilisation des fonctions de conversion du device mono)
            self.monodevice.simEnergy = energylims[1]
            lims.append(self.monodevice.simLambda)
            # Conversion de la limite superieure en wavelength inferieure (Utilisation des fonctions de conversion du device mono)
            self.monodevice.simEnergy = energylims[0]
            lims.append(self.monodevice.simLambda)
            #        logging.getLogger("HWR").info("HOS : wavelength Limits: %.4f %.4f" % lims)
            logging.getLogger("HWR").info("HOS : wavelength Limits: %s" % lims)
            return lims
        else:
            return None

    def startMoveEnergy(self, value, wait=False):
        logging.getLogger("HWR").debug("%s: BLEnergy.startMoveEnergy: %.3f",
                                       self.name(), float(value))

        # MODIFICATION DE CETTE FONCTION POUR COMPENSER LE PROBLEME D'HYSTERESIS DE L"ONDULEUR
        # PAR CETTE METHODE ON APPLIQUE TOUJOURS UN GAP CROISSANT
        backlash = 0.1  # en mm
        gaplimite = 5.5  # en mm

        if self.mono_mt_rx_statech is not None and self.mono_mt_rx_oncmd is not None:
            while str(self.mono_mt_rx_statech.getValue()) == 'OFF':
                logging.getLogger("HWR").info(
                    "BLEnergy : turning mono1-mt_rx on")
                self.mono_mt_rx_oncmd()
                time.sleep(0.2)

        if self.mono_mt_rx_fine_statech is not None and self.mono_mt_rx_fine_oncmd is not None:
            while str(self.mono_mt_rx_fine_statech.getValue()) == 'OFF':
                logging.getLogger("HWR").info(
                    "BLEnergy : turning mono1-mt_rx_fine on")
                self.mono_mt_rx_fine_oncmd()
                time.sleep(0.2)

        if (str(self.BLEnergydevice.State()) != "MOVING" and self.deviceOk):
            if self.doBacklashCompensation:
                try:
                    # Recuperation de la valeur de gap correspondant a l'energie souhaitee
                    self.U20Energydevice.autoApplyComputedParameters = False
                    self.U20Energydevice.energy = value
                    newgap = self.U20Energydevice.computedGap
                    actualgap = self.U20Energydevice.gap

                    self.U20Energydevice.autoApplyComputedParameters = True

                    # On applique le backlash que si on doit descendre en gap
                    if newgap < actualgap + backlash:
                        # Envoi a un gap juste en dessous (backlash)
                        if newgap - backlash > gaplimite:
                            self.U20Energydevice.gap = newgap - backlash
                        else:
                            self.U20Energydevice.gap = gaplimite
                            self.U20Energydevice.gap = newgap + backlash
                        time.sleep(1)
                except:
                    logging.getLogger("HWR").error(
                        "%s: Cannot move undulator U20 : State device = %s",
                        self.name(), str(self.U20Energydevice.State()))

            try:
                # Envoi a l'energie desiree
                self.BLEnergydevice.energy = value
            except:
                logging.getLogger("HWR").error(
                    "%s: Cannot move BLEnergy : State device = %s",
                    self.name(), str(self.BLEnergydevice.State()))

        else:
            statusBLEnergydevice = self.BLEnergydevice.Status()
            logging.getLogger("HWR").error(
                "%s: Cannot move : State device = %s", self.name(),
                str(self.BLEnergydevice.State()))

            for i in statusBLEnergydevice.split("\n"):
                logging.getLogger().error("\t%s\n" % i)
            logging.getLogger().error("\tCheck devices")

    def startMoveWavelength(self, value, wait=False):
        logging.getLogger("HWR").debug(
            "%s: BLEnergy.startMoveWavelength: %.3f", self.name(), value)
        self.monodevice.simLambda = value
        self.startMoveEnergy(self.monodevice.simEnergy)


#        return self.startMoveEnergy(energy_val)

    def cancelMoveEnergy(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.cancelMoveEnergy",
                                       self.name())
        self.BLEnergydevice.Stop()
        self.moving = False

    def energyLimitsChanged(self, limits):
        logging.getLogger("HWR").debug(
            "%s: BLEnergy.energyLimitsChanged: %.3f", self.name(), value)
        self.monodevice.simEnergy = limits[0]
        wav_limits.append[self.monodevice.simLambda]
        self.monodevice.simEnergy = limits[1]
        wav_limits.append[self.monodevice.simLambda]
        self.emit('energyLimitsChanged', (limits, ))
        if wav_limits[0] != None and wav_limits[1] != None:
            self.emit('wavelengthLimitsChanged', (wav_limits, ))
        else:
            self.emit('wavelengthLimitsChanged', (None, ))

    def moveEnergyCmdReady(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.moveEnergyCmdReady",
                                       self.name())
        if not self.moving:
            self.emit('moveEnergyReady', (True, ))

    def moveEnergyCmdNotReady(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.moveEnergyCmdNotReady",
                                       self.name())
        if not self.moving:
            self.emit('moveEnergyReady', (False, ))

    def moveEnergyCmdStarted(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.moveEnergyCmdStarted",
                                       self.name())
        self.moving = True
        #self.emit('moveEnergyStarted',(BLEnergy.stateEnergy[str(self.BLEnergydevice.State())]))
        self.emit('moveEnergyStarted', ())

    def moveEnergyCmdFailed(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.moveEnergyCmdFailed",
                                       self.name())
        self.moving = False
        self.emit('moveEnergyFailed', ())

    def moveEnergyCmdAborted(self):
        self.moving = False
        logging.getLogger("HWR").debug("%s: BLEnergy.moveEnergyCmdAborted",
                                       self.name())

    def moveEnergyCmdFinished(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.moveEnergyCmdFinished",
                                       self.name())
        self.moving = False
        print 'moveEnergyFinished'
        #self.emit('moveEnergyFinished',(BLEnergy.stateEnergy[str(self.BLEnergydevice.State())]))
        self.emit('moveEnergyFinished', ())

    def getPreviousResolution(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.getPreviousResolution",
                                       self.name())
        return (None, None)

    def restoreResolution(self):
        logging.getLogger("HWR").debug("%s: BLEnergy.restoreResolution",
                                       self.name())
        return (False, "Resolution motor not defined")

    def errorDeviceInstance(self, device):
        logging.getLogger("HWR").debug("%s: BLEnergy.errorDeviceInstance: %s",
                                       self.name(), device)
        db = DeviceProxy("sys/database/dbds1")
        logging.getLogger().error("Check Instance of Device server %s" %
                                  db.DbGetDeviceInfo(device)[1][3])
        self.sDisconnected()
class TangoMotorZoomPX2(Device):

    stateDict = {
        "UNKNOWN": 0,
        "ALARM": 1,
        "FAULT": 1,
        "STANDBY": 2,
        "RUNNING": 4,
        "MOVING": 4,
        "ON": 2,
        '2': 2
    }

    def __init__(self, name):
        Device.__init__(self, name)
        self.GUIstep = 0.1

    def _init(self):

        self.MOVESTARTED = 0
        self.NOTINITIALIZED = 0
        self.UNUSABLE = 0
        self.READY = 2
        self.MOVING = 4
        self.ONLIMITS = 1

        #self.device = SimpleDevice(self.getProperty("tangoname"), verbose=False)
        #self.device.timeout = 6000 # Setting timeout to 6 sec
        self.device = DeviceProxy(self.getProperty("tangoname"))
        self.device.waitMoves = False
        logging.getLogger("HWR").info("TangoMotorZoomPX2._init of device %s" %
                                      self.device.name)
        self.setIsReady(True)
        print("TangoMotorZoomPX2._init of device %s" % self.device.name)
        positionChan = self.getChannelObject(
            "position"
        )  # utile seulement si statechan n'est pas defini dans le code
        positionChan.connectSignal("update", self.positionChanged)
        #focus_positionChan = self.getChannelObject("focus_position")
        #focus_positionChan.connectSignal("update", self.positionChanged)
        stateChan = self.getChannelObject(
            "state"
        )  # utile seulement si statechan n'est pas defini dans le code
        stateChan.connectSignal("update", self.motorStateChanged)

        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2._init, %s", self.name(), '')

    def positionChanged(self, value):
        try:
            logging.getLogger("HWR").info(
                "%s: TangoMotorZoomPX2.positionChanged: %.3f", self.name(),
                value)
        except:
            logging.getLogger("HWR").error("%s: TangoMotor not responding, %s",
                                           self.name(), '')

        self.emit('positionChanged', (value, ))

    def isReady(self):
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.isReady", self.name())
        return str(self.device.State()) == 'STANDBY'

    def connectNotify(self, signal):
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.connectNotify, : %s", self.name(), signal)
        if signal == 'hardwareObjectName,stateChanged':
            self.motorStateChanged(TangoMotorZoomPX2.stateDict[str(
                self.device.State())])
        elif signal == 'limitsChanged':
            self.motorLimitsChanged()
            #print "Not implemented yet."PhiTableXAxisPosition

        elif signal == 'positionChanged':
            #self.motorPositionChanged(self.device.position)
            print('MS debug 18.10.2012')
            #print self.device
            print(self.device.read_attribute("ZoomLevel").value)
            self.motorPositionChanged(
                self.device.read_attribute(
                    "ZoomLevel").value)  #MS debug 18.10.2012

        self.setIsReady(True)

    def motorState(self):
        return TangoMotorZoomPX2.stateDict[str(self.device.State())]

    def motorStateChanged(self, state):
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.motorStateChanged, %s", self.name(), state)
        #self.setIsReady(state == 'STANDBY')
        self.setIsReady(True)
        #print "motorStateChanged", str(state)
        self.emit('stateChanged',
                  (TangoMotorZoomPX2.stateDict[str(self.device.State())], ))

    def getState(self):
        state = str(self.device.State())
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.getState, %s", self.name(), state)
        return TangoMotorZoomPX2.stateDict[str(self.device.State())]

    def getLimits(self):
        #limits = self.device.getLimits("positiopositionChan.connectSignal("update", self.positionChanged)n")
        # MS 18.09.2012 adapted for use without SimpleDevice
        position_info = self.device.attribute_query("ZoomLevel")
        rlow = 1  # position_info.min_value
        rhigh = 10  #position_info.max_value
        #logging.getLogger("HWR").info("TangoMotorZoomPX2.getLimits: %.4f %.4f" % limits)
        return rlow, rhigh

    def motorLimitsChanged(self):
        #self.emit('limitsChanged', (self.getLimits(), ))
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.limitsChanged", self.name())
        self.emit('limitsChanged', (self.getLimits(), ))

    def motorMoveDone(self, channelValue):
        #SpecMotorA.motorMoveDone(self, channelValue)
        #logging.getLogger("HWR").info("TangoMotorZoomPX2.motorMoveDone")
        if str(self.device.State()) == 'STANDBY':

            #self.emit('moveDone', (self.specversion, self.specname, ))
            self.emit('moveDone', ("EH3", "toto"))

    def motorPositionChanged(self, absolutePosition):
        self.emit('positionChanged', (absolutePosition, ))

    def syncQuestionAnswer(self, specSteps, controllerSteps):
        return '0'  #NO ('1' means YES)

    def getPosition(self):
        pos = self.device.read_attribute(
            "ZoomLevel").value  #self.device.position
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.getPosition, pos = %.3f", self.name(), pos)
        return pos

    def syncMove(self, position):
        #print 'about to start moving', self.motorState
        t0 = time.time()
        prev_position = self.getPosition()
        self.device.position = position

        print('move started from %s to %s, state is %s' %
              (prev_position, position, str(self.device.State())))

        while str(self.device.State()) == "RUNNING" or str(
                self.device.State()
        ) == "MOVING":  # or str(self.device.State()) == SpecMotor.MOVESTARTED:
            #print 'processing events...', self.motorState
            qApp.processEvents(100)

        print('move done (%s s), state is %s' %
              (time.time() - t0, str(self.device.State())))

    def moveRelative(self, position):
        old_pos = self.device.position
        self.device.position = old_pos + position
        #self.moveRelahardwareObjectName,tive(position)

        while str(self.device.State()) == "RUNNING" or str(
                self.device.State()) == "MOVING":
            qApp.processEvents(100)

    def syncMoveRelative(self, position):
        old_pos = self.device.position
        self.device.position = old_pos + position
        #self.moveRelahardwareObjectName,tive(position)

        while str(self.device.State()) == "RUNNING" or str(
                self.device.State()) == "MOVING":
            qApp.processEvents(100)

    def getMotorMnemonic(self):
        return self.specName

    def move(self, absolutePosition):
        """Move the motor to the required position

        Arguments:
        absolutePosition -- position to move to
        """
        if type(absolutePosition) != float and type(absolutePosition) != int:
            logging.getLogger("TangoClient").error(
                "Cannot move %s: position '%s' is not a number",
                self.device.name, absolutePosition)

        #self.__changeMotorState(MOVESTARTED)

        #c = self.connection.getChannel(self.chanNamePrefix % 'start_one')
        logging.getLogger("HWR").info(
            "TangoMotorZoomPX2.move to absolute position: %.3f" %
            absolutePosition)
        self.device.position = absolutePosition

    def stop(self):
        logging.getLogger("HWR").info("TangoMotorZoomPX2.stop")
        self.device.Stop()

    def isSpecConnected(self):
        logging.getLogger().debug("%s: TangoMotorZoomPX2.isSpecConnected()" %
                                  self.name())
        return TruehardwareObjectName,
Ejemplo n.º 14
0
class TangoChannel(ChannelObject):
    _tangoEventsQueue = Queue()
    _eventReceivers = {}
    _tangoEventsProcessingTimer = gevent.get_hub().loop.async_()

    # start Tango events processing timer
    _tangoEventsProcessingTimer.start(processTangoEvents)

    def __init__(self,
                 name,
                 attribute_name,
                 tangoname=None,
                 username=None,
                 polling=None,
                 timeout=10000,
                 **kwargs):
        ChannelObject.__init__(self, name, username, **kwargs)

        self.attributeName = attribute_name
        self.deviceName = tangoname
        self.device = None
        self.value = Poller.NotInitializedValue
        self.polling = polling
        self.pollingTimer = None
        self.pollingEvents = False
        self.timeout = int(timeout)
        self.read_as_str = kwargs.get("read_as_str", False)
        self._device_initialized = Event()
        logging.getLogger("HWR").debug(
            "creating Tango attribute %s/%s, polling=%s, timeout=%d",
            self.deviceName,
            self.attributeName,
            polling,
            self.timeout,
        )
        self.init_device()
        self.continue_init(None)
        """
        self.init_poller = Poller.poll(self.init_device,
                                       polling_period = 3000,
                                       value_changed_callback = self.continue_init,
                                       error_callback = self.init_poll_failed,
                                       start_delay=100)
        """

    def init_poll_failed(self, e, poller_id):
        self._device_initialized.clear()
        logging.warning(
            "%s/%s (%s): could not complete init. (hint: device server is not running, or has to be restarted)",
            self.deviceName,
            self.attributeName,
            self.name(),
        )
        self.init_poller = self.init_poller.restart(3000)

    def continue_init(self, _):
        # self.init_poller.stop()

        if isinstance(self.polling, int):
            self.raw_device = RawDeviceProxy(self.deviceName)
            Poller.poll(
                self.poll,
                polling_period=self.polling,
                value_changed_callback=self.update,
                error_callback=self.pollFailed,
            )
        else:
            if self.polling == "events":
                # try to register event
                try:
                    self.pollingEvents = True
                    # logging.getLogger("HWR").debug("subscribing to CHANGE event for %s", self.attributeName)
                    self.device.subscribe_event(
                        self.attributeName,
                        PyTango.EventType.CHANGE_EVENT,
                        self,
                        [],
                        True,
                    )
                    # except PyTango.EventSystemFailed:
                    #   pass
                except Exception:
                    logging.getLogger("HWR").exception(
                        "could not subscribe event")
        self._device_initialized.set()

    def init_device(self):
        try:
            self.device = DeviceProxy(self.deviceName)
        except PyTango.DevFailed as traceback:
            self.imported = False
            last_error = traceback[-1]
            logging.getLogger("HWR").error("%s: %s", str(self.name()),
                                           last_error["desc"])
        else:
            self.imported = True
            try:
                self.device.ping()
            except PyTango.ConnectionFailed:
                self.device = None
                raise ConnectionError
            else:
                self.device.set_timeout_millis(self.timeout)

                # check that the attribute exists (to avoid Abort in PyTango grrr)
                if not self.attributeName.lower() in [
                        attr.name.lower()
                        for attr in self.device.attribute_list_query()
                ]:
                    logging.getLogger("HWR").error(
                        "no attribute %s in Tango device %s",
                        self.attributeName,
                        self.deviceName,
                    )
                    self.device = None

    def push_event(self, event):
        # logging.getLogger("HWR").debug("%s | attr_value=%s, event.errors=%s, quality=%s", self.name(), event.attr_value, event.errors,event.attr_value is None and "N/A" or event.attr_value.quality)
        if (event.attr_value is None or event.err
                or event.attr_value.quality != PyTango.AttrQuality.ATTR_VALID):
            # logging.getLogger("HWR").debug("%s, receving BAD event... attr_value=%s, event.errors=%s, quality=%s", self.name(), event.attr_value, event.errors, event.attr_value is None and "N/A" or event.attr_value.quality)
            return
        else:
            pass
            # logging.getLogger("HWR").debug("%s, receiving good event", self.name())
        ev = E(event)
        TangoChannel._eventReceivers[id(ev)] = saferef.safe_ref(self.update)
        TangoChannel._tangoEventsQueue.put(ev)
        TangoChannel._tangoEventsProcessingTimer.send()

    def poll(self):
        if self.read_as_str:
            value = self.raw_device.read_attribute(
                self.attributeName,
                PyTango.DeviceAttribute.ExtractAs.String).value
            # value = self.device.read_attribute_as_str(self.attributeName).value
        else:
            value = self.raw_device.read_attribute(self.attributeName).value
        self.emit("update", value)
        return value

    def pollFailed(self, e, poller_id):
        self.emit("update", None)
        """
        emit_update = True
        if self.value is None:
          emit_update = False
        else:
          self.value = None

        try:
            self.init_device()
        except:
            pass

        poller = Poller.get_poller(poller_id)
        if poller is not None:
            poller.restart(1000)

        try:
          raise e
        except:
          logging.exception("%s: Exception happened while polling %s", self.name(), self.attributeName)

        if emit_update:
          # emit at the end => can raise exceptions in callbacks
          self.emit('update', None)
        """

    def getInfo(self):
        self._device_initialized.wait(timeout=3)
        return self.device.get_attribute_config(self.attributeName)

    def update(self, value=Poller.NotInitializedValue):
        if value == Poller.NotInitializedValue:
            value = self.getValue()
        if isinstance(value, types.TupleType):
            value = list(value)

        self.value = value
        self.emit("update", value)

    def getValue(self):
        self._device_initialized.wait(timeout=3)

        if self.read_as_str:
            value = self.device.read_attribute(
                self.attributeName,
                PyTango.DeviceAttribute.ExtractAs.String).value
        else:
            value = self.device.read_attribute(self.attributeName).value

        return value

    def setValue(self, newValue):
        self.device.write_attribute(self.attributeName, newValue)
        # attr = PyTango.AttributeProxy(self.deviceName + "/" + self.attributeName)
        # a = attr.read()
        # a.value = newValue
        # attr.write(a)

    def isConnected(self):
        return self.device is not None
Ejemplo n.º 15
0
class TangoDevice(object):
    """
    Wrapper for basic Tango device.
    It provides registering device, halting device and executing commands
    """
    POLL_STATE_TIME = 0.5
    TEST_MODE = False

    def __init__(self, devicePath=None):
        """
        Class constructor
        @type devicePath: String
        """
        self.devicePath = devicePath
        self.maxValue = False
        self.minValue = False
        self.name = "Generic device"
        self.output = {}
        self.profiling = False
        self.deviceError = False
        self.defaultClass = self.__class__

        # state change marker
        self._bstate_changed = False
        self.old_state = None

        self.__thread = None

        try:
            self.__device_init()
        except:
            logging.error(
                str("Device %s could not be connected" % self.devicePath))
            self.name = self.devicePath
            if config.DEVICE_ALLOW_RETRY:
                self._retry_device()
                #raise Exception(str("Device %s could not be connected" % self.devicePath))
                # logging.error(str("Device %s could not be connected" % self.devicePath))
                #else:

                #raise Exception(str("Device %s could not be connected" % self.devicePath))

    def __postInit__(self):
        pass

    def __device_init(self):
        self.device = DeviceProxy(self.devicePath)
        info = self.device.import_info()
        self.name = info.name

        if (self.name in DEVICE_NAMES):
            self.name = DEVICE_NAMES[self.name]

        self.deviceError = False
        self.__postInit__()

    def _retry_device(self, callback=None):
        self.deviceError = True
        thread = Thread(target=self.__retry_routine, args=([callback]))
        threads.add_thread(thread)
        thread.start()
        self.__class__ = DummyDevice

    def __retry_routine(self, callback):
        retrySleep = [True]
        while (retrySleep[0] and threads.THREAD_KEEP_ALIVE):
            try:
                DeviceProxy(self.devicePath).state()
                logging.error("Device online: %s" % (self.devicePath))
                retrySleep = [False]
            except:
                logging.error("Device offline, retrying: %s" %
                              (self.devicePath))
            threads.thread_sleep(config.DEVICE_RETRY_INTERVAL,
                                 sleepFlags=retrySleep)
        if threads.THREAD_KEEP_ALIVE == True:
            self.__class__ = self.defaultClass
            self.__device_init()
            if callback: callback()
        return True

    def isDeviceError(self):
        return self.deviceError

    def halt(self, callBack=None):
        """
        Stop device
        """
        pass

    def running_remove(self, *args):
        """
        Remove device from all running devices set
        """
        try:
            if (not stopDevices):
                runningDevices.remove(self)
        except:
            pass

    def running_add(self):
        """
        Add device to all runing devices set
        """
        global runningDevices
        runningDevices.add(self)

    def is_connected(self):
        """
        Return true if device is connected
        @rtype: bool
        """
        if self.device is None: return False
        else: return True

    def read_attributes(self, attributes):
        try:
            return self.device.read_attributes(attributes)
        except:
            logging.error("Device read attribute error: retrying device")
            if not config.DEVICE_ALLOW_RETRY:
                raise Exception(
                    str("Device %s could not be connected" % self.devicePath))
            else:
                self._retry_device()
                return self.read_attributes(attributes)

    def read_attribute(self, attribute):
        try:
            return self.device.read_attribute(attribute)
        except:
            if not config.DEVICE_ALLOW_RETRY:
                raise Exception(
                    str("Device %s could not be connected" % self.devicePath))
            else:
                self._retry_device()
                return self.read_attribute(attribute)

    def write_attributes(self, attributes):
        """
        Write attribute to device
        @type attributes: list
        @rtype: String
        """
        res = None
        if self.device:
            for attribute in attributes:
                logging.info("Attribute: %s wrote on device: %s", attribute[0],
                             self.devicePath)

            try:
                self.device.state()
                res = self.device.write_attributes(attributes)
            except (DevFailed, AttributeError) as e:
                pass
        return res

    def write_attributes_async(self, attributes, callback=None):
        res = None
        if self.device:
            for attribute in attributes:
                logging.info("Attribute: %s wrote on device: %s", attribute[0],
                             self.devicePath)

            try:
                self.device.state()
                res = self.device.write_attributes_asynch(attributes, callback)
            except (DevFailed, AttributeError) as e:
                pass
        return res

    def execute_command(self, commandName, commandParam=None):
        """
        Execute command on device
        @type commandName: String
        @type commandParam: String
        @rtype: String
        """
        try:
            if self.device:
                return self.device.command_inout(commandName, commandParam)
        except:
            if not config.DEVICE_ALLOW_RETRY:
                raise Exception(
                    str("Device %s could not be connected" % self.devicePath))
            else:
                self._retry_device()
                return self.execute_command(commandName, commandParam)

    def wait_for_state(self, state, callback=None):
        """
        Wait for state
        @type state: DevState.state
        """
        if self.device:
            while (self.device.state() == state):
                sleep(self.POLL_STATE_TIME)
            if not (callback is None): callback(self)

    def wait_seconds(self, duration=1):
        """
        Wait for a time duration
        @type duration: float if not config.DEVICE_ALLOW_RETRY: 
                raise Exception(str("Device %s could not be connected" % self.devicePath))
            else: 
                self._retry_device()
                return self.execute_command(commandName, commandParam)
        """
        if self.device:
            sleep(duration)

    def poll(self,
             commandName,
             duration=0.1,
             commandResult=True,
             callback=None,
             commandParam=None):
        """
        Poll device with command
        @type commandName: String
        @type duration: float
        @type callback: fun
        @type commandParam: String  
        """
        while (self.execute_command(commandName, commandParam) == commandResult
               and threads.THREAD_KEEP_ALIVE):
            self.wait_seconds(duration)
        if not (callback is None): callback(self)

    def poll_attribute(self,
                       attrName,
                       duration=0.1,
                       attributeResult=True,
                       callback=None,
                       commandParam=None):
        """
        Poll device with command
        @type attrName: String
        @type duration: float
        @type callback: fun
        @type commandParam: String
        """
        while (self.read_attribute(attrName).value == attributeResult
               and threads.THREAD_KEEP_ALIVE):
            self.wait_seconds(duration)
        if not (callback is None): callback(self)

    def check_idle(self):
        """
        Check if device id idle
        """
        pass

    def is_idle(self):
        """
        Return True if is idle, False if not and None if unknown 
        """
        return None

    def start_profiling(self):
        if self.profiling: return False
        self.profiling = True
        logging.info("Profiling of device %s started" % self.devicePath)
        return True

    def stop_profiling(self):
        self.profiling = False
        self.cleanup_thread()

    def current_value(self, value):
        return self.read_attribute(value).value

    def __profiling_routine(self):
        pass

    @property
    def thread(self):
        return self.__thread

    def start_external_profiling(self, func):
        """
        Starts profiling with an external function
        """
        self.profiling = True

        if self.__thread is None:
            thread = threads.threading.Thread(target=func, args=([self]))
            threads.add_thread(thread)
            thread.start()

            self.__thread = thread

    def cleanup_thread(self):
        if self.__thread is not None:
            self.profiling = False
            threads.join_thread(self.__thread)
            self.__thread = None

    def state(self):
        """
        Overload of the state function to keep track of old states
        :return:
        """
        state = None
        try:
            state = DeviceProxy(self.devicePath).state()

            self._bstate_changed = False
            if state != self.old_state:
                self.old_state = state
                self._bstate_changed = True
        except DevFailed:
            pass
        return state

    def is_state_changed(self):
        return self._bstate_changed
Ejemplo n.º 16
0
class CatsMaint(Equipment):

    __TYPE__ = "CATS"
    NO_OF_LIDS = 3
    """
    Actual implementation of the CATS Sample Changer, MAINTENANCE COMMANDS ONLY
    BESSY BL14.1 installation with 3 lids
    """
    def __init__(self, *args, **kwargs):
        Equipment.__init__(self, *args, **kwargs)

        self._state = None
        self._running = None
        self._powered = None
        self._toolopen = None
        self._message = None
        self._regulating = None
        self._lid1state = None
        self._lid2state = None
        self._lid3state = None
        self._charging = None

    def init(self):

        self.cats_device = DeviceProxy(self.tangoname)

        try:
            self.cats_model = self.cats_device.read_attribute(
                "CatsModel").value
        except BaseException:
            self.cats_model = "CATS"

        if self.is_isara():
            self.nb_of_lids = 1
        else:
            self.nb_of_lids = 3

        self._chnState = self.add_channel(
            {
                "type": "tango",
                "name": "_chnState",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "State",
        )

        self._chnPathRunning = self.add_channel(
            {
                "type": "tango",
                "name": "_chnPathRunning",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "PathRunning",
        )
        self._chnPowered = self.add_channel(
            {
                "type": "tango",
                "name": "_chnPowered",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "Powered",
        )
        self._chnMessage = self.add_channel(
            {
                "type": "tango",
                "name": "_chnMessage",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "Message",
        )
        self._chnToolOpenClose = self.add_channel(
            {
                "type": "tango",
                "name": "_chnToolOpenClose",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "di_ToolOpen",
        )
        self._chnLN2Regulation = self.add_channel(
            {
                "type": "tango",
                "name": "_chnLN2Regulation",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "LN2Regulating",
        )
        self._chnBarcode = self.add_channel(
            {
                "type": "tango",
                "name": "_chnBarcode",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "Barcode",
        )

        self._chnLid1State = self.add_channel(
            {
                "type": "tango",
                "name": "_chnLid1State",
                "tangoname": self.tangoname,
                "polling": 1000,
            },
            "di_Lid1Open",
        )
        self._chnLid1State.connectSignal("update", self._updateLid1State)

        if self.nb_of_lids > 1:
            self._chnLid2State = self.add_channel(
                {
                    "type": "tango",
                    "name": "_chnLid2State",
                    "tangoname": self.tangoname,
                    "polling": 1000,
                },
                "di_Lid2Open",
            )
            self._chnLid2State.connectSignal("update", self._updateLid2State)

        if self.nb_of_lids > 2:
            self._chnLid3State = self.add_channel(
                {
                    "type": "tango",
                    "name": "_chnLid3State",
                    "tangoname": self.tangoname,
                    "polling": 1000,
                },
                "di_Lid3Open",
            )
            self._chnLid3State.connectSignal("update", self._updateLid3State)

        self._chnState.connectSignal("update", self._update_state)
        self._chnPathRunning.connectSignal("update",
                                           self._update_running_state)
        self._chnPowered.connectSignal("update", self._update_powered_state)
        self._chnToolOpenClose.connectSignal("update", self._updateToolState)
        self._chnMessage.connectSignal("update", self._updateMessage)
        self._chnLN2Regulation.connectSignal("update",
                                             self._updateRegulationState)
        self._chnBarcode.connectSignal("update", self._updateBarcode)

        self._chnCurrentTool = self.add_channel(
            {
                "type": "tango",
                "name": "_chnCurrentTool",
                "tangoname": self.tangoname
            },
            "Tool",
        )
        #
        self._cmdPowerOn = self.add_command(
            {
                "type": "tango",
                "name": "_cmdPowerOn",
                "tangoname": self.tangoname
            },
            "powerOn",
        )
        self._cmdPowerOff = self.add_command(
            {
                "type": "tango",
                "name": "_cmdPowerOff",
                "tangoname": self.tangoname
            },
            "powerOff",
        )
        self._cmdOpenTool = self.add_command(
            {
                "type": "tango",
                "name": "_cmdOpenTool",
                "tangoname": self.tangoname
            },
            "opentool",
        )
        self._cmdCloseTool = self.add_command(
            {
                "type": "tango",
                "name": "_cmdCloseTool",
                "tangoname": self.tangoname
            },
            "closetool",
        )
        self._cmdMagnetOn = self.add_command(
            {
                "type": "tango",
                "name": "_cmdMagnetOn",
                "tangoname": self.tangoname
            },
            "magnetOn",
        )
        self._cmdMagnetOff = self.add_command(
            {
                "type": "tango",
                "name": "_cmdMagnetOff",
                "tangoname": self.tangoname
            },
            "magnetOff",
        )

        # LIDs
        self._cmdOpenLid1 = self.add_command(
            {
                "type": "tango",
                "name": "_cmdOpenLid1",
                "tangoname": self.tangoname
            },
            "openlid1",
        )
        self._cmdCloseLid1 = self.add_command(
            {
                "type": "tango",
                "name": "_cmdCloseLid1",
                "tangoname": self.tangoname
            },
            "closelid1",
        )

        if self.nb_of_lids > 1:
            self._cmdOpenLid2 = self.add_command(
                {
                    "type": "tango",
                    "name": "_cmdOpenLid1",
                    "tangoname": self.tangoname
                },
                "openlid2",
            )
            self._cmdCloseLid2 = self.add_command(
                {
                    "type": "tango",
                    "name": "_cmdCloseLid1",
                    "tangoname": self.tangoname
                },
                "closelid2",
            )

        if self.nb_of_lids > 2:
            self._cmdOpenLid3 = self.add_command(
                {
                    "type": "tango",
                    "name": "_cmdOpenLid1",
                    "tangoname": self.tangoname
                },
                "openlid3",
            )
            self._cmdCloseLid3 = self.add_command(
                {
                    "type": "tango",
                    "name": "_cmdCloseLid1",
                    "tangoname": self.tangoname
                },
                "closelid3",
            )

        self._cmdRegulOn = self.add_command(
            {
                "type": "tango",
                "name": "_cmdRegulOn",
                "tangoname": self.tangoname
            },
            "regulon",
        )
        self._cmdRegulOff = self.add_command(
            {
                "type": "tango",
                "name": "_cmdRegulOff",
                "tangoname": self.tangoname
            },
            "reguloff",
        )

        self._cmdToolOpen = self.add_command(
            {
                "type": "tango",
                "name": "_cmdToolOpen",
                "tangoname": self.tangoname
            },
            "opentool",
        )
        self._cmdToolClose = self.add_command(
            {
                "type": "tango",
                "name": "_cmdToolClose",
                "tangoname": self.tangoname
            },
            "closetool",
        )

        # Paths
        self._cmdAbort = self.add_command(
            {
                "type": "tango",
                "name": "_cmdAbort",
                "tangoname": self.tangoname
            }, "abort")
        self._cmdDry = self.add_command(
            {
                "type": "tango",
                "name": "_cmdDry",
                "tangoname": self.tangoname
            }, "dry")
        self._cmdSafe = self.add_command(
            {
                "type": "tango",
                "name": "_cmdSafe",
                "tangoname": self.tangoname
            }, "safe")
        self._cmdHome = self.add_command(
            {
                "type": "tango",
                "name": "_cmdHome",
                "tangoname": self.tangoname
            }, "home")
        self._cmdSoak = self.add_command(
            {
                "type": "tango",
                "name": "_cmdSoak",
                "tangoname": self.tangoname
            }, "soak")
        self._cmdBack = self.add_command(
            {
                "type": "tango",
                "name": "_cmdBack",
                "tangoname": self.tangoname
            }, "back")
        self._cmdCalibration = self.add_command(
            {
                "type": "tango",
                "name": "_cmdCalibration",
                "tangoname": self.tangoname
            },
            "toolcalibration",
        )

        self._cmdClearMemory = self.add_command(
            {
                "type": "tango",
                "name": "_cmdClearMemory",
                "tangoname": self.tangoname
            },
            "clear_memory",
        )
        self._cmdReset = self.add_command(
            {
                "type": "tango",
                "name": "_cmdReset",
                "tangoname": self.tangoname
            }, "reset")
        self._cmdResetParameters = self.add_command(
            {
                "type": "tango",
                "name": "_cmdResetParameters",
                "tangoname": self.tangoname,
            },
            "reset_parameters",
        )

        self._cmdRecoverFailure = self.add_command(
            {
                "type": "tango",
                "name": "_cmdRecoverFailure",
                "tangoname": self.tangoname,
            },
            "recoverFailure",
        )

        self._cmdResetMotion = self.add_command(
            {
                "type": "tango",
                "name": "_cmdResetMotion",
                "tangoname": self.tangoname
            },
            "resetmotion",
        )

        self._cmdSetOnDiff = self.add_command(
            {
                "type": "tango",
                "name": "_cmdSetOnDiff",
                "tangoname": self.tangoname
            },
            "setondiff",
        )
        self._cmdSetOnTool = self.add_command(
            {
                "type": "tango",
                "name": "_cmdSetOnTool",
                "tangoname": self.tangoname
            },
            "settool",
        )
        self._cmdSetOnTool2 = self.add_command(
            {
                "type": "tango",
                "name": "_cmdSetOnTool2",
                "tangoname": self.tangoname
            },
            "settool2",
        )

        self.state_actions = {
            "power": {
                "in_open": self._cmdPowerOn,
                "out_close": self._cmdPowerOff,
                "state": self._chnPowered,
            }
        }

    def is_isara(self):
        return self.cats_model == "ISARA"

    def is_cats(self):
        return self.cats_model != "ISARA"

    def get_current_tool(self):
        current_value = self._chnCurrentTool.getValue()

        tool = TOOL_TO_STR.get(current_value, None)

        return tool

    ################################################################################

    def backTraj(self):
        """
        Moves a sample from the gripper back into the dewar to its logged position.
        """
        return self._execute_task(False, self._doBack)

    def safeTraj(self):
        """
        Safely Moves the robot arm and the gripper to the home position
        """
        return self._execute_task(False, self._doSafe)

    def _do_abort(self):
        """
        Launch the "abort" trajectory on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdAbort()

    def _do_home(self):
        """
        Launch the "abort" trajectory on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        tool = self.get_current_tool()
        self._cmdHome(tool)

    def _do_reset(self):
        """
        Launch the "reset" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        logging.getLogger("HWR").debug("CatsMaint. doing reset")
        return
        self._cmdReset()

    def _do_reset_memory(self):
        """
        Launch the "reset memory" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdClearMemory()
        time.sleep(1)
        self._cmdResetParameters()
        time.sleep(1)

    def _do_resetMotion(self):
        """
        Launch the "reset_motion" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdResetMotion()

    def _doRecoverFailure(self):
        """
        Launch the "recoverFailure" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdRecoverFailure()

    def _doCalibration(self):
        """
        Launch the "toolcalibration" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        tool = self.get_current_tool()
        self._cmdCalibration(tool)

    def _doOpenTool(self):
        """
        Launch the "opentool" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdOpenTool()

    def _doCloseTool(self):
        """
        Launch the "closetool" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        self._cmdCloseTool()

    def _doDryGripper(self):
        """
        Launch the "dry" command on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        tool = self.get_current_tool()
        self._cmdDry(tool)

    def _doSetOnDiff(self, sample):
        """
        Launch the "setondiff" command on the CATS Tango DS, an example of sample value is 2:05

        :returns: None
        :rtype: None
        """

        if sample is None:
            raise Exception("No sample selected")
        else:
            str_tmp = str(sample)
            sample_tmp = str_tmp.split(":")
            # calculate CATS specific lid/sample number
            lid = (int(sample_tmp[0]) - 1) / 3 + 1
            puc_pos = ((int(sample_tmp[0]) - 1) % 3) * 10 + int(sample_tmp[1])
            argin = [str(lid), str(puc_pos), "0"]
            logging.getLogger().info("to SetOnDiff %s", argin)
            self._execute_server_task(self._cmdSetOnDiff, argin)

    def _doBack(self):
        """
        Launch the "back" trajectory on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        tool = self.get_current_tool()
        argin = [str(tool), "0"]  # to send string array with two arg...
        self._execute_server_task(self._cmdBack, argin)

    def _doSafe(self):
        """
        Launch the "safe" trajectory on the CATS Tango DS

        :returns: None
        :rtype: None
        """
        argin = self.get_current_tool()
        self._execute_server_task(self._cmdSafe, argin)

    def _doPowerState(self, state=False):
        """
        Switch on CATS power if >state< == True, power off otherwise

        :returns: None
        :rtype: None
        """
        logging.getLogger("HWR").debug("   running power state command ")
        if state:
            self._cmdPowerOn()
        else:
            self._cmdPowerOff()

        self.do_state_action("power", state)

    def _doEnableRegulation(self):
        """
        Switch on CATS regulation

        :returns: None
        :rtype: None
        """
        self._cmdRegulOn()

    def _doDisableRegulation(self):
        """
        Switch off CATS regulation

        :returns: None
        :rtype: None
        """
        self._cmdRegulOff()

    def _doLid1State(self, state=True):
        """
        Opens lid 1 if >state< == True, closes the lid otherwise

        :returns: None
        :rtype: None
        """
        if state:
            self._execute_server_task(self._cmdOpenLid1)
        else:
            self._execute_server_task(self._cmdCloseLid1)

    def _doLid2State(self, state=True):
        """
        Opens lid 2 if >state< == True, closes the lid otherwise

        :returns: None
        :rtype: None
        """
        if state:
            self._execute_server_task(self._cmdOpenLid2)
        else:
            self._execute_server_task(self._cmdCloseLid2)

    def _doLid3State(self, state=True):
        """
        Opens lid 3 if >state< == True, closes the lid otherwise

        :returns: None
        :rtype: None
        """
        if state:
            self._execute_server_task(self._cmdOpenLid3)
        else:
            self._execute_server_task(self._cmdCloseLid3)

    def _doMagnetOn(self):
        self._execute_server_task(self._cmdMagnetOn)

    def _doMagnetOff(self):
        self._execute_server_task(self._cmdMagnetOff)

    def _doToolOpen(self):
        self._execute_server_task(self._cmdToolOpen)

    def _doToolClose(self):
        self._execute_server_task(self._cmdToolClose)

    # ########################          PROTECTED          #########################

    def _execute_task(self, wait, method, *args):
        ret = self._run(method, wait=False, *args)
        if wait:
            return ret.get()
        else:
            return ret

    @task
    def _run(self, method, *args):
        exception = None
        ret = None
        try:
            ret = method(*args)
        except Exception as ex:
            exception = ex
        if exception is not None:
            raise exception
        return ret

    # ########################           PRIVATE           #########################

    def _update_running_state(self, value):
        self._running = value
        self.emit("runningStateChanged", (value, ))
        self._update_global_state()

    def _update_powered_state(self, value):
        self._powered = value
        self.emit("powerStateChanged", (value, ))
        self._update_global_state()

    def _updateToolState(self, value):
        self._toolopen = value
        self.emit("toolStateChanged", (value, ))
        self._update_global_state()

    def _updateMessage(self, value):
        self._message = value
        self.emit("messageChanged", (value, ))
        self._update_global_state()

    def _updateRegulationState(self, value):
        self._regulating = value
        self.emit("regulationStateChanged", (value, ))
        self._update_global_state()

    def _updateBarcode(self, value):
        self._barcode = value
        self.emit("barcodeChanged", (value, ))

    def _update_state(self, value):
        self._state = value
        self._update_global_state()

    def _updateLid1State(self, value):
        self._lid1state = value
        self.emit("lid1StateChanged", (value, ))
        self._update_global_state()

    def _updateLid2State(self, value):
        self._lid2state = value
        self.emit("lid2StateChanged", (value, ))
        self._update_global_state()

    def _updateLid3State(self, value):
        self._lid3state = value
        self.emit("lid3StateChanged", (value, ))
        self._update_global_state()

    def _updateOperationMode(self, value):
        self._charging = not value

    def _update_global_state(self):
        state_dict, cmd_state, message = self.get_global_state()
        self.emit("globalStateChanged", (state_dict, cmd_state, message))

    def get_global_state(self):
        """
           Update clients with a global state that
           contains different:

           - first param (state_dict):
               collection of state bits

           - second param (cmd_state):
               list of command identifiers and the
               status of each of them True/False
               representing whether the command is
               currently available or not

           - message
               a message describing current state information
               as a string
        """
        _ready = str(self._state) in ("READY", "ON")

        if self._running:
            state_str = "MOVING"
        elif not (self._powered) and _ready:
            state_str = "DISABLED"
        elif _ready:
            state_str = "READY"
        else:
            state_str = str(self._state)

        state_dict = {
            "toolopen": self._toolopen,
            "powered": self._powered,
            "running": self._running,
            "regulating": self._regulating,
            "lid1": self._lid1state,
            "lid2": self._lid2state,
            "lid3": self._lid3state,
            "state": state_str,
        }

        cmd_state = {
            "powerOn": (not self._powered) and _ready,
            "powerOff": (self._powered) and _ready,
            "regulon": (not self._regulating) and _ready,
            "openlid1": (not self._lid1state) and self._powered and _ready,
            "closelid1": self._lid1state and self._powered and _ready,
            "dry": (not self._running) and self._powered and _ready,
            "soak": (not self._running) and self._powered and _ready,
            "home": (not self._running) and self._powered and _ready,
            "back": (not self._running) and self._powered and _ready,
            "safe": (not self._running) and self._powered and _ready,
            "clear_memory": True,
            "reset": True,
            "abort": True,
        }

        message = self._message

        return state_dict, cmd_state, message

    def get_cmd_info(self):
        """ return information about existing commands for this object
           the information is organized as a list
           with each element contains
           [ cmd_name,  display_name, category ]
        """
        """ [cmd_id, cmd_display_name, nb_args, cmd_category, description ] """
        cmd_list = [
            [
                "Power",
                [
                    ["powerOn", "PowerOn", "Switch Power On"],
                    ["powerOff", "PowerOff", "Switch Power Off"],
                    ["regulon", "Regulation On", "Swich LN2 Regulation On"],
                ],
            ],
            [
                "Lid",
                [
                    ["openlid1", "Open Lid", "Open Lid"],
                    ["closelid1", "Close Lid", "Close Lid"],
                ],
            ],
            [
                "Actions",
                [
                    ["home", "Home", "Actions", "Home (trajectory)"],
                    ["dry", "Dry", "Actions", "Dry (trajectory)"],
                    ["soak", "Soak", "Actions", "Soak (trajectory)"],
                ],
            ],
            [
                "Recovery",
                [
                    [
                        "clear_memory",
                        "Clear Memory",
                        "Clear Info in Robot Memory "
                        " (includes info about sample on Diffr)",
                    ],
                    ["reset", "Reset Message", "Reset Cats State"],
                    ["back", "Back", "Reset Cats State"],
                    ["safe", "Safe", "Reset Cats State"],
                ],
            ],
            ["Abort", [["abort", "Abort", "Abort Execution of Command"]]],
        ]
        return cmd_list

    def _execute_server_task(self, method, *args):
        task_id = method(*args)
        ret = None
        # introduced wait because it takes some time before the attribute PathRunning is set
        # after launching a transfer
        # after setting refresh in the Tango DS to 0.1 s a wait of 1s is enough
        time.sleep(1.0)
        while str(self._chnPathRunning.getValue()).lower() == "true":
            gevent.sleep(0.1)
        ret = True
        return ret

    def send_command(self, cmdname, args=None):

        #
        lid = 1
        toolcal = 0
        tool = self.get_current_tool()

        if cmdname in ["dry", "safe", "home"]:
            if tool is not None:
                args = [tool]
            else:
                raise Exception(
                    "Cannot detect type of TOOL in Cats. Command ignored")

        if cmdname == "soak":
            if tool in [TOOL_DOUBLE, TOOL_UNIPUCK]:
                args = [str(tool), str(lid)]
            else:
                raise Exception("Can SOAK only when UNIPUCK tool is mounted")

        if cmdname == "back":
            if tool is not None:
                args = [tool, toolcal]
            else:
                raise Exception(
                    "Cannot detect type of TOOL in Cats. Command ignored")

        cmd = getattr(self.cats_device, cmdname)

        try:
            if args is not None:
                if len(args) > 1:
                    ret = cmd(map(str, args))
                else:
                    ret = cmd(*args)
            else:
                ret = cmd()
            return ret
        except Exception as exc:
            import traceback

            traceback.print_exc()
            msg = exc[0].desc
            raise Exception(msg)
Ejemplo n.º 17
0
class TangoChannel(ChannelObject):
    _tangoEventsQueue = Queue.Queue()
    _eventReceivers = {}
    _tangoEventsProcessingTimer = gevent.get_hub().loop.async()

    # start Tango events processing timer
    _tangoEventsProcessingTimer.start(processTangoEvents)

    def __init__(
        self,
        name,
        attribute_name,
        tangoname=None,
        username=None,
        polling=None,
        timeout=10000,
        **kwargs
    ):
        ChannelObject.__init__(self, name, username, **kwargs)

        self.attributeName = attribute_name
        self.deviceName = tangoname
        self.device = None
        self.value = Poller.NotInitializedValue
        self.polling = polling
        self.pollingTimer = None
        self.pollingEvents = False
        self.timeout = int(timeout)
        self.read_as_str = kwargs.get("read_as_str", False)
        self._device_initialized = gevent.event.Event()
        logging.getLogger("HWR").debug(
            "creating Tango attribute %s/%s, polling=%s, timeout=%d",
            self.deviceName,
            self.attributeName,
            polling,
            self.timeout,
        )
        self.init_device()
        self.continue_init(None)
        """
        self.init_poller = Poller.poll(self.init_device,
                                       polling_period = 3000,
                                       value_changed_callback = self.continue_init,
                                       error_callback = self.init_poll_failed,
                                       start_delay=100)
        """

    def init_poll_failed(self, e, poller_id):
        self._device_initialized.clear()
        logging.warning(
            "%s/%s (%s): could not complete init. (hint: device server is not running, or has to be restarted)",
            self.deviceName,
            self.attributeName,
            self.name(),
        )
        self.init_poller = self.init_poller.restart(3000)

    def continue_init(self, _):
        # self.init_poller.stop()

        if isinstance(self.polling, types.IntType):
            self.raw_device = RawDeviceProxy(self.deviceName)
            Poller.poll(
                self.poll,
                polling_period=self.polling,
                value_changed_callback=self.update,
                error_callback=self.pollFailed,
            )
        else:
            if self.polling == "events":
                # try to register event
                try:
                    self.pollingEvents = True
                    # logging.getLogger("HWR").debug("subscribing to CHANGE event for %s", self.attributeName)
                    self.device.subscribe_event(
                        self.attributeName,
                        PyTango.EventType.CHANGE_EVENT,
                        self,
                        [],
                        True,
                    )
                    # except PyTango.EventSystemFailed:
                    #   pass
                except BaseException:
                    logging.getLogger("HWR").exception("could not subscribe event")
        self._device_initialized.set()

    def init_device(self):
        try:
            self.device = DeviceProxy(self.deviceName)
        except PyTango.DevFailed as traceback:
            self.imported = False
            last_error = traceback[-1]
            logging.getLogger("HWR").error(
                "%s: %s", str(self.name()), last_error["desc"]
            )
        else:
            self.imported = True
            try:
                self.device.ping()
            except PyTango.ConnectionFailed:
                self.device = None
                raise ConnectionError
            else:
                self.device.set_timeout_millis(self.timeout)

                # check that the attribute exists (to avoid Abort in PyTango grrr)
                if not self.attributeName.lower() in [
                    attr.name.lower() for attr in self.device.attribute_list_query()
                ]:
                    logging.getLogger("HWR").error(
                        "no attribute %s in Tango device %s",
                        self.attributeName,
                        self.deviceName,
                    )
                    self.device = None

    def push_event(self, event):
        # logging.getLogger("HWR").debug("%s | attr_value=%s, event.errors=%s, quality=%s", self.name(), event.attr_value, event.errors,event.attr_value is None and "N/A" or event.attr_value.quality)
        if (
            event.attr_value is None
            or event.err
            or event.attr_value.quality != PyTango.AttrQuality.ATTR_VALID
        ):
            # logging.getLogger("HWR").debug("%s, receving BAD event... attr_value=%s, event.errors=%s, quality=%s", self.name(), event.attr_value, event.errors, event.attr_value is None and "N/A" or event.attr_value.quality)
            return
        else:
            pass
            # logging.getLogger("HWR").debug("%s, receiving good event", self.name())
        ev = E(event)
        TangoChannel._eventReceivers[id(ev)] = saferef.safe_ref(self.update)
        TangoChannel._tangoEventsQueue.put(ev)
        TangoChannel._tangoEventsProcessingTimer.send()

    def poll(self):
        if self.read_as_str:
            value = self.raw_device.read_attribute(
                self.attributeName, PyTango.DeviceAttribute.ExtractAs.String
            ).value
            # value = self.device.read_attribute_as_str(self.attributeName).value
        else:
            value = self.raw_device.read_attribute(self.attributeName).value

        return value

    def pollFailed(self, e, poller_id):
        self.emit("update", None)
        """
        emit_update = True
        if self.value is None:
          emit_update = False
        else:
          self.value = None

        try:
            self.init_device()
        except:
            pass

        poller = Poller.get_poller(poller_id)
        if poller is not None:
            poller.restart(1000)

        try:
          raise e
        except:
          logging.exception("%s: Exception happened while polling %s", self.name(), self.attributeName)

        if emit_update:
          # emit at the end => can raise exceptions in callbacks
          self.emit('update', None)
        """

    def getInfo(self):
        self._device_initialized.wait(timeout=3)
        return self.device.get_attribute_config(self.attributeName)

    def update(self, value=Poller.NotInitializedValue):
        if value == Poller.NotInitializedValue:
            value = self.getValue()
        if isinstance(value, types.TupleType):
            value = list(value)

        self.value = value
        self.emit("update", value)

    def getValue(self):
        self._device_initialized.wait(timeout=3)

        if self.read_as_str:
            value = self.device.read_attribute(
                self.attributeName, PyTango.DeviceAttribute.ExtractAs.String
            ).value
        else:
            value = self.device.read_attribute(self.attributeName).value

        return value

    def setValue(self, newValue):
        self.device.write_attribute(self.attributeName, newValue)
        # attr = PyTango.AttributeProxy(self.deviceName + "/" + self.attributeName)
        # a = attr.read()
        # a.value = newValue
        # attr.write(a)

    def isConnected(self):
        return self.device is not None
class TangoMotorZoomPX2(Device):
    
    stateDict = {
         "UNKNOWN": 0,
         "ALARM":   1,
         "FAULT":   1,
         "STANDBY": 2,
         "RUNNING": 4,
         "MOVING":  4,
         "ON": 2,
         '2':         2}


    def __init__(self, name):
        Device.__init__(self, name)
        self.GUIstep = 0.1

    def _init(self):
        
        self.MOVESTARTED = 0
        self.NOTINITIALIZED = 0
        self.UNUSABLE = 0
        self.READY = 2
        self.MOVING = 4
        self.ONLIMIT = 1

        #self.device = SimpleDevice(self.getProperty("tangoname"), verbose=False)
        #self.device.timeout = 6000 # Setting timeout to 6 sec
        self.device = DeviceProxy(self.getProperty("tangoname"))
        self.device.waitMoves = False
        logging.getLogger("HWR").info("TangoMotorZoomPX2._init of device %s" % self.device.name)
        self.setIsReady(True)
        print "TangoMotorZoomPX2._init of device %s" % self.device.name
        positionChan = self.getChannelObject("position") # utile seulement si statechan n'est pas defini dans le code
        positionChan.connectSignal("update", self.positionChanged) 
        #focus_positionChan = self.getChannelObject("focus_position")
        #focus_positionChan.connectSignal("update", self.positionChanged)
        stateChan = self.getChannelObject("state") # utile seulement si statechan n'est pas defini dans le code
        stateChan.connectSignal("update", self.motorStateChanged) 
        
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2._init, %s", self.name(), '')
        

    def positionChanged(self, value):
        try:
            logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.positionChanged: %.3f", self.name(), value)
        except:
            logging.getLogger("HWR").error("%s: TangoMotor not responding, %s", self.name(), '')
        
        self.emit('positionChanged', (value,))
    
    def isReady(self):
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.isReady", self.name())
        return str(self.device.State()) == 'STANDBY'
        
        
    def connectNotify(self, signal):
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.connectNotify, : %s", self.name(), signal)
        if signal == 'hardwareObjectName,stateChanged':
            self.motorStateChanged(TangoMotorZoomPX2.stateDict[str(self.device.State())])
        elif signal == 'limitsChanged':
            self.motorLimitsChanged()
            #print "Not implemented yet."PhiTableXAxisPosition
            
        elif signal == 'positionChanged':
            #self.motorPositionChanged(self.device.position)
            print 'MS debug 18.10.2012'
            #print self.device
            print self.device.read_attribute("ZoomLevel").value
            self.motorPositionChanged(self.device.read_attribute("ZoomLevel").value) #MS debug 18.10.2012
            
        self.setIsReady(True)
    
    def motorState(self):
        return TangoMotorZoomPX2.stateDict[str(self.device.State())]
    
    def motorStateChanged(self, state):
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.motorStateChanged, %s", self.name(), state)
        #self.setIsReady(state == 'STANDBY')
        self.setIsReady(True)
        #print "motorStateChanged", str(state)
        self.emit('stateChanged', (TangoMotorZoomPX2.stateDict[str(self.device.State())], ))
        
    def getState(self):
        state = str(self.device.State())
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.getState, %s", self.name(), state)
        return TangoMotorZoomPX2.stateDict[str(self.device.State())]
    
    def getLimits(self):
        #limits = self.device.getLimits("positiopositionChan.connectSignal("update", self.positionChanged)n")
        # MS 18.09.2012 adapted for use without SimpleDevice
        position_info = self.device.attribute_query("ZoomLevel")
        rlow  = 1 # position_info.min_value
        rhigh = 10 #position_info.max_value
        #logging.getLogger("HWR").info("TangoMotorZoomPX2.getLimits: %.4f %.4f" % limits)
        return rlow, rhigh
        
    def motorLimitsChanged(self):
        #self.emit('limitsChanged', (self.getLimits(), ))
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.limitsChanged", self.name())
        self.emit('limitsChanged', (self.getLimits(), )) 
                      
    def motorMoveDone(self, channelValue):
       #SpecMotorA.motorMoveDone(self, channelValue)
       #logging.getLogger("HWR").info("TangoMotorZoomPX2.motorMoveDone")
       if str(self.device.State()) == 'STANDBY':
           
          #self.emit('moveDone', (self.specversion, self.specname, ))
          self.emit('moveDone', ("EH3","toto" ))
          
    def motorPositionChanged(self, absolutePosition):
        self.emit('positionChanged', (absolutePosition, ))

    def syncQuestionAnswer(self, specSteps, controllerSteps):
        return '0' #NO ('1' means YES)
    
    def getPosition(self):
        pos = self.device.read_attribute("ZoomLevel").value #self.device.position
        #logging.getLogger("HWR").info("%s: TangoMotorZoomPX2.getPosition, pos = %.3f", self.name(), pos)
        return pos
    
    def syncMove(self, position):
        #print 'about to start moving', self.motorState
        t0 = time.time()
        prev_position =  self.getPosition()
        self.device.position = position

        print 'move started from %s to %s, state is %s' % (prev_position, position, str(self.device.State()))
        
        while str(self.device.State()) == "RUNNING" or str(self.device.State()) == "MOVING": # or str(self.device.State()) == SpecMotor.MOVESTARTED:
            #print 'processing events...', self.motorState
            qApp.processEvents(100)

        print 'move done (%s s), state is %s' % (time.time()-t0,  str(self.device.State()))
        
    def moveRelative(self, position):
        old_pos = self.device.position
        self.device.position = old_pos + position
        #self.moveRelahardwareObjectName,tive(position)

        while str(self.device.State()) == "RUNNING" or str(self.device.State()) == "MOVING":
            qApp.processEvents(100)
        
    def syncMoveRelative(self, position):
        old_pos = self.device.position
        self.device.position = old_pos + position
        #self.moveRelahardwareObjectName,tive(position)

        while str(self.device.State()) == "RUNNING" or str(self.device.State()) == "MOVING":
            qApp.processEvents(100)
        

    def getMotorMnemonic(self):
        return self.specName

    def move(self, absolutePosition):
        """Move the motor to the required position

        Arguments:
        absolutePosition -- position to move to
        """
        if type(absolutePosition) != float and type(absolutePosition) != int:
            logging.getLogger("TangoClient").error("Cannot move %s: position '%s' is not a number", self.device.name, absolutePosition)
            
        #self.__changeMotorState(MOVESTARTED)

        #c = self.connection.getChannel(self.chanNamePrefix % 'start_one')
        logging.getLogger("HWR").info("TangoMotorZoomPX2.move to absolute position: %.3f" % absolutePosition)
        self.device.position = absolutePosition
        
    def stop(self):
        logging.getLogger("HWR").info("TangoMotorZoomPX2.stop")
        self.device.Stop()

    def isSpecConnected(self):
        logging.getLogger().debug("%s: TangoMotorZoomPX2.isSpecConnected()" % self.name())
        return TruehardwareObjectName,
Ejemplo n.º 19
0
class TangoConnector(Connector):

    value_changed = pyqtSignal(str, name="valueChanged")

    def __init__(self,
                 uri=None,
                 attributes=[],
                 policy=UpdatePolicy.POLLING,
                 interval=1.0):
        #QThread.__init__(self)
        self.alive = False
        self.connected = False
        self.poll_attributes = {}
        self.thread = threading.Thread(target=self.run, name=uri)
        try:
            self.proxy = DeviceProxy(uri)
            self.connected = True
        except:
            self.attributes["state"]["value"] = State.UNKNOWN
            self.janus.utils["logger"].error("TangoConnector(" + self.uri +
                                             ").__init__() " +
                                             "connection failed")
            self.janus.utils["logger"].debug("", exc_info=True)
        Connector.__init__(self, uri, attributes, policy, interval)

    def add_attribute(self, attribute=None):
        Connector.add_attribute(self, attribute=attribute)
        if type(attribute) is not dict or "attr" not in attribute:
            return
        if "mode" in attribute and attribute["mode"] == "execute":
            return
        if "name" in attribute:
            name = attribute["name"]
        else:
            name = attribute["attr"].lower()
        self.poll_attributes[attribute["attr"]] = name

    def update_policy(self, policy=UpdatePolicy.POLLING, interval=1.0):
        self.interval = interval
        if policy != UpdatePolicy.POLLING and self.isRunning():
            self.stop()
        elif policy != UpdatePolicy.EVENTBASED:
            for attr in self.attributes.keys():
                if "event" not in self.attributes[attr]:
                    continue
                try:
                    self.proxy.unsubscribe_event(
                        self.attributes[attr]["event"])
                except:
                    self.janus.utils["logger"].error(
                        "TangoConnector(" + self.uri + ").update_policy() " +
                        "failed to unsubscribe from tango event")
                    self.janus.utils["logger"].debug("", exc_info=True)
                del self.attributes[attr]["event"]
        if policy == UpdatePolicy.POLLING and not self.thread.is_alive():
            self.thread.start()
        elif policy == UpdatePolicy.EVENTBASED:
            for attr in self.attributes.keys:
                try:
                    self.attributes[attr]["event"] = \
                        self.proxy.subscribe_event(EventType.CHANGE_EVENT, \
                                self.on_tango_event, [], False)
                except:
                    self.janus.utils["logger"].error(
                        "TangoConnector(" + self.uri + ").update_policy() " +
                        "failed to subscribe to tango event")
                    self.janus.utils["logger"].debug("", exc_info=True)
        self.policy = policy

    def on_tango_event(self, event):
        try:
            name = event.attr_name
            value = event.attr_value.value
        except:
            self.janus.utils["logger"].warning("TangoConnector(" + self.uri +
                                               ").on_tango_event() " +
                                               "invalid tango event type")
            self.janus.utils["logger"].debug("", exc_info=True)
        self.attributes[self.poll_attributes[name]]["value"] = value
        self.value_changed.emit(self.poll_attributes[name])

    def stop_device(self):
        self.stop()

    def stop(self):
        self.alive = False
        self.thread.join()
        pass

    def run(self):
        print("thread started: {} ({})".format(
            threading.get_ident(),
            threading.currentThread().getName()))
        self.alive = True
        while self.alive:
            #remember when we started
            timestamp = time.time()
            #try to poll attributes
            try:
                attrs = self.proxy.read_attributes(
                    list(self.poll_attributes.keys()))
            except:
                self.attributes["state"]["value"] = State.UNKNOWN
                self.janus.utils["logger"].error(
                    "TangoConnector(" + self.uri + ").run() " +
                    "reading tango attributes failed")
                self.janus.utils["logger"].debug("", exc_info=True)
                attrs = []
            #assign attribute values and fire change signal if necessary
            for attr in attrs:
                name = self.poll_attributes[attr.name]
                changed = False
                if "delta" in self.attributes[name]:
                    if self.attributes[name]["value"] is None or \
                            abs(self.attributes[name]["value"] - attr.value) > \
                            self.attributes[name]["delta"]:
                        changed = True
                elif name == "state" and \
                        int(self.attributes[name]["value"]) != int(attr.value):
                    changed = True
                elif name == "image_8":
                    changed = True
                elif self.attributes[name]["value"] != attr.value:
                    changed = True
                if changed:
                    if name == "state":
                        self.attributes[name]["value"] = State(int(attr.value))
                    else:
                        self.attributes[name]["value"] = attr.value
                    self.value_changed.emit(name)
                if not self.alive:
                    break
            #wait for the rest of the polling interval
            interval = int((self.interval - (time.time() - timestamp)))
            while interval > 0:
                if interval > 0.05:
                    time.sleep(0.05)
                    interval -= 0.05
                else:
                    time.sleep(interval)
                    interval = 0
                if not self.alive:
                    break
        print("closing thread: {} ({})".format(
            threading.get_ident(),
            threading.currentThread().getName()))

    def state(self, refresh=False):
        if refresh:
            try:
                self.attributes["state"]["value"] = State(
                    int(self.proxy.state()))
            except:
                self.attributes["state"]["value"] = State.UNKNOWN
                self.janus.utils["logger"].error("TangoConnector(" + self.uri +
                                                 ").state() " +
                                                 "reading tango state failed")
                self.janus.utils["logger"].debug("", exc_info=True)
        return self.attributes["state"]["value"]

    def read(self, attribute=None, refresh=False, alt=None):
        if refresh or self.attributes[attribute]["value"] is None:
            try:
                self.attributes[attribute]["value"] = \
                    self.proxy.read_attribute(self.attributes[attribute]["attr"]).value
            except:
                self.janus.utils["logger"].error(
                    "TangoConnector(" + self.uri + ")" + ".read(" + attribute +
                    ") " + "reading tango attribute failed")
                self.janus.utils["logger"].debug("", exc_info=True)
                if self.attributes[attribute]["value"] is None \
                        and alt is not None:
                    return alt
        return self.attributes[attribute]["value"]

    def write(self, attribute=None, value=None):
        try:
            self.proxy.write_attribute(self.attributes[attribute]["attr"],
                                       value)
            return True
        except:
            self.janus.utils["logger"].error("TangoConnector(" + self.uri +
                                             ")" + ".write(" + attribute +
                                             ") " +
                                             "writing tango attribute failed")
            self.janus.utils["logger"].debug("", exc_info=True)
            return False

    def execute(self, command=None, *values):
        try:
            if len(values) == 0:
                value = self.proxy.command_inout(
                    self.attributes[command]["attr"])
            else:
                value = self.proxy.command_inout(
                    self.attributes[command]["attr"], values)
        except Exception as e:
            self.janus.utils["logger"].error("TangoConnector(" + self.uri +
                                             ")" + ".execute(" + command +
                                             ") " +
                                             "executing tango command failed")
            self.janus.utils["logger"].debug("", exc_info=True)
            return None
        return value