HTGAA 2026 - Homework
Week 3 - February 17, 2026

Lab Automation

No lecture this week. Published paper on open-source automation, the Nash Automaton protocol, three project concept slides, and how this thinking evolved into Fuzi Poiesis.

Opentrons OT-2 Nash Automaton Project Genesis Global Student
Context

No Lecture — Lab Week

Opentrons Artwork · Due by Lab Time

Fluorescent Pixel Art — Bacterial Canvas

Using the opentrons-art.rcdonovan.com GUI, a pixel-art design was created by selecting coordinates on an agar plate canvas and assigning fluorescent protein colors to each dot. The resulting coordinate map — organized by fluorescent protein — was exported and used to generate the Opentrons OT-2 Python script below. Each colored point corresponds to a 1 µL dispense of a specific fluorescent protein solution onto the agar surface; the robot pipettes each color in sequence, aspirating from a 96-well PCR strip loaded with the corresponding protein preparations.

Opentrons pixel art design — fluorescent protein layout on agar plate canvas
Automation Art Interface — design preview · 13 fluorescent proteins · mKO2, mRFP1, tdTomato, mTurquoise2, mKate2, eqFP578, PA-GFP, mCherry, EGFP, mAzamiGreen, mVenus, Electra2, mHoneydew
Fluorescent protein palette used

The design uses 13 distinct fluorescent proteins, each dispensed from a separate well of the PCR strip on the aluminium block: mKO2 (orange, 70 points), mTurquoise2 (cyan, 41 points), mRFP1 (red, 36 points), mHoneydew (pale green, 8 points), mAzamiGreen (green, 14 points), mkate2 (far-red, 12 points), tdTomato (orange-red, 19 points), EGFP (green, 10 points), PA-GFP (photoactivatable, 6 points), mCherry (red, 6 points), mVenus (yellow, 2 points), Electra2 (5 points), and eqFP578 (1 point). Each point = 1 µL, dispensed using a P20 single-channel GEN2 pipette with a maximum aspirate volume of 18 µL per tip pickup.

Visual Design — What was drawn

The composition is made up of six simple but visually distinct motifs, each assigned to a different region of the agar plate and rendered in a different fluorescent protein color. The goal was legibility at the scale of a petri dish — bold shapes that read clearly under UV illumination.

Motif 1 · Top-left quadrant
Yeezus — mKO2 orange
A simplified pixel rendering of the cross motif from Kanye West's Yeezus album cover (2013) — a stark red-on-white cross on a black field, here translated into orange mKO2 dots. The largest single motif on the plate (70 points), occupying the upper-left quadrant. Chosen for its graphic boldness and cultural weight.
Motif 2 · Lower-left quadrant
Red cluster — mRFP1
A compact pixel heart or blob shape rendered in deep red mRFP1 (36 points). Placed in the lower-left as a counterweight to the large orange cross above it. The contrast between mKO2 and mRFP1 — both warm-spectrum but spectrally separated — is designed to read clearly under a standard UV/green excitation source.
Motif 3 · Center
Swirl — mTurquoise2 cyan
A radiating swirl or spiral shape in mTurquoise2 (41 points) — the cool-tone anchor of the composition. The spiral form contrasts with the angular geometry of the cross and star, and cyan sits spectrally opposite to the orange/red cluster on the left, creating a natural visual focal point at the center of the plate.
Motif 4 · Upper-center
Star — mAzamiGreen + mVenus
A five- or six-pointed star shape rendered in green mAzamiGreen (14 points) with mVenus yellow (2 points) as accent. Placed near the top-center of the plate. Stars are a canonical pixel-art motif — simple enough to be legible at low resolution, immediately recognizable.
Motif 5 · Center-right
Lightning bolt — tdTomato + mkate2
A diagonal lightning bolt in orange-red tdTomato (19 points) with far-red mKate2 (12 points) shadow. A lightning bolt reads well as a pixel motif because it can be rendered in as few as 5–6 points per "segment." The warm-to-far-red gradient from tdTomato to mKate2 gives it depth under fluorescence imaging.
Motif 6 · Lower-center
Blue cross + heart — mHoneydew + EGFP
A small cross shape in pale mHoneydew green (8 points) and an EGFP green (10 points) heart or compact cluster below it — two small, tight motifs sharing the lower-center zone. These use the shortest-wavelength emission proteins in the palette, creating a cool counterpoint to the warm tdTomato/mKate2 bolt above.
Compositional logic

