From 20c788030c1558730ccddc2c8b932b8cafba966f Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Tue, 12 Dec 2023 17:49:11 -0500 Subject: [PATCH 01/14] basic reorg and toctree --- api/docs/v2/new_pipette.rst | 470 +---------------------- api/docs/v2/pipettes/characteristics.rst | 246 ++++++++++++ api/docs/v2/pipettes/configuring.rst | 60 +++ api/docs/v2/pipettes/loading.rst | 171 +++++++++ 4 files changed, 489 insertions(+), 458 deletions(-) create mode 100644 api/docs/v2/pipettes/characteristics.rst create mode 100644 api/docs/v2/pipettes/configuring.rst create mode 100644 api/docs/v2/pipettes/loading.rst diff --git a/api/docs/v2/new_pipette.rst b/api/docs/v2/new_pipette.rst index 7d8602b064b..6798f9cf7fb 100644 --- a/api/docs/v2/new_pipette.rst +++ b/api/docs/v2/new_pipette.rst @@ -2,471 +2,25 @@ .. _new-pipette: -######## +******** Pipettes -######## +******** -When writing a protocol, you must inform the Protocol API about the pipettes you will be using on your robot. The :py:meth:`.ProtocolContext.load_instrument` function provides this information and returns an :py:class:`.InstrumentContext` object. - -For information about liquid handling, see :ref:`v2-atomic-commands` and :ref:`v2-complex-commands`. - -.. _new-create-pipette: - -Loading Pipettes -================ - -As noted above, you call the :py:meth:`~.ProtocolContext.load_instrument` method to load a pipette. This method also requires the :ref:`pipette's API load name `, its left or right mount position, and (optionally) a list of associated tip racks. Even if you don't use the pipette anywhere else in your protocol, the Opentrons App and the robot won't let you start the protocol run until all pipettes loaded by ``load_instrument()`` are attached properly. - -Loading Flex 1- and 8-Channel Pipettes --------------------------------------- - -This code sample loads a Flex 1-Channel Pipette in the left mount and a Flex 8-Channel Pipette in the right mount. Both pipettes are 1000 µL. Each pipette uses its own 1000 µL tip rack. - -.. code-block:: Python - :substitutions: - - from opentrons import protocol_api - - requirements = {'robotType': 'Flex', 'apiLevel':'|apiLevel|'} - - def run(protocol: protocol_api.ProtocolContext): - tiprack1 = protocol.load_labware( - load_name='opentrons_flex_96_tiprack_1000ul', location='D1') - tiprack2 = protocol.load_labware( - load_name='opentrons_flex_96_tiprack_1000ul', location='C1') - left = protocol.load_instrument( - instrument_name='flex_1channel_1000', - mount='left', - tip_racks=[tiprack1]) - right = protocol.load_instrument( - instrument_name='flex_8channel_1000', - mount='right', - tip_racks=[tiprack2]) - -If you're writing a protocol that uses the Flex Gripper, you might think that this would be the place in your protocol to declare that. However, the gripper doesn't require ``load_instrument``! Whether your gripper requires a protocol is determined by the presence of :py:meth:`.ProtocolContext.move_labware` commands. See :ref:`moving-labware` for more details. - -Loading a Flex 96-Channel Pipette ---------------------------------- - -This code sample loads the Flex 96-Channel Pipette. Because of its size, the Flex 96-Channel Pipette requires the left *and* right pipette mounts. You cannot use this pipette with 1- or 8-Channel Pipette in the same protocol or when these instruments are attached to the robot. When loading the 96-Channel Pipette, you can omit the ``mount`` argument from ``load_instrument()`` as shown here: - -.. code-block:: python - - def run(protocol: protocol_api.ProtocolContext): - pipette = protocol.load_instrument( - instrument_name='flex_96channel_1000') - -.. versionadded:: 2.15 - -Loading OT-2 Pipettes ---------------------- - -This code sample loads a P1000 Single-Channel GEN2 pipette in the left mount and a P300 Single-Channel GEN2 pipette in the right mount. Each pipette uses its own 1000 µL tip rack. - -.. code-block:: python - :substitutions: - - from opentrons import protocol_api - - metadata = {'apiLevel': '2.14'} - - def run(protocol: protocol_api.ProtocolContext): - tiprack1 = protocol.load_labware( - load_name='opentrons_96_tiprack_1000ul', location=1) - tiprack2 = protocol.load_labware( - load_name='opentrons_96_tiprack_1000ul', location=2) - left = protocol.load_instrument( - instrument_name='p1000_single_gen2', - mount='left', - tip_racks=[tiprack1]) - right = protocol.load_instrument( - instrument_name='p300_multi_gen2', - mount='right', - tip_racks=[tiprack1]) - -.. versionadded:: 2.0 - -.. _new-multichannel-pipettes: - -Multi-Channel Pipettes -====================== - -All building block and advanced commands work with single- and multi-channel pipettes. - -To keep the interface to the Opentrons API consistent between single- and multi-channel pipettes, commands treat the *backmost channel* (furthest from the door) of a multi-channel pipette as the location of the pipette. Location arguments to building block and advanced commands are specified for the backmost channel. - -Also, this means that offset changes (such as :py:meth:`.Well.top` or :py:meth:`.Well.bottom`) can be applied to the single specified well, and each pipette channel will be at the same position relative to the well that it is over. - -Finally, because there is only one motor in a multi-channel pipette, these pipettes always aspirate and dispense on all channels simultaneously. - -8-Channel, 96-Well Plate Example --------------------------------- - -To demonstrate these concepts, let's write a protocol that uses a Flex 8-Channel Pipette and a 96-well plate. We'll then aspirate and dispense a liquid to different locations on the same well plate. To start, let's load a pipette in the right mount and add our labware. - -.. code-block:: python - :substitutions: - - from opentrons import protocol_api - - requirements = {'robotType': 'Flex', 'apiLevel':'|apiLevel|'} - - def run(protocol: protocol_api.ProtocolContext): - # Load a tiprack for 1000 µL tips - tiprack1 = protocol.load_labware( - load_name='opentrons_flex_96_tiprack_1000ul', location='D1') - # Load a 96-well plate - plate = protocol.load_labware( - load_name='corning_96_wellplate_360ul_flat', location='C1') - # Load an 8-channel pipette on the right mount - right = protocol.load_instrument( - instrument_name='flex_8channel_1000', - mount='right', - tip_racks=[tiprack1]) - -After loading our instruments and labware, let's tell the robot to pick up a pipette tip from location ``A1`` in ``tiprack1``:: - - right.pick_up_tip() - -With the backmost pipette channel above location A1 on the tip rack, all eight channels are above the eight tip rack wells in column 1. - -After picking up a tip, let's tell the robot to aspirate 300 µL from the well plate at location ``A2``:: - - right.aspirate(volume=300, location=plate['A2']) - -With the backmost pipette tip above location A2 on the well plate, all eight channels are above the eight wells in column 2. - -Finally, let's tell the robot to dispense 300 µL into the well plate at location ``A3``:: - - right.dispense(volume=300, location=plate['A3'].top()) - -With the backmost pipette tip above location A3, all eight channels are above the eight wells in column 3. The pipette will dispense liquid into all the wells simultaneously. - -8-Channel, 384-Well Plate Example ---------------------------------- - -In general, you should specify wells in the first row of a well plate when using multi-channel pipettes. An exception to this rule is when using 384-well plates. The greater well density means the nozzles of a multi-channel pipette can only access every other well in a column. Specifying well A1 accesses every other well starting with the first (rows A, C, E, G, I, K, M, and O). Similarly, specifying well B1 also accesses every other well, but starts with the second (rows B, D, F, H, J, L, N, and P). - -To demonstrate these concepts, let's write a protocol that uses a Flex 8-Channel Pipette and a 384-well plate. We'll then aspirate and dispense a liquid to different locations on the same well plate. To start, let's load a pipette in the right mount and add our labware. - -.. code-block:: python - - def run(protocol: protocol_api.ProtocolContext): - # Load a tiprack for 200 µL tips - tiprack1 = protocol.load_labware( - load_name='opentrons_flex_96_tiprack_200ul', location="D1") - # Load a well plate - plate = protocol.load_labware( - load_name='corning_384_wellplate_112ul_flat', location="D2") - # Load an 8-channel pipette on the right mount - right = protocol.load_instrument( - instrument_name='flex_8channel_1000', - mount='right', - tip_racks=[tiprack1]) - - -After loading our instruments and labware, let's tell the robot to pick up a pipette tip from location ``A1`` in ``tiprack1``:: - - right.pick_up_tip() - -With the backmost pipette channel above location A1 on the tip rack, all eight channels are above the eight tip rack wells in column 1. - -After picking up a tip, let's tell the robot to aspirate 100 µL from the well plate at location ``A1``:: - - right.aspirate(volume=100, location=plate['A1']) - -The eight pipette channels will only aspirate from every other well in the column: A1, C1, E1, G1, I1, K1, M1, and O1. - -Finally, let's tell the robot to dispense 100 µL into the well plate at location ``B1``:: - - right.dispense(volume=100, location=plate['B1']) - -The eight pipette channels will only dispense into every other well in the column: B1, D1, F1, H1, J1, L1, N1, and P1. - -.. _pipette-tip-racks: - -Adding Tip Racks -================ - -The ``load_instrument()`` method includes the optional argument ``tip_racks``. This parameter accepts a list of tip rack labware objects, which lets you to specify as many tip racks as you want. The advantage of using ``tip_racks`` is twofold. First, associating tip racks with your pipette allows for automatic tip tracking throughout your protocol. Second, it removes the need to specify tip locations in the :py:meth:`.InstrumentContext.pick_up_tip` method. For example, let's start by loading loading some labware and instruments like this:: - - def run(protocol: protocol_api.ProtocolContext): - tiprack_left = protocol.load_labware( - load_name='opentrons_flex_96_tiprack_200ul', location='D1') - tiprack_right = protocol.load_labware( - load_name='opentrons_flex_96_tiprack_200ul', location='D2') - left_pipette = protocol.load_instrument( - instrument_name='flex_8channel_1000', mount='left') - right_pipette = protocol.load_instrument( - instrument_name='flex_8channel_1000', - mount='right', - tip_racks=[tiprack_right]) - -Let's pick up a tip with the left pipette. We need to specify the location as an argument of ``pick_up_tip()``, since we loaded the left pipette without a ``tip_racks`` argument. - -.. code-block:: python - - left_pipette.pick_up_tip(tiprack_left['A1']) - left_pipette.drop_tip() - -But now you have to specify ``tiprack_left`` every time you call ``pick_up_tip``, which means you're doing all your own tip tracking:: - - left_pipette.pick_up_tip(tiprack_left['A2']) - left_pipette.drop_tip() - left_pipette.pick_up_tip(tiprack_left['A3']) - left_pipette.drop_tip() - -However, because you specified a tip rack location for the right pipette, the robot will automatically pick up from location ``A1`` of its associated tiprack:: - - right_pipette.pick_up_tip() - right_pipette.drop_tip() - -Additional calls to ``pick_up_tip`` will automatically progress through the tips in the right rack:: - - right_pipette.pick_up_tip() # picks up from A2 - right_pipette.drop_tip() - right_pipette.pick_up_tip() # picks up from A3 - right_pipette.drop_tip() - -See also, :ref:`v2-atomic-commands` and :ref:`v2-complex-commands`. - -.. versionadded:: 2.0 - -.. _new-pipette-models: - -API Load Names -============== - -The pipette's API load name (``instrument_name``) is the first parameter of the ``load_instrument()`` method. It tells your robot which attached pipette you're going to use in a protocol. The tables below list the API load names for the currently available Flex and OT-2 pipettes. - -.. tabs:: - - .. tab:: Flex Pipettes - - +-------------------------+---------------+-------------------------+ - | Pipette Model | Volume (µL) | API Load Name | - +=========================+===============+===+=====================+ - | Flex 1-Channel Pipette | 1–50 | ``flex_1channel_50`` | - + +---------------+-------------------------+ - | | 5–1000 | ``flex_1channel_1000`` | - +-------------------------+---------------+-------------------------+ - | Flex 8-Channel Pipette | 1–50 | ``flex_8channel_50`` | - + +---------------+-------------------------+ - | | 5–1000 | ``flex_8channel_1000`` | - +-------------------------+---------------+-------------------------+ - | Flex 96-Channel Pipette | 5–1000 | ``flex_96channel_1000`` | - +-------------------------+---------------+-------------------------+ - - .. tab:: OT-2 Pipettes - - +-----------------------------+--------------------+-----------------------+ - | Pipette Model | Volume (µL) | API Load Name | - +=============================+====================+=======================+ - | P20 Single-Channel GEN2 | 1-20 | ``p20_single_gen2`` | - +-----------------------------+ +-----------------------+ - | P20 Multi-Channel GEN2 | | ``p20_multi_gen2`` | - +-----------------------------+--------------------+-----------------------+ - | P300 Single-Channel GEN2 | 20-300 | ``p300_single_gen2`` | - +-----------------------------+ +-----------------------+ - | P300 Multi-Channel GEN2 | | ``p300_multi_gen2`` | - +-----------------------------+--------------------+-----------------------+ - | P1000 Single-Channel GEN2 | 100-1000 | ``p1000_single_gen2`` | - +-----------------------------+--------------------+-----------------------+ - - See the OT-2 Pipette Generations section below if you're using GEN1 pipettes on an OT-2. The GEN1 family includes the P10, P50, and P300 single- and multi-channel pipettes, along with the P1000 single-chanel model. - - -OT-2 Pipette Generations -======================== - -The OT-2 works with the GEN1 and GEN2 pipette models. The newer GEN2 pipettes have different volume ranges than the older GEN1 pipettes. With some exceptions, the volume ranges for GEN2 pipettes overlap those used by the GEN1 models. If your protocol specifies a GEN1 pipette, but you have a GEN2 pipette with a compatible volume range, you can still run your protocol. The OT-2 will consider the GEN2 pipette to have the same minimum volume as the GEN1 pipette. The following table lists the volume compatibility between the GEN2 and GEN1 pipettes. - -.. list-table:: - :header-rows: 1 - - * - GEN2 Pipette - - GEN1 Pipette - - GEN1 Volume - * - P20 Single-Channel GEN2 - - P10 Single-Channel GEN1 - - 1-10 µL - * - P20 Multi-Channel GEN2 - - P10 Multi-Channel GEN1 - - 1-10 µL - * - P300 Single-Channel GEN2 - - P300 Single-Channel GEN1 - - 30-300 µL - * - P300 Multi-Channel GEN2 - - P300 Multi-Channel GEN1 - - 20-200 µL - * - P1000 Single-Channel GEN2 - - P1000 Single-Channel GEN1 - - 100-1000 µL - -The single- and multi-channel P50 GEN1 pipettes are the exceptions here. If your protocol uses a P50 GEN1 pipette, there is no backward compatibility with a related GEN2 pipette. To replace a P50 GEN1 with a corresponding GEN2 pipette, edit your protocol to load a P20 Single-Channel GEN2 (for volumes below 20 µL) or a P300 Single-Channel GEN2 (for volumes between 20 and 50 µL). - -.. _pipette-volume-modes: - -Volume Modes -============ - -The Flex 1-Channel 50 µL and Flex 8-Channel 50 µL pipettes must operate in a low-volume mode to accurately dispense very small volumes of liquid. Set the volume mode by calling :py:meth:`.InstrumentContext.configure_for_volume` with the amount of liquid you plan to aspirate, in µL:: - - pipette50.configure_for_volume(1) - pipette50.pick_up_tip() - pipette50.aspirate(1, plate["A1"]) +.. toctree:: + pipettes/loading + pipettes/characteristics + pipettes/configuring -.. versionadded:: 2.15 +Opentrons pipettes are configurable devices used to move liquids throughout the working area during the execution of protocols. Flex and OT-2 each have their own pipettes, which are available for use in the Python API. -Passing different values to ``configure_for_volume()`` changes the minimum and maximum volume of Flex 50 µL pipettes as follows: +Pages in this section of the documentation cover: -.. list-table:: - :header-rows: 1 - :widths: 2 3 3 - - * - Value - - Minimum Volume (µL) - - Maximum Volume (µL) - * - 1–4.9 - - 1 - - 30 - * - 5–50 - - 5 - - 50 - -.. note:: - The pipette must not contain liquid when you call ``configure_for_volume()``, or the API will raise an error. - - Also, if the pipette is in a well location that may contain liquid, it will move upward to ensure it is not immersed in liquid before changing its mode. Calling ``configure_for_volume()`` *before* ``pick_up_tip()`` helps to avoid this situation. - -In a protocol that handles many different volumes, it's a good practice to call ``configure_for_volume()`` once for each :py:meth:`.transfer` or :py:meth:`.aspirate`, specifying the volume that you are about to handle. When operating with a list of volumes, nest ``configure_for_volume()`` inside a ``for`` loop to ensure that the pipette is properly configured for each volume: - -.. code-block:: python - - volumes = [1, 2, 3, 4, 1, 5, 2, 8] - sources = plate.columns()[0] - destinations = plate.columns()[1] - for i in range(8): - pipette50.configure_for_volume(volumes[i]) - pipette50.pick_up_tip() - pipette50.aspirate(volume=volumes[i], location=sources[i]) - pipette50.dispense(location=destinations[i]) - pipette50.drop_tip() - -If you know that all your liquid handling will take place in a specific mode, then you can call ``configure_for_volume()`` just once with a representative volume. Or if all the volumes correspond to the pipette's default mode, you don't have to call ``configure_for_volume()`` at all. - - -.. _new-plunger-flow-rates: - -Pipette Flow Rates -================== - -Measured in µL/s, the flow rate determines how much liquid a pipette can aspirate, dispense, and blow out. Opentrons pipettes have their own default flow rates. The API lets you change the flow rate on a loaded :py:class:`.InstrumentContext` by altering the :py:obj:`.InstrumentContext.flow_rate` properties listed below. - -* Aspirate: ``InstrumentContext.flow_rate.aspirate`` -* Dispense: ``InstrumentContext.flow_rate.dispense`` -* Blow out: ``InstrumentContext.flow_rate.blow_out`` - -These flow rate properties operate independently. This means you can specify different flow rates for each property within the same protocol. For example, let's load a simple protocol and set different flow rates for the attached pipette. - -.. code-block:: python - - def run(protocol: protocol_api.ProtocolContext): - tiprack1 = protocol.load_labware( - load_name='opentrons_flex_96_tiprack_1000ul', location='D1') - pipette = protocol.load_instrument( - instrument_name='flex_1channel_1000', - mount='left', - tip_racks=[tiprack1]) - plate = protocol.load_labware( - load_name='corning_96_wellplate_360ul_flat', location='D3') - pipette.pick_up_tip() + - :ref:`Loading pipettes ` into your protocol. + - :ref:`Characteristics of pipettes `, such as how fast they can move liquid and how they move around the deck. + - :ref:`Configuring Flex pipettes ` in different modes, such as for low-volume transfers or only using some of their nozzles. -Let's tell the robot to aspirate, dispense, and blow out the liquid using default flow rates. Notice how you don't need to specify a ``flow_rate`` attribute to use the defaults:: - - pipette.aspirate(200, plate['A1']) # 160 µL/s - pipette.dispense(200, plate['A2']) # 160 µL/s - pipette.blow_out() # 80 µL/s - -Now let's change the flow rates for each action:: - - pipette.flow_rate.aspirate = 50 - pipette.flow_rate.dispense = 100 - pipette.flow_rate.blow_out = 75 - pipette.aspirate(200, plate['A1']) # 50 µL/s - pipette.dispense(200, plate['A2']) # 100 µL/s - pipette.blow_out() # 75 µL/s - -These flow rates will remain in effect until you change the ``flow_rate`` attribute again *or* call ``configure_for_volume()``. Calling ``configure_for_volume()`` always resets all pipette flow rates to the defaults for the mode that it sets. - -.. TODO add mode ranges and flow defaults to sections below - -.. note:: - In API version 2.13 and earlier, :py:obj:`.InstrumentContext.speed` offered similar functionality to ``.flow_rate``. It attempted to set the plunger speed in mm/s. Due to technical limitations, that speed could only be approximate. You must use ``.flow_rate`` in version 2.14 and later, and you should consider replacing older code that sets ``.speed``. - -.. versionadded:: 2.0 - - -Flex Pipette Flow Rates ------------------------ - -The default flow rates for Flex pipettes depend on the maximum volume of the pipette and the capacity of the currently attached tip. For each pipette–tip configuration, the default flow rate is the same for aspirate, dispense, and blowout actions. - -.. list-table:: - :header-rows: 1 - - * - Pipette Model - - Tip Capacity (µL) - - Flow Rate (µL/s) - * - 50 µL (1- and 8-channel) - - All capacities - - 57 - * - 1000 µL (1-, 8-, and 96-channel) - - 50 - - 478 - * - 1000 µL (1-, 8-, and 96-channel) - - 200 - - 716 - * - 1000 µL (1-, 8-, and 96-channel) - - 1000 - - 716 - - -Additionally, all Flex pipettes have a well bottom clearance of 1 mm for aspirate and dispense actions. - -.. _ot2-flow-rates: +For information about liquid handling, see :ref:`v2-atomic-commands` and :ref:`v2-complex-commands`. -OT-2 Pipette Flow Rates ------------------------ -The following table provides data on the default aspirate, dispense, and blowout flow rates (in µL/s) for OT-2 GEN2 pipettes. Default flow rates are the same across all three actions. -.. list-table:: - :header-rows: 1 - * - Pipette Model - - Volume (µL) - - Flow Rates (µL/s) - * - P20 Single-Channel GEN2 - - 1–20 - - - * API v2.6 or higher: 7.56 - * API v2.5 or lower: 3.78 - * - P300 Single-Channel GEN2 - - 20–300 - - - * API v2.6 or higher: 92.86 - * API v2.5 or lower: 46.43 - * - P1000 Single-Channel GEN2 - - 100–1000 - - - * API v2.6 or higher: 274.7 - * API v2.5 or lower: 137.35 - * - P20 Multi-Channel GEN2 - - 1–20 - - 7.6 - * - P300 Multi-Channel GEN2 - - 20–300 - - 94 - -Additionally, all OT-2 GEN2 pipettes have a default head speed of 400 mm/s and a well bottom clearance of 1 mm for aspirate and dispense actions. diff --git a/api/docs/v2/pipettes/characteristics.rst b/api/docs/v2/pipettes/characteristics.rst new file mode 100644 index 00000000000..61cf34c858f --- /dev/null +++ b/api/docs/v2/pipettes/characteristics.rst @@ -0,0 +1,246 @@ +####################### +Pipette Characteristics +####################### + +.. _new-multichannel-pipettes: + +Multi-Channel Pipettes +====================== + +All building block and advanced commands work with single- and multi-channel pipettes. + +To keep the interface to the Opentrons API consistent between single- and multi-channel pipettes, commands treat the *backmost channel* (furthest from the door) of a multi-channel pipette as the location of the pipette. Location arguments to building block and advanced commands are specified for the backmost channel. + +Also, this means that offset changes (such as :py:meth:`.Well.top` or :py:meth:`.Well.bottom`) can be applied to the single specified well, and each pipette channel will be at the same position relative to the well that it is over. + +Finally, because there is only one motor in a multi-channel pipette, these pipettes always aspirate and dispense on all channels simultaneously. + +8-Channel, 96-Well Plate Example +-------------------------------- + +To demonstrate these concepts, let's write a protocol that uses a Flex 8-Channel Pipette and a 96-well plate. We'll then aspirate and dispense a liquid to different locations on the same well plate. To start, let's load a pipette in the right mount and add our labware. + +.. code-block:: python + :substitutions: + + from opentrons import protocol_api + + requirements = {'robotType': 'Flex', 'apiLevel':'|apiLevel|'} + + def run(protocol: protocol_api.ProtocolContext): + # Load a tiprack for 1000 µL tips + tiprack1 = protocol.load_labware( + load_name='opentrons_flex_96_tiprack_1000ul', location='D1') + # Load a 96-well plate + plate = protocol.load_labware( + load_name='corning_96_wellplate_360ul_flat', location='C1') + # Load an 8-channel pipette on the right mount + right = protocol.load_instrument( + instrument_name='flex_8channel_1000', + mount='right', + tip_racks=[tiprack1]) + +After loading our instruments and labware, let's tell the robot to pick up a pipette tip from location ``A1`` in ``tiprack1``:: + + right.pick_up_tip() + +With the backmost pipette channel above location A1 on the tip rack, all eight channels are above the eight tip rack wells in column 1. + +After picking up a tip, let's tell the robot to aspirate 300 µL from the well plate at location ``A2``:: + + right.aspirate(volume=300, location=plate['A2']) + +With the backmost pipette tip above location A2 on the well plate, all eight channels are above the eight wells in column 2. + +Finally, let's tell the robot to dispense 300 µL into the well plate at location ``A3``:: + + right.dispense(volume=300, location=plate['A3'].top()) + +With the backmost pipette tip above location A3, all eight channels are above the eight wells in column 3. The pipette will dispense liquid into all the wells simultaneously. + +8-Channel, 384-Well Plate Example +--------------------------------- + +In general, you should specify wells in the first row of a well plate when using multi-channel pipettes. An exception to this rule is when using 384-well plates. The greater well density means the nozzles of a multi-channel pipette can only access every other well in a column. Specifying well A1 accesses every other well starting with the first (rows A, C, E, G, I, K, M, and O). Similarly, specifying well B1 also accesses every other well, but starts with the second (rows B, D, F, H, J, L, N, and P). + +To demonstrate these concepts, let's write a protocol that uses a Flex 8-Channel Pipette and a 384-well plate. We'll then aspirate and dispense a liquid to different locations on the same well plate. To start, let's load a pipette in the right mount and add our labware. + +.. code-block:: python + + def run(protocol: protocol_api.ProtocolContext): + # Load a tiprack for 200 µL tips + tiprack1 = protocol.load_labware( + load_name='opentrons_flex_96_tiprack_200ul', location="D1") + # Load a well plate + plate = protocol.load_labware( + load_name='corning_384_wellplate_112ul_flat', location="D2") + # Load an 8-channel pipette on the right mount + right = protocol.load_instrument( + instrument_name='flex_8channel_1000', + mount='right', + tip_racks=[tiprack1]) + + +After loading our instruments and labware, let's tell the robot to pick up a pipette tip from location ``A1`` in ``tiprack1``:: + + right.pick_up_tip() + +With the backmost pipette channel above location A1 on the tip rack, all eight channels are above the eight tip rack wells in column 1. + +After picking up a tip, let's tell the robot to aspirate 100 µL from the well plate at location ``A1``:: + + right.aspirate(volume=100, location=plate['A1']) + +The eight pipette channels will only aspirate from every other well in the column: A1, C1, E1, G1, I1, K1, M1, and O1. + +Finally, let's tell the robot to dispense 100 µL into the well plate at location ``B1``:: + + right.dispense(volume=100, location=plate['B1']) + +The eight pipette channels will only dispense into every other well in the column: B1, D1, F1, H1, J1, L1, N1, and P1. + + +.. _new-plunger-flow-rates: + +Pipette Flow Rates +================== + +Measured in µL/s, the flow rate determines how much liquid a pipette can aspirate, dispense, and blow out. Opentrons pipettes have their own default flow rates. The API lets you change the flow rate on a loaded :py:class:`.InstrumentContext` by altering the :py:obj:`.InstrumentContext.flow_rate` properties listed below. + +* Aspirate: ``InstrumentContext.flow_rate.aspirate`` +* Dispense: ``InstrumentContext.flow_rate.dispense`` +* Blow out: ``InstrumentContext.flow_rate.blow_out`` + +These flow rate properties operate independently. This means you can specify different flow rates for each property within the same protocol. For example, let's load a simple protocol and set different flow rates for the attached pipette. + +.. code-block:: python + + def run(protocol: protocol_api.ProtocolContext): + tiprack1 = protocol.load_labware( + load_name='opentrons_flex_96_tiprack_1000ul', location='D1') + pipette = protocol.load_instrument( + instrument_name='flex_1channel_1000', + mount='left', + tip_racks=[tiprack1]) + plate = protocol.load_labware( + load_name='corning_96_wellplate_360ul_flat', location='D3') + pipette.pick_up_tip() + +Let's tell the robot to aspirate, dispense, and blow out the liquid using default flow rates. Notice how you don't need to specify a ``flow_rate`` attribute to use the defaults:: + + pipette.aspirate(200, plate['A1']) # 160 µL/s + pipette.dispense(200, plate['A2']) # 160 µL/s + pipette.blow_out() # 80 µL/s + +Now let's change the flow rates for each action:: + + pipette.flow_rate.aspirate = 50 + pipette.flow_rate.dispense = 100 + pipette.flow_rate.blow_out = 75 + pipette.aspirate(200, plate['A1']) # 50 µL/s + pipette.dispense(200, plate['A2']) # 100 µL/s + pipette.blow_out() # 75 µL/s + +These flow rates will remain in effect until you change the ``flow_rate`` attribute again *or* call ``configure_for_volume()``. Calling ``configure_for_volume()`` always resets all pipette flow rates to the defaults for the mode that it sets. + +.. TODO add mode ranges and flow defaults to sections below + +.. note:: + In API version 2.13 and earlier, :py:obj:`.InstrumentContext.speed` offered similar functionality to ``.flow_rate``. It attempted to set the plunger speed in mm/s. Due to technical limitations, that speed could only be approximate. You must use ``.flow_rate`` in version 2.14 and later, and you should consider replacing older code that sets ``.speed``. + +.. versionadded:: 2.0 + + +Flex Pipette Flow Rates +----------------------- + +The default flow rates for Flex pipettes depend on the maximum volume of the pipette and the capacity of the currently attached tip. For each pipette–tip configuration, the default flow rate is the same for aspirate, dispense, and blowout actions. + +.. list-table:: + :header-rows: 1 + + * - Pipette Model + - Tip Capacity (µL) + - Flow Rate (µL/s) + * - 50 µL (1- and 8-channel) + - All capacities + - 57 + * - 1000 µL (1-, 8-, and 96-channel) + - 50 + - 478 + * - 1000 µL (1-, 8-, and 96-channel) + - 200 + - 716 + * - 1000 µL (1-, 8-, and 96-channel) + - 1000 + - 716 + + +Additionally, all Flex pipettes have a well bottom clearance of 1 mm for aspirate and dispense actions. + +.. _ot2-flow-rates: + +OT-2 Pipette Flow Rates +----------------------- + +The following table provides data on the default aspirate, dispense, and blowout flow rates (in µL/s) for OT-2 GEN2 pipettes. Default flow rates are the same across all three actions. + +.. list-table:: + :header-rows: 1 + + * - Pipette Model + - Volume (µL) + - Flow Rates (µL/s) + * - P20 Single-Channel GEN2 + - 1–20 + - + * API v2.6 or higher: 7.56 + * API v2.5 or lower: 3.78 + * - P300 Single-Channel GEN2 + - 20–300 + - + * API v2.6 or higher: 92.86 + * API v2.5 or lower: 46.43 + * - P1000 Single-Channel GEN2 + - 100–1000 + - + * API v2.6 or higher: 274.7 + * API v2.5 or lower: 137.35 + * - P20 Multi-Channel GEN2 + - 1–20 + - 7.6 + * - P300 Multi-Channel GEN2 + - 20–300 + - 94 + +Additionally, all OT-2 GEN2 pipettes have a default head speed of 400 mm/s and a well bottom clearance of 1 mm for aspirate and dispense actions. + +OT-2 Pipette Generations +======================== + +The OT-2 works with the GEN1 and GEN2 pipette models. The newer GEN2 pipettes have different volume ranges than the older GEN1 pipettes. With some exceptions, the volume ranges for GEN2 pipettes overlap those used by the GEN1 models. If your protocol specifies a GEN1 pipette, but you have a GEN2 pipette with a compatible volume range, you can still run your protocol. The OT-2 will consider the GEN2 pipette to have the same minimum volume as the GEN1 pipette. The following table lists the volume compatibility between the GEN2 and GEN1 pipettes. + +.. list-table:: + :header-rows: 1 + + * - GEN2 Pipette + - GEN1 Pipette + - GEN1 Volume + * - P20 Single-Channel GEN2 + - P10 Single-Channel GEN1 + - 1-10 µL + * - P20 Multi-Channel GEN2 + - P10 Multi-Channel GEN1 + - 1-10 µL + * - P300 Single-Channel GEN2 + - P300 Single-Channel GEN1 + - 30-300 µL + * - P300 Multi-Channel GEN2 + - P300 Multi-Channel GEN1 + - 20-200 µL + * - P1000 Single-Channel GEN2 + - P1000 Single-Channel GEN1 + - 100-1000 µL + +The single- and multi-channel P50 GEN1 pipettes are the exceptions here. If your protocol uses a P50 GEN1 pipette, there is no backward compatibility with a related GEN2 pipette. To replace a P50 GEN1 with a corresponding GEN2 pipette, edit your protocol to load a P20 Single-Channel GEN2 (for volumes below 20 µL) or a P300 Single-Channel GEN2 (for volumes between 20 and 50 µL). + diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst new file mode 100644 index 00000000000..ca6cd32877d --- /dev/null +++ b/api/docs/v2/pipettes/configuring.rst @@ -0,0 +1,60 @@ +######################### +Configuring Pipette Modes +######################### + +TK configuring intro + +Partial Tip Pickup +================== + +TKTKTK + +.. _pipette-volume-modes: + +Volume Modes +============ + +The Flex 1-Channel 50 µL and Flex 8-Channel 50 µL pipettes must operate in a low-volume mode to accurately dispense very small volumes of liquid. Set the volume mode by calling :py:meth:`.InstrumentContext.configure_for_volume` with the amount of liquid you plan to aspirate, in µL:: + + pipette50.configure_for_volume(1) + pipette50.pick_up_tip() + pipette50.aspirate(1, plate["A1"]) + +.. versionadded:: 2.15 + +Passing different values to ``configure_for_volume()`` changes the minimum and maximum volume of Flex 50 µL pipettes as follows: + +.. list-table:: + :header-rows: 1 + :widths: 2 3 3 + + * - Value + - Minimum Volume (µL) + - Maximum Volume (µL) + * - 1–4.9 + - 1 + - 30 + * - 5–50 + - 5 + - 50 + +.. note:: + The pipette must not contain liquid when you call ``configure_for_volume()``, or the API will raise an error. + + Also, if the pipette is in a well location that may contain liquid, it will move upward to ensure it is not immersed in liquid before changing its mode. Calling ``configure_for_volume()`` *before* ``pick_up_tip()`` helps to avoid this situation. + +In a protocol that handles many different volumes, it's a good practice to call ``configure_for_volume()`` once for each :py:meth:`.transfer` or :py:meth:`.aspirate`, specifying the volume that you are about to handle. When operating with a list of volumes, nest ``configure_for_volume()`` inside a ``for`` loop to ensure that the pipette is properly configured for each volume: + +.. code-block:: python + + volumes = [1, 2, 3, 4, 1, 5, 2, 8] + sources = plate.columns()[0] + destinations = plate.columns()[1] + for i in range(8): + pipette50.configure_for_volume(volumes[i]) + pipette50.pick_up_tip() + pipette50.aspirate(volume=volumes[i], location=sources[i]) + pipette50.dispense(location=destinations[i]) + pipette50.drop_tip() + +If you know that all your liquid handling will take place in a specific mode, then you can call ``configure_for_volume()`` just once with a representative volume. Or if all the volumes correspond to the pipette's default mode, you don't have to call ``configure_for_volume()`` at all. diff --git a/api/docs/v2/pipettes/loading.rst b/api/docs/v2/pipettes/loading.rst new file mode 100644 index 00000000000..379d42b48ae --- /dev/null +++ b/api/docs/v2/pipettes/loading.rst @@ -0,0 +1,171 @@ +When writing a protocol, you must inform the Protocol API about the pipettes you will be using on your robot. The :py:meth:`.ProtocolContext.load_instrument` function provides this information and returns an :py:class:`.InstrumentContext` object. + +For information about liquid handling, see :ref:`v2-atomic-commands` and :ref:`v2-complex-commands`. + +.. _new-create-pipette: + +Loading Pipettes +================ + +As noted above, you call the :py:meth:`~.ProtocolContext.load_instrument` method to load a pipette. This method also requires the :ref:`pipette's API load name `, its left or right mount position, and (optionally) a list of associated tip racks. Even if you don't use the pipette anywhere else in your protocol, the Opentrons App and the robot won't let you start the protocol run until all pipettes loaded by ``load_instrument()`` are attached properly. + +.. _new-pipette-models: + +API Load Names +-------------- + +The pipette's API load name (``instrument_name``) is the first parameter of the ``load_instrument()`` method. It tells your robot which attached pipette you're going to use in a protocol. The tables below list the API load names for the currently available Flex and OT-2 pipettes. + +.. tabs:: + + .. tab:: Flex Pipettes + + +-------------------------+---------------+-------------------------+ + | Pipette Model | Volume (µL) | API Load Name | + +=========================+===============+===+=====================+ + | Flex 1-Channel Pipette | 1–50 | ``flex_1channel_50`` | + + +---------------+-------------------------+ + | | 5–1000 | ``flex_1channel_1000`` | + +-------------------------+---------------+-------------------------+ + | Flex 8-Channel Pipette | 1–50 | ``flex_8channel_50`` | + + +---------------+-------------------------+ + | | 5–1000 | ``flex_8channel_1000`` | + +-------------------------+---------------+-------------------------+ + | Flex 96-Channel Pipette | 5–1000 | ``flex_96channel_1000`` | + +-------------------------+---------------+-------------------------+ + + .. tab:: OT-2 Pipettes + + +-----------------------------+--------------------+-----------------------+ + | Pipette Model | Volume (µL) | API Load Name | + +=============================+====================+=======================+ + | P20 Single-Channel GEN2 | 1-20 | ``p20_single_gen2`` | + +-----------------------------+ +-----------------------+ + | P20 Multi-Channel GEN2 | | ``p20_multi_gen2`` | + +-----------------------------+--------------------+-----------------------+ + | P300 Single-Channel GEN2 | 20-300 | ``p300_single_gen2`` | + +-----------------------------+ +-----------------------+ + | P300 Multi-Channel GEN2 | | ``p300_multi_gen2`` | + +-----------------------------+--------------------+-----------------------+ + | P1000 Single-Channel GEN2 | 100-1000 | ``p1000_single_gen2`` | + +-----------------------------+--------------------+-----------------------+ + + See the OT-2 Pipette Generations section below if you're using GEN1 pipettes on an OT-2. The GEN1 family includes the P10, P50, and P300 single- and multi-channel pipettes, along with the P1000 single-chanel model. + +Loading Flex 1- and 8-Channel Pipettes +-------------------------------------- + +This code sample loads a Flex 1-Channel Pipette in the left mount and a Flex 8-Channel Pipette in the right mount. Both pipettes are 1000 µL. Each pipette uses its own 1000 µL tip rack. + +.. code-block:: Python + :substitutions: + + from opentrons import protocol_api + + requirements = {'robotType': 'Flex', 'apiLevel':'|apiLevel|'} + + def run(protocol: protocol_api.ProtocolContext): + tiprack1 = protocol.load_labware( + load_name='opentrons_flex_96_tiprack_1000ul', location='D1') + tiprack2 = protocol.load_labware( + load_name='opentrons_flex_96_tiprack_1000ul', location='C1') + left = protocol.load_instrument( + instrument_name='flex_1channel_1000', + mount='left', + tip_racks=[tiprack1]) + right = protocol.load_instrument( + instrument_name='flex_8channel_1000', + mount='right', + tip_racks=[tiprack2]) + +If you're writing a protocol that uses the Flex Gripper, you might think that this would be the place in your protocol to declare that. However, the gripper doesn't require ``load_instrument``! Whether your gripper requires a protocol is determined by the presence of :py:meth:`.ProtocolContext.move_labware` commands. See :ref:`moving-labware` for more details. + +Loading a Flex 96-Channel Pipette +--------------------------------- + +This code sample loads the Flex 96-Channel Pipette. Because of its size, the Flex 96-Channel Pipette requires the left *and* right pipette mounts. You cannot use this pipette with 1- or 8-Channel Pipette in the same protocol or when these instruments are attached to the robot. To load the 96-Channel Pipette, specify its position as ``mount='left'`` as shown here: + +.. code-block:: python + + def run(protocol: protocol_api.ProtocolContext): + left = protocol.load_instrument( + instrument_name='flex_96channel_1000', mount='left') + +.. versionadded:: 2.15 + +Loading OT-2 Pipettes +--------------------- + +This code sample loads a P1000 Single-Channel GEN2 pipette in the left mount and a P300 Single-Channel GEN2 pipette in the right mount. Each pipette uses its own 1000 µL tip rack. + +.. code-block:: python + :substitutions: + + from opentrons import protocol_api + + metadata = {'apiLevel': '2.14'} + + def run(protocol: protocol_api.ProtocolContext): + tiprack1 = protocol.load_labware( + load_name='opentrons_96_tiprack_1000ul', location=1) + tiprack2 = protocol.load_labware( + load_name='opentrons_96_tiprack_1000ul', location=2) + left = protocol.load_instrument( + instrument_name='p1000_single_gen2', + mount='left', + tip_racks=[tiprack1]) + right = protocol.load_instrument( + instrument_name='p300_multi_gen2', + mount='right', + tip_racks=[tiprack1]) + +.. versionadded:: 2.0 + +.. _pipette-tip-racks: + +Adding Tip Racks +---------------- + +The ``load_instrument()`` method includes the optional argument ``tip_racks``. This parameter accepts a list of tip rack labware objects, which lets you to specify as many tip racks as you want. The advantage of using ``tip_racks`` is twofold. First, associating tip racks with your pipette allows for automatic tip tracking throughout your protocol. Second, it removes the need to specify tip locations in the :py:meth:`.InstrumentContext.pick_up_tip` method. For example, let's start by loading loading some labware and instruments like this:: + + def run(protocol: protocol_api.ProtocolContext): + tiprack_left = protocol.load_labware( + load_name='opentrons_flex_96_tiprack_200ul', location='D1') + tiprack_right = protocol.load_labware( + load_name='opentrons_flex_96_tiprack_200ul', location='D2') + left_pipette = protocol.load_instrument( + instrument_name='flex_8channel_1000', mount='left') + right_pipette = protocol.load_instrument( + instrument_name='flex_8channel_1000', + mount='right', + tip_racks=[tiprack_right]) + +Let's pick up a tip with the left pipette. We need to specify the location as an argument of ``pick_up_tip()``, since we loaded the left pipette without a ``tip_racks`` argument. + +.. code-block:: python + + left_pipette.pick_up_tip(tiprack_left['A1']) + left_pipette.drop_tip() + +But now you have to specify ``tiprack_left`` every time you call ``pick_up_tip``, which means you're doing all your own tip tracking:: + + left_pipette.pick_up_tip(tiprack_left['A2']) + left_pipette.drop_tip() + left_pipette.pick_up_tip(tiprack_left['A3']) + left_pipette.drop_tip() + +However, because you specified a tip rack location for the right pipette, the robot will automatically pick up from location ``A1`` of its associated tiprack:: + + right_pipette.pick_up_tip() + right_pipette.drop_tip() + +Additional calls to ``pick_up_tip`` will automatically progress through the tips in the right rack:: + + right_pipette.pick_up_tip() # picks up from A2 + right_pipette.drop_tip() + right_pipette.pick_up_tip() # picks up from A3 + right_pipette.drop_tip() + +See also, :ref:`v2-atomic-commands` and :ref:`v2-complex-commands`. + +.. versionadded:: 2.0 From 0b3870e931ba363ce0540df8d5c8f840d7332998 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Wed, 13 Dec 2023 12:27:10 -0500 Subject: [PATCH 02/14] first draft landing page + links --- api/docs/v2/pipettes/characteristics.rst | 2 ++ api/docs/v2/pipettes/configuring.rst | 2 ++ api/docs/v2/pipettes/loading.rst | 7 +++---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/api/docs/v2/pipettes/characteristics.rst b/api/docs/v2/pipettes/characteristics.rst index 61cf34c858f..7f1bd19d89b 100644 --- a/api/docs/v2/pipettes/characteristics.rst +++ b/api/docs/v2/pipettes/characteristics.rst @@ -1,3 +1,5 @@ +.. _pipette-characteristics: + ####################### Pipette Characteristics ####################### diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index ca6cd32877d..a9ecc69f7f5 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -1,3 +1,5 @@ +.. _configuring-pipette-modes: + ######################### Configuring Pipette Modes ######################### diff --git a/api/docs/v2/pipettes/loading.rst b/api/docs/v2/pipettes/loading.rst index 379d42b48ae..f5caee2b493 100644 --- a/api/docs/v2/pipettes/loading.rst +++ b/api/docs/v2/pipettes/loading.rst @@ -1,12 +1,11 @@ -When writing a protocol, you must inform the Protocol API about the pipettes you will be using on your robot. The :py:meth:`.ProtocolContext.load_instrument` function provides this information and returns an :py:class:`.InstrumentContext` object. - -For information about liquid handling, see :ref:`v2-atomic-commands` and :ref:`v2-complex-commands`. - .. _new-create-pipette: +.. _loading-pipettes: Loading Pipettes ================ +When writing a protocol, you must inform the Protocol API about the pipettes you will be using on your robot. The :py:meth:`.ProtocolContext.load_instrument` function provides this information and returns an :py:class:`.InstrumentContext` object. + As noted above, you call the :py:meth:`~.ProtocolContext.load_instrument` method to load a pipette. This method also requires the :ref:`pipette's API load name `, its left or right mount position, and (optionally) a list of associated tip racks. Even if you don't use the pipette anywhere else in your protocol, the Opentrons App and the robot won't let you start the protocol run until all pipettes loaded by ``load_instrument()`` are attached properly. .. _new-pipette-models: From 07a3c938b3c329d8e169b8306a8e9cd9f850a75a Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Mon, 18 Dec 2023 17:10:33 -0500 Subject: [PATCH 03/14] fix up header styles --- api/docs/v2/pipettes/characteristics.rst | 4 ++-- api/docs/v2/pipettes/configuring.rst | 4 ++-- api/docs/v2/pipettes/loading.rst | 13 +++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/api/docs/v2/pipettes/characteristics.rst b/api/docs/v2/pipettes/characteristics.rst index 7f1bd19d89b..1b91ce3ec76 100644 --- a/api/docs/v2/pipettes/characteristics.rst +++ b/api/docs/v2/pipettes/characteristics.rst @@ -1,8 +1,8 @@ .. _pipette-characteristics: -####################### +*********************** Pipette Characteristics -####################### +*********************** .. _new-multichannel-pipettes: diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index a9ecc69f7f5..122a01b02bf 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -1,8 +1,8 @@ .. _configuring-pipette-modes: -######################### +************************* Configuring Pipette Modes -######################### +************************* TK configuring intro diff --git a/api/docs/v2/pipettes/loading.rst b/api/docs/v2/pipettes/loading.rst index f5caee2b493..f873e9bd157 100644 --- a/api/docs/v2/pipettes/loading.rst +++ b/api/docs/v2/pipettes/loading.rst @@ -1,8 +1,9 @@ .. _new-create-pipette: .. _loading-pipettes: +**************** Loading Pipettes -================ +**************** When writing a protocol, you must inform the Protocol API about the pipettes you will be using on your robot. The :py:meth:`.ProtocolContext.load_instrument` function provides this information and returns an :py:class:`.InstrumentContext` object. @@ -11,7 +12,7 @@ As noted above, you call the :py:meth:`~.ProtocolContext.load_instrument` method .. _new-pipette-models: API Load Names --------------- +============== The pipette's API load name (``instrument_name``) is the first parameter of the ``load_instrument()`` method. It tells your robot which attached pipette you're going to use in a protocol. The tables below list the API load names for the currently available Flex and OT-2 pipettes. @@ -52,7 +53,7 @@ The pipette's API load name (``instrument_name``) is the first parameter of the See the OT-2 Pipette Generations section below if you're using GEN1 pipettes on an OT-2. The GEN1 family includes the P10, P50, and P300 single- and multi-channel pipettes, along with the P1000 single-chanel model. Loading Flex 1- and 8-Channel Pipettes --------------------------------------- +====================================== This code sample loads a Flex 1-Channel Pipette in the left mount and a Flex 8-Channel Pipette in the right mount. Both pipettes are 1000 µL. Each pipette uses its own 1000 µL tip rack. @@ -80,7 +81,7 @@ This code sample loads a Flex 1-Channel Pipette in the left mount and a Flex 8-C If you're writing a protocol that uses the Flex Gripper, you might think that this would be the place in your protocol to declare that. However, the gripper doesn't require ``load_instrument``! Whether your gripper requires a protocol is determined by the presence of :py:meth:`.ProtocolContext.move_labware` commands. See :ref:`moving-labware` for more details. Loading a Flex 96-Channel Pipette ---------------------------------- +================================= This code sample loads the Flex 96-Channel Pipette. Because of its size, the Flex 96-Channel Pipette requires the left *and* right pipette mounts. You cannot use this pipette with 1- or 8-Channel Pipette in the same protocol or when these instruments are attached to the robot. To load the 96-Channel Pipette, specify its position as ``mount='left'`` as shown here: @@ -93,7 +94,7 @@ This code sample loads the Flex 96-Channel Pipette. Because of its size, the Fle .. versionadded:: 2.15 Loading OT-2 Pipettes ---------------------- +===================== This code sample loads a P1000 Single-Channel GEN2 pipette in the left mount and a P300 Single-Channel GEN2 pipette in the right mount. Each pipette uses its own 1000 µL tip rack. @@ -123,7 +124,7 @@ This code sample loads a P1000 Single-Channel GEN2 pipette in the left mount and .. _pipette-tip-racks: Adding Tip Racks ----------------- +================ The ``load_instrument()`` method includes the optional argument ``tip_racks``. This parameter accepts a list of tip rack labware objects, which lets you to specify as many tip racks as you want. The advantage of using ``tip_racks`` is twofold. First, associating tip racks with your pipette allows for automatic tip tracking throughout your protocol. Second, it removes the need to specify tip locations in the :py:meth:`.InstrumentContext.pick_up_tip` method. For example, let's start by loading loading some labware and instruments like this:: From b779d05d9ac5374bdc643bbad417d341b69bb326 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Mon, 18 Dec 2023 18:47:33 -0500 Subject: [PATCH 04/14] Configuring intro + first bit of partial pickup --- api/docs/v2/pipettes/configuring.rst | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index 122a01b02bf..bf03198ba45 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -4,12 +4,35 @@ Configuring Pipette Modes ************************* -TK configuring intro +The API provides methods to configure certain pipettes to operate in a specific mode. These configuration methods change the default behavior of the pipette on an ongoing basis, until you call them again with different values. + +This page covers the currently available modes. + +- :ref:`partial-tip-pickup`: The 96-channel pipette can be configured to use 8 or 96 nozzles for pipetting. +- :ref:`pipette-volume-modes`: The Flex 50 µL pipettes can be configured to handle liquid differently for low or high volumes. + +There are no mode configurations for OT-2 pipettes. + + +.. _partial-tip-pickup: Partial Tip Pickup ================== -TKTKTK +The 96-channel pipette occupies both pipette mounts on Flex, so it's not possible to attach another pipette at the same time. Partial tip pickup lets you perform some of the same actions that you would be able to perform with a second pipette. As of version 2.16 of the API, you can configure the 96-channel pipette pick up a single column of tips, similar to the behavior of an 8-channel pipette. + +Nozzle Layout +------------- + +Use the :py:meth:`.configure_nozzle_layout` method to choose how many tips the 96-channel pipette will pick up + + +Tip Rack Adapters +----------------- + + +Tip Pickup and Return Behavior +------------------------------ .. _pipette-volume-modes: From bbabd0a398892a69784ab6f99cad3b0a0dea7b14 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Mon, 18 Dec 2023 22:21:05 -0500 Subject: [PATCH 05/14] first stab at basic column pickup --- api/docs/v2/pipettes/configuring.rst | 54 +++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index bf03198ba45..ace9b4bc604 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -24,8 +24,60 @@ The 96-channel pipette occupies both pipette mounts on Flex, so it's not possibl Nozzle Layout ------------- -Use the :py:meth:`.configure_nozzle_layout` method to choose how many tips the 96-channel pipette will pick up +Use the :py:meth:`.configure_nozzle_layout` method to choose how many tips the 96-channel pipette will pick up. The method's ``style`` parameter accepts special layout constants. When using partial tip pickup, it's generally easiest to import these at the top of your protocol. +.. code-block:: python + + from opentrons import protocol_api + from opentrons.protocol_api import COLUMN, ALL + +Then when you call ``configure_nozzle_layout`` later in your protocol, you can set ``style=COLUMN``. If, instead, you use ``from opentrons import protocol_api``, then you can pass ``protocol_api.COLUMN``. If you don't put any ``import`` statements at the top of your protocol, you won't be able to configure the nozzle layout. + +Assuming the ``import`` statements from above, here is the start of a protocol that loads a 96-channel pipette and sets it to pick up a single column of tips. + +.. code-block:: python + :substitutions: + + requirements = {"robotType": "Flex", "apiLevel": "|apiLevel|"} + + def run(protocol: protocol_api.ProtocolContext): + partial_pickup_tips = protocol.load_labware( + load_name="opentrons_flex_96_tiprack_1000ul", + location="D3" + ) + pipette = protocol.load_instrument("flex_96channel_1000") + pipette.configure_nozzle_layout( + style=COLUMN, + start="A12", + tip_racks=[partial_pickup_tips] + ) + +.. versionadded: 2.16 + +Let's unpack some of the details of this code. + +First, we've given a special name to the tip rack, ``partial_pickup_tips``. You can name your tip racks whatever you like, but if you're performing full pickup and partial pickup in the same protocol, you'll need to keep them separate. See :ref:`partial-tip-rack-adapters` below. + +Next, we load the 96-channel pipette. Note that ``load_instrument()`` only has a single argument. The 96-channel pipette occupies both mounts, so ``mount`` is omissible. The ``tip_racks`` argument is always optional. But it would have no effect to declare it here, because every call to ``configure_nozzle_layout()`` resets the pipette's :py:obj:`.InstrumentContext.tip_racks` property. + +Finally, we configure the nozzle layout, with three arguments. + + - The ``style`` parameter directly accepts the ``COLUMN`` constant, since we imported it at the top of the protocol. + - The ``start`` parameter accepts a nozzle name, representing the back-left nozzle in the layout, as a string. ``"A12"`` tells the pipette to use its rightmost column of nozzles for pipetting. + - The ``tip_racks`` parameter tells the pipette which racks to use for tip tracking, just like when loading a pipette. + +Now that the pipette is configured in column mode, pipetting actions will use a single column:: + + # configured in COLUMN mode + pipette.pick_up_tip() # picks up A1-H1 from tip rack + pipette.drop_tip() + pipette.pick_up_tip() # picks up A2-H2 from tip rack + +.. warning:: + + :py:meth:`.InstrumentContext.pick_up_tip` always accepts a ``location`` argument, regardless of nozzle configuration. Do not pass a value that would lead the pipette to line up over more unused tips than specified by the current layout. For example, setting ``COLUMN`` layout and then calling ``pipette.pick_up_tip(tip_rack["A2"])`` on a full tip rack will lead to unexpected pipetting behavior and potential crashes. + +.. _partial-tip-rack-adapters: Tip Rack Adapters ----------------- From d7cadf967c0b0fca473c6afa0fa03d29fce96007 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Mon, 18 Dec 2023 23:17:05 -0500 Subject: [PATCH 06/14] =?UTF-8?q?first=20draft=20of=20tip=20rack=20adapter?= =?UTF-8?q?s=20=C2=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/docs/v2/pipettes/configuring.rst | 51 +++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index ace9b4bc604..e12c2068887 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -41,7 +41,7 @@ Assuming the ``import`` statements from above, here is the start of a protocol t requirements = {"robotType": "Flex", "apiLevel": "|apiLevel|"} def run(protocol: protocol_api.ProtocolContext): - partial_pickup_tips = protocol.load_labware( + tip_rack = protocol.load_labware( load_name="opentrons_flex_96_tiprack_1000ul", location="D3" ) @@ -49,7 +49,7 @@ Assuming the ``import`` statements from above, here is the start of a protocol t pipette.configure_nozzle_layout( style=COLUMN, start="A12", - tip_racks=[partial_pickup_tips] + tip_racks=[tip_rack] ) .. versionadded: 2.16 @@ -66,7 +66,7 @@ Finally, we configure the nozzle layout, with three arguments. - The ``start`` parameter accepts a nozzle name, representing the back-left nozzle in the layout, as a string. ``"A12"`` tells the pipette to use its rightmost column of nozzles for pipetting. - The ``tip_racks`` parameter tells the pipette which racks to use for tip tracking, just like when loading a pipette. -Now that the pipette is configured in column mode, pipetting actions will use a single column:: +In this configuration, pipetting actions will use a single column:: # configured in COLUMN mode pipette.pick_up_tip() # picks up A1-H1 from tip rack @@ -82,9 +82,50 @@ Now that the pipette is configured in column mode, pipetting actions will use a Tip Rack Adapters ----------------- +Partial tip pickup requires a tip rack that is placed directly in a deck slot. When picking up fewer than 96 tips, the 96-channel pipette lowers onto the tip rack in a horizontally offset position. If the tip rack were in the tip rack adapter, the pipette would collide with the adapter's posts, which protrude above the top of the tip rack. If you configure a partial nozzle layout and then call ``pick_up_tip()`` on a tip rack that's in an adapter, the API will raise an error. -Tip Pickup and Return Behavior ------------------------------- +On the other hand, full tip pickup requires the tip rack adapter. If the 96-channel pipette is in a full layout, either by default or by configuring ``style=ALL``, and you then call ``pick_up_tip()`` on a tip rack that's not in an adapter, the API will raise an error. + +If your protocol switches between full and partial pickup, you may want to organize your tip racks into lists, depending on whether they're loaded on adapters or not. + +.. code-block:: python + + tips_1 = protocol.load_labware( + "opentrons_flex_96_tiprack_1000ul", "D1" + ) + tips_2 = protocol.load_labware( + "opentrons_flex_96_tiprack_1000ul", "D2" + ) + tips_3 = protocol.load_labware( + "opentrons_flex_96_tiprack_1000ul", "C1", + adapter="opentrons_flex_96_tiprack_adapter" + ) + tips_4 = protocol.load_labware( + "opentrons_flex_96_tiprack_1000ul", "C2", + adapter="opentrons_flex_96_tiprack_adapter" + ) + + partial_tip_racks = [tips_1, tips_2] + full_tip_racks = [tips_3, tips_4] + +Now, when you configure the nozzle layout, you can use the appropriate list as the value of ``tip_racks``:: + + pipette.configure_nozzle_layout( + style=COLUMN, + start="A12", + tip_racks=partial_tip_racks + ) + # partial pipetting commands go here + + pipette.configure_nozzle_layout( + style=ALL, + tip_racks=full_tip_racks + ) + pipette.pick_up_tip() # picks up full rack in C1 + + +Tip Pickup and Conflicts +------------------------ .. _pipette-volume-modes: From 7af3e1498115a0c8799d17b9862c8a3c19fccdc4 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Tue, 19 Dec 2023 14:33:12 -0500 Subject: [PATCH 07/14] =?UTF-8?q?prose=20edits,=20first=20line=20of=20Tip?= =?UTF-8?q?=20Pickup=20=C2=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/docs/v2/pipettes/configuring.rst | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index e12c2068887..337121aebdd 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -41,7 +41,7 @@ Assuming the ``import`` statements from above, here is the start of a protocol t requirements = {"robotType": "Flex", "apiLevel": "|apiLevel|"} def run(protocol: protocol_api.ProtocolContext): - tip_rack = protocol.load_labware( + column_rack = protocol.load_labware( load_name="opentrons_flex_96_tiprack_1000ul", location="D3" ) @@ -49,14 +49,14 @@ Assuming the ``import`` statements from above, here is the start of a protocol t pipette.configure_nozzle_layout( style=COLUMN, start="A12", - tip_racks=[tip_rack] + tip_racks=[column_rack] ) -.. versionadded: 2.16 +.. versionadded:: 2.16 Let's unpack some of the details of this code. -First, we've given a special name to the tip rack, ``partial_pickup_tips``. You can name your tip racks whatever you like, but if you're performing full pickup and partial pickup in the same protocol, you'll need to keep them separate. See :ref:`partial-tip-rack-adapters` below. +First, we've given a special name to the tip rack, ``column_rack``. You can name your tip racks whatever you like, but if you're performing full pickup and partial pickup in the same protocol, you'll need to keep them separate. See :ref:`partial-tip-rack-adapters` below. Next, we load the 96-channel pipette. Note that ``load_instrument()`` only has a single argument. The 96-channel pipette occupies both mounts, so ``mount`` is omissible. The ``tip_racks`` argument is always optional. But it would have no effect to declare it here, because every call to ``configure_nozzle_layout()`` resets the pipette's :py:obj:`.InstrumentContext.tip_racks` property. @@ -64,7 +64,7 @@ Finally, we configure the nozzle layout, with three arguments. - The ``style`` parameter directly accepts the ``COLUMN`` constant, since we imported it at the top of the protocol. - The ``start`` parameter accepts a nozzle name, representing the back-left nozzle in the layout, as a string. ``"A12"`` tells the pipette to use its rightmost column of nozzles for pipetting. - - The ``tip_racks`` parameter tells the pipette which racks to use for tip tracking, just like when loading a pipette. + - The ``tip_racks`` parameter tells the pipette which racks to use for tip tracking, just like :ref:`adding tip racks ` when loading a pipette. In this configuration, pipetting actions will use a single column:: @@ -82,7 +82,7 @@ In this configuration, pipetting actions will use a single column:: Tip Rack Adapters ----------------- -Partial tip pickup requires a tip rack that is placed directly in a deck slot. When picking up fewer than 96 tips, the 96-channel pipette lowers onto the tip rack in a horizontally offset position. If the tip rack were in the tip rack adapter, the pipette would collide with the adapter's posts, which protrude above the top of the tip rack. If you configure a partial nozzle layout and then call ``pick_up_tip()`` on a tip rack that's in an adapter, the API will raise an error. +Partial tip pickup requires a tip rack that is placed directly in a deck slot. When picking up fewer than 96 tips, the 96-channel pipette lowers onto the tip rack in a horizontally offset position. If the tip rack were in the tip rack adapter, the pipette would collide with the adapter's posts, which protrude above the top of the tip rack. If you configure a partial nozzle layout and then call ``pick_up_tip()`` on a tip rack that's loaded onto an adapter, the API will raise an error. On the other hand, full tip pickup requires the tip rack adapter. If the 96-channel pipette is in a full layout, either by default or by configuring ``style=ALL``, and you then call ``pick_up_tip()`` on a tip rack that's not in an adapter, the API will raise an error. @@ -91,17 +91,17 @@ If your protocol switches between full and partial pickup, you may want to organ .. code-block:: python tips_1 = protocol.load_labware( - "opentrons_flex_96_tiprack_1000ul", "D1" + "opentrons_flex_96_tiprack_1000ul", "C1" ) tips_2 = protocol.load_labware( - "opentrons_flex_96_tiprack_1000ul", "D2" + "opentrons_flex_96_tiprack_1000ul", "D1" ) tips_3 = protocol.load_labware( - "opentrons_flex_96_tiprack_1000ul", "C1", + "opentrons_flex_96_tiprack_1000ul", "C3", adapter="opentrons_flex_96_tiprack_adapter" ) tips_4 = protocol.load_labware( - "opentrons_flex_96_tiprack_1000ul", "C2", + "opentrons_flex_96_tiprack_1000ul", "D3", adapter="opentrons_flex_96_tiprack_adapter" ) @@ -127,6 +127,8 @@ Now, when you configure the nozzle layout, you can use the appropriate list as t Tip Pickup and Conflicts ------------------------ +The horizontally offset position of the 96-channel pipette during partial tip pickup also places restrictions on where you can put other tall labware on the deck. + .. _pipette-volume-modes: Volume Modes From 69f6c90849e1012e103a9b7b576eed48607ec155 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Tue, 19 Dec 2023 17:14:07 -0500 Subject: [PATCH 08/14] draft of all tip tracking sections complete --- api/docs/v2/pipettes/configuring.rst | 65 +++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index 337121aebdd..67714c09a59 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -127,7 +127,70 @@ Now, when you configure the nozzle layout, you can use the appropriate list as t Tip Pickup and Conflicts ------------------------ -The horizontally offset position of the 96-channel pipette during partial tip pickup also places restrictions on where you can put other tall labware on the deck. +The horizontally offset position of the 96-channel pipette during partial tip pickup also places restrictions on where you can put other tall labware on the deck. + +Using Column 12 +^^^^^^^^^^^^^^^ + +All of the examples in this section will use a 96-channel pipette configured to pick up tips with column 12. This is the *only* partial nozzle configuration for which the API will automatically detect labware placed in locations that could cause collisions, and raise errors to prevent them. + +.. code-block:: python + + pipette.configure_nozzle_layout( + style=COLUMN, + start="A12", + ) + +When using column 12, the pipette overhangs space to the left of wherever it is picking up tips or pipetting. For this reason, it's a good idea to organize tip racks front to back on the deck. If you place them side by side, the rack to the right will be inaccessible. For example, let's load three tip racks in the front left corner of the deck:: + + tips_C1 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "C1") + tips_D1 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "D1") + tips_D2 = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "D2") + +Now the pipette will be able to access the racks in column 1 only. ``pick_up_tip(tips_D2["A1"])`` will raise an error due to the tip rack immediately to its left, in slot D1. There a couple of ways to avoid this error: + + - Load the tip rack in a different slot, with no tall labware to its left. + - Use all the tips in slot D1 first, and then use :py:meth:`.move_labware` to make space for the pipette before picking up tips from D2. + +You would get a similar error trying to aspirate from or dispense into a well plate in slot D3, since there is a tip rack to the left. + +.. tip:: + + When using column 12 for partial tip pickup and pipetting, generally organize your deck with the shortest labware on the left side of the deck, and the tallest labware on the right side. + +Using Column 1 +^^^^^^^^^^^^^^ + +If your application can't accommodate a deck layout that works well with column 12, you can configure the 96-channel pipette to pick up tips with column 1:: + + pipette.configure_nozzle_layout( + style=COLUMN, + start="A1", + ) + +This configuration has several drawbacks compared to using column 12. + +First, tip tracking is not available with column 1. You must always specify a ``location`` parameter for :py:meth:`.pick_up_tip`. This *requires careful tip tracking* so you don't place the pipette over more than a single column of unused tips at once. You can write some additional code to manage valid tip pickup locations, like this:: + + tip_rack = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "C1") + pipette.configure_nozzle_layout(style=COLUMN, start="A1") + row_a = tiprack.rows()[0] + pipette.pick_up_tip(row_a.pop()) # pick up A12-H12 + pipette.drop_tip() + pipette.pick_up_tip(row_a.pop()) # pick up A11-H11 + pipette.drop_tip() + +This code first constructs a list of all the wells in row A of the tip rack. Then, when picking up a tip, instead of referencing one of those wells directly, the ``location`` is set to ``row_a.pop()``. This uses the built-in :py:meth:`pop` method to get the last item from the list and remove it from the list. If you keep using this approach to pick up tips, you'll get an error once the tip rack is empty — not from the API, but from Python itself, since you're trying to ``pop`` an item from an empty list. + +While you can easily add tip tracking to a column 1 configuration, you will still be operating without the collision detection the API has for column 12. + +.. warning:: + + The API *will not* raise errors for potential labware crashes when using a column 1 partial configuration. If you must use one: + + - Plan your deck layout carefully. Make a diagram and visualize everywhere the pipette will travel. + - Simulate your protocol and compare the run preview to your expectations of where the pipette will travel. + - Perform a dry run with only tip racks on the deck. Have the Emergency Stop Pendant handy in case you see an impending crash. .. _pipette-volume-modes: From e1383c841d11a10cdb0e3433874f2b51431a8406 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Wed, 20 Dec 2023 10:24:15 -0500 Subject: [PATCH 09/14] code typo --- api/docs/v2/pipettes/configuring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index 67714c09a59..332c2591e28 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -174,7 +174,7 @@ First, tip tracking is not available with column 1. You must always specify a `` tip_rack = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "C1") pipette.configure_nozzle_layout(style=COLUMN, start="A1") - row_a = tiprack.rows()[0] + row_a = tip_rack.rows()[0] pipette.pick_up_tip(row_a.pop()) # pick up A12-H12 pipette.drop_tip() pipette.pick_up_tip(row_a.pop()) # pick up A11-H11 From 8a412fcdd82fe31300e548aab451d61b5928b68d Mon Sep 17 00:00:00 2001 From: Ed Cormany Date: Wed, 20 Dec 2023 10:55:04 -0500 Subject: [PATCH 10/14] review typo fix Co-authored-by: Sanniti Pimpley --- api/docs/v2/pipettes/configuring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index 332c2591e28..20547abe055 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -19,7 +19,7 @@ There are no mode configurations for OT-2 pipettes. Partial Tip Pickup ================== -The 96-channel pipette occupies both pipette mounts on Flex, so it's not possible to attach another pipette at the same time. Partial tip pickup lets you perform some of the same actions that you would be able to perform with a second pipette. As of version 2.16 of the API, you can configure the 96-channel pipette pick up a single column of tips, similar to the behavior of an 8-channel pipette. +The 96-channel pipette occupies both pipette mounts on Flex, so it's not possible to attach another pipette at the same time. Partial tip pickup lets you perform some of the same actions that you would be able to perform with a second pipette. As of version 2.16 of the API, you can configure the 96-channel pipette to pick up a single column of tips, similar to the behavior of an 8-channel pipette. Nozzle Layout ------------- From 87148e7b9d4715ceb0ad1bec193416864acc3d32 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Wed, 20 Dec 2023 14:38:57 -0500 Subject: [PATCH 11/14] edits to loading page --- api/docs/v2/pipettes/characteristics.rst | 2 ++ api/docs/v2/pipettes/loading.rst | 24 +++++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/api/docs/v2/pipettes/characteristics.rst b/api/docs/v2/pipettes/characteristics.rst index 1b91ce3ec76..c8660d7bc65 100644 --- a/api/docs/v2/pipettes/characteristics.rst +++ b/api/docs/v2/pipettes/characteristics.rst @@ -217,6 +217,8 @@ The following table provides data on the default aspirate, dispense, and blowout Additionally, all OT-2 GEN2 pipettes have a default head speed of 400 mm/s and a well bottom clearance of 1 mm for aspirate and dispense actions. +.. _ot2-pipette-generations: + OT-2 Pipette Generations ======================== diff --git a/api/docs/v2/pipettes/loading.rst b/api/docs/v2/pipettes/loading.rst index f873e9bd157..4d2451a2dd8 100644 --- a/api/docs/v2/pipettes/loading.rst +++ b/api/docs/v2/pipettes/loading.rst @@ -50,7 +50,7 @@ The pipette's API load name (``instrument_name``) is the first parameter of the | P1000 Single-Channel GEN2 | 100-1000 | ``p1000_single_gen2`` | +-----------------------------+--------------------+-----------------------+ - See the OT-2 Pipette Generations section below if you're using GEN1 pipettes on an OT-2. The GEN1 family includes the P10, P50, and P300 single- and multi-channel pipettes, along with the P1000 single-chanel model. + See the :ref:`OT-2 Pipette Generations ` section if you're using GEN1 pipettes on an OT-2. The GEN1 family includes the P10, P50, and P300 single- and multi-channel pipettes, along with the P1000 single-channel model. Loading Flex 1- and 8-Channel Pipettes ====================================== @@ -83,15 +83,20 @@ If you're writing a protocol that uses the Flex Gripper, you might think that th Loading a Flex 96-Channel Pipette ================================= -This code sample loads the Flex 96-Channel Pipette. Because of its size, the Flex 96-Channel Pipette requires the left *and* right pipette mounts. You cannot use this pipette with 1- or 8-Channel Pipette in the same protocol or when these instruments are attached to the robot. To load the 96-Channel Pipette, specify its position as ``mount='left'`` as shown here: +This code sample loads the Flex 96-Channel Pipette. Because of its size, the Flex 96-Channel Pipette requires the left *and* right pipette mounts. You cannot use this pipette with 1- or 8-Channel Pipette in the same protocol or when these instruments are attached to the robot. Load the 96-channel pipette as follows: .. code-block:: python def run(protocol: protocol_api.ProtocolContext): - left = protocol.load_instrument( - instrument_name='flex_96channel_1000', mount='left') + pipette = protocol.load_instrument( + instrument_name='flex_96channel_1000' + ) + +In protocols specifying API version 2.15, also include ``mount='left'`` as a parameter of ``load_instrument()``. .. versionadded:: 2.15 +.. versionchanged:: 2.16 + The ``mount`` parameter is optional. Loading OT-2 Pipettes ===================== @@ -126,7 +131,12 @@ This code sample loads a P1000 Single-Channel GEN2 pipette in the left mount and Adding Tip Racks ================ -The ``load_instrument()`` method includes the optional argument ``tip_racks``. This parameter accepts a list of tip rack labware objects, which lets you to specify as many tip racks as you want. The advantage of using ``tip_racks`` is twofold. First, associating tip racks with your pipette allows for automatic tip tracking throughout your protocol. Second, it removes the need to specify tip locations in the :py:meth:`.InstrumentContext.pick_up_tip` method. For example, let's start by loading loading some labware and instruments like this:: +The ``load_instrument()`` method includes the optional argument ``tip_racks``. This parameter accepts a list of tip rack labware objects, which lets you to specify as many tip racks as you want. You can also edit a pipette's tip racks after loading it by setting its :py:obj:`.InstrumentContext.tip_racks` property. + +.. note:: + Some methods, like :py:meth:`.configure_nozzle_layout`, reset a pipette's tip racks. See :ref:`partial-tip-pickup` for more information. + +The advantage of using ``tip_racks`` is twofold. First, associating tip racks with your pipette allows for automatic tip tracking throughout your protocol. Second, it removes the need to specify tip locations in the :py:meth:`.InstrumentContext.pick_up_tip` method. For example, let's start by loading loading some labware and instruments like this:: def run(protocol: protocol_api.ProtocolContext): tiprack_left = protocol.load_labware( @@ -166,6 +176,6 @@ Additional calls to ``pick_up_tip`` will automatically progress through the tips right_pipette.pick_up_tip() # picks up from A3 right_pipette.drop_tip() -See also, :ref:`v2-atomic-commands` and :ref:`v2-complex-commands`. - .. versionadded:: 2.0 + +See also :ref:`v2-atomic-commands` and :ref:`v2-complex-commands`. From c1e2db0d1a1b603830762b8c5b5291bc57ffe052 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Wed, 20 Dec 2023 15:17:41 -0500 Subject: [PATCH 12/14] =?UTF-8?q?new=20characteristics=20page=20intro=20an?= =?UTF-8?q?d=20multi-channel=20=C2=A7=20intro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/docs/v2/pipettes/characteristics.rst | 36 ++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/api/docs/v2/pipettes/characteristics.rst b/api/docs/v2/pipettes/characteristics.rst index c8660d7bc65..3f9c4fb466d 100644 --- a/api/docs/v2/pipettes/characteristics.rst +++ b/api/docs/v2/pipettes/characteristics.rst @@ -4,18 +4,44 @@ Pipette Characteristics *********************** +Each Opentrons pipette has different capabilities, which you'll want to take advantage of in your protocols. This page covers some fundamental pipette characteristics. + +:ref:`new-multichannel-pipettes` gives examples of how multi-channel pipettes move around the deck by using just one of their channels as a reference point. Taking this into account is important for commanding your pipettes to perform actions in the correct locations. + +:ref:`new-plunger-flow-rates` discusses how quickly each type of pipette can handle liquids. The defaults are designed to operate quickly, based on the pipette's hardware and assuming that you're handling aqueous liquids. You can speed up or slow down a pipette's flow rate to suit your protocol's needs. + +Finally, the volume ranges of pipettes affect what you can do with them. The volume ranges for current pipettes are listed on the :ref:`Loading Pipettes ` page. The :ref:`ot2-pipette-generations` section of this page describes how the API behaves when running protocols that specify older OT-2 pipettes. + .. _new-multichannel-pipettes: -Multi-Channel Pipettes +Multi-Channel Movement ====================== -All building block and advanced commands work with single- and multi-channel pipettes. +All :ref:`building block ` and :ref:`complex commands ` work with single- and multi-channel pipettes. -To keep the interface to the Opentrons API consistent between single- and multi-channel pipettes, commands treat the *backmost channel* (furthest from the door) of a multi-channel pipette as the location of the pipette. Location arguments to building block and advanced commands are specified for the backmost channel. +To keep the protocol API consistent when using single- and multi-channel pipettes, commands treat the back left channel of a multi-channel pipette as its *primary channel*. Location arguments of pipetting commands use the primary channel. The :py:meth:`.InstrumentContext.configure_nozzle_layout` method can change the pipette's primary channel, using its ``start`` parameter. See :ref:`partial-tip-pickup` for more information. -Also, this means that offset changes (such as :py:meth:`.Well.top` or :py:meth:`.Well.bottom`) can be applied to the single specified well, and each pipette channel will be at the same position relative to the well that it is over. +With a pipette's default settings, you can generally access the wells indicated in the table below. Moving to any other well may cause the pipette to crash. -Finally, because there is only one motor in a multi-channel pipette, these pipettes always aspirate and dispense on all channels simultaneously. +.. list-table:: + :header-rows: 1 + + * - Channels + - 96-well plate + - 384-well plate + * - 1 + - Any well, A1–H12 + - Any well, A1–P24 + * - 8 + - A1–A12 + - A1–B24 + * - 96 + - A1 only + - A1–B2 + +Also, you should apply any location offset, such as :py:meth:`.Well.top` or :py:meth:`.Well.bottom`, to the well accessed by the primary channel. Since all of the pipette's channels move together, each channel will have the same offset relative to the well that it is over. + +Finally, because each multi-channel pipette has only one motor, they always aspirate and dispense on all channels simultaneously. 8-Channel, 96-Well Plate Example -------------------------------- From f313bc0268f64bfb3689133a146aa8cb8be324d2 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Wed, 20 Dec 2023 16:44:37 -0500 Subject: [PATCH 13/14] feedback and edits on modes page --- api/docs/v2/pipettes/configuring.rst | 49 +++++++++++++++++----------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index 20547abe055..92b6df60e39 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -4,16 +4,13 @@ Configuring Pipette Modes ************************* -The API provides methods to configure certain pipettes to operate in a specific mode. These configuration methods change the default behavior of the pipette on an ongoing basis, until you call them again with different values. +The API provides methods that let you configure a 96-channel pipette to perform partial tip pickup and configure Flex 50 µL pipettes for low-volume liquid handling. Each configuration method places the pipette in a new mode, which changes the default behavior of the pipette on an ongoing basis, until you call it again with different values. -This page covers the currently available modes. +This page covers the following modes, which currently apply only to Flex pipettes. There are no mode configurations for OT-2 pipettes. - :ref:`partial-tip-pickup`: The 96-channel pipette can be configured to use 8 or 96 nozzles for pipetting. - :ref:`pipette-volume-modes`: The Flex 50 µL pipettes can be configured to handle liquid differently for low or high volumes. -There are no mode configurations for OT-2 pipettes. - - .. _partial-tip-pickup: Partial Tip Pickup @@ -24,20 +21,28 @@ The 96-channel pipette occupies both pipette mounts on Flex, so it's not possibl Nozzle Layout ------------- -Use the :py:meth:`.configure_nozzle_layout` method to choose how many tips the 96-channel pipette will pick up. The method's ``style`` parameter accepts special layout constants. When using partial tip pickup, it's generally easiest to import these at the top of your protocol. +Use the :py:meth:`.configure_nozzle_layout` method to choose how many tips the 96-channel pipette will pick up. The method's ``style`` parameter accepts special layout constants. You must import these constants at the top of your protocol, or you won't be able to configure the pipette for partial tip pickup. -.. code-block:: python +At minimum, import the API from the ``opentrons`` package:: from opentrons import protocol_api + +Then when you call ``configure_nozzle_layout`` later in your protocol, you can set ``style=protocol_api.COLUMN``. + +For greater convenience, also import the individual layout constants that you plan to use in your protocol:: + from opentrons.protocol_api import COLUMN, ALL -Then when you call ``configure_nozzle_layout`` later in your protocol, you can set ``style=COLUMN``. If, instead, you use ``from opentrons import protocol_api``, then you can pass ``protocol_api.COLUMN``. If you don't put any ``import`` statements at the top of your protocol, you won't be able to configure the nozzle layout. +Then when you call ``configure_nozzle_layout`` later in your protocol, you can set ``style=COLUMN``. -Assuming the ``import`` statements from above, here is the start of a protocol that loads a 96-channel pipette and sets it to pick up a single column of tips. +Here is the start of a protocol that performs both imports, loads a 96-channel pipette, and sets it to pick up a single column of tips. .. code-block:: python :substitutions: + from opentrons import protocol_api + from opentrons.protocol_api import COLUMN, ALL + requirements = {"robotType": "Flex", "apiLevel": "|apiLevel|"} def run(protocol: protocol_api.ProtocolContext): @@ -58,7 +63,7 @@ Let's unpack some of the details of this code. First, we've given a special name to the tip rack, ``column_rack``. You can name your tip racks whatever you like, but if you're performing full pickup and partial pickup in the same protocol, you'll need to keep them separate. See :ref:`partial-tip-rack-adapters` below. -Next, we load the 96-channel pipette. Note that ``load_instrument()`` only has a single argument. The 96-channel pipette occupies both mounts, so ``mount`` is omissible. The ``tip_racks`` argument is always optional. But it would have no effect to declare it here, because every call to ``configure_nozzle_layout()`` resets the pipette's :py:obj:`.InstrumentContext.tip_racks` property. +Next, we load the 96-channel pipette. Note that :py:meth:`.load_instrument` only has a single argument. The 96-channel pipette occupies both mounts, so ``mount`` is omissible. The ``tip_racks`` argument is always optional. But it would have no effect to declare it here, because every call to ``configure_nozzle_layout()`` resets the pipette's :py:obj:`.InstrumentContext.tip_racks` property. Finally, we configure the nozzle layout, with three arguments. @@ -82,11 +87,13 @@ In this configuration, pipetting actions will use a single column:: Tip Rack Adapters ----------------- -Partial tip pickup requires a tip rack that is placed directly in a deck slot. When picking up fewer than 96 tips, the 96-channel pipette lowers onto the tip rack in a horizontally offset position. If the tip rack were in the tip rack adapter, the pipette would collide with the adapter's posts, which protrude above the top of the tip rack. If you configure a partial nozzle layout and then call ``pick_up_tip()`` on a tip rack that's loaded onto an adapter, the API will raise an error. +You can use both partial and full tip pickup in the same protocol. This requires having some tip racks directly on the deck, and some tip racks in the tip rack adapter. + +Do not use a tip rack adapter when performing partial tip pickup. Instead, place the tip rack on the deck. During partial tip pickup, the 96-channel pipette lowers onto the tip rack in a horizontally offset position. If the tip rack were in its adapter, the pipette would collide with the adapter's posts, which protrude above the top of the tip rack. If you configure the pipette for partial pickup and then call ``pick_up_tip()`` on a tip rack that's loaded onto an adapter, the API will raise an error. -On the other hand, full tip pickup requires the tip rack adapter. If the 96-channel pipette is in a full layout, either by default or by configuring ``style=ALL``, and you then call ``pick_up_tip()`` on a tip rack that's not in an adapter, the API will raise an error. +On the other hand, you must use the tip rack adapter for full tip pickup. If the 96-channel pipette is in a full layout, either by default or by configuring ``style=ALL``, and you then call ``pick_up_tip()`` on a tip rack that's not in an adapter, the API will raise an error. -If your protocol switches between full and partial pickup, you may want to organize your tip racks into lists, depending on whether they're loaded on adapters or not. +When switching between full and partial pickup, you may want to organize your tip racks into lists, depending on whether they're loaded on adapters or not. .. code-block:: python @@ -108,7 +115,7 @@ If your protocol switches between full and partial pickup, you may want to organ partial_tip_racks = [tips_1, tips_2] full_tip_racks = [tips_3, tips_4] -Now, when you configure the nozzle layout, you can use the appropriate list as the value of ``tip_racks``:: +Now, when you configure the nozzle layout, you can reference the appropriate list as the value of ``tip_racks``:: pipette.configure_nozzle_layout( style=COLUMN, @@ -122,19 +129,19 @@ Now, when you configure the nozzle layout, you can use the appropriate list as t tip_racks=full_tip_racks ) pipette.pick_up_tip() # picks up full rack in C1 + +This keeps tip tracking consistent across each type of pickup. And it reduces the risk of errors due to the incorrect presence or absence of a tip rack adapter. Tip Pickup and Conflicts ------------------------ -The horizontally offset position of the 96-channel pipette during partial tip pickup also places restrictions on where you can put other tall labware on the deck. +The horizontally offset position of the 96-channel pipette during partial tip pickup places restrictions on where you can put other tall labware on the deck. The restrictions vary depending on the layout. For column layouts, Opentrons recommends using column 12. Currently, this is the *only* partial nozzle configuration for which the API will automatically detect labware placed in locations that could cause collisions, and raise errors to prevent them. Using Column 12 ^^^^^^^^^^^^^^^ -All of the examples in this section will use a 96-channel pipette configured to pick up tips with column 12. This is the *only* partial nozzle configuration for which the API will automatically detect labware placed in locations that could cause collisions, and raise errors to prevent them. - -.. code-block:: python +All of the examples in this section will use a 96-channel pipette configured to pick up tips with column 12:: pipette.configure_nozzle_layout( style=COLUMN, @@ -157,6 +164,8 @@ You would get a similar error trying to aspirate from or dispense into a well pl .. tip:: When using column 12 for partial tip pickup and pipetting, generally organize your deck with the shortest labware on the left side of the deck, and the tallest labware on the right side. + +One limitation of the column 12 nozzle layout is that it can't access column 1 wells of labware loaded onto the Thermocycler Module. If you need to use all 96 wells on the Thermocycler, you can temporarily switch to the column 1 nozzle layout. Using Column 1 ^^^^^^^^^^^^^^ @@ -182,7 +191,7 @@ First, tip tracking is not available with column 1. You must always specify a `` This code first constructs a list of all the wells in row A of the tip rack. Then, when picking up a tip, instead of referencing one of those wells directly, the ``location`` is set to ``row_a.pop()``. This uses the built-in :py:meth:`pop` method to get the last item from the list and remove it from the list. If you keep using this approach to pick up tips, you'll get an error once the tip rack is empty — not from the API, but from Python itself, since you're trying to ``pop`` an item from an empty list. -While you can easily add tip tracking to a column 1 configuration, you will still be operating without the collision detection the API has for column 12. +Second, the API does not provide the same collision detection for the column 1 layout that it does for column 12. .. warning:: @@ -191,6 +200,8 @@ While you can easily add tip tracking to a column 1 configuration, you will stil - Plan your deck layout carefully. Make a diagram and visualize everywhere the pipette will travel. - Simulate your protocol and compare the run preview to your expectations of where the pipette will travel. - Perform a dry run with only tip racks on the deck. Have the Emergency Stop Pendant handy in case you see an impending crash. + +Finally, you can't access the rightmost columns in labware in column 3, since they are beyond the movement limit of the pipette. The exact number of inaccessible columns varies by labware type. Any well that is within 28 mm of the right edge of the slot is inaccessible in a column 12 configuration. Call ``confiure_nozzle_layout()`` again to switch to a column 1 layout if you need to pipette in that area. .. _pipette-volume-modes: From aa8ed3427a925c4832553d2e3640bd83ad025a83 Mon Sep 17 00:00:00 2001 From: Edward Cormany Date: Wed, 20 Dec 2023 16:58:06 -0500 Subject: [PATCH 14/14] split volume modes into separate page --- api/docs/v2/new_pipette.rst | 6 ++- api/docs/v2/pipettes/configuring.rst | 77 +++------------------------ api/docs/v2/pipettes/volume_modes.rst | 49 +++++++++++++++++ 3 files changed, 61 insertions(+), 71 deletions(-) create mode 100644 api/docs/v2/pipettes/volume_modes.rst diff --git a/api/docs/v2/new_pipette.rst b/api/docs/v2/new_pipette.rst index 6798f9cf7fb..102759f7ef7 100644 --- a/api/docs/v2/new_pipette.rst +++ b/api/docs/v2/new_pipette.rst @@ -10,14 +10,16 @@ Pipettes pipettes/loading pipettes/characteristics pipettes/configuring + pipettes/volume_modes Opentrons pipettes are configurable devices used to move liquids throughout the working area during the execution of protocols. Flex and OT-2 each have their own pipettes, which are available for use in the Python API. Pages in this section of the documentation cover: - :ref:`Loading pipettes ` into your protocol. - - :ref:`Characteristics of pipettes `, such as how fast they can move liquid and how they move around the deck. - - :ref:`Configuring Flex pipettes ` in different modes, such as for low-volume transfers or only using some of their nozzles. + - :ref:`Pipette characteristics `, such as how fast they can move liquid and how they move around the deck. + - The :ref:`partial tip pickup ` configuration for the Flex 96-Channel Pipette, which uses only 8 channels for pipetting. Full and partial tip pickup can be combined in a single protocol. + - The :ref:`volume modes ` of Flex 50 µL pipettes, which must operate in low-volume mode to accurately dispense very small volumes of liquid. For information about liquid handling, see :ref:`v2-atomic-commands` and :ref:`v2-complex-commands`. diff --git a/api/docs/v2/pipettes/configuring.rst b/api/docs/v2/pipettes/configuring.rst index 92b6df60e39..e667ac1a41c 100644 --- a/api/docs/v2/pipettes/configuring.rst +++ b/api/docs/v2/pipettes/configuring.rst @@ -1,25 +1,13 @@ -.. _configuring-pipette-modes: - -************************* -Configuring Pipette Modes -************************* - -The API provides methods that let you configure a 96-channel pipette to perform partial tip pickup and configure Flex 50 µL pipettes for low-volume liquid handling. Each configuration method places the pipette in a new mode, which changes the default behavior of the pipette on an ongoing basis, until you call it again with different values. - -This page covers the following modes, which currently apply only to Flex pipettes. There are no mode configurations for OT-2 pipettes. - -- :ref:`partial-tip-pickup`: The 96-channel pipette can be configured to use 8 or 96 nozzles for pipetting. -- :ref:`pipette-volume-modes`: The Flex 50 µL pipettes can be configured to handle liquid differently for low or high volumes. - .. _partial-tip-pickup: +****************** Partial Tip Pickup -================== +****************** The 96-channel pipette occupies both pipette mounts on Flex, so it's not possible to attach another pipette at the same time. Partial tip pickup lets you perform some of the same actions that you would be able to perform with a second pipette. As of version 2.16 of the API, you can configure the 96-channel pipette to pick up a single column of tips, similar to the behavior of an 8-channel pipette. Nozzle Layout -------------- +============= Use the :py:meth:`.configure_nozzle_layout` method to choose how many tips the 96-channel pipette will pick up. The method's ``style`` parameter accepts special layout constants. You must import these constants at the top of your protocol, or you won't be able to configure the pipette for partial tip pickup. @@ -85,7 +73,7 @@ In this configuration, pipetting actions will use a single column:: .. _partial-tip-rack-adapters: Tip Rack Adapters ------------------ +================= You can use both partial and full tip pickup in the same protocol. This requires having some tip racks directly on the deck, and some tip racks in the tip rack adapter. @@ -134,12 +122,12 @@ This keeps tip tracking consistent across each type of pickup. And it reduces th Tip Pickup and Conflicts ------------------------- +======================== The horizontally offset position of the 96-channel pipette during partial tip pickup places restrictions on where you can put other tall labware on the deck. The restrictions vary depending on the layout. For column layouts, Opentrons recommends using column 12. Currently, this is the *only* partial nozzle configuration for which the API will automatically detect labware placed in locations that could cause collisions, and raise errors to prevent them. Using Column 12 -^^^^^^^^^^^^^^^ +--------------- All of the examples in this section will use a 96-channel pipette configured to pick up tips with column 12:: @@ -168,7 +156,7 @@ You would get a similar error trying to aspirate from or dispense into a well pl One limitation of the column 12 nozzle layout is that it can't access column 1 wells of labware loaded onto the Thermocycler Module. If you need to use all 96 wells on the Thermocycler, you can temporarily switch to the column 1 nozzle layout. Using Column 1 -^^^^^^^^^^^^^^ +-------------- If your application can't accommodate a deck layout that works well with column 12, you can configure the 96-channel pipette to pick up tips with column 1:: @@ -201,54 +189,5 @@ Second, the API does not provide the same collision detection for the column 1 l - Simulate your protocol and compare the run preview to your expectations of where the pipette will travel. - Perform a dry run with only tip racks on the deck. Have the Emergency Stop Pendant handy in case you see an impending crash. -Finally, you can't access the rightmost columns in labware in column 3, since they are beyond the movement limit of the pipette. The exact number of inaccessible columns varies by labware type. Any well that is within 28 mm of the right edge of the slot is inaccessible in a column 12 configuration. Call ``confiure_nozzle_layout()`` again to switch to a column 1 layout if you need to pipette in that area. +Finally, you can't access the rightmost columns in labware in column 3, since they are beyond the movement limit of the pipette. The exact number of inaccessible columns varies by labware type. Any well that is within 28 mm of the right edge of the slot is inaccessible in a column 12 configuration. Call ``configure_nozzle_layout()`` again to switch to a column 1 layout if you need to pipette in that area. -.. _pipette-volume-modes: - -Volume Modes -============ - -The Flex 1-Channel 50 µL and Flex 8-Channel 50 µL pipettes must operate in a low-volume mode to accurately dispense very small volumes of liquid. Set the volume mode by calling :py:meth:`.InstrumentContext.configure_for_volume` with the amount of liquid you plan to aspirate, in µL:: - - pipette50.configure_for_volume(1) - pipette50.pick_up_tip() - pipette50.aspirate(1, plate["A1"]) - -.. versionadded:: 2.15 - -Passing different values to ``configure_for_volume()`` changes the minimum and maximum volume of Flex 50 µL pipettes as follows: - -.. list-table:: - :header-rows: 1 - :widths: 2 3 3 - - * - Value - - Minimum Volume (µL) - - Maximum Volume (µL) - * - 1–4.9 - - 1 - - 30 - * - 5–50 - - 5 - - 50 - -.. note:: - The pipette must not contain liquid when you call ``configure_for_volume()``, or the API will raise an error. - - Also, if the pipette is in a well location that may contain liquid, it will move upward to ensure it is not immersed in liquid before changing its mode. Calling ``configure_for_volume()`` *before* ``pick_up_tip()`` helps to avoid this situation. - -In a protocol that handles many different volumes, it's a good practice to call ``configure_for_volume()`` once for each :py:meth:`.transfer` or :py:meth:`.aspirate`, specifying the volume that you are about to handle. When operating with a list of volumes, nest ``configure_for_volume()`` inside a ``for`` loop to ensure that the pipette is properly configured for each volume: - -.. code-block:: python - - volumes = [1, 2, 3, 4, 1, 5, 2, 8] - sources = plate.columns()[0] - destinations = plate.columns()[1] - for i in range(8): - pipette50.configure_for_volume(volumes[i]) - pipette50.pick_up_tip() - pipette50.aspirate(volume=volumes[i], location=sources[i]) - pipette50.dispense(location=destinations[i]) - pipette50.drop_tip() - -If you know that all your liquid handling will take place in a specific mode, then you can call ``configure_for_volume()`` just once with a representative volume. Or if all the volumes correspond to the pipette's default mode, you don't have to call ``configure_for_volume()`` at all. diff --git a/api/docs/v2/pipettes/volume_modes.rst b/api/docs/v2/pipettes/volume_modes.rst new file mode 100644 index 00000000000..bb8533650d1 --- /dev/null +++ b/api/docs/v2/pipettes/volume_modes.rst @@ -0,0 +1,49 @@ +.. _pipette-volume-modes: + +Volume Modes +============ + +The Flex 1-Channel 50 µL and Flex 8-Channel 50 µL pipettes must operate in a low-volume mode to accurately dispense very small volumes of liquid. Set the volume mode by calling :py:meth:`.InstrumentContext.configure_for_volume` with the amount of liquid you plan to aspirate, in µL:: + + pipette50.configure_for_volume(1) + pipette50.pick_up_tip() + pipette50.aspirate(1, plate["A1"]) + +.. versionadded:: 2.15 + +Passing different values to ``configure_for_volume()`` changes the minimum and maximum volume of Flex 50 µL pipettes as follows: + +.. list-table:: + :header-rows: 1 + :widths: 2 3 3 + + * - Value + - Minimum Volume (µL) + - Maximum Volume (µL) + * - 1–4.9 + - 1 + - 30 + * - 5–50 + - 5 + - 50 + +.. note:: + The pipette must not contain liquid when you call ``configure_for_volume()``, or the API will raise an error. + + Also, if the pipette is in a well location that may contain liquid, it will move upward to ensure it is not immersed in liquid before changing its mode. Calling ``configure_for_volume()`` *before* ``pick_up_tip()`` helps to avoid this situation. + +In a protocol that handles many different volumes, it's a good practice to call ``configure_for_volume()`` once for each :py:meth:`.transfer` or :py:meth:`.aspirate`, specifying the volume that you are about to handle. When operating with a list of volumes, nest ``configure_for_volume()`` inside a ``for`` loop to ensure that the pipette is properly configured for each volume: + +.. code-block:: python + + volumes = [1, 2, 3, 4, 1, 5, 2, 8] + sources = plate.columns()[0] + destinations = plate.columns()[1] + for i in range(8): + pipette50.configure_for_volume(volumes[i]) + pipette50.pick_up_tip() + pipette50.aspirate(volume=volumes[i], location=sources[i]) + pipette50.dispense(location=destinations[i]) + pipette50.drop_tip() + +If you know that all your liquid handling will take place in a specific mode, then you can call ``configure_for_volume()`` just once with a representative volume. Or if all the volumes correspond to the pipette's default mode, you don't have to call ``configure_for_volume()`` at all.