Labs

Lab writeups:

  • Week 1 Lab: Pipetting

    Prelab Dilution Practice 1 Scenario: The stock concentration of a mystery substance (MS) is 5 M. Dilute to 100 µM (0.1 mM) using serial dilutions. 5 M = 5,000,000 µM Step 1: 500× dilution 5,000,000 µM / 10,000 µM = 500

  • Week 2 Lab: DNA Gel Art

    Lab 2 Benchling & In-silico Gel Art: Recap This week, we made gel electrophoresis art using Lambda phage DNA and ten restriction enzymes. Gel electrophoresis uses a positive charge to pull negatively charged DNA through a conductive gel. Longer strands move slower and shorter strands move faster meaning that different lengths of DNA fragments will appear as different bars in your gel. To use this in an artistic context we take our input Lambda DNA and cut it to different lengths using different restriction enzymes which allows us to have coarse control over where these bars end up and thus we can make art with it. I have decided to really commit to my favorite animal, turtles, this semester and try to have a turtle-inspired theme to all of my projects. In an ideal world this is what I wanted my gel art to look like.

  • Week 3 Lab: Lab Opentrons Art

    Lab 3 Lab Recap This week, we programmed the Opentrons liquid handling robot to create fluorescent protein masterpieces. I was really looking forward to this lab and even did last week homework about expressing GFP in E.Coli. Rather than using the GFP, I found we used a variety of different colors of superfluorescent proteins. Ronan’s webtool [1] made it really easy to visualize a design, and we could even upload images to serve as a template for our designs. I decided to go all in on turtles and make a turtles all the way down image featuring a turtle with a globe for its shell. This was the original image, from my collection of Turtle CADS:

Subsections of Labs

Week 1 Lab: Pipetting

cover image

Prelab

Dilution Practice 1

Scenario: The stock concentration of a mystery substance (MS) is 5 M. Dilute to 100 µM (0.1 mM) using serial dilutions.

5 M = 5,000,000 µM

Step 1: 500× dilution

5,000,000 µM / 10,000 µM = 500

This corresponds to a 1:499 dilution.

  • 2 µL stock + 998 µL water = 10,000 µM

Step 2: 100× dilution

10,000 µM / 100 µM = 100

This corresponds to a 1:99 dilution.

  • 10 µL of 10,000 µM + 990 µL water = 100 µM

Dilution Practice 2

Given:

  • Stock concentration = 5 M
  • Molar mass = 532 g/mol

Stock Concentration

5 mol/L × 532 g/mol = 2660 g/L
2660 g/L ÷ 1000 = 2.66 g/mL

Serial dilution plan (5 M to 100 µM)

Overall dilution:

5,000,000 µM / 100 µM = 50,000

Dilution plan:

  • 1:100 to 50,000 µM
  • 1:50 to 1,000 µM
  • 1:10 to 100 µM

This would use 3 dilution steps and the P10, P200, and P1000 pipettes

Final Reaction

Total volume: 60 µL
Final MS concentration: 40 µM

ReagentStock concentrationDesired concentrationVolume (µL)
Loading dye6X1X10
MS100 µM40 µM24
dH₂On/an/a26

Making 100 µM stock makes it easier to pipette and lets you make multiple final concentrations. Making 40 µM directly via serial dilution would require weird dilution ratios and introduce additional error.

Lab

In lab this week, we learned how to use pipettes and the basics of running a gel. It was my first time using a pipette and I quickly realized that my hands were not quite as steady as I wanted them to be. We didn’t follow the lab protocol exactly, it was more about trying all of the different pipettes and learning how they operate. I work with inkjets in my research but I didn’t realize that you could create beautiful tiny droplets by hand as well. Using the P20 I could create droplets only slightly larger than the ones my single-nozzle inkjets create.

My goal was to make a colorful picture in a petri dish similar to the dot paintings with the sequins. I began by using the P1000, but this was much too coarse and oftentimes my dots would bleed into each other, so I switched to a P200 and found I had much more control. I created a couple of abstract pieces whilst getting the hang of the pipettes.

