예제 #1
0
    def move_to(self, location, instrument=None, strategy='arc', **kwargs):
        """
        Move an instrument to a coordinate, container or a coordinate within
        a container.

        Parameters
        ----------
        location : one of the following:
            1. :class:`Placeable` (i.e. Container, Deck, Slot, Well) — will
            move to the origin of a container.
            2. :class:`Vector` move to the given coordinate in Deck coordinate
            system.
            3. (:class:`Placeable`, :class:`Vector`) move to a given coordinate
            within object's coordinate system.

        instrument :
            Instrument to move relative to. If ``None``, move relative to the
            center of a gantry.

        strategy : {'arc', 'direct'}
            ``arc`` : move to the point using arc trajectory
            avoiding obstacles.

            ``direct`` : move to the point in a straight line.

        Examples
        --------
        >>> from opentrons import Robot
        >>> robot.reset() # doctest: +ELLIPSIS
        <opentrons.robot.robot.Robot object at ...>
        >>> robot.connect('Virtual Smoothie')
        >>> robot.home()
        >>> plate = robot.add_container('96-flat', 'A1', 'plate')
        >>> robot.move_to(plate[0])
        >>> robot.move_to(plate[0].top())
        """

        placeable, coordinates = containers.unpack_location(location)

        if instrument:
            coordinates = instrument.calibrator.convert(placeable, coordinates)
        else:
            coordinates += placeable.coordinates(placeable.get_deck())

        if strategy == 'arc':
            arc_coords = self._create_arc(coordinates, placeable, instrument)
            for coord in arc_coords:
                self._driver.move_head(**coord)
        elif strategy == 'direct':
            self._driver.move_head(x=coordinates[0],
                                   y=coordinates[1],
                                   z=coordinates[2])
        else:
            raise RuntimeError('Unknown move strategy: {}'.format(strategy))
예제 #2
0
    def _associate_placeable(self, location):
        """
        Saves a reference to a placeable
        """
        if not location:
            return

        placeable, _ = unpack_location(location)
        self.previous_placeable = placeable
        if not self.placeables or (placeable != self.placeables[-1]):
            self.placeables.append(placeable)
예제 #3
0
    def _associate_placeable(self, location):
        """
        Saves a reference to a placeable
        """
        if not location:
            return

        placeable, _ = containers.unpack_location(location)
        self.previous_placeable = placeable
        if not self.placeables or (placeable != self.placeables[-1]):
            self.placeables.append(placeable)
예제 #4
0
    def _dispense_during_transfer(self, vol, loc, **kwargs):
        """
        Performs a :any:`dispense` when running a :any:`transfer`, and
        optionally a :any:`mix`, :any:`touch_tip`, and/or
        :any:`blow_out` afterwards.
        """
        mix_after = kwargs.get('mix_after', (0, 0))
        rate = kwargs.get('rate', 1)
        air_gap = kwargs.get('air_gap', 0)

        well, _ = unpack_location(loc)

        if air_gap:
            self.dispense(air_gap, well.top(5), rate=rate)
        self.dispense(vol, loc, rate=rate)
        self._mix_during_transfer(mix_after, well, **kwargs)
예제 #5
0
    def _aspirate_during_transfer(self, vol, loc, **kwargs):
        """
        Performs an :any:`aspirate` when running a :any:`transfer`, and
        optionally a :any:`touch_tip` afterwards.
        """
        rate = kwargs.get('rate', 1)
        mix_before = kwargs.get('mix', kwargs.get('mix_before', (0, 0)))
        air_gap = kwargs.get('air_gap', 0)
        touch_tip = kwargs.get('touch_tip', False)

        well, _ = unpack_location(loc)

        if self.current_volume == 0:
            self._mix_during_transfer(mix_before, well, **kwargs)
        self.aspirate(vol, loc, rate=rate)
        if air_gap:
            self.air_gap(air_gap)
        if touch_tip or touch_tip is 0:
            self.touch_tip(touch_tip)
예제 #6
0
    def _position_for_aspirate(self, location=None):
        """
        Position this :any:`Pipette` for an aspiration,
        given it's current state
        """

        # first go to the destination
        if location:
            placeable, _ = unpack_location(location)
            self.move_to(placeable.top(), strategy='arc')

        # setup the plunger above the liquid
        if self.current_volume == 0:
            self.motor.move(self._get_plunger_position('bottom'))

        # then go inside the location
        if location:
            if isinstance(location, Placeable):
                location = location.bottom(min(location.z_size(), 1))
            self.move_to(location, strategy='direct')
예제 #7
0
    def _position_for_aspirate(self, location=None, plunger_empty=False):
        """
        Position this :any:`Pipette` for an aspiration,
        given it's current state
        """

        # first go to the destination
        if location:
            placeable, _ = containers.unpack_location(location)
            self.move_to(placeable.top(), strategy='arc', enqueue=False)

        # setup the plunger above the liquid
        if plunger_empty:
            self.motor.move(self._get_plunger_position('bottom'))

        # then go inside the location
        if location:
            if isinstance(location, Placeable):
                location = location.bottom(1)
            self.move_to(location, strategy='direct', enqueue=False)
예제 #8
0
    def _position_for_aspirate(self, location=None, plunger_empty=False):
        """
        Position this :any:`Pipette` for an aspiration,
        given it's current state
        """

        # first go to the destination
        if location:
            placeable, _ = containers.unpack_location(location)
            self.move_to(placeable.top(), strategy='arc', enqueue=False)

        # setup the plunger above the liquid
        if plunger_empty:
            self.motor.move(self._get_plunger_position('bottom'))

        # then go inside the location
        if location:
            if isinstance(location, Placeable):
                location = location.bottom(1)
            self.move_to(location, strategy='direct', enqueue=False)
예제 #9
0
        def _setup():
            nonlocal location
            if not location:
                if self.has_tip_rack():
                    # TODO: raise warning/exception if looped back to first tip
                    location = next(self.tip_rack_iter)
                else:
                    self.robot.add_warning(
                        'pick_up_tip called with no reference to a tip')

            self.current_tip_home_well = None
            if location:
                placeable, _ = containers.unpack_location(location)
                self.current_tip_home_well = placeable

            if isinstance(location, Placeable):
                location = location.bottom()

            self._associate_placeable(location)

            self.current_volume = 0
예제 #10
0
        def _setup():
            nonlocal location
            if not location:
                if self.has_tip_rack():
                    # TODO: raise warning/exception if looped back to first tip
                    location = next(self.tip_rack_iter)
                else:
                    self.robot.add_warning(
                        'pick_up_tip called with no reference to a tip')

            self.current_tip_home_well = None
            if location:
                placeable, _ = containers.unpack_location(location)
                self.current_tip_home_well = placeable

            if isinstance(location, Placeable):
                location = location.bottom()

            self._associate_placeable(location)

            self.current_volume = 0
예제 #11
0
    def pick_up_tip(self, location=None, presses=3):
        """
        Pick up a tip for the Pipette to run liquid-handling commands with

        Notes
        -----
        A tip can be manually set by passing a `location`. If no location
        is passed, the Pipette will pick up the next available tip in
        it's `tip_racks` list (see :any:`Pipette`)

        Parameters
        ----------
        location : :any:`Placeable` or tuple(:any:`Placeable`, :any:`Vector`)
            The :any:`Placeable` (:any:`Well`) to perform the pick_up_tip.
            Can also be a tuple with first item :any:`Placeable`,
            second item relative :any:`Vector`

        Returns
        -------

        This instance of :class:`Pipette`.

        Examples
        --------
        ..
        >>> robot.reset() # doctest: +ELLIPSIS
        <opentrons.robot.robot.Robot object at ...>
        >>> tiprack = containers.load('tiprack-200ul', 'A1')
        >>> p200 = instruments.Pipette(axis='a', tip_racks=[tiprack])
        >>> p200.pick_up_tip(tiprack[0]) # doctest: +ELLIPSIS
        <opentrons.instruments.pipette.Pipette object at ...>
        >>> p200.return_tip() # doctest: +ELLIPSIS
        <opentrons.instruments.pipette.Pipette object at ...>
        >>> # `pick_up_tip` will automatically go to tiprack[1]
        >>> p200.pick_up_tip() # doctest: +ELLIPSIS
        <opentrons.instruments.pipette.Pipette object at ...>
        >>> p200.return_tip() # doctest: +ELLIPSIS
        <opentrons.instruments.pipette.Pipette object at ...>
        """

        if not location:
            location = self.get_next_tip()
        self.current_tip(None)
        if location:
            placeable, _ = unpack_location(location)
            self.current_tip(placeable)

        if isinstance(location, Placeable):
            location = location.bottom()

        _description = "Picking up tip {0}".format(
            ('from ' +
             humanize_location(location) if location else ''))  # NOQA
        self.robot.add_command(_description)

        presses = (1 if not helpers.is_number(presses) else presses)

        self.motor.move(self._get_plunger_position('bottom'))
        self.current_volume = 0

        if location:
            self.move_to(location, strategy='arc')

        tip_plunge = 6
        for i in range(int(presses) - 1):
            self.robot.move_head(z=tip_plunge, mode='relative')
            self.robot.move_head(z=-tip_plunge, mode='relative')
        return self
