Heather Qian — HTGAA Spring 2026

cover image cover image

About me

I am a third year undergraduate at William and Mary majoring in Biology and Computational and Applied Mathematics. I conduct research on phage satellites in the Saha Lab, and I’m excited to take this course!

Contact info

hlqian@wm.edu

Homework

Labs

Projects

Subsections of Heather Qian — HTGAA Spring 2026

Homework

Weekly homework submissions:

  • Week 1 HW: Principles and Practices

    Governance 1. Bioengineering Tool Phage satellites are a diverse class of mobile genetic elements that parasitize a phage. Extracellular Prophage-Inducing Particles (EPIPs), are a novel class of phage satellite discovered by the Saha Lab that induces the extremely stable prophage, HerbertWM, in Mycolicibacterium aichiense. Due to their novelty, much of their mechanisms of action are unknown, but it is hypothesized that they contain antirepressors or partial antirepressors due to annotated genes that bear resemblance to BRO domains which have been noted to have some influence over transcription (Zemskov et al., 2000). Because of the observed ability of EPIPs to induce a stable prophage, developing a lytic-lysogenic switch from their putative antirepressors would be valuable for many applications including medical and environmental applications. This switch could ensure that a temperate phage lyses bacterial pathogens in phage therapy or control the transcription of engineered constructs in the soil.

  • Week 2 HW: DNA Read, Write, and Edit

    DNA Design Challenge Protein chosen: tape measure protein of Alyssa1, a Mycolicibacterium phage satellite called an “Extracellular Prophage-Inducing Particle” (EPIP). Tape measure proteins are rare in phage satellites, and TEM imaging has shown that EPIPs have uniquely long tails compared to the helper phage, the phage they parasitize, suggesting the tape measure protein may contribute to a unique mechanism of parasitism.

  • Week 3 HW: Lab Automation

    Paper Discussion Paper: AssemblyTron: flexible automation of DNA assembly with Opentrons OT-2 lab robots This paper reports using the Opentrons robot to conduct PCR, Golden Gate assembly, and Gibson assembly. It appears that the robot was able to determine specific parameters for experiments such as annealing temperature. The paper did not go into much detail about how this occurred, but after looking at some of the supplementary materials, the script likely parses .csv files that include primer and fragement sequences.

Subsections of Homework

Week 1 HW: Principles and Practices

cover image cover image

Governance

1. Bioengineering Tool

Phage satellites are a diverse class of mobile genetic elements that parasitize a phage. Extracellular Prophage-Inducing Particles (EPIPs), are a novel class of phage satellite discovered by the Saha Lab that induces the extremely stable prophage, HerbertWM, in Mycolicibacterium aichiense. Due to their novelty, much of their mechanisms of action are unknown, but it is hypothesized that they contain antirepressors or partial antirepressors due to annotated genes that bear resemblance to BRO domains which have been noted to have some influence over transcription (Zemskov et al., 2000).
Because of the observed ability of EPIPs to induce a stable prophage, developing a lytic-lysogenic switch from their putative antirepressors would be valuable for many applications including medical and environmental applications. This switch could ensure that a temperate phage lyses bacterial pathogens in phage therapy or control the transcription of engineered constructs in the soil.

2. Governance/Policy Goals

  • Enhancebiosecurity: making sure this tool won’t activate genes or viruses that could harm people
    • Preventing incidents
    • Helping respond
  • Foster lab safety: while M. aichiense is BSL-1, safety precautions should still be used
    • Preventing incidents
    • Helping respond
  • Protect the environment: monitor how using this tool in the environment effects ecology
    • Preventing incidents
    • Helping respond
  • Other considerations
    • Minimizing costs/burdens to stakeholders
    • Feasibility
    • Not impede research
    • Promote constructive applications

3. Actions

Option 1: Make grant funding easier to obtain if the researcher is working toward using this tool in a beneficial application

  • Purpose: encourage beneficence
  • Design: funding sources such as the NIH or NSF must agree to this. These sources also must have enough money allocated by the government to give out, so the government must also agree to this.
  • Assumptions: researchers want money; it is already required of researchers to discuss potential applications of their work when applying for funding
  • Risks of failure and “success”: this could accidentally discourage basic science research—research for the sake of knowledge or a better understanding of the world that could benefit more people in the long run.

Option 2: Ensure individuals are well-trained to prevent contamination by more harmful microbes

  • Purpose: policies regarding BSL-1 waste disposal are already in place; however, in the past, M. aichiense cultures have become contaminated with bacteria that could have been a higher BSL level (but thankfully were not)
  • Design: more senior researchers should give newer researchers more hands-on focused training
  • Assumptions: senior researchers have the time to give newer researchers this training
  • Risks of failure and “success”: this could detract from the time spent researching, making the lab less productive

Option 3: Researchers must study long-term effects of using this tool in the environment

  • Purpose: ensure the application the tool is used for does not harm the environment
  • Design: researchers must have the means to track environmental changes over time. Some regulatory agency must enforce this standard.
  • Assumptions: researchers will do this to some extent anyway to see how durable/effective their work is in the environment
  • Risks of failure and “success”: researchers may not have the resources or time to allocate to study this. They may feel that their resources are better spent elsewhere

4. Scoring

Does the option:Option 1Option 2Option 3
Enhance Biosecurity211
• By preventing incidents112
• By helping respond321
Foster Lab Safetyn/a1n/a
• By preventing incidentsn/a1n/a
• By helping respondn/a1n/a
Protect the environment2n/a1
• By preventing incidents2n/a2
• By helping respond3n/a1
Other considerations
• Minimizing costs and burdens to stakeholders223
• Feasibility?213
• Not impede research122
• Promote constructive applications132

5. Prioritization

Options 1 and 2 should be prioritized because they are more easily enforced and are based on pre-existing regulations and practices, making them fairly feasible. Option 3 is difficult to enforce and offers researchers no incentive to comply, whereas option 1 provides incentive and works through positive reinforcement. Additionally, both options 1 and 2 focus on preventing incidents by offering incentives toward beneficence (option 1) or providing better safety training (option 2). Meanwhile, option 3 prioritizes reacting to possible incidents by tracking environmental changes, noticing damage to the environment, and responding. Lastly, option 3 most obviously hinders research by dictating what resaerchers must investigate, while option 1 does not hinder research and option 2 will help research in the long run, even if it initially takes time away from research to teach good practices.

Pre-Lecture Work

Professor Jacobson

  1. DNA polymerase’s error rate is 1:106. The human genome is ~3 billion bp, so on average, there would be 3000 mistakes made per round of DNA replication. Biology deals with this by destroying misfolded proteins and/or killing cells with too many mutations.
  2. Due to third-base wobble, there are many ways to code for a protein of interest. In real life, many of these don’t work because certain organisms have a bias toward particular tRNAs, so mRNA codons must match the tRNA anticodons.

Dr. LeProust

  1. The most common method of oligo synthesis uses phosphoramidite.
  2. Chemical errors accumulate, so making fragments longer than 200 bp is difficult with direct synthesis.
  3. Errors have accumulated so much that there are basically no fragments with the correct sequence.

George Church

  1. 10 essential amino acids: histidine, isoleucine, leucine, lysine, methionine, phenylalanine, threonine, tryptophan, valine, and arginine. The “lysine contingnecy” suggests that humans (and other animals) must eat plants because they are our only source of lysine, but they are also the only source of all of these amino acids, not just lysine.
  2. I would use slide 4, the NA to AA conversion to know what nucleotides to use that would result in amino acids that would chemically interact.
  3. BoSS: It would be great to find a way to store medications/treatments at room temperature; however, this could lead to unintended consequences such as vulnerability to contamination. As someone who works in a lab with bacteria, although the bacteria I work with could survive at room temperature, we store them in a fridge to help prevent contamination. I would also be concerned about using protective molecules from organisms that have adapted to survive at extreme temperatures to store medications/treatments, as these protective molecules could harm humans if they contaminate the treatment.

HTGAA Website

I added information about me, my email, and a cover image to the home page of the website. I have also learned the basics of markdown (including how to embed links and add images) during that process and have added this homework assignment to the website as well.

Week 2 HW: DNA Read, Write, and Edit

DNA Design Challenge

Protein chosen: tape measure protein of Alyssa1, a Mycolicibacterium phage satellite called an “Extracellular Prophage-Inducing Particle” (EPIP). Tape measure proteins are rare in phage satellites, and TEM imaging has shown that EPIPs have uniquely long tails compared to the helper phage, the phage they parasitize, suggesting the tape measure protein may contribute to a unique mechanism of parasitism.

TMP_info TMP_info

Amino acid sequence: MARKAGMSTGVEVARISVKVGPDTKHFRRELKKDLDRIEESMRAKIDVEPDMKGFRQEVQSKTKGMRTSVKVDADVDRKGFLGRIADSLSQIQPPSFGSGINPTGYAAIAAGIAALTPLIAGTLGAATTALMALPGLVAAVATPIAALTLGIDGLKAAATRLQGPFEDLKATMSSAVESQFGPVFDQLRSLFPVLKGALPSVTAGLADMAKSIADVIASPEGLAKIDTTIRNIGMALTTAAPGVGKFTDGLMGLVQSFTGKPLQGVAEWFSKTGDSFSAWVEKMTRPSWFTGKSPLEVAFGNLGDTLKTIADTLGDVGQKALDFFSDPEKIKSFRDELTLVSDAVKGIATGINGIATAYSSLPLSGEGLKGLMPIQAQLGVKMFDGLKESAAKAFAEVATMAGGFVSNIGSTFMSIGDTLSGIWGGITNAAATAFNSLVSAAQSAVSGVVSAVATIPGQVASALAGLAEAGASAGRNLVQGLVNGISGMIGSAVAKARELASSVASAVTGFLGIHSPSKLFTEIGEYVGQGFDNGLQSQLATLGQTAKAMAETVTEEFNGGLKFGADGFSTDSDNPLMQAGAGLANAPVDFAKATGKQFLSDLGISGNGVLSRALTEGIQYIFQISSVDEALSIKDRETSKNALSIVGR

Reverse translated nucleotide sequence:
atggcgcgcaaagcgggcatgagcaccggcgtggaagtggcgcgcattagcgtgaaagtgggcccggataccaaacattttcgccgcgaactgaaaaaagatctggatcgcattgaagaaagcatgcgcgcgaaaattgatgtggaaccggatatgaaaggctttcgccaggaagtgcagagcaaaaccaaaggcatgcgcaccagcgtgaaagtggatgcggatgtggatcgcaaaggctttctgggccgcattgcggatagcctgagccagattcagccgccgagctttggcagcggcattaacccgaccggctatgcggcgattgcggcgggcattgcggcgctgaccccgctgattgcgggcaccctgggcgcggcgaccaccgcgctgatggcgctgccgggcctggtggcggcggtggcgaccccgattgcggcgctgaccctgggcattgatggcctgaaagcggcggcgacccgcctgcagggcccgtttgaagatctgaaagcgaccatgagcagcgcggtggaaagccagtttggcccggtgtttgatcagctgcgcagcctgtttccggtgctgaaaggcgcgctgccgagcgtgaccgcgggcctggcggatatggcgaaaagcattgcggatgtgattgcgagcccggaaggcctggcgaaaattgataccaccattcgcaacattggcatggcgctgaccaccgcggcgccgggcgtgggcaaatttaccgatggcctgatgggcctggtgcagagctttaccggcaaaccgctgcagggcgtggcggaatggtttagcaaaaccggcgatagctttagcgcgtgggtggaaaaaatgacccgcccgagctggtttaccggcaaaagcccgctggaagtggcgtttggcaacctgggcgataccctgaaaaccattgcggataccctgggcgatgtgggccagaaagcgctggatttttttagcgatccggaaaaaattaaaagctttcgcgatgaactgaccctggtgagcgatgcggtgaaaggcattgcgaccggcattaacggcattgcgaccgcgtatagcagcctgccgctgagcggcgaaggcctgaaaggcctgatgccgattcaggcgcagctgggcgtgaaaatgtttgatggcctgaaagaaagcgcggcgaaagcgtttgcggaagtggcgaccatggcgggcggctttgtgagcaacattggcagcacctttatgagcattggcgataccctgagcggcatttggggcggcattaccaacgcggcggcgaccgcgtttaacagcctggtgagcgcggcgcagagcgcggtgagcggcgtggtgagcgcggtggcgaccattccgggccaggtggcgagcgcgctggcgggcctggcggaagcgggcgcgagcgcgggccgcaacctggtgcagggcctggtgaacggcattagcggcatgattggcagcgcggtggcgaaagcgcgcgaactggcgagcagcgtggcgagcgcggtgaccggctttctgggcattcatagcccgagcaaactgtttaccgaaattggcgaatatgtgggccagggctttgataacggcctgcagagccagctggcgaccctgggccagaccgcgaaagcgatggcggaaaccgtgaccgaagaatttaacggcggcctgaaatttggcgcggatggctttagcaccgatagcgataacccgctgatgcaggcgggcgcgggcctggcgaacgcgccggtggattttgcgaaagcgaccggcaaacagtttctgagcgatctgggcattagcggcaacggcgtgctgagccgcgcgctgaccgaaggcattcagtatatttttcagattagcagcgtggatgaagcgctgagcattaaagatcgcgaaaccagcaaaaacgcgctgagcattgtgggccgc

