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
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
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
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)
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)
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))
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))
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
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)
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()
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()
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,
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
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
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)
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,
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