Skip to content

feat(api): prepare for aspirate in air gap#17919

Merged
sfoster1 merged 3 commits intochore_release-8.4.0from
exec-1391-prepare-before-air-gap
Mar 31, 2025
Merged

feat(api): prepare for aspirate in air gap#17919
sfoster1 merged 3 commits intochore_release-8.4.0from
exec-1391-prepare-before-air-gap

Conversation

@sfoster1
Copy link
Copy Markdown
Member

@sfoster1 sfoster1 commented Mar 28, 2025

We should add a prepare-to-aspirate to the python protocol api air_gap command, where it can issue the command after we've moved to a known-dry position and before we actually dispense the airgap command. We know the position is dry and therefore it's safe to do a prepare.

However, to be able to unconditionally do a prepare, we also need to add a fix to the engine prepare command to no-op if the pipette is already prepared to aspirate. This is pretty important because if we've already aspirated some liquid, we really don't want to move back to the bottom position and dispense it all.

Useful testing protocol:

from opentrons.protocol_api import ProtocolContext

metadata = {"protocolName": "Test air gap prepare"}
requirements = {"apiLevel": "2.22", "robotType": "Flex"}


def run(protocol: ProtocolContext) -> None:
    plate = protocol.load_labware("biorad_384_wellplate_50ul", "A1")
    rack = protocol.load_labware("opentrons_flex_96_tiprack_50ul", "A2")
    pipette = protocol.load_instrument("flex_1channel_50", "left", tip_racks=[rack])

    pipette.pick_up_tip()
    pipette.aspirate(location=plate["A1"].bottom(z=2), volume=10)
    pipette.dispense(location=plate["A1"].top(), volume=10)
    pipette.blow_out(location=plate["A1"].top())
    pipette.air_gap(height=5, volume=10)

    pipette.dispense(location=plate["A2"].top(), volume=10)
    pipette.return_tip()

Closes EXEC-1391

@sfoster1 sfoster1 requested review from a team as code owners March 28, 2025 14:21
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 28, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 25.82%. Comparing base (e1eac6f) to head (ace126d).
Report is 7 commits behind head on chore_release-8.4.0.

Additional details and impacted files

Impacted file tree graph

@@                 Coverage Diff                  @@
##           chore_release-8.4.0   #17919   +/-   ##
====================================================
  Coverage                25.82%   25.82%           
====================================================
  Files                     3005     3005           
  Lines                   227433   227433           
  Branches                 18912    18912           
====================================================
  Hits                     58724    58724           
  Misses                  168696   168696           
  Partials                    13       13           
Flag Coverage Δ
protocol-designer 18.75% <ø> (ø)
step-generation 4.34% <ø> (ø)

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.

@ddcc4
Copy link
Copy Markdown
Contributor

ddcc4 commented Mar 28, 2025

since previously those protocols would neither analyze nor run.

Small nitpick: Until recently, protocols that were missing the prepare_to_aspirate() would analyze successfully (but fail when run), since analysis did not track whether the pipette was ready to aspirate.

state_update = StateUpdate()
if params.failIfNotPreparedToAspirate:
raise PipetteNotReadyToAspirateError(
"Pipette cannot air gap in place because of a previous blow out."
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you also update this error message to make it easier for users to figure out what's wrong? The problem we ran into last time was due to a push out, not a blow out.

Otherwise this could actually cause a spurious dispense.
@sfoster1 sfoster1 force-pushed the exec-1391-prepare-before-air-gap branch from fc36f94 to ace126d Compare March 28, 2025 21:01
Copy link
Copy Markdown
Contributor

@SyntaxColoring SyntaxColoring left a comment

Choose a reason for hiding this comment

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

💨
↔️

target = loc.labware.as_well().top(height)
self.move_to(target, publish=False)
if self.api_version >= _AIR_GAP_TRACKING_ADDED_IN:
self._core.prepare_to_aspirate()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

_AIR_GAP_TRACKING_ADDED_IN is 2.22 but we're about to release 2.23. Does this not need another api_version gate, or is it harmless enough that we're not worrying about it?

@sfoster1 sfoster1 merged commit 016faab into chore_release-8.4.0 Mar 31, 2025
24 checks passed
@sfoster1 sfoster1 deleted the exec-1391-prepare-before-air-gap branch March 31, 2025 13:49
ddcc4 added a commit that referenced this pull request May 12, 2025
…#18314)

# Overview

After the recent PAPI changes to support `air_gap()` in-place, we can
now generate Python for the `airGapInPlace` CommandCreator.

This in turn completes the support for the `airGapInTrash` and
`airGapInWasteChute` compound commands.

Note that in the `airGapInTrash` and `airGapInWasteChute`
CommandCreators, we suppress the Python for `prepareToAspirate`, because
the Python `air_gap()` command automatically issues
`prepare_to_aspirate()` (PR #17919).

## Test Plan and Hands on Testing

Added unit tests.

I also tried PD Python export for a protocol that used air gaps, and
confirmed that it passed analysis.

## Risk assessment

Low.
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.

3 participants