Codon optimized nucleotide sequence:
ATGGCCCGCAAAGCCGGCATGAGCACCGGCGTGGAAGTCGCGCGTATTAGCGTGAAAGTGGGCCCGGATACCAAACATTTTCGTCGCGAACTGAAAAAAGATCTGGATCGCATTGAAGAAAGCATGCGTGCCAAAATTGACGTAGAACCGGATATGAAAGGCTTTCGTCAGGAAGTGCAGAGCAAAACCAAAGGCATGCGCACCAGCGTGAAAGTGGATGCGGATGTGGATCGCAAAGGCTTCCTGGGCCGTATTGCCGATAGCCTGAGTCAGATTCAGCCGCCTAGCTTTGGCAGCGGCATTAACCCGACCGGTTACGCCGCGATTGCGGCGGGCATTGCCGCGCTGACCCCGCTGATTGCGGGCACCCTGGGCGCGGCGACCACCGCGCTGATGGCCCTGCCGGGCCTGGTGGCGGCGGTGGCGACCCCGATTGCGGCGCTGACTCTGGGCATTGATGGCCTGAAAGCCGCCGCGACCCGCCTGCAGGGTCCGTTTGAAGATCTGAAAGCCACCATGTCGAGCGCCGTGGAAAGCCAATTTGGCCCGGTGTTTGATCAGCTGCGTAGCCTGTTTCCGGTGCTGAAAGGCGCGCTGCCGAGCGTGACCGCGGGTCTTGCGGATATGGCGAAGAGCATTGCCGATGTGATTGCCAGCCCGGAAGGCCTGGCAAAAATTGATACCACCATCCGTAACATTGGCATGGCCCTGACCACCGCGGCCCCGGGCGTTGGCAAATTTACCGATGGTCTGATGGGCCTGGTACAGAGCTTTACCGGCAAACCGCTGCAGGGCGTGGCGGAATGGTTTAGTAAAACCGGTGATTCATTTAGCGCCTGGGTGGAAAAAATGACCCGCCCGAGCTGGTTTACCGGCAAAAGCCCGCTGGAAGTCGCATTCGGCAACCTGGGCGATACCCTGAAAACCATTGCCGATACGCTGGGCGATGTCGGCCAGAAAGCCCTGGATTTTTTTAGCGATCCGGAAAAAATTAAATCGTTTCGCGATGAACTGACCCTGGTGAGCGATGCCGTAAAAGGCATTGCCACCGGTATCAACGGCATTGCCACCGCCTACTCATCCCTGCCGCTGAGCGGCGAAGGCCTGAAAGGCCTGATGCCGATTCAGGCCCAGCTGGGCGTTAAAATGTTTGATGGTCTGAAAGAAAGCGCCGCGAAAGCCTTCGCGGAAGTTGCGACCATGGCAGGCGGCTTTGTGTCGAACATTGGCTCCACCTTTATGAGCATTGGCGATACCCTGAGCGGTATTTGGGGTGGCATTACCAATGCGGCGGCGACCGCGTTTAACAGCCTGGTTAGCGCGGCGCAGAGCGCGGTGAGCGGCGTGGTGAGCGCGGTGGCCACCATTCCGGGTCAGGTGGCGAGCGCCCTGGCGGGCCTGGCCGAAGCAGGCGCCAGCGCCGGCCGCAATCTGGTGCAGGGTCTGGTCAACGGCATTAGCGGCATGATCGGCAGCGCCGTAGCGAAAGCGCGCGAACTGGCGAGCAGCGTGGCGTCAGCGGTTACCGGCTTCCTGGGCATTCACAGCCCGAGCAAATTATTTACCGAAATTGGTGAATATGTGGGCCAGGGCTTCGATAACGGCCTGCAGAGCCAGCTGGCGACTCTGGGTCAGACCGCGAAAGCGATGGCGGAAACCGTGACCGAAGAATTTAACGGCGGCCTGAAATTTGGTGCGGACGGCTTTAGCACCGACAGCGATAATCCGTTAATGCAGGCGGGCGCCGGCCTGGCCAACGCGCCGGTGGATTTTGCGAAAGCCACCGGTAAACAGTTTCTGTCTGATCTGGGTATCAGCGGCAACGGCGTTCTGAGCCGTGCACTGACCGAAGGCATCCAGTATATTTTTCAGATTAGCAGCGTTGATGAAGCGCTGAGCATTAAAGATCGCGAAACCAGCAAAAACGCCCTGAGCATTGTGGGCCGT

This sequence has been optimized for expression in E. coli. In this instance, it would be helpful to do this as these phage satellites were discovered in Mycolicibacterium aichiense, a non-model organism, so expressing this protein in E. coli would make it easier to work with. In general, nucleotide sequences are optimized so that the protein can be more efficiently expressed in a given organism, so that working with it is easier (such as by removing restriction enzyme cut sites), or so that synthesis is easier (such as by lowering the GC content).

Prepare a Twist DNA Synthesis Order

Alyssa1 Tape Measure Protein Expression Cassette in Benchling
Sequence in Benchling
Benchling Benchling

Choosing a Vector in Twist: I chose pTwist Amp High Copy because the Saha Lab works with ampicillin and if I want to express this protein in E. coli, I assume I’d want a lot of protein and for every E. coli descendent to have the plasmid, so a high copy plasmid would work best.

Alyssa1 Tape Measure Protein in Plasmid
Sequence from Twist imported into Benchling
Alyssa TMP in plasmid Alyssa TMP in plasmid

DNA Read/Write/Edit

Read

What DNA would you want to sequence (e.g., read) and why?
I would like to sequence my gut microbiome. I’ve read about how the microbiome, specifically the gut microbiome can influence a person’s behaviors and send signals to the brain. This raises some philosophical questions of whether humans are truly governed by their own thoughts or if their thoughts are being subtly influenced by bacteria in their gut. I think it would be interesting to see what species dominate my microbiome.

