Skip to content

fix(api): meniscus relative positioning in LC based transfers#18097

Merged
sanni-t merged 6 commits intoedgefrom
api-fix-meniscus-rel-positioning-in-lc-based-transfers
Apr 28, 2025
Merged

fix(api): meniscus relative positioning in LC based transfers#18097
sanni-t merged 6 commits intoedgefrom
api-fix-meniscus-rel-positioning-in-lc-based-transfers

Conversation

@sanni-t
Copy link
Copy Markdown
Member

@sanni-t sanni-t commented Apr 16, 2025

Closes AUTH-1653

Overview

Meniscus relative positions for aspirate & dispense will now be relative to the position of meniscus of the liquid after the aspirate or dispense action.

Updated the absolute_point_from_position_reference_and_offset() function to use well.estimate_liquid_height_after_pipetting() instead of well.meniscus()

Test Plan and Hands on Testing

Added unit tests but will need to be tested on a real Flex in order to test that the pipette goes to the correct location.

Test protocol (updated after rebasing onto edge)-

metadata = {
"name": "Perform a liquid transfer using water class"
}

requirements = {
"robotType": "Flex",
"apiLevel": "2.23"
}

def run(protocol_context):
	tiprack = protocol_context.load_labware("opentrons_flex_96_tiprack_200ul", "A2")
	trash = protocol_context.load_trash_bin('A3')
	pipette_1k = protocol_context.load_instrument(
		"flex_1channel_1000", "left", tip_racks=[tiprack], liquid_presence_detection=True)

	source = protocol_context.load_labware("nest_96_wellplate_2ml_deep", "C1")
	dest_plate = protocol_context.load_labware(
		"opentrons_96_wellplate_200ul_pcr_full_skirt", "C2")

	water = protocol_context.define_liquid(name="Aqueous", description="H₂O",
		display_color="#738ee6")
	source.load_liquid(wells=source.wells(), liquid=water, volume=500)
	dest_plate.load_empty(wells=dest_plate.wells())

	water_class = protocol_context.define_liquid_class("water")
	water_props = water_class.get_for(pipette_1k, tiprack)

	# Should start submerging with submerge speed
	# from 5mm above the current src liquid height
	water_props.aspirate.submerge.start_position.position_reference = "liquid-meniscus"
	water_props.aspirate.submerge.start_position.offset = (0, 0, 5)

	# Should aspirate from 1.5mm below the expected position of meniscus
	# *after* the liquid is aspirated
	# So if we expect the meniscus to be at 5mm above well bottom after aspirating,
	# then it should aspirate the liquid from 3.5mm above well bottom
	water_props.aspirate.aspirate_position.position_reference = "liquid-meniscus"
	water_props.aspirate.aspirate_position.offset = (0, 0, -1.5)

	# Should retract to 5mm above the current height of liquid in source
	water_props.aspirate.retract.end_position.position_reference = "liquid-meniscus"
	water_props.aspirate.retract.end_position.offset = (0, 0, 5)

	# Should start submerging with submerge speed
	# from 40mm above the current destination liquid height 
	# (which should be 40mm above well-bottom since there's no liquid in dest well yet)
	water_props.dispense.submerge.start_position.position_reference = "liquid-meniscus"
	water_props.dispense.submerge.start_position.offset = (0, 0, 40)

	# Should dispense from 2mm above the expected position of meniscus
	# *after* the liquid is dispensed in the dest.
	# So if we expect the meniscus to be at 20mm above well bottom after dispensing,
	# then it should dispense the liquid from 22mm above well bottom
	water_props.dispense.dispense_position.position_reference = "liquid-meniscus"
	water_props.dispense.dispense_position.offset = (0, 0, 2.0)

	# Should transfer successfully
	pipette_1k.transfer_with_liquid_class(
		liquid_class=water_class,
		volume=100,
		source=source.wells_by_name()['A1'],
		dest=dest_plate.wells_by_name()['A1'],
		new_tip="once",
		trash_location=trash,
		)

Pipette positioning expectations-

  • The pipette will probe the source well and find the correct meniscus
  • Pipette will go to submerge loc of 5mm above current meniscus in source well
  • Pipette will start submerging and go to 1.5mm below liquid height expected after aspirating 100uL
  • Will aspirate 100ul
  • Will retract to 5mm above the meniscus
  • Pipette will go to submerge loc of 40mm above current meniscus in dest well (which will just be 40mm from bottom)
  • Pipette will move to 2mm above when meniscus will be after dispensing
  • Will dispense
  • Pipette will retract to 2mm above well top

