opentrons-integration

用于 OT-2 和 Flex 机器人的官方 Opentrons 协议 API。在编写专门针对 Opentrons 硬件的协议时使用,并可完全访问 Protocol API v2 的功能。最适合用于生产级的 Opentrons 协议,提供官方 API 兼容性。若进行多供应商自动化或更广泛的设备控制,请使用 pylabrobot。

安装

热度:0

下载并解压到你的 skills 目录

复制命令,发送给智能体自动安装:

下载并安装这个技能 https://openskills.cc/api/download?slug=k-dense-ai-skills-opentrons-integration&locale=zh&source=copy
name:opentrons-integrationdescription:Official Opentrons Protocol API for OT-2 and Flex robots. Use when writing protocols specifically for Opentrons hardware with full access to Protocol API v2 features. Best for production Opentrons protocols, official API compatibility. For multi-vendor automation or broader equipment control use pylabrobot.license:Unknownmetadata:[object Object]

Opentrons Integration

Overview

Opentrons is a Python-based lab automation platform for Flex and OT-2 robots. Write Protocol API v2 protocols for liquid handling, control hardware modules (heater-shaker, thermocycler), manage labware, for automated pipetting workflows.

When to Use This Skill

This skill should be used when:

  • Writing Opentrons Protocol API v2 protocols in Python

  • Automating liquid handling workflows on Flex or OT-2 robots

  • Controlling hardware modules (temperature, magnetic, heater-shaker, thermocycler)

  • Setting up labware configurations and deck layouts

  • Implementing complex pipetting operations (serial dilutions, plate replication, PCR setup)

  • Managing tip usage and optimizing protocol efficiency

  • Working with multi-channel pipettes for 96-well plate operations

  • Simulating and testing protocols before robot execution
  • Core Capabilities

    1. Protocol Structure and Metadata

    Every Opentrons protocol follows a standard structure:

    from opentrons import protocol_api
    
    # Metadata
    metadata = {
        'protocolName': 'My Protocol',
        'author': 'Name <email@example.com>',
        'description': 'Protocol description',
        'apiLevel': '2.19'  # Use latest available API version
    }
    
    # Requirements (optional)
    requirements = {
        'robotType': 'Flex',  # or 'OT-2'
        'apiLevel': '2.19'
    }
    
    # Run function
    def run(protocol: protocol_api.ProtocolContext):
        # Protocol commands go here
        pass

    Key elements:

  • Import protocol_api from opentrons

  • Define metadata dict with protocolName, author, description, apiLevel

  • Optional requirements dict for robot type and API version

  • Implement run() function receiving ProtocolContext as parameter

  • All protocol logic goes inside the run() function
  • 2. Loading Hardware

    Loading Instruments (Pipettes):

    def run(protocol: protocol_api.ProtocolContext):
        # Load pipette on specific mount
        left_pipette = protocol.load_instrument(
            'p1000_single_flex',  # Instrument name
            'left',               # Mount: 'left' or 'right'
            tip_racks=[tip_rack]  # List of tip rack labware objects
        )

    Common pipette names:

  • Flex: p50_single_flex, p1000_single_flex, p50_multi_flex, p1000_multi_flex

  • OT-2: p20_single_gen2, p300_single_gen2, p1000_single_gen2, p20_multi_gen2, p300_multi_gen2
  • Loading Labware:

    # Load labware directly on deck
    plate = protocol.load_labware(
        'corning_96_wellplate_360ul_flat',  # Labware API name
        'D1',                                # Deck slot (Flex: A1-D3, OT-2: 1-11)
        label='Sample Plate'                 # Optional display label
    )
    
    # Load tip rack
    tip_rack = protocol.load_labware('opentrons_flex_96_tiprack_1000ul', 'C1')
    
    # Load labware on adapter
    adapter = protocol.load_adapter('opentrons_flex_96_tiprack_adapter', 'B1')
    tips = adapter.load_labware('opentrons_flex_96_tiprack_200ul')

    Loading Modules:

    # Temperature module
    temp_module = protocol.load_module('temperature module gen2', 'D3')
    temp_plate = temp_module.load_labware('corning_96_wellplate_360ul_flat')
    
    # Magnetic module
    mag_module = protocol.load_module('magnetic module gen2', 'C2')
    mag_plate = mag_module.load_labware('nest_96_wellplate_100ul_pcr_full_skirt')
    
    # Heater-Shaker module
    hs_module = protocol.load_module('heaterShakerModuleV1', 'D1')
    hs_plate = hs_module.load_labware('corning_96_wellplate_360ul_flat')
    
    # Thermocycler module (takes up specific slots automatically)
    tc_module = protocol.load_module('thermocyclerModuleV2')
    tc_plate = tc_module.load_labware('nest_96_wellplate_100ul_pcr_full_skirt')

    3. Liquid Handling Operations

    Basic Operations:

    # Pick up tip
    pipette.pick_up_tip()
    
    # Aspirate (draw liquid in)
    pipette.aspirate(
        volume=100,           # Volume in µL
        location=source['A1'] # Well or location object
    )
    
    # Dispense (expel liquid)
    pipette.dispense(
        volume=100,
        location=dest['B1']
    )
    
    # Drop tip
    pipette.drop_tip()
    
    # Return tip to rack
    pipette.return_tip()

    Complex Operations:

    # Transfer (combines pick_up, aspirate, dispense, drop_tip)
    pipette.transfer(
        volume=100,
        source=source_plate['A1'],
        dest=dest_plate['B1'],
        new_tip='always'  # 'always', 'once', or 'never'
    )
    
    # Distribute (one source to multiple destinations)
    pipette.distribute(
        volume=50,
        source=reservoir['A1'],
        dest=[plate['A1'], plate['A2'], plate['A3']],
        new_tip='once'
    )
    
    # Consolidate (multiple sources to one destination)
    pipette.consolidate(
        volume=50,
        source=[plate['A1'], plate['A2'], plate['A3']],
        dest=reservoir['A1'],
        new_tip='once'
    )

    Advanced Techniques:

    # Mix (aspirate and dispense in same location)
    pipette.mix(
        repetitions=3,
        volume=50,
        location=plate['A1']
    )
    
    # Air gap (prevent dripping)
    pipette.aspirate(100, source['A1'])
    pipette.air_gap(20)  # 20µL air gap
    pipette.dispense(120, dest['A1'])
    
    # Blow out (expel remaining liquid)
    pipette.blow_out(location=dest['A1'].top())
    
    # Touch tip (remove droplets on tip exterior)
    pipette.touch_tip(location=plate['A1'])

    Flow Rate Control:

    # Set flow rates (µL/s)
    pipette.flow_rate.aspirate = 150
    pipette.flow_rate.dispense = 300
    pipette.flow_rate.blow_out = 400

    4. Accessing Wells and Locations

    Well Access Methods:

    # By name
    well_a1 = plate['A1']
    
    # By index
    first_well = plate.wells()[0]
    
    # All wells
    all_wells = plate.wells()  # Returns list
    
    # By rows
    rows = plate.rows()  # Returns list of lists
    row_a = plate.rows()[0]  # All wells in row A
    
    # By columns
    columns = plate.columns()  # Returns list of lists
    column_1 = plate.columns()[0]  # All wells in column 1
    
    # Wells by name (dictionary)
    wells_dict = plate.wells_by_name()  # {'A1': Well, 'A2': Well, ...}

    Location Methods:

    # Top of well (default: 1mm below top)
    pipette.aspirate(100, well.top())
    pipette.aspirate(100, well.top(z=5))  # 5mm above top
    
    # Bottom of well (default: 1mm above bottom)
    pipette.aspirate(100, well.bottom())
    pipette.aspirate(100, well.bottom(z=2))  # 2mm above bottom
    
    # Center of well
    pipette.aspirate(100, well.center())

    5. Hardware Module Control

    Temperature Module:

    # Set temperature
    temp_module.set_temperature(celsius=4)
    
    # Wait for temperature
    temp_module.await_temperature(celsius=4)
    
    # Deactivate
    temp_module.deactivate()
    
    # Check status
    current_temp = temp_module.temperature  # Current temperature
    target_temp = temp_module.target  # Target temperature

    Magnetic Module:

    # Engage (raise magnets)
    mag_module.engage(height_from_base=10)  # mm from labware base
    
    # Disengage (lower magnets)
    mag_module.disengage()
    
    # Check status
    is_engaged = mag_module.status  # 'engaged' or 'disengaged'

    Heater-Shaker Module:

    # Set temperature
    hs_module.set_target_temperature(celsius=37)
    
    # Wait for temperature
    hs_module.wait_for_temperature()
    
    # Set shake speed
    hs_module.set_and_wait_for_shake_speed(rpm=500)
    
    # Close labware latch
    hs_module.close_labware_latch()
    
    # Open labware latch
    hs_module.open_labware_latch()
    
    # Deactivate heater
    hs_module.deactivate_heater()
    
    # Deactivate shaker
    hs_module.deactivate_shaker()

    Thermocycler Module:

    # Open lid
    tc_module.open_lid()
    
    # Close lid
    tc_module.close_lid()
    
    # Set lid temperature
    tc_module.set_lid_temperature(celsius=105)
    
    # Set block temperature
    tc_module.set_block_temperature(
        temperature=95,
        hold_time_seconds=30,
        hold_time_minutes=0.5,
        block_max_volume=50  # µL per well
    )
    
    # Execute profile (PCR cycling)
    profile = [
        {'temperature': 95, 'hold_time_seconds': 30},
        {'temperature': 57, 'hold_time_seconds': 30},
        {'temperature': 72, 'hold_time_seconds': 60}
    ]
    tc_module.execute_profile(
        steps=profile,
        repetitions=30,
        block_max_volume=50
    )
    
    # Deactivate
    tc_module.deactivate_lid()
    tc_module.deactivate_block()

    Absorbance Plate Reader:

    # Initialize and read
    result = plate_reader.read(wavelengths=[450, 650])
    
    # Access readings
    absorbance_data = result  # Dict with wavelength keys

    6. Liquid Tracking and Labeling

    Define Liquids:

    # Define liquid types
    water = protocol.define_liquid(
        name='Water',
        description='Ultrapure water',
        display_color='#0000FF'  # Hex color code
    )
    
    sample = protocol.define_liquid(
        name='Sample',
        description='Cell lysate sample',
        display_color='#FF0000'
    )

    Load Liquids into Wells:

    # Load liquid into specific wells
    reservoir['A1'].load_liquid(liquid=water, volume=50000)  # µL
    plate['A1'].load_liquid(liquid=sample, volume=100)
    
    # Mark wells as empty
    plate['B1'].load_empty()

    7. Protocol Control and Utilities

    Execution Control:

    # Pause protocol
    protocol.pause(msg='Replace tip box and resume')
    
    # Delay
    protocol.delay(seconds=60)
    protocol.delay(minutes=5)
    
    # Comment (appears in logs)
    protocol.comment('Starting serial dilution')
    
    # Home robot
    protocol.home()

    Conditional Logic:

    # Check if simulating
    if protocol.is_simulating():
        protocol.comment('Running in simulation mode')
    else:
        protocol.comment('Running on actual robot')

    Rail Lights (Flex only):

    # Turn lights on
    protocol.set_rail_lights(on=True)
    
    # Turn lights off
    protocol.set_rail_lights(on=False)

    8. Multi-Channel and 8-Channel Pipetting

    When using multi-channel pipettes:

    # Load 8-channel pipette
    multi_pipette = protocol.load_instrument(
        'p300_multi_gen2',
        'left',
        tip_racks=[tips]
    )
    
    # Access entire column with single well reference
    multi_pipette.transfer(
        volume=100,
        source=source_plate['A1'],  # Accesses entire column 1
        dest=dest_plate['A1']       # Dispenses to entire column 1
    )
    
    # Use rows() for row-wise operations
    for row in plate.rows():
        multi_pipette.transfer(100, reservoir['A1'], row[0])

    9. Common Protocol Patterns

    Serial Dilution:

    def run(protocol: protocol_api.ProtocolContext):
        # Load labware
        tips = protocol.load_labware('opentrons_flex_96_tiprack_200ul', 'D1')
        reservoir = protocol.load_labware('nest_12_reservoir_15ml', 'D2')
        plate = protocol.load_labware('corning_96_wellplate_360ul_flat', 'D3')
    
        # Load pipette
        p300 = protocol.load_instrument('p300_single_flex', 'left', tip_racks=[tips])
    
        # Add diluent to all wells except first
        p300.transfer(100, reservoir['A1'], plate.rows()[0][1:])
    
        # Serial dilution across row
        p300.transfer(
            100,
            plate.rows()[0][:11],  # Source: wells 0-10
            plate.rows()[0][1:],   # Dest: wells 1-11
            mix_after=(3, 50),     # Mix 3x with 50µL after dispense
            new_tip='always'
        )

    Plate Replication:

    def run(protocol: protocol_api.ProtocolContext):
        # Load labware
        tips = protocol.load_labware('opentrons_flex_96_tiprack_1000ul', 'C1')
        source = protocol.load_labware('corning_96_wellplate_360ul_flat', 'D1')
        dest = protocol.load_labware('corning_96_wellplate_360ul_flat', 'D2')
    
        # Load pipette
        p1000 = protocol.load_instrument('p1000_single_flex', 'left', tip_racks=[tips])
    
        # Transfer from all wells in source to dest
        p1000.transfer(
            100,
            source.wells(),
            dest.wells(),
            new_tip='always'
        )

    PCR Setup:

    def run(protocol: protocol_api.ProtocolContext):
        # Load thermocycler
        tc_mod = protocol.load_module('thermocyclerModuleV2')
        tc_plate = tc_mod.load_labware('nest_96_wellplate_100ul_pcr_full_skirt')
    
        # Load tips and reagents
        tips = protocol.load_labware('opentrons_flex_96_tiprack_200ul', 'C1')
        reagents = protocol.load_labware('opentrons_24_tuberack_nest_1.5ml_snapcap', 'D1')
    
        # Load pipette
        p300 = protocol.load_instrument('p300_single_flex', 'left', tip_racks=[tips])
    
        # Open thermocycler lid
        tc_mod.open_lid()
    
        # Distribute master mix
        p300.distribute(
            20,
            reagents['A1'],
            tc_plate.wells(),
            new_tip='once'
        )
    
        # Add samples (example for first 8 wells)
        for i, well in enumerate(tc_plate.wells()[:8]):
            p300.transfer(5, reagents.wells()[i+1], well, new_tip='always')
    
        # Run PCR
        tc_mod.close_lid()
        tc_mod.set_lid_temperature(105)
    
        # PCR profile
        tc_mod.set_block_temperature(95, hold_time_seconds=180)
    
        profile = [
            {'temperature': 95, 'hold_time_seconds': 15},
            {'temperature': 60, 'hold_time_seconds': 30},
            {'temperature': 72, 'hold_time_seconds': 30}
        ]
        tc_mod.execute_profile(steps=profile, repetitions=35, block_max_volume=25)
    
        tc_mod.set_block_temperature(72, hold_time_minutes=5)
        tc_mod.set_block_temperature(4)
    
        tc_mod.deactivate_lid()
        tc_mod.open_lid()

    Best Practices

  • Always specify API level: Use the latest stable API version in metadata

  • Use meaningful labels: Label labware for easier identification in logs

  • Check tip availability: Ensure sufficient tips for protocol completion

  • Add comments: Use protocol.comment() for debugging and logging

  • Simulate first: Always test protocols in simulation before running on robot

  • Handle errors gracefully: Add pauses for manual intervention when needed

  • Consider timing: Use delays when protocols require incubation periods

  • Track liquids: Use liquid tracking for better setup validation

  • Optimize tip usage: Use new_tip='once' when appropriate to save tips

  • Control flow rates: Adjust flow rates for viscous or volatile liquids
  • Troubleshooting

    Common Issues:

  • Out of tips: Verify tip rack capacity matches protocol requirements

  • Labware collisions: Check deck layout for spatial conflicts

  • Volume errors: Ensure volumes don't exceed well or pipette capacities

  • Module not responding: Verify module is properly connected and firmware is updated

  • Inaccurate volumes: Calibrate pipettes and check for air bubbles

  • Protocol fails in simulation: Check API version compatibility and labware definitions
  • Resources

    For detailed API documentation, see references/api_reference.md in this skill directory.

    For example protocol templates, see scripts/ directory.