art image

art image

Then we ran a gel and though we’re going more in detail in lab during week 2 it was cool to learn about how to set up a gel and the concept of ladders. I thought that ladders would be absolute, like physical markings on the side of the machine but it’s incredible that ladders are run beside your sample because it’s so context dependent. We also learned that you can recover a specific part of your sample from the gel, but that this is a lot of work compared to other methods. I’m looking forward to learning more about the process in lab next week.

gel image

Sources

AI Prompts -“Help me do math in mark down, make me a markdown math cheat sheet, I’m doing unit conversions and serial dilutions” -“Help me add images in markdown, how to add image in different upstream folder”

Week 2 Lab: DNA Gel Art

cover image

Lab 2

Benchling & In-silico Gel Art: Recap

This week, we made gel electrophoresis art using Lambda phage DNA and ten restriction enzymes. Gel electrophoresis uses a positive charge to pull negatively charged DNA through a conductive gel. Longer strands move slower and shorter strands move faster meaning that different lengths of DNA fragments will appear as different bars in your gel. To use this in an artistic context we take our input Lambda DNA and cut it to different lengths using different restriction enzymes which allows us to have coarse control over where these bars end up and thus we can make art with it. I have decided to really commit to my favorite animal, turtles, this semester and try to have a turtle-inspired theme to all of my projects. In an ideal world this is what I wanted my gel art to look like.

cover image

However, it was really hard to design this with such coarse control, I spent hours on Ronan's website to no avail before eventually deciding on something simpler, my initials: AH.

cover image cover image

Gel Art - Restriction Digests and Gel Electrophoresis

This was my first time making a gel and it was amazing to go through the entire process. I worked with Terry Luo and Sean Murphy, we tried to make an “AH” and ended up with the letters “LU”

cover image

Making gel by mixing 1% agave with conductive liquid (TAE buffer) and DNA stain.

cover image

Pouring gel once cool and inserting comb to create wells and lanes for DNA to travel

cover image cover image

Preparing solutions based on recipe: distilled water + cutsmart buffer + lambda DNA + enzymes

cover image

Putting tubes in incubator

cover image cover image

Preparing final solution for gel: diluting digest with water and adding loading dye

cover image cover image

Loading digest in gel wells, it was really hard to keep my hand steady and not peirce the bottom

cover image

Gel completely set up, starting run

cover image

It only got this far after 45minutes so we ran it as is though more time would've led to more vertical spread

cover image cover image

Viewing results in the transilluminator. It mostly worked but there were a few mistakes. We didn't wait long enough to get a farther vertical spread, and we had some contamination between lanes (likely caused earlier on by forgetting to swap the pipette tip), but overall it was a success. We got "LU" instead of "AH" but this ended up being better because LU stands for love you and it was right before Valentines day.

Week 3 Lab: Lab Opentrons Art

cover image

Lab 3

Lab Recap

This week, we programmed the Opentrons liquid handling robot to create fluorescent protein masterpieces. I was really looking forward to this lab and even did last week homework about expressing GFP in E.Coli. Rather than using the GFP, I found we used a variety of different colors of superfluorescent proteins. Ronan’s webtool [1] made it really easy to visualize a design, and we could even upload images to serve as a template for our designs. I decided to go all in on turtles and make a turtles all the way down image featuring a turtle with a globe for its shell. This was the original image, from my collection of Turtle CADS:

turtle image cad

Once the image was imported, I went to work adjusting it to make my design. I tried to stick to fewer colors just in case we had less than what was on the website, which did not end up being an issue. This is how my image looked in the end:

turtle image pixels

I took the coordinates from this image for each different color and put them into the Colab Python Script. I had to add and change colors to match the ones I used. I originally ran into a problem where I’d tell the robot to fill up the pipette, empty it, then continue attempting to dispense I was able to see this error in the simulation and correct it by adding a loop where, after the pipette was empty (20 dots in my case using a p20 and 1ul droplets) I’d pick up more before continuing. I used the built-in Gemini chatbot to help with this assignment, after explaining the functions I had access to I asked it to use these functions to deposit blue droplets at every coordinate in a list. From there, I used the same functions and procedures to do the rest of my colors. After some troubleshooting, the simulation finally showed me the result I wanted, and the verification also went through. I’ll attach my Python code at the end of this webpage.