Review requests

  • When do we expect estimate_liquid_height_after_pipetting to return a SimulatedProbeResult? How should we handle it?
  • Am I using the height estimation function correctly?

Risk assessment

Low. Only affects meniscus-relative pipetting locations

@sanni-t sanni-t requested a review from a team as a code owner April 16, 2025 18:45
Comment on lines 866 to +841
case PositionReference.LIQUID_MENISCUS:
meniscus_point = well.get_meniscus()
if not isinstance(meniscus_point, Point):
reference_point = well.get_center()
estimated_liquid_height = well.estimate_liquid_height_after_pipetting(
operation_volume=well_volume_difference,
)
if isinstance(estimated_liquid_height, (float, int)):
reference_point = well.get_bottom(z_offset=estimated_liquid_height)
else:
reference_point = meniscus_point
# If estimated liquid height gives a SimulatedProbeResult then
# assume meniscus is at well center.
# Will this cause more harm than good? Is there a better alternative to this?
reference_point = well.get_center()
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andySigler @caila-marashaj am I using the estimate_liquid_height_after_pipetting function correctly?

@sanni-t sanni-t requested a review from jbleon95 April 16, 2025 20:49
Copy link
Copy Markdown
Contributor

@jbleon95 jbleon95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code make senses, thanks for the doc strings and comments

@sanni-t
Copy link
Copy Markdown
Member Author

sanni-t commented Apr 16, 2025

There's a known bug in this implementation that will raise an error if meniscus relative positions are specified for aspirate or dispense and the protocol does not specify well volumes with load_liquid(). There is no issue if you specify meniscus relative positions for submerge and retract without using load_liquid().

This does not affect any well-relative positions at all so I think this can still be merged so that meniscus relative positions are corrected for testing. I will follow up with a fix for the described bug.

@sanni-t sanni-t force-pushed the api-fix-meniscus-rel-positioning-in-lc-based-transfers branch from 5cd4258 to 4a2c86c Compare April 28, 2025 04:49
@sanni-t sanni-t requested review from a team as code owners April 28, 2025 04:49
@sanni-t sanni-t requested review from ncdiehl11 and removed request for a team April 28, 2025 04:49
@sanni-t sanni-t changed the base branch from chore_release-8.4.0 to edge April 28, 2025 04:49
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 28, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 57.38%. Comparing base (72ee75d) to head (9e79746).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             edge   #18097   +/-   ##
=======================================
  Coverage   57.38%   57.38%           
=======================================
  Files        3041     3041           
  Lines      255256   255256           
  Branches    30439    30439           
=======================================
  Hits       146484   146484           
  Misses     108586   108586           
  Partials      186      186           
Flag Coverage Δ
protocol-designer 18.98% <ø> (ø)
step-generation 4.37% <ø> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sanni-t
Copy link
Copy Markdown
Member Author

sanni-t commented Apr 28, 2025

There's a known bug in this implementation ..

Update: Fixed the above bug. The transfer will no longer raise any wrongful errors if meniscus relative positions are specified for aspirate or dispense and the protocol does not specify well volumes with load_liquid()

@sanni-t sanni-t requested a review from jbleon95 April 28, 2025 15:03
Copy link
Copy Markdown
Contributor

@jbleon95 jbleon95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes and code reorganization since last review all look good and make sense.

@sanni-t sanni-t merged commit 7429fae into edge Apr 28, 2025
24 checks passed
ddcc4 pushed a commit that referenced this pull request May 16, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations
ddcc4 pushed a commit that referenced this pull request May 16, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations
ddcc4 pushed a commit that referenced this pull request May 16, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations
ddcc4 pushed a commit that referenced this pull request May 16, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations
ddcc4 pushed a commit that referenced this pull request May 17, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations
ddcc4 pushed a commit that referenced this pull request May 17, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations
ddcc4 pushed a commit that referenced this pull request May 17, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations
ddcc4 pushed a commit that referenced this pull request May 17, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 17, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 17, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 17, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 17, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 17, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 19, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 19, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 19, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 20, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 20, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 22, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 23, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 24, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 24, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 29, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 29, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 29, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 29, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 29, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 29, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
ddcc4 pushed a commit that referenced this pull request May 29, 2025
Closes AUTH-1653

# Overview

Meniscus relative positions for aspirate & dispense will now be relative
to the position of meniscus of the liquid *after* the aspirate or
dispense action.

Updated the `absolute_point_from_position_reference_and_offset()`
function to use `well.estimate_liquid_height_after_pipetting()` instead
of `well.meniscus()`

## Risk assessment

Low. Only affects meniscus-relative pipetting locations

(cherry picked from commit 7429fae)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants