Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
69305db
Added Nimbus TCP proxy connection and firmware modules. Controls thro…
cmoscy Aug 7, 2025
5195996
Merge remote-tracking branch 'origin/main' into nimbus8
cmoscy Oct 13, 2025
0f84346
Update project configuration and add TCP communication support
cmoscy Oct 16, 2025
01bd4d4
Merge branch 'PyLabRobot:main' into nimbus8
cmoscy Oct 16, 2025
aca49f1
Add TCP Comlink test notebook and validation JSON
cmoscy Oct 16, 2025
9d16f3b
Update TCP communication implementation and add Hamilton protocol sup…
cmoscy Oct 25, 2025
e540a1d
Merge branch 'PyLabRobot:main' into nimbus8
cmoscy Oct 25, 2025
a420023
Hamilton Direct TCP backend
cmoscy Oct 27, 2025
7d1623a
Merge branch 'PyLabRobot:main' into nimbus8
cmoscy Oct 27, 2025
6a36308
Now you can ask the instrument what commands to use!
cmoscy Oct 29, 2025
28d729f
Merge branch 'PyLabRobot:main' into nimbus8
cmoscy Oct 29, 2025
0a39c14
Cleanup example notebook
cmoscy Oct 29, 2025
554f3e5
ignore
cmoscy Oct 29, 2025
5bcec1a
Merge branch 'PyLabRobot:main' into nimbus8
cmoscy Nov 3, 2025
a385890
Remove DLL control features - moved to DLL_CONTROL branch
cmoscy Nov 4, 2025
96a7f67
Refactored Hamilton TCP Backend. Update example notebook.
cmoscy Nov 4, 2025
da5bcca
Merge branch 'PyLabRobot:main' into nimbus8
cmoscy Nov 4, 2025
d4c9067
Log and ignore cleanup
cmoscy Nov 4, 2025
c21a937
Linting/Typing cleanup for PR. Introspection interface now properly d…
cmoscy Nov 5, 2025
32b17fa
Merge branch 'PyLabRobot:main' into nimbus8
cmoscy Nov 5, 2025
221e993
tcp_introspection straggler. Improved return type handling.
cmoscy Nov 5, 2025
344f213
Add Nimbus backend with setup method. Create bare Nimbus deck and uti…
cmoscy Nov 6, 2025
03b1779
Merge branch 'PyLabRobot:main' into nimbus8
cmoscy Nov 6, 2025
33e2b42
Improved setup. Implemented PickupTips and DropTips
cmoscy Nov 8, 2025
c34f7a7
notebook edit
cmoscy Nov 8, 2025
127a503
Merge branch 'PyLabRobot:main' into nimbus8
cmoscy Nov 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 260 additions & 0 deletions nimbus-dev/nimbus_backend_demo.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Nimbus Backend Demo\n",
"\n",
"This notebook demonstrates how to set up and use the Hamilton Nimbus backend with PyLabRobot's `LiquidHandler` interface.\n",
"\n",
"The demo covers:\n",
"1. Creating a `NimbusBackend` instance\n",
"2. Creating a `NimbusDeck` (using defaults or from config files)\n",
"3. Creating a `LiquidHandler` with the backend and deck\n",
"4. Setting up the robot\n",
"5. Parking the pipette\n",
"6. Demonstrating door lock operations (if available)\n",
"7. Closing the connection\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Import necessary modules\n",
"from pylabrobot.liquid_handling import LiquidHandler\n",
"from pylabrobot.liquid_handling.backends.hamilton.nimbus_backend import NimbusBackend\n",
"from pylabrobot.resources.hamilton.nimbus_decks import NimbusDeck\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Deck created: deck\n",
" Size: 831.85 x 424.18 x 300.0 mm\n",
" Rails: 30\n"
]
},
{
"data": {
"text/plain": [
"{'name': 'deck',\n",
" 'type': 'NimbusDeck',\n",
" 'size_x': 831.85,\n",
" 'size_y': 424.18,\n",
" 'size_z': 300.0,\n",
" 'location': {'x': 0, 'y': 0, 'z': 0, 'type': 'Coordinate'},\n",
" 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
" 'category': 'deck',\n",
" 'barcode': None,\n",
" 'children': [],\n",
" 'parent_name': None,\n",
" 'num_rails': 30,\n",
" 'with_trash': False,\n",
" 'with_trash96': False,\n",
" 'hamilton_origin': {'x': -151.51, 'y': -363.83, 'z': 0.0},\n",
" 'y_min': -310.0,\n",
" 'y_max': 20.0,\n",
" 'z_max': 146.0,\n",
" 'rail_start_x': -125.7,\n",
" 'rail_width': 22.454,\n",
" 'rail_y': -360.487}"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Create NimbusBackend instance\n",
"# Replace with your instrument's IP address\n",
"backend = NimbusBackend(\n",
" host=\"192.168.100.100\", # Replace with your instrument's IP\n",
" port=2000,\n",
" read_timeout=30,\n",
" write_timeout=30\n",
")\n",
"\n",
"# Create NimbusDeck using default values (layout 8 dimensions)\n",
"deck = NimbusDeck()\n",
"\n",
"# Alternatively, you can load from config files:\n",
"# deck = NimbusDeck.from_files(\n",
"# cfg_path=\"/path/to/Nimbus8.cfg\",\n",
"# dck_path=\"/path/to/Nimbus8.dck\"\n",
"# )\n",
"\n",
"print(f\"Deck created: {deck.name}\")\n",
"print(f\" Size: {deck.get_size_x()} x {deck.get_size_y()} x {deck.get_size_z()} mm\")\n",
"print(f\" Rails: {deck.num_rails}\")\n",
"deck.serialize()\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"LiquidHandler created successfully\n",
"\n",
"============================================================\n",
"SETUP COMPLETE\n",
"============================================================\n",
"Setup finished: True\n",
"\n",
"Connection Info:\n",
" Client ID: 7\n",
" Client Address: 2:7:65535\n",
"\n",
"Discovered Objects:\n",
" NimbusCore Root: 1:1:48896\n",
" Pipette: 1:1:257\n",
" DoorLock: 1:1:268\n",
"\n",
"Instrument Configuration:\n",
" Number of channels: 4\n"
]
}
],
"source": [
"# Create LiquidHandler with backend and deck\n",
"lh = LiquidHandler(backend=backend, deck=deck)\n",
"\n",
"print(\"LiquidHandler created successfully\")\n",
"\n",
"# Setup the robot\n",
"# This will:\n",
"# - Connect to the instrument via TCP\n",
"# - Discover instrument objects (Pipette, DoorLock, NimbusCore)\n",
"# - Lock the door if available\n",
"# - Pre-initialize the pipette\n",
"# - Query tip presence\n",
"# - Query channel configuration\n",
"# Optionally unlock door after pre-initialization:\n",
"await lh.setup(unlock_door=False)\n",
"\n",
"print(\"\\n\" + \"=\"*60)\n",
"print(\"SETUP COMPLETE\")\n",
"print(\"=\"*60)\n",
"print(f\"Setup finished: {backend.setup_finished}\")\n",
"print(f\"\\nConnection Info:\")\n",
"print(f\" Client ID: {backend._client_id}\")\n",
"print(f\" Client Address: {backend.client_address}\")\n",
"print(f\"\\nDiscovered Objects:\")\n",
"print(f\" NimbusCore Root: {backend._nimbus_core_address}\")\n",
"print(f\" Pipette: {backend._pipette_address}\")\n",
"if backend._door_lock_address is not None:\n",
" print(f\" DoorLock: {backend._door_lock_address}\")\n",
"else:\n",
" print(f\" DoorLock: Not available on this instrument\")\n",
"print(f\"\\nInstrument Configuration:\")\n",
"print(f\" Number of channels: {backend.num_channels}\")\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Pipette parked successfully\n",
"Door is currently: locked\n",
"Door unlocked\n",
"Door is now: unlocked\n"
]
}
],
"source": [
"# Park the pipette channels\n",
"await lh.backend.park()\n",
"\n",
"print(\"Pipette parked successfully\")\n",
"\n",
"# Check if door lock is available and demonstrate operations\n",
"# Check door lock status\n",
"is_locked = await lh.backend.is_door_locked()\n",
"print(f\"Door is currently: {'locked' if is_locked else 'unlocked'}\")\n",
"\n",
"# Unlock the door\n",
"await lh.backend.unlock_door()\n",
"print(\"Door unlocked\")\n",
"\n",
"# Check status again\n",
"is_locked = await lh.backend.is_door_locked()\n",
"print(f\"Door is now: {'locked' if is_locked else 'unlocked'}\")\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING:root:Closing connection to TCP server.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Connection closed successfully\n"
]
}
],
"source": [
"# Stop and close connection\n",
"await lh.stop()\n",
"\n",
"print(\"Connection closed successfully\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"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.10.18"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading