{ "cells": [ { "cell_type": "markdown", "id": "8yvxm6cktvk", "metadata": {}, "source": "# OT-2 Simulator with Visualizer\n\nThis notebook shows how to use the `OpentronsOT2Simulator` backend to test OT-2 protocols offline, with the visualizer for real-time feedback.\n\nSee [the OT-2 hello world notebook](hello-world.ipynb) for using the real hardware." }, { "cell_type": "code", "execution_count": 1, "id": "qml6wch61b", "metadata": {}, "outputs": [], "source": [ "from pylabrobot.liquid_handling import LiquidHandler\n", "from pylabrobot.liquid_handling.backends import OpentronsOT2Simulator\n", "from pylabrobot.resources.opentrons import (\n", " OTDeck,\n", " opentrons_96_filtertiprack_20ul,\n", " opentrons_96_tiprack_300ul,\n", ")\n", "from pylabrobot.resources.celltreat import CellTreat_96_wellplate_350ul_Fb\n", "from pylabrobot.resources import set_tip_tracking, set_volume_tracking\n", "from pylabrobot.visualizer import Visualizer" ] }, { "cell_type": "code", "execution_count": 2, "id": "08rlkxblsvgs", "metadata": {}, "outputs": [], "source": [ "set_tip_tracking(True)\n", "set_volume_tracking(True)" ] }, { "cell_type": "markdown", "id": "09gvm1i32tfj", "metadata": {}, "source": [ "## Set up the simulator and visualizer\n", "\n", "The simulator takes optional pipette names. Defaults are `p300_single_gen2` (left) and `p20_single_gen2` (right)." ] }, { "cell_type": "code", "execution_count": 3, "id": "ij4yhnx4zqq", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-03-12 18:32:17,220 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - OpentronsOT2Simulator setup: left=p300_single_gen2, right=p20_single_gen2\n", "2026-03-12 18:32:17,220 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - Homing (simulated).\n" ] } ], "source": [ "backend = OpentronsOT2Simulator()\n", "deck = OTDeck()\n", "lh = LiquidHandler(backend=backend, deck=deck)\n", "await lh.setup()" ] }, { "cell_type": "code", "execution_count": 4, "id": "h25lkq3p6m4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Websocket server started at http://127.0.0.1:2121\n", "File server started at http://127.0.0.1:1337 . Open this URL in your browser.\n" ] } ], "source": [ "vis = Visualizer(resource=lh)\n", "await vis.setup()" ] }, { "cell_type": "markdown", "id": "iwvn83iixz", "metadata": {}, "source": [ "## Add labware to the deck\n", "\n", "Assign tip racks and a plate. These will appear in the visualizer automatically." ] }, { "cell_type": "code", "execution_count": 5, "id": "2jblokus51v", "metadata": {}, "outputs": [], "source": [ "tip_rack_20 = opentrons_96_filtertiprack_20ul(name=\"tip_rack_20\")\n", "deck.assign_child_at_slot(tip_rack_20, slot=1)\n", "\n", "tip_rack_300 = opentrons_96_tiprack_300ul(name=\"tip_rack_300\")\n", "deck.assign_child_at_slot(tip_rack_300, slot=2)\n", "\n", "plate = CellTreat_96_wellplate_350ul_Fb(name=\"plate\")\n", "deck.assign_child_at_slot(plate, slot=6)" ] }, { "cell_type": "markdown", "id": "k3wy4vevi4", "metadata": {}, "source": [ "## Run a simple protocol\n", "\n", "Pick up a 20 uL tip (right pipette = channel 1), aspirate from well A1, dispense into well B1, and return the tip." ] }, { "cell_type": "code", "execution_count": 6, "id": "vetyk6lxwv", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-03-12 18:32:17,371 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - Picked up tip from tip_rack_20_A1 with pipette sim-right\n" ] } ], "source": [ "await lh.pick_up_tips(tip_rack_20[\"A1\"], use_channels=[1])" ] }, { "cell_type": "code", "execution_count": 7, "id": "t8p5sechijb", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-03-12 18:32:17,377 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - Aspirated 15.00 µL from plate_well_A1\n" ] } ], "source": [ "plate.get_well(\"A1\").tracker.set_volume(200)\n", "await lh.aspirate(plate[\"A1\"], vols=[15], use_channels=[1])" ] }, { "cell_type": "code", "execution_count": 8, "id": "gsplfidciro", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-03-12 18:32:17,384 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - Dispensed 15.00 µL to plate_well_B1\n" ] } ], "source": [ "await lh.dispense(plate[\"B1\"], vols=[15], use_channels=[1])" ] }, { "cell_type": "code", "execution_count": 9, "id": "yhq53lilekm", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-03-12 18:32:17,390 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - Dropped tip to tip_rack_20_A1 with pipette sim-right\n" ] } ], "source": [ "await lh.return_tips()" ] }, { "cell_type": "markdown", "id": "motyoooioj", "metadata": {}, "source": [ "Now try the left pipette (p300) with the 300 uL tip rack." ] }, { "cell_type": "code", "execution_count": 10, "id": "87wafam374a", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-03-12 18:32:17,395 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - Picked up tip from tip_rack_300_A1 with pipette sim-left\n" ] } ], "source": [ "await lh.pick_up_tips(tip_rack_300[\"A1\"])" ] }, { "cell_type": "code", "execution_count": 11, "id": "ddprpyr2o8q", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-03-12 18:32:17,402 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - Aspirated 100.00 µL from plate_well_A1\n", "2026-03-12 18:32:17,404 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - Dispensed 100.00 µL to plate_well_C1\n" ] } ], "source": [ "await lh.aspirate(plate[\"A1\"], vols=[100])\n", "await lh.dispense(plate[\"C1\"], vols=[100])" ] }, { "cell_type": "code", "execution_count": 12, "id": "lgz8dc8jv3n", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-03-12 18:32:17,417 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - Dropped tip to tip_rack_300_A1 with pipette sim-left\n" ] } ], "source": [ "await lh.return_tips()" ] }, { "cell_type": "markdown", "id": "px3gkxjx3kr", "metadata": {}, "source": [ "## Clean up" ] }, { "cell_type": "code", "execution_count": 13, "id": "qt1yijht0z", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-03-12 18:32:17,442 - pylabrobot.liquid_handling.backends.opentrons_simulator - INFO - OpentronsOT2Simulator stopped.\n" ] } ], "source": [ "await vis.stop()\n", "await lh.stop()" ] } ], "metadata": { "kernelspec": { "display_name": "env", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.12" } }, "nbformat": 4, "nbformat_minor": 5 }