skills/pylabrobot/references/visualization.md
Verified against PyLabRobot 0.2.1 on 2026-07-23.
Do not conflate:
None is a robot physics simulator, collision-motion planner, liquid-dynamics model, or physical sensor.
The verified stable import is:
from pylabrobot.liquid_handling import LiquidHandler
from pylabrobot.liquid_handling.backends import LiquidHandlerChatterboxBackend
from pylabrobot.resources.hamilton import STARLetDeck
lh = LiquidHandler(
backend=LiquidHandlerChatterboxBackend(num_channels=8),
deck=STARLetDeck(),
)
await lh.setup()
try:
# Assign resources, seed tracker state, and execute planned calls.
...
finally:
await lh.stop()
setup() above is offline only because the backend is constructed literally as
LiquidHandlerChatterboxBackend. Never replace it from a config string,
environment variable, plugin, or auto-detected device.
The stable docs sometimes use the generic phrase ChatterboxBackend, but the
verified liquid-handler class/import is LiquidHandlerChatterboxBackend.
ChatterBoxBackend (capital B) is a distinct exported legacy-named class.
Current stable usage:
from pylabrobot.visualizer import Visualizer
vis = Visualizer(
resource=lh,
host="127.0.0.1",
ws_port=2121,
fs_port=1337,
open_browser=False,
)
await vis.setup()
try:
# Exercise the software-only liquid handler.
...
finally:
await vis.stop()
Corrections to stale examples:
Visualizer requires a root resource; Visualizer() alone is incomplete.setup() / stop(), not start().lh.visualizer = vis; pass lh as the Visualizer resource.The Visualizer starts two local servers and can open a browser. It therefore
uses localhost networking even when the liquid handler is software-only.
Do not use it where the requirement is "no network." Bind only to loopback,
keep open_browser=False for controlled tests, avoid shared/untrusted hosts,
and stop both services reliably.
The bundled CLIs and tests do not start the Visualizer or any socket.
It:
Resource tree;It does not:
Upstream's contributor guide explicitly describes the browser as passive: it renders messages and does not perform simulation logic.
from pylabrobot.resources import set_tip_tracking, set_volume_tracking
set_tip_tracking(True)
set_volume_tracking(True)
source.get_well("A1").tracker.set_volume(100.0)
Set initial state from a synthetic fixture for tests. For later live work, reconcile planned state with the physical deck; do not infer physical presence from what the browser draws.
Generate a JSON plan without importing PyLabRobot:
python3 skills/pylabrobot/scripts/generate_simulation_plan.py \
--manifest skills/pylabrobot/tests/fixtures/protocol_manifest.json \
--transfers skills/pylabrobot/tests/fixtures/transfers.csv
The output:
PyLabRobot==0.2.1;LiquidHandlerChatterboxBackend;It intentionally produces data, not executable Python.
Use layers of evidence:
Test failures should be deterministic. Do not catch broad errors and continue; do not disable trackers; do not mutate expected state to make a failed assertion pass.
Run bundled tests without bytecode:
PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover \
-s skills/pylabrobot/tests -p "test_*.py" -v
Use /stable/ for pinned 0.2.1 behavior. /dev/ and repository main may
change event payloads, resource serialization, supported devices, or
Visualizer UI. Do not copy development examples into a stable protocol without
installing and testing an actual later stable release.
Checked 2026-07-23:
Visualizer(resource=lh), setup(), and localhost ports.LiquidHandlerChatterboxBackend.v0.2.1 Visualizer source
and chatterbox source
— exact constructor/method verification; tag dated 2026-03-23.