Skip to content

docs(api): liquid meniscus in API 2.23 #17971

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 16, 2025
62 changes: 62 additions & 0 deletions api/docs/v2/basic_commands/liquids.rst
Original file line number Diff line number Diff line change
@@ -48,6 +48,28 @@ You can also aspirate from a location along the center vertical axis within a we
depth = plate["A1"].bottom(z=2) # tip is 2 mm above well bottom
pipette.aspirate(200, depth)


Use the :py:meth:`.Well.meniscus` method to aspirate relative to the meniscus of liquid in a well with a Flex pipette. First, you'll need to determine the amount of liquid in your well one of two ways:

- Specify your starting liquid volume with :py:meth:`~.Labware.load_liquid`.
- Measure the height of the liquid with :py:meth:`~.InstrumentContext.measure_liquid_height`.

This example measures the liquid height in well A2 of a plate and then immediately aspirates below the meniscus::

pipette.pick_up_tip()
pipette.measure_liquid_height(plate["A2"])
pipette.aspirate(
volume=200,
location=plate["A2"].meniscus(target="end", z=-1)
)
# aspirates at 1 mm below the liquid meniscus

The liquid meniscus changes when you aspirate liquid from a well. Set ``target="end"`` to ensure the pipette stays submerged while aspirating. For more information, see :ref:`well-meniscus`.

``measure_liquid_height()`` works best with a new pipette tip each time. To save time and tips throughout your protocol, use ``Labware.load_liquid`` instead to specify starting liquid volumes.

.. versionadded:: 2.23

See also:

- :ref:`new-default-op-positions` for information about controlling pipette height for a particular pipette.
@@ -105,6 +127,27 @@ You can also dispense from a location along the center vertical axis within a we
depth = plate["B1"].bottom(z=2) # tip is 2 mm above well bottom
pipette.dispense(200, depth)


Use the :py:meth:`.Well.meniscus` method to dispense at the meniscus of liquid in your well with a Flex pipette. First, you'll need to determine the amount of liquid in your well one of two ways:

- Specify your starting liquid volume with :py:meth:`~.Labware.load_liquid`.
- Measure the height of liquid with :py:meth:`~.InstrumentContext.measure_liquid_height`.

This example measures the liquid height in well B1 of a plate and then immediately dispenses below the meniscus::

pipette.measure_liquid_height(plate["B1"])
pipette.dispense(
volume=200,
location=plate["B1"].meniscus(target="start", z=-1)
)
# dispenses at 1 mm below the liquid meniscus

The liquid meniscus changes when you dispense liquid into a well. Set ``target="start"`` to ensure the pipette begins the dispense at the liquid meniscus. For more information, see :ref:`well-meniscus`.

``measure_liquid_height()`` works best with a new pipette tip each time. To save time and tips throughout your protocol, use ``Labware.load_liquid`` instead to specify starting liquid volumes.

.. versionadded:: 2.23

See also:

- :ref:`new-default-op-positions` for information about controlling pipette height for a particular pipette.
@@ -323,3 +366,22 @@ The :py:meth:`.InstrumentContext.require_liquid_presence` method tells a Flex pi
You can also require liquid presence for all aspirations performed with a given pipette. See :ref:`lpd`.

.. versionadded:: 2.20

.. _measure-liquids:

Measure Liquids
===============

The :py:meth:`~.InstrumentContext.measure_liquid_height` method tells a Flex pipette to measure the height of liquid relative to the bottom of a well. When ``measure_liquid_height()`` finds an empty well, it raises and error and pauses the protocol to let you resolve the problem.

``measure_liquid_height()`` is a standalone method that records the height of liquid in a well during a protocol. You can use the liquid height to aspirate or dispense from, or move to, the liquid meniscus, either immediately after or later in your protocol.

.. code-block:: python

pipette.pick_up_tip()
pipette.measure_liquid_height(plate["A1"])
pipette.aspirate(
volume=200, location=plate["A1"].meniscus(target="end", z=-1)
) # aspirates from 1 mm below the liquid meniscus

You don't have to aspirate after measuring liquid height, but you should always pick up a tip immediately prior to measuring the liquid height, and either aspirate or drop the tip immediately after. This ensures that the pipette uses a clean, dry tip to check for liquid, and prevents cross-contamination.
3 changes: 1 addition & 2 deletions api/docs/v2/new_protocol_api.rst
Original file line number Diff line number Diff line change
@@ -28,8 +28,7 @@ Labware
=======
.. autoclass:: opentrons.protocol_api.Labware
:members:
:exclude-members: next_tip, use_tips, previous_tip, return_tips, load_empty, load_liquid, load_liquid_by_well

:exclude-members: next_tip, use_tips, previous_tip, return_tips
..
The trailing ()s at the end of TrashBin and WasteChute here hide the __init__()
signatures, since users should never construct these directly.
2 changes: 1 addition & 1 deletion api/docs/v2/pipettes/loading.rst
Original file line number Diff line number Diff line change
@@ -261,7 +261,7 @@ Let's take a look at how all this works. With automatic liquid detection enabled

Liquid detection takes place prior to aspiration. Upon detecting a liquid, the pipette stops, raises itself above the liquid's surface, and then aspirates according to your protocol. Checking for a liquid adds time to your protocol run, so be aware of that before using it. If Flex doesn't detect liquid, it raises an error and stops the protocol until the problem is resolved.

However, aspiration isn't required for liquid level detection. Two standalone methods, :py:meth:`.detect_liquid_presence` and :py:meth:`.require_liquid_presence`, let you add liquid detection to a protocol with or without aspirating. Automatic detection is the same as calling ``require_liquid_presence()`` before every aspiration. See :ref:`detect-liquid-presence` and :ref:`require-liquid-presence` for details.
However, aspiration isn't required for liquid level detection. Three standalone methods, :py:meth:`.detect_liquid_presence`, :py:meth:`.require_liquid_presence`, and :py:meth:`.measure_liquid_height`, let you add liquid detection to a protocol with or without aspirating. Automatic detection is the same as calling ``require_liquid_presence()`` before every aspiration. See :ref:`detect-liquid-presence`, :ref:`require-liquid-presence`, or :ref:`measure-liquids` for details.

.. versionadded:: 2.20

39 changes: 34 additions & 5 deletions api/docs/v2/robot_position.rst
Original file line number Diff line number Diff line change
@@ -16,10 +16,12 @@ Position Relative to Labware

When the robot positions itself relative to a piece of labware, where it moves is determined by the labware definition, the actions you want it to perform, and the labware offsets for a specific deck slot. This section describes how these positional components are calculated and how to change them.

Top, Bottom, and Center
-----------------------
Well Positions
---------------------------------

Every well on every piece of labware has three addressable positions: top, bottom, and center. The position is determined by the labware definition and what the labware is loaded on top of. You can use these positions as-is or calculate other positions relative to them.
Every well on every piece of labware has four addressable positions: top, bottom, center, and meniscus.

The top, bottom, and center positions are determined by the labware definition and what the labware is loaded on top of. The meniscus position is determined by the height of the liquid inside a well. You can use these positions as-is or calculate other positions relative to them.

.. _well-top:

@@ -79,13 +81,39 @@ Let's look at the :py:meth:`.Well.center` method. It returns a position centered

.. versionadded:: 2.0

.. _well-meniscus:

Meniscus
^^^^^^^^

Let's look at the :py:meth:`.Well.meniscus` method. It returns a position at the surface of liquid, or meniscus, inside a well. Like the ``.Well.top`` and ``.Well.bottom`` methods, you can adjust the height of the meniscus with the optional argument ``z``, which is measured in mm. Positive ``z`` values move the position up, and negative ones move it down.

.. code-block:: python

plate["A1"].meniscus(
target= "end", z=-1
)
# 1 mm below the meniscus of liquid inside the well


The liquid meniscus in a well changes during aspirating or dispensing, so you'll also need to specify a ``target`` position relative to the meniscus. Each position target is useful in different scenarios:

- Set ``target="start"`` to target the existing liquid meniscus in the destination well before a dispense.
- Set ``target="end"`` to ensure the pipette stays submerged while aspirating, or to avoid touching liquid in the destination well while dispensing.

.. note::
To use the :py:meth:`~.Well.meniscus` method, you'll first need to specify the starting liquid volume with :py:meth:`~.Labware.load_liquid` or probe for liquid with :py:meth:`~.InstrumentContext.measure_liquid_height`.

Detecting liquid in a well requires pipette sensors, so you can only measure liquid height with a Flex pipette.

.. versionadded:: 2.23

.. _new-default-op-positions:

Default Positions
-----------------

By default, your robot will aspirate and dispense 1 mm above the bottom of wells. This default clearance may not be suitable for some labware geometries, liquids, or protocols. You can change this value by using the :py:meth:`.Well.bottom` method with the ``z`` argument, though it can be cumbersome to do so repeatedly.
By default, your robot will aspirate and dispense 1 mm above the bottom of wells. This default clearance may not be suitable for some labware geometries, liquids, or protocols. You can change this value based on your labware with the :py:meth:`.Well.bottom` method and the ``z`` argument, though it can be cumbersome to do so repeatedly.

If you need to change the aspiration or dispensing height for multiple operations, specify the distance in mm from the well bottom with the :py:obj:`.InstrumentContext.well_bottom_clearance` object. It has two attributes: ``well_bottom_clearance.aspirate`` and ``well_bottom_clearance.dispense``. These change the aspiration height and dispense height, respectively.

@@ -110,6 +138,7 @@ Modifying these attributes will affect all subsequent aspirate and dispense acti
pipette.dispense(50, plate["A1"])

.. versionadded:: 2.0


Using Labware Position Check
============================
@@ -169,7 +198,7 @@ Move To

The :py:meth:`.InstrumentContext.move_to` method moves a pipette to any reachable location on the deck. If the pipette has picked up a tip, it will move the end of the tip to that position; if it hasn't, it will move the pipette nozzle to that position.

The :py:meth:`~.InstrumentContext.move_to` method requires the :py:class:`.Location` argument. The location can be automatically generated by methods like ``Well.top()`` and ``Well.bottom()`` or one you've created yourself, but you can't move a pipette to a well directly:
The :py:meth:`~.InstrumentContext.move_to` method requires the :py:class:`.Location` argument. The location can be automatically generated by methods like ``Well.top()``, ``Well.bottom()``, and ``Well.mensicus()``, or one you've created yourself. However, you can't move a pipette to a well directly:

.. code-block:: python

6 changes: 3 additions & 3 deletions api/src/opentrons/protocol_api/labware.py
Original file line number Diff line number Diff line change
@@ -268,10 +268,10 @@ def meniscus(
"""
:param z: An offset on the z-axis, in mm. Positive offsets are higher and
negative offsets are lower.
:param target: The relative position inside the well to target when performing a liquid handling operation.
:return: A :py:class:`~opentrons.types.Location` that indicates location is meniscus and that holds the ``z`` offset in its point.z field.
:param target: The relative position of the liquid meniscus inside the well to target when performing a liquid handling operation.

:return: A :py:class:`~opentrons.types.Location` corresponding to the liquid meniscus, plus a target position and ``z`` offset as specified.

:meta private:
"""
return Location(
point=Point(x=0, y=0, z=z),