Back to Claude Scientific Skills

Visualization and software-only simulation

skills/pylabrobot/references/visualization.md

2.55.06.5 KB
Original Source

Visualization and software-only simulation

Verified against PyLabRobot 0.2.1 on 2026-07-23.

Three different layers

Do not conflate:

  1. Manifest/ledger planning — the bundled dependency-free CLIs validate bounded JSON/CSV and produce non-executable JSON.
  2. Chatterbox backend — PyLabRobot validates frontend/tracker operations and prints them instead of sending hardware commands.
  3. Visualizer — a browser renderer that receives resource and tracker events over localhost HTTP/WebSocket services.

None is a robot physics simulator, collision-motion planner, liquid-dynamics model, or physical sensor.

Chatterbox backend

The verified stable import is:

python
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.

Visualizer API

Current stable usage:

python
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.
  • Use setup() / stop(), not start().
  • Do not assign lh.visualizer = vis; pass lh as the Visualizer resource.
  • Stable defaults are WebSocket port 2121 and file-server port 1337, not 1234.

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.

What the Visualizer does

It:

  • renders a Resource tree;
  • receives assignment/unassignment callbacks;
  • renders tracker state such as planned tips and volumes;
  • updates as frontend operations change state.

It does not:

  • calculate physical trajectories or clearances;
  • detect an incorrect/missing physical resource, tip, or liquid;
  • model meniscus, viscosity, foam, pressure, carryover, or pipetting error;
  • emulate firmware timing, sensors, interlocks, doors, arms, or failures;
  • validate liquid classes or calibrations;
  • authorize a live run.

Upstream's contributor guide explicitly describes the browser as passive: it renders messages and does not perform simulation logic.

Tracker setup

python
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.

Deterministic no-network plan

Generate a JSON plan without importing PyLabRobot:

bash
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:

  • fixes the target at PyLabRobot==0.2.1;
  • names only LiquidHandlerChatterboxBackend;
  • marks live backends as forbidden;
  • records zero connection attempts and no serial/USB/network access;
  • expands each transfer into tip pickup, aspirate, dispense, and tip disposal;
  • includes final planned volumes, tip counts, limitations, and a mandatory human review checklist.

It intentionally produces data, not executable Python.

Test strategy

Use layers of evidence:

  1. Strict manifest schema validation.
  2. Static deck bounds and axis-aligned overlap screen.
  3. Transfer/dead-volume/destination/tip/channel/rate/height ledger.
  4. Non-executable simulation plan review.
  5. Pinned 0.2.1 import/signature inspection with zero backend instances.
  6. Chatterbox-only protocol smoke with synthetic resources.
  7. Optional Visualizer review on an approved loopback host.
  8. Independent physical commissioning only after explicit operator approval.

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:

bash
PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover \
  -s skills/pylabrobot/tests -p "test_*.py" -v

Stable versus development

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.

Sources

Checked 2026-07-23: