Opentrons Magnetic Block
Overview
The Opentrons Magnetic Block is an unpowered, 96-well magnetic separator exclusively for Opentrons Flex. It uses high-strength neodymium magnets to pull magnetic beads to the side of wells, enabling supernatant removal for DNA/RNA purification, protein cleanup, immunoprecipitation, and other bead-based separation protocols.
Core value: Automate magnetic bead-based purification workflows without manual plate transfers. Combine gripper-based plate movement with magnetic separation for fully automated DNA extraction, PCR cleanup, and bead-based assays.
Platform: Opentrons Flex only (not compatible with OT-2)
When to Use
Use the Magnetic Block skill when:
- •Performing DNA/RNA extraction with magnetic beads
- •PCR product cleanup (AMPure, SPRIselect beads)
- •Magnetic bead-based library preparation (NGS)
- •Protein purification or immunoprecipitation with magnetic beads
- •Cell sorting or enrichment with magnetic particles
- •Any protocol requiring magnetic bead separation
Don't use when:
- •Working with OT-2 robot (Magnetic Block is Flex-only)
- •Need vertical bead movement within solution (block only pulls to side)
- •Require heated magnetic separation
- •Working without Opentrons Flex gripper
Quick Reference
| Operation | Method | Key Parameters |
|---|---|---|
| Load module | protocol.load_module() | "magneticBlockV1", location |
| Move plate to block | protocol.move_labware() | labware, mag_block, use_gripper=True |
| Wait for separation | protocol.delay() | minutes (typically 2-5) |
| Pipette supernatant | pipette.transfer() | source, dest |
| Move plate off block | protocol.move_labware() | labware, new_location, use_gripper=True |
Platform Requirements
Opentrons Flex only
- •API version: 2.15 or later (Magnetic Block introduced)
- •Gripper required: All plate movement uses gripper
- •Robot type: Must specify
"robotType": "Flex"
Key Characteristics
Unpowered Design
Important: The Magnetic Block is completely unpowered:
- •No electronic control
- •No on/off switching
- •Always magnetic when plate is present
- •Robot and Opentrons App are not aware of magnetic state
Implication: All control is manual through:
- •Physical plate positioning (gripper movement)
- •Timed delays for bead separation
- •Pipetting operations
Loading the Module
from opentrons import protocol_api
metadata = {'apiLevel': '2.19'}
requirements = {"robotType": "Flex", "apiLevel": "2.19"}
def run(protocol: protocol_api.ProtocolContext):
# Load Magnetic Block
mag_block = protocol.load_module(
module_name="magneticBlockV1",
location="D1"
)
# Load compatible labware
mag_plate = mag_block.load_labware(
name="biorad_96_wellplate_200ul_pcr"
)
Compatible deck slots: Any Flex slot (A1-D3) Recommended: D1, D2, or D3 (bottom row for workflow efficiency)
Compatible Labware
The Magnetic Block works with 96-well plates that fit the magnetic footprint:
Common compatible labware:
- •
biorad_96_wellplate_200ul_pcr - •
nest_96_wellplate_100ul_pcr_full_skirt - •
opentrons_96_wellplate_200ul_pcr_full_skirt - •Other 96-well PCR plates with standard footprint
Important:
- •Labware must be grippable (compatible with Flex gripper)
- •Wells must align with magnet positions
- •Standard 96-well footprint required
Basic Magnetic Separation Workflow
Step 1: Load Sample Plate
# Start with sample plate on deck (not on magnetic block yet)
sample_plate = protocol.load_labware("biorad_96_wellplate_200ul_pcr", "C1")
# Add magnetic beads and binding buffer
pipette.transfer(10, bead_stock, sample_plate.wells())
pipette.transfer(100, binding_buffer, sample_plate.wells(), mix_after=(5, 80))
Step 2: Incubate for Binding
# Incubate to allow beads to bind target (DNA/RNA/protein) protocol.delay(minutes=5) # Optional: Mix during incubation (use Heater-Shaker)
Step 3: Move to Magnetic Block
# Move plate to magnetic block using gripper
protocol.move_labware(
labware=sample_plate,
new_location=mag_block,
use_gripper=True
)
Step 4: Wait for Bead Separation
# Allow beads to collect at side of wells protocol.delay(minutes=3) # Beads are now held at well edges by magnets
Step 5: Remove Supernatant
# Pipette supernatant while beads are held by magnets
pipette.transfer(
volume=110,
source=sample_plate.wells(),
dest=waste.wells(),
new_tip="always"
)
# Beads remain in wells, held by magnetic field
Step 6: Move Off Magnetic Block
# Move plate off magnets for bead resuspension
protocol.move_labware(
labware=sample_plate,
new_location="C2",
use_gripper=True
)
# Beads are now free to resuspend
Step 7: Wash and Repeat
# Add wash buffer pipette.transfer(150, wash_buffer, sample_plate.wells()) # Mix to resuspend beads pipette.mix(repetitions=5, volume=100, location=sample_plate.wells()) # Return to magnetic block protocol.move_labware(sample_plate, mag_block, use_gripper=True) # Wait for separation protocol.delay(minutes=2) # Remove supernatant pipette.transfer(150, sample_plate.wells(), waste.wells(), new_tip="always")
Step 8: Elute
# Move off magnets protocol.move_labware(sample_plate, "C2", use_gripper=True) # Add elution buffer pipette.transfer(50, elution_buffer, sample_plate.wells(), mix_after=(5, 30)) # Incubate protocol.delay(minutes=2) # Final magnetic separation protocol.move_labware(sample_plate, mag_block, use_gripper=True) protocol.delay(minutes=2) # Transfer eluate (purified product) pipette.transfer(45, sample_plate.wells(), elution_plate.wells(), new_tip="always")
Complete DNA Extraction Protocol
# Complete automated DNA extraction workflow
def run(protocol: protocol_api.ProtocolContext):
# Modules and labware
mag_block = protocol.load_module("magneticBlockV1", "D1")
sample_plate = mag_block.load_labware("biorad_96_wellplate_200ul_pcr")
# Additional labware
tips = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "A1")
waste = protocol.load_trash_bin("A3")
reagents = protocol.load_labware("nest_12_reservoir_15ml", "C2")
# Pipette
pipette = protocol.load_instrument("flex_8channel_1000", "left", tip_racks=[tips])
# Reagent locations
lysis_beads = reagents["A1"]
wash_buffer = reagents["A2"]
elution_buffer = reagents["A3"]
# Samples already in plate (loaded manually or via earlier steps)
# 1. Add lysis beads and bind DNA
pipette.transfer(100, lysis_beads, sample_plate.columns()[0], mix_after=(5, 80))
protocol.delay(minutes=5)
# 2. Magnetic separation - remove lysate
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(200, sample_plate.columns()[0], waste, new_tip="always")
# 3. First wash
protocol.move_labware(sample_plate, "C1", use_gripper=True)
pipette.transfer(150, wash_buffer, sample_plate.columns()[0], mix_after=(5, 100))
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(150, sample_plate.columns()[0], waste, new_tip="always")
# 4. Second wash
protocol.move_labware(sample_plate, "C1", use_gripper=True)
pipette.transfer(150, wash_buffer, sample_plate.columns()[0], mix_after=(5, 100))
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(150, sample_plate.columns()[0], waste, new_tip="always")
# 5. Dry beads
protocol.delay(minutes=5)
# 6. Elute DNA
protocol.move_labware(sample_plate, "C1", use_gripper=True)
pipette.transfer(50, elution_buffer, sample_plate.columns()[0], mix_after=(5, 30))
protocol.delay(minutes=2)
# 7. Final magnetic separation
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
# 8. Collect purified DNA
elution_plate = protocol.load_labware("biorad_96_wellplate_200ul_pcr", "C3")
pipette.transfer(45, sample_plate.columns()[0], elution_plate.columns()[0], new_tip="always")
Common Patterns
PCR Cleanup (AMPure Beads)
# Clean PCR product with AMPure beads
mag_block = protocol.load_module("magneticBlockV1", "D1")
pcr_plate = protocol.load_labware("biorad_96_wellplate_200ul_pcr", "C1")
# 1. Add beads (0.8x ratio for >300bp fragments)
pipette.transfer(40, ampure_beads, pcr_plate.wells(), mix_after=(5, 35))
protocol.delay(minutes=5)
# 2. Magnetic separation
protocol.move_labware(pcr_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(90, pcr_plate.wells(), waste.wells())
# 3. Ethanol washes (2x)
for _ in range(2):
pipette.transfer(150, ethanol_70, pcr_plate.wells())
protocol.delay(seconds=30)
pipette.transfer(150, pcr_plate.wells(), waste.wells())
# 4. Dry
protocol.delay(minutes=5)
# 5. Elute
protocol.move_labware(pcr_plate, "C2", use_gripper=True)
pipette.transfer(30, water, pcr_plate.wells(), mix_after=(5, 20))
protocol.delay(minutes=2)
# 6. Final separation and collection
protocol.move_labware(pcr_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(25, pcr_plate.wells(), clean_plate.wells())
NGS Library Preparation
# Magnetic bead-based library prep
mag_block = protocol.load_module("magneticBlockV1", "D2")
lib_plate = mag_block.load_labware("biorad_96_wellplate_200ul_pcr")
# After adapter ligation...
# 1. Add SPRI beads for size selection (0.6x for >400bp)
pipette.transfer(30, spri_beads, lib_plate.wells(), mix_after=(5, 25))
protocol.delay(minutes=5)
# 2. Bind large fragments
protocol.move_labware(lib_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
# 3. SAVE supernatant (contains fragments to remove)
protocol.move_labware(lib_plate, "C1", use_gripper=True)
# 4. Add more beads to supernatant (bring to 1.0x total)
pipette.transfer(20, spri_beads, lib_plate.wells(), mix_after=(5, 30))
protocol.delay(minutes=5)
# 5. Bind desired fragments
protocol.move_labware(lib_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
# 6. Discard supernatant
pipette.transfer(100, lib_plate.wells(), waste.wells())
# 7. Wash and elute (standard protocol)
Protein Immunoprecipitation
# Magnetic bead IP
mag_block = protocol.load_module("magneticBlockV1", "D1")
ip_plate = mag_block.load_labware("biorad_96_wellplate_200ul_pcr")
# 1. Pre-coupled antibody-bead complex in wells
# 2. Add lysate
pipette.transfer(100, lysate_plate.wells(), ip_plate.wells(), mix_after=(3, 80))
# 3. Incubate (binding)
protocol.delay(minutes=30)
# 4. Wash unbound protein
for wash_num in range(3):
protocol.move_labware(ip_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(150, ip_plate.wells(), waste.wells())
protocol.move_labware(ip_plate, "C1", use_gripper=True)
pipette.transfer(150, wash_buffer, ip_plate.wells(), mix_after=(3, 100))
# 5. Elute bound protein
protocol.move_labware(ip_plate, "C1", use_gripper=True)
pipette.transfer(50, elution_buffer, ip_plate.wells(), mix_after=(5, 30))
protocol.delay(minutes=5)
# 6. Collect eluate
protocol.move_labware(ip_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(45, ip_plate.wells(), analysis_plate.wells())
Integration with Other Modules
With Heater-Shaker (Heated Lysis)
# Combine heating with magnetic purification
hs_mod = protocol.load_module("heaterShakerModuleV1", "D1")
mag_block = protocol.load_module("magneticBlockV1", "D2")
sample_plate = protocol.load_labware("biorad_96_wellplate_200ul_pcr", "C1")
# 1. Heat lysis on heater-shaker
hs_mod.open_labware_latch()
protocol.move_labware(sample_plate, hs_mod, use_gripper=True)
hs_mod.close_labware_latch()
hs_mod.set_and_wait_for_temperature(56)
hs_mod.set_and_wait_for_shake_speed(1000)
protocol.delay(minutes=15)
hs_mod.deactivate_shaker()
hs_mod.deactivate_heater()
hs_mod.open_labware_latch()
# 2. Magnetic bead binding
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
# ... continue with washes and elution ...
With Temperature Module (Cold Elution)
# Cold elution for stability
temp_mod = protocol.load_module("temperature module gen2", "D3")
mag_block = protocol.load_module("magneticBlockV1", "D2")
# Pre-cool elution buffer
temp_mod.set_temperature(4)
# After magnetic washes...
protocol.move_labware(sample_plate, "C1", use_gripper=True)
# Add cold elution buffer
pipette.transfer(50, cold_elution, sample_plate.wells(), mix_after=(5, 30))
# Move to cold module for elution
protocol.move_labware(sample_plate, temp_mod, use_gripper=True)
protocol.delay(minutes=5)
# Final separation
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(45, sample_plate.wells(), storage_plate.wells())
temp_mod.deactivate()
With Thermocycler (Post-PCR Cleanup)
# PCR → Cleanup workflow
tc_mod = protocol.load_module("thermocyclerModuleV2")
mag_block = protocol.load_module("magneticBlockV1", "D2")
# Run PCR
tc_mod.close_lid()
# ... PCR cycling ...
tc_mod.set_block_temperature(4)
tc_mod.open_lid()
# Move to deck for bead addition
pcr_plate = tc_mod.labware
protocol.move_labware(pcr_plate, "C1", use_gripper=True)
# Add AMPure beads
pipette.transfer(40, ampure_beads, pcr_plate.wells(), mix_after=(5, 35))
protocol.delay(minutes=5)
# Cleanup on magnetic block
protocol.move_labware(pcr_plate, mag_block, use_gripper=True)
# ... cleanup steps ...
Best Practices
- •Allow sufficient separation time - Typically 2-5 minutes depending on bead type
- •Use gripper for all plate movements - Manual movement defeats automation purpose
- •Avoid disturbing beads when pipetting - Aspirate from opposite side of well
- •Mix thoroughly after moving off magnets - Ensure complete bead resuspension
- •Track bead volume in calculations - Account for beads when calculating total volume
- •Use consistent bead types - Different beads have different separation times
- •Plan deck layout - Position magnetic block near other modules for efficiency
- •Test separation time - Optimize delay for your specific beads and sample type
- •Don't over-dry beads - Can reduce elution efficiency
- •Validate elution volume - Leave some headroom to avoid transferring beads
Separation Time Guidelines
Typical separation times by bead type:
- •AMPure/SPRIselect (DNA): 2-3 minutes
- •RNAClean (RNA): 3-4 minutes
- •Protein G/A beads: 2-3 minutes
- •High-density beads: 1-2 minutes
- •Large volume samples: 4-5 minutes
Factors affecting separation:
- •Bead concentration
- •Sample volume
- •Viscosity
- •Magnetic bead strength
- •Well geometry
Recommendation: Start with 3 minutes, adjust based on visual inspection or protocol optimization.
Common Mistakes
❌ Moving plate without gripper:
# Manual movement not practical in automated protocol protocol.move_labware(sample_plate, mag_block, use_gripper=False) # User must manually move plate - defeats automation
✅ Correct:
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
❌ Insufficient separation time:
protocol.move_labware(sample_plate, mag_block, use_gripper=True) protocol.delay(seconds=30) # Too short - beads still in solution pipette.transfer(100, sample_plate.wells(), waste.wells()) # Transfers beads!
✅ Correct:
protocol.move_labware(sample_plate, mag_block, use_gripper=True) protocol.delay(minutes=3) # Adequate time for separation pipette.transfer(100, sample_plate.wells(), waste.wells())
❌ Pipetting through bead pellet:
# Aspirating from center may disturb beads on side pipette.aspirate(100, sample_plate.wells()[0])
✅ Correct:
# Aspirate from side opposite beads pipette.aspirate(100, sample_plate.wells()[0].bottom(z=2)) # Or use touch_tip to ensure beads aren't transferred
❌ Incomplete bead resuspension:
protocol.move_labware(sample_plate, "C1", use_gripper=True) pipette.transfer(150, wash_buffer, sample_plate.wells()) # Beads may not resuspend
✅ Correct:
protocol.move_labware(sample_plate, "C1", use_gripper=True) pipette.transfer(150, wash_buffer, sample_plate.wells(), mix_after=(5, 100)) # Mix to resuspend
❌ Using incompatible labware:
# Deep well plates may not align with magnets properly
mag_plate = mag_block.load_labware("nest_96_wellplate_2ml_deep")
✅ Correct:
# Use standard 96-well PCR plates
mag_plate = mag_block.load_labware("biorad_96_wellplate_200ul_pcr")
Troubleshooting
Beads not separating:
- •Increase separation time (try 4-5 minutes)
- •Check bead type and concentration
- •Verify plate is properly seated on magnetic block
- •Ensure labware is compatible with magnet positions
Beads being transferred with supernatant:
- •Extend separation time
- •Pipette more carefully (avoid bead pellet)
- •Reduce aspiration flow rate
- •Leave more residual volume
Incomplete elution:
- •Ensure beads are fully resuspended before elution incubation
- •Mix more vigorously
- •Extend elution incubation time
- •Verify beads haven't dried excessively
- •Use appropriate elution buffer volume
Bead clumping:
- •Mix more thoroughly when resuspending
- •Ensure beads are well-mixed before adding to samples
- •Avoid drying beads too long
- •Check bead storage conditions
Variable recovery across wells:
- •Ensure consistent bead addition volumes
- •Mix uniformly across all wells
- •Use consistent separation times
- •Check for plate positioning issues on magnetic block
Advanced Techniques
Dual-Size Selection
# Select DNA fragments within specific size range # First selection: Remove large fragments pipette.transfer(30, spri_beads, lib_plate.wells(), mix_after=(5, 25)) # 0.6x protocol.delay(minutes=5) protocol.move_labware(lib_plate, mag_block, use_gripper=True) protocol.delay(minutes=3) # Collect supernatant (has small + target fragments) protocol.move_labware(lib_plate, "C1", use_gripper=True) pipette.transfer(80, lib_plate.wells(), temp_plate.wells()) # Second selection: Bind target fragments pipette.transfer(20, spri_beads, temp_plate.wells(), mix_after=(5, 30)) # Brings to 1.0x protocol.delay(minutes=5) protocol.move_labware(temp_plate, mag_block, use_gripper=True) protocol.delay(minutes=3) # Discard supernatant (small fragments removed) pipette.transfer(100, temp_plate.wells(), waste.wells()) # Wash and elute target size range
Differential Elution
# Elute different targets sequentially # After binding multiple targets to beads... # First elution (low stringency) pipette.transfer(50, elution_buffer_1, sample_plate.wells(), mix_after=(5, 30)) protocol.delay(minutes=2) protocol.move_labware(sample_plate, mag_block, use_gripper=True) protocol.delay(minutes=2) pipette.transfer(45, sample_plate.wells(), fraction_1_plate.wells()) # Second elution (high stringency) protocol.move_labware(sample_plate, "C1", use_gripper=True) pipette.transfer(50, elution_buffer_2, sample_plate.wells(), mix_after=(5, 30)) protocol.delay(minutes=2) protocol.move_labware(sample_plate, mag_block, use_gripper=True) protocol.delay(minutes=2) pipette.transfer(45, sample_plate.wells(), fraction_2_plate.wells())
No Electronic Control
Remember: The Magnetic Block has no electronic interface.
This means:
- •❌ Cannot turn magnets on/off programmatically
- •❌ No status reporting to robot
- •❌ No automatic timing
- •✅ Full control through plate positioning
- •✅ Predictable, passive magnetic field
- •✅ No calibration or initialization required
Control strategy: Move plate TO block = magnets engaged, move plate OFF block = magnets disengaged
API Version Requirements
- •Minimum API version: 2.15 (Magnetic Block introduced)
- •Recommended: 2.19+ for full Flex feature support
- •Robot type: Must be Opentrons Flex
Additional Resources
- •Magnetic Block Documentation: https://docs.opentrons.com/v2/modules/magnetic_block.html
- •Gripper Documentation: https://docs.opentrons.com/v2/new_protocol_api.html#opentrons.protocol_api.ProtocolContext.move_labware
- •Protocol Library: https://protocols.opentrons.com/
- •Opentrons Support: https://support.opentrons.com/
Related Skills
- •
opentrons- Main Opentrons Python API skill - •
opentrons-gripper- Automated labware movement (required) - •
opentrons-heater-shaker- Heated incubation with mixing - •
opentrons-temperature-module- Temperature control - •
opentrons-thermocycler- PCR for molecular workflows