예제 #12
0
    def move_to(self, location, instrument=None, strategy="arc", **kwargs):
        """
        Move an instrument to a coordinate, container or a coordinate within
        a container.

        Parameters
        ----------
        location : one of the following:
            1. :class:`Placeable` (i.e. Container, Deck, Slot, Well) — will
            move to the origin of a container.
            2. :class:`Vector` move to the given coordinate in Deck coordinate
            system.
            3. (:class:`Placeable`, :class:`Vector`) move to a given coordinate
            within object's coordinate system.

        instrument :
            Instrument to move relative to. If ``None``, move relative to the
            center of a gantry.

        strategy : {'arc', 'direct'}
            ``arc`` : move to the point using arc trajectory
            avoiding obstacles.

            ``direct`` : move to the point in a straight line.

        Examples
        --------
        >>> from opentrons import Robot
        >>> robot.reset() # doctest: +ELLIPSIS
        <opentrons.robot.robot.Robot object at ...>
        >>> robot.connect('Virtual Smoothie')
        True
        >>> robot.home()
        True
        >>> plate = robot.add_container('96-flat', 'A1', 'plate')
        >>> robot.move_to(plate[0])
        >>> robot.move_to(plate[0].top())
        """

        enqueue = kwargs.get("enqueue", False)
        # Adding this for backwards compatibility with old move_to(now=False)
        # convention.
        if "now" in kwargs:
            enqueue = not kwargs.get("now")

        placeable, coordinates = containers.unpack_location(location)

        if instrument:
            coordinates = instrument.calibrator.convert(placeable, coordinates)
        else:
            coordinates += placeable.coordinates(placeable.get_deck())

        def _do():
            if strategy == "arc":
                arc_coords = self._create_arc(coordinates, placeable)
                for coord in arc_coords:
                    self._driver.move_head(**coord)
            elif strategy == "direct":
                self._driver.move_head(x=coordinates[0], y=coordinates[1], z=coordinates[2])
            else:
                raise RuntimeError("Unknown move strategy: {}".format(strategy))

        if enqueue:
            self.add_command(Command(do=_do))
        else:
            _do()
예제 #13
0
    def move_to(self, location, instrument, strategy='arc', **kwargs):
        """
        Move an instrument to a coordinate, container or a coordinate within
        a container.

        Parameters
        ----------
        location : one of the following:
            1. :class:`Placeable` (i.e. Container, Deck, Slot, Well) — will
            move to the origin of a container.
            2. :class:`Vector` move to the given coordinate in Deck coordinate
            system.
            3. (:class:`Placeable`, :class:`Vector`) move to a given coordinate
            within object's coordinate system.

        instrument :
            Instrument to move relative to. If ``None``, move relative to the
            center of a gantry.

        strategy : {'arc', 'direct'}
            ``arc`` : move to the point using arc trajectory
            avoiding obstacles.

            ``direct`` : move to the point in a straight line.
        """

        placeable, coordinates = containers.unpack_location(location)

        # because the top position is what is tracked,
        # this checks if coordinates doesn't equal top
        offset = subtract(coordinates, placeable.top()[1])

        if 'trough' in repr(placeable):
            # Move the pipette so that a multi-channel pipette is centered in
            # the trough well to prevent crashing into the side, which would
            # happen if you send the "A1" tip to the center of the well. See
            # `robot.calibrate_container_with_instrument` for corresponding
            # offset and comment.
            offset = offset + (0, Y_OFFSET_MULTI, 0)

        if isinstance(placeable, containers.WellSeries):
            placeable = placeable[0]

        target = add(pose_tracker.absolute(self.poses, placeable),
                     offset.coordinates)

        if self._previous_instrument:
            if self._previous_instrument != instrument:
                self._previous_instrument.retract()
                # because we're switching pipettes, this ensures a large (safe)
                # Z arc height will be used for the new pipette
                self._prev_container = None

        self._previous_instrument = instrument

        if strategy == 'arc':
            arc_coords = self._create_arc(instrument, target, placeable)
            for coord in arc_coords:
                self.poses = instrument._move(self.poses, **coord)

        elif strategy == 'direct':
            position = {'x': target[0], 'y': target[1], 'z': target[2]}
            self.poses = instrument._move(self.poses, **position)
        else:
            raise RuntimeError('Unknown move strategy: {}'.format(strategy))