The six motifs were arranged to distribute spectral emission across the plate spatially — warm tones (orange, red) on the left, cool tones (cyan, green) on the right and center, with the far-red mKate2 and mRFP1 acting as anchors. Under a standard fluorescence imager with sequential excitation channels, each motif would appear in a distinct channel image, and the composite would reconstruct the full composition. The Yeezus cross was chosen as the dominant motif because its pixel form is architecturally simple — a rectangle intersected by a bar — and because its cultural specificity makes the plate immediately readable as an intentional design rather than a random distribution of protein dots.

Python Script — Diseño_Art.py
from opentrons import types
import string

metadata = {
    'protocolName': 'HTGAA Opentrons Art - Week 3',   # ← reemplaza con tu nombre
    'author': 'HTGAA 2026',
    'source': 'HTGAA 2026',
    'apiLevel': '2.20'
}

# ──────────────────────────────────────────────
# Parámetros globales
# ──────────────────────────────────────────────
Z_VALUE_AGAR  = 2.0   # offset z sobre el agar (mm)
POINT_SIZE    = 1     # µL por punto

# ──────────────────────────────────────────────
# Coordenadas de cada proteína fluorescente
# (generadas desde opentrons-art.rcdonovan.com)
# ──────────────────────────────────────────────
mko2_points = [
    (13.2,26.4), (-26.4,24.2), (-24.2,24.2), (-22,24.2), (-19.8,24.2), (-17.6,24.2),
    (13.2,24.2), (-26.4,22), (-24.2,22), (-22,22), (-19.8,22), (13.2,22),
    (-28.6,19.8), (-26.4,19.8), (-24.2,19.8), (-22,19.8), (-19.8,19.8), (-13.2,19.8),
    (11,19.8), (13.2,19.8), (15.4,19.8), (-28.6,17.6), (-26.4,17.6), (-24.2,17.6),
    (-22,17.6), (-19.8,17.6), (-17.6,17.6), (-15.4,17.6), (-13.2,17.6), (-11,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), (22,17.6), (-30.8,15.4), (-28.6,15.4), (-26.4,15.4),
    (-24.2,15.4), (-22,15.4), (-19.8,15.4), (-17.6,15.4), (-15.4,15.4), (-13.2,15.4),
    (-11,15.4), (11,15.4), (15.4,15.4), (-22,13.2), (-19.8,13.2), (-17.6,13.2),
    (-15.4,13.2), (-13.2,13.2), (8.8,13.2), (17.6,13.2), (-22,11), (-19.8,11),
    (-17.6,11), (-15.4,11), (6.6,11), (19.8,11), (-22,8.8), (-19.8,8.8),
    (-17.6,8.8), (-22,6.6), (-19.8,6.6), (-22,4.4)
]
mrfp1_points = [
    (-24.2,-6.6), (-22,-6.6), (-17.6,-6.6), (-15.4,-6.6), (-26.4,-8.8), (-24.2,-8.8),
    (-22,-8.8), (-19.8,-8.8), (-17.6,-8.8), (-15.4,-8.8), (-13.2,-8.8), (-26.4,-11),
    (-24.2,-11), (-22,-11), (-19.8,-11), (-17.6,-11), (-15.4,-11), (-13.2,-11),
    (-24.2,-13.2), (-22,-13.2), (-19.8,-13.2), (-17.6,-13.2), (-15.4,-13.2),
    (-22,-15.4), (-19.8,-15.4), (-17.6,-15.4), (19.8,-15.4), (22,-15.4), (24.2,-15.4),
    (-19.8,-17.6), (19.8,-17.6), (22,-17.6), (24.2,-17.6), (19.8,-19.8),
    (22,-19.8), (24.2,-19.8)
]
tdtomato_points = [
    (11,-6.6), (13.2,-6.6), (15.4,-6.6), (11,-8.8), (15.4,-8.8), (13.2,-11),
    (2.2,-15.4), (4.4,-17.6), (6.6,-17.6), (2.2,-19.8), (4.4,-19.8), (6.6,-19.8),
    (11,-24.2), (13.2,-24.2), (15.4,-24.2), (11,-26.4), (15.4,-26.4),
    (11,-28.6), (13.2,-28.6)
]
mturquoise2_points = [
    (8.8,-6.6), (17.6,-6.6), (6.6,-8.8), (17.6,-8.8), (19.8,-8.8), (4.4,-11),
    (6.6,-11), (8.8,-11), (17.6,-11), (19.8,-11), (22,-11), (2.2,-13.2),
    (4.4,-13.2), (6.6,-13.2), (8.8,-13.2), (11,-13.2), (15.4,-13.2), (17.6,-13.2),
    (19.8,-13.2), (24.2,-13.2), (6.6,-15.4), (8.8,-15.4), (17.6,-15.4),
    (8.8,-19.8), (17.6,-19.8), (2.2,-22), (4.4,-22), (6.6,-22), (8.8,-22),
    (11,-22), (15.4,-22), (17.6,-22), (19.8,-22), (22,-22), (24.2,-22),
    (4.4,-24.2), (8.8,-24.2), (19.8,-24.2), (22,-24.2), (6.6,-26.4), (8.8,-26.4),
    (17.6,-26.4), (19.8,-26.4), (17.6,-28.6)
]
mkate2_points = [
    (13.2,-13.2), (11,-15.4), (13.2,-15.4), (15.4,-15.4), (8.8,-17.6), (11,-17.6),
    (15.4,-17.6), (17.6,-17.6), (11,-19.8), (13.2,-19.8), (15.4,-19.8), (13.2,-22)
]
eqfp578_points   = [(13.2,-17.6)]
pa_gfp_points    = [(8.8,-8.8), (11,-11), (22,-13.2), (6.6,-24.2), (17.6,-24.2), (8.8,-28.6)]
mcherry_points   = [(13.2,-8.8), (15.4,-11), (4.4,-15.4), (2.2,-17.6), (13.2,-26.4), (15.4,-28.6)]
egfp_points      = [(-28.6,24.2), (-28.6,22), (-30.8,17.6), (-24.2,13.2), (-24.2,11),
                    (-24.2,8.8), (-26.4,6.6), (-24.2,6.6), (-24.2,4.4), (-24.2,2.2)]
