Initial commit
This commit is contained in:
567
skills/opentrons-integration/SKILL.md
Normal file
567
skills/opentrons-integration/SKILL.md
Normal file
@@ -0,0 +1,567 @@
|
||||
---
|
||||
name: opentrons-integration
|
||||
description: "Lab automation platform for Flex/OT-2 robots. Write Protocol API v2 protocols, liquid handling, hardware modules (heater-shaker, thermocycler), labware management, for automated pipetting workflows."
|
||||
---
|
||||
|
||||
# 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:
|
||||
|
||||
```python
|
||||
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):**
|
||||
|
||||
```python
|
||||
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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
# Check if simulating
|
||||
if protocol.is_simulating():
|
||||
protocol.comment('Running in simulation mode')
|
||||
else:
|
||||
protocol.comment('Running on actual robot')
|
||||
```
|
||||
|
||||
**Rail Lights (Flex only):**
|
||||
|
||||
```python
|
||||
# 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:
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
|
||||
```python
|
||||
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:**
|
||||
|
||||
```python
|
||||
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:**
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
1. **Always specify API level**: Use the latest stable API version in metadata
|
||||
2. **Use meaningful labels**: Label labware for easier identification in logs
|
||||
3. **Check tip availability**: Ensure sufficient tips for protocol completion
|
||||
4. **Add comments**: Use `protocol.comment()` for debugging and logging
|
||||
5. **Simulate first**: Always test protocols in simulation before running on robot
|
||||
6. **Handle errors gracefully**: Add pauses for manual intervention when needed
|
||||
7. **Consider timing**: Use delays when protocols require incubation periods
|
||||
8. **Track liquids**: Use liquid tracking for better setup validation
|
||||
9. **Optimize tip usage**: Use `new_tip='once'` when appropriate to save tips
|
||||
10. **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.
|
||||
366
skills/opentrons-integration/references/api_reference.md
Normal file
366
skills/opentrons-integration/references/api_reference.md
Normal file
@@ -0,0 +1,366 @@
|
||||
# Opentrons Python Protocol API v2 Reference
|
||||
|
||||
## Protocol Context Methods
|
||||
|
||||
### Labware Management
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `load_labware(name, location, label=None, namespace=None, version=None)` | Load labware onto deck | Labware object |
|
||||
| `load_adapter(name, location, namespace=None, version=None)` | Load adapter onto deck | Labware object |
|
||||
| `load_labware_from_definition(definition, location, label=None)` | Load custom labware from JSON | Labware object |
|
||||
| `load_labware_on_adapter(name, adapter, label=None)` | Load labware on adapter | Labware object |
|
||||
| `load_labware_by_name(name, location, label=None, namespace=None, version=None)` | Alternative load method | Labware object |
|
||||
| `load_lid_stack(load_name, location, quantity=None)` | Load lid stack (Flex only) | Labware object |
|
||||
|
||||
### Instrument Management
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `load_instrument(instrument_name, mount, tip_racks=None, replace=False)` | Load pipette | InstrumentContext |
|
||||
|
||||
### Module Management
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `load_module(module_name, location=None, configuration=None)` | Load hardware module | ModuleContext |
|
||||
|
||||
### Liquid Management
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `define_liquid(name, description=None, display_color=None)` | Define liquid type | Liquid object |
|
||||
|
||||
### Execution Control
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `pause(msg=None)` | Pause protocol execution | None |
|
||||
| `resume()` | Resume after pause | None |
|
||||
| `delay(seconds=0, minutes=0, msg=None)` | Delay execution | None |
|
||||
| `comment(msg)` | Add comment to protocol log | None |
|
||||
| `home()` | Home all axes | None |
|
||||
| `set_rail_lights(on)` | Control rail lights (Flex only) | None |
|
||||
|
||||
### Protocol Properties
|
||||
|
||||
| Property | Description | Type |
|
||||
|----------|-------------|------|
|
||||
| `deck` | Deck layout | Deck object |
|
||||
| `fixed_trash` | Fixed trash location (OT-2) | TrashBin object |
|
||||
| `loaded_labwares` | Dictionary of loaded labware | Dict |
|
||||
| `loaded_instruments` | Dictionary of loaded instruments | Dict |
|
||||
| `loaded_modules` | Dictionary of loaded modules | Dict |
|
||||
| `is_simulating()` | Check if protocol is simulating | Bool |
|
||||
| `bundled_data` | Access to bundled data files | Dict |
|
||||
| `params` | Runtime parameters | ParametersContext |
|
||||
|
||||
## Instrument Context (Pipette) Methods
|
||||
|
||||
### Tip Management
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `pick_up_tip(location=None, presses=None, increment=None)` | Pick up tip | InstrumentContext |
|
||||
| `drop_tip(location=None, home_after=True)` | Drop tip in trash | InstrumentContext |
|
||||
| `return_tip(home_after=True)` | Return tip to rack | InstrumentContext |
|
||||
| `reset_tipracks()` | Reset tip tracking | None |
|
||||
|
||||
### Liquid Handling - Basic
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `aspirate(volume=None, location=None, rate=1.0)` | Aspirate liquid | InstrumentContext |
|
||||
| `dispense(volume=None, location=None, rate=1.0, push_out=None)` | Dispense liquid | InstrumentContext |
|
||||
| `blow_out(location=None)` | Expel remaining liquid | InstrumentContext |
|
||||
| `touch_tip(location=None, radius=1.0, v_offset=-1.0, speed=60.0)` | Remove droplets from tip | InstrumentContext |
|
||||
| `mix(repetitions=1, volume=None, location=None, rate=1.0)` | Mix liquid | InstrumentContext |
|
||||
| `air_gap(volume=None, height=None)` | Create air gap | InstrumentContext |
|
||||
|
||||
### Liquid Handling - Complex
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `transfer(volume, source, dest, **kwargs)` | Transfer liquid | InstrumentContext |
|
||||
| `distribute(volume, source, dest, **kwargs)` | Distribute from one to many | InstrumentContext |
|
||||
| `consolidate(volume, source, dest, **kwargs)` | Consolidate from many to one | InstrumentContext |
|
||||
|
||||
**transfer(), distribute(), consolidate() kwargs:**
|
||||
- `new_tip`: 'always', 'once', or 'never'
|
||||
- `trash`: True/False - trash tips after use
|
||||
- `touch_tip`: True/False - touch tip after aspirate/dispense
|
||||
- `blow_out`: True/False - blow out after dispense
|
||||
- `mix_before`: (repetitions, volume) tuple
|
||||
- `mix_after`: (repetitions, volume) tuple
|
||||
- `disposal_volume`: Extra volume for contamination prevention
|
||||
- `carryover`: True/False - enable multi-transfer for large volumes
|
||||
- `gradient`: (start_concentration, end_concentration) for gradients
|
||||
|
||||
### Movement and Positioning
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `move_to(location, force_direct=False, minimum_z_height=None, speed=None)` | Move to location | InstrumentContext |
|
||||
| `home()` | Home pipette axes | None |
|
||||
|
||||
### Pipette Properties
|
||||
|
||||
| Property | Description | Type |
|
||||
|----------|-------------|------|
|
||||
| `default_speed` | Default movement speed | Float |
|
||||
| `min_volume` | Minimum pipette volume | Float |
|
||||
| `max_volume` | Maximum pipette volume | Float |
|
||||
| `current_volume` | Current volume in tip | Float |
|
||||
| `has_tip` | Check if tip is attached | Bool |
|
||||
| `name` | Pipette name | String |
|
||||
| `model` | Pipette model | String |
|
||||
| `mount` | Mount location | String |
|
||||
| `channels` | Number of channels | Int |
|
||||
| `tip_racks` | Associated tip racks | List |
|
||||
| `trash_container` | Trash location | TrashBin object |
|
||||
| `starting_tip` | Starting tip for protocol | Well object |
|
||||
| `flow_rate` | Flow rate settings | FlowRates object |
|
||||
|
||||
### Flow Rate Properties
|
||||
|
||||
Access via `pipette.flow_rate`:
|
||||
|
||||
| Property | Description | Units |
|
||||
|----------|-------------|-------|
|
||||
| `aspirate` | Aspirate flow rate | µL/s |
|
||||
| `dispense` | Dispense flow rate | µL/s |
|
||||
| `blow_out` | Blow out flow rate | µL/s |
|
||||
|
||||
## Labware Methods
|
||||
|
||||
### Well Access
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `wells()` | Get all wells | List[Well] |
|
||||
| `wells_by_name()` | Get wells dictionary | Dict[str, Well] |
|
||||
| `rows()` | Get wells by row | List[List[Well]] |
|
||||
| `columns()` | Get wells by column | List[List[Well]] |
|
||||
| `rows_by_name()` | Get rows dictionary | Dict[str, List[Well]] |
|
||||
| `columns_by_name()` | Get columns dictionary | Dict[str, List[Well]] |
|
||||
|
||||
### Labware Properties
|
||||
|
||||
| Property | Description | Type |
|
||||
|----------|-------------|------|
|
||||
| `name` | Labware name | String |
|
||||
| `parent` | Parent location | Location object |
|
||||
| `quirks` | Labware quirks list | List |
|
||||
| `magdeck_engage_height` | Magnetic module height | Float |
|
||||
| `uri` | Labware URI | String |
|
||||
| `calibrated_offset` | Calibration offset | Point |
|
||||
|
||||
## Well Methods and Properties
|
||||
|
||||
### Liquid Operations
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `load_liquid(liquid, volume)` | Load liquid into well | None |
|
||||
| `load_empty()` | Mark well as empty | None |
|
||||
| `from_center_cartesian(x, y, z)` | Get location from center | Location |
|
||||
|
||||
### Location Methods
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `top(z=0)` | Get location at top of well | Location |
|
||||
| `bottom(z=0)` | Get location at bottom of well | Location |
|
||||
| `center()` | Get location at center of well | Location |
|
||||
|
||||
### Well Properties
|
||||
|
||||
| Property | Description | Type |
|
||||
|----------|-------------|------|
|
||||
| `diameter` | Well diameter (circular) | Float |
|
||||
| `length` | Well length (rectangular) | Float |
|
||||
| `width` | Well width (rectangular) | Float |
|
||||
| `depth` | Well depth | Float |
|
||||
| `max_volume` | Maximum volume | Float |
|
||||
| `display_name` | Display name | String |
|
||||
| `has_tip` | Check if tip present | Bool |
|
||||
|
||||
## Module Contexts
|
||||
|
||||
### Temperature Module
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `set_temperature(celsius)` | Set target temperature | None |
|
||||
| `await_temperature(celsius)` | Wait for temperature | None |
|
||||
| `deactivate()` | Turn off temperature control | None |
|
||||
| `load_labware(name, label=None, namespace=None, version=None)` | Load labware on module | Labware |
|
||||
|
||||
**Properties:**
|
||||
- `temperature`: Current temperature (°C)
|
||||
- `target`: Target temperature (°C)
|
||||
- `status`: 'idle', 'holding', 'cooling', or 'heating'
|
||||
- `labware`: Loaded labware
|
||||
|
||||
### Magnetic Module
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `engage(height_from_base=None, offset=None, height=None)` | Engage magnets | None |
|
||||
| `disengage()` | Disengage magnets | None |
|
||||
| `load_labware(name, label=None, namespace=None, version=None)` | Load labware on module | Labware |
|
||||
|
||||
**Properties:**
|
||||
- `status`: 'engaged' or 'disengaged'
|
||||
- `labware`: Loaded labware
|
||||
|
||||
### Heater-Shaker Module
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `set_target_temperature(celsius)` | Set heater target | None |
|
||||
| `wait_for_temperature()` | Wait for temperature | None |
|
||||
| `set_and_wait_for_temperature(celsius)` | Set and wait | None |
|
||||
| `deactivate_heater()` | Turn off heater | None |
|
||||
| `set_and_wait_for_shake_speed(rpm)` | Set shake speed | None |
|
||||
| `deactivate_shaker()` | Turn off shaker | None |
|
||||
| `open_labware_latch()` | Open latch | None |
|
||||
| `close_labware_latch()` | Close latch | None |
|
||||
| `load_labware(name, label=None, namespace=None, version=None)` | Load labware on module | Labware |
|
||||
|
||||
**Properties:**
|
||||
- `temperature`: Current temperature (°C)
|
||||
- `target_temperature`: Target temperature (°C)
|
||||
- `current_speed`: Current shake speed (rpm)
|
||||
- `target_speed`: Target shake speed (rpm)
|
||||
- `labware_latch_status`: 'idle_open', 'idle_closed', 'opening', 'closing'
|
||||
- `status`: Module status
|
||||
- `labware`: Loaded labware
|
||||
|
||||
### Thermocycler Module
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `open_lid()` | Open lid | None |
|
||||
| `close_lid()` | Close lid | None |
|
||||
| `set_lid_temperature(celsius)` | Set lid temperature | None |
|
||||
| `deactivate_lid()` | Turn off lid heater | None |
|
||||
| `set_block_temperature(temperature, hold_time_seconds=0, hold_time_minutes=0, ramp_rate=None, block_max_volume=None)` | Set block temperature | None |
|
||||
| `deactivate_block()` | Turn off block | None |
|
||||
| `execute_profile(steps, repetitions, block_max_volume=None)` | Run temperature profile | None |
|
||||
| `load_labware(name, label=None, namespace=None, version=None)` | Load labware on module | Labware |
|
||||
|
||||
**Profile step format:**
|
||||
```python
|
||||
{'temperature': 95, 'hold_time_seconds': 30, 'hold_time_minutes': 0}
|
||||
```
|
||||
|
||||
**Properties:**
|
||||
- `block_temperature`: Current block temperature (°C)
|
||||
- `block_target_temperature`: Target block temperature (°C)
|
||||
- `lid_temperature`: Current lid temperature (°C)
|
||||
- `lid_target_temperature`: Target lid temperature (°C)
|
||||
- `lid_position`: 'open', 'closed', 'in_between'
|
||||
- `ramp_rate`: Block temperature ramp rate (°C/s)
|
||||
- `status`: Module status
|
||||
- `labware`: Loaded labware
|
||||
|
||||
### Absorbance Plate Reader Module
|
||||
|
||||
| Method | Description | Returns |
|
||||
|--------|-------------|---------|
|
||||
| `initialize(mode, wavelengths)` | Initialize reader | None |
|
||||
| `read(export_filename=None)` | Read plate | Dict |
|
||||
| `close_lid()` | Close lid | None |
|
||||
| `open_lid()` | Open lid | None |
|
||||
| `load_labware(name, label=None, namespace=None, version=None)` | Load labware on module | Labware |
|
||||
|
||||
**Read modes:**
|
||||
- `'single'`: Single wavelength
|
||||
- `'multi'`: Multiple wavelengths
|
||||
|
||||
**Properties:**
|
||||
- `is_lid_on`: Lid status
|
||||
- `labware`: Loaded labware
|
||||
|
||||
## Common Labware API Names
|
||||
|
||||
### Plates
|
||||
|
||||
- `corning_96_wellplate_360ul_flat`
|
||||
- `nest_96_wellplate_100ul_pcr_full_skirt`
|
||||
- `nest_96_wellplate_200ul_flat`
|
||||
- `biorad_96_wellplate_200ul_pcr`
|
||||
- `appliedbiosystems_384_wellplate_40ul`
|
||||
|
||||
### Reservoirs
|
||||
|
||||
- `nest_12_reservoir_15ml`
|
||||
- `nest_1_reservoir_195ml`
|
||||
- `usascientific_12_reservoir_22ml`
|
||||
|
||||
### Tip Racks
|
||||
|
||||
**Flex:**
|
||||
- `opentrons_flex_96_tiprack_50ul`
|
||||
- `opentrons_flex_96_tiprack_200ul`
|
||||
- `opentrons_flex_96_tiprack_1000ul`
|
||||
|
||||
**OT-2:**
|
||||
- `opentrons_96_tiprack_20ul`
|
||||
- `opentrons_96_tiprack_300ul`
|
||||
- `opentrons_96_tiprack_1000ul`
|
||||
|
||||
### Tube Racks
|
||||
|
||||
- `opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical`
|
||||
- `opentrons_24_tuberack_nest_1.5ml_snapcap`
|
||||
- `opentrons_24_tuberack_nest_1.5ml_screwcap`
|
||||
- `opentrons_15_tuberack_falcon_15ml_conical`
|
||||
|
||||
### Adapters
|
||||
|
||||
- `opentrons_flex_96_tiprack_adapter`
|
||||
- `opentrons_96_deep_well_adapter`
|
||||
- `opentrons_aluminum_flat_bottom_plate`
|
||||
|
||||
## Error Handling
|
||||
|
||||
Common exceptions:
|
||||
|
||||
- `OutOfTipsError`: No tips available
|
||||
- `LabwareNotLoadedError`: Labware not loaded on deck
|
||||
- `InvalidContainerError`: Invalid labware specification
|
||||
- `InstrumentNotLoadedError`: Pipette not loaded
|
||||
- `InvalidVolumeError`: Volume out of range
|
||||
|
||||
## Simulation and Debugging
|
||||
|
||||
Check simulation status:
|
||||
```python
|
||||
if protocol.is_simulating():
|
||||
protocol.comment('Running in simulation')
|
||||
```
|
||||
|
||||
Access bundled data files:
|
||||
```python
|
||||
data_file = protocol.bundled_data['data.csv']
|
||||
with open(data_file) as f:
|
||||
data = f.read()
|
||||
```
|
||||
|
||||
## Version Compatibility
|
||||
|
||||
API Level compatibility:
|
||||
|
||||
| API Level | Features |
|
||||
|-----------|----------|
|
||||
| 2.19 | Latest features, Flex support |
|
||||
| 2.18 | Absorbance plate reader |
|
||||
| 2.17 | Liquid tracking improvements |
|
||||
| 2.16 | Flex 8-channel partial tip pickup |
|
||||
| 2.15 | Heater-Shaker Gen1 |
|
||||
| 2.13 | Temperature Module Gen2 |
|
||||
| 2.0-2.12 | Core OT-2 functionality |
|
||||
|
||||
Always use the latest stable API version for new protocols.
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Basic Opentrons Protocol Template
|
||||
|
||||
This template provides a minimal starting point for creating Opentrons protocols.
|
||||
Replace the placeholder values and add your specific protocol logic.
|
||||
"""
|
||||
|
||||
from opentrons import protocol_api
|
||||
|
||||
# Metadata
|
||||
metadata = {
|
||||
'protocolName': 'Basic Protocol Template',
|
||||
'author': 'Your Name <email@example.com>',
|
||||
'description': 'A basic protocol template for Opentrons',
|
||||
'apiLevel': '2.19'
|
||||
}
|
||||
|
||||
# Requirements
|
||||
requirements = {
|
||||
'robotType': 'Flex', # or 'OT-2'
|
||||
'apiLevel': '2.19'
|
||||
}
|
||||
|
||||
def run(protocol: protocol_api.ProtocolContext):
|
||||
"""
|
||||
Main protocol function.
|
||||
|
||||
Args:
|
||||
protocol: The protocol context provided by Opentrons
|
||||
"""
|
||||
|
||||
# Load tip racks
|
||||
tips_200 = protocol.load_labware('opentrons_flex_96_tiprack_200ul', 'D1')
|
||||
|
||||
# Load labware
|
||||
source_plate = protocol.load_labware(
|
||||
'nest_96_wellplate_200ul_flat',
|
||||
'D2',
|
||||
label='Source Plate'
|
||||
)
|
||||
|
||||
dest_plate = protocol.load_labware(
|
||||
'nest_96_wellplate_200ul_flat',
|
||||
'D3',
|
||||
label='Destination Plate'
|
||||
)
|
||||
|
||||
# Load pipette
|
||||
pipette = protocol.load_instrument(
|
||||
'p300_single_flex',
|
||||
'left',
|
||||
tip_racks=[tips_200]
|
||||
)
|
||||
|
||||
# Protocol commands
|
||||
protocol.comment('Starting protocol...')
|
||||
|
||||
# Example: Transfer from A1 to B1
|
||||
pipette.transfer(
|
||||
volume=50,
|
||||
source=source_plate['A1'],
|
||||
dest=dest_plate['B1'],
|
||||
new_tip='always'
|
||||
)
|
||||
|
||||
protocol.comment('Protocol complete!')
|
||||
154
skills/opentrons-integration/scripts/pcr_setup_template.py
Normal file
154
skills/opentrons-integration/scripts/pcr_setup_template.py
Normal file
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
PCR Setup Protocol Template
|
||||
|
||||
This template demonstrates how to set up PCR reactions using the Thermocycler module.
|
||||
Includes master mix distribution, sample addition, and PCR cycling.
|
||||
"""
|
||||
|
||||
from opentrons import protocol_api
|
||||
|
||||
metadata = {
|
||||
'protocolName': 'PCR Setup with Thermocycler',
|
||||
'author': 'Opentrons',
|
||||
'description': 'Automated PCR setup and cycling protocol',
|
||||
'apiLevel': '2.19'
|
||||
}
|
||||
|
||||
requirements = {
|
||||
'robotType': 'Flex',
|
||||
'apiLevel': '2.19'
|
||||
}
|
||||
|
||||
def run(protocol: protocol_api.ProtocolContext):
|
||||
"""
|
||||
Sets up PCR reactions and runs thermocycler.
|
||||
|
||||
Protocol performs:
|
||||
1. Distributes master mix to PCR plate
|
||||
2. Adds DNA samples
|
||||
3. Runs PCR cycling program
|
||||
"""
|
||||
|
||||
# Load thermocycler module
|
||||
tc_mod = protocol.load_module('thermocyclerModuleV2')
|
||||
tc_plate = tc_mod.load_labware('nest_96_wellplate_100ul_pcr_full_skirt')
|
||||
|
||||
# Load tips and reagents
|
||||
tips_20 = protocol.load_labware('opentrons_flex_96_tiprack_50ul', 'C1')
|
||||
tips_200 = protocol.load_labware('opentrons_flex_96_tiprack_200ul', 'C2')
|
||||
reagent_rack = protocol.load_labware(
|
||||
'opentrons_24_tuberack_nest_1.5ml_snapcap',
|
||||
'D1',
|
||||
label='Reagents'
|
||||
)
|
||||
|
||||
# Load pipettes
|
||||
p20 = protocol.load_instrument('p50_single_flex', 'left', tip_racks=[tips_20])
|
||||
p300 = protocol.load_instrument('p300_single_flex', 'right', tip_racks=[tips_200])
|
||||
|
||||
# Define liquids
|
||||
master_mix = protocol.define_liquid(
|
||||
name='PCR Master Mix',
|
||||
description='2x PCR master mix',
|
||||
display_color='#FFB6C1'
|
||||
)
|
||||
|
||||
template_dna = protocol.define_liquid(
|
||||
name='Template DNA',
|
||||
description='DNA samples',
|
||||
display_color='#90EE90'
|
||||
)
|
||||
|
||||
# Load liquids
|
||||
reagent_rack['A1'].load_liquid(liquid=master_mix, volume=1000)
|
||||
for i in range(8): # 8 samples
|
||||
reagent_rack.wells()[i + 1].load_liquid(liquid=template_dna, volume=50)
|
||||
|
||||
# PCR setup parameters
|
||||
num_samples = 8
|
||||
master_mix_volume = 20 # µL per reaction
|
||||
template_volume = 5 # µL per reaction
|
||||
total_reaction_volume = 25 # µL
|
||||
|
||||
protocol.comment('Starting PCR setup...')
|
||||
|
||||
# Open thermocycler lid
|
||||
tc_mod.open_lid()
|
||||
protocol.comment('Thermocycler lid opened')
|
||||
|
||||
# Step 1: Distribute master mix
|
||||
protocol.comment(f'Distributing {master_mix_volume}µL master mix to {num_samples} wells...')
|
||||
p300.distribute(
|
||||
master_mix_volume,
|
||||
reagent_rack['A1'],
|
||||
tc_plate.wells()[:num_samples],
|
||||
new_tip='once',
|
||||
disposal_volume=10 # Extra volume to prevent shortage
|
||||
)
|
||||
|
||||
# Step 2: Add template DNA
|
||||
protocol.comment('Adding template DNA to each well...')
|
||||
for i in range(num_samples):
|
||||
p20.transfer(
|
||||
template_volume,
|
||||
reagent_rack.wells()[i + 1], # Sample tubes
|
||||
tc_plate.wells()[i], # PCR plate wells
|
||||
mix_after=(3, 10), # Mix 3x with 10µL
|
||||
new_tip='always'
|
||||
)
|
||||
|
||||
protocol.comment('PCR reactions prepared')
|
||||
|
||||
# Close lid and start PCR
|
||||
tc_mod.close_lid()
|
||||
protocol.comment('Thermocycler lid closed')
|
||||
|
||||
# Set lid temperature
|
||||
tc_mod.set_lid_temperature(celsius=105)
|
||||
protocol.comment('Lid heating to 105°C')
|
||||
|
||||
# Initial denaturation
|
||||
protocol.comment('Initial denaturation...')
|
||||
tc_mod.set_block_temperature(
|
||||
temperature=95,
|
||||
hold_time_seconds=180,
|
||||
block_max_volume=total_reaction_volume
|
||||
)
|
||||
|
||||
# PCR cycling profile
|
||||
protocol.comment('Starting PCR cycling...')
|
||||
profile = [
|
||||
{'temperature': 95, 'hold_time_seconds': 15}, # Denaturation
|
||||
{'temperature': 60, 'hold_time_seconds': 30}, # Annealing
|
||||
{'temperature': 72, 'hold_time_seconds': 30} # Extension
|
||||
]
|
||||
|
||||
num_cycles = 35
|
||||
tc_mod.execute_profile(
|
||||
steps=profile,
|
||||
repetitions=num_cycles,
|
||||
block_max_volume=total_reaction_volume
|
||||
)
|
||||
|
||||
# Final extension
|
||||
protocol.comment('Final extension...')
|
||||
tc_mod.set_block_temperature(
|
||||
temperature=72,
|
||||
hold_time_minutes=5,
|
||||
block_max_volume=total_reaction_volume
|
||||
)
|
||||
|
||||
# Hold at 4°C
|
||||
protocol.comment('Cooling to 4°C for storage...')
|
||||
tc_mod.set_block_temperature(
|
||||
temperature=4,
|
||||
block_max_volume=total_reaction_volume
|
||||
)
|
||||
|
||||
# Deactivate and open
|
||||
tc_mod.deactivate_lid()
|
||||
tc_mod.open_lid()
|
||||
|
||||
protocol.comment('PCR complete! Plate ready for removal.')
|
||||
protocol.comment(f'Completed {num_cycles} cycles for {num_samples} samples')
|
||||
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Serial Dilution Protocol Template
|
||||
|
||||
This template demonstrates how to perform a serial dilution across a plate row.
|
||||
Useful for creating concentration gradients for assays.
|
||||
"""
|
||||
|
||||
from opentrons import protocol_api
|
||||
|
||||
metadata = {
|
||||
'protocolName': 'Serial Dilution Template',
|
||||
'author': 'Opentrons',
|
||||
'description': 'Serial dilution protocol for creating concentration gradients',
|
||||
'apiLevel': '2.19'
|
||||
}
|
||||
|
||||
requirements = {
|
||||
'robotType': 'Flex',
|
||||
'apiLevel': '2.19'
|
||||
}
|
||||
|
||||
def run(protocol: protocol_api.ProtocolContext):
|
||||
"""
|
||||
Performs a serial dilution across plate rows.
|
||||
|
||||
Protocol performs:
|
||||
1. Adds diluent to all wells except the first column
|
||||
2. Transfers stock solution to first column
|
||||
3. Performs serial dilutions across rows
|
||||
"""
|
||||
|
||||
# Load labware
|
||||
tips = protocol.load_labware('opentrons_flex_96_tiprack_200ul', 'D1')
|
||||
reservoir = protocol.load_labware('nest_12_reservoir_15ml', 'D2', label='Reservoir')
|
||||
plate = protocol.load_labware('corning_96_wellplate_360ul_flat', 'D3', label='Dilution Plate')
|
||||
|
||||
# Load pipette
|
||||
p300 = protocol.load_instrument('p300_single_flex', 'left', tip_racks=[tips])
|
||||
|
||||
# Define liquids (optional, for visualization)
|
||||
diluent = protocol.define_liquid(
|
||||
name='Diluent',
|
||||
description='Buffer or growth media',
|
||||
display_color='#B0E0E6'
|
||||
)
|
||||
|
||||
stock = protocol.define_liquid(
|
||||
name='Stock Solution',
|
||||
description='Concentrated stock',
|
||||
display_color='#FF6347'
|
||||
)
|
||||
|
||||
# Load liquids into wells
|
||||
reservoir['A1'].load_liquid(liquid=diluent, volume=15000)
|
||||
reservoir['A2'].load_liquid(liquid=stock, volume=5000)
|
||||
|
||||
# Protocol parameters
|
||||
dilution_factor = 2 # 1:2 dilution
|
||||
transfer_volume = 100 # µL
|
||||
num_dilutions = 11 # Number of dilution steps
|
||||
|
||||
protocol.comment('Starting serial dilution protocol')
|
||||
|
||||
# Step 1: Add diluent to all wells except first column
|
||||
protocol.comment('Adding diluent to wells...')
|
||||
for row in plate.rows()[:8]: # For each row (A-H)
|
||||
p300.transfer(
|
||||
transfer_volume,
|
||||
reservoir['A1'], # Diluent source
|
||||
row[1:], # All wells except first (columns 2-12)
|
||||
new_tip='once'
|
||||
)
|
||||
|
||||
# Step 2: Add stock solution to first column
|
||||
protocol.comment('Adding stock solution to first column...')
|
||||
p300.transfer(
|
||||
transfer_volume * 2, # Double volume for first well
|
||||
reservoir['A2'], # Stock source
|
||||
[row[0] for row in plate.rows()[:8]], # First column (wells A1-H1)
|
||||
new_tip='always'
|
||||
)
|
||||
|
||||
# Step 3: Perform serial dilution
|
||||
protocol.comment('Performing serial dilutions...')
|
||||
for row in plate.rows()[:8]: # For each row
|
||||
p300.transfer(
|
||||
transfer_volume,
|
||||
row[:num_dilutions], # Source wells (1-11)
|
||||
row[1:num_dilutions + 1], # Destination wells (2-12)
|
||||
mix_after=(3, 50), # Mix 3x with 50µL after each transfer
|
||||
new_tip='always'
|
||||
)
|
||||
|
||||
protocol.comment('Serial dilution complete!')
|
||||
protocol.comment(f'Created {num_dilutions} dilutions with {dilution_factor}x dilution factor')
|
||||
Reference in New Issue
Block a user