opentrons-integration

Par mkurman · zorai

API Protocole officielle Opentrons pour les robots OT-2 et Flex. À utiliser pour rédiger des protocoles spécifiquement destinés au matériel Opentrons, avec un accès complet aux fonctionnalités de l'API Protocole v2. Idéal pour les protocoles Opentrons en production et la compatibilité avec l'API officielle. Pour l'automatisation multi-fournisseurs ou le contrôle d'équipements plus large, utiliser pylabrobot.

npx skills add https://github.com/mkurman/zorai --skill opentrons-integration

Intégration Opentrons

Aperçu

Opentrons est une plateforme d'automatisation de laboratoire basée sur Python pour les robots Flex et OT-2. Écrivez des protocoles Protocol API v2 pour la manipulation de liquides, contrôlez les modules matériels (heater-shaker, thermocycler), gérez les labwares pour des workflows de pipetage automatisés.

Quand utiliser cette skill

Cette skill doit être utilisée quand :

  • Vous écrivez des protocoles Opentrons Protocol API v2 en Python
  • Vous automatisez des workflows de manipulation de liquides sur les robots Flex ou OT-2
  • Vous contrôlez des modules matériels (température, magnétique, heater-shaker, thermocycler)
  • Vous configurez des configurations de labware et des dispositions de deck
  • Vous implémentez des opérations de pipetage complexes (dilutions en série, réplication de plaques, setup PCR)
  • Vous gérez l'utilisation de pointes et optimisez l'efficacité du protocole
  • Vous travaillez avec des pipettes multi-canaux pour des opérations sur plaques 96 puits
  • Vous simulez et testez les protocoles avant l'exécution sur le robot

Capacités principales

1. Structure du protocole et métadonnées

Chaque protocole Opentrons suit une structure standard :

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

Éléments clés :

  • Importez protocol_api depuis opentrons
  • Définissez le dictionnaire metadata avec protocolName, author, description, apiLevel
  • Dictionnaire requirements optionnel pour le type de robot et la version API
  • Implémentez la fonction run() recevant ProtocolContext comme paramètre
  • Toute la logique du protocole se trouve à l'intérieur de la fonction run()

2. Chargement du matériel

Chargement des 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
    )

Noms courants de pipettes :

  • 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

Chargement de labwares :

# 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')

Chargement des 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. Opérations de manipulation de liquides

Opérations basiques :

# 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()

Opérations complexes :

# 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'
)

Techniques avancées :

# 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'])

Contrôle du débit :

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

4. Accès aux puits et aux emplacements

Méthodes d'accès aux puits :

# 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, ...}

Méthodes d'emplacement :

# 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. Contrôle des modules matériels

Module de température :

# 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

Module magnétique :

# 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'

Module Heater-Shaker :

# 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()

Module Thermocycler :

# 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()

Lecteur de plaque d'absorbance :

# Initialize and read
result = plate_reader.read(wavelengths=[450, 650])

# Access readings
absorbance_data = result  # Dict with wavelength keys

6. Suivi des liquides et étiquetage

Définir les liquides :

# 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'
)

Charger les liquides dans les puits :

# 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. Contrôle du protocole et utilitaires

Contrôle de l'exécution :

# 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()

Logique conditionnelle :

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

Lights des rails (Flex seulement) :

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

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

8. Pipetage multi-canaux et 8 canaux

Lors de l'utilisation de pipettes multi-canaux :

# 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. Motifs courants de protocole

Dilution en série :

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'
    )

Réplication de plaque :

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'
    )

Setup PCR :

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()

Bonnes pratiques

  1. Toujours spécifier le niveau API : Utilisez la dernière version stable d'API dans les métadonnées
  2. Utiliser des étiquettes significatives : Étiquetez les labwares pour une identification plus facile dans les logs
  3. Vérifier la disponibilité des pointes : Assurez-vous d'avoir suffisamment de pointes pour la réalisation du protocole
  4. Ajouter des commentaires : Utilisez protocol.comment() pour le débogage et la journalisation
  5. Simuler en premier : Testez toujours les protocoles en simulation avant de les exécuter sur le robot
  6. Gérer les erreurs avec élégance : Ajoutez des pauses pour l'intervention manuelle si nécessaire
  7. Considérer le timing : Utilisez des délais lorsque les protocoles nécessitent des périodes d'incubation
  8. Suivre les liquides : Utilisez le suivi des liquides pour une meilleure validation de la configuration
  9. Optimiser l'utilisation des pointes : Utilisez new_tip='once' le cas échéant pour économiser les pointes
  10. Contrôler les débits : Ajustez les débits pour les liquides visqueux ou volatiles

Dépannage

Problèmes courants :

  • Manque de pointes : Vérifiez que la capacité du support de pointes correspond aux exigences du protocole
  • Collisions de labware : Vérifiez la disposition du deck pour détecter les conflits spatiaux
  • Erreurs de volume : Assurez-vous que les volumes ne dépassent pas les capacités des puits ou des pipettes
  • Module ne réagissant pas : Vérifiez que le module est correctement connecté et que le firmware est à jour
  • Volumes imprécis : Étalonnez les pipettes et vérifiez les bulles d'air
  • Le protocole échoue en simulation : Vérifiez la compatibilité de la version API et les définitions de labware

Ressources

Pour une documentation API détaillée, consultez references/api_reference.md dans le répertoire de cette skill.

Pour des exemples de modèles de protocoles, consultez le répertoire scripts/.

Skills similaires