class FlexHCD(SampleChanger): __TYPE__ = "HCD" def __init__(self, *args, **kwargs): super(FlexHCD, self).__init__(self.__TYPE__, True, *args, **kwargs) def init(self): sc3_pucks = self.getProperty("sc3_pucks", True) for i in range(8): cell = Cell(self, i + 1, sc3_pucks) self._add_component(cell) self.robot = self.getProperty("tango_device") if self.robot: self.robot = DeviceProxy(self.robot) self.exporter_addr = self.getProperty("exporter_address") """ if self.exporter_addr: self.swstate_attr = self.add_channel( { "type": "exporter", "exporter_address": self.exporter_addr, "name": "swstate", }, "State", ) """ self.controller = self.getObjectByRole("controller") self.prepareLoad = self.get_command_object("moveToLoadingPosition") self.timeout = 3 self.gripper_types = { -1: "No Gripper", 1: "UNIPUCK", 2: "MINISPINE", 3: "FLIPPING", 4: "UNIPUCK_DOUBLE", 5: "PLATE", } return SampleChanger.init(self) @task def prepare_load(self): if self.controller: self.controller.hutch_actions(condition=True) else: self.prepareLoad() @task def _prepare_centring_task(self): if self.controller: self.controller.hutch_actions(condition=False, sc_loading=True) else: gevent.sleep(2) self.get_command_object("unlockMinidiffMotors")(wait=True) self.get_command_object("prepareCentring")(wait=True) def prepare_centring(self): self._prepare_centring_task() def get_sample_properties(self): return (Pin.__HOLDER_LENGTH_PROPERTY__,) def get_basket_list(self): basket_list = [] # put here only the baskets that exist, not all the possible ones # if self.exporter_addr: # basket_list = for cell in self.get_components(): for basket in cell.get_components(): if isinstance(basket, Basket): basket_list.append(basket) return basket_list def _do_change_mode(self, *args, **kwargs): return def _do_update_info(self): # self._update_selection() self._update_state() def _do_scan(self, component, recursive=True, saved={"barcodes": None}): return def _execute_cmd(self, cmd, *args, **kwargs): timeout = kwargs.pop("timeout", None) if args: cmd_str = "flex.%s(%s)" % (cmd, ",".join(map(repr, args))) else: cmd_str = "flex.%s()" % cmd cmd_id = self.robot.eval(cmd_str) if not cmd_id: cmd_id = self.robot.eval(cmd_str) with gevent.Timeout( timeout, RuntimeError("Timeout while executing %s" % repr(cmd_str)) ): while True: if self.robot.is_finished(cmd_id): break gevent.sleep(0.2) res = self.robot.get_result(cmd_id) if res: res = pickle.loads(base64.decodestring(res)) if isinstance(res, Exception): raise res else: return res def _execute_cmd_exporter(self, cmd, *args, **kwargs): ret = None timeout = kwargs.pop("timeout", 900) if args: args_str = "%s" % "\t".join(map(repr, args)) if kwargs.pop("command", None): exp_cmd = self.add_command( { "type": "exporter", "exporter_address": self.exporter_addr, "name": "%s" % cmd, }, "%s" % cmd, ) if args: ret = exp_cmd(args_str) else: ret = exp_cmd() if kwargs.pop("attribute", None): exp_attr = self.add_channel( { "type": "exporter", "exporter_address": self.exporter_addr, "name": "%s" % cmd, }, "%s" % cmd[3:], ) if cmd.startswith("get"): return exp_attr.getValue() if cmd.startswith("set"): ret = exp_attr.setValue(args_str) self._wait_ready(timeout=timeout) return ret def _ready(self): # return self.swstate_attr.getValue() == "Ready" return True def _wait_ready(self, timeout=None): err_msg = "Timeout waiting for sample changer to be ready" # None means infinite timeout <=0 means default timeout if timeout is not None and timeout <= 0: timeout = self.timeout with gevent.Timeout(timeout, RuntimeError(err_msg)): while not self._ready(): time.sleep(0.5) def _do_select(self, component): if isinstance(component, Cell): cell_pos = component.get_index() + 1 elif isinstance(component, Basket) or isinstance(component, Pin): cell_pos = component.get_cell_no() if self.exporter_addr: self._execute_cmd_exporter("moveDewar", cell_pos, command=True) else: self._execute_cmd("moveDewar", cell_pos) self._update_selection() @task def load_sample( self, holderLength, sample_id=None, sample_location=None, sampleIsLoadedCallback=None, failureCallback=None, prepareCentring=True, ): cell, basket, sample = sample_location sample = self.get_component_by_address(Pin.get_sample_address(cell, basket, sample)) return self.load(sample) def chained_load(self, old_sample, sample): if self.exporter_addr: unload_load_task = gevent.spawn( self._execute_cmd_exporter, "load_sample", sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no(), command=True, ) else: unload_load_task = gevent.spawn( self._execute_cmd, "chainedUnldLd", [ old_sample.get_cell_no(), old_sample.get_basket_no(), old_sample.get_vial_no(), ], [sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no()], ) gevent.sleep(15) err_msg = "Timeout waiting for sample changer to be in safe position" while not unload_load_task.ready(): if self.exporter_addr: loading_state = self._execute_cmd_exporter( "getCurrentLoadSampleState", attribute=True ) if "on_gonio" in loading_state: self._set_loaded_sample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while not self._execute_cmd_exporter( "getRobotIsSafe", attribute=True ): gevent.sleep(0.5) return True else: loading_state = str( self._execute_cmd("sampleStatus", "LoadSampleStatus") ) if "on_gonio" in loading_state: self._set_loaded_sample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while ( not self._execute_cmd( "get_robot_cache_variable", "data:dioRobotIsSafe" ) == "true" ): gevent.sleep(0.5) return True gevent.sleep(1) logging.getLogger("HWR").info("unload load task done") for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) return self._check_pin_on_gonio() def _check_pin_on_gonio(self): if self.exporter_addr: _on_gonio = self._execute_cmd_exporter("pin_on_gonio", command=True) else: _on_gonio = self._execute_cmd("pin_on_gonio") if _on_gonio: # finish the loading actions self._prepare_centring_task() return True else: logging.getLogger("HWR").info("reset loaded sample") self._reset_loaded_sample() # if self.controller: # self.controller.hutch_actions(release_interlock=True) return False def reset_loaded_sample(self): if self.exporter_addr: self._execute_cmd_exporter("reset_loaded_position", command=True) else: self._execute_cmd("reset_loaded_position") self._reset_loaded_sample() def get_robot_exceptions(self): if self.exporter_addr: """ return self._execute_cmd_exporter('getRobotExceptions', attribute=True) """ return "" else: return self._execute_cmd("getRobotExceptions") @task def load(self, sample): self.prepare_load(wait=True) self.enable_power() try: res = SampleChanger.load(self, sample) finally: for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) if res: self.prepare_centring() return res @task def unload_sample( self, holderLength, sample_id=None, sample_location=None, successCallback=None, failureCallback=None, ): cell, basket, sample = sample_location sample = self.get_component_by_address(Pin.get_sample_address(cell, basket, sample)) return self.unload(sample) @task def unload(self, sample): self.prepare_load(wait=True) self.enable_power() try: SampleChanger.unload(self, sample) finally: for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) def get_gripper(self): if self.exporter_addr: gripper_type = self._execute_cmd_exporter( "get_gripper_type", attribute=True ) else: gripper_type = self._execute_cmd("get_gripper_type") return self.gripper_types.get(gripper_type, "?") def get_available_grippers(self): grippers = [] if self.exporter_addr: ret = sorted( self._execute_cmd_exporter("getSupportedGrippers", attribute=True) ) for gripper in ret: grippers.append(self.gripper_types[gripper]) return grippers @task def change_gripper(self, gripper=None): self.prepare_load(wait=True) self.enable_power() if self.exporter_addr: if gripper: self._execute_cmd_exporter("setGripper", gripper, command=True) else: self._execute_cmd_exporter("changeGripper", command=True) else: self._execute_cmd("changeGripper") @task def home(self): self.prepare_load(wait=True) self.enable_power() if self.exporter_addr: self._execute_cmd_exporter("homeClear", command=True) else: self._execute_cmd("homeClear") @task def enable_power(self): if not self.exporter_addr: self._execute_cmd("enablePower", 1) @task def defreeze(self): self.prepare_load(wait=True) self.enable_power() if self.exporter_addr: self._execute_cmd_exporter("defreezeGripper", command=True) else: self._execute_cmd("defreezeGripper") def _do_load(self, sample=None): self._update_state() if self.exporter_addr: load_task = gevent.spawn( self._execute_cmd_exporter, "load_sample", sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no(), command=True, ) else: load_task = gevent.spawn( self._execute_cmd, "load_sample", sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no(), ) gevent.sleep(5) err_msg = "Timeout waiting for sample changer to be in safe position" while not load_task.ready(): if self.exporter_addr: loading_state = self._execute_cmd_exporter( "getCurrentLoadSampleState", attribute=True ) if "on_gonio" in loading_state: self._set_loaded_sample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while not self._execute_cmd_exporter( "getRobotIsSafe", attribute=True ): gevent.sleep(0.5) return True else: loading_state = str( self._execute_cmd("sampleStatus", "LoadSampleStatus") ) if "on_gonio" in loading_state: self._set_loaded_sample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while ( not self._execute_cmd( "get_robot_cache_variable", "data:dioRobotIsSafe" ) == "true" ): gevent.sleep(0.5) return True gevent.sleep(1) if self.exporter_addr: loaded_sample = self._execute_cmd_exporter( "get_loaded_sample", attribute=True ) else: loaded_sample = self._execute_cmd("get_loaded_sample") if loaded_sample == ( sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no(), ): self._set_loaded_sample(sample) return True return self._check_pin_on_gonio() def _do_unload(self, sample=None): loaded_sample = self.get_loaded_sample() if loaded_sample is not None and loaded_sample != sample: raise RuntimeError("Cannot unload another sample") if self.exporter_addr: self._execute_cmd_exporter( "unload_sample", sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no(), command=True, ) loaded_sample = self._execute_cmd_exporter( "get_loaded_sample", attribute=True ) else: self._execute_cmd( "unload_sample", sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no(), ) loaded_sample = self._execute_cmd("get_loaded_sample") if loaded_sample == (-1, -1, -1): self._reset_loaded_sample() if self.controller: self.controller.hutch_actions(release_interlock=True) return True return False def _do_abort(self): if self.exporter_addr: self._execute_cmd_exporter("abort", command=True) else: self._execute_cmd("abort") def _do_reset(self): if self.exporter_addr: self._execute_cmd_exporter("homeClear", command=True) else: self._execute_cmd("homeClear") def clear_basket_info(self, basket): return self._reset_basket_info(basket) def _reset_basket_info(self, basket): pass def clear_cell_info(self, cell): return self._reset_cell_info(cell) def _reset_cell_info(self, cell): pass def _update_state(self): # see if the command exists for exporter if not self.exporter_addr: defreezing = self._execute_cmd("isDefreezing") if defreezing: self._set_state(SampleChangerState.Ready) try: state = self._read_state() except Exception: state = SampleChangerState.Unknown self._set_state(state) def is_sequencer_ready(self): if self.prepareLoad: cmdobj = self.get_command_object return all( [cmd.isSpecReady() for cmd in (cmdobj("moveToLoadingPosition"),)] ) return True def _read_state(self): # should read state from robot if self.exporter_addr: # state = self.swstate_attr.get_value().upper() state = self._execute_cmd_exporter("State", attrubute=True) else: state = "RUNNING" if self._execute_cmd("robot.isBusy") else "STANDBY" if state == "STANDBY" and not self.is_sequencer_ready(): state = "RUNNING" state = "READY" state_converter = { "ALARM": SampleChangerState.Alarm, "FAULT": SampleChangerState.Fault, "RUNNING": SampleChangerState.Moving, "READY": SampleChangerState.Ready, "STANDBY": SampleChangerState.Ready, } return state_converter.get(state, SampleChangerState.Unknown) def _is_device_busy(self, state=None): if state is None: state = self._read_state() return state not in ( SampleChangerState.Ready, SampleChangerState.Loaded, SampleChangerState.Alarm, SampleChangerState.Disabled, SampleChangerState.Fault, SampleChangerState.StandBy, ) def _is_device_ready(self): state = self._read_state() return state in (SampleChangerState.Ready, SampleChangerState.Charging) def _wait_device_ready(self, timeout=None): with gevent.Timeout(timeout, Exception("Timeout waiting for device ready")): while not self._is_device_ready(): gevent.sleep(0.01) def _update_selection(self): if self.exporter_addr: sample_cell, sample_puck, sample = self._execute_cmd_exporter( "get_loaded_sample", attribute=True ) cell = sample_cell puck = sample_puck else: cell, puck = self._execute_cmd("get_cell_position") sample_cell, sample_puck, sample = self._execute_cmd("get_loaded_sample") for c in self.get_components(): i = c.get_index() if cell == i + 1: self._set_selected_component(c) break # find sample for s in self.get_sample_list(): if s.get_coords() == (sample_cell, sample_puck, sample): self._set_loaded_sample(s) # self._set_selected_sample(s) return for s in self.get_sample_list(): s._set_loaded(False) self._set_selected_sample(None) def prepare_hutch(self, **kwargs): if self.exporter_addr: return user_port = kwargs.get("user_port") robot_port = kwargs.get("robot_port") if user_port is not None: self._execute_cmd("robot.user_port(user_port)") if robot_port is not None: self._execute_cmd("robot.robot_port(robot_port)")
class EMBLFlexHCD(SampleChanger): __TYPE__ = "HCD" def __init__(self, *args, **kwargs): super(EMBLFlexHCD, self).__init__(self.__TYPE__, True, *args, **kwargs) def init(self): sc3_pucks = self.getProperty("sc3_pucks", True) for i in range(8): cell = Cell(self, i + 1, sc3_pucks) self._add_component(cell) self.robot = self.getProperty("tango_device") if self.robot: self.robot = DeviceProxy(self.robot) self.exporter_addr = self.getProperty("exporter_address") self.swstate_attr = self.add_channel( { "type": "exporter", "exporter_address": self.exporter_addr, "name": "swstate", }, "State", ) self.controller = self.getObjectByRole("controller") self.prepareLoad = self.get_command_object("moveToLoadingPosition") self.timeout = 3 self.gripper_types = { -1: "No Gripper", 1: "UNIPUCK", 2: "MINISPINE", 3: "FLIPPING", 4: "UNIPUCK_DOUBLE", 5: "PLATE", } SampleChanger.init(self) # self._set_state(SampleChangerState.Disabled) self._update_selection() self.state = self._read_state() def get_sample_list(self): sample_list = super().get_sample_list() sc_present_sample_list = self._execute_cmd_exporter( "getPresentSamples", attribute=True).split(":") present_sample_list = [] for sample in sample_list: for present_sample_str in sc_present_sample_list: present_sample = present_sample_str.split(",") if sample.get_address() == (str(present_sample[0]) + ":" + str(present_sample[1]) + ":" + "%02d" % int(present_sample[4])): present_sample_list.append(sample) return present_sample_list @task def prepare_load(self): if self.controller: self.controller.hutch_actions(enter=True) else: self.prepareLoad() @task def _prepare_centring_task(self): if self.controller: #gevent.sleep(2) self.controller.hutch_actions(enter=False, sc_loading=True) else: gevent.sleep(2) self.get_command_object("unlockMinidiffMotors")(wait=True) self.get_command_object("prepareCentring")(wait=True) def prepare_centring(self): self._prepare_centring_task() def get_sample_properties(self): return (Pin.__HOLDER_LENGTH_PROPERTY__, ) def get_basket_list(self): basket_list = [] # put here only the baskets that exist, not all the possible ones for cell in self.get_components(): for basket in cell.get_components(): if isinstance(basket, Basket): basket_list.append(basket) return basket_list def _do_change_mode(self, *args, **kwargs): return def _do_update_info(self): # self._update_selection() self._update_state() def _do_scan(self, component, recursive=True, saved={"barcodes": None}): return def _execute_cmd(self, cmd, *args, **kwargs): timeout = kwargs.pop("timeout", None) if args: cmd_str = "flex.%s(%s)" % (cmd, ",".join(map(repr, args))) else: cmd_str = "flex.%s()" % cmd cmd_id = self.robot.eval(cmd_str) if not cmd_id: cmd_id = self.robot.eval(cmd_str) with gevent.Timeout( timeout, RuntimeError("Timeout while executing %s" % repr(cmd_str))): while True: if self.robot.is_finished(cmd_id): break gevent.sleep(0.2) res = self.robot.get_result(cmd_id) if res: res = pickle.loads(base64.b64decode(res)) if isinstance(res, Exception): raise res else: return res def _execute_cmd_exporter(self, cmd, *args, **kwargs): ret = None timeout = kwargs.pop("timeout", 900) if args: args_str = "%s" % "\t".join(map(repr, args)) if kwargs.pop("command", None): exp_cmd = self.add_command( { "type": "exporter", "exporter_address": self.exporter_addr, "name": "%s" % cmd, }, "%s" % cmd, ) if args: ret = exp_cmd(args_str) else: ret = exp_cmd() if kwargs.pop("attribute", None): exp_attr = self.add_channel( { "type": "exporter", "exporter_address": self.exporter_addr, "name": "%s" % cmd, }, "%s" % cmd[3:], ) if cmd.startswith("get"): return exp_attr.get_value() if cmd.startswith("set"): ret = exp_attr.set_value(args_str) self._wait_ready(timeout=timeout) return ret def _assert_ready(self): if not self._ready(): raise RuntimeError("Sample changer is busy cant mount/unmount") def _ready(self): return self._execute_cmd_exporter("getState", attribute=True) == "Ready" def _busy(self): return self._execute_cmd_exporter("getState", attribute=True) != "Ready" def _wait_ready(self, timeout=None): # None means wait forever timeout <=0 use default timeout if timeout is not None and timeout <= 0: timeout = self.timeout err_msg = "Timeout waiting for sample changer to be ready" with gevent.Timeout(timeout, RuntimeError(err_msg)): while not self._ready(): gevent.sleep(0.5) def _wait_busy(self, timeout=None): # None means wait forever timeout <=0 use default timeout if timeout is not None and timeout <= 0: timeout = self.timeout err_msg = "Timeout waiting for sample changer action to start" with gevent.Timeout(timeout, RuntimeError(err_msg)): while not self._busy(): gevent.sleep(0.5) def _do_select(self, component): if isinstance(component, Cell): cell_pos = component.get_index() + 1 elif isinstance(component, Basket) or isinstance(component, Pin): cell_pos = component.get_cell_no() self._execute_cmd_exporter("moveDewar", cell_pos, command=True) self._update_selection() @task def load_sample( self, holderLength, sample_id=None, sample_location=None, sampleIsLoadedCallback=None, failureCallback=None, prepareCentring=True, ): # self._assert_ready() cell, basket, sample = sample_location sample = self.get_component_by_address( Pin.get_sample_address(cell, basket, sample)) return self.load(sample) def chained_load(self, old_sample, sample): return self._do_load(sample) def _set_loaded_sample_and_prepare(self, sample): res = False if not -1 in sample: self._set_loaded_sample(self.get_sample_with_address(sample)) self._prepare_centring_task() res = True return res def _hw_get_mounted_sample(self): loaded_sample = tuple( self._execute_cmd_exporter("getMountedSamplePosition", attribute=True)) return (str(loaded_sample[0]) + ":" + str(loaded_sample[1]) + ":" + "%02d" % loaded_sample[2]) def get_loaded_sample(self): sample = None loaded_sample_addr = self._hw_get_mounted_sample() for s in self.get_sample_list(): if s.get_address() == loaded_sample_addr: sample = s return sample def get_sample_with_address(self, address): sample = None address = str(address[0]) + ":" + str( address[1]) + ":" + "%02d" % address[2] for s in self.get_sample_list(): if s.get_address() == address: sample = s return sample def reset_loaded_sample(self): self._execute_cmd_exporter("resetLoadedPosition", command=True) self._reset_loaded_sample() def get_robot_exceptions(self): return [ self._execute_cmd_exporter('getLastTaskException', attribute=True) ] or [""] @task def load(self, sample): self.prepare_load(wait=True) self.enable_power() try: res = SampleChanger.load(self, sample) finally: for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) if res: self.prepare_centring() return res @task def unload_sample( self, holderLength, sample_id=None, sample_location=None, successCallback=None, failureCallback=None, ): self._assert_ready() cell, basket, sample = sample_location sample = self.get_component_by_address( Pin.get_sample_address(cell, basket, sample)) return self.unload(sample) @task def unload(self, sample): self.prepare_load(wait=True) self.enable_power() if not sample: sample = self._hw_get_mounted_sample() try: SampleChanger.unload(self, sample) finally: for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) def get_gripper(self): gripper_type = self._execute_cmd_exporter("get_gripper_type", attribute=True) return self.gripper_types.get(gripper_type, "?") def get_available_grippers(self): grippers = [] try: ret = sorted( self._execute_cmd_exporter("getSupportedGrippers", attribute=True)) for gripper in ret: grippers.append(self.gripper_types[gripper]) except Exception: grippers = [-1] return grippers @task def change_gripper(self, gripper=None): self.prepare_load(wait=True) self.enable_power() if gripper: self._execute_cmd_exporter("setGripper", gripper, command=True) else: self._execute_cmd_exporter("changeGripper", command=True) @task def home(self): self.prepare_load(wait=True) self.enable_power() self._execute_cmd_exporter("homeClear", command=True) @task def enable_power(self): if not self.exporter_addr: self._execute_cmd("enablePower", 1) @task def defreeze(self): self.prepare_load(wait=True) self.enable_power() self._execute_cmd_exporter("defreezeGripper", command=True) def _do_load(self, sample=None): self._update_state() # We wait for the sample changer if its already doing something, like defreezing # wait for 6 minutes then timeout ! self._wait_ready(600) # Start loading load_task = gevent.spawn( self._execute_cmd_exporter, "loadSample", sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no(), command=True, ) # Wait for sample changer to start activity self._wait_busy(30) # Wait for the sample to be loaded, (put on the goniometer) err_msg = "Timeout while waiting to sample to be loaded" with gevent.Timeout(600, RuntimeError(err_msg)): while not load_task.ready(): loaded_sample = tuple( self._execute_cmd_exporter("getMountedSamplePosition", attribute=True)) if loaded_sample == ( sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no(), ): break gevent.sleep(2) with gevent.Timeout(600, RuntimeError(err_msg)): while True: is_safe = self._execute_cmd_exporter("getRobotIsSafe", attribute=True) if is_safe: break gevent.sleep(2) for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) return self._set_loaded_sample_and_prepare(loaded_sample) def _do_unload(self, sample=None): self._execute_cmd_exporter( "unloadSample", sample.get_cell_no(), sample.get_basket_no(), sample.get_vial_no(), command=True, ) loaded_sample = tuple( self._execute_cmd_exporter("getMountedSamplePosition", attribute=True)) for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) if loaded_sample == (-1, -1, -1): self._reset_loaded_sample() if self.controller: self.controller.hutch_actions(release_interlock=True) return True return False def _do_abort(self): self._execute_cmd_exporter("abort", command=True) def _do_reset(self): self._execute_cmd_exporter("homeClear", command=True) def clear_basket_info(self, basket): return self._reset_basket_info(basket) def _reset_basket_info(self, basket): pass def clear_cell_info(self, cell): return self._reset_cell_info(cell) def _reset_cell_info(self, cell): pass def _update_state(self): try: state = self._read_state() status = self._execute_cmd_exporter("getStatus", attribute=True) except Exception: state = SampleChangerState.Unknown status = "Unknown" self._set_state(state, status) def is_sequencer_ready(self): if self.prepareLoad: cmdobj = self.get_command_object return all([ cmd.isSpecReady() for cmd in (cmdobj("moveToLoadingPosition"), ) ]) return True def _read_state(self): state = self._execute_cmd_exporter("getState", attribute=True).upper() state_converter = { "ALARM": SampleChangerState.Alarm, "FAULT": SampleChangerState.Fault, "RUNNING": SampleChangerState.Moving, "READY": SampleChangerState.Ready, "STANDBY": SampleChangerState.Ready, } return state_converter.get(state, SampleChangerState.Unknown) def _is_device_busy(self, state=None): if state is None: state = self._read_state() return state not in ( SampleChangerState.Ready, SampleChangerState.Loaded, SampleChangerState.Alarm, SampleChangerState.Disabled, SampleChangerState.Fault, SampleChangerState.StandBy, ) def _is_device_ready(self): state = self._read_state() return state in (SampleChangerState.Ready, SampleChangerState.Charging) def _wait_device_ready(self, timeout=None): with gevent.Timeout(timeout, Exception("Timeout waiting for device ready")): while not self._is_device_ready(): gevent.sleep(0.01) def _update_selection(self): sample_cell, sample_puck, sample = self._execute_cmd_exporter( "getMountedSamplePosition", attribute=True) cell = sample_cell puck = sample_puck for c in self.get_components(): i = c.get_index() if cell == i + 1: self._set_selected_component(c) break # find sample for s in self.get_sample_list(): if s.get_coords() == (sample_cell, sample_puck, sample): self._set_loaded_sample(s) self._set_selected_sample(s) else: s._set_loaded(False) self._set_selected_sample(None) def prepare_hutch(self, **kwargs): return
class FlexHCD(SampleChanger): __TYPE__ = 'HCD' def __init__(self, *args, **kwargs): super(FlexHCD, self).__init__(self.__TYPE__, True, *args, **kwargs) def init(self): sc3_pucks = self.getProperty('sc3_pucks', True) for i in range(8): cell = Cell(self, i + 1, sc3_pucks) self._addComponent(cell) self.robot = self.getProperty('tango_device') if self.robot: self.robot = DeviceProxy(self.robot) self.exporter_addr = self.getProperty('exporter_address') if self.exporter_addr: self.swstate_attr = self.addChannel( { 'type': 'exporter', 'exporter_address': self.exporter_addr, 'name': 'swstate' }, 'State') self.controller = self.getObjectByRole('controller') self.prepareLoad = self.getCommandObject('moveToLoadingPosition') self.timeout = 3 self.gripper_types = { -1: "No Gripper", 1: "UNIPUCK", 2: "MINISPINE", 3: "FLIPPING", 4: "UNIPUCK_DOUBLE", 5: "PLATE" } return SampleChanger.init(self) @task def prepare_load(self): if self.controller: self.controller.hutch_actions(condition=True) else: self.prepareLoad() @task def prepare_centring(self): if self.controller: self.controller.hutch_actions(condition=False, sc_loading=True) else: gevent.sleep(2) self.getCommandObject('unlockMinidiffMotors')(wait=True) self.getCommandObject('prepareCentring')(wait=True) def prepareCentring(self): self.prepare_centring() def getSampleProperties(self): return (Pin.__HOLDER_LENGTH_PROPERTY__, ) def getBasketList(self): basket_list = [] # put here only the baskets that exist, not all the possible ones # if self.exporter_addr: # basket_list = for cell in self.getComponents(): for basket in cell.getComponents(): if isinstance(basket, Basket): basket_list.append(basket) return basket_list def _doChangeMode(self, *args, **kwargs): return def _doUpdateInfo(self): # self._updateSelection() self._updateState() def _doScan(self, component, recursive=True, saved={'barcodes': None}): return def _execute_cmd(self, cmd, *args, **kwargs): timeout = kwargs.pop('timeout', None) if args: cmd_str = 'flex.%s(%s)' % (cmd, ",".join(map(repr, args))) else: cmd_str = 'flex.%s()' % cmd cmd_id = self.robot.eval(cmd_str) if not cmd_id: cmd_id = self.robot.eval(cmd_str) with gevent.Timeout( timeout, RuntimeError("Timeout while executing %s" % repr(cmd_str))): while True: if self.robot.is_finished(cmd_id): break gevent.sleep(0.2) res = self.robot.get_result(cmd_id) if res: res = cPickle.loads(base64.decodestring(res)) if isinstance(res, Exception): raise res else: return res def _execute_cmd_exporter(self, cmd, *args, **kwargs): timeout = kwargs.pop('timeout', 900) if args: args_str = "%s" % "\t".join(map(repr, args)) if kwargs.pop('command', None): exp_cmd = self.addCommand( { 'type': 'exporter', 'exporter_address': self.exporter_addr, 'name': '%s' % cmd }, "%s" % cmd) if args: ret = exp_cmd(args_str) else: ret = exp_cmd() if kwargs.pop('attribute', None): exp_attr = self.addChannel( { 'type': 'exporter', 'exporter_address': self.exporter_addr, 'name': '%s' % cmd }, "%s" % cmd[3:]) if cmd.startswith('get'): return exp_attr.getValue() if cmd.startswith('set'): ret = exp_attr.setValue(args_str) self._wait_ready(timeout=timeout) return ret def _ready(self): return self.swstate_attr.getValue() == 'Ready' def _wait_ready(self, timeout=None): err_msg = "Timeout waiting for sample changer to be ready" # None means infinite timeout <=0 means default timeout if timeout is not None and timeout <= 0: timeout = self.timeout with gevent.Timeout(timeout, RuntimeError(err_msg)): while not self._ready(): time.sleep(0.5) def _doSelect(self, component): if isinstance(component, Cell): cell_pos = component.getIndex() + 1 elif isinstance(component, Basket) or isinstance(component, Pin): cell_pos = component.getCellNo() if self.exporter_addr: self._execute_cmd_exporter('moveDewar', cell_pos, command=True) else: self._execute_cmd('moveDewar', cell_pos) self._updateSelection() @task def load_sample(self, holderLength, sample_id=None, sample_location=None, sampleIsLoadedCallback=None, failureCallback=None, prepareCentring=True): cell, basket, sample = sample_location sample = self.getComponentByAddress( Pin.getSampleAddress(cell, basket, sample)) return self.load(sample) def chained_load(self, old_sample, sample): if self.exporter_addr: unload_load_task = gevent.spawn(self._execute_cmd_exporter, 'loadSample', sample.getCellNo(), sample.getBasketNo(), sample.getVialNo(), command=True) else: unload_load_task = gevent.spawn( self._execute_cmd, 'chainedUnldLd', [ old_sample.getCellNo(), old_sample.getBasketNo(), old_sample.getVialNo() ], [sample.getCellNo(), sample.getBasketNo(), sample.getVialNo()]) gevent.sleep(15) err_msg = "Timeout waiting for sample changer to be in safe position" while not unload_load_task.ready(): if self.exporter_addr: loading_state = self._execute_cmd_exporter( 'getCurrentLoadSampleState', attribute=True) if 'on_gonio' in loading_state: self._setLoadedSample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while not self._execute_cmd_exporter('getRobotIsSafe', attribute=True): gevent.sleep(0.5) return True else: loading_state = str( self._execute_cmd('sampleStatus', 'LoadSampleStatus')) if 'on_gonio' in loading_state: self._setLoadedSample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while not self._execute_cmd( 'get_robot_cache_variable', 'data:dioRobotIsSafe') == 'true': gevent.sleep(0.5) return True gevent.sleep(1) logging.getLogger('HWR').info("unload load task done") for msg in self.get_robot_exceptions(): logging.getLogger('HWR').error(msg) return self._check_pin_on_gonio() def _check_pin_on_gonio(self): print "_check_pin_on_gonio" if self.exporter_addr: _on_gonio = self._execute_cmd_exporter('pin_on_gonio', command=True) else: _on_gonio = self._execute_cmd('pin_on_gonio') if _on_gonio: # finish the loading actions self.prepare_centring() return True else: logging.getLogger('HWR').info("reset loaded sample") self._resetLoadedSample() # if self.controller: # self.controller.hutch_actions(release_interlock=True) return False def reset_loaded_sample(self): if self.exporter_addr: self._execute_cmd_exporter('reset_loaded_position', command=True) else: self._execute_cmd('reset_loaded_position') self._resetLoadedSample() def get_robot_exceptions(self): if self.exporter_addr: """ return self._execute_cmd_exporter('getRobotExceptions', attribute=True) """ return "" else: return self._execute_cmd('getRobotExceptions') @task def load(self, sample): self.prepare_load(wait=True) self.enable_power() try: res = SampleChanger.load(self, sample) finally: for msg in self.get_robot_exceptions(): logging.getLogger('HWR').error(msg) if res: self.prepareCentring() return res @task def unload_sample(self, holderLength, sample_id=None, sample_location=None, successCallback=None, failureCallback=None): cell, basket, sample = sample_location sample = self.getComponentByAddress( Pin.getSampleAddress(cell, basket, sample)) return self.unload(sample) @task def unload(self, sample): self.prepare_load(wait=True) self.enable_power() try: SampleChanger.unload(self, sample) finally: for msg in self.get_robot_exceptions(): logging.getLogger('HWR').error(msg) def get_gripper(self): if self.exporter_addr: gripper_type = self._execute_cmd_exporter('get_gripper_type', attribute=True) else: gripper_type = self._execute_cmd('get_gripper_type') return self.gripper_types.get(gripper_type, '?') def get_available_grippers(self): grippers = [] if self.exporter_addr: ret = self._execute_cmd_exporter('getSupportedGrippers', attribute=True) ret.sort() for gripper in ret: grippers.append(self.gripper_types[gripper]) return grippers @task def change_gripper(self, gripper=None): self.prepare_load(wait=True) self.enable_power() if self.exporter_addr: if gripper: self._execute_cmd_exporter('setGripper', gripper, command=True) else: self._execute_cmd_exporter('changeGripper', command=True) else: self._execute_cmd('changeGripper') @task def home(self): self.prepare_load(wait=True) self.enable_power() if self.exporter_addr: self._execute_cmd_exporter('homeClear', command=True) else: self._execute_cmd('homeClear') @task def enable_power(self): if not self.exporter_addr: self._execute_cmd('enablePower', 1) @task def defreeze(self): self.prepare_load(wait=True) self.enable_power() if self.exporter_addr: self._execute_cmd_exporter('defreezeGripper', command=True) else: self._execute_cmd('defreezeGripper') def _doLoad(self, sample=None): self._updateState() if self.exporter_addr: load_task = gevent.spawn(self._execute_cmd_exporter, 'loadSample', sample.getCellNo(), sample.getBasketNo(), sample.getVialNo(), command=True) else: load_task = gevent.spawn(self._execute_cmd, 'loadSample', sample.getCellNo(), sample.getBasketNo(), sample.getVialNo()) gevent.sleep(5) err_msg = "Timeout waiting for sample changer to be in safe position" while not load_task.ready(): if self.exporter_addr: loading_state = self._execute_cmd_exporter( 'getCurrentLoadSampleState', attribute=True) if 'on_gonio' in loading_state: self._setLoadedSample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while not self._execute_cmd_exporter('getRobotIsSafe', attribute=True): gevent.sleep(0.5) return True else: loading_state = str( self._execute_cmd('sampleStatus', 'LoadSampleStatus')) if 'on_gonio' in loading_state: self._setLoadedSample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while not self._execute_cmd( 'get_robot_cache_variable', 'data:dioRobotIsSafe') == 'true': gevent.sleep(0.5) return True gevent.sleep(1) if self.exporter_addr: loaded_sample = self._execute_cmd_exporter('get_loaded_sample', attribute=True) else: loaded_sample = self._execute_cmd('get_loaded_sample') if loaded_sample == (sample.getCellNo(), sample.getBasketNo(), sample.getVialNo()): self._setLoadedSample(sample) return True return self._check_pin_on_gonio() def _doUnload(self, sample=None): loaded_sample = self.getLoadedSample() if loaded_sample is not None and loaded_sample != sample: raise RuntimeError("Cannot unload another sample") if self.exporter_addr: self._execute_cmd_exporter('unloadSample', sample.getCellNo(), sample.getBasketNo(), sample.getVialNo(), command=True) loaded_sample = self._execute_cmd_exporter('get_loaded_sample', attribute=True) else: self._execute_cmd('unloadSample', sample.getCellNo(), sample.getBasketNo(), sample.getVialNo()) loaded_sample = self._execute_cmd('get_loaded_sample') if loaded_sample == (-1, -1, -1): self._resetLoadedSample() if self.controller: self.controller.hutch_actions(release_interlock=True) return True return False def _doAbort(self): if self.exporter_addr: self._execute_cmd_exporter('abort', command=True) else: self._execute_cmd('abort') def _doReset(self): if self.exporter_addr: self._execute_cmd_exporter('homeClear', command=True) else: self._execute_cmd('homeClear') def clearBasketInfo(self, basket): return self._reset_basket_info(basket) def _reset_basket_info(self, basket): pass def clearCellInfo(self, cell): return self._reset_cell_info(cell) def _reset_cell_info(self, cell): pass def _updateState(self): # see if the command exists for exporter if not self.exporter_addr: defreezing = self._execute_cmd('isDefreezing') if defreezing: self._setState(SampleChangerState.Ready) try: state = self._readState() except Exception: state = SampleChangerState.Unknown self._setState(state) def isSequencerReady(self): if self.prepareLoad: cmdobj = self.getCommandObject return all([ cmd.isSpecReady() for cmd in (cmdobj('moveToLoadingPosition'), ) ]) return True def _readState(self): # should read state from robot if self.exporter_addr: state = self.swstate_attr.getValue().upper() else: state = 'RUNNING' if self._execute_cmd( 'robot.isBusy') else 'STANDBY' if state == 'STANDBY' and not self.isSequencerReady(): state = 'RUNNING' state_converter = { 'ALARM': SampleChangerState.Alarm, 'FAULT': SampleChangerState.Fault, 'RUNNING': SampleChangerState.Moving, 'READY': SampleChangerState.Ready, 'STANDBY': SampleChangerState.Ready } return state_converter.get(state, SampleChangerState.Unknown) def _isDeviceBusy(self, state=None): if state is None: state = self._readState() return state not in (SampleChangerState.Ready, SampleChangerState.Loaded, SampleChangerState.Alarm, SampleChangerState.Disabled, SampleChangerState.Fault, SampleChangerState.StandBy) def _isDeviceReady(self): state = self._readState() return state in (SampleChangerState.Ready, SampleChangerState.Charging) def _waitDeviceReady(self, timeout=None): with gevent.Timeout(timeout, Exception("Timeout waiting for device ready")): while not self._isDeviceReady(): gevent.sleep(0.01) def _updateSelection(self): if self.exporter_addr: sample_cell, sample_puck, sample = self._execute_cmd_exporter( 'get_loaded_sample', attribute=True) cell = sample_cell puck = sample_puck else: cell, puck = self._execute_cmd('get_cell_position') sample_cell, sample_puck, sample = self._execute_cmd( 'get_loaded_sample') for c in self.getComponents(): i = c.getIndex() if cell == i + 1: self._setSelectedComponent(c) break # find sample for s in self.getSampleList(): if s.getCoords() == (sample_cell, sample_puck, sample): self._setLoadedSample(s) # self._setSelectedSample(s) return for s in self.getSampleList(): s._setLoaded(False) self._setSelectedSample(None) def prepare_hutch(self, **kwargs): if self.exporter_addr: return user_port = kwargs.get('user_port') robot_port = kwargs.get('robot_port') if user_port is not None: self._execute_cmd('robot.user_port(user_port)') if robot_port is not None: self._execute_cmd('robot.robot_port(robot_port)')
class FlexHCD(SampleChanger): __TYPE__ = "HCD" def __init__(self, *args, **kwargs): super(FlexHCD, self).__init__(self.__TYPE__, True, *args, **kwargs) def init(self): sc3_pucks = self.getProperty("sc3_pucks", True) for i in range(8): cell = Cell(self, i + 1, sc3_pucks) self._addComponent(cell) self.robot = self.getProperty("tango_device") if self.robot: self.robot = DeviceProxy(self.robot) self.exporter_addr = self.getProperty("exporter_address") if self.exporter_addr: self.swstate_attr = self.addChannel( { "type": "exporter", "exporter_address": self.exporter_addr, "name": "swstate", }, "State", ) self.controller = self.getObjectByRole("controller") self.prepareLoad = self.getCommandObject("moveToLoadingPosition") self.timeout = 3 self.gripper_types = { -1: "No Gripper", 1: "UNIPUCK", 2: "MINISPINE", 3: "FLIPPING", 4: "UNIPUCK_DOUBLE", 5: "PLATE", } return SampleChanger.init(self) @task def prepare_load(self): if self.controller: self.controller.hutch_actions(condition=True) else: self.prepareLoad() @task def prepare_centring(self): if self.controller: self.controller.hutch_actions(condition=False, sc_loading=True) else: gevent.sleep(2) self.getCommandObject("unlockMinidiffMotors")(wait=True) self.getCommandObject("prepareCentring")(wait=True) def prepareCentring(self): self.prepare_centring() def getSampleProperties(self): return (Pin.__HOLDER_LENGTH_PROPERTY__,) def getBasketList(self): basket_list = [] # put here only the baskets that exist, not all the possible ones # if self.exporter_addr: # basket_list = for cell in self.getComponents(): for basket in cell.getComponents(): if isinstance(basket, Basket): basket_list.append(basket) return basket_list def _doChangeMode(self, *args, **kwargs): return def _doUpdateInfo(self): # self._updateSelection() self._updateState() def _doScan(self, component, recursive=True, saved={"barcodes": None}): return def _execute_cmd(self, cmd, *args, **kwargs): timeout = kwargs.pop("timeout", None) if args: cmd_str = "flex.%s(%s)" % (cmd, ",".join(map(repr, args))) else: cmd_str = "flex.%s()" % cmd cmd_id = self.robot.eval(cmd_str) if not cmd_id: cmd_id = self.robot.eval(cmd_str) with gevent.Timeout( timeout, RuntimeError("Timeout while executing %s" % repr(cmd_str)) ): while True: if self.robot.is_finished(cmd_id): break gevent.sleep(0.2) res = self.robot.get_result(cmd_id) if res: res = cPickle.loads(base64.decodestring(res)) if isinstance(res, Exception): raise res else: return res def _execute_cmd_exporter(self, cmd, *args, **kwargs): timeout = kwargs.pop("timeout", 900) if args: args_str = "%s" % "\t".join(map(repr, args)) if kwargs.pop("command", None): exp_cmd = self.addCommand( { "type": "exporter", "exporter_address": self.exporter_addr, "name": "%s" % cmd, }, "%s" % cmd, ) if args: ret = exp_cmd(args_str) else: ret = exp_cmd() if kwargs.pop("attribute", None): exp_attr = self.addChannel( { "type": "exporter", "exporter_address": self.exporter_addr, "name": "%s" % cmd, }, "%s" % cmd[3:], ) if cmd.startswith("get"): return exp_attr.getValue() if cmd.startswith("set"): ret = exp_attr.setValue(args_str) self._wait_ready(timeout=timeout) return ret def _ready(self): return self.swstate_attr.getValue() == "Ready" def _wait_ready(self, timeout=None): err_msg = "Timeout waiting for sample changer to be ready" # None means infinite timeout <=0 means default timeout if timeout is not None and timeout <= 0: timeout = self.timeout with gevent.Timeout(timeout, RuntimeError(err_msg)): while not self._ready(): time.sleep(0.5) def _doSelect(self, component): if isinstance(component, Cell): cell_pos = component.getIndex() + 1 elif isinstance(component, Basket) or isinstance(component, Pin): cell_pos = component.getCellNo() if self.exporter_addr: self._execute_cmd_exporter("moveDewar", cell_pos, command=True) else: self._execute_cmd("moveDewar", cell_pos) self._updateSelection() @task def load_sample( self, holderLength, sample_id=None, sample_location=None, sampleIsLoadedCallback=None, failureCallback=None, prepareCentring=True, ): cell, basket, sample = sample_location sample = self.getComponentByAddress(Pin.getSampleAddress(cell, basket, sample)) return self.load(sample) def chained_load(self, old_sample, sample): if self.exporter_addr: unload_load_task = gevent.spawn( self._execute_cmd_exporter, "loadSample", sample.getCellNo(), sample.getBasketNo(), sample.getVialNo(), command=True, ) else: unload_load_task = gevent.spawn( self._execute_cmd, "chainedUnldLd", [ old_sample.getCellNo(), old_sample.getBasketNo(), old_sample.getVialNo(), ], [sample.getCellNo(), sample.getBasketNo(), sample.getVialNo()], ) gevent.sleep(15) err_msg = "Timeout waiting for sample changer to be in safe position" while not unload_load_task.ready(): if self.exporter_addr: loading_state = self._execute_cmd_exporter( "getCurrentLoadSampleState", attribute=True ) if "on_gonio" in loading_state: self._setLoadedSample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while not self._execute_cmd_exporter( "getRobotIsSafe", attribute=True ): gevent.sleep(0.5) return True else: loading_state = str( self._execute_cmd("sampleStatus", "LoadSampleStatus") ) if "on_gonio" in loading_state: self._setLoadedSample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while ( not self._execute_cmd( "get_robot_cache_variable", "data:dioRobotIsSafe" ) == "true" ): gevent.sleep(0.5) return True gevent.sleep(1) logging.getLogger("HWR").info("unload load task done") for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) return self._check_pin_on_gonio() def _check_pin_on_gonio(self): if self.exporter_addr: _on_gonio = self._execute_cmd_exporter("pin_on_gonio", command=True) else: _on_gonio = self._execute_cmd("pin_on_gonio") if _on_gonio: # finish the loading actions self.prepare_centring() return True else: logging.getLogger("HWR").info("reset loaded sample") self._resetLoadedSample() # if self.controller: # self.controller.hutch_actions(release_interlock=True) return False def reset_loaded_sample(self): if self.exporter_addr: self._execute_cmd_exporter("reset_loaded_position", command=True) else: self._execute_cmd("reset_loaded_position") self._resetLoadedSample() def get_robot_exceptions(self): if self.exporter_addr: """ return self._execute_cmd_exporter('getRobotExceptions', attribute=True) """ return "" else: return self._execute_cmd("getRobotExceptions") @task def load(self, sample): self.prepare_load(wait=True) self.enable_power() try: res = SampleChanger.load(self, sample) finally: for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) if res: self.prepareCentring() return res @task def unload_sample( self, holderLength, sample_id=None, sample_location=None, successCallback=None, failureCallback=None, ): cell, basket, sample = sample_location sample = self.getComponentByAddress(Pin.getSampleAddress(cell, basket, sample)) return self.unload(sample) @task def unload(self, sample): self.prepare_load(wait=True) self.enable_power() try: SampleChanger.unload(self, sample) finally: for msg in self.get_robot_exceptions(): logging.getLogger("HWR").error(msg) def get_gripper(self): if self.exporter_addr: gripper_type = self._execute_cmd_exporter( "get_gripper_type", attribute=True ) else: gripper_type = self._execute_cmd("get_gripper_type") return self.gripper_types.get(gripper_type, "?") def get_available_grippers(self): grippers = [] if self.exporter_addr: ret = sorted( self._execute_cmd_exporter("getSupportedGrippers", attribute=True) ) for gripper in ret: grippers.append(self.gripper_types[gripper]) return grippers @task def change_gripper(self, gripper=None): self.prepare_load(wait=True) self.enable_power() if self.exporter_addr: if gripper: self._execute_cmd_exporter("setGripper", gripper, command=True) else: self._execute_cmd_exporter("changeGripper", command=True) else: self._execute_cmd("changeGripper") @task def home(self): self.prepare_load(wait=True) self.enable_power() if self.exporter_addr: self._execute_cmd_exporter("homeClear", command=True) else: self._execute_cmd("homeClear") @task def enable_power(self): if not self.exporter_addr: self._execute_cmd("enablePower", 1) @task def defreeze(self): self.prepare_load(wait=True) self.enable_power() if self.exporter_addr: self._execute_cmd_exporter("defreezeGripper", command=True) else: self._execute_cmd("defreezeGripper") def _doLoad(self, sample=None): self._updateState() if self.exporter_addr: load_task = gevent.spawn( self._execute_cmd_exporter, "loadSample", sample.getCellNo(), sample.getBasketNo(), sample.getVialNo(), command=True, ) else: load_task = gevent.spawn( self._execute_cmd, "loadSample", sample.getCellNo(), sample.getBasketNo(), sample.getVialNo(), ) gevent.sleep(5) err_msg = "Timeout waiting for sample changer to be in safe position" while not load_task.ready(): if self.exporter_addr: loading_state = self._execute_cmd_exporter( "getCurrentLoadSampleState", attribute=True ) if "on_gonio" in loading_state: self._setLoadedSample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while not self._execute_cmd_exporter( "getRobotIsSafe", attribute=True ): gevent.sleep(0.5) return True else: loading_state = str( self._execute_cmd("sampleStatus", "LoadSampleStatus") ) if "on_gonio" in loading_state: self._setLoadedSample(sample) with gevent.Timeout(20, RuntimeError(err_msg)): while ( not self._execute_cmd( "get_robot_cache_variable", "data:dioRobotIsSafe" ) == "true" ): gevent.sleep(0.5) return True gevent.sleep(1) if self.exporter_addr: loaded_sample = self._execute_cmd_exporter( "get_loaded_sample", attribute=True ) else: loaded_sample = self._execute_cmd("get_loaded_sample") if loaded_sample == ( sample.getCellNo(), sample.getBasketNo(), sample.getVialNo(), ): self._setLoadedSample(sample) return True return self._check_pin_on_gonio() def _doUnload(self, sample=None): loaded_sample = self.getLoadedSample() if loaded_sample is not None and loaded_sample != sample: raise RuntimeError("Cannot unload another sample") if self.exporter_addr: self._execute_cmd_exporter( "unloadSample", sample.getCellNo(), sample.getBasketNo(), sample.getVialNo(), command=True, ) loaded_sample = self._execute_cmd_exporter( "get_loaded_sample", attribute=True ) else: self._execute_cmd( "unloadSample", sample.getCellNo(), sample.getBasketNo(), sample.getVialNo(), ) loaded_sample = self._execute_cmd("get_loaded_sample") if loaded_sample == (-1, -1, -1): self._resetLoadedSample() if self.controller: self.controller.hutch_actions(release_interlock=True) return True return False def _doAbort(self): if self.exporter_addr: self._execute_cmd_exporter("abort", command=True) else: self._execute_cmd("abort") def _doReset(self): if self.exporter_addr: self._execute_cmd_exporter("homeClear", command=True) else: self._execute_cmd("homeClear") def clearBasketInfo(self, basket): return self._reset_basket_info(basket) def _reset_basket_info(self, basket): pass def clearCellInfo(self, cell): return self._reset_cell_info(cell) def _reset_cell_info(self, cell): pass def _updateState(self): # see if the command exists for exporter if not self.exporter_addr: defreezing = self._execute_cmd("isDefreezing") if defreezing: self._setState(SampleChangerState.Ready) try: state = self._readState() except Exception: state = SampleChangerState.Unknown self._setState(state) def isSequencerReady(self): if self.prepareLoad: cmdobj = self.getCommandObject return all( [cmd.isSpecReady() for cmd in (cmdobj("moveToLoadingPosition"),)] ) return True def _readState(self): # should read state from robot if self.exporter_addr: state = self.swstate_attr.getValue().upper() else: state = "RUNNING" if self._execute_cmd("robot.isBusy") else "STANDBY" if state == "STANDBY" and not self.isSequencerReady(): state = "RUNNING" state_converter = { "ALARM": SampleChangerState.Alarm, "FAULT": SampleChangerState.Fault, "RUNNING": SampleChangerState.Moving, "READY": SampleChangerState.Ready, "STANDBY": SampleChangerState.Ready, } return state_converter.get(state, SampleChangerState.Unknown) def _isDeviceBusy(self, state=None): if state is None: state = self._readState() return state not in ( SampleChangerState.Ready, SampleChangerState.Loaded, SampleChangerState.Alarm, SampleChangerState.Disabled, SampleChangerState.Fault, SampleChangerState.StandBy, ) def _isDeviceReady(self): state = self._readState() return state in (SampleChangerState.Ready, SampleChangerState.Charging) def _waitDeviceReady(self, timeout=None): with gevent.Timeout(timeout, Exception("Timeout waiting for device ready")): while not self._isDeviceReady(): gevent.sleep(0.01) def _updateSelection(self): if self.exporter_addr: sample_cell, sample_puck, sample = self._execute_cmd_exporter( "get_loaded_sample", attribute=True ) cell = sample_cell puck = sample_puck else: cell, puck = self._execute_cmd("get_cell_position") sample_cell, sample_puck, sample = self._execute_cmd("get_loaded_sample") for c in self.getComponents(): i = c.getIndex() if cell == i + 1: self._setSelectedComponent(c) break # find sample for s in self.getSampleList(): if s.getCoords() == (sample_cell, sample_puck, sample): self._setLoadedSample(s) # self._setSelectedSample(s) return for s in self.getSampleList(): s._setLoaded(False) self._setSelectedSample(None) def prepare_hutch(self, **kwargs): if self.exporter_addr: return user_port = kwargs.get("user_port") robot_port = kwargs.get("robot_port") if user_port is not None: self._execute_cmd("robot.user_port(user_port)") if robot_port is not None: self._execute_cmd("robot.robot_port(robot_port)")