# Using the simulator#

In this notebook you will learn how to use the simulator to test out methods.

## Setting up a connection with the robot#

As described in the basic liquid handling tutorial, we will use the LiquidHandler class to control the robot. This time, however, instead of using the Hamilton STAR backend, we are using virtual the SimulatorBackend backend. This means that liquid handling will work exactly the same, but the commands are sent to the simulator instead of a real physical robot.

%load_ext autoreload

from pylabrobot.liquid_handling import LiquidHandler
from pylabrobot.liquid_handling.backends.simulation.simulator_backend import SimulatorBackend

from pylabrobot.resources.hamilton import STARLetDeck

from pylabrobot.resources import (
TIP_CAR_480_A00,
PLT_CAR_L5AC_A00,
Cos_96_DW_1mL,
STF_L
)

sb = SimulatorBackend(open_browser=False)
lh = LiquidHandler(backend=sb, deck=STARLetDeck())


Calling setup() will set up the simulation server and open it in a new browser tab.

await lh.setup()

Websocket server started at http://127.0.0.1:2121
File server started at http://127.0.0.1:1337 . Open this URL in your browser.


For the optimal experience, we recommend that you run the notebook and simulator side by side.

sb.wait_for_connection()


## Assigning plates and tips#

With the simulator, assigning resources has the additional affect of placing the resources on the simulated deck. They will appear immediately.

from pylabrobot.resources import (
TIP_CAR_480_A00,
PLT_CAR_L5AC_A00,
Cos_96_DW_1mL,
HTF_L
)

tip_car = TIP_CAR_480_A00(name='tip carrier')
tip_car[0] = tips = HTF_L(name='tips_01')
tip_car[1] = HTF_L(name='tips_02')
tip_car[2] = HTF_L(name='tips_03')
tip_car[3] = HTF_L(name='tips_04')
tip_car[4] = HTF_L(name='tips_05')

lh.deck.assign_child_resource(tip_car, rails=15)

plt_car = PLT_CAR_L5AC_A00(name='plate carrier')
plt_car[0] = plate = Cos_96_DW_1mL(name='plate_01')
plt_car[1] = Cos_96_DW_1mL(name='plate_02')
plt_car[2] = Cos_96_DW_1mL(name='plate_03')

lh.deck.assign_child_resource(plt_car, rails=8)


## Build the deck layout: placing resources#

Where you would manually place the resources like tips and liquid on the deck when using a physical system, with the Simulator you can add them using code.

### Tips#

Let’s use fill_tip_rack() to place tips at all spots in the tip rack in location 0.

tiprack = lh.get_resource("tips_01")
tiprack

TipRack(name=tips_01, size_x=122.4, size_y=82.6, size_z=20.0, location=(000.000, 000.000, 000.000))

await sb.fill_tip_rack(tiprack)


You can precisely control the presence of tips using edit_tips().

tips4 = lh.get_resource("tips_04")
await sb.edit_tips(tips4, pattern=[[True]*6 + [False]*6]*8)

await sb.edit_tips(lh.get_resource("tips_03"), pattern=[[True, False]*6]*8)

await sb.edit_tips(lh.get_resource("tips_02"), pattern=[[True, True, False, False]*3]*8)


### Liquids#

pylabrobot.liquid_handling.backends.simulation.simulator_backend Adding liquid to wells works similarly. You can use adjust_well_volume() to adjust the volume of individual wells in each resource. Note that the opacity of the well matches the volume of the well.

plate_1 = lh.get_resource("plate_01")
plate_2 = lh.get_resource("plate_02")

await sb.adjust_well_volume(plate_1, pattern=[[500]*12]*8)

await sb.adjust_well_volume(plate_2, pattern=[[100, 500]*6]*8)


Using the simulator backend we have adjusted the volume in the simulator, which you can best compare to adding liquid in reality. Now we need to tell PyLabRobot how much volume is in the wells, so that it can validate your actions. This is done using set_well_volumes(). Note that this can be done in all liquid handling protocols, not just the simulator.

await plate_1.set_well_volumes([[500]*12]*8)
await plate_2.set_well_volumes([[100, 500]*6]*8)


## Liquid handling#

Once the layout is complete, you can run the same commands as described in the basic liquid handling tutorial.

### Picking up tips#

tip_0 = lh.get_resource("tips_01")

await lh.pick_up_tips(tip_0["A1", "B2", "C3", "D4"])

await lh.drop_tips(tip_0["A1", "B2", "C3", "D4"])


### Aspirating and dispensing#

await lh.pick_up_tips(tip_0["A1"])

plate = lh.get_resource("plate_01")

await lh.aspirate(plate["A2"], vols=[300])

await lh.dispense(plate_2["A1"], vols=[300])

await lh.drop_tips(tip_0["A1"])


### Aspirating using CoRe 96#

The CoRe 96 head supports liquid handling operations for 96 channels at once. Here’s how to use:

await lh.pick_up_tips96(tiprack)

await lh.aspirate_plate(plt_car[0].resource, volume=200)

await lh.dispense_plate(plt_car[2].resource, volume=200)

await (tip_car[0].resource)


## Shutting down#

When you’re done, remember to shut down the simulator by calling stop().

await lh.stop()