In lecture, a variety of sequencing technologies were mentioned. What technology or technologies would you use to perform sequencing on your DNA and why?
Nanopore sequencing it can generate long reads, so it is easier to identify unique features of each species. This makes it easier to assemble genomes.

Write

What DNA would you want to synthesize (e.g., write) and why?
I have always wondered if it would one day be possible to create an organism with “no evolutionary history.” Many of the synthetic biology products/parts now are from preexisting organisms, but is it possible to create an entirely new sequence of DNA that produces proteins with no orthologs? Theoretically, this may be possible, similar to the “monkey at a type-writer” idea, where by chance a random sequence of nucleotides could not only produce a novel protein, but a novel organism. I would like to do this if only to see if it is possible.

What technology or technologies would you use to perform this DNA synthesis and why?
To design this sequence, I would need some kind of machine learning model because biology is extremely complex and cannot be modeled with traditional methods. To synthesize this DNA, I could use the most common method of DNA synthesis, phosphoramidite chemistry, to synthesize pieces of this DNA, then use an assembly technique like Gibson assembly or Golden Gate assembly to construct the genome. These methods are most accessible and are commonly used.

Essential steps: deprotection, add next nucleotide, cap to stop strands that didn’t get the new nucleotide added from growing, and oxidation.
Limitations: this method can’t make fragments longer than ~200 bp due to errors that accumulate.

Edit

What DNA would you want to edit and why? I would like to edit my dog’s DNA to make him age more slowly. My dog makes me very happy but I don’t get to see him much because I’m at college and he lives with my parents. I would love it if he could stick around long enough that I could take care of him once I am out of school.

What technology or technologies would you use to perform these DNA edits and why?
I would use CRISPR to knock in or out genes that I’d need to change. Editing an organism to change its life span would require many edits to the genome, and those edits would likely have to be precise. Because of that, CRISPR would be the best option.

Essential steps: guide RNA recognizes DNA sequence, and the Cas 9 enzyme makes a double-stranded break in the DNA.
Preparation and input: prepare the guide RNA, so I’d need to know the sequence. Inputs include cells, some sort of vector to get the CRISPR-Cas9 system into the cells, and the CRISPR-Cas9 system (enzyme and guide RNA)
Limitations: cuts in off target places, requirement of a PAM sequence, delivery mechanism (finding a vector)

Week 3 HW: Lab Automation

Paper Discussion

Paper: AssemblyTron: flexible automation of DNA assembly with Opentrons OT-2 lab robots

This paper reports using the Opentrons robot to conduct PCR, Golden Gate assembly, and Gibson assembly. It appears that the robot was able to determine specific parameters for experiments such as annealing temperature. The paper did not go into much detail about how this occurred, but after looking at some of the supplementary materials, the script likely parses .csv files that include primer and fragement sequences.

Automation in Final Project

Since my final project will likely involve assembly techniques as described above, I could use automation by writing a Python script that automatically calculates experiment parameters such as temperatures and concentrations based on information that I put in such as DNA sequences and concentrations. This part of experiment planning is tedious and often involves multiple tools/pages (such as NEB’s Tm calculator, and various protocols for each method of assembly), so having one script that can do this automatically would be helpful. Additionally, it would be interesting to see how the Opentrons robot can run this script, though I predict that that would require some amount of troubleshooting that I may not have time for.

Final Project Ideas

Slide deck

Labs

