Opentrons Coding

I designed my pattern using the open interface: https://opentrons-art.rcdonovan.com/

image.png

From there, I received the coordinates:

red_points =

| • (-30, 0) • (-20, -20) • (-20, 20) • (0, 0) • (0, -30) • (0, 30) • (20, -20) • (20, 20) • (30, 0) | | --- |

green_points =

(-5, 35),(5, 35),(-10, 30),(10, 30),(-5, 25),(0, 25),(5, 25),(0, 20),(-5, 15),(5, 15),(-30, 10),(-10, 10),(10, 10),(30, 10),(-35, 5),(-25, 5),(-15, 5),(15, 5),(25, 5),(35, 5),(-25, 0),(-20, 0),(20, 0),(25, 0),(-35, -5),(-25, -5),(-15, -5),(15, -5),(25, -5),(35, -5),(-30, -10),(-10, -10),(10, -10),(30, -10),(-5, -15),(5, -15),(0, -20),(-5, -25),(0, -25),(5, -25),(-10, -30),(10, -30),(-5, -35),(5, -35)

orange_points =

| • (-20, 25) • (20, 25) • (-25, 20) • (-15, 20) • (15, 20) • (25, 20) • (-20, 15) • (20, 15) • (-20, -15) • (20, -15) • (-25, -20) • (-15, -20) • (15, -20) • (25, -20) • (-20, -25)

• (20, -25)

I edited the code using the Opentrons Colab link, using the previous examples as a guidance: https://colab.research.google.com/drive/1q7i-xHfolH0f1fnmLg8R8uREdT4w6JQy?usp=sharing

Final Code:

from opentrons import types

metadata = {    # see <https://docs.opentrons.com/v2/tutorial.html#tutorial-metadata>
    'author': 'Divya Srinivasan',
    'protocolName': 'Kolam',
    'description': 'Symmetrical Dot Pattern',
    'source': 'HTGAA 2025 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_jog(pipette, 1, loc)
  def dispense_and_jog(pipette, volume, location):
      """
      Dispense and then move up 5mm to ensure the pipette is not moving laterally before the dispensing is done.
      """
      assert(isinstance(volume, (int, float)))
      pipette.dispense(volume, location)
      currLoc = pipette._get_last_location_by_api_version()
      pipette.move_to(currLoc.move(types.Point(z=5)))

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

  red_points = [(0, 30), (-20, 20), (20, 20), (-30, 0), (0, 0), (30, 0), (-20, -20), (20, -20), (0, -30)]
  green_points = [(i, j) for i, j in zip(
        [-5, 5, -10, 10, -5, 0, 5, 0, -5, 5, -30, -10, 10, 30, -35, -25, -15, 15, 25, 35, -25, -20, 20, 25, -35, -25, -15, 15, 25, 35, -30, -10, 10, 30, -5, 5, 0, -5, 0, 5, -10, 10, -5, 5],
        [35, 35, 30, 30, 25, 25, 25, 20, 15, 15, 10, 10, 10, 10, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, -5, -5, -5, -5, -5, -5, -10, -10, -10, -10, -15, -15, -20, -25, -25, -25, -30, -30, -35, -35])]
  orange_points = [(-20, 25), (20, 25), (-25, 20), (-15, 20), (15, 20), (25, 20), (-20, 15), (20, 15), (0, 5),
                     (-5, 0), (5, 0), (0, -5), (-20, -15), (20, -15), (-25, -20), (-15, -20), (15, -20), (25, -20),
                     (-20, -25), (20, -25)]

  #Dispense Red Dots
  pipette_20ul.pick_up_tip()

  pipette_20ul.aspirate(9, location_of_color('Red'))
  for points in [red_points]:
        for x, y in points:
            dispense_and_jog(pipette_20ul, 1, center_location.move(types.Point(x=x, y=y)))

  pipette_20ul.drop_tip()
   
  #Dispense Green Dots
  pipette_20ul.pick_up_tip()

  Count = 0
  pipette_20ul.aspirate(15, location_of_color('Green')) 

  for points in [green_points]:
        for x, y in points:
            if Count < 15:
              dispense_and_jog(pipette_20ul, 1, center_location.move(types.Point(x=x, y=y)))
              Count += 1
            if Count == 15:
              pipette_20ul.aspirate(15, location_of_color('Green'))
              Count = 0

  pipette_20ul.drop_tip()
  
  #Dispense Orange Dots
  pipette_20ul.pick_up_tip()

  pipette_20ul.aspirate(20, location_of_color('Orange'))
  for points in [orange_points]:
        for x, y in points:
            dispense_and_jog(pipette_20ul, 1, center_location.move(types.Point(x=x, y=y)))

  pipette_20ul.drop_tip()

  # Don't forget to end with a drop_tip()
# Execute Simulation / Visualization -- don't change this code block
protocol = OpentronsMock(well_colors)
run(protocol)
protocol.visualize()

Final Output

=== VOLUME TOTALS BY COLOR ===
	Green:		 aspirated 45	 dispensed 44		##### WASTING BIO-INK : more aspirated than dispensed!
	Red:		 aspirated 9	 dispensed 9
	Orange:		 aspirated 20	 dispensed 20
	[all colors]:	[aspirated 74]	[dispensed 73]

=== TIP COUNT ===
	 Used 3 tip(s)  (ideally exactly one per unique color)

image.png

Post Lab Questions