colab simulation code

n code:

It was really straightforward to go from my design to the Opentron, at least from my point of view as a student (not sure what magic the TAs and staff work behind the scenes). The machine itself was incredibly precise, not only in movement but also in dispensing.

cover image

Opentrons machine setup for my experiment. All solutions are ready and pipette tips have been moved into position. Gel is set in a 3D printed holder.

cover image

First color dispensing, machine goes back to refill when out of fluid, but this is not because of sensing but instead code we input. It also doesn’t know where the top of the gel is so we calibrated and retuned to find the perfect height to dispense at and the right height to move at to clear the dish walls.

cover image

Before I knew it, the dispensing part was finished, but the cells still needed to be cultured. We dispensed E.Coli capable of producing fluorescent proteins but they still had to incubate overnight so the proteins could be produced

cover image

Here's the final image. And the image of the whole class's work!

cover image

Sources

AI Prompts

  • “Using the functions described in this document, write a loop that deposits blue droplets at every coordinate in a given list”
  • “Use the function to refill the pipette after it’s empty, then continue depositing droplets if there are more droplets than the pipette can hold at once”

Python Code:

from opentrons import types

metadata = {    # see https://docs.opentrons.com/v2/tutorial.html#tutorial-metadata
    'author': 'Alayah Hines',
    'protocolName': 'HGTAA Lab3 Turtle',
    'description': 'Makes a cute turtle',
    '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' : 'darkgreen', #swapped
    'B1' : 'Green',
    'C1' : 'Orange',
    'D1' : 'Cyan', # Added
    'E1' : 'Blue', # Added
    'F1' : 'Yellow'
}


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

  ###
  ### Turtle Code Below
  ###

  # Each tuple is (x_offset_mm, y_offset_mm)
  green_coords = [
      (-34.8, 8.4),(20.4, 8.4),(22.8, 8.4),(25.2, 8.4),(27.6, 8.4),(30, 8.4),(32.4, 8.4),(-34.8, 6),(18, 6),(27.6, 6),(30, 6),(32.4, 6),(34.8, 6),(15.6, 3.6),(18, 3.6),(27.6, 3.6),(30, 3.6),(32.4, 3.6),(34.8, 3.6),(37.2, 3.6),(13.2, 1.2),(15.6, 1.2),(18, 1.2),(27.6, 1.2),(30, 1.2),(32.4, 1.2),(34.8, 1.2),(37.2, 1.2),(13.2, -1.2),(15.6, -1.2),(18, -1.2),(20.4, -1.2),(22.8, -1.2),(25.2, -1.2),(27.6, -1.2),(30, -1.2),(32.4, -1.2),(34.8, -1.2),(37.2, -1.2),(13.2, -3.6),(15.6, -3.6),(18, -3.6),(20.4, -3.6),(22.8, -3.6),(25.2, -3.6),(27.6, -3.6),(30, -3.6),(32.4, -3.6),(34.8, -3.6),(37.2, -3.6),(13.2, -6),(15.6, -6),(18, -6),(20.4, -6),(22.8, -6),(25.2, -6),(27.6, -6),(30, -6),(32.4, -6),(34.8, -6),(-32.4, -8.4),(-32.4, -10.8),(-30, -10.8),(-32.4, -13.2),(-30, -13.2),(-27.6, -13.2),(-25.2, -13.2),(-32.4, -15.6),(-30, -15.6),(-27.6, -15.6),(-25.2, -15.6),(-6, -20.4),(-3.6, -20.4),(-1.2, -20.4),(1.2, -20.4),(3.6, -20.4),(6, -20.4),(-6, -22.8),(-3.6, -22.8),(-1.2, -22.8),(1.2, -22.8),(3.6, -22.8),(6, -22.8),(-6, -25.2),(-3.6, -25.2),(-1.2, -25.2),(1.2, -25.2),(3.6, -25.2),(6, -25.2)
  ]

  # Pick up a tip for green color
  pipette_20ul.pick_up_tip()

  # Dispense each green dot
  for i, (x_offset, y_offset) in enumerate(green_coords):
    if i % 20 == 0:
      # Aspirate 20uL or the remaining number of dispenses, whichever is smaller
      pipette_20ul.aspirate(min(20, len(green_coords) - i), location_of_color('Green'))

    adjusted_location = center_location.move(types.Point(x=x_offset, y=y_offset))
    dispense_and_detach(pipette_20ul, 1, adjusted_location)

  # After all green drops are dispensed, drop the tip
  pipette_20ul.drop_tip()

  # --- End of green ---
  # --- Begin Cyan Patterning ---

  cyan_coords = [
      (-20.4, 30),(-18, 30),(-15.6, 30),(-13.2, 30),(-10.8, 30),(-8.4, 30),(-6, 30),(-3.6, 30),(-1.2, 30),(1.2, 30),(3.6, 30),(6, 30),(8.4, 30),(-22.8, 27.6),(10.8, 27.6),(13.2, 27.6),(-25.2, 25.2),(15.6, 25.2),(-27.6, 22.8),(18, 22.8),(-30, 20.4),(20.4, 20.4),(-32.4, 18),(22.8, 18),(-32.4, 15.6),(22.8, 15.6),(-32.4, 13.2),(22.8, 13.2),(-37.2, 10.8),(-34.8, 10.8),(-32.4, 10.8),(20.4, 10.8),(22.8, 10.8),(25.2, 10.8),(27.6, 10.8),(30, 10.8),(32.4, 10.8),(-37.2, 8.4),(-32.4, 8.4),(18, 8.4),(34.8, 8.4),(-37.2, 6),(-32.4, 6),(15.6, 6),(37.2, 6),(-37.2, 3.6),(-34.8, 3.6),(-32.4, 3.6),(13.2, 3.6),(39.6, 3.6),(-34.8, 1.2),(10.8, 1.2),(39.6, 1.2),(-34.8, -1.2),(-30, -1.2),(10.8, -1.2),(39.6, -1.2),(-34.8, -3.6),(-27.6, -3.6),(10.8, -3.6),(39.6, -3.6),(-34.8, -6),(-32.4, -6),(-25.2, -6),(-22.8, -6),(-20.4, -6),(10.8, -6),(37.2, -6),(-34.8, -8.4),(-30, -8.4),(-18, -8.4),(-15.6, -8.4),(-13.2, -8.4),(-10.8, -8.4),(6, -8.4),(8.4, -8.4),(13.2, -8.4),(15.6, -8.4),(18, -8.4),(20.4, -8.4),(22.8, -8.4),(25.2, -8.4),(27.6, -8.4),(30, -8.4),(32.4, -8.4),(34.8, -8.4),(-34.8, -10.8),(-27.6, -10.8),(-25.2, -10.8),(-8.4, -10.8),(-6, -10.8),(-3.6, -10.8),(-1.2, -10.8),(1.2, -10.8),(3.6, -10.8),(13.2, -10.8),(27.6, -10.8),(-34.8, -13.2),(-22.8, -13.2),(-20.4, -13.2),(13.2, -13.2),(27.6, -13.2),(-34.8, -15.6),(-22.8, -15.6),(-20.4, -15.6),(-18, -15.6),(-15.6, -15.6),(-13.2, -15.6),(-10.8, -15.6),(-8.4, -15.6),(8.4, -15.6),(10.8, -15.6),(13.2, -15.6),(27.6, -15.6),(-32.4, -18),(-30, -18),(-27.6, -18),(-25.2, -18),(-8.4, -18),(-6, -18),(-3.6, -18),(-1.2, -18),(1.2, -18),(3.6, -18),(6, -18),(8.4, -18),(15.6, -18),(18, -18),(20.4, -18),(22.8, -18),(25.2, -18),(-8.4, -20.4),(8.4, -20.4),(-8.4, -22.8),(8.4, -22.8),(-8.4, -25.2),(8.4, -25.2),(-6, -27.6),(-3.6, -27.6),(-1.2, -27.6),(1.2, -27.6),(3.6, -27.6),(6, -27.6)
  ]

  # Pick up a tip for Cyan color
  pipette_20ul.pick_up_tip()

  # Dispense each Cyan dot
  for i, (x_offset, y_offset) in enumerate(cyan_coords):
    if i % 20 == 0:
      # Aspirate 20uL or the remaining number of dispenses, whichever is smaller
      pipette_20ul.aspirate(min(20, len(cyan_coords) - i), location_of_color('Cyan'))

    adjusted_location = center_location.move(types.Point(x=x_offset, y=y_offset))
    dispense_and_detach(pipette_20ul, 1, adjusted_location)

  # After all Cyan drops are dispensed, drop the tip
  pipette_20ul.drop_tip()

  # --- End Cyan Patterning ---
  # --- Begin Blue Patterning ---

  blue_coords =  [
      (-18, 27.6),(-15.6, 27.6),(-13.2, 27.6),(-10.8, 27.6),(-8.4, 27.6),(-6, 27.6),(-3.6, 27.6),(-1.2, 27.6),(1.2, 27.6),(3.6, 27.6),(6, 27.6),(8.4, 27.6),(-18, 25.2),(-15.6, 25.2),(-13.2, 25.2),(-10.8, 25.2),(-8.4, 25.2),(-6, 25.2),(-3.6, 25.2),(-1.2, 25.2),(1.2, 25.2),(3.6, 25.2),(6, 25.2),(8.4, 25.2),(-18, 22.8),(-15.6, 22.8),(-13.2, 22.8),(-10.8, 22.8),(-8.4, 22.8),(-6, 22.8),(-3.6, 22.8),(-1.2, 22.8),(1.2, 22.8),(3.6, 22.8),(6, 22.8),(-18, 20.4),(-15.6, 20.4),(-13.2, 20.4),(-10.8, 20.4),(-8.4, 20.4),(-6, 20.4),(-3.6, 20.4),(-1.2, 20.4),(1.2, 20.4),(3.6, 20.4),(-15.6, 18),(-13.2, 18),(-10.8, 18),(-8.4, 18),(-6, 18),(3.6, 18),(-15.6, 15.6),(-13.2, 15.6),(-10.8, 15.6),(3.6, 15.6),(6, 15.6),(8.4, 15.6),(-30, 13.2),(-27.6, 13.2),(-25.2, 13.2),(-22.8, 13.2),(-20.4, 13.2),(6, 13.2),(8.4, 13.2),(10.8, 13.2),(13.2, 13.2),(-30, 10.8),(-27.6, 10.8),(-25.2, 10.8),(-22.8, 10.8),(-20.4, 10.8),(-18, 10.8),(6, 10.8),(8.4, 10.8),(10.8, 10.8),(13.2, 10.8),(15.6, 10.8),(-30, 8.4),(-27.6, 8.4),(-25.2, 8.4),(-22.8, 8.4),(-20.4, 8.4),(-18, 8.4),(6, 8.4),(8.4, 8.4),(10.8, 8.4),(13.2, 8.4),(15.6, 8.4),(-30, 6),(-27.6, 6),(-25.2, 6),(-22.8, 6),(-20.4, 6),(-18, 6),(-1.2, 6),(1.2, 6),(3.6, 6),(6, 6),(8.4, 6),(10.8, 6),(13.2, 6),(20.4, 6),(22.8, 6),(25.2, 6),(-30, 3.6),(-27.6, 3.6),(-25.2, 3.6),(-22.8, 3.6),(-20.4, 3.6),(-18, 3.6),(-15.6, 3.6),(-3.6, 3.6),(-1.2, 3.6),(1.2, 3.6),(3.6, 3.6),(6, 3.6),(8.4, 3.6),(10.8, 3.6),(20.4, 3.6),(-30, 1.2),(-27.6, 1.2),(-25.2, 1.2),(-22.8, 1.2),(-20.4, 1.2),(-18, 1.2),(-15.6, 1.2),(-3.6, 1.2),(-1.2, 1.2),(1.2, 1.2),(3.6, 1.2),(6, 1.2),(8.4, 1.2),(20.4, 1.2),(-27.6, -1.2),(-25.2, -1.2),(-22.8, -1.2),(-20.4, -1.2),(-18, -1.2),(-15.6, -1.2),(-3.6, -1.2),(-1.2, -1.2),(1.2, -1.2),(3.6, -1.2),(6, -1.2),(8.4, -1.2),(-25.2, -3.6),(-22.8, -3.6),(-20.4, -3.6),(-18, -3.6),(-15.6, -3.6),(-13.2, -3.6),(-3.6, -3.6),(-1.2, -3.6),(1.2, -3.6),(3.6, -3.6),(6, -3.6),(8.4, -3.6),(-18, -6),(-15.6, -6),(-13.2, -6),(-3.6, -6),(-1.2, -6),(1.2, -6),(3.6, -6),(6, -6),(8.4, -6),(-3.6, -8.4),(-1.2, -8.4),(1.2, -8.4),(3.6, -8.4)
  ]

  # Pick up a tip for Blue color
  pipette_20ul.pick_up_tip()

  # Dispense each Blue dot
  for i, (x_offset, y_offset) in enumerate(blue_coords):
    if i % 20 == 0:
      # Aspirate 20uL or the remaining number of dispenses, whichever is smaller
      pipette_20ul.aspirate(min(20, len(blue_coords) - i), location_of_color('Blue'))

    adjusted_location = center_location.move(types.Point(x=x_offset, y=y_offset))
    dispense_and_detach(pipette_20ul, 1, adjusted_location)

  # After all Blue drops are dispensed, drop the tip
  pipette_20ul.drop_tip()

  # --- End Blue Patterning ---
  # --- Begin Dark green Patterning ---

  dark_green_coords =  [
      (-20.4, 27.6),(-22.8, 25.2),(-20.4, 25.2),(10.8, 25.2),(13.2, 25.2),(-25.2, 22.8),(-22.8, 22.8),(-20.4, 22.8),(8.4, 22.8),(10.8, 22.8),(13.2, 22.8),(15.6, 22.8),(-27.6, 20.4),(-25.2, 20.4),(-22.8, 20.4),(-20.4, 20.4),(6, 20.4),(8.4, 20.4),(10.8, 20.4),(13.2, 20.4),(15.6, 20.4),(18, 20.4),(-30, 18),(-27.6, 18),(-25.2, 18),(-22.8, 18),(-20.4, 18),(-18, 18),(-3.6, 18),(-1.2, 18),(1.2, 18),(6, 18),(8.4, 18),(10.8, 18),(13.2, 18),(15.6, 18),(18, 18),(20.4, 18),(-30, 15.6),(-27.6, 15.6),(-25.2, 15.6),(-22.8, 15.6),(-20.4, 15.6),(-18, 15.6),(-8.4, 15.6),(-6, 15.6),(-3.6, 15.6),(-1.2, 15.6),(1.2, 15.6),(10.8, 15.6),(13.2, 15.6),(15.6, 15.6),(18, 15.6),(20.4, 15.6),(-18, 13.2),(-15.6, 13.2),(-13.2, 13.2),(-10.8, 13.2),(-8.4, 13.2),(-6, 13.2),(-3.6, 13.2),(-1.2, 13.2),(1.2, 13.2),(3.6, 13.2),(15.6, 13.2),(18, 13.2),(20.4, 13.2),(-15.6, 10.8),(-13.2, 10.8),(-10.8, 10.8),(-8.4, 10.8),(-6, 10.8),(-3.6, 10.8),(-1.2, 10.8),(1.2, 10.8),(3.6, 10.8),(18, 10.8),(-15.6, 8.4),(-13.2, 8.4),(-10.8, 8.4),(-8.4, 8.4),(-6, 8.4),(-3.6, 8.4),(-1.2, 8.4),(1.2, 8.4),(3.6, 8.4),(-15.6, 6),(-13.2, 6),(-10.8, 6),(-8.4, 6),(-6, 6),(-3.6, 6),(-13.2, 3.6),(-10.8, 3.6),(-8.4, 3.6),(-6, 3.6),(-13.2, 1.2),(-10.8, 1.2),(-8.4, 1.2),(-6, 1.2),(-13.2, -1.2),(-10.8, -1.2),(-8.4, -1.2),(-6, -1.2),(-10.8, -3.6),(-8.4, -3.6),(-6, -3.6),(-10.8, -6),(-8.4, -6),(-6, -6),(-8.4, -8.4),(-6, -8.4),(15.6, -10.8),(18, -10.8),(20.4, -10.8),(22.8, -10.8),(25.2, -10.8),(15.6, -13.2),(18, -13.2),(20.4, -13.2),(22.8, -13.2),(25.2, -13.2),(15.6, -15.6),(18, -15.6),(20.4, -15.6),(22.8, -15.6),(25.2, -15.6)
  ]

  # Pick up a tip for Dark green color
  pipette_20ul.pick_up_tip()

  # Dispense each Dark Green dot
  for i, (x_offset, y_offset) in enumerate(dark_green_coords):
    if i % 20 == 0:
      # Aspirate 20uL or the remaining number of dispenses, whichever is smaller
      pipette_20ul.aspirate(min(20, len(dark_green_coords) - i), location_of_color('darkgreen'))

    adjusted_location = center_location.move(types.Point(x=x_offset, y=y_offset))
    dispense_and_detach(pipette_20ul, 1, adjusted_location)

  # After all Dark Green drops are dispensed, drop the tip
  pipette_20ul.drop_tip()
  # --- End Dark Green Patterning ---
  # --- Begin Yellow Patterning  ---

  yellow_points = [
      (22.8, 3.6),(25.2, 3.6),(-32.4, 1.2),(22.8, 1.2),(25.2, 1.2),(-32.4, -1.2),(-32.4, -3.6),(-30, -3.6),(-30, -6),(-27.6, -6),(-27.6, -8.4),(-25.2, -8.4),(-22.8, -8.4),(-20.4, -8.4),(10.8, -8.4),(-22.8, -10.8),(-20.4, -10.8),(-18, -10.8),(-15.6, -10.8),(-13.2, -10.8),(-10.8, -10.8),(6, -10.8),(8.4, -10.8),(10.8, -10.8),(-18, -13.2),(-15.6, -13.2),(-13.2, -13.2),(-10.8, -13.2),(-8.4, -13.2),(-6, -13.2),(-3.6, -13.2),(-1.2, -13.2),(1.2, -13.2),(3.6, -13.2),(6, -13.2),(8.4, -13.2),(10.8, -13.2),(-6, -15.6),(-3.6, -15.6),(-1.2, -15.6),(1.2, -15.6),(3.6, -15.6),(6, -15.6)
  ]

  # Pick up a tip for Yellow color
  pipette_20ul.pick_up_tip()

  # Dispense each Yellow dot
  for i, (x_offset, y_offset) in enumerate(yellow_points):
    if i % 20 == 0:
      # Aspirate 20uL or the remaining number of dispenses, whichever is smaller
      pipette_20ul.aspirate(min(20, len(yellow_points) - i), location_of_color('Yellow'))

    adjusted_location = center_location.move(types.Point(x=x_offset, y=y_offset))
    dispense_and_detach(pipette_20ul, 1, adjusted_location)

  # After all Yellow drops are dispensed, drop the tip
  pipette_20ul.drop_tip()

  # --- End Yellow Patterning (yellow_points) ---

  # Don't forget to end with a drop_tip()