Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
73bee9e
upgrade Visualizer
BioCam Feb 1, 2026
4b9e507
testing with Rick
BioCam Feb 1, 2026
091348b
Merge branch 'main' into visualizer_update
BioCam Feb 1, 2026
1a6b936
create "Module Section" / liquid handler displaying pipette states
BioCam Feb 2, 2026
c50d2bc
Merge branch 'main' into visualizer_update
BioCam Feb 2, 2026
ac1402a
remove unused variables
rickwierenga Feb 2, 2026
98e37ca
updates to arm tracking
BioCam Feb 2, 2026
1d3bf89
`make format`
BioCam Feb 2, 2026
4ee8d15
selective appearance of lh modules in navbar
BioCam Feb 2, 2026
ef1c67f
remove flickering in navbar
BioCam Feb 2, 2026
b18b80a
update 96-head visual
BioCam Feb 2, 2026
58f33f4
update single-channel popup
BioCam Feb 2, 2026
61f2ff3
prioritize GIF maker
BioCam Feb 2, 2026
ff2d850
create measurement recording inside `Get Location` tool
BioCam Feb 3, 2026
09d6598
make lh module popups responsive and informative
BioCam Feb 3, 2026
6bd4b3b
Merge branch 'main' into visualizer_update
BioCam Feb 3, 2026
2be8ed3
add info panels for resources on double-click in view window
BioCam Feb 3, 2026
cb1a2fe
upgrade Workcell Tree Expand/Collapse behaviour
BioCam Feb 3, 2026
84045e6
Merge branch 'PyLabRobot:main' into visualizer_update
BioCam Feb 3, 2026
8ebee5b
update hover behaviour for file name
BioCam Feb 3, 2026
3311cd8
adjust nomenclature to lh "Acutators"
BioCam Feb 3, 2026
8302e53
automated bullseye scaling
BioCam Feb 3, 2026
a7b632a
functional volume-in-tip visualization
BioCam Feb 3, 2026
a39a167
Merge remote-tracking branch 'origin/main' into visualizer_update
BioCam Feb 3, 2026
93ba563
remove tooltip interference
BioCam Feb 3, 2026
e2942d6
Merge branch 'main' into visualizer_update
BioCam Feb 5, 2026
e30341b
Add multi-arm support, conditional head96, and enriched state seriali…
BioCam Feb 5, 2026
758fbc0
Revert "Add multi-arm support, conditional head96, and enriched state…
BioCam Feb 5, 2026
afe2dfb
Add multi-arm support, conditional head96, and enriched state seriali…
BioCam Feb 5, 2026
20bffc4
Merge branch 'main' into pr/multi-arm-head96
BioCam Feb 6, 2026
0e0912e
Merge branch 'main' into visualizer_update
BioCam Feb 7, 2026
c047daf
Update pylabrobot/resources/tip_tracker.py
BioCam Feb 7, 2026
f905f1e
serialize arm_state, make num_arms property
BioCam Feb 7, 2026
49e9904
Merge branch 'pr/multi-arm-head96' of https://github.com/BioCam/pylab…
BioCam Feb 7, 2026
08aacbf
prepare rename to head96 (future PR for full change)
BioCam Feb 7, 2026
2649b14
return None to installation status start state
BioCam Feb 7, 2026
0c90d06
Merge branch 'main' into pr/multi-arm-head96
BioCam Feb 7, 2026
798063b
fix type checking
BioCam Feb 7, 2026
f2d60c9
clean up core96 usages
BioCam Feb 7, 2026
9456b7a
merge latest version of machine updates
BioCam Feb 7, 2026
4bf01a2
fix type checking
BioCam Feb 7, 2026
812cada
`make format`
BioCam Feb 7, 2026
fef6324
Merge branch 'main' into visualizer_update
BioCam Feb 7, 2026
7fb9d7c
type checking
BioCam Feb 7, 2026
4b39648
linting: remove unused imports
BioCam Feb 7, 2026
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
Binary file added pylabrobot/visualizer/img/integrated_arm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pylabrobot/visualizer/img/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
305 changes: 284 additions & 21 deletions pylabrobot/visualizer/index.html

Large diffs are not rendered by default.

3,627 changes: 3,545 additions & 82 deletions pylabrobot/visualizer/lib.js

Large diffs are not rendered by default.

867 changes: 862 additions & 5 deletions pylabrobot/visualizer/main.css

Large diffs are not rendered by default.

50 changes: 44 additions & 6 deletions pylabrobot/visualizer/vis.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,27 @@ function setRootResource(data) {
resource.location = { x: 0, y: 0, z: 0 };
resource.draw(resourceLayer);

// center the root resource on the stage.
let centerXOffset = (stage.width() - resource.size_x) / 2;
let centerYOffset = (stage.height() - resource.size_y) / 2;
stage.x(centerXOffset);
stage.y(-centerYOffset);
// Store globally so fitToViewport() can use it.
rootResource = resource;

fitToViewport();

buildResourceTree(resource);
}

// Save the full serialized resource data before it is destroyed.
// Called from the resource_unassigned handler while the resource and all its
// children are still intact. The serialized data is later used by buildSingleArm
// to create a live Konva stage using the exact same draw() code as the main canvas.
// Cost: one serialize() call per unassigned resource — negligible.
function snapshotResource(resourceName) {
var res = resources[resourceName];
if (!res) return;
try {
resourceSnapshots[resourceName] = res.serialize();
} catch (e) {
console.warn("[snapshot] failed for " + resourceName, e);
}
}

function removeResource(resourceName) {
Expand All @@ -46,7 +62,15 @@ function setState(allStates) {
for (let resourceName in allStates) {
let state = allStates[resourceName];
let resource = resources[resourceName];
resource.setState(state);
if (!resource) {
console.warn(`[setState] resource not found: ${resourceName}`);
continue;
}
try {
resource.setState(state);
} catch (e) {
console.error(`[setState] error for ${resourceName}:`, e);
}
}
}

Expand All @@ -60,16 +84,30 @@ async function processCentralEvent(event, data) {
resource = loadResource(data.resource);
resource.draw(resourceLayer);
setState(data.state);
addResourceToTree(resource);
break;

case "resource_unassigned":
// Snapshot the resource before destruction so the arm panel can show a
// pixel-perfect replica. Done here (not in destroy()) because the Konva
// group and all children are guaranteed intact at this point.
snapshotResource(data.resource_name);
removeResourceFromTree(data.resource_name);
removeResource(data.resource_name);
break;

case "set_state":
let allStates = data;
setState(allStates);
// Rebuild the sidepanel tree so summaries reflect the updated state
const rootName = Object.keys(resources).find(
(n) => resources[n] && !resources[n].parent
);
if (rootName) buildResourceTree(resources[rootName], { rebuildNavbar: false });
break;

case "show_actuators":
openAllActuatorPanels();
break;

default:
Expand Down
Loading