mazamigreen_points = [
    (-2.2,37.4), (0,37.4), (4.4,37.4), (11,35.2), (13.2,35.2), (-6.6,33), (0,33),
    (17.6,33), (-6.6,30.8), (-2.2,30.8), (2.2,30.8), (-6.6,28.6), (2.2,28.6), (0,26.4)
]
mvenus_points    = [(-4.4,35.2), (-2.2,26.4)]
electra2_points  = [(-2.2,2.2), (-4.4,0), (0,0), (-2.2,-2.2), (-2.2,-4.4)]
mhoneydew_points = [(-2.2,4.4), (-6.6,0), (-2.2,0), (2.2,0), (-4.4,-4.4), (0,-4.4),
                    (-2.2,-6.6), (-2.2,-8.8)]

point_name_pairing = [
    ("mko2",        mko2_points),
    ("mrfp1",       mrfp1_points),
    ("tdtomato",    tdtomato_points),
    ("mturquoise2", mturquoise2_points),
    ("mkate2",      mkate2_points),
    ("eqfp578",     eqfp578_points),
    ("pa_gfp",      pa_gfp_points),
    ("mcherry",     mcherry_points),
    ("egfp",        egfp_points),
    ("mazamigreen", mazamigreen_points),
    ("mvenus",      mvenus_points),
    ("electra2",    electra2_points),
    ("mhoneydew",   mhoneydew_points),
]

# ──────────────────────────────────────────────
# Deck setup
# ──────────────────────────────────────────────
TIP_RACK_DECK_SLOT       = 9
COLORS_DECK_SLOT         = 6
AGAR_DECK_SLOT           = 5
PIPETTE_STARTING_TIP_WELL = 'A1'

