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
Beispiel #3
0
    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)))
Beispiel #4
0
    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)
Beispiel #5
0
    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)")