diff --git a/api/docs/v2/complex_commands/order_operations.rst b/api/docs/v2/complex_commands/order_operations.rst index a55143e33e3..32c8b3ccafe 100644 --- a/api/docs/v2/complex_commands/order_operations.rst +++ b/api/docs/v2/complex_commands/order_operations.rst @@ -13,7 +13,12 @@ This page describes what steps you should expect the robot to perform when using Step Sequence ============= -The order of steps is fixed within complex commands. Aspiration and dispensing are the only required actions. You can enable or disable all of the other actions with :ref:`complex liquid handling parameters <complex_params>`. A complex command designed to perform every possible action will proceed in this order: +The order of steps is fixed within complex commands, but basic and liquid class complex commands handle transfer steps and changes to actions differently. + +Basic Step Sequence +-------------------- + +In a basic ``transfer()``, aspiration and dispensing are the only required actions. You can enable or disable all of the other actions with :ref:`complex liquid handling parameters <complex_params>`. A basic ``transfer()`` command designed to perform every possible action will proceed in this order: 1. Pick up tip 2. Mix at source @@ -25,13 +30,45 @@ The order of steps is fixed within complex commands. Aspiration and dispensing a 8. Touch tip at destination 9. Blow out 10. Drop tip - -The command may repeat some or all of these steps in order to move liquid as requested. :py:meth:`.transfer` repeats as many times as there are wells in the longer of its ``source`` or ``dest`` argument. :py:meth:`.distribute` and :py:meth:`.consolidate` try to repeat as few times as possible. See :ref:`complex-tip-refilling` below for how they behave when they do need to repeat. + + +Liquid Class Step Sequence +--------------------------- + +In a ``transfer_with_liquid_class()``, the liquid class definition specifies nearly all transfer behavior your Flex pipette will perform. A liquid class definition with every action enabled would proceed in this order: + + 1. Pick up tip + 2. Submerge into the source to the aspirate position + 3. Delay for an amount of time + 4. Mix at the aspirate position + 5. Pre-wet the attached tip at the aspirate position + 6. Aspirate from source + 7. Delay for an amount of time + 8. Retract from the source to the specified position + 9. Touch tip at source + 10. Add an air gap + 11. Move to and submerge into the destination to the dispense position + 12. Delay for an amount of time + 13. Dispense into destination + 14. Push out into destination + 15. Delay for an amount of time + 16. Mix at the dispense position + 17. Retract from the dispense to the specified position + 18. Delay for an amount of time + 19. Blow out at the specified location + 20. Touch tip at the blow out location + 21. Drop tip + +## TODO: shorten this long list. create a table with summaries of some steps (group together aspirate, etc.) or include icons to provide some information visually. + +The ``transfer_with_liquid_class()`` method includes more steps, like delays or air gaps. Your chosen liquid class definition adds some or all of this transfer behavior, including position information, to optimize liquid transfers. For more information, see :ref:`liquid-class-definitions`. + +Each command may repeat some or all of these steps in order to move liquid as requested. :py:meth:`.transfer` repeats as many times as there are wells in the longer of its ``source`` or ``dest`` argument. Both basic and liquid class distribute and and consolidate methods try to repeat as few times as possible. See :ref:`complex-tip-refilling` below for how they behave when they do need to repeat. Example Orders ============== -The smallest possible number of steps in a complex command is just two: aspirating and dispensing. This is possible by omitting the tip pickup and drop steps:: +The smallest possible number of steps in a complex command like ``transfer()`` is just two: aspirating and dispensing. This is possible by omitting the tip pickup and drop steps:: pipette.transfer( volume=100, @@ -40,6 +77,8 @@ The smallest possible number of steps in a complex command is just two: aspirati new_tip="never", ) +You can also use ``new_tip="never"`` to reuse pipette tips and decrease the total number of steps in any liquid class complex command. + Here's another example, a distribute command that adds touch tip steps (and does not turn off tip handling). The code for this command is:: pipette.distribute( @@ -75,6 +114,8 @@ Let's unpack this. Picking up and dropping tips is default behavior for ``distri Since dispensing and touching the tip are both associated with the destination wells, those steps are performed at each of the two destination wells. +If you use ``distribute_with_liquid_class()`` to perform the same transfer, the liquid class definition automatically determines transfer behaviors like touch tip and blowout. For more information on automatic changes to transfer steps, see the :ref:`Opentrons-verified liquid class definitions <liquid-class-definitions>`. + .. _complex-tip-refilling: Tip Refilling @@ -82,7 +123,7 @@ Tip Refilling One factor that affects the exact order of steps for a complex command is whether the amount of liquid being moved can fit in the tip at once. If it won't fit, you don't have to adjust your command. The API will handle it for you by including additional steps to refill the tip when needed. -For example, say you need to move 100 µL of liquid from one well to another, but you only have a 50 µL pipette attached to your robot. To accomplish this with building block commands, you'd need multiple aspirates and dispenses. ``aspirate(volume=100)`` would raise an error, since it exceeds the tip's volume. But you can accomplish this with a single transfer command:: +For example, say you need to move 100 µL of liquid from one well to another, but you only have a 50 µL pipette attached to your robot. To accomplish this with building block commands, you'd need multiple aspirates and dispenses. ``aspirate(volume=100)`` would raise an error, since it exceeds the tip's volume. But you can accomplish this with a single basic or liquid class transfer command:: pipette50.transfer( volume=100, @@ -103,7 +144,7 @@ To effect the transfer, the API will aspirate and dispense the maximum volume of You can change ``volume`` to any value (above the minimum volume of the pipette) and the API will automatically calculate how many times the pipette needs to aspirate and dispense. ``volume=50`` would require just one repetition. ``volume=75`` would require two, split into 50 µL and 25 µL. ``volume=1000`` would repeat 20 times — not very efficient, but perhaps more useful than having to swap to a different pipette! -Remember that ``distribute()`` includes a disposal volume by default, and this can affect the number of times the pipette refills its tip. Say you want to distribute 80 µL to each of the 12 wells in row A of a plate. That's 960 µL total — less than the capacity of the pipette — but the 100 µL disposal volume will cause the pipette to refill. +Remember that ``distribute()`` and ``distribute_with_liquid_class()`` include a disposal volume by default, and this can affect the number of times the pipette refills its tip. Say you want to ``distribute()`` 80 µL to each of the 12 wells in row A of a plate. That's 960 µL total — less than the capacity of the pipette — but the 100 µL disposal volume will cause the pipette to refill. .. code-block:: text @@ -127,7 +168,7 @@ This command will blow out 200 total µL of liquid in the trash. If you need to List of Volumes =============== -Complex commands can aspirate or dispense different amounts for different wells, rather than the same amount across all wells. To do this, set the ``volume`` parameter to a list of volumes instead of a single number. The list must be the same length as the longer of ``source`` or ``dest``, or the API will raise an error. For example, this command transfers a different amount of liquid into each of wells B1, B2, and B3:: +Complex commands can aspirate or dispense different amounts for different wells, rather than the same amount across all wells. To do this, set the ``volume`` parameter to a list of volumes instead of a single number. The list must be the same length as the number of ``source`` or ``dest`` (or the longer of the two for a basic ``transfer()``), or the API will raise an error. For example, this command transfers a different amount of liquid into each of wells B1, B2, and B3:: pipette.transfer( volume=[20, 40, 60], diff --git a/api/docs/v2/complex_commands/parameters.rst b/api/docs/v2/complex_commands/parameters.rst index 2c044a73e6e..37673fe24db 100644 --- a/api/docs/v2/complex_commands/parameters.rst +++ b/api/docs/v2/complex_commands/parameters.rst @@ -8,9 +8,9 @@ Complex Liquid Handling Parameters Complex commands accept a number of optional parameters that give you greater control over the exact steps they perform. -This page describes the accepted values and behavior of each parameter. The parameters are organized in the order that they first add a step. Some parameters, such as ``touch_tip``, add multiple steps. See :ref:`complex-command-order` for more details on the sequence of steps performed by complex commands. +This page describes the accepted values and behavior of each parameter for different complex commands. The parameters are organized in the order that they first add a step. Some parameters, such as ``touch_tip``, add multiple steps. See :ref:`complex-command-order` for more details on the sequence of steps performed by complex commands. -The API reference entry for :py:meth:`.InstrumentContext.transfer` also lists the parameters and has more information on their implementation as keyword arguments. +The API reference entries for :py:meth:`.InstrumentContext.transfer` and :py:meth:`.InstrumentContext.transfer_with_liquid_class` also list the available parameters and have more information on their implementation as keyword arguments. .. _param-tip-handling: @@ -60,9 +60,9 @@ Avoiding Cross-Contamination One reason to set ``new_tip="always"`` is to avoid cross-contamination between wells. However, you should always do a dry run of your protocol to test that the pipette is picking up and dropping tips in the way that your application requires. -:py:meth:`~.InstrumentContext.transfer` will pick up a new tip before *every* aspirate when ``new_tip="always"``. This includes when :ref:`tip refilling <complex-tip-refilling>` requires multiple aspirations from a single source well. +:py:meth:`~.InstrumentContext.transfer` and :py:meth:`~.InstrumentContext.transfer_with_liquid_class` will pick up a new tip before *every* aspirate when ``new_tip="always"``. This includes when :ref:`tip refilling <complex-tip-refilling>` requires multiple aspirations from a single source well. -:py:meth:`~.InstrumentContext.distribute` and :py:meth:`~.InstrumentContext.consolidate` only pick up one tip, even when ``new_tip="always"``. For example, this distribute command returns to the source well a second time, because the amount to be distributed (400 µL total plus disposal volume) exceeds the pipette capacity (300 µL):: +Both basic and liquid class consolidate and distribute methods only pick up one tip, even when ``new_tip="always"``. For example, this ``distribute()`` command returns to the source well a second time, because the amount to be distributed (400 µL total plus disposal volume) exceeds the pipette capacity (300 µL):: pipette.distribute( volume=200, @@ -86,7 +86,7 @@ But it *does not* pick up a new tip after dispensing into B1: If this poses a contamination risk, you can work around it in a few ways: - * Use ``transfer()`` with ``new_tip="always"`` instead. + * Use ``transfer()`` or ``transfer_with_liquid_class()`` with ``new_tip="always"`` instead. * Set :py:obj:`.well_bottom_clearance` high enough that the tip doesn't contact liquid in the destination well. * Use :ref:`building block commands <v2-atomic-commands>` instead of complex commands. @@ -98,7 +98,7 @@ Mix Before The ``mix_before`` parameter controls mixing in source wells before each aspiration. Its value must be a :py:class:`tuple` with two numeric values. The first value is the number of repetitions, and the second value is the amount of liquid to mix in µL. -For example, this transfer command will mix 50 µL of liquid 3 times before each of its aspirations:: +For example, this basic transfer command will mix 50 µL of liquid 3 times before each of its aspirations:: pipette.transfer( volume=100, @@ -111,6 +111,8 @@ For example, this transfer command will mix 50 µL of liquid 3 times before each Mixing occurs before every aspiration, including when :ref:`tip refilling <complex-tip-refilling>` is required. +Liquid class definitions determine mix behavior for liquid class complex commands like ``transfer_with_liquid_class()``. For more information, see the :ref:`Opentrons-verified liquid class definitions <liquid-class-definitions>`. + .. note:: :py:meth:`~.InstrumentContext.consolidate` ignores any value of ``mix_before``. Mixing on the second and subsequent aspirations of a consolidate command would defeat its purpose: to aspirate multiple times in a row, from different wells, *before* dispensing. @@ -143,6 +145,8 @@ If the amount to aspirate plus the disposal volume exceeds the tip's capacity, ` The amount to dispense in the destination is 960 µL (120 µL for each of 8 wells in the column). Adding the 50 µL disposal volume exceeds the 1000 µL capacity of the tip. The command will be split across two aspirations, each with the full disposal volume of 50 µL. The pipette will dispose *a total of 100 µL* during the command. +Liquid class definitions automatically include a disposal volume for liquid class complex commands like ``distribute_with_liquid_class()``. + .. note:: :py:meth:`~.InstrumentContext.transfer` will not aspirate additional liquid if you set ``disposal_volume``. However, it will perform a very small blow out after each dispense. @@ -173,6 +177,8 @@ This parameter always uses default motion behavior for touch tip. Use the :ref:` * Only touch the tip after aspirating or dispensing, but not both. * Control the speed, radius, or height of the touch tip motion. +Liquid class definitions determine touch tip behavior for liquid class complex commands like ``transfer_with_liquid_class()``. For more information, see the :ref:`Opentrons-verified liquid class definitions <liquid-class-definitions>`. + .. _param-air-gap: Air Gap @@ -200,7 +206,9 @@ Air-gapping behavior is different for each complex command. The different behavi - Air gap after each aspiration. This may create multiple air gaps within the tip. - Pipette is empty after dispensing. -For example, this transfer command will create a 20 µL air gap after each of its aspirations. When dispensing, it will clear the air gap and dispense the full 100 µL of liquid:: +The liquid class definition determines whether air gaps are added after aspirating or dispensing in liquid class complex commands. For more information, see the :ref:`Opentrons-verified liquid class definitions <liquid-class-definitions>`. + +In this basic ``transfer()`` command will create a 20 µL air gap after each of its aspirations. When dispensing, it will clear the air gap and dispense the full 100 µL of liquid:: pipette.transfer( volume=100, @@ -211,7 +219,7 @@ For example, this transfer command will create a 20 µL air gap after each of it .. versionadded:: 2.0 -When consolidating, air gaps still occur after every aspiration. In this example, the tip will use 210 µL of its capacity (50 µL of liquid followed by 20 µL of air, repeated three times):: +During a basic ``consolidate()``, air gaps still occur after every aspiration. In this example, the tip will use 210 µL of its capacity (50 µL of liquid followed by 20 µL of air, repeated three times):: pipette.consolidate( volume=50, @@ -235,7 +243,7 @@ When consolidating, air gaps still occur after every aspiration. In this example Dispensing 210.0 uL into B1 of well plate on 2 at 92.86 uL/sec Dropping tip into A1 of Opentrons Fixed Trash on 12 -If adding an air gap would exceed the pipette's maximum volume, the complex command will use a :ref:`tip refilling strategy <complex-tip-refilling>`. For example, this command uses a 300 µL pipette to transfer 300 µL of liquid plus an air gap:: +If adding an air gap would exceed the pipette's maximum volume, a basic complex command will use a :ref:`tip refilling strategy <complex-tip-refilling>`. For example, this command uses a 300 µL pipette to transfer 300 µL of liquid plus an air gap:: pipette.transfer( volume=300, @@ -244,20 +252,20 @@ If adding an air gap would exceed the pipette's maximum volume, the complex comm air_gap=20, ) -As a result, the transfer is split into two aspirates of 150 µL, each with their own 20 µL air gap: +As a result, the ``transfer()`` is split into two aspirates of 150 µL, each with their own 20 µL air gap: .. code-block:: text - Picking up tip from A1 of tip rack on 3 - Aspirating 150.0 uL from A1 of well plate on 2 at 92.86 uL/sec - Air gap - Aspirating 20.0 uL from A1 of well plate on 2 at 92.86 uL/sec - Dispensing 170.0 uL into B1 of well plate on 2 at 92.86 uL/sec - Aspirating 150.0 uL from A1 of well plate on 2 at 92.86 uL/sec - Air gap - Aspirating 20.0 uL from A1 of well plate on 2 at 92.86 uL/sec - Dispensing 170.0 uL into B1 of well plate on 2 at 92.86 uL/sec - Dropping tip into A1 of Opentrons Fixed Trash on 12 + Picking up tip from A1 of tip rack on 3 + Aspirating 150.0 uL from A1 of well plate on 2 at 92.86 uL/sec + Air gap + Aspirating 20.0 uL from A1 of well plate on 2 at 92.86 uL/sec + Dispensing 170.0 uL into B1 of well plate on 2 at 92.86 uL/sec + Aspirating 150.0 uL from A1 of well plate on 2 at 92.86 uL/sec + Air gap + Aspirating 20.0 uL from A1 of well plate on 2 at 92.86 uL/sec + Dispensing 170.0 uL into B1 of well plate on 2 at 92.86 uL/sec + Dropping tip into A1 of Opentrons Fixed Trash on 12 .. _param-mix-after: @@ -266,7 +274,7 @@ Mix After The ``mix_after`` parameter controls mixing in source wells after each dispense. Its value must be a :py:class:`tuple` with two numeric values. The first value is the number of repetitions, and the second value is the amount of liquid to mix in µL. -For example, this transfer command will mix 50 µL of liquid 3 times after each of its dispenses:: +For example, this ``transfer()`` command will mix 50 µL of liquid 3 times after each of its dispenses:: pipette.transfer( volume=100, @@ -274,7 +282,9 @@ For example, this transfer command will mix 50 µL of liquid 3 times after each dest=[plate["B1"], plate["B2"]], mix_after=(3, 50), ) - + +Liquid class definitions determine mix behavior for liquid class complex commands like ``transfer_with_liquid_class()``. For more information, see the :ref:`Opentrons-verified liquid class definitions <liquid-class-definitions>`. + .. versionadded:: 2.0 .. note:: @@ -285,7 +295,9 @@ For example, this transfer command will mix 50 µL of liquid 3 times after each Blow Out ======== -There are two parameters that control whether and where the pipette blows out liquid. The ``blow_out`` parameter accepts a Boolean value. When ``True``, the pipette blows out remaining liquid when the tip is empty or only contains the disposal volume. The ``blowout_location`` parameter controls in which of three locations these blowout actions occur. The default blowout location is the trash. Blowout behavior is different for each complex command. +There are two parameters that control whether and where the pipette blows out liquid. The ``blow_out`` parameter accepts a Boolean value. When ``True``, the pipette blows out remaining liquid when the tip is empty or only contains the disposal volume. The ``blowout_location`` parameter controls in which of three locations these blowout actions occur. A liquid class definition defines both parameters and blowout behavior for any liquid class complex command. For more information, see the :ref:`Opentrons-verified liquid class definitions <liquid-class-definitions>`. + +In a basic complex command, the default blowout location is the trash. Blowout behavior is different for each command: .. list-table:: :header-rows: 1 @@ -305,7 +317,7 @@ There are two parameters that control whether and where the pipette blows out li - Blow out after the only dispense. - Valid locations: ``"trash"``, ``"destination well"`` -For example, this transfer command will blow out liquid in the trash twice, once after each dispense into a destination well:: +For example, this ``transfer()`` command will blow out liquid in the trash twice, once after each dispense into a destination well:: pipette.transfer( volume=100, @@ -369,7 +381,11 @@ With ``distribute()``, the pipette will still blow out if you only set ``blowout Trash Tips ========== -The ``trash`` parameter controls what the pipette does with tips at the end of complex commands. When ``True``, the pipette drops tips into the trash. When ``False``, the pipette returns tips to their original locations in their tip rack. +The ``trash`` parameter controls what the pipette does with tips at the end of complex commands. + +In a basic complex command, set the ``trash`` parameter to ``True`` or ``False``: + - ``True``: the pipette drops tips into the trash. + - ``False``: the pipette returns tips to their original locations in their tip rack. The default is ``True``, so you only have to set ``trash`` when you want the tip-returning behavior:: @@ -380,4 +396,19 @@ The default is ``True``, so you only have to set ``trash`` when you want the tip trash=False, ) -.. versionadded:: 2.0 \ No newline at end of file +.. versionadded:: 2.0 + +In a liquid class complex command, use the ``trash_location`` to drop tips in a trash container or well:: + + ## define liquid and trash + liquid_1 = protocol_context.define_liquid_class("ethanol_80") + trash = protocol_context.load_trash_bin('A3') + pipette.transfer_with_liquid_class( + liquid_class=liquid_1 + volume=100, + source=plate["A1"], + dest=plate["B1"], + trash_location=trash, + ) + +.. versionadded:: 2.23 \ No newline at end of file diff --git a/api/docs/v2/complex_commands/sources_destinations.rst b/api/docs/v2/complex_commands/sources_destinations.rst index 3c8e725a9aa..17ba9de3348 100644 --- a/api/docs/v2/complex_commands/sources_destinations.rst +++ b/api/docs/v2/complex_commands/sources_destinations.rst @@ -6,9 +6,9 @@ Sources and Destinations ************************ -The :py:meth:`.InstrumentContext.transfer`, :py:meth:`.InstrumentContext.distribute`, and :py:meth:`.InstrumentContext.consolidate` methods form the family of complex liquid handling commands. These methods require ``source`` and ``dest`` (destination) arguments to move liquid from one well, or group of wells, to another. In contrast, the :ref:`building block commands <v2-atomic-commands>` :py:meth:`~.InstrumentContext.aspirate` and :py:meth:`~.InstrumentContext.dispense` only operate in a single location. +The basic and liquid class transfer methods form the family of complex liquid handling commands. These methods require ``source`` and ``dest`` (destination) arguments to move liquid from one well, or group of wells, to another. In contrast, the :ref:`building block commands <v2-atomic-commands>` :py:meth:`~.InstrumentContext.aspirate` and :py:meth:`~.InstrumentContext.dispense` only operate in a single location. -For example, this command performs a simple transfer between two wells on a plate:: +This example uses :py:meth:`.InstrumentContext.transfer()` to perform a basic transfer between two wells on a plate:: pipette.transfer( volume=100, @@ -18,6 +18,20 @@ For example, this command performs a simple transfer between two wells on a plat .. versionadded:: 2.0 +You could also use :py:meth:`.InstrumentContext.transfer_with_liquid_class` to perform the transfer:: + + liquid_1 = protocol_context.define_liquid_class("glycerol_50") + pipette.transfer_with_liquid_class( + liquid_class=liquid_1, + volume=100, + source=plate["A1"], + dest=plate["A2"], + ) + +This time, the ``glycerol_50`` liquid class definition automatically optimizes transfer behavior on the Flex for your viscous liquid. + +.. versionadded:: 2.23 + This page covers the restrictions on sources and destinations for complex commands, their different patterns of aspirating and dispensing, and how to optimize them for different use cases. @@ -26,11 +40,11 @@ This page covers the restrictions on sources and destinations for complex comman Source and Destination Arguments ================================ -As noted above, the :py:meth:`~.InstrumentContext.transfer`, :py:meth:`~.InstrumentContext.distribute`, and :py:meth:`~.InstrumentContext.consolidate` methods require ``source`` and ``dest`` (destination) arguments to aspirate and dispense liquid. However, each method handles liquid sources and destinations differently. Understanding how complex commands work with source and destination wells is essential to using these methods effectively. +As noted above, each complex liquid handling command requires ``source`` and ``dest`` (destination) arguments to aspirate and dispense liquid. However, each method handles liquid sources and destinations differently. Understanding how complex commands work with source and destination wells is essential to using these methods effectively. :py:meth:`~.InstrumentContext.transfer` is the most versatile complex liquid handling function, because it has the fewest restrictions on what wells it can operate on. You will likely use transfer commands in many of your protocols. -Certain liquid handling cases focus on moving liquid to or from a single well. :py:meth:`~.InstrumentContext.distribute` limits its source to a single well, while :py:meth:`~.InstrumentContext.consolidate` limits its destination to a single well. Distribute commands also make changes to liquid-handling behavior to improve the accuracy of dispensing. +Certain liquid handling cases focus on moving liquid to or from a single well. :py:meth:`~.InstrumentContext.distribute` and :py:meth:`~.InstrumentContext.distribute_with_liquid_class` limit their sources to a single well, while :py:meth:`~.InstrumentContext.consolidate` and :py:meth:`~.InstrumentContext.consolidate_with_liquid_class` limit their destinations to a single well. The ``distribute()`` method and all liquid class complex commands also make changes to liquid-handling behavior to improve accuracy. The following table summarizes the source and destination restrictions for each method. @@ -44,18 +58,23 @@ The following table summarizes the source and destination restrictions for each - **Source:** Any number of wells. - **Destination:** Any number of wells. - The larger group of wells must be evenly divisible by the smaller group. - * - ``distribute()`` + * - ``transfer_with_liquid_class()`` + - + - **Source:** Any number of wells. + - **Destination:** Any number of wells. + - The total number of source and destination wells must be equal to one another. + * - ``distribute()`` and ``distribute_with_liquid_class()`` - - **Source:** Exactly one well. - **Destination:** Any number of wells. - * - ``consolidate()`` + * - ``consolidate()`` and ``consolidate_with_liquid_class()`` - - **Source:** Any number of wells. - **Destination:** Exactly one well. A single well can be passed by itself or as a list with one item: ``source=plate["A1"]`` and ``source=[plate["A1"]]`` are equivalent. -The section on :ref:`many-to-many transfers <many-to-many>` below covers how ``transfer()`` works when specifying sources and destinations of different sizes. However, if they don't meet the even divisibility requirement, the API will raise an error. You can work around such situations by making multiple calls to ``transfer()`` in sequence or by using a :ref:`list of volumes <complex-list-volumes>` to skip certain wells. +The section on :ref:`many-to-many transfers <many-to-many>` below covers how a basic ``transfer()`` works when specifying sources and destinations of different sizes. However, if they don't meet the even divisibility requirement, the API will raise an error. You can work around such situations by making multiple calls to ``transfer()`` in sequence or by using a :ref:`list of volumes <complex-list-volumes>` to skip certain wells. For distributing and consolidating, the API will not raise an error if you use a list of wells as the argument that is limited to exactly one well. Instead, the API will ignore everything except the first well in the list. For example, the following command will only aspirate from well A1:: @@ -65,19 +84,19 @@ For distributing and consolidating, the API will not raise an error if you use a dest=plate.columns()[1], ) -On the other hand, a transfer command with the same arguments would aspirate from both A1 and A2. The next section examines the exact order of aspiration and dispensing for all three methods. +On the other hand, a basic ``transfer()`` command with the same arguments would aspirate from both A1 and A2. The next section examines the exact order of aspiration and dispensing for all six methods. .. _complex-transfer-patterns: Transfer Patterns ================= -Each complex command uses a different pattern of aspiration and dispensing. In addition, when you provide multiple wells as both the source and destination for ``transfer()``, it maps the source list onto the destination list in a certain way. +Each complex command uses a different pattern of aspiration and dispensing. In addition, when you provide multiple wells as both the source and destination for a basic ``transfer()``, it maps the source list onto the destination list in a certain way. Aspirating and Dispensing ------------------------- -``transfer()`` always alternates between aspirating and dispensing, regardless of how many wells are in the source and destination. Its default behavior is: +``transfer()`` and ``transfer_with_liquid_class()`` always alternate between aspirating and dispensing, regardless of how many wells are in the source and destination. Their default behavior is: 1. Pick up a tip. 2. Aspirate from the first source well. @@ -92,7 +111,8 @@ Aspirating and Dispensing This transfer aspirates six times and dispenses six times. -``distribute()`` always fills the tip with as few aspirations as possible, and then dispenses to the destination wells in order. Its default behavior is: + +``distribute()`` and ``distribute_with_liquid_class()`` always fill the tip with as few aspirations as possible, and then dispenses to the destination wells in order. Their default behavior is: 1. Pick up a tip. 2. Aspirate enough to dispense in all the destination wells. This aspirate includes a disposal volume. @@ -109,7 +129,7 @@ See :ref:`complex-tip-refilling` below for cases where the total amount to be di This distribute aspirates one time and dispenses three times. -``consolidate()`` aspirates multiple times in a row, and then dispenses as few times as possible in the destination well. Its default behavior is: +``consolidate()`` and ``consolidate_with_liquid_class()`` aspirate multiple times in a row, and then dispense as few times as possible in the destination well. Their default behavior is: 1. Pick up a tip. 2. Aspirate from the first source well. @@ -125,9 +145,12 @@ See :ref:`complex-tip-refilling` below for cases where the total amount to be as :align: center This consolidate aspirates three times and dispenses one time. + + +In addition to their default behavior, all liquid class commands automatically include changes like flow rate, adding an air gap, or delaying based on the liquid class definition. For more inforamtion, see :ref:`liquid-classes`. .. note:: - By default, all three commands begin by picking up a tip and conclude by dropping a tip. In general, don't call :py:meth:`.pick_up_tip` just before a complex command, or the API will raise an error. You can override this behavior with the :ref:`tip handling complex parameter <param-tip-handling>`, by setting ``new_tip="never"``. + By default, all complex commands begin by picking up a tip and conclude by dropping a tip. In general, don't call :py:meth:`.pick_up_tip` just before a complex command, or the API will raise an error. You can override this behavior with the :ref:`tip handling complex parameter <param-tip-handling>`, by setting ``new_tip="never"``. .. _many-to-many: @@ -135,11 +158,13 @@ See :ref:`complex-tip-refilling` below for cases where the total amount to be as Many-to-Many ------------ -``transfer()`` lets you specify both ``source`` and ``dest`` arguments that contain multiple wells. This section covers how the method determines which wells to aspirate from and dispense to in these cases. +Both ``transfer()`` and ``transfer_with_liquid_class()`` let you specify both ``source`` and ``dest`` arguments that contain multiple wells. This section covers how these methods determine which wells to aspirate from and dispense to in these cases. -When the source and destination both contain the same number of wells, the mapping between wells is straightforward. You can imagine writing out the two lists one above each other, with each unique well in the source list paired to a unique well in the destination list. For example, here is the code for using one row as the source and another row as the destination, and the resulting correspondence between wells:: +The number of source and destination wells must be equal to one another in a ``transfer_with_liquid_class``. Here, the mapping between wells is straightforward. You can imagine writing out the two lists one above each other, with each unique well in the source list paired to a unique well in the destination list. For example, here is the code for using one row as the source and another row as the destination, and the resulting correspondence between wells:: - pipette.transfer( + liquid_1 = protocol_context.define_liquid_class("glycerol_50") + pipette.transfer_with_liquid_class( + liquid_class=liquid_1, volume=50, source=plate.rows()[0], dest=plate.rows()[1], @@ -175,7 +200,7 @@ When the source and destination both contain the same number of wells, the mappi - B11 - B12 -There's no requirement that the source and destination lists be mutually exclusive. In fact, this command adapted from the :ref:`tutorial <tutorial>` deliberately uses slices of the same list, saved to the variable ``row``, with the effect that each aspiration happens in the same location as the previous dispense:: +In a basic ``transfer()``, there's no requirement that the source and destination lists be mutually exclusive. In fact, this command adapted from the :ref:`tutorial <tutorial>` deliberately uses slices of the same list, saved to the variable ``row``, with the effect that each aspiration happens in the same location as the previous dispense:: row = plate.rows()[0] pipette.transfer( @@ -212,7 +237,7 @@ There's no requirement that the source and destination lists be mutually exclusi - A11 - A12 -When the source and destination lists contain different numbers of wells, ``transfer()`` will always aspirate and dispense as many times as there are wells in the *longer* list. The shorter list will be "stretched" to cover the length of the longer list. Here is an example of transferring from 3 wells to a full row of 12 wells:: +For a basic ``transfer()``, you can specify different numbers of wells. When the source and destination lists contain different numbers of wells, ``transfer()`` will always aspirate and dispense as many times as there are wells in the *longer* list. The shorter list will be "stretched" to cover the length of the longer list. Here is an example of transferring from 3 wells to a full row of 12 wells:: pipette.transfer( volume=50, @@ -264,7 +289,8 @@ The API raises this error rather than presuming which wells to aspirate from thr pipette.transfer(50, plate["A1"], plate.columns()[3][:3]) pipette.transfer(50, plate["A2"], plate.columns()[3][3:6]) pipette.transfer(50, plate["A3"], plate.columns()[3][6:]) - + + Finally, be aware of the ordering of source and destination lists when constructing them with :ref:`well accessor methods <well-accessor-methods>`. For example, at first glance this code may appear to take liquid from each well in the first row of a plate and move it to each of the other wells in the same column:: pipette.transfer( @@ -292,9 +318,11 @@ Here the repeat index ``i`` picks out: Optimizing Patterns ------------------- -Choosing the right complex command optimizes gantry movement and helps save time in your protocol. For example, say you want to take liquid from a reservoir and put 50 µL in each well of the first row of a plate. You could use ``transfer()``, like this:: +Choosing the right complex command optimizes gantry movement and helps save time in your protocol. For example, say you want to take liquid from a reservoir and put 50 µL in each well of the first row of a plate. You could use ``transfer_with_liquid_class()``, like this:: - pipette.transfer( + liquid_1 = protocol_context.define_liquid_class("glycerol_50") + pipette.transfer_with_liquid_class( + liquid_class=liquid_1, volume=50, source=reservoir["A1"], destination=plate.rows()[0], @@ -302,7 +330,9 @@ Choosing the right complex command optimizes gantry movement and helps save time This will produce 12 aspirate steps and 12 dispense steps. The steps alternate, with the pipette moving back and forth between the reservoir and plate each time. Using ``distribute()`` with the same arguments is more optimal in this scenario:: - pipette.distribute( + liquid_1 = protocol_context.define_liquid_class("glycerol_50") + pipette.distribute_with_liquid_class( + liquid_class=liquid_1, volume=50, source=reservoir["A1"], destination=plate.rows()[0], diff --git a/api/docs/v2/index.rst b/api/docs/v2/index.rst index 29fad41865b..42802ffbc5a 100644 --- a/api/docs/v2/index.rst +++ b/api/docs/v2/index.rst @@ -10,6 +10,8 @@ Welcome tutorial versioning new_labware + liquid_classes + liquid_class_definitions moving_labware new_modules deck_slots diff --git a/api/docs/v2/liquid_class_definitions.rst b/api/docs/v2/liquid_class_definitions.rst new file mode 100644 index 00000000000..a2b8b6f6174 --- /dev/null +++ b/api/docs/v2/liquid_class_definitions.rst @@ -0,0 +1,150 @@ +:og:description: How to select and apply a liquid class definition in Opentrons protocols. + +.. _liquid-class-definitions: + +Liquid Class Definitions +========================= + +A liquid class definition specifies nearly all transfer behavior a Flex pipette will perform during a :py:meth:`.InstrumentContext.transfer_with_liquid_class`, :py:meth:`.InstrumentContext.distribute_with_liquid_class`, or :py:meth:`.InstrumentContext.consolidate_with_liquid_class`. + +Let's take a look at a Flex P50 1-channel pipette transferring 30 µL of an ``aqueous`` liquid: + +## TODO: insert icons paired with text description for steps of this transfer. can also make this a transfer that performs every action.I already have a text description of a transfer in the Liquid Classes article- can keep both or cut the first to spend more time describing how to edit. + +The rest of this section details specific changes to transfer behavior for each liquid class. The transfer steps are listed in order the robot performs them. Advanced settings like mix, pre-wet tip, touch tip, and blowout are automatically disabled for liquid class transfers. + +To use the tables below, select your liquid class: :ref:`aqueous`, :ref:`viscous`, or :ref:`volatile`. Then, use the tabs feature to find your pipette and tip combination. + +The flow rates and air gap or push out volumes used in a liquid class transfer vary based on the pipette and tip combination in your protocol. Let's say you use a Flex P1000 1-channel pipette and Flex 200 µL tips to aspirate a volatile liquid. The transfer volume specifies the flow rate: +* 7 µL/sec to aspirate 5 µL +* 50 µL/sec to aspirate 50 µL +* 200 µL/sec to aspirate 200 µL + +When you aspirate a liquid between these three volumes, like 100 µL, a linear interpolation automatically determines the flow rate. + +.. _aqueous: + +Aqueous +------- +.. tabs:: + + .. tab:: Flex P50 1-channel + + +----------------+------------------------------+---------------------------------------------------+ + | | Transfer Step | Flex 96 Tiprack 50 µL | + +================+==============================+===================================================+ + | Aspirate | Submerge speed | 100 mm/sec | + | +------------------------------+---------------------------------------------------+ + | | Aspirate flow rate by volume | - Default: 50 µL/sec- 1 µL: 35 µL/sec | + | | | - 10 µL: 24 µL/sec- 50 µL: 35 µL/sec | + | +------------------------------+---------------------------------------------------+ + | | Correction by volume | -- | + | +------------------------------+---------------------------------------------------+ + | | Delay after aspirating | 0.2 sec | + | +------------------------------+---------------------------------------------------+ + | | Retract speed | 50 mm/sec | + | +------------------------------+---------------------------------------------------+ + | | Delay after retracting | -- | + | +------------------------------+---------------------------------------------------+ + | | Air gap by volume | - Default: 0.1 µL- 1-49.9 µL: 0.1 µL- 50 µL: 0 µL | + +----------------+------------------------------+---------------------------------------------------+ + | Dispense | Submerge speed | 100 mm/sec | + | +------------------------------+---------------------------------------------------+ + | | Dispense position | 2 mm above the well bottom | + | +------------------------------+---------------------------------------------------+ + | | Dispense flow rate by volume | Default: 50 µL | + | +------------------------------+---------------------------------------------------+ + | | Push out by volume | - Default: 2 µL- 1-4.999 µL: 7 µL- 5-50 µL: 2 µL | + | +------------------------------+---------------------------------------------------+ + | | Delay after push out | 0.2 sec | + | +------------------------------+---------------------------------------------------+ + | | Retract speed | 50 mm/sec | + | +------------------------------+---------------------------------------------------+ + | | Delay after retracting | -- | + | +------------------------------+---------------------------------------------------+ + | | Air gap by volume | - Default: 0.1µL- 1-49.9 µL: 0.1 µL- 50 µL: 0 µL | + +----------------+------------------------------+---------------------------------------------------+ + | Multi-dispense | Submerge speed | 100 mm/sec | + | +------------------------------+---------------------------------------------------+ + | | Dispense position | 2 mm below the well top | + | +------------------------------+---------------------------------------------------+ + | | Dispense flow rate by volume | 50 µL/sec | + | +------------------------------+---------------------------------------------------+ + | | Delay after dispensing | 0.2 sec | + | +------------------------------+---------------------------------------------------+ + | | Retract speed | 50 mm/sec | + | +------------------------------+---------------------------------------------------+ + | | Delay after retracting | -- | + | +------------------------------+---------------------------------------------------+ + | | Air gap by volume | - Default: 0.1 µL- 1-49.9 µL:0.1 µL- 50 µL: 0 µL | + +----------------+------------------------------+---------------------------------------------------+ + + +.. tabs:: + + .. tab:: Flex P50 8-channel + + +----------------+------------------------------+----------------------------------------------------------------+ + | | Transfer Step | Flex 96 Tiprack 50 µL | + +================+==============================+================================================================+ + | Aspirate | Submerge speed | 100 mm/sec | + | +------------------------------+----------------------------------------------------------------+ + | | Aspirate flow rate by volume | - Default: 50 µL/sec- 1 µL: 35 µL/sec | + | | | - 10 µL: 24 µL/sec- 50 µL: 35 µL/sec | + | +------------------------------+----------------------------------------------------------------+ + | | Correction by volume | -- | + | +------------------------------+----------------------------------------------------------------+ + | | Delay after aspirating | 0.2 sec | + | +------------------------------+----------------------------------------------------------------+ + | | Retract speed | 50 mm/sec | + | +------------------------------+----------------------------------------------------------------+ + | | Delay after retracting | -- | + | +------------------------------+----------------------------------------------------------------+ + | | Air gap by volume | - Default: 0.1 µL- 1-49.9 µL: 0.1 µL- 50 µL: 0 µL | + +----------------+------------------------------+----------------------------------------------------------------+ + | Dispense | Submerge speed | 100 mm/sec | + | +------------------------------+----------------------------------------------------------------+ + | | Dispense position | 2 mm above the well bottom | + | +------------------------------+----------------------------------------------------------------+ + | | Dispense flow rate by volume | Default: 50 µL | + | +------------------------------+----------------------------------------------------------------+ + | | Push out by volume | - Default: 2 µL- 1-4.999 µL: 7 µL- 5-50 µL: 2 µL - 50 µL: 3 µL | + | +------------------------------+----------------------------------------------------------------+ + | | Delay after push out | 0.3 sec | + | +------------------------------+----------------------------------------------------------------+ + | | Retract speed | 50 mm/sec | + | +------------------------------+----------------------------------------------------------------+ + | | Delay after retracting | -- | + | +------------------------------+----------------------------------------------------------------+ + | | Air gap by volume | - Default: 0.1µL- 1-49.9 µL: 0.1 µL- 50 µL: 0 µL | + +----------------+------------------------------+----------------------------------------------------------------+ + | Multi-dispense | Submerge speed | 100 mm/sec | + | +------------------------------+----------------------------------------------------------------+ + | | Dispense position | 2 mm above the well bottom | + | +------------------------------+----------------------------------------------------------------+ + | | Dispense flow rate by volume | 50 µL/sec | + | +------------------------------+----------------------------------------------------------------+ + | | Delay after dispensing | 0.3 sec | + | +------------------------------+----------------------------------------------------------------+ + | | Retract speed | 50 mm/sec | + | +------------------------------+----------------------------------------------------------------+ + | | Delay after retracting | -- | + | +------------------------------+----------------------------------------------------------------+ + | | Air gap by volume | - Default: 0.1 µL- 1-49.9 µL:0.1 µL- 50 µL: 0 µL | + +----------------+------------------------------+----------------------------------------------------------------+ + + +.. _viscous: + +Viscous +------- + +.. _volatile: + +Volatile +--------- + + + + + \ No newline at end of file diff --git a/api/docs/v2/liquid_classes.rst b/api/docs/v2/liquid_classes.rst new file mode 100644 index 00000000000..fb8a4683200 --- /dev/null +++ b/api/docs/v2/liquid_classes.rst @@ -0,0 +1,165 @@ +:og:description: How to select and apply a liquid class definition in Opentrons protocols. + +.. _liquid-classes: + +*************** +Liquid Classes +*************** + +At the core of your protocol are liquid transfers, the liquid handling steps the robot performs to move liquids in labware. + +Accounting for properties of a liquid, like viscosity or volatility, can improve pipetting accuracy on the Flex. You can use liquid classes in your protocols to automatically define optimized transfer behavior based on a specific liquid. For example, a slower flow rate can improve pipetting for a viscous liquid, and an air gap can prevent a volatile liquid from dripping onto the deck. + +Each Opentrons-verified liquid class is defined by a set of properties: + +.. list-table:: + :header-rows: 1 + + * - Property + - Description + * - Submerge position, speed + - + * Position where the pipette begins before submerging into the liquid. + * Speed the pipette submerges into the liquid at to prevent air bubbles from forming. + * - Delay + - + * Time the pipette delays before submerging into or retracting from liquid. + * Time the pipette delays before or after an aspirate or dispense, or after a push out. + * - Mix + - Mix liquid inside a well before an aspirate or after a dispense. + * - Pre-wet tip + - Pre-wet tip before an aspirate to prevent droplets from sticking to the pipette. + * - Flow rate* + - Speed the pipette aspirates or dispenses liquid at. + * - Retract position, speed + - + * Position the pipette moves to in order to retract from the liquid. + * Speed the pipette retracts at to prevent droplets from sticking to the pipette. + * - Push out* + - Volume of air the pipette dispenses to ensure all liquid leaves the tip. + * - Touch tip + - Pipette touches the tip to the sides of a well to remove droplets from the pipette. + * - Air gap* + - Pipette adds an air gap after an aspirate or dispense to prevent liquid from dripping onto the deck. + * - Blowout + - Larger volume of air the pipette dispenses to ensure all liquid leaves the tip. + + +## TODO: update property table with icons (?) and maybe for the most important parameters (chosen by Sanniti and Andy): +- required parameters: position reference + offset, speed, and delay, correctionByVolume, flowRateByVolume, delay, disposalByVolume, and conditioningByVolume, airGapByVolume and pushOutByVolume + blowout +- optional parameters: mix repetitions/volume, touch tip z offset, mmToEdge, and speed + +A :ref:`liquid class definition <liquid-class-definitions>` specifies values for each property based on the liquid class. When you transfer with a liquid class in your protocol, transfer behavior based on each property is automatically applied. For example, when you use `.InstrumentContext.transfer_with_liquid_class` to transfer a viscous liquid, your Flex pipette automatically submerges more slowly into the liquid to prevent air bubbles from forming. + +Properties marked with an asterisk, shown above, are determined by your pipette, tip, and volume combinations. For more information, see :ref:`liquid-class-definitions`. + +.. _opentrons-verified-liquid-classes: + +Opentrons-verified Liquid Classes +================================= + +Opentrons-verified liquid classes are liquid class definitions based on the properties of a specific liquid: + +.. list-table:: + :header-rows: 1 + + * - Opentrons-verified liquid class + - Description + - Load name + * - Aqueous + - + * Based on deionized water + * The system default + - ``water`` + * - Volatile + - Based on 80% ethanol + - ``ethanol_80`` + * - Viscous + - Based on 50% glycerol + - ``glycerol_50`` + +You can define and specify liquid classes in your protocols to automatically apply transfer behavior like flow rate, submerge and retract speeds, and advanced settings optimized for your liquid class. + +.. _selecting-a-liquid-class: + +Selecting a Liquid Class +======================== + +You'll use a :ref:`liquid class definition <liquid-class-definitions>` in your protocol to optimize transfer behavior based not only on liquid properties, but on your chosen Flex pipette and tips. Start by defining the tips, trash, pipette, and labware used in your transfers. Then, use :py:meth:`.ProtocolContext.define_liquid_class` to select a liquid class. + +.. code-block:: python + :substitutions: + + from opentrons import protocol_api + + requirements = {"robotType": "Flex", "apiLevel": "|2.23|"} + + # define tips, trash, and pipette + def run(protocol: protocol_api.ProtocolContext): + tiprack1 = protocol_context.load_labware("opentrons_flex_96_tiprack_50ul", "D3") + trash = protocol_context.load_trash_bin("A3") + pipette_50 = protocol_context.load_instrument("flex_1channel_50", "left, tip_racks=[tiprack1]") + + ## load source and destination labware + + nest_plate = protocol_context.load_labware("nest_96_wellplate_200ul_flat", "C3") + arma_plate = protocol_context.load_labware("armadillo_96_wellplate_200ul_pcr_full_skirt","C2") + + # select liquid classes + + liquid_1 = protocol_context.define_liquid_class("glycerol_50") + liquid_2 = protocol_context.define_liquid_class("ethanol_80") + liquid_3 = protocol_context.define_liquid_class("glycerol_50") + + +You'll need to add a label to liquid classes in your protocol, like ``liquid_1``. Not only does this help you keep track of multiple liquids of the same class in a protocol, but ``transfer_with_liquid_class()`` requires a label previously defined in your protocol instead of a liquid class load name, like ``glycerol_50``. + +.. _liquid-class-transfers: + +Liquid Class Transfers +====================== + +Use ``transfer_with_liquid_class`` to transfer an aqueous, volatile, or viscous liquid defined in your protocol. Here, you'll specify your liquid, volume, source, and destination wells, tip handling preferences, and the trash location. + +TODO: add in transfer_with_liquid_class py meth references when updated + +.. code-block:: python + + pipette_50.transfer_with_liquid_class( + liquid_class=liquid_1, + volume=50, + source=nest_plate.rows()[0], + dest=arma_plate.rows()[0], + new_tip="always", + trash_location=trash) + +The Flex P50 1-channel pipette will transfer 50 µL of your viscous ``liquid_1`` from each well of the source plate to each well of the destination plate. A new tip is used for each well transfer, and each tip is dropped in the trash bin loaded in slot A3. + +The ``glycerol_50`` viscous liquid class definition accounts for all other transfer behavior, like flow rate, whether or not to add an air gap or delay, and submerge and retract speeds. For each aspirate, the pipette: + +* Moves to the submerge start position of 2 mm above the top of the source well at 4 mm/sec. +* Submerges into ``liquid_1`` at 4 mm/sec to the aspirate start position of 2 mm above the bottom of the well. +* Aspirates 50 µL of ``liquid_1`` at 50 µL/sec with a correction by volume of -0.2 µL. +* Delays for 1 sec after aspirating. +* Moves to the retract position of 2 mm above the top of the well at 4 mm/sec. + +And for each dispense, the pipette: + +* Moves to the submerge start position of 2 mm above the top of the destination well at 4 mm/sec. +* Moves to the dispense position of 2 mm above the top of the destination well at 4 mm/sec. +* Dispense 50 µL of ``liquid_1`` at 25 µL/sec with a correction by volume of -0.2 µL. +* Pushes out a volume of air equivalent to 3.9 µL to ensure all liquid leaves the tip, and delays for 0.5 sec afterward. +* Moves to the retract position of 2 mm above the top of the well at 4 mm/sec. + +In many cases, the liquid class definition represents fine-tuned changes optimized for each liquid class. If you instead use the Flex P50 1-channel pipette to transfer 50 µL of a volatile liquid, transfer behavior would include: +* Submerging into and retracting from the volatile ``liquid_2`` at 100 mm/sec. +* Adding larger air gaps after aspirating *and* dispensing to prevent dripping onto the deck. +* Aspirating and dispensing at 30 µL/sec with a larger correction by volume. +* Pushing out a larger volume of air to ensure all liquid leaves the tip. + +Not all transfer behavior is easily visible. See :ref:`liquid-class-definitions` for a full list of changes based on liquid class, pipette, and tip combination. For more detail on individual transfer settings, see :ref:`liquid-control`. + +##TODO: possibly insert an "edit a liquid class definition" section with 8.5 +##TODO: could also set up a toctree for liquid classes > liquid class definitions + editing a liquid class articles within + + diff --git a/api/docs/v2/new_complex_commands.rst b/api/docs/v2/new_complex_commands.rst index 161a6dc8549..e37928b9793 100644 --- a/api/docs/v2/new_complex_commands.rst +++ b/api/docs/v2/new_complex_commands.rst @@ -11,13 +11,27 @@ Complex Commands complex_commands/order_operations complex_commands/parameters -Complex liquid handling commands combine multiple :ref:`building block commands <v2-atomic-commands>` into a single method call. These commands make it easier to handle larger groups of wells and repeat actions without having to write your own control flow code. They integrate tip-handling behavior and can pick up, use, and drop multiple tips depending on how you want to handle your liquids. They can optionally perform other actions, like adding air gaps, knocking droplets off the tip, mixing, and blowing out excess liquid from the tip. +Complex liquid handling commands combine multiple :ref:`building block commands <v2-atomic-commands>` into a single method call. These commands make it easier to handle larger groups of wells and repeat actions without having to write your own control flow code. They integrate tip-handling behavior and can pick up, use, and drop multiple tips depending on how you want to handle your liquids. -There are three complex liquid handling commands, each optimized for a different liquid handling scenario: +There are six complex liquid handling commands, each optimized for a different liquid handling scenario: + +.. list-table:: + :header-rows: 1 + + * - Basic + - + * :py:meth:`.InstrumentContext.transfer` + * :py:meth:`.InstrumentContext.distribute` + * :py:meth:`.InstrumentContext.consolidate` + * - Liquid Class + - + * :py:meth:`.InstrumentContext.transfer_with_liquid_class` + * :py:meth:`.InstrumentContext.distribute_with_liquid_class` + * :py:meth:`.InstrumentContext.consolidate_with_liquid_class` + + +The basic commands can optionally perform other actions, like adding air gaps, knocking droplets off the tip, mixing, and blowing out excess liquid from the tip. In a liquid class command, these and other transfer behaviors are determined by a liquid class definition to account for properties like viscosity. For more information, see :ref:`liquid-classes`. - - :py:meth:`.InstrumentContext.transfer` - - :py:meth:`.InstrumentContext.distribute` - - :py:meth:`.InstrumentContext.consolidate` Pages in this section of the documentation cover: diff --git a/api/docs/v2/new_examples.rst b/api/docs/v2/new_examples.rst index 42dbf92fd8d..88ed57856d4 100644 --- a/api/docs/v2/new_examples.rst +++ b/api/docs/v2/new_examples.rst @@ -193,7 +193,9 @@ This protocol uses some :ref:`building block commands <v2-atomic-commands>` to t Advanced Method --------------- -This protocol accomplishes the same thing as the previous example, but does it a little more efficiently. Notice how it uses the :py:meth:`.InstrumentContext.transfer` method to move liquid between well plates. The source and destination well arguments (e.g., ``plate["A1"], plate["B1"]``) are part of ``transfer()`` method parameters. You don't need separate calls to ``aspirate`` or ``dispense`` here. +These protocols accomplish the same thing as the previous example, but do it a little more efficiently. Here, use the :py:meth:`.InstrumentContext.transfer` or :py:meth:`.InstrumentContext.transfer_with_liquid_class` method to move liquid between well plates. Because each is a complex command, you don't need separate calls to ``aspirate`` or ``dispense`` here. + +Let's start with a basic complex command, using ``transfer()``. The source and destination well arguments (e.g., ``plate["A1"], plate["B1"]``) are part of ``transfer()`` method parameters. .. tabs:: @@ -244,6 +246,44 @@ This protocol accomplishes the same thing as the previous example, but does it a # transfer 100 µL from well A1 to well B1 p300.transfer(100, plate["A1"], plate["B1"]) +When using the liquid class complex command ``transfer_with_liquid_class()``, you'll need to specify a ``liquid_class`` along with volume, source and destination, and trash parameters. + +Only Flex pipettes can perform liquid class transfers. + +.. tab:: Flex + + .. code-block:: python + :substitutions: + + from opentrons import protocol_api + + metadata = {"apiLevel": "|apiLevel|"} + + def run(protocol: protocol_api.ProtocolContext): + plate = protocol.load_labware( + load_name="corning_96_wellplate_360ul_flat", + location="D1" + ) + tiprack_1 = protocol.load_labware( + load_name="opentrons_flex_96_tiprack_200ul", + location="C1" + ) + p50 = protocol.load_instrument( + instrument_name="flex_1channel_50", + mount="left", + tip_racks=[tiprack_1] + ) + liquid_1 = protocol.define_liquid_class("glycerol_50") + trash = protocol.load_trash_bin("A3") + + # transfer 100 µL from well A1 to well B1 + p50.transfer_with_liquid_class( + liquid_class=liquid_1, + volume=100, + source=plate["A1"], + dest=plate["B1"], + trash_location=trash) + Loops ===== diff --git a/api/docs/v2/pipettes/characteristics.rst b/api/docs/v2/pipettes/characteristics.rst index 00971d71832..957d987d83f 100644 --- a/api/docs/v2/pipettes/characteristics.rst +++ b/api/docs/v2/pipettes/characteristics.rst @@ -127,8 +127,26 @@ Finally, let's tell the robot to dispense 100 µL into the well plate at locatio 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. +The eight pipette channels will only dispense into every other well in the column: B1, D1, F1, H1, J1, L1, N1, and P1. +Liquid Class Transfers +----------------------- +You can transfer liquids of a defined class with single or multi-channel pipettes. + +Instead of providing the primary nozzle for a method like :py:meth:`.InstrumentContext.transfer_with_liquid_class`, you'll need to provide every well that will be visited during a transfer that uses partial tip pickup. Let's look at an example with each well of two 96-well plates:: + + liquid_1 = protocol.define_liquid_class("glycerol_50") + trash = protocol.load_trash_bin("A3") + + right.transfer_with_liquid_class( + liquid_class=liquid_1, + volume=50, + source=plate[.wells] + dest=plate_2[.wells] + trash_location=trash + ) + +TODOs: updated to include a better explanation (still needs work). is this the best section? does this cover all examples (emphasize further this situtation with 96 and 384 well plates)? check code blocks. .. _new-plunger-flow-rates: diff --git a/api/src/opentrons/protocol_api/protocol_context.py b/api/src/opentrons/protocol_api/protocol_context.py index 11d0f20a22c..613cd5147ee 100644 --- a/api/src/opentrons/protocol_api/protocol_context.py +++ b/api/src/opentrons/protocol_api/protocol_context.py @@ -1364,7 +1364,6 @@ def define_liquid_class( """ Define a liquid class for use in the protocol. - :meta private: """ return self._core.define_liquid_class(name=name)