Lab writeups:

  • Week 1 Lab: Pipetting

  • Week 2 Lab: DNA Gel Art

    Design Lane 4 will be left empty. EcoRI is listed here for visual purposes. Restriction Digest Protocol Digest components X uL NFW to 20 uL 2 uL 10X Promega buffer 1.5 ug DNA 15 units restriction enzyme Calculations for 10 uL reactions

  • Week 3 Lab: Opentrons Art

    Design Code Colab File from opentrons import types metadata = { # see https://docs.opentrons.com/v2/tutorial.html#tutorial-metadata 'author': 'Heather Qian', 'protocolName': 'Opentrons Flower', 'description': 'Makes a red and green flower', 'source': 'HTGAA 2026 Opentrons Lab', 'apiLevel': '2.20' } ############################################################################## ### Robot deck setup constants - don't change these ############################################################################## TIP_RACK_DECK_SLOT = 9 COLORS_DECK_SLOT = 6 AGAR_DECK_SLOT = 5 PIPETTE_STARTING_TIP_WELL = 'A1' well_colors = { 'A1' : 'Red', 'B1' : 'Green', 'C1' : 'Orange' } def run(protocol): ############################################################################## ### Load labware, modules and pipettes ############################################################################## # Tips tips_20ul = protocol.load_labware('opentrons_96_tiprack_20ul', TIP_RACK_DECK_SLOT, 'Opentrons 20uL Tips') # Pipettes pipette_20ul = protocol.load_instrument("p20_single_gen2", "right", [tips_20ul]) # Modules temperature_module = protocol.load_module('temperature module gen2', COLORS_DECK_SLOT) # Temperature Module Plate temperature_plate = temperature_module.load_labware('opentrons_96_aluminumblock_generic_pcr_strip_200ul', 'Cold Plate') # Choose where to take the colors from color_plate = temperature_plate # Agar Plate agar_plate = protocol.load_labware('htgaa_agar_plate', AGAR_DECK_SLOT, 'Agar Plate') ## TA MUST CALIBRATE EACH PLATE! # Get the top-center of the plate, make sure the plate was calibrated before running this center_location = agar_plate['A1'].top() pipette_20ul.starting_tip = tips_20ul.well(PIPETTE_STARTING_TIP_WELL) ############################################################################## ### Patterning ############################################################################## ### ### Helper functions for this lab ### # pass this e.g. 'Red' and get back a Location which can be passed to aspirate() def location_of_color(color_string): for well,color in well_colors.items(): if color.lower() == color_string.lower(): return color_plate[well] raise ValueError(f"No well found with color {color_string}") # For this lab, instead of calling pipette.dispense(1, loc) use this: dispense_and_detach(pipette, 1, loc) def dispense_and_detach(pipette, volume, location): """ Move laterally 5mm above the plate (to avoid smearing a drop); then drop down to the plate, dispense, move back up 5mm to detach drop, and stay high to be ready for next lateral move. 5mm because a 4uL drop is 2mm diameter; and a 2deg tilt in the agar pour is >3mm difference across a plate. """ assert(isinstance(volume, (int, float))) above_location = location.move(types.Point(z=location.point.z + 5)) # 5mm above pipette.move_to(above_location) # Go to 5mm above the dispensing location pipette.dispense(volume, location) # Go straight downwards and dispense pipette.move_to(above_location) # Go straight up to detach drop and stay high ### ### YOUR CODE HERE to create your design ### # Center pipette_20ul.pick_up_tip() pipette_20ul.aspirate(18, location_of_color("Green")) cursor = center_location.move(types.Point(x=-4, y=15)) for i in range(9): dispense_and_detach(pipette_20ul, 3, cursor) if i != 8: cursor = cursor.move(types.Point(x=4)) if i % 3 == 2 and i != 8: cursor = cursor.move(types.Point(x=-12, y=-4)) if i == 5: pipette_20ul.aspirate(9, location_of_color("Green")) pipette_20ul.drop_tip() # Right petal pipette_20ul.pick_up_tip() pipette_20ul.aspirate(18, location_of_color("Red")) cursor = cursor.move(types.Point(x=4)) for i in range(6): dispense_and_detach(pipette_20ul, 3, cursor) cursor = cursor.move(types.Point(y=4)) if i % 3 == 2: cursor = cursor.move(types.Point(x=4, y=-12)) pipette_20ul.aspirate(3, location_of_color("Red")) cursor = cursor.move(types.Point(y=4)) dispense_and_detach(pipette_20ul, 3, cursor) # Top petal pipette_20ul.aspirate(18, location_of_color("Red")) cursor = cursor.move(types.Point(x=-12, y=8)) for i in range(6): dispense_and_detach(pipette_20ul, 3, cursor) cursor = cursor.move(types.Point(x=-4)) if i % 3 == 2: cursor = cursor.move(types.Point(x=12, y=4)) pipette_20ul.aspirate(3, location_of_color("Red")) cursor = cursor.move(types.Point(x=-4)) dispense_and_detach(pipette_20ul, 3, cursor) # Left petal pipette_20ul.aspirate(18, location_of_color("Red")) cursor = cursor.move(types.Point(x=-8, y=-12)) for i in range(6): dispense_and_detach(pipette_20ul, 3, cursor) cursor = cursor.move(types.Point(y=-4)) if i % 3 == 2: cursor = cursor.move(types.Point(x=-4, y=12)) pipette_20ul.aspirate(3, location_of_color("Red")) cursor = cursor.move(types.Point(y=-4)) dispense_and_detach(pipette_20ul, 3, cursor) # Bottom petal pipette_20ul.aspirate(18, location_of_color("Red")) cursor = cursor.move(types.Point(x=12, y=-8)) for i in range(6): dispense_and_detach(pipette_20ul, 3, cursor) cursor = cursor.move(types.Point(x=4)) if i % 3 == 2: cursor = cursor.move(types.Point(x=-12, y=-4)) pipette_20ul.aspirate(3, location_of_color("Red")) cursor = cursor.move(types.Point(x=4)) dispense_and_detach(pipette_20ul, 3, cursor) pipette_20ul.drop_tip() # Stem pipette_20ul.pick_up_tip() pipette_20ul.aspirate(18, location_of_color("Green")) for i in range(6): cursor = cursor.move(types.Point(y=-4)) dispense_and_detach(pipette_20ul, 3, cursor) # Right leaf pipette_20ul.aspirate(15, location_of_color("Green")) cursor = cursor.move(types.Point(x=4, y=8)) for i in range(5): dispense_and_detach(pipette_20ul, 3, cursor) if i % 2 == 0: cursor = cursor.move(types.Point(y=4)) else: cursor = cursor.move(types.Point(x=4)) # Left leaf pipette_20ul.aspirate(15, location_of_color("Green")) cursor = cursor.move(types.Point(x=-16, y=-12)) for i in range(5): dispense_and_detach(pipette_20ul, 3, cursor) if i % 2 == 0: cursor = cursor.move(types.Point(y=4)) else: cursor = cursor.move(types.Point(x=-4)) pipette_20ul.drop_tip() Results

Subsections of Labs

Week 1 Lab: Pipetting

cover image cover image

Week 2 Lab: DNA Gel Art

Design

design design
Lane 4 will be left empty. EcoRI is listed here for visual purposes.

Restriction Digest Protocol

Digest components

  • X uL NFW to 20 uL
  • 2 uL 10X Promega buffer
  • 1.5 ug DNA
  • 15 units restriction enzyme

Calculations for 10 uL reactions

  • Kampy DNA concentration: 324 ng/uL
    • Use 4.6 uL DNA

BstXI

  • Stock BstXI concentration: 10 u/uL
    • 1.5 uL enzyme
    • 11.9 uL NFW
  • Buffer: Buffer H
  • Temperature: 37C

SfiI

  • Stock SfiI concentration: 10 u/uL
    • 1.5 uL enzyme
    • 11.9 uL NFW
  • Buffer: Buffer B
  • Temperature: 50C

KpnI

  • Stock KpnI concentration: 12 u/uL
    • 1.25 uL enzyme
    • 12.15 uL NFW
  • Buffer: Multicore buffer
  • Temperature: 37C

Gel Protocol

Gel components

  • 0.50 g agarose
  • 50 mL TAE buffer

Running the Gel

  • Sample order: ladder, BstXI, KpnI, BstXI, empty, BstXI, SfiI, BstXI
  • Add 4 uL 6X loading dye to each restriction digest
  • Run 12 uL digest in each well for 40 min at 150V
  • Stain the gel in 100 mL Millipore water and 3 drops of ethidium bromide

Results: Phage!

gel_image gel_image

Week 3 Lab: Opentrons Art

Design

opentrons_flower opentrons_flower

Code

Colab File

from opentrons import types

metadata = {    # see https://docs.opentrons.com/v2/tutorial.html#tutorial-metadata
    'author': 'Heather Qian',
    'protocolName': 'Opentrons Flower',
    'description': 'Makes a red and green flower',
    'source': 'HTGAA 2026 Opentrons Lab',
    'apiLevel': '2.20'
}

##############################################################################
###   Robot deck setup constants - don't change these
##############################################################################

TIP_RACK_DECK_SLOT = 9
COLORS_DECK_SLOT = 6
AGAR_DECK_SLOT = 5
PIPETTE_STARTING_TIP_WELL = 'A1'

well_colors = {
    'A1' : 'Red',
    'B1' : 'Green',
    'C1' : 'Orange'
}


def run(protocol):
  ##############################################################################
  ###   Load labware, modules and pipettes
  ##############################################################################

  # Tips
  tips_20ul = protocol.load_labware('opentrons_96_tiprack_20ul', TIP_RACK_DECK_SLOT, 'Opentrons 20uL Tips')

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

  # Modules
  temperature_module = protocol.load_module('temperature module gen2', COLORS_DECK_SLOT)

  # Temperature Module Plate
  temperature_plate = temperature_module.load_labware('opentrons_96_aluminumblock_generic_pcr_strip_200ul',
                                                      'Cold Plate')
  # Choose where to take the colors from
  color_plate = temperature_plate

  # Agar Plate
  agar_plate = protocol.load_labware('htgaa_agar_plate', AGAR_DECK_SLOT, 'Agar Plate')  ## TA MUST CALIBRATE EACH PLATE!
  # Get the top-center of the plate, make sure the plate was calibrated before running this
  center_location = agar_plate['A1'].top()

  pipette_20ul.starting_tip = tips_20ul.well(PIPETTE_STARTING_TIP_WELL)

  ##############################################################################
  ###   Patterning
  ##############################################################################

  ###
  ### Helper functions for this lab
  ###

  # pass this e.g. 'Red' and get back a Location which can be passed to aspirate()
  def location_of_color(color_string):
    for well,color in well_colors.items():
      if color.lower() == color_string.lower():
        return color_plate[well]
    raise ValueError(f"No well found with color {color_string}")

  # For this lab, instead of calling pipette.dispense(1, loc) use this: dispense_and_detach(pipette, 1, loc)
  def dispense_and_detach(pipette, volume, location):
      """
      Move laterally 5mm above the plate (to avoid smearing a drop); then drop down to the plate,
      dispense, move back up 5mm to detach drop, and stay high to be ready for next lateral move.
      5mm because a 4uL drop is 2mm diameter; and a 2deg tilt in the agar pour is >3mm difference across a plate.
      """
      assert(isinstance(volume, (int, float)))
      above_location = location.move(types.Point(z=location.point.z + 5))  # 5mm above
      pipette.move_to(above_location)       # Go to 5mm above the dispensing location
      pipette.dispense(volume, location)    # Go straight downwards and dispense
      pipette.move_to(above_location)       # Go straight up to detach drop and stay high

  ###
  ### YOUR CODE HERE to create your design
  ###

  # Center
  pipette_20ul.pick_up_tip()
  pipette_20ul.aspirate(18, location_of_color("Green"))

  cursor = center_location.move(types.Point(x=-4, y=15))

  for i in range(9):
    dispense_and_detach(pipette_20ul, 3, cursor)
    if i != 8:
      cursor = cursor.move(types.Point(x=4))
    if i % 3 == 2 and i != 8:
      cursor = cursor.move(types.Point(x=-12, y=-4))
    if i == 5: 
      pipette_20ul.aspirate(9, location_of_color("Green"))

  pipette_20ul.drop_tip()

  # Right petal
  pipette_20ul.pick_up_tip()
  pipette_20ul.aspirate(18, location_of_color("Red"))

  cursor = cursor.move(types.Point(x=4))

  for i in range(6):
    dispense_and_detach(pipette_20ul, 3, cursor)
    cursor = cursor.move(types.Point(y=4))
    if i % 3 == 2:
      cursor = cursor.move(types.Point(x=4, y=-12))

  pipette_20ul.aspirate(3, location_of_color("Red"))
  cursor = cursor.move(types.Point(y=4))
  dispense_and_detach(pipette_20ul, 3, cursor)

  # Top petal
  pipette_20ul.aspirate(18, location_of_color("Red"))

  cursor = cursor.move(types.Point(x=-12, y=8))

  for i in range(6):
    dispense_and_detach(pipette_20ul, 3, cursor)
    cursor = cursor.move(types.Point(x=-4))
    if i % 3 == 2:
      cursor = cursor.move(types.Point(x=12, y=4))

  pipette_20ul.aspirate(3, location_of_color("Red"))
  cursor = cursor.move(types.Point(x=-4))
  dispense_and_detach(pipette_20ul, 3, cursor)

  # Left petal
  pipette_20ul.aspirate(18, location_of_color("Red"))

  cursor = cursor.move(types.Point(x=-8, y=-12))

  for i in range(6):
    dispense_and_detach(pipette_20ul, 3, cursor)
    cursor = cursor.move(types.Point(y=-4))
    if i % 3 == 2:
      cursor = cursor.move(types.Point(x=-4, y=12))

  pipette_20ul.aspirate(3, location_of_color("Red"))
  cursor = cursor.move(types.Point(y=-4))
  dispense_and_detach(pipette_20ul, 3, cursor)

  # Bottom petal
  pipette_20ul.aspirate(18, location_of_color("Red"))

  cursor = cursor.move(types.Point(x=12, y=-8))
  
  for i in range(6):
    dispense_and_detach(pipette_20ul, 3, cursor)
    cursor = cursor.move(types.Point(x=4))
    if i % 3 == 2:
      cursor = cursor.move(types.Point(x=-12, y=-4))

  pipette_20ul.aspirate(3, location_of_color("Red"))
  cursor = cursor.move(types.Point(x=4))
  dispense_and_detach(pipette_20ul, 3, cursor)

  pipette_20ul.drop_tip()

  # Stem
  pipette_20ul.pick_up_tip()
  pipette_20ul.aspirate(18, location_of_color("Green"))
  
  for i in range(6):
    cursor = cursor.move(types.Point(y=-4))
    dispense_and_detach(pipette_20ul, 3, cursor)

  # Right leaf
  pipette_20ul.aspirate(15, location_of_color("Green"))

  cursor = cursor.move(types.Point(x=4, y=8))

  for i in range(5):
    dispense_and_detach(pipette_20ul, 3, cursor)
    if i % 2 == 0:
      cursor = cursor.move(types.Point(y=4))
    else:
      cursor = cursor.move(types.Point(x=4))

  # Left leaf
  pipette_20ul.aspirate(15, location_of_color("Green"))

  cursor = cursor.move(types.Point(x=-16, y=-12))

  for i in range(5):
    dispense_and_detach(pipette_20ul, 3, cursor)
    if i % 2 == 0:
      cursor = cursor.move(types.Point(y=4))
    else:
      cursor = cursor.move(types.Point(x=-4))

  pipette_20ul.drop_tip()

Results

Subsections of Projects

Individual Final Project

cover image cover image

Group Final Project

cover image cover image