Week 3 HW: Lab Automation
Week 3 HW: Lab Automation
🎨 Assignment: Python Script for Opentrons Artwork
Link: https://colab.research.google.com/drive/1Yw0ZrnxIz1kG73b_9PcuZNgXGv6uQy9s?usp=sharing
Click to expand code
mscarlet_i_points = [(-17.6, 17.6),(-15.4, 17.6),(-13.2, 17.6),(-11, 17.6),(-8.8, 17.6),(-6.6, 17.6),(-4.4, 17.6),(-2.2, 17.6),(0, 17.6),(2.2, 17.6),(4.4, 17.6),(6.6, 17.6),(8.8, 17.6),(11, 17.6),(13.2, 17.6),(15.4, 17.6),(17.6, 17.6),(19.8, 17.6),(-17.6, 15.4),(-15.4, 15.4),(-13.2, 15.4),(-11, 15.4),(-8.8, 15.4),(-6.6, 15.4),(-4.4, 15.4),(-2.2, 15.4),(0, 15.4),(2.2, 15.4),(4.4, 15.4),(6.6, 15.4),(8.8, 15.4),(11, 15.4),(13.2, 15.4),(15.4, 15.4),(17.6, 15.4),(19.8, 15.4),(-17.6, 13.2),(-15.4, 13.2),(-13.2, 13.2),(-11, 13.2),(-8.8, 13.2),(-6.6, 13.2),(-4.4, 13.2),(-2.2, 13.2),(0, 13.2),(2.2, 13.2),(4.4, 13.2),(6.6, 13.2),(8.8, 13.2),(11, 13.2),(13.2, 13.2),(15.4, 13.2),(17.6, 13.2),(19.8, 13.2),(-17.6, 11),(-15.4, 11),(-13.2, 11),(-11, 11),(-8.8, 11),(-6.6, 11),(-4.4, 11),(-2.2, 11),(0, 11),(2.2, 11),(4.4, 11),(6.6, 11),(8.8, 11),(11, 11),(13.2, 11),(15.4, 11),(17.6, 11),(19.8, 11),(-17.6, 8.8),(-15.4, 8.8),(-13.2, 8.8),(-11, 8.8),(-6.6, 8.8),(-4.4, 8.8),(-2.2, 8.8),(0, 8.8),(2.2, 8.8),(4.4, 8.8),(6.6, 8.8),(8.8, 8.8),(13.2, 8.8),(15.4, 8.8),(17.6, 8.8),(19.8, 8.8),(-17.6, 6.6),(-15.4, 6.6),(-13.2, 6.6),(-11, 6.6),(-6.6, 6.6),(-4.4, 6.6),(-2.2, 6.6),(0, 6.6),(2.2, 6.6),(4.4, 6.6),(6.6, 6.6),(8.8, 6.6),(13.2, 6.6),(15.4, 6.6),(17.6, 6.6),(19.8, 6.6),(-17.6, 4.4),(-15.4, 4.4),(-13.2, 4.4),(-11, 4.4),(-6.6, 4.4),(-4.4, 4.4),(-2.2, 4.4),(0, 4.4),(2.2, 4.4),(4.4, 4.4),(6.6, 4.4),(8.8, 4.4),(13.2, 4.4),(15.4, 4.4),(17.6, 4.4),(19.8, 4.4),(-17.6, 2.2),(-15.4, 2.2),(-13.2, 2.2),(-11, 2.2),(-8.8, 2.2),(-6.6, 2.2),(-4.4, 2.2),(-2.2, 2.2),(0, 2.2),(2.2, 2.2),(4.4, 2.2),(6.6, 2.2),(8.8, 2.2),(11, 2.2),(13.2, 2.2),(15.4, 2.2),(17.6, 2.2),(19.8, 2.2),(-24.2, 0),(-22, 0),(-19.8, 0),(-17.6, 0),(-15.4, 0),(-13.2, 0),(-11, 0),(-8.8, 0),(-6.6, 0),(-4.4, 0),(-2.2, 0),(0, 0),(2.2, 0),(4.4, 0),(6.6, 0),(8.8, 0),(11, 0),(13.2, 0),(15.4, 0),(17.6, 0),(19.8, 0),(22, 0),(24.2, 0),(26.4, 0),(-24.2, -2.2),(-22, -2.2),(-19.8, -2.2),(-17.6, -2.2),(-15.4, -2.2),(-13.2, -2.2),(-11, -2.2),(-8.8, -2.2),(-6.6, -2.2),(-4.4, -2.2),(-2.2, -2.2),(0, -2.2),(2.2, -2.2),(4.4, -2.2),(6.6, -2.2),(8.8, -2.2),(11, -2.2),(13.2, -2.2),(15.4, -2.2),(17.6, -2.2),(19.8, -2.2),(22, -2.2),(24.2, -2.2),(26.4, -2.2),(-24.2, -4.4),(-22, -4.4),(-19.8, -4.4),(-17.6, -4.4),(-15.4, -4.4),(-13.2, -4.4),(-11, -4.4),(-8.8, -4.4),(-6.6, -4.4),(-4.4, -4.4),(-2.2, -4.4),(0, -4.4),(2.2, -4.4),(4.4, -4.4),(6.6, -4.4),(8.8, -4.4),(11, -4.4),(13.2, -4.4),(15.4, -4.4),(17.6, -4.4),(19.8, -4.4),(22, -4.4),(24.2, -4.4),(26.4, -4.4),(-17.6, -6.6),(-15.4, -6.6),(-13.2, -6.6),(-11, -6.6),(-8.8, -6.6),(-6.6, -6.6),(-4.4, -6.6),(-2.2, -6.6),(0, -6.6),(2.2, -6.6),(4.4, -6.6),(6.6, -6.6),(8.8, -6.6),(11, -6.6),(13.2, -6.6),(15.4, -6.6),(17.6, -6.6),(19.8, -6.6),(-17.6, -8.8),(-15.4, -8.8),(-13.2, -8.8),(-11, -8.8),(-8.8, -8.8),(-6.6, -8.8),(-4.4, -8.8),(-2.2, -8.8),(0, -8.8),(2.2, -8.8),(4.4, -8.8),(6.6, -8.8),(8.8, -8.8),(11, -8.8),(13.2, -8.8),(15.4, -8.8),(17.6, -8.8),(19.8, -8.8),(-17.6, -11),(-15.4, -11),(-13.2, -11),(-11, -11),(-8.8, -11),(-6.6, -11),(-4.4, -11),(-2.2, -11),(0, -11),(2.2, -11),(4.4, -11),(6.6, -11),(8.8, -11),(11, -11),(13.2, -11),(15.4, -11),(17.6, -11),(19.8, -11),(-13.2, -13.2),(-11, -13.2),(-6.6, -13.2),(-4.4, -13.2),(6.6, -13.2),(8.8, -13.2),(13.2, -13.2),(15.4, -13.2),(-13.2, -15.4),(-11, -15.4),(-6.6, -15.4),(-4.4, -15.4),(6.6, -15.4),(8.8, -15.4),(13.2, -15.4),(15.4, -15.4),(-13.2, -17.6),(-11, -17.6),(-6.6, -17.6),(-4.4, -17.6),(6.6, -17.6),(8.8, -17.6),(13.2, -17.6),(15.4, -17.6),(-13.2, -19.8),(-11, -19.8),(-6.6, -19.8),(-4.4, -19.8),(6.6, -19.8),(8.8, -19.8),(13.2, -19.8),(15.4, -19.8)]
mjuniper_points = [(-4.4, 28.6),(-2.2, 28.6),(0, 28.6),(2.2, 28.6),(4.4, 28.6),(-4.4, 26.4),(-2.2, 26.4),(2.2, 26.4),(4.4, 26.4),(-4.4, 24.2),(-2.2, 24.2),(2.2, 24.2),(4.4, 24.2),(-6.6, 22),(-4.4, 22),(-2.2, 22),(2.2, 22),(4.4, 22),(6.6, 22),(-6.6, 19.8),(-4.4, 19.8),(-2.2, 19.8),(0, 19.8),(2.2, 19.8),(4.4, 19.8),(6.6, 19.8)]
mturquoise2_points = [(0, 26.4),(0, 24.2),(0, 22)]
📖 Assigment: Automation paper
“Automated Cell Culture Splitter (ACCS): An open-source benchtop system for cell passaging with integrated cell counting” — PNAS Nexus, December 2025
Citation: Automated Cell Culture Splitter (ACCS), PNAS Nexus, 4(12), pgaf385, 2025. https://academic.oup.com/pnasnexus/article/4/12/pgaf385/8405882
Why this paper: This paper presents an open-source system built around the Opentrons OT-2 that automates the passaging of adherent or suspension cells in 96-well plates. What makes it novel is the integration of a custom Cell Counting Imager (CCI) that adjusts seeding volumes per-well based on measured cell density (the robot doesn’t just pipette blindly, it makes decisions based on real-time data). The system fits inside a biosafety cabinet, processes 2–3 plates per working day with minimal intervention, and communicates status updates via Slack.
Relevance to my final project ideas: All three of my proposed projects involve cell culture steps. Automated cell passaging with integrated counting is exactly the infrastructure needed upstream of any of these experiments. The paper also demonstrates how custom hardware (the CCI) can be integrated with the OT-2’s Python API, which is relevant for designing my own automation protocols that might need plate reader integration for fluorescence readouts.
⚙️ Assignment: How I’ll apply automation in my projects
This is how I’d use automation for my proposed final project #1 (“Idea 1: CRISPR Epigenome Editing at Clock CpG Sites”): Step 1 — Transfection Setup (Opentrons OT-2/Flex) Dispensing cells, transfection reagents (e.g., Lipofectamine or PEI), and different gRNA/construct combinations across a 96-well plate. Each well gets a different gRNA targeting a different CpG site, allowing parallel testing of multiple epigenome editing targets.
Step 2 — Bisulfite Conversion Sample Prep (Opentrons OT-2) After editing, validate whether methylation was actually changed at the target site. This requires bisulfite conversion of genomic DNA — a multi-step protocol (denaturation → bisulfite treatment → desulphonation → cleanup) that is repetitive, error-prone, and ideal for automation. Zymo Research already provides Opentrons-compatible scripts for their EZ DNA Methylation kits.
Step 3 — Targeted PCR Setup (Opentrons OT-2) Set up PCR reactions targeting the specific CpG sites of interest (using bisulfite-specific primers) across the 96-well plate for downstream sequencing.
Pseudocode for Transfection Protocol:
from opentrons import protocol_api
metadata = {
‘protocolName’: ‘dCas9-TET1 Epigenome Editing Transfection Setup’,
‘author’: ‘[Your Name]’,
‘description’: ‘Automated transfection of dCas9-TET1 + gRNAs targeting aging clock CpG sites’
}
requirements = {“robotType”: “OT-2”, “apiLevel”: “2.16”}
def run(protocol: protocol_api.ProtocolContext):
# — LABWARE —
plate = protocol.load_labware(‘corning_96_wellplate_360ul_flat’, ‘1’)
reagent_rack = protocol.load_labware(‘opentrons_24_tuberack_nest_1.5ml’, ‘2’)
tiprack_20 = protocol.load_labware(‘opentrons_96_tiprack_20ul’, ‘3’)
tiprack_300 = protocol.load_labware(‘opentrons_96_tiprack_300ul’, ‘6’)
# --- INSTRUMENTS ---
p20 = protocol.load_instrument('p20_single_gen2', 'left', tip_racks=[tiprack_20])
p300 = protocol.load_instrument('p300_single_gen2', 'right', tip_racks=[tiprack_300])
# --- REAGENTS (in tube rack) ---
# A1: OptiMEM reduced serum media
# A2: Lipofectamine 3000 reagent
# A3: P3000 reagent
# A4: dCas9-TET1 plasmid (shared across all wells)
# B1-B6: gRNAs targeting 6 different aging clock CpG sites
# B1: gRNA for ELOVL2 promoter (cg16867657)
# B2: gRNA for FHL2 promoter (cg22454769)
# B3: gRNA for PENK intron (cg16008966)
# B4: gRNA for KLF14 promoter (cg07553761)
# B5: gRNA for TRIM59 (cg00481951)
# B6: non-targeting control gRNA
# C1: Cell suspension (pre-trypsinized, counted)
optimen = reagent_rack['A1']
lipofectamine = reagent_rack['A2']
p3000 = reagent_rack['A3']
dcas9_tet1 = reagent_rack['A4']
grnas = [reagent_rack[well] for well in ['B1', 'B2', 'B3', 'B4', 'B5', 'B6']]
cells = reagent_rack['C1']
# --- PROTOCOL ---
# Step 1: Seed cells into all wells (200 uL per well, ~40,000 cells)
# Note: In practice, cells would be seeded 24h prior
# This step shows the protocol for Day 0
protocol.comment("Step 1: Seeding cells")
for well in plate.wells()[:48]: # 48 wells = 6 gRNAs x 8 replicates
p300.transfer(200, cells, well, new_tip='always')
# [Protocol would pause here for 24h incubation]
protocol.pause("Incubate plate at 37°C, 5% CO2 for 24 hours. Resume for transfection.")
# Step 2: Prepare transfection complexes
# Each gRNA condition gets 8 replicate wells (columns)
protocol.comment("Step 2: Preparing lipofection complexes")
for grna_idx, grna in enumerate(grnas):
# Target wells: 8 wells per gRNA (one column)
target_wells = plate.columns()[grna_idx][:8]
for well in target_wells:
# Add OptiMEM
p20.transfer(10, optimen, well, new_tip='always')
# Add dCas9-TET1 plasmid (250 ng)
p20.transfer(2, dcas9_tet1, well, new_tip='always')
# Add specific gRNA plasmid (250 ng)
p20.transfer(2, grna, well, new_tip='always')
# Add P3000 reagent
p20.transfer(1, p3000, well, new_tip='always')
# Add Lipofectamine
p20.transfer(1, lipofectamine, well, mix_after=(3, 10), new_tip='always')
protocol.comment("Transfection complete. Incubate 72h before harvesting.")
# After 72h: harvest cells for bisulfite conversion + methylation analysis
Pseudocode for Bisulfite Conversion (Post-editing validation):
def run_bisulfite_conversion(protocol: protocol_api.ProtocolContext):
"""
Automated bisulfite conversion of genomic DNA from transfected cells.
Validates whether dCas9-TET1 successfully demethylated target CpG sites.
Uses Zymo EZ DNA Methylation Kit protocol adapted for OT-2.
"""
# Step 1: Add CT Conversion Reagent to each DNA sample
# 130 uL CT reagent + 20 uL DNA sample per well
for well in sample_plate.wells()[:48]:
p300.transfer(130, ct_reagent, well, mix_after=(5, 100))
# Step 2: Thermal cycling for bisulfite conversion
# Would use Opentrons Thermocycler Module:
# 98°C for 8 min (denaturation)
# 64°C for 3.5 hours (conversion)
# 4°C hold
thermocycler.set_block_temperature(98, hold_time_minutes=8)
thermocycler.set_block_temperature(64, hold_time_minutes=210)
thermocycler.set_block_temperature(4)
# Step 3: Desulphonation + Cleanup
# Transfer to spin columns, wash, elute
# (Magnetic bead-based cleanup would be more OT-2 friendly)
for well in sample_plate.wells()[:48]:
# Add binding buffer
p300.transfer(600, binding_buffer, well, mix_after=(3, 200))
# Transfer to magnetic bead plate
# Wash 2x with wash buffer
# Elute in 10 uL elution buffer
p20.transfer(10, elution_buffer, well, mix_after=(5, 8))
# Step 4: Set up targeted PCR for clock CpG sites
# Bisulfite-specific primers for each target locus
for i, primer_pair in enumerate(bisulfite_primers):
target_wells = pcr_plate.columns()[i][:8]
for well in target_wells:
p20.transfer(10, pcr_master_mix, well)
p20.transfer(2, primer_pair, well)
p20.transfer(8, converted_dna, well, mix_after=(3, 15))
💡 Final project ideas
Added the slides to the slide deck.
3 final project ideas I'd like to pursue
1. Design targeted epigenetic editors to reverse aging methylation signaturesTraining a Minimal Epigenetic Aging Clock and Design of a Fluorescent Age Reporter Construct
- Cross-Intervention Epigenetic Clock Comparison and CRISPR Knock-in Design of a p16 Aging Sensor