Week 3: Lab Automation

Week 3 cover Week 3 cover

Context
This page recasts my Week 3 assignment (Lab Automation) for Hugo. Instructions reflect the original course guidance for this week. :contentReference[oaicite:0]{index=0}


Recitation


Homework

Warning

Deadlines & readiness
Submit your code before your lab time; then sign up for a robot time slot. If you hit scripting snags, reach out early—don’t wait until lab. :contentReference[oaicite:3]{index=3}

What to do

  1. Pre-lab — Review the week’s materials and workflow. :contentReference[oaicite:4]{index=4}
  2. Create your protocol — Write and test a Python routine in a Google Colab notebook. :contentReference[oaicite:5]{index=5}
  3. Submit your completed protocol to your TA, and make sure you’ve booked a robot slot. :contentReference[oaicite:6]{index=6}
  4. Book & file your submission using the links below.

About the automation task

You’ll use an Opentrons OT-2–style Python protocol to automate mixing/dispensing steps and generate outputs you’ll report (see Deliverables). If you’re new to the platform, these references help:

  • Opentrons docs hub (Protocol Designer + Python API). :contentReference[oaicite:10]{index=10}
  • Protocol examples (API v2) for Flex/OT-2. :contentReference[oaicite:11]{index=11}
  • Liquid handling commands (aspirate/dispense, mix, distribute). :contentReference[oaicite:12]{index=12}
  • Google Colab (run and share notebooks). :contentReference[oaicite:13]{index=13}

Deliverables

Please include (or be prepared to report) the following with your submission:

  • A shareable link to your Colab notebook cell that holds the metadata + code (ensure “Anyone with the link” is a Viewer). :contentReference[oaicite:14]{index=14}
  • Simulation-derived totals:
    • Number of tips used by your protocol.
    • Volumes (µL) used per color channel: Red, Yellow, Green, Cyan, Blue. :contentReference[oaicite:15]{index=15}
  • A short notes/reflection on any issues and fixes.

Post-lab questions (mandatory)

Use a few sentences/bullets for each:

  1. What did automation let you do more precisely or reproducibly than manual pipetting?
  2. Where did your protocol struggle (e.g., timing, tip use, residuals), and how would you improve it?
  3. If you repeated this on the robot with new constraints (less time, fewer tips), what would you optimize first?
  4. How might this automation approach accelerate your final project work? :contentReference[oaicite:16]{index=16}

Tips

  • Keep commands simple and log outputs you’ll need for reporting (tip counts, per-color volumes).
  • Prefer distribute/transfer helpers when appropriate; fall back to explicit aspirate/dispense for tricky steps. :contentReference[oaicite:17]{index=17}
  • Test logic in Colab, then export the cell link for submission. :contentReference[oaicite:18]{index=18}

Pages in this week

  • Week 3: Protocol Skeleton (Colab/OT-2)

    Prelude to this lab What this is A minimal, well-commented Opentrons Python API v2 protocol that mixes five dye “channels” (Red/Yellow/Green/Cyan/Blue) and logs the total consumables.

Subsections of Week 3: Lab Automation

Week 3: Protocol Skeleton (Colab/OT-2)

Prelude to this lab

What this is
A minimal, well-commented Opentrons Python API v2 protocol that mixes five dye “channels” (Red/Yellow/Green/Cyan/Blue) and logs the total consumables.

It will report: tips used and µL per color. It uses OT-2 GEN2 p300, 300 µL tips, a 96-well Corning 360 µL flat plate, and an Eppendorf 1.5 mL 24-tube rack. The log messages appear via protocol.comment().


Opentrons protocol (copy into a single Colab cell or .py)

# metadata / requirements — declare API level (>=2.15 recommended)
# You can put apiLevel here or in `metadata["apiLevel"]`.
requirements = {"apiLevel": "2.15"}  # see docs on versioning
metadata = {
    "protocolName": "HTGAA W3 — Gel Art Mix (5 colors) — Skeleton",
    "author": "Alireza Hekmati",
    "description": "Distribute 5 color channels to a 96-well plate; log tip count and per-color volumes."
}

from opentrons import protocol_api

def run(protocol: protocol_api.ProtocolContext):
    # --- Deck / labware -------------------------------------------------------
    # Tip rack: 300 µL filtered/unfiltered (OT-2 standard)
    tips300 = protocol.load_labware("opentrons_96_tiprack_300ul", "8")
    # Plate: Corning 96-well, 360 µL flat bottom
    plate   = protocol.load_labware("corning_96_wellplate_360ul_flat", "2")
    # Tube rack: Eppendorf 1.5 mL Safe-Lock (24 position)
    tuberack = protocol.load_labware("opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap", "5")

    # Pipette: P300 Single-Channel GEN2 on left
    p300 = protocol.load_instrument("p300_single_gen2", "left", tip_racks=[tips300])

    # --- Parameters you may tweak ---------------------------------------------
    VOLUME_PER_WELL = 30   # µL to dispense per destination well
    N_WELLS_PER_COLOR = 6  # how many wells to fill for each color
    MIX_BEFORE_ASPIRATE = (3, 150)  # (reps, µL) on source tube

    # Map dye sources in tube rack (prepare physical dyes in these tubes)
    # A1..A5 will be the 5 color sources.
    sources = {
        "Red":   tuberack["A1"],
        "Yellow":tuberack["A2"],
        "Green": tuberack["A3"],
        "Cyan":  tuberack["A4"],
        "Blue":  tuberack["A5"],
    }

    # Choose simple destination pattern: first 5 rows (A-E), left to right
    row_index = {"A":0, "B":1, "C":2, "D":3, "E":4}
    dest_rows = {
        "Red":    "A",
        "Yellow": "B",
        "Green":  "C",
        "Cyan":   "D",
        "Blue":   "E",
    }

    # --- Accounting: tip count & per-color volumes ----------------------------
    tips_used = 0
    per_color_uL = {k: 0 for k in sources.keys()}

    # Helper to pick up a tip and track it
    def get_tip():
        nonlocal tips_used
        p300.pick_up_tip()
        tips_used += 1

    # --- Work loop -------------------------------------------------------------
    for color, src in sources.items():
        # Decide the row and the first N destinations in that row
        row = dest_rows[color]
        dests = plate.rows()[row_index[row]][:N_WELLS_PER_COLOR]

        # Mix the source (optional, helps with homogeneity)
        get_tip()
        p300.mix(MIX_BEFORE_ASPIRATE[0], MIX_BEFORE_ASPIRATE[1], src)

        # Use one tip per color; distribute to N wells
        for d in dests:
            p300.aspirate(VOLUME_PER_WELL, src)   # atomic commands: aspirate/dispense
            p300.dispense(VOLUME_PER_WELL, d)
            # (optional) touch_tip to minimize droplets
            # p300.touch_tip(d)

            per_color_uL[color] += VOLUME_PER_WELL

        # Final blowout back into source top to clear residual
        p300.blow_out(src.top())
        p300.drop_tip()

    # --- Log summary to run log -----------------------------------------------
    protocol.comment("=== HTGAA W3 — RUN SUMMARY ===")
    protocol.comment(f"Tips used (P300): {tips_used}")
    for c, uL in per_color_uL.items():
        protocol.comment(f"{c}: {uL} µL total")

    protocol.comment("Per-color wells filled: " + str(N_WELLS_PER_COLOR))
    protocol.comment(f"Volume per well: {VOLUME_PER_WELL} µL")
    protocol.comment("Plate: corning_96_wellplate_360ul_flat | Tips: opentrons_96_tiprack_300ul")