# Mapa pozo → color (placa PCR strip 96-well)
well_colors = {
    'A1': 'sfGFP',     'A2': 'mRFP1',      'A3': 'mKO2',
    'A4': 'Venus',     'A5': 'mKate2_TF',  'A6': 'Azurite',
    'A7': 'mCerulean3','A8': 'mClover3',   'A9': 'mJuniper',
    'A10':'mTurquoise2','A11':'mBanana',    'A12':'mPlum',
    'B1': 'Electra2',  'B2': 'mWasabi',    'B3': 'mScarlet_I',
    'B4': 'mPapaya',   'B5': 'eqFP578',    'B6': 'tdTomato',
    'B7': 'DsRed',     'B8': 'mKate2',     'B9': 'EGFP',
    'B10':'mRuby2',    'B11':'TagBFP',     'B12':'mChartreuse_TF',
    'C1': 'mLychee_TF','C2': 'mTagBFP2',  'C3': 'mEGFP',
    'C4': 'mNeonGreen','C5': 'mAzamiGreen','C6': 'mWatermelon',
    'C7': 'avGFP',     'C8': 'mCitrine',  'C9': 'mVenus',
    'C10':'mCherry',   'C11':'mHoneydew', 'C12':'TagRFP',
    'D1': 'mTFP1',     'D2': 'Ultramarine','D3': 'ZsGreen1',
    'D4': 'mMiCy',     'D5': 'mStayGold2','D6': 'PA_GFP',
}

# Volumen acumulado por color (para control de pozo activo)
volume_used = {k: 0 for k, _ in point_name_pairing}

# ──────────────────────────────────────────────
# Utilidades
# ──────────────────────────────────────────────
def update_volume_remaining(current_color, quantity_to_aspirate):
    """Avanza al siguiente pozo cuando el actual supera 250 µL."""
    rows = string.ascii_uppercase
    for well, color in list(well_colors.items()):
        if color.lower() == current_color.lower():
            if (volume_used[current_color] + quantity_to_aspirate) > 250:
                row, col = well[0], well[1:]
                next_well = f"{rows[rows.index(row) + 1]}{col}"
                del well_colors[well]
                well_colors[next_well] = current_color
                volume_used[current_color] = quantity_to_aspirate
            else:
                volume_used[current_color] += quantity_to_aspirate
            break


