def validate_gantry_calibration(gantry_cal: List[List[float]]): """ This function determines whether the gantry calibration is valid or not based on the following use-cases: """ curr_cal = np.array(gantry_cal) row, _ = curr_cal.shape rank = np.linalg.matrix_rank(curr_cal) id_matrix = linal.identity_deck_transform() z = abs(curr_cal[2][-1]) outofrange = z < 16 or z > 34 if row != rank: # Check that the matrix is non-singular return DeckTransformState.SINGULARITY elif np.array_equal(curr_cal, id_matrix): # Check that the matrix is not an identity return DeckTransformState.IDENTITY elif outofrange: # Check that the matrix is not out of range. return DeckTransformState.BAD_CALIBRATION else: # Transform as it stands is sufficient. return DeckTransformState.OK
def _determine_calibration_to_use(deck_cal_to_check, api_v1): """ The default calibration loaded in simulation is not a valid way to check whether labware exceeds a given height. As a workaround, we should load the identity matrix with a Z offset if we are not running on a robot. """ id_matrix = linal.identity_deck_transform() deck_cal_to_use = deck_cal_to_check if not config.IS_ROBOT and not api_v1: if not deck_cal_to_check: deck_cal_to_use = DEFAULT_SIMULATION_CALIBRATION elif deck_cal_to_check and\ array_equal(array(deck_cal_to_check), id_matrix): deck_cal_to_use = deck_cal_to_check return deck_cal_to_use
def __init__(self, hardware): self.id = _get_uuid() self.pipettes = {} self.current_mount = None self.current_model = None self.tip_length = None self.points = {k: None for k in expected_points().keys()} self.z_value = None self.cp = None self.pipette_id = None self.adapter = hardware.sync self.current_transform = identity_deck_transform() robot_configs.backup_configuration(self.adapter.config) # Start from fresh identity matrix every calibration session self.adapter.update_config(gantry_calibration=list( map(lambda i: list(i), self.current_transform)))
def __init__(self, hardware): self.id = _get_uuid() self.pipettes = {} self.current_mount = None self.current_model = None self.tip_length = None self.points = {k: None for k in expected_points().keys()} self.z_value = None self.cp = None self.pipette_id = None self.adapter = hardware self.current_transform = identity_deck_transform() if feature_flags.use_protocol_api_v2(): self.adapter = hardware_control.adapters.SynchronousAdapter( hardware) # Start from fresh identity matrix every calibration session self.adapter.update_config(gantry_calibration=self.current_transform)
def __init__(self, point_set, hardware, pickup_tip=None, loop=None, log_level=None): # URWID user interface objects if not loop: loop = asyncio.get_event_loop() loop = urwid.main_loop.AsyncioEventLoop(loop=loop) controls = '\n'.join([ 'arrow keys: move the gantry', 'q/a: move the pipette up/down', '=/-: increase/decrease the distance moved on each step', '1/2/3: go to calibration point 1/2/3', 'enter: confirm current calibration point position', 'space: save data (after confirming all 3 points)', 'p: perform tip probe (after saving calibration data)', 'esc: exit calibration tool', '?: Full Instructions' ]) self._tip_text_box = urwid.Text(controls) self._status_text_box = urwid.Text('') self._pile = urwid.Pile([self._tip_text_box, self._status_text_box]) self._filler = urwid.Filler(self._pile, 'top') self.hardware = hardware self._pipettes = {} if not feature_flags.use_protocol_api_v2(): self._current_mount = right else: self._current_mount = types.Mount.RIGHT self.update_pipette_models() self.current_transform = identity_deck_transform() self._tip_length = DEFAULT_TIP_LENGTH # Other state if not pickup_tip: self._tip_length =\ self._pipettes[self._current_mount]._fallback_tip_length if feature_flags.use_protocol_api_v2(): self.hardware.add_tip(types.Mount.RIGHT, self._tip_length) if self._pipettes[types.Mount.LEFT]: self.hardware.add_tip( types.Mount.LEFT, self._pipettes[types.Mount.LEFT]._fallback_tip_length) else: for pip in self._pipettes.values(): if pip: pip._add_tip(pip._tip_length) self.current_position = (0, 0, 0) self._steps = [0.1, 0.25, 0.5, 1, 5, 10, 20, 40, 80] self._steps_index = 2 self._current_point = 1 self.model_offset = self._pipettes[self._current_mount].model_offset deck_height = 0 if not feature_flags.use_protocol_api_v2(): deck_height = self._tip_length self.actual_points = {1: (0, 0), 2: (0, 0), 3: (0, 0)} self._expected_points = self.set_deck_height_expected_points( deck_height, point_set) self._test_points = self.set_deck_height_test_points(deck_height) slot5 = self._test_points['slot5'] log_val = self.hardware.config.log_level if log_level: log_val = log_level.upper() logging_config.log_init(log_val) self.key_map = { '-': lambda: self.decrease_step(), '=': lambda: self.increase_step(), 'z': lambda: self.save_z_value(), 'p': lambda: self.probe(slot5), 'enter': lambda: self.save_point(), '\\': lambda: self.home(), ' ': lambda: self.save_transform(), 'esc': lambda: self.exit(), 'q': lambda: self._jog(self._current_mount, +1, self.current_step()), 'a': lambda: self._jog(self._current_mount, -1, self.current_step()), 'n': lambda: self.update_pipette_models(), 'up': lambda: self._jog('Y', +1, self.current_step()), 'down': lambda: self._jog('Y', -1, self.current_step()), 'left': lambda: self._jog('X', -1, self.current_step()), 'right': lambda: self._jog('X', +1, self.current_step()), 'm': lambda: self.validate_mount_offset(), 's': lambda: self.switch_mounts(), 't': lambda: self.try_pickup_tip(), '1': lambda: self.validate(self._expected_points[1], 1, self. _current_mount), '2': lambda: self.validate(self._expected_points[2], 2, self. _current_mount), '3': lambda: self.validate(self._expected_points[3], 3, self. _current_mount), '4': lambda: self.validate(self._test_points['slot5'], 4, self. _current_mount), '5': lambda: self.validate(self._test_points['corner3'], 5, self. _current_mount), '6': lambda: self.validate(self._test_points['corner8'], 6, self. _current_mount), '7': lambda: self.validate(self._test_points['corner9'], 7, self. _current_mount), '?': lambda: self.print_instructions(), } self.ui_loop = urwid.MainLoop(self._filler, handle_mouse=False, unhandled_input=self._on_key_press, event_loop=loop) log.debug("Starting gantry calibration command line interface (CLI)")