week-03-hw-lab-automation
Bioart Using Opentrons
Goal of learning this lesson and doing the OpenTron automation.
- Utilizing different tools to automate different lab work using programmed robots.
- Be able to design, coordinate, code, and print one’s design using OpenTron robots.

Code
CLICK HERE SEE THE CODE USED
from opentrons import types
metadata = { ‘author’: ‘Kaleab’, ‘protocolName’: ‘ADWA’, ‘description’: ‘ADWA in Amharic and English’, ‘source’: ‘HTGAA 2026 Opentrons Lab’, ‘apiLevel’: ‘2.20’ }
Robot deck setup constants
TIP_RACK_DECK_SLOT = 9 COLORS_DECK_SLOT = 6 AGAR_DECK_SLOT = 5 PIPETTE_STARTING_TIP_WELL = ‘A1’
well_colors = { ‘A1’: ‘Red’, # mRFP1 bacteria ‘B1’: ‘Green’, # sfGFP bacteria }
Coordinates for each bacterial color
mRFP1 (Red) points - in mm offset from agar plate center mrfp1_points = [ (-26.4, 17.6), (-28.6, 15.4), (-24.2, 15.4), (30.8, 15.4), (-30.8, 13.2), (-22, 13.2), (-13.2, 13.2), (-11, 13.2), (-8.8, 13.2), (-6.6, 13.2), (-4.4, 13.2), (-2.2, 13.2), (6.6, 13.2), (19.8, 13.2), (28.6, 13.2), (33, 13.2), (-33, 11), (-19.8, 11), (-13.2, 11), (0, 11), (6.6, 11), (13.2, 11), (19.8, 11), (26.4, 11), (35.2, 11), (-35.2, 8.8), (-17.6, 8.8), (-13.2, 8.8), (2.2, 8.8), (6.6, 8.8), (13.2, 8.8), (19.8, 8.8), (24.2, 8.8), (37.4, 8.8), (-35.2, 6.6), (-17.6, 6.6), (-13.2, 6.6), (2.2, 6.6), (6.6, 6.6), (13.2, 6.6), (19.8, 6.6), (24.2, 6.6), (37.4, 6.6), (-35.2, 4.4), (-17.6, 4.4), (-13.2, 4.4), (2.2, 4.4), (6.6, 4.4), (13.2, 4.4), (19.8, 4.4), (24.2, 4.4), (37.4, 4.4), (-35.2, 2.2), (-17.6, 2.2), (-13.2, 2.2), (2.2, 2.2), (6.6, 2.2), (13.2, 2.2), (19.8, 2.2), (24.2, 2.2), (26.4, 2.2), (28.6, 2.2), (30.8, 2.2), (33, 2.2), (35.2, 2.2), (37.4, 2.2), (-35.2, 0), (-33, 0), (-30.8, 0), (-28.6, 0), (-26.4, 0), (-24.2, 0), (-22, 0), (-19.8, 0), (-17.6, 0), (-13.2, 0), (2.2, 0), (6.6, 0), (13.2, 0), (19.8, 0), (24.2, 0), (37.4, 0), (-35.2, -2.2), (-17.6, -2.2), (-13.2, -2.2), (2.2, -2.2), (6.6, -2.2), (13.2, -2.2), (19.8, -2.2), (24.2, -2.2), (37.4, -2.2), (-35.2, -4.4), (-17.6, -4.4), (-13.2, -4.4), (2.2, -4.4), (6.6, -4.4), (13.2, -4.4), (19.8, -4.4), (24.2, -4.4), (37.4, -4.4), (-35.2, -6.6), (-17.6, -6.6), (-13.2, -6.6), (2.2, -6.6), (8.8, -6.6), (13.2, -6.6), (19.8, -6.6), (24.2, -6.6), (37.4, -6.6), (-35.2, -8.8), (-17.6, -8.8), (-13.2, -8.8), (0, -8.8), (11, -8.8), (13.2, -8.8), (15.4, -8.8), (17.6, -8.8), (24.2, -8.8), (37.4, -8.8), (-35.2, -11), (-17.6, -11), (-11, -11), (-8.8, -11), (-6.6, -11), (-4.4, -11), (-2.2, -11) ]
sfGFP (Green) points - in mm offset from agar plate center sfgfp_points = [ (-15.4, 35.2), (-2.2, 35.2), (0, 35.2), (8.8, 35.2), (11, 35.2), (13.2, 35.2), (-17.6, 33), (-2.2, 33), (0, 33), (2.2, 33), (6.6, 33), (11, 33), (15.4, 33), (-17.6, 30.8), (-15.4, 30.8), (-13.2, 30.8), (-11, 30.8), (-8.8, 30.8), (-2.2, 30.8), (0, 30.8), (6.6, 30.8), (11, 30.8), (15.4, 30.8), (-11, 28.6), (-4.4, 28.6), (-2.2, 28.6), (0, 28.6), (2.2, 28.6), (6.6, 28.6), (11, 28.6), (15.4, 28.6), (-13.2, 26.4), (-4.4, 26.4), (2.2, 26.4), (8.8, 26.4), (11, 26.4), (13.2, 26.4), (-15.4, 24.2), (-13.2, 24.2), (-11, 24.2), (-8.8, 24.2), (-4.4, 24.2), (2.2, 24.2), (11, 24.2), (-15.4, 22), (-8.8, 22), (-4.4, 22), (2.2, 22), (11, 22), (-15.4, 19.8), (-8.8, 19.8), (-4.4, 19.8), (2.2, 19.8), (11, 19.8), (-15.4, 17.6), (-8.8, 17.6), (-4.4, 17.6), (2.2, 17.6), (11, 17.6), (-17.6, -15.4), (-15.4, -15.4), (-6.6, -15.4), (-4.4, -15.4), (-2.2, -15.4), (0, -15.4), (8.8, -15.4), (11, -15.4), (13.2, -15.4), (-19.8, -17.6), (-15.4, -17.6), (2.2, -17.6), (6.6, -17.6), (15.4, -17.6), (-15.4, -19.8), (2.2, -19.8), (6.6, -19.8), (15.4, -19.8), (-15.4, -22), (2.2, -22), (6.6, -22), (15.4, -22), (-15.4, -24.2), (-6.6, -24.2), (-4.4, -24.2), (-2.2, -24.2), (0, -24.2), (6.6, -24.2), (15.4, -24.2), (-15.4, -26.4), (2.2, -26.4), (6.6, -26.4), (15.4, -26.4), (-15.4, -28.6), (2.2, -28.6), (6.6, -28.6), (15.4, -28.6), (-19.8, -30.8), (-17.6, -30.8), (-15.4, -30.8), (-13.2, -30.8), (-11, -30.8), (-6.6, -30.8), (-4.4, -30.8), (-2.2, -30.8), (0, -30.8), (2.2, -30.8), (8.8, -30.8), (11, -30.8), (13.2, -30.8) ]
Volume to dispense per dot (uL) DISPENSE_VOLUME = 1
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')
# Get the top-center of the plate (calibration reference point)
center_location = agar_plate['A1'].top()
pipette_20ul.starting_tip = tips_20ul.well(PIPETTE_STARTING_TIP_WELL)
##############################################################################
### Helper functions
##############################################################################
def location_of_color(color_string):
"""Return the well location for a given color name."""
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}")
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.
"""
assert isinstance(volume, (int, float))
above_location = location.move(types.Point(z=5))
pipette.move_to(above_location)
pipette.dispense(volume, location)
pipette.move_to(above_location)
def stamp_color(color_string, points):
"""
Aspirate enough liquid to dispense across all points, then visit each
coordinate and dispense a small dot. Re-aspirate when the tip runs low.
Args:
color_string: 'Red' or 'Green'
points: list of (x, y) tuples in mm offset from plate center
"""
source_well = location_of_color(color_string)
max_volume = 18 # stay below 20uL max, leave headroom
remaining = 0
pipette_20ul.pick_up_tip()
for x_offset, y_offset in points:
# Aspirate a fresh batch if the tip is about to run dry
if remaining < DISPENSE_VOLUME:
# How many dots can we fit in one pickup?
dots_per_fill = int(max_volume // DISPENSE_VOLUME)
aspirate_vol = min(dots_per_fill * DISPENSE_VOLUME, max_volume)
pipette_20ul.aspirate(aspirate_vol, source_well)
remaining = aspirate_vol
# Build the target location: offset (x, y) from center, at plate surface
target_location = center_location.move(types.Point(x=x_offset, y=y_offset, z=0))
dispense_and_detach(pipette_20ul, DISPENSE_VOLUME, target_location)
remaining -= DISPENSE_VOLUME
# Drop tip when done with this color
pipette_20ul.drop_tip()
##############################################################################
### Patterning — stamp each bacterial strain
##############################################################################
# 1. mRFP1 (Red) — Amharic characters
stamp_color('Red', mrfp1_points)
# 2. sfGFP (Green) — English / additional characters
stamp_color('Green', sfgfp_points)