def run(protocol):
    protocol.home()

    # ── Labware ──────────────────────────────
    tips_20ul = protocol.load_labware(
        'opentrons_96_tiprack_20ul', TIP_RACK_DECK_SLOT, 'Tips 20 µL')

    pipette_20ul = protocol.load_instrument(
        "p20_single_gen2", "right", [tips_20ul])

    temperature_plate = protocol.load_labware(
        'opentrons_96_aluminumblock_generic_pcr_strip_200ul', COLORS_DECK_SLOT)

    agar_plate = protocol.load_labware(
        'htgaa_agar_plate', AGAR_DECK_SLOT, 'Agar Plate')
    agar_plate.set_offset(x=0.00, y=0.00, z=Z_VALUE_AGAR)

    center_location = agar_plate['A1'].top()
    pipette_20ul.starting_tip = tips_20ul.well(PIPETTE_STARTING_TIP_WELL)

    # ── Helpers ──────────────────────────────
    def dispense_and_jog(pipette, volume, location):
        """
        Mueve 2 mm sobre el punto, dispensa y retrocede.
        FIX: usamos offset relativo (z=2) en lugar de absoluto.
        """
        assert isinstance(volume, (int, float))
        above = location.move(types.Point(z=2))   # ← corregido (era z=location.point.z+2)
        pipette.move_to(above)
        pipette.dispense(volume, location)
        pipette.move_to(above)

    def location_of_color(color_string):
        for well, color in well_colors.items():
            if color.lower() == color_string.lower():
                return temperature_plate[well]
        raise ValueError(f"Color no encontrado: {color_string}")

    # ── Impresión ─────────────────────────────
    for color_idx, (current_color, point_list) in enumerate(point_name_pairing):
        if not point_list:
            continue

        pipette_20ul.pick_up_tip()
        max_aspirate   = int(18 // POINT_SIZE) * POINT_SIZE
        qty_to_aspirate = min(len(point_list) * POINT_SIZE, max_aspirate)
        update_volume_remaining(current_color, qty_to_aspirate)
        pipette_20ul.aspirate(qty_to_aspirate, location_of_color(current_color))

        # FIX: renombrado índice interno 'pt_idx' para no pisar 'color_idx'
        for pt_idx in range(len(point_list)):
            x, y = point_list[pt_idx]
            adjusted_location = center_location.move(types.Point(x, y, 0))
            dispense_and_jog(pipette_20ul, POINT_SIZE, adjusted_location)

            remaining = point_list[pt_idx + 1:]
            if pipette_20ul.current_volume == 0 and remaining:
                qty_to_aspirate = min(len(remaining) * POINT_SIZE, max_aspirate)
                update_volume_remaining(current_color, qty_to_aspirate)
                pipette_20ul.aspirate(qty_to_aspirate, location_of_color(current_color))

        pipette_20ul.drop_tip()
Script design notes

The script implements a volume-tracking helper (update_volume_remaining) that advances to the next row of the PCR strip when a well exceeds 250 µL of use, preventing over-aspiration. The dispense_and_jog function moves 2 mm above the agar surface before dispensing and retracts afterward, minimizing cross-contamination between dots. Coordinates are relative to the center of the agar plate (agar_plate['A1'].top()) and were generated directly from the opentrons-art GUI export.

AI use declaration: The Python script (Diseño_Art.py) was reviewed and debugged with assistance from an AI language model (Claude, Anthropic). Two bugs were identified and corrected: (1) the absolute z-coordinate offset in dispense_and_jog was replaced with a relative types.Point(z=2) offset; (2) the loop variable color_idx was renamed pt_idx inside the inner point loop to avoid shadowing the outer enumeration variable. The pixel art design coordinates were generated using the opentrons-art.rcdonovan.com web interface without AI assistance.

Post-Lab Question 1 · Published Paper

Published Paper — ACCS System

The paper reviewed is "Open-Source Cell Culture Automation System with Integrated Cell Counting for Passaging Microplate Cultures" (Courville et al., 2025, PNAS Nexus). It describes the Automated Cell Culture Divider (ACCS) -- an Opentrons OT-2 system with a custom-integrated cell count imager (CCI) that measures cell concentration in real time to adjust seeding volumes per well.

Novel biological application
Real-time density-adaptive cell seeding

Precision: CV less than 11% well-to-well, vs. manual estimation which is highly variable.

Imaging performance: 92% usable imaging sites (OpenCell 3D fluorescence) vs. 52% manual.

Efficiency: 61% reduction in researcher intervention time per run.

Open-source: All hardware and Python software released under open-source licenses.

Courville, G., Vaid, S., Toruno, A., Lebel, P., Cabrera, J. P., Raghavan, P., ... and Gomez-Sjoberg, R. (2025). Open-source cell culture automation system with integrated cell counting for passaging microplate cultures. PNAS Nexus, 4(12), pgaf385.
Post-Lab Question 1 · Critical Analysis

ACCS Paper — Extended Critique

The ACCS system (Courville et al., 2025, PNAS Nexus) demonstrates significant advances in open-source lab automation, but a committed reader must interrogate both its methodological assumptions and the limits of its transferability.

Methodological strengths
What the ACCS paper demonstrates well
The reported CV of less than 11% well-to-well (vs. high variability in manual estimation) is a meaningful precision benchmark for cell culture passaging. The 61% reduction in researcher intervention time per run addresses a genuine bottleneck in cell culture-intensive workflows. The fully open-source release of both hardware and Python software (under open-source licenses) is a substantial contribution to reproducibility — a rarity in instrumentation papers. The 92% usable imaging sites vs. 52% manual represents a quantifiable quality improvement, not merely a time savings.
Methodological limitations
What the paper leaves unaddressed

Transferability to non-mammalian systems. The ACCS system was validated exclusively on adherent mammalian cell lines. Bacterial cultures — including E. coli K-12 and Halomonas elongata as used in Füzi Poiesis — have fundamentally different growth kinetics (generation time ~20 min vs. 24+ hours), do not require attachment surface monitoring, and measure density by optical methods rather than cell counting. The CV and imaging benchmarks reported by Courville et al. cannot be assumed to transfer to bacterial microplate cultures without re-validation.

Closed-loop feedback limitation. The ACCS system adjusts seeding volumes based on cell density measured at the time of passaging — a single-point measurement. It does not implement continuous monitoring or adaptive control during the growth phase. For a Lotka-Volterra-based consortium like Füzi Poiesis, where population dynamics are governed by differential equations with time-varying metabolite concentrations, a single-point density readout is insufficient to parameterize the ODE system in real time. True closed-loop automation would require in-line metabolite sensing (SRP, H₂S, AHL) integrated with the OT-2 pipetting logic.

Statistical scope. The n reported for precision benchmarks is not specified in the abstract. CV below 11% is promising but the confidence interval around this estimate depends on the number of replicate runs, which is critical for evaluating whether the precision advantage over manual is statistically significant across different operators and cell types.

How I would extend this work

For the Nash Automaton protocol — the Opentrons-based automated selection system designed for Füzi Poiesis — the ACCS architecture would need to be extended in three directions: (1) replacing the cell count imager (CCI) with a turbidimetry module or OD600 reader compatible with bacterial microcultures; (2) integrating a fluorescence module to read quorum signal (AHL-linked GFP reporter in Strain C) as a proxy for consortium population ratio; and (3) replacing single-point density measurement with multi-timepoint sampling to fit Monod growth parameters in real time and feed them back into the Lotka-Volterra selection logic. The open-source Python codebase released by Courville et al. provides the OT-2 control infrastructure on which these extensions would be built.

Post-Lab Question 2 · Automation for Final Project

The Nash Automaton

The automation design for the project was the Nash Automaton -- a robotic protocol that subjects the consortium to iterative metabolic tests under automated artificial selection, executing a Minimax algorithm to select the variant that best withstands worst-case environmental stress from Lake Budi.

from opentrons import protocol_api

metadata = {
    'apiLevel': '2.13',
    'protocolName': 'Nash Automaton: Minimax Stress Matrix',
    'author': 'Nicolas Escobar Fierro -- HTGAA 2026',
    'description': 'Automated distribution of stressors for consortium selection.'
}

def run(protocol: protocol_api.ProtocolContext):

    benthic_plate   = protocol.load_labware('corning_96_wellplate_360ul_flat', '1')
    stressors_res   = protocol.load_labware('nest_12_reservoir_15ml', '2')
    inoculum_res    = protocol.load_labware('nest_12_reservoir_15ml', '3')
    tiprack         = protocol.load_labware('opentrons_96_tiprack_300ul', '4')

    p300 = protocol.load_instrument('p300_single_gen2', 'right', tip_racks=[tiprack])

    h2s_toxin       = stressors_res.wells()[0]
    master_inoculum = inoculum_res.wells()[0]

    # H2S gradient: 10 uL start, +2.5 uL per well (max 247.5 uL, safe for 360 uL well)
    current_vol   = 10
    vol_increment = 2.5

    p300.pick_up_tip()
    for well in benthic_plate.wells():
        p300.transfer(current_vol, h2s_toxin, well,
                      mix_after=(2, 20), new_tip='never')
        current_vol += vol_increment
    p300.drop_tip()

    p300.pick_up_tip()
    for well in benthic_plate.wells():
        p300.transfer(25, master_inoculum, well, new_tip='never')
    p300.drop_tip()

    protocol.comment("Nash Automaton complete.")
Design evolution

The MazF/MazE kill switch was replaced in Fuzi Poiesis by topological biocontainment via the three-strain auxotrophic ring. The AND-gate inputs were updated from skatole/H2S to AHL quorum signal and soluble reactive phosphorus. The osmotic acclimation and co-culture inoculation logic remain directly applicable to Aim 2.

AI use declaration: For the development of the Opentrons script, the Gemini language model (Google) was used as a technical review assistant, optimizing stress gradients and ensuring volumetric safety of the protocol.

Post-Lab Question 2 · Executable Protocol

Nash Automaton — Executable Protocol

The Nash Automaton was the automation design concept for Füzi Poiesis at this stage of the project — a robotic protocol implementing iterative metabolic selection using Opentrons OT-2 as the physical execution layer. The mathematical framework draws from Lotka-Volterra population dynamics and Minimax decision theory. Note: as the project evolved toward topological biocontainment via auxotrophic coupling, the Nash Automaton's role shifted from an active control mechanism to a characterization tool for Aim 2 parameter estimation.

Protocol overview
Nash Automaton — Step-by-step OT-2 workflow
  • Step 1 · Initialization (t = 0) — Load three strains (Strain A, B, C) into a 96-well microplate at equal starting densities (OD₆₀₀ ≈ 0.05 each) in minimal medium supplemented with the auxotrophic amino acids at defined concentrations: L-leucine (Strain A supply, 50 μM), L-tryptophan (Strain B supply, 50 μM), L-histidine (Strain C supply, 50 μM). Total volume per well: 200 μL. Plate layout: 8 replicates per condition, 4 amino acid concentration conditions (0×, 0.5×, 1×, 2× baseline), 3 monoculture controls.
  • Step 2 · Growth phase (t = 0 to 4 h) — Incubate at 37°C with orbital shaking at 200 rpm. No OT-2 action required during this phase. OD₆₀₀ is read by plate reader at t = 0, 1, 2, 3, 4 h to parameterize Monod growth rates (μ_max) and carrying capacity (K) for each strain under each amino acid concentration condition.
  • Step 2 · Density readout — At t = 4 h, OT-2 transfers 20 μL from each well to a flat-bottom OD measurement plate (P300 multi-channel pipette, 96-well format). OD₆₀₀ is read and values transmitted to the Python control script.
  • Step 3 · Lotka-Volterra parameterization — The Python control script fits the six-equation ODE system (dN_i/dt = μ_max,i · S_j/(K_i + S_j) · N_i − D·N_i) to the time-series OD data using scipy.optimize.curve_fit. The fitted μ_max and K values are used to compute the Jacobian eigenvalue spectrum and verify that the current amino acid concentrations maintain the system at the stable interior fixed point.
  • Step 4 · Minimax selection — The control script applies the Nash Minimax criterion: identify the amino acid concentration set that minimizes the maximum deviation of each strain from its target equilibrium density (n* ≈ 0.629 in dimensionless units). This is equivalent to finding the strategy that is most robust to perturbation — the Nash equilibrium of the three-player consortium game.
  • Step 5 · Passaging (t = 4 h) — OT-2 prepares fresh medium with the Minimax-selected amino acid concentrations. Using P300 multi-channel pipette: aspirate 180 μL from each well, discard, add 180 μL fresh medium at Minimax concentrations + 20 μL culture (1:10 dilution). This maintains the consortium at log-phase growth while updating metabolite supply to the optimal strategy.
  • Step 6 · Iteration — Steps 2–5 repeat for 6 passaging cycles (24 h total), producing a time series of Lotka-Volterra parameters under automated artificial selection. Final readout: the amino acid concentrations and OD₆₀₀ ratios at which the three-strain consortium maintains stable coexistence closest to the predicted interior fixed point.
Labware specification

Opentrons OT-2 · P300 multi-channel GEN2 pipette · Corning 96-well flat-bottom microplate · Opentrons 96-well aluminum block at 37°C · 12-channel reservoir for media preparation · Opentrons 300 μL tip rack (×4). Python packages: opentrons API v2, scipy, numpy, pandas. Script execution: Jupyter notebook running on OT-2 onboard computer via SSH, with plate reader data imported via CSV after each OD measurement cycle.

Design evolution note

The Nash Automaton was designed at this stage of Füzi Poiesis as an active control mechanism — the robot would continuously adjust the biochemical environment to maintain the Nash equilibrium of the three-strain game. As the project architecture matured, this role was re-scoped: topological biocontainment via auxotrophic coupling encodes stability structurally into the consortium, without requiring external robotic intervention. The Nash Automaton's role in the final Füzi Poiesis design is therefore as a Aim 2 characterization tool — used to measure the Monod kinetic parameters needed to calibrate the ODE model for native Lake Budi strains — rather than as a deployment control system.

Reflection · Week 3

Connecting to the Node

This week was the first where the course stopped feeling abstract and started feeling like a community. The SynBio USFQ Node brought together students from across South America — Argentina, Chile, México — and for the first time I was sharing a virtual space with people who were navigating the same course from the same side of the world, with the same timezone problems, the same access constraints, and the same excitement.

What I didn't expect was the range of people. I'm 21. Some of the others in the node are senior researchers, founders of biotech companies, people who have already built things — real things, not student projects. Sitting in the same call as someone who runs a biotech firm in Buenos Aires or Mexico City while I'm still figuring out what direction to take is a strange and clarifying experience. Not intimidating in the way I feared. More like a useful collision.

What I took from it

The age gap cuts both ways. They have experience I don't have — industry knowledge, real failure, institutional context. I have something too, maybe: fewer fixed assumptions about what's possible, less attachment to how things have been done. The most interesting conversations this week weren't about protocols or papers. They were about why each person is here — what problem they're actually trying to solve. Everyone had a different answer. Nobody's answer was wrong.

On being a Global Student from Temuco

Temuco doesn't appear on many synthetic biology maps. La Frontera isn't a research hub by any conventional measure. Being here — designing pixel art for a robot I'll never touch, writing protocols for a lab I'll never walk into, submitting forms across a twelve-hour timezone difference — has a specific texture. There's something clarifying about doing serious work from a place that doesn't expect it of you. The node made that feel less like a limitation and more like a position.

A note on time

Most of the people I met this week have been working in biology longer than I've been thinking about it seriously. That used to feel like a disadvantage. This week it started to feel like information — a data point about how long it takes to build something worth building, and a reason to start now rather than later.

Final Project Ideas · Due by Feb 24 Lecture

The Genesis of Fuzi Poiesis

This week's assignment required presenting three different concept slides for what our project could be. I submitted one slide with three distinct levels of complexity and ambition -- from the most grounded to the most epic. None of these concepts survived exactly into the final design, but all three fed the thinking that became Fuzi Poiesis.

The Bricolage Inoculum concept slide
Concept 1 - The Bricolage Inoculum. Pumice/Bokashi scaffold + K-Core native consortium. The most grounded concept -- closest to what we were already developing.
The Memory of Gold - Kintsugi concept slide
Concept 2 - The Memory of Gold. Kintsugi Ecosystem Therapy. Repair the broken biogeochemical network with synthetic biology as gold -- poetic and architecturally precise.
The Gambit of Redemption concept slide
Concept 3 - The Gambit of Redemption. Bio-reprogramming Lake Budi using the Nash Automaton. The most ambitious -- bioremediation as a non-zero-sum game against eutrophication.
Concept 1
The Bricolage Inoculum

The Scaffolding: Local hardware, living software. Pumice/Bokashi acts as a low-entropy skeleton. Within its micropores resides the K-Core -- a minimal consortium of native bacteria that operate as an obligatory metabolic symphony, transforming the physical support into a biological processor.

Core Pillars: Topological Resilience (strengthening key nodes to stabilize the ecosystem through cascading effects), Metabolic Bricolage (syntrophic engineering via cross-auxotrophies), and Entropy Sequestration (converting H2S/Nitrogen pollutants into useful biomass).

What survived into Fuzi Poiesis: The Bokashi del Budi scaffold, the cross-auxotrophic coupling, and the syntrophic engineering logic are all present in the final design.

Concept 2
The Memory of Gold -- Kintsugi Ecosystem Therapy

Core idea: Eutrophication in Lake Budi acts as metabolic amnesia, collapsing biodiversity (Shannon Entropy). Inspired by Kintsugi -- the Japanese art of repairing broken pottery with gold -- we repair the broken biogeochemical network not with foreign species, but by patching native microorganisms with synthetic biology, creating a resilient hybrid ecosystem.

Control Logic: AND gate (H2S AND pathogens exceed threshold) activates the remediation operon. MazF/MazE kill switch for biocontainment.

What survived: The AND-gate logic (inputs later changed to AHL + SRP), the Shannon entropy framing of ecosystem collapse, and the name "Kintsugi Inoculum" -- which later became "Fuzi Poiesis" after incorporating Mapudungun and Maturana's autopoiesis concept.

Concept 3
The Gambit of Redemption -- Bio-Reprogramming Lake Budi

Core idea: Biogeochemical entropy (cyanobacterial bloom) leads to system collapse (anoxia), while the player (Nash Automaton) seeks bioremediation. The game is won when equilibrium is reached and the lake's metabolism is regulated. Non-zero-sum game: both the ecosystem and the community win.

Players: Nash Automaton (Opentrons + Lotka-Volterra + Minimax) as feedback loop control; Cyanobacterial Bloom as the opponent (exponential growth and positive feedback of collapse); Lake Budi as referee.

What survived: The Lotka-Volterra population dynamics framework, the Nash equilibrium framing, and the Minimax automated selection logic all appear in the final Fuzi Poiesis ODE model and Aim 2 experimental design.

From three concepts to one architecture

None of these three concepts was chosen -- and all three were. The Bricolage Inoculum provided the physical scaffold (Bokashi del Budi). The Memory of Gold provided the AND-gate circuit logic and the name lineage (Kintsugi Inoculum - Fuzi Poiesis). The Gambit of Redemption provided the mathematical framework (Lotka-Volterra, Nash equilibrium, Lyapunov stability). Fuzi Poiesis is the synthesis of all three, stripped of the poetic framing and rebuilt on rigorous mathematical foundations.