diff --git a/.gitignore b/.gitignore
index e2c2063..f915811 100644
--- a/.gitignore
+++ b/.gitignore
@@ -232,4 +232,5 @@ CATKIN_IGNORE
/**/local_config.py
-*.graphml
\ No newline at end of file
+*.graphml
+unilabos/device_mesh/view_robot.rviz
diff --git a/README.md b/README.md
index c10ed4e..3435276 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,11 @@
[](https://github.com/dptech-corp/Uni-Lab-OS/issues)
[](https://github.com/dptech-corp/Uni-Lab-OS/blob/main/LICENSE)
-Uni-Lab Operating System is a platform for laboratory automation, designed to connect and control various experimental equipment, enabling automation and standardization of experimental workflows.
+Uni-Lab-OS is a platform for laboratory automation, designed to connect and control various experimental equipment, enabling automation and standardization of experimental workflows.
+
+## 🏆 Competition
+
+Join the [Intelligent Organic Chemistry Synthesis Competition](https://bohrium.dp.tech/competitions/1451645258) to explore automated synthesis with Uni-Lab-OS!
## Key Features
@@ -45,7 +49,7 @@ conda env update --file unilabos-[YOUR_OS].yml -n environment_name
# Currently, you need to install the `unilabos_msgs` package
# You can download the system-specific package from the Release page
-conda install ros-humble-unilabos-msgs-0.9.1-xxxxx.tar.bz2
+conda install ros-humble-unilabos-msgs-0.9.4-xxxxx.tar.bz2
# Install PyLabRobot and other prerequisites
git clone https://github.com/PyLabRobot/pylabrobot plr_repo
diff --git a/README_zh.md b/README_zh.md
index b0b7b30..4f3607d 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -12,7 +12,11 @@
[](https://github.com/dptech-corp/Uni-Lab-OS/issues)
[](https://github.com/dptech-corp/Uni-Lab-OS/blob/main/LICENSE)
-Uni-Lab 操作系统是一个用于实验室自动化的综合平台,旨在连接和控制各种实验设备,实现实验流程的自动化和标准化。
+Uni-Lab-OS是一个用于实验室自动化的综合平台,旨在连接和控制各种实验设备,实现实验流程的自动化和标准化。
+
+## 🏆 比赛
+
+欢迎参加[有机化学合成智能实验大赛](https://bohrium.dp.tech/competitions/1451645258),使用 Uni-Lab-OS 探索自动化合成!
## 核心特点
@@ -45,7 +49,7 @@ conda env update --file unilabos-[YOUR_OS].yml -n 环境名
# 现阶段,需要安装 `unilabos_msgs` 包
# 可以前往 Release 页面下载系统对应的包进行安装
-conda install ros-humble-unilabos-msgs-0.9.1-xxxxx.tar.bz2
+conda install ros-humble-unilabos-msgs-0.9.4-xxxxx.tar.bz2
# 安装PyLabRobot等前置
git clone https://github.com/PyLabRobot/pylabrobot plr_repo
diff --git a/recipes/ros-humble-unilabos-msgs/recipe.yaml b/recipes/ros-humble-unilabos-msgs/recipe.yaml
index 2ee7f1f..febca42 100644
--- a/recipes/ros-humble-unilabos-msgs/recipe.yaml
+++ b/recipes/ros-humble-unilabos-msgs/recipe.yaml
@@ -1,6 +1,6 @@
package:
name: ros-humble-unilabos-msgs
- version: 0.9.1
+ version: 0.9.4
source:
path: ../../unilabos_msgs
folder: ros-humble-unilabos-msgs/src/work
diff --git a/recipes/unilabos/recipe.yaml b/recipes/unilabos/recipe.yaml
index 5b03630..51ddea1 100644
--- a/recipes/unilabos/recipe.yaml
+++ b/recipes/unilabos/recipe.yaml
@@ -1,6 +1,6 @@
package:
name: unilabos
- version: "0.9.1"
+ version: "0.9.4"
source:
path: ../..
diff --git a/setup.cfg b/setup.cfg
index e152926..5197889 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,4 +1,2 @@
-[develop]
-script_dir=$base/lib/unilabos
[install]
install_scripts=$base/lib/unilabos
diff --git a/setup.py b/setup.py
index 847098a..038d820 100644
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,7 @@ package_name = 'unilabos'
setup(
name=package_name,
- version='0.9.1',
+ version='0.9.4',
packages=find_packages(),
include_package_data=True,
install_requires=['setuptools'],
diff --git a/test/experiments/biomek.json b/test/experiments/biomek.json
new file mode 100644
index 0000000..604adcc
--- /dev/null
+++ b/test/experiments/biomek.json
@@ -0,0 +1,22 @@
+{
+ "nodes": [
+ {
+ "id": "BIOMEK",
+ "name": "BIOMEK",
+ "parent": null,
+ "type": "device",
+ "class": "liquid_handler.biomek",
+ "position": {
+ "x": 620.6111111111111,
+ "y": 171,
+ "z": 0
+ },
+ "config": {
+ },
+ "data": {},
+ "children": [
+ ]
+ }
+ ],
+ "links": []
+}
\ No newline at end of file
diff --git a/test/experiments/plr_test_converted.json b/test/experiments/plr_test_converted.json
index 533d99c..6b5cae4 100644
--- a/test/experiments/plr_test_converted.json
+++ b/test/experiments/plr_test_converted.json
@@ -47,6 +47,9 @@
},
"config": {
"type": "OTDeck",
+ "size_x": 624.3,
+ "size_y": 565.2,
+ "size_z": 900,
"with_trash": false,
"rotation": {
"x": 0,
@@ -163,7 +166,7 @@
"type": "plate",
"class": "opentrons_96_filtertiprack_1000ul",
"position": {
- "x": 0,
+ "x": 265.0,
"y": 0,
"z": 69
},
@@ -281,6 +284,10 @@
},
"data": {}
},
+
+
+
+
{
"id": "tip_rack_A1",
"name": "tip_rack_A1",
@@ -290,14 +297,14 @@
"type": "device",
"class": "",
"position": {
- "x": 7.2,
- "y": 68.3,
+ "x": 11.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -309,19 +316,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -330,10 +337,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -346,14 +353,14 @@
"type": "device",
"class": "",
"position": {
- "x": 7.2,
- "y": 59.3,
+ "x": 11.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -365,19 +372,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -386,10 +393,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -402,14 +409,14 @@
"type": "device",
"class": "",
"position": {
- "x": 7.2,
- "y": 50.3,
+ "x": 11.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -421,19 +428,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -442,10 +449,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -458,14 +465,14 @@
"type": "device",
"class": "",
"position": {
- "x": 7.2,
- "y": 41.3,
+ "x": 11.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -477,19 +484,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -498,10 +505,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -514,14 +521,14 @@
"type": "device",
"class": "",
"position": {
- "x": 7.2,
- "y": 32.3,
+ "x": 11.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -533,19 +540,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -554,10 +561,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -570,14 +577,14 @@
"type": "device",
"class": "",
"position": {
- "x": 7.2,
- "y": 23.3,
+ "x": 11.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -589,19 +596,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -610,10 +617,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -626,14 +633,14 @@
"type": "device",
"class": "",
"position": {
- "x": 7.2,
- "y": 14.3,
+ "x": 11.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -645,19 +652,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -666,10 +673,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -682,14 +689,14 @@
"type": "device",
"class": "",
"position": {
- "x": 7.2,
- "y": 5.3,
+ "x": 11.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -701,19 +708,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -722,10 +729,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -738,14 +745,14 @@
"type": "device",
"class": "",
"position": {
- "x": 16.2,
- "y": 68.3,
+ "x": 20.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -757,19 +764,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -778,10 +785,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -794,14 +801,14 @@
"type": "device",
"class": "",
"position": {
- "x": 16.2,
- "y": 59.3,
+ "x": 20.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -813,19 +820,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -834,10 +841,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -850,14 +857,14 @@
"type": "device",
"class": "",
"position": {
- "x": 16.2,
- "y": 50.3,
+ "x": 20.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -869,19 +876,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -890,10 +897,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -906,14 +913,14 @@
"type": "device",
"class": "",
"position": {
- "x": 16.2,
- "y": 41.3,
+ "x": 20.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -925,19 +932,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -946,10 +953,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -962,14 +969,14 @@
"type": "device",
"class": "",
"position": {
- "x": 16.2,
- "y": 32.3,
+ "x": 20.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -981,19 +988,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1002,10 +1009,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1018,14 +1025,14 @@
"type": "device",
"class": "",
"position": {
- "x": 16.2,
- "y": 23.3,
+ "x": 20.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1037,19 +1044,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1058,10 +1065,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1074,14 +1081,14 @@
"type": "device",
"class": "",
"position": {
- "x": 16.2,
- "y": 14.3,
+ "x": 20.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1093,19 +1100,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1114,10 +1121,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1130,14 +1137,14 @@
"type": "device",
"class": "",
"position": {
- "x": 16.2,
- "y": 5.3,
+ "x": 20.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1149,19 +1156,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1170,10 +1177,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1186,14 +1193,14 @@
"type": "device",
"class": "",
"position": {
- "x": 25.2,
- "y": 68.3,
+ "x": 29.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1205,19 +1212,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1226,10 +1233,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1242,14 +1249,14 @@
"type": "device",
"class": "",
"position": {
- "x": 25.2,
- "y": 59.3,
+ "x": 29.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1261,19 +1268,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1282,10 +1289,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1298,14 +1305,14 @@
"type": "device",
"class": "",
"position": {
- "x": 25.2,
- "y": 50.3,
+ "x": 29.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1317,19 +1324,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1338,10 +1345,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1354,14 +1361,14 @@
"type": "device",
"class": "",
"position": {
- "x": 25.2,
- "y": 41.3,
+ "x": 29.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1373,19 +1380,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1394,10 +1401,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1410,14 +1417,14 @@
"type": "device",
"class": "",
"position": {
- "x": 25.2,
- "y": 32.3,
+ "x": 29.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1429,19 +1436,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1450,10 +1457,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1466,14 +1473,14 @@
"type": "device",
"class": "",
"position": {
- "x": 25.2,
- "y": 23.3,
+ "x": 29.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1485,19 +1492,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1506,10 +1513,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1522,14 +1529,14 @@
"type": "device",
"class": "",
"position": {
- "x": 25.2,
- "y": 14.3,
+ "x": 29.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1541,19 +1548,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1562,10 +1569,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1578,14 +1585,14 @@
"type": "device",
"class": "",
"position": {
- "x": 25.2,
- "y": 5.3,
+ "x": 29.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1597,19 +1604,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1618,10 +1625,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1634,14 +1641,14 @@
"type": "device",
"class": "",
"position": {
- "x": 34.2,
- "y": 68.3,
+ "x": 38.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1653,19 +1660,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1674,10 +1681,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1690,14 +1697,14 @@
"type": "device",
"class": "",
"position": {
- "x": 34.2,
- "y": 59.3,
+ "x": 38.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1709,19 +1716,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1730,10 +1737,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1746,14 +1753,14 @@
"type": "device",
"class": "",
"position": {
- "x": 34.2,
- "y": 50.3,
+ "x": 38.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1765,19 +1772,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1786,10 +1793,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1802,14 +1809,14 @@
"type": "device",
"class": "",
"position": {
- "x": 34.2,
- "y": 41.3,
+ "x": 38.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1821,19 +1828,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1842,10 +1849,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1858,14 +1865,14 @@
"type": "device",
"class": "",
"position": {
- "x": 34.2,
- "y": 32.3,
+ "x": 38.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1877,19 +1884,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1898,10 +1905,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1914,14 +1921,14 @@
"type": "device",
"class": "",
"position": {
- "x": 34.2,
- "y": 23.3,
+ "x": 38.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1933,19 +1940,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -1954,10 +1961,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -1970,14 +1977,14 @@
"type": "device",
"class": "",
"position": {
- "x": 34.2,
- "y": 14.3,
+ "x": 38.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -1989,19 +1996,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2010,10 +2017,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2026,14 +2033,14 @@
"type": "device",
"class": "",
"position": {
- "x": 34.2,
- "y": 5.3,
+ "x": 38.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2045,19 +2052,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2066,10 +2073,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2082,14 +2089,14 @@
"type": "device",
"class": "",
"position": {
- "x": 43.2,
- "y": 68.3,
+ "x": 47.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2101,19 +2108,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2122,10 +2129,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2138,14 +2145,14 @@
"type": "device",
"class": "",
"position": {
- "x": 43.2,
- "y": 59.3,
+ "x": 47.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2157,19 +2164,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2178,10 +2185,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2194,14 +2201,14 @@
"type": "device",
"class": "",
"position": {
- "x": 43.2,
- "y": 50.3,
+ "x": 47.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2213,19 +2220,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2234,10 +2241,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2250,14 +2257,14 @@
"type": "device",
"class": "",
"position": {
- "x": 43.2,
- "y": 41.3,
+ "x": 47.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2269,19 +2276,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2290,10 +2297,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2306,14 +2313,14 @@
"type": "device",
"class": "",
"position": {
- "x": 43.2,
- "y": 32.3,
+ "x": 47.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2325,19 +2332,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2346,10 +2353,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2362,14 +2369,14 @@
"type": "device",
"class": "",
"position": {
- "x": 43.2,
- "y": 23.3,
+ "x": 47.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2381,19 +2388,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2402,10 +2409,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2418,14 +2425,14 @@
"type": "device",
"class": "",
"position": {
- "x": 43.2,
- "y": 14.3,
+ "x": 47.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2437,19 +2444,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2458,10 +2465,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2474,14 +2481,14 @@
"type": "device",
"class": "",
"position": {
- "x": 43.2,
- "y": 5.3,
+ "x": 47.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2493,19 +2500,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2514,10 +2521,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2530,14 +2537,14 @@
"type": "device",
"class": "",
"position": {
- "x": 52.2,
- "y": 68.3,
+ "x": 56.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2549,19 +2556,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2570,10 +2577,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2586,14 +2593,14 @@
"type": "device",
"class": "",
"position": {
- "x": 52.2,
- "y": 59.3,
+ "x": 56.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2605,19 +2612,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2626,10 +2633,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2642,14 +2649,14 @@
"type": "device",
"class": "",
"position": {
- "x": 52.2,
- "y": 50.3,
+ "x": 56.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2661,19 +2668,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2682,10 +2689,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2698,14 +2705,14 @@
"type": "device",
"class": "",
"position": {
- "x": 52.2,
- "y": 41.3,
+ "x": 56.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2717,19 +2724,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2738,10 +2745,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2754,14 +2761,14 @@
"type": "device",
"class": "",
"position": {
- "x": 52.2,
- "y": 32.3,
+ "x": 56.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2773,19 +2780,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2794,10 +2801,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2810,14 +2817,14 @@
"type": "device",
"class": "",
"position": {
- "x": 52.2,
- "y": 23.3,
+ "x": 56.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2829,19 +2836,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2850,10 +2857,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2866,14 +2873,14 @@
"type": "device",
"class": "",
"position": {
- "x": 52.2,
- "y": 14.3,
+ "x": 56.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2885,19 +2892,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2906,10 +2913,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2922,14 +2929,14 @@
"type": "device",
"class": "",
"position": {
- "x": 52.2,
- "y": 5.3,
+ "x": 56.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2941,19 +2948,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -2962,10 +2969,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -2978,14 +2985,14 @@
"type": "device",
"class": "",
"position": {
- "x": 61.2,
- "y": 68.3,
+ "x": 65.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -2997,19 +3004,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3018,10 +3025,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3034,14 +3041,14 @@
"type": "device",
"class": "",
"position": {
- "x": 61.2,
- "y": 59.3,
+ "x": 65.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3053,19 +3060,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3074,10 +3081,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3090,14 +3097,14 @@
"type": "device",
"class": "",
"position": {
- "x": 61.2,
- "y": 50.3,
+ "x": 65.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3109,19 +3116,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3130,10 +3137,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3146,14 +3153,14 @@
"type": "device",
"class": "",
"position": {
- "x": 61.2,
- "y": 41.3,
+ "x": 65.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3165,19 +3172,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3186,10 +3193,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3202,14 +3209,14 @@
"type": "device",
"class": "",
"position": {
- "x": 61.2,
- "y": 32.3,
+ "x": 65.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3221,19 +3228,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3242,10 +3249,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3258,14 +3265,14 @@
"type": "device",
"class": "",
"position": {
- "x": 61.2,
- "y": 23.3,
+ "x": 65.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3277,19 +3284,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3298,10 +3305,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3314,14 +3321,14 @@
"type": "device",
"class": "",
"position": {
- "x": 61.2,
- "y": 14.3,
+ "x": 65.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3333,19 +3340,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3354,10 +3361,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3370,14 +3377,14 @@
"type": "device",
"class": "",
"position": {
- "x": 61.2,
- "y": 5.3,
+ "x": 65.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3389,19 +3396,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3410,10 +3417,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3426,14 +3433,14 @@
"type": "device",
"class": "",
"position": {
- "x": 70.2,
- "y": 68.3,
+ "x": 74.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3445,19 +3452,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3466,10 +3473,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3482,14 +3489,14 @@
"type": "device",
"class": "",
"position": {
- "x": 70.2,
- "y": 59.3,
+ "x": 74.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3501,19 +3508,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3522,10 +3529,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3538,14 +3545,14 @@
"type": "device",
"class": "",
"position": {
- "x": 70.2,
- "y": 50.3,
+ "x": 74.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3557,19 +3564,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3578,10 +3585,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3594,14 +3601,14 @@
"type": "device",
"class": "",
"position": {
- "x": 70.2,
- "y": 41.3,
+ "x": 74.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3613,19 +3620,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3634,10 +3641,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3650,14 +3657,14 @@
"type": "device",
"class": "",
"position": {
- "x": 70.2,
- "y": 32.3,
+ "x": 74.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3669,19 +3676,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3690,10 +3697,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3706,14 +3713,14 @@
"type": "device",
"class": "",
"position": {
- "x": 70.2,
- "y": 23.3,
+ "x": 74.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3725,19 +3732,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3746,10 +3753,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3762,14 +3769,14 @@
"type": "device",
"class": "",
"position": {
- "x": 70.2,
- "y": 14.3,
+ "x": 74.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3781,19 +3788,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3802,10 +3809,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3818,14 +3825,14 @@
"type": "device",
"class": "",
"position": {
- "x": 70.2,
- "y": 5.3,
+ "x": 74.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3837,19 +3844,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3858,10 +3865,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3874,14 +3881,14 @@
"type": "device",
"class": "",
"position": {
- "x": 79.2,
- "y": 68.3,
+ "x": 83.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3893,19 +3900,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3914,10 +3921,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3930,14 +3937,14 @@
"type": "device",
"class": "",
"position": {
- "x": 79.2,
- "y": 59.3,
+ "x": 83.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -3949,19 +3956,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -3970,10 +3977,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -3986,14 +3993,14 @@
"type": "device",
"class": "",
"position": {
- "x": 79.2,
- "y": 50.3,
+ "x": 83.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4005,19 +4012,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4026,10 +4033,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4042,14 +4049,14 @@
"type": "device",
"class": "",
"position": {
- "x": 79.2,
- "y": 41.3,
+ "x": 83.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4061,19 +4068,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4082,10 +4089,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4098,14 +4105,14 @@
"type": "device",
"class": "",
"position": {
- "x": 79.2,
- "y": 32.3,
+ "x": 83.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4117,19 +4124,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4138,10 +4145,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4154,14 +4161,14 @@
"type": "device",
"class": "",
"position": {
- "x": 79.2,
- "y": 23.3,
+ "x": 83.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4173,19 +4180,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4194,10 +4201,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4210,14 +4217,14 @@
"type": "device",
"class": "",
"position": {
- "x": 79.2,
- "y": 14.3,
+ "x": 83.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4229,19 +4236,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4250,10 +4257,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4266,14 +4273,14 @@
"type": "device",
"class": "",
"position": {
- "x": 79.2,
- "y": 5.3,
+ "x": 83.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4285,19 +4292,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4306,10 +4313,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4322,14 +4329,14 @@
"type": "device",
"class": "",
"position": {
- "x": 88.2,
- "y": 68.3,
+ "x": 92.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4341,19 +4348,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4362,10 +4369,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4378,14 +4385,14 @@
"type": "device",
"class": "",
"position": {
- "x": 88.2,
- "y": 59.3,
+ "x": 92.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4397,19 +4404,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4418,10 +4425,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4434,14 +4441,14 @@
"type": "device",
"class": "",
"position": {
- "x": 88.2,
- "y": 50.3,
+ "x": 92.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4453,19 +4460,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4474,10 +4481,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4490,14 +4497,14 @@
"type": "device",
"class": "",
"position": {
- "x": 88.2,
- "y": 41.3,
+ "x": 92.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4509,19 +4516,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4530,10 +4537,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4546,14 +4553,14 @@
"type": "device",
"class": "",
"position": {
- "x": 88.2,
- "y": 32.3,
+ "x": 92.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4565,19 +4572,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4586,10 +4593,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4602,14 +4609,14 @@
"type": "device",
"class": "",
"position": {
- "x": 88.2,
- "y": 23.3,
+ "x": 92.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4621,19 +4628,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4642,10 +4649,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4658,14 +4665,14 @@
"type": "device",
"class": "",
"position": {
- "x": 88.2,
- "y": 14.3,
+ "x": 92.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4677,19 +4684,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4698,10 +4705,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4714,14 +4721,14 @@
"type": "device",
"class": "",
"position": {
- "x": 88.2,
- "y": 5.3,
+ "x": 92.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4733,19 +4740,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4754,10 +4761,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4770,14 +4777,14 @@
"type": "device",
"class": "",
"position": {
- "x": 97.2,
- "y": 68.3,
+ "x": 101.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4789,19 +4796,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4810,10 +4817,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4826,14 +4833,14 @@
"type": "device",
"class": "",
"position": {
- "x": 97.2,
- "y": 59.3,
+ "x": 101.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4845,19 +4852,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4866,10 +4873,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4882,14 +4889,14 @@
"type": "device",
"class": "",
"position": {
- "x": 97.2,
- "y": 50.3,
+ "x": 101.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4901,19 +4908,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4922,10 +4929,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4938,14 +4945,14 @@
"type": "device",
"class": "",
"position": {
- "x": 97.2,
- "y": 41.3,
+ "x": 101.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -4957,19 +4964,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -4978,10 +4985,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -4994,14 +5001,14 @@
"type": "device",
"class": "",
"position": {
- "x": 97.2,
- "y": 32.3,
+ "x": 101.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5013,19 +5020,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5034,10 +5041,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5050,14 +5057,14 @@
"type": "device",
"class": "",
"position": {
- "x": 97.2,
- "y": 23.3,
+ "x": 101.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5069,19 +5076,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5090,10 +5097,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5106,14 +5113,14 @@
"type": "device",
"class": "",
"position": {
- "x": 97.2,
- "y": 14.3,
+ "x": 101.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5125,19 +5132,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5146,10 +5153,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5162,14 +5169,14 @@
"type": "device",
"class": "",
"position": {
- "x": 97.2,
- "y": 5.3,
+ "x": 101.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5181,19 +5188,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5202,10 +5209,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5218,14 +5225,14 @@
"type": "device",
"class": "",
"position": {
- "x": 106.2,
- "y": 68.3,
+ "x": 110.804,
+ "y": 71.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5237,19 +5244,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5258,10 +5265,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5274,14 +5281,14 @@
"type": "device",
"class": "",
"position": {
- "x": 106.2,
- "y": 59.3,
+ "x": 110.804,
+ "y": 62.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5293,19 +5300,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5314,10 +5321,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5330,14 +5337,14 @@
"type": "device",
"class": "",
"position": {
- "x": 106.2,
- "y": 50.3,
+ "x": 110.804,
+ "y": 53.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5349,19 +5356,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5370,10 +5377,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5386,14 +5393,14 @@
"type": "device",
"class": "",
"position": {
- "x": 106.2,
- "y": 41.3,
+ "x": 110.804,
+ "y": 44.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5405,19 +5412,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5426,10 +5433,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5442,14 +5449,14 @@
"type": "device",
"class": "",
"position": {
- "x": 106.2,
- "y": 32.3,
+ "x": 110.804,
+ "y": 35.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5461,19 +5468,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5482,10 +5489,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5498,14 +5505,14 @@
"type": "device",
"class": "",
"position": {
- "x": 106.2,
- "y": 23.3,
+ "x": 110.804,
+ "y": 26.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5517,19 +5524,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5538,10 +5545,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5554,14 +5561,14 @@
"type": "device",
"class": "",
"position": {
- "x": 106.2,
- "y": 14.3,
+ "x": 110.804,
+ "y": 17.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5573,19 +5580,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5594,10 +5601,10 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
@@ -5610,14 +5617,14 @@
"type": "device",
"class": "",
"position": {
- "x": 106.2,
- "y": 5.3,
+ "x": 110.804,
+ "y": 8.704,
"z": 9.47
},
"config": {
"type": "TipSpot",
- "size_x": 9.0,
- "size_y": 9.0,
+ "size_x": 5.112,
+ "size_y": 5.112,
"size_z": 0,
"rotation": {
"x": 0,
@@ -5629,19 +5636,19 @@
"model": null,
"prototype_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
},
"data": {
"tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
},
"tip_state": {
"liquids": [],
@@ -5650,13 +5657,16 @@
},
"pending_tip": {
"type": "Tip",
- "total_tip_length": 39.2,
+ "total_tip_length": 88,
"has_filter": true,
- "maximal_volume": 20.0,
- "fitting_depth": 3.29
+ "maximal_volume": 1000.0,
+ "fitting_depth": 7.95
}
}
},
+
+
+
{
"id": "plate_well",
"name": "plate_well",
@@ -5677,7 +5687,7 @@
"plate_well_E2",
"plate_well_F2",
"plate_well_G2",
- "plate_well_H2",
+ "plate_well_H2",
"plate_well_A3",
"plate_well_B3",
"plate_well_C3",
@@ -5756,14 +5766,15 @@
"plate_well_D12",
"plate_well_E12",
"plate_well_F12",
- "plate_well_G12"
+ "plate_well_G12",
+ "plate_well_H12"
],
"parent": "deck",
"type": "plate",
"class": "nest_96_wellplate_2ml_deep",
"position": {
- "x": 265.0,
- "y": 0,
+ "x": 0,
+ "y": 90.5,
"z": 69
},
"config": {
@@ -5880,6 +5891,11 @@
},
"data": {}
},
+
+
+
+
+
{
"id": "plate_well_A1",
"name": "plate_well_A1",
@@ -5889,15 +5905,15 @@
"type": "device",
"class": "",
"position": {
- "x": 10.87,
- "y": 70.77,
- "z": 3.03
+ "x": 10.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -5906,16 +5922,16 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
- "liquids": [],
- "pending_liquids": [],
+ "liquids": [["water", 50.0]],
+ "pending_liquids": [["water", 50.0]],
"liquid_history": []
}
},
@@ -5928,15 +5944,15 @@
"type": "device",
"class": "",
"position": {
- "x": 10.87,
- "y": 61.77,
- "z": 3.03
+ "x": 10.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -5945,16 +5961,16 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
- "liquids": [],
- "pending_liquids": [],
+ "liquids": [["water", 50.0]],
+ "pending_liquids": [["water", 50.0]],
"liquid_history": []
}
},
@@ -5967,15 +5983,15 @@
"type": "device",
"class": "",
"position": {
- "x": 10.87,
- "y": 52.77,
- "z": 3.03
+ "x": 10.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -5984,16 +6000,16 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
- "liquids": [],
- "pending_liquids": [],
+ "liquids": [["water", 50.0]],
+ "pending_liquids": [["water", 50.0]],
"liquid_history": []
}
},
@@ -6006,15 +6022,15 @@
"type": "device",
"class": "",
"position": {
- "x": 10.87,
- "y": 43.77,
- "z": 3.03
+ "x": 10.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6023,16 +6039,16 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
- "liquids": [],
- "pending_liquids": [],
+ "liquids": [["water", 50.0]],
+ "pending_liquids": [["water", 50.0]],
"liquid_history": []
}
},
@@ -6045,15 +6061,15 @@
"type": "device",
"class": "",
"position": {
- "x": 10.87,
- "y": 34.77,
- "z": 3.03
+ "x": 10.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6062,16 +6078,16 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
- "liquids": [],
- "pending_liquids": [],
+ "liquids": [["water", 50.0]],
+ "pending_liquids": [["water", 50.0]],
"liquid_history": []
}
},
@@ -6084,15 +6100,15 @@
"type": "device",
"class": "",
"position": {
- "x": 10.87,
- "y": 25.77,
- "z": 3.03
+ "x": 10.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6101,16 +6117,16 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
- "liquids": [],
- "pending_liquids": [],
+ "liquids": [["water", 50.0]],
+ "pending_liquids": [["water", 50.0]],
"liquid_history": []
}
},
@@ -6123,15 +6139,15 @@
"type": "device",
"class": "",
"position": {
- "x": 10.87,
- "y": 16.77,
- "z": 3.03
+ "x": 10.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6140,16 +6156,16 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
- "liquids": [],
- "pending_liquids": [],
+ "liquids": [["water", 50.0]],
+ "pending_liquids": [["water", 50.0]],
"liquid_history": []
}
},
@@ -6162,15 +6178,15 @@
"type": "device",
"class": "",
"position": {
- "x": 10.87,
- "y": 7.77,
- "z": 3.03
+ "x": 10.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6179,16 +6195,16 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
- "liquids": [],
- "pending_liquids": [],
+ "liquids": [["water", 50.0]],
+ "pending_liquids": [["water", 50.0]],
"liquid_history": []
}
},
@@ -6201,15 +6217,15 @@
"type": "device",
"class": "",
"position": {
- "x": 19.87,
- "y": 70.77,
- "z": 3.03
+ "x": 19.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6218,12 +6234,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6240,15 +6256,15 @@
"type": "device",
"class": "",
"position": {
- "x": 19.87,
- "y": 61.77,
- "z": 3.03
+ "x": 19.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6257,12 +6273,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6279,15 +6295,15 @@
"type": "device",
"class": "",
"position": {
- "x": 19.87,
- "y": 52.77,
- "z": 3.03
+ "x": 19.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6296,12 +6312,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6318,15 +6334,15 @@
"type": "device",
"class": "",
"position": {
- "x": 19.87,
- "y": 43.77,
- "z": 3.03
+ "x": 19.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6335,12 +6351,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6357,15 +6373,15 @@
"type": "device",
"class": "",
"position": {
- "x": 19.87,
- "y": 34.77,
- "z": 3.03
+ "x": 19.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6374,12 +6390,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6396,15 +6412,15 @@
"type": "device",
"class": "",
"position": {
- "x": 19.87,
- "y": 25.77,
- "z": 3.03
+ "x": 19.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6413,12 +6429,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6435,15 +6451,15 @@
"type": "device",
"class": "",
"position": {
- "x": 19.87,
- "y": 16.77,
- "z": 3.03
+ "x": 19.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6452,12 +6468,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6474,15 +6490,15 @@
"type": "device",
"class": "",
"position": {
- "x": 19.87,
- "y": 7.77,
- "z": 3.03
+ "x": 19.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6491,12 +6507,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6513,15 +6529,15 @@
"type": "device",
"class": "",
"position": {
- "x": 28.87,
- "y": 70.77,
- "z": 3.03
+ "x": 28.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6530,12 +6546,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6552,15 +6568,15 @@
"type": "device",
"class": "",
"position": {
- "x": 28.87,
- "y": 61.77,
- "z": 3.03
+ "x": 28.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6569,12 +6585,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6591,15 +6607,15 @@
"type": "device",
"class": "",
"position": {
- "x": 28.87,
- "y": 52.77,
- "z": 3.03
+ "x": 28.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6608,12 +6624,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6630,15 +6646,15 @@
"type": "device",
"class": "",
"position": {
- "x": 28.87,
- "y": 43.77,
- "z": 3.03
+ "x": 28.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6647,12 +6663,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6669,15 +6685,15 @@
"type": "device",
"class": "",
"position": {
- "x": 28.87,
- "y": 34.77,
- "z": 3.03
+ "x": 28.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6686,12 +6702,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6708,15 +6724,15 @@
"type": "device",
"class": "",
"position": {
- "x": 28.87,
- "y": 25.77,
- "z": 3.03
+ "x": 28.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6725,12 +6741,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6747,15 +6763,15 @@
"type": "device",
"class": "",
"position": {
- "x": 28.87,
- "y": 16.77,
- "z": 3.03
+ "x": 28.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6764,12 +6780,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6786,15 +6802,15 @@
"type": "device",
"class": "",
"position": {
- "x": 28.87,
- "y": 7.77,
- "z": 3.03
+ "x": 28.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6803,12 +6819,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6825,15 +6841,15 @@
"type": "device",
"class": "",
"position": {
- "x": 37.87,
- "y": 70.77,
- "z": 3.03
+ "x": 37.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6842,12 +6858,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6864,15 +6880,15 @@
"type": "device",
"class": "",
"position": {
- "x": 37.87,
- "y": 61.77,
- "z": 3.03
+ "x": 37.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6881,12 +6897,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6903,15 +6919,15 @@
"type": "device",
"class": "",
"position": {
- "x": 37.87,
- "y": 52.77,
- "z": 3.03
+ "x": 37.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6920,12 +6936,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6942,15 +6958,15 @@
"type": "device",
"class": "",
"position": {
- "x": 37.87,
- "y": 43.77,
- "z": 3.03
+ "x": 37.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6959,12 +6975,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -6981,15 +6997,15 @@
"type": "device",
"class": "",
"position": {
- "x": 37.87,
- "y": 34.77,
- "z": 3.03
+ "x": 37.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -6998,12 +7014,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7020,15 +7036,15 @@
"type": "device",
"class": "",
"position": {
- "x": 37.87,
- "y": 25.77,
- "z": 3.03
+ "x": 37.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7037,12 +7053,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7059,15 +7075,15 @@
"type": "device",
"class": "",
"position": {
- "x": 37.87,
- "y": 16.77,
- "z": 3.03
+ "x": 37.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7076,12 +7092,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7098,15 +7114,15 @@
"type": "device",
"class": "",
"position": {
- "x": 37.87,
- "y": 7.77,
- "z": 3.03
+ "x": 37.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7115,12 +7131,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7137,15 +7153,15 @@
"type": "device",
"class": "",
"position": {
- "x": 46.87,
- "y": 70.77,
- "z": 3.03
+ "x": 46.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7154,12 +7170,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7176,15 +7192,15 @@
"type": "device",
"class": "",
"position": {
- "x": 46.87,
- "y": 61.77,
- "z": 3.03
+ "x": 46.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7193,12 +7209,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7215,15 +7231,15 @@
"type": "device",
"class": "",
"position": {
- "x": 46.87,
- "y": 52.77,
- "z": 3.03
+ "x": 46.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7232,12 +7248,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7254,15 +7270,15 @@
"type": "device",
"class": "",
"position": {
- "x": 46.87,
- "y": 43.77,
- "z": 3.03
+ "x": 46.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7271,12 +7287,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7293,15 +7309,15 @@
"type": "device",
"class": "",
"position": {
- "x": 46.87,
- "y": 34.77,
- "z": 3.03
+ "x": 46.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7310,12 +7326,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7332,15 +7348,15 @@
"type": "device",
"class": "",
"position": {
- "x": 46.87,
- "y": 25.77,
- "z": 3.03
+ "x": 46.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7349,12 +7365,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7371,15 +7387,15 @@
"type": "device",
"class": "",
"position": {
- "x": 46.87,
- "y": 16.77,
- "z": 3.03
+ "x": 46.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7388,12 +7404,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7410,15 +7426,15 @@
"type": "device",
"class": "",
"position": {
- "x": 46.87,
- "y": 7.77,
- "z": 3.03
+ "x": 46.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7427,12 +7443,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7449,15 +7465,15 @@
"type": "device",
"class": "",
"position": {
- "x": 55.87,
- "y": 70.77,
- "z": 3.03
+ "x": 55.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7466,12 +7482,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7488,15 +7504,15 @@
"type": "device",
"class": "",
"position": {
- "x": 55.87,
- "y": 61.77,
- "z": 3.03
+ "x": 55.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7505,12 +7521,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7527,15 +7543,15 @@
"type": "device",
"class": "",
"position": {
- "x": 55.87,
- "y": 52.77,
- "z": 3.03
+ "x": 55.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7544,12 +7560,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7566,15 +7582,15 @@
"type": "device",
"class": "",
"position": {
- "x": 55.87,
- "y": 43.77,
- "z": 3.03
+ "x": 55.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7583,12 +7599,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7605,15 +7621,15 @@
"type": "device",
"class": "",
"position": {
- "x": 55.87,
- "y": 34.77,
- "z": 3.03
+ "x": 55.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7622,12 +7638,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7644,15 +7660,15 @@
"type": "device",
"class": "",
"position": {
- "x": 55.87,
- "y": 25.77,
- "z": 3.03
+ "x": 55.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7661,12 +7677,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7683,15 +7699,15 @@
"type": "device",
"class": "",
"position": {
- "x": 55.87,
- "y": 16.77,
- "z": 3.03
+ "x": 55.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7700,12 +7716,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7722,15 +7738,15 @@
"type": "device",
"class": "",
"position": {
- "x": 55.87,
- "y": 7.77,
- "z": 3.03
+ "x": 55.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7739,12 +7755,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7761,15 +7777,15 @@
"type": "device",
"class": "",
"position": {
- "x": 64.87,
- "y": 70.77,
- "z": 3.03
+ "x": 64.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7778,12 +7794,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7800,15 +7816,15 @@
"type": "device",
"class": "",
"position": {
- "x": 64.87,
- "y": 61.77,
- "z": 3.03
+ "x": 64.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7817,12 +7833,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7839,15 +7855,15 @@
"type": "device",
"class": "",
"position": {
- "x": 64.87,
- "y": 52.77,
- "z": 3.03
+ "x": 64.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7856,12 +7872,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7878,15 +7894,15 @@
"type": "device",
"class": "",
"position": {
- "x": 64.87,
- "y": 43.77,
- "z": 3.03
+ "x": 64.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7895,12 +7911,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7917,15 +7933,15 @@
"type": "device",
"class": "",
"position": {
- "x": 64.87,
- "y": 34.77,
- "z": 3.03
+ "x": 64.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7934,12 +7950,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7956,15 +7972,15 @@
"type": "device",
"class": "",
"position": {
- "x": 64.87,
- "y": 25.77,
- "z": 3.03
+ "x": 64.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -7973,12 +7989,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -7995,15 +8011,15 @@
"type": "device",
"class": "",
"position": {
- "x": 64.87,
- "y": 16.77,
- "z": 3.03
+ "x": 64.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8012,12 +8028,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8034,15 +8050,15 @@
"type": "device",
"class": "",
"position": {
- "x": 64.87,
- "y": 7.77,
- "z": 3.03
+ "x": 64.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8051,12 +8067,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8073,15 +8089,15 @@
"type": "device",
"class": "",
"position": {
- "x": 73.87,
- "y": 70.77,
- "z": 3.03
+ "x": 73.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8090,12 +8106,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8112,15 +8128,15 @@
"type": "device",
"class": "",
"position": {
- "x": 73.87,
- "y": 61.77,
- "z": 3.03
+ "x": 73.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8129,12 +8145,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8151,15 +8167,15 @@
"type": "device",
"class": "",
"position": {
- "x": 73.87,
- "y": 52.77,
- "z": 3.03
+ "x": 73.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8168,12 +8184,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8190,15 +8206,15 @@
"type": "device",
"class": "",
"position": {
- "x": 73.87,
- "y": 43.77,
- "z": 3.03
+ "x": 73.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8207,12 +8223,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8229,15 +8245,15 @@
"type": "device",
"class": "",
"position": {
- "x": 73.87,
- "y": 34.77,
- "z": 3.03
+ "x": 73.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8246,12 +8262,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8268,15 +8284,15 @@
"type": "device",
"class": "",
"position": {
- "x": 73.87,
- "y": 25.77,
- "z": 3.03
+ "x": 73.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8285,12 +8301,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8307,15 +8323,15 @@
"type": "device",
"class": "",
"position": {
- "x": 73.87,
- "y": 16.77,
- "z": 3.03
+ "x": 73.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8324,12 +8340,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8346,15 +8362,15 @@
"type": "device",
"class": "",
"position": {
- "x": 73.87,
- "y": 7.77,
- "z": 3.03
+ "x": 73.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8363,12 +8379,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8385,15 +8401,15 @@
"type": "device",
"class": "",
"position": {
- "x": 82.87,
- "y": 70.77,
- "z": 3.03
+ "x": 82.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8402,12 +8418,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8424,15 +8440,15 @@
"type": "device",
"class": "",
"position": {
- "x": 82.87,
- "y": 61.77,
- "z": 3.03
+ "x": 82.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8441,12 +8457,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8463,15 +8479,15 @@
"type": "device",
"class": "",
"position": {
- "x": 82.87,
- "y": 52.77,
- "z": 3.03
+ "x": 82.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8480,12 +8496,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8502,15 +8518,15 @@
"type": "device",
"class": "",
"position": {
- "x": 82.87,
- "y": 43.77,
- "z": 3.03
+ "x": 82.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8519,12 +8535,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8541,15 +8557,15 @@
"type": "device",
"class": "",
"position": {
- "x": 82.87,
- "y": 34.77,
- "z": 3.03
+ "x": 82.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8558,12 +8574,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8580,15 +8596,15 @@
"type": "device",
"class": "",
"position": {
- "x": 82.87,
- "y": 25.77,
- "z": 3.03
+ "x": 82.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8597,12 +8613,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8619,15 +8635,15 @@
"type": "device",
"class": "",
"position": {
- "x": 82.87,
- "y": 16.77,
- "z": 3.03
+ "x": 82.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8636,12 +8652,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8658,15 +8674,15 @@
"type": "device",
"class": "",
"position": {
- "x": 82.87,
- "y": 7.77,
- "z": 3.03
+ "x": 82.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8675,12 +8691,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8697,15 +8713,15 @@
"type": "device",
"class": "",
"position": {
- "x": 91.87,
- "y": 70.77,
- "z": 3.03
+ "x": 91.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8714,12 +8730,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8736,15 +8752,15 @@
"type": "device",
"class": "",
"position": {
- "x": 91.87,
- "y": 61.77,
- "z": 3.03
+ "x": 91.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8753,12 +8769,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8775,15 +8791,15 @@
"type": "device",
"class": "",
"position": {
- "x": 91.87,
- "y": 52.77,
- "z": 3.03
+ "x": 91.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8792,12 +8808,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8814,15 +8830,15 @@
"type": "device",
"class": "",
"position": {
- "x": 91.87,
- "y": 43.77,
- "z": 3.03
+ "x": 91.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8831,12 +8847,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8853,15 +8869,15 @@
"type": "device",
"class": "",
"position": {
- "x": 91.87,
- "y": 34.77,
- "z": 3.03
+ "x": 91.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8870,12 +8886,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8892,15 +8908,15 @@
"type": "device",
"class": "",
"position": {
- "x": 91.87,
- "y": 25.77,
- "z": 3.03
+ "x": 91.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8909,12 +8925,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8931,15 +8947,15 @@
"type": "device",
"class": "",
"position": {
- "x": 91.87,
- "y": 16.77,
- "z": 3.03
+ "x": 91.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8948,12 +8964,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -8970,15 +8986,15 @@
"type": "device",
"class": "",
"position": {
- "x": 91.87,
- "y": 7.77,
- "z": 3.03
+ "x": 91.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -8987,12 +9003,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9009,15 +9025,15 @@
"type": "device",
"class": "",
"position": {
- "x": 100.87,
- "y": 70.77,
- "z": 3.03
+ "x": 100.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9026,12 +9042,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9048,15 +9064,15 @@
"type": "device",
"class": "",
"position": {
- "x": 100.87,
- "y": 61.77,
- "z": 3.03
+ "x": 100.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9065,12 +9081,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9087,15 +9103,15 @@
"type": "device",
"class": "",
"position": {
- "x": 100.87,
- "y": 52.77,
- "z": 3.03
+ "x": 100.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9104,12 +9120,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9126,15 +9142,15 @@
"type": "device",
"class": "",
"position": {
- "x": 100.87,
- "y": 43.77,
- "z": 3.03
+ "x": 100.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9143,12 +9159,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9165,15 +9181,15 @@
"type": "device",
"class": "",
"position": {
- "x": 100.87,
- "y": 34.77,
- "z": 3.03
+ "x": 100.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9182,12 +9198,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9204,15 +9220,15 @@
"type": "device",
"class": "",
"position": {
- "x": 100.87,
- "y": 25.77,
- "z": 3.03
+ "x": 100.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9221,12 +9237,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9243,15 +9259,15 @@
"type": "device",
"class": "",
"position": {
- "x": 100.87,
- "y": 16.77,
- "z": 3.03
+ "x": 100.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9260,12 +9276,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9282,15 +9298,15 @@
"type": "device",
"class": "",
"position": {
- "x": 100.87,
- "y": 7.77,
- "z": 3.03
+ "x": 100.2,
+ "y": 7.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9299,12 +9315,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9321,15 +9337,15 @@
"type": "device",
"class": "",
"position": {
- "x": 109.87,
- "y": 70.77,
- "z": 3.03
+ "x": 109.2,
+ "y": 70.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9338,12 +9354,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9360,15 +9376,15 @@
"type": "device",
"class": "",
"position": {
- "x": 109.87,
- "y": 61.77,
- "z": 3.03
+ "x": 109.2,
+ "y": 61.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9377,12 +9393,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9399,15 +9415,15 @@
"type": "device",
"class": "",
"position": {
- "x": 109.87,
- "y": 52.77,
- "z": 3.03
+ "x": 109.2,
+ "y": 52.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9416,12 +9432,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9438,15 +9454,15 @@
"type": "device",
"class": "",
"position": {
- "x": 109.87,
- "y": 43.77,
- "z": 3.03
+ "x": 109.2,
+ "y": 43.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9455,12 +9471,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9477,15 +9493,15 @@
"type": "device",
"class": "",
"position": {
- "x": 109.87,
- "y": 34.77,
- "z": 3.03
+ "x": 109.2,
+ "y": 34.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9494,12 +9510,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9516,15 +9532,15 @@
"type": "device",
"class": "",
"position": {
- "x": 109.87,
- "y": 25.77,
- "z": 3.03
+ "x": 109.2,
+ "y": 25.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9533,12 +9549,12 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
@@ -9555,15 +9571,15 @@
"type": "device",
"class": "",
"position": {
- "x": 109.87,
- "y": 16.77,
- "z": 3.03
+ "x": 109.2,
+ "y": 16.05,
+ "z": 3
},
"config": {
"type": "Well",
- "size_x": 6.86,
- "size_y": 6.86,
- "size_z": 10.67,
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
"rotation": {
"x": 0,
"y": 0,
@@ -9572,18 +9588,126 @@
},
"category": "well",
"model": null,
- "max_volume": 360,
- "material_z_thickness": 0.5,
+ "max_volume": 2000,
+ "material_z_thickness": null,
"compute_volume_from_height": null,
"compute_height_from_volume": null,
- "bottom_type": "flat",
- "cross_section_type": "circle"
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
},
"data": {
"liquids": [],
"pending_liquids": [],
"liquid_history": []
}
+ },
+ {
+ "id": "plate_well_H12",
+ "name": "plate_well_H12",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 109.2,
+ "y": 7.05,
+ "z": 3
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 8.2,
+ "size_y": 8.2,
+ "size_z": 38,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 2000,
+ "material_z_thickness": null,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "unknown",
+ "cross_section_type": "rectangle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+
+
+
+
+ {
+ "id": "arm_slider",
+ "name": "arm_slider",
+ "children": [],
+ "parent": null,
+ "type": "device",
+ "class": "moveit.arm_slider",
+ "position": {
+ "x": -500,
+ "y": 1000,
+ "z": -100
+ },
+ "config": {
+ "moveit_type": "arm_slider",
+ "joint_poses": {
+ "arm": {
+ "hotel_1": [
+ 1.05,
+ 0.568,
+ -1.0821,
+ 0.0,
+ 1.0821
+ ],
+ "home": [
+ 0.865,
+ 0.09,
+ 0.8727,
+ 0.0,
+ -0.8727
+ ]
+ }
+ },
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": -1.5708,
+ "type": "Rotation"
+ },
+ "device_config": {}
+ },
+ "data": {}
+ },
+ {
+ "id": "hotel",
+ "name": "hotel",
+ "children": [],
+ "parent": null,
+ "type": "device",
+ "class": "hotel.thermo_orbitor_rs2_hotel",
+ "position": {
+ "x": 0,
+ "y": -700,
+ "z": -10
+ },
+ "config": {
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "device_config": {}
+ },
+ "data": {}
}
],
"links": []
diff --git a/test/experiments/plr_test_converted_slim.json b/test/experiments/plr_test_converted_slim.json
new file mode 100644
index 0000000..43e05e7
--- /dev/null
+++ b/test/experiments/plr_test_converted_slim.json
@@ -0,0 +1,1710 @@
+{
+ "nodes": [
+ {
+ "id": "PLR_STATION",
+ "name": "PLR_LH_TEST",
+ "parent": null,
+ "type": "device",
+ "class": "liquid_handler",
+ "position": {
+ "x": 620.6111111111111,
+ "y": 171,
+ "z": 0
+ },
+ "config": {
+ "data": {
+ "children": [
+ {
+ "_resource_child_name": "deck",
+ "_resource_type": "pylabrobot.resources.opentrons.deck:OTDeck"
+ }
+ ],
+ "backend": {
+ "type": "LiquidHandlerChatterboxBackend"
+ }
+ }
+ },
+ "data": {},
+ "children": [
+ "deck"
+ ]
+ },
+ {
+ "id": "deck",
+ "name": "deck",
+ "sample_id": null,
+ "children": [
+ "tip_rack",
+ "plate_well"
+ ],
+ "parent": "PLR_STATION",
+ "type": "deck",
+ "class": "OTDeck",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "config": {
+ "type": "OTDeck",
+ "with_trash": false,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ }
+ },
+ "data": {}
+ },
+ {
+ "id": "tip_rack",
+ "name": "tip_rack",
+ "sample_id": null,
+ "children": [
+ "tip_rack_A1",
+ "tip_rack_B1",
+ "tip_rack_C1",
+ "tip_rack_D1",
+ "tip_rack_E1",
+ "tip_rack_F1",
+ "tip_rack_G1",
+ "tip_rack_H1",
+ "tip_rack_A2",
+ "tip_rack_B2",
+ "tip_rack_C2",
+ "tip_rack_D2",
+ "tip_rack_E2",
+ "tip_rack_F2",
+ "tip_rack_G2",
+ "tip_rack_H2"
+ ],
+ "parent": "deck",
+ "type": "plate",
+ "class": "opentrons_96_filtertiprack_1000ul",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "z": 69
+ },
+ "config": {
+ "type": "TipRack",
+ "size_x": 122.4,
+ "size_y": 82.6,
+ "size_z": 20.0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_rack",
+ "model": "HTF",
+ "ordering": [
+ "A1",
+ "B1",
+ "C1",
+ "D1",
+ "E1",
+ "F1",
+ "G1",
+ "H1",
+ "A2",
+ "B2",
+ "C2",
+ "D2",
+ "E2",
+ "F2",
+ "G2",
+ "H2"
+ ]
+ },
+ "data": {}
+ },
+ {
+ "id": "tip_rack_A1",
+ "name": "tip_rack_A1",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 7.2,
+ "y": 68.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_B1",
+ "name": "tip_rack_B1",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 7.2,
+ "y": 59.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_C1",
+ "name": "tip_rack_C1",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 7.2,
+ "y": 50.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_D1",
+ "name": "tip_rack_D1",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 7.2,
+ "y": 41.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_E1",
+ "name": "tip_rack_E1",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 7.2,
+ "y": 32.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_F1",
+ "name": "tip_rack_F1",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 7.2,
+ "y": 23.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_G1",
+ "name": "tip_rack_G1",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 7.2,
+ "y": 14.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_H1",
+ "name": "tip_rack_H1",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 7.2,
+ "y": 5.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_A2",
+ "name": "tip_rack_A2",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 16.2,
+ "y": 68.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_B2",
+ "name": "tip_rack_B2",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 16.2,
+ "y": 59.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_C2",
+ "name": "tip_rack_C2",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 16.2,
+ "y": 50.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_D2",
+ "name": "tip_rack_D2",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 16.2,
+ "y": 41.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_E2",
+ "name": "tip_rack_E2",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 16.2,
+ "y": 32.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_F2",
+ "name": "tip_rack_F2",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 16.2,
+ "y": 23.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_G2",
+ "name": "tip_rack_G2",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 16.2,
+ "y": 14.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "tip_rack_H2",
+ "name": "tip_rack_H2",
+ "sample_id": null,
+ "children": [],
+ "parent": "tip_rack",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 16.2,
+ "y": 5.3,
+ "z": 9.47
+ },
+ "config": {
+ "type": "TipSpot",
+ "size_x": 9.0,
+ "size_y": 9.0,
+ "size_z": 0,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "tip_spot",
+ "model": null,
+ "prototype_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ },
+ "data": {
+ "tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ },
+ "tip_state": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ },
+ "pending_tip": {
+ "type": "Tip",
+ "total_tip_length": 39.2,
+ "has_filter": true,
+ "maximal_volume": 20.0,
+ "fitting_depth": 3.29
+ }
+ }
+ },
+ {
+ "id": "plate_well",
+ "name": "plate_well",
+ "sample_id": null,
+ "children": [
+ "plate_well_A1",
+ "plate_well_B1",
+ "plate_well_C1",
+ "plate_well_D1",
+ "plate_well_E1",
+ "plate_well_F1",
+ "plate_well_G1",
+ "plate_well_H1",
+ "plate_well_A11",
+ "plate_well_B11",
+ "plate_well_C11",
+ "plate_well_D11",
+ "plate_well_E11",
+ "plate_well_F11",
+ "plate_well_G11",
+ "plate_well_H11"
+ ],
+ "parent": "deck",
+ "type": "plate",
+ "class": "nest_96_wellplate_2ml_deep",
+ "position": {
+ "x": 265.0,
+ "y": 0,
+ "z": 69
+ },
+ "config": {
+ "type": "Plate",
+ "size_x": 127.76,
+ "size_y": 85.48,
+ "size_z": 14.2,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "plate",
+ "model": "Cor_96_wellplate_360ul_Fb",
+ "ordering": [
+ "A1",
+ "B1",
+ "C1",
+ "D1",
+ "E1",
+ "F1",
+ "G1",
+ "H1",
+ "A11",
+ "B11",
+ "C11",
+ "D11",
+ "E11",
+ "F11",
+ "G11",
+ "H11"
+ ]
+ },
+ "data": {}
+ },
+ {
+ "id": "plate_well_A1",
+ "name": "plate_well_A1",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 10.87,
+ "y": 70.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_B1",
+ "name": "plate_well_B1",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 10.87,
+ "y": 61.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_C1",
+ "name": "plate_well_C1",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 10.87,
+ "y": 52.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_D1",
+ "name": "plate_well_D1",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 10.87,
+ "y": 43.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_E1",
+ "name": "plate_well_E1",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 10.87,
+ "y": 34.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_F1",
+ "name": "plate_well_F1",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 10.87,
+ "y": 25.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_G1",
+ "name": "plate_well_G1",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 10.87,
+ "y": 16.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_H1",
+ "name": "plate_well_H1",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 10.87,
+ "y": 7.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_A11",
+ "name": "plate_well_A11",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 100.87,
+ "y": 70.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_B11",
+ "name": "plate_well_B11",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 100.87,
+ "y": 61.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_C11",
+ "name": "plate_well_C11",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 100.87,
+ "y": 52.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_D11",
+ "name": "plate_well_D11",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 100.87,
+ "y": 43.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_E11",
+ "name": "plate_well_E11",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 100.87,
+ "y": 34.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_F11",
+ "name": "plate_well_F11",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 100.87,
+ "y": 25.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_G11",
+ "name": "plate_well_G11",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 100.87,
+ "y": 16.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ },
+ {
+ "id": "plate_well_H11",
+ "name": "plate_well_H11",
+ "sample_id": null,
+ "children": [],
+ "parent": "plate_well",
+ "type": "device",
+ "class": "",
+ "position": {
+ "x": 100.87,
+ "y": 7.77,
+ "z": 3.03
+ },
+ "config": {
+ "type": "Well",
+ "size_x": 6.86,
+ "size_y": 6.86,
+ "size_z": 10.67,
+ "rotation": {
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "type": "Rotation"
+ },
+ "category": "well",
+ "model": null,
+ "max_volume": 360,
+ "material_z_thickness": 0.5,
+ "compute_volume_from_height": null,
+ "compute_height_from_volume": null,
+ "bottom_type": "flat",
+ "cross_section_type": "circle"
+ },
+ "data": {
+ "liquids": [],
+ "pending_liquids": [],
+ "liquid_history": []
+ }
+ }
+ ],
+ "links": []
+}
\ No newline at end of file
diff --git a/test/experiments/test_moveit.json b/test/experiments/test_moveit.json
new file mode 100644
index 0000000..41b003b
--- /dev/null
+++ b/test/experiments/test_moveit.json
@@ -0,0 +1,35 @@
+{
+ "nodes": [
+
+ {
+ "id": "benyao",
+ "name": "benyao",
+ "children": [
+ ],
+ "parent": null,
+ "type": "device",
+ "class": "moveit.arm_slider",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "z": 0
+ },
+ "config": {
+ "moveit_type": "arm_slider",
+ "joint_poses": {
+ "arm": {
+ "home": [0.0, 0.2, 0.0, 0.0, 0.0],
+ "pick": [1.2, 0.0, 0.0, 0.0, 0.0]
+ }
+ },
+ "device_config": {
+ }
+ },
+ "data": {
+ }
+ }
+ ],
+ "links": [
+
+ ]
+}
\ No newline at end of file
diff --git a/unilabos/app/main.py b/unilabos/app/main.py
index 0db290a..0f6b2f4 100644
--- a/unilabos/app/main.py
+++ b/unilabos/app/main.py
@@ -10,6 +10,8 @@ from copy import deepcopy
import yaml
+from unilabos.resources.graphio import tree_to_list
+
# 首先添加项目根目录到路径
current_dir = os.path.dirname(os.path.abspath(__file__))
unilabos_dir = os.path.dirname(os.path.dirname(current_dir))
@@ -144,19 +146,19 @@ def main():
else read_graphml(args_dict["graph"])
)
devices_and_resources = dict_from_graph(graph_res.physical_setup_graph)
- args_dict["resources_config"] = initialize_resources(list(deepcopy(devices_and_resources).values()))
+ # args_dict["resources_config"] = initialize_resources(list(deepcopy(devices_and_resources).values()))
+ args_dict["resources_config"] = list(devices_and_resources.values())
args_dict["devices_config"] = dict_to_nested_dict(deepcopy(devices_and_resources), devices_only=False)
- # args_dict["resources_config"] = dict_to_tree(devices_and_resources, devices_only=False)
-
args_dict["graph"] = graph_res.physical_setup_graph
else:
if args_dict["devices"] is None or args_dict["resources"] is None:
print_status("Either graph or devices and resources must be provided.", "error")
sys.exit(1)
args_dict["devices_config"] = json.load(open(args_dict["devices"], encoding="utf-8"))
- args_dict["resources_config"] = initialize_resources(
- list(json.load(open(args_dict["resources"], encoding="utf-8")).values())
- )
+ # args_dict["resources_config"] = initialize_resources(
+ # list(json.load(open(args_dict["resources"], encoding="utf-8")).values())
+ # )
+ args_dict["resources_config"] = list(json.load(open(args_dict["resources"], encoding="utf-8")).values())
print_status(f"{len(args_dict['resources_config'])} Resources loaded:", "info")
for i in args_dict["resources_config"]:
diff --git a/unilabos/app/mq.py b/unilabos/app/mq.py
index 9f87069..fbd57b9 100644
--- a/unilabos/app/mq.py
+++ b/unilabos/app/mq.py
@@ -1,6 +1,7 @@
import json
import time
import traceback
+from typing import Optional
import uuid
import paho.mqtt.client as mqtt
@@ -161,12 +162,14 @@ class MQTTClient:
status = {"data": device_status.get(device_id, {}), "device_id": device_id}
address = f"labs/{MQConfig.lab_id}/devices/"
self.client.publish(address, json.dumps(status), qos=2)
- logger.critical(f"Device status published: address: {address}, {status}")
+ logger.debug(f"Device status published: address: {address}, {status}")
- def publish_job_status(self, feedback_data: dict, job_id: str, status: str):
+ def publish_job_status(self, feedback_data: dict, job_id: str, status: str, return_info: Optional[str] = None):
if self.mqtt_disable:
return
- jobdata = {"job_id": job_id, "data": feedback_data, "status": status}
+ if return_info is None:
+ return_info = "{}"
+ jobdata = {"job_id": job_id, "data": feedback_data, "status": status, "return_info": return_info}
self.client.publish(f"labs/{MQConfig.lab_id}/job/list/", json.dumps(jobdata), qos=2)
def publish_registry(self, device_id: str, device_info: dict):
diff --git a/unilabos/app/web/client.py b/unilabos/app/web/client.py
index da5d069..6932948 100644
--- a/unilabos/app/web/client.py
+++ b/unilabos/app/web/client.py
@@ -30,18 +30,18 @@ class HTTPClient:
self.auth = MQConfig.lab_id
info(f"HTTPClient 初始化完成: remote_addr={self.remote_addr}")
- def resource_add(self, resources: List[Dict[str, Any]]) -> requests.Response:
+ def resource_add(self, resources: List[Dict[str, Any]], database_process_later:bool) -> requests.Response:
"""
添加资源
Args:
resources: 要添加的资源列表
-
+ database_process_later: 后台处理资源
Returns:
Response: API响应对象
"""
response = requests.post(
- f"{self.remote_addr}/lab/resource/",
+ f"{self.remote_addr}/lab/resource/?database_process_later={1 if database_process_later else 0}",
json=resources,
headers={"Authorization": f"lab {self.auth}"},
timeout=5,
@@ -60,7 +60,7 @@ class HTTPClient:
Dict: 返回的资源数据
"""
response = requests.get(
- f"{self.remote_addr}/lab/resource/",
+ f"{self.remote_addr}/lab/resource/?edge_format=1",
params={"id": id, "with_children": with_children},
headers={"Authorization": f"lab {self.auth}"},
timeout=5,
@@ -96,7 +96,7 @@ class HTTPClient:
Response: API响应对象
"""
response = requests.patch(
- f"{self.remote_addr}/lab/resource/batch_update/",
+ f"{self.remote_addr}/lab/resource/batch_update/?edge_format=1",
json=resources,
headers={"Authorization": f"lab {self.auth}"},
timeout=5,
diff --git a/unilabos/device_mesh/devices/arm_slider/config/initial_positions.yaml b/unilabos/device_mesh/devices/arm_slider/config/initial_positions.yaml
new file mode 100644
index 0000000..94fb9f5
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/initial_positions.yaml
@@ -0,0 +1,9 @@
+# Default initial positions for full_dev's ros2_control fake system
+
+initial_positions:
+ arm_base_joint: 0
+ arm_link_1_joint: 0
+ arm_link_2_joint: 0
+ arm_link_3_joint: 0
+ gripper_base_joint: 0
+ gripper_right_joint: 0.03
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/arm_slider/config/joint_limits.yaml b/unilabos/device_mesh/devices/arm_slider/config/joint_limits.yaml
new file mode 100644
index 0000000..d4dffc3
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/joint_limits.yaml
@@ -0,0 +1,40 @@
+# joint_limits.yaml allows the dynamics properties specified in the URDF to be overwritten or augmented as needed
+
+# For beginners, we downscale velocity and acceleration limits.
+# You can always specify higher scaling factors (<= 1.0) in your motion requests. # Increase the values below to 1.0 to always move at maximum speed.
+default_velocity_scaling_factor: 0.1
+default_acceleration_scaling_factor: 0.1
+
+# Specific joint properties can be changed with the keys [max_position, min_position, max_velocity, max_acceleration]
+# Joint limits can be turned off with [has_velocity_limits, has_acceleration_limits]
+joint_limits:
+ arm_base_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ arm_link_1_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ arm_link_2_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ arm_link_3_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ gripper_base_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ gripper_right_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/arm_slider/config/kinematics.yaml b/unilabos/device_mesh/devices/arm_slider/config/kinematics.yaml
new file mode 100644
index 0000000..c9a5d60
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/kinematics.yaml
@@ -0,0 +1,4 @@
+arm:
+ kinematics_solver: lma_kinematics_plugin/LMAKinematicsPlugin
+ kinematics_solver_search_resolution: 0.0050000000000000001
+ kinematics_solver_timeout: 0.0050000000000000001
diff --git a/unilabos/device_mesh/devices/arm_slider/config/macro.ros2_control.xacro b/unilabos/device_mesh/devices/arm_slider/config/macro.ros2_control.xacro
new file mode 100644
index 0000000..026d977
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/macro.ros2_control.xacro
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+ mock_components/GenericSystem
+
+
+
+
+ ${initial_positions['arm_base_joint']}
+
+
+
+
+
+
+ ${initial_positions['arm_link_1_joint']}
+
+
+
+
+
+
+ ${initial_positions['arm_link_2_joint']}
+
+
+
+
+
+
+ ${initial_positions['arm_link_3_joint']}
+
+
+
+
+
+
+ ${initial_positions['gripper_base_joint']}
+
+
+
+
+
+
+ ${initial_positions['gripper_right_joint']}
+
+
+
+
+
+
+
diff --git a/unilabos/device_mesh/devices/arm_slider/config/macro.srdf.xacro b/unilabos/device_mesh/devices/arm_slider/config/macro.srdf.xacro
new file mode 100644
index 0000000..9c3ef9d
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/macro.srdf.xacro
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/unilabos/device_mesh/devices/arm_slider/config/move_group.json b/unilabos/device_mesh/devices/arm_slider/config/move_group.json
new file mode 100644
index 0000000..5be9ad3
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/move_group.json
@@ -0,0 +1,14 @@
+{
+ "arm":
+ {
+ "joint_names": [
+ "arm_base_joint",
+ "arm_link_1_joint",
+ "arm_link_2_joint",
+ "arm_link_3_joint",
+ "gripper_base_joint"
+ ],
+ "base_link_name": "device_link",
+ "end_effector_name": "gripper_base"
+ }
+}
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/arm_slider/config/moveit_controllers.yaml b/unilabos/device_mesh/devices/arm_slider/config/moveit_controllers.yaml
new file mode 100644
index 0000000..70a1b55
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/moveit_controllers.yaml
@@ -0,0 +1,29 @@
+# MoveIt uses this configuration for controller management
+
+moveit_controller_manager: moveit_simple_controller_manager/MoveItSimpleControllerManager
+
+moveit_simple_controller_manager:
+ controller_names:
+ - arm_controller
+ - gripper_controller
+
+ arm_controller:
+ type: FollowJointTrajectory
+ action_ns: follow_joint_trajectory
+ default: true
+ joints:
+ - arm_base_joint
+ - arm_link_1_joint
+ - arm_link_2_joint
+ - arm_link_3_joint
+ - gripper_base_joint
+ action_ns: follow_joint_trajectory
+ default: true
+ gripper_controller:
+ type: FollowJointTrajectory
+ action_ns: follow_joint_trajectory
+ default: true
+ joints:
+ - gripper_right_joint
+ action_ns: follow_joint_trajectory
+ default: true
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/arm_slider/config/moveit_planners.yaml b/unilabos/device_mesh/devices/arm_slider/config/moveit_planners.yaml
new file mode 100644
index 0000000..8560e1c
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/moveit_planners.yaml
@@ -0,0 +1,2 @@
+planner_configs:
+ - ompl_interface/OMPLPlanner
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/arm_slider/config/pilz_cartesian_limits.yaml b/unilabos/device_mesh/devices/arm_slider/config/pilz_cartesian_limits.yaml
new file mode 100644
index 0000000..b2997ca
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/pilz_cartesian_limits.yaml
@@ -0,0 +1,6 @@
+# Limits for the Pilz planner
+cartesian_limits:
+ max_trans_vel: 1.0
+ max_trans_acc: 2.25
+ max_trans_dec: -5.0
+ max_rot_vel: 1.57
diff --git a/unilabos/device_mesh/devices/arm_slider/config/ros2_controllers.yaml b/unilabos/device_mesh/devices/arm_slider/config/ros2_controllers.yaml
new file mode 100644
index 0000000..9c68cbf
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/config/ros2_controllers.yaml
@@ -0,0 +1,39 @@
+# This config file is used by ros2_control
+controller_manager:
+ ros__parameters:
+ update_rate: 100 # Hz
+
+ arm_controller:
+ type: joint_trajectory_controller/JointTrajectoryController
+
+
+ gripper_controller:
+ type: joint_trajectory_controller/JointTrajectoryController
+
+
+ joint_state_broadcaster:
+ type: joint_state_broadcaster/JointStateBroadcaster
+
+arm_controller:
+ ros__parameters:
+ joints:
+ - arm_base_joint
+ - arm_link_1_joint
+ - arm_link_2_joint
+ - arm_link_3_joint
+ - gripper_base_joint
+ command_interfaces:
+ - position
+ state_interfaces:
+ - position
+ - velocity
+
+gripper_controller:
+ ros__parameters:
+ joints:
+ - gripper_right_joint
+ command_interfaces:
+ - position
+ state_interfaces:
+ - position
+ - velocity
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/arm_slider/joint_limit.yaml b/unilabos/device_mesh/devices/arm_slider/joint_limit.yaml
new file mode 100644
index 0000000..b141262
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/joint_limit.yaml
@@ -0,0 +1,44 @@
+joint_limits:
+
+ arm_base_joint:
+ effort: 50
+ velocity: 1.0
+ lower: 0
+ upper: 1.5
+
+ arm_link_1_joint:
+ effort: 50
+ velocity: 1.0
+ lower: 0
+ upper: 0.6
+
+ arm_link_2_joint:
+ effort: 50
+ velocity: 1.0
+ lower: !degrees -95
+ upper: !degrees 95
+
+ arm_link_3_joint:
+ effort: 50
+ velocity: 1.0
+ lower: !degrees -195
+ upper: !degrees 195
+
+ gripper_base_joint:
+ effort: 50
+ velocity: 1.0
+ lower: !degrees -95
+ upper: !degrees 95
+
+
+ gripper_right_joint:
+ effort: 50
+ velocity: 1.0
+ lower: 0
+ upper: 0.03
+
+ gripper_left_joint:
+ effort: 50
+ velocity: 1.0
+ lower: 0
+ upper: 0.03
diff --git a/unilabos/device_mesh/devices/arm_slider/macro_device.xacro b/unilabos/device_mesh/devices/arm_slider/macro_device.xacro
new file mode 100644
index 0000000..871229d
--- /dev/null
+++ b/unilabos/device_mesh/devices/arm_slider/macro_device.xacro
@@ -0,0 +1,293 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/arm_slider/meshes/arm_base.STL b/unilabos/device_mesh/devices/arm_slider/meshes/arm_base.STL
new file mode 100644
index 0000000..804e1c6
Binary files /dev/null and b/unilabos/device_mesh/devices/arm_slider/meshes/arm_base.STL differ
diff --git a/unilabos/device_mesh/devices/arm_slider/meshes/arm_link_1.STL b/unilabos/device_mesh/devices/arm_slider/meshes/arm_link_1.STL
new file mode 100644
index 0000000..dd1d7c1
Binary files /dev/null and b/unilabos/device_mesh/devices/arm_slider/meshes/arm_link_1.STL differ
diff --git a/unilabos/device_mesh/devices/arm_slider/meshes/arm_link_2.STL b/unilabos/device_mesh/devices/arm_slider/meshes/arm_link_2.STL
new file mode 100644
index 0000000..6042fa0
Binary files /dev/null and b/unilabos/device_mesh/devices/arm_slider/meshes/arm_link_2.STL differ
diff --git a/unilabos/device_mesh/devices/arm_slider/meshes/arm_link_3.STL b/unilabos/device_mesh/devices/arm_slider/meshes/arm_link_3.STL
new file mode 100644
index 0000000..e8510fb
Binary files /dev/null and b/unilabos/device_mesh/devices/arm_slider/meshes/arm_link_3.STL differ
diff --git a/unilabos/device_mesh/devices/arm_slider/meshes/arm_slideway.STL b/unilabos/device_mesh/devices/arm_slider/meshes/arm_slideway.STL
new file mode 100644
index 0000000..65737ab
Binary files /dev/null and b/unilabos/device_mesh/devices/arm_slider/meshes/arm_slideway.STL differ
diff --git a/unilabos/device_mesh/devices/arm_slider/meshes/gripper_base.STL b/unilabos/device_mesh/devices/arm_slider/meshes/gripper_base.STL
new file mode 100644
index 0000000..5de88d0
Binary files /dev/null and b/unilabos/device_mesh/devices/arm_slider/meshes/gripper_base.STL differ
diff --git a/unilabos/device_mesh/devices/arm_slider/meshes/gripper_left.STL b/unilabos/device_mesh/devices/arm_slider/meshes/gripper_left.STL
new file mode 100644
index 0000000..0a5fd52
Binary files /dev/null and b/unilabos/device_mesh/devices/arm_slider/meshes/gripper_left.STL differ
diff --git a/unilabos/device_mesh/devices/arm_slider/meshes/gripper_right.STL b/unilabos/device_mesh/devices/arm_slider/meshes/gripper_right.STL
new file mode 100644
index 0000000..0c5ac69
Binary files /dev/null and b/unilabos/device_mesh/devices/arm_slider/meshes/gripper_right.STL differ
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/initial_positions.yaml b/unilabos/device_mesh/devices/benyao_arm/config/initial_positions.yaml
new file mode 100644
index 0000000..94fb9f5
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/initial_positions.yaml
@@ -0,0 +1,9 @@
+# Default initial positions for full_dev's ros2_control fake system
+
+initial_positions:
+ arm_base_joint: 0
+ arm_link_1_joint: 0
+ arm_link_2_joint: 0
+ arm_link_3_joint: 0
+ gripper_base_joint: 0
+ gripper_right_joint: 0.03
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/joint_limits.yaml b/unilabos/device_mesh/devices/benyao_arm/config/joint_limits.yaml
new file mode 100644
index 0000000..d4dffc3
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/joint_limits.yaml
@@ -0,0 +1,40 @@
+# joint_limits.yaml allows the dynamics properties specified in the URDF to be overwritten or augmented as needed
+
+# For beginners, we downscale velocity and acceleration limits.
+# You can always specify higher scaling factors (<= 1.0) in your motion requests. # Increase the values below to 1.0 to always move at maximum speed.
+default_velocity_scaling_factor: 0.1
+default_acceleration_scaling_factor: 0.1
+
+# Specific joint properties can be changed with the keys [max_position, min_position, max_velocity, max_acceleration]
+# Joint limits can be turned off with [has_velocity_limits, has_acceleration_limits]
+joint_limits:
+ arm_base_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ arm_link_1_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ arm_link_2_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ arm_link_3_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ gripper_base_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ gripper_right_joint:
+ has_velocity_limits: true
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/kinematics.yaml b/unilabos/device_mesh/devices/benyao_arm/config/kinematics.yaml
new file mode 100644
index 0000000..c9a5d60
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/kinematics.yaml
@@ -0,0 +1,4 @@
+arm:
+ kinematics_solver: lma_kinematics_plugin/LMAKinematicsPlugin
+ kinematics_solver_search_resolution: 0.0050000000000000001
+ kinematics_solver_timeout: 0.0050000000000000001
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/macro.ros2_control.xacro b/unilabos/device_mesh/devices/benyao_arm/config/macro.ros2_control.xacro
new file mode 100644
index 0000000..70f8634
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/macro.ros2_control.xacro
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+ mock_components/GenericSystem
+
+
+
+
+ ${initial_positions['arm_base_joint']}
+
+
+
+
+
+
+ ${initial_positions['arm_link_1_joint']}
+
+
+
+
+
+
+ ${initial_positions['arm_link_2_joint']}
+
+
+
+
+
+
+ ${initial_positions['arm_link_3_joint']}
+
+
+
+
+
+
+ ${initial_positions['gripper_base_joint']}
+
+
+
+
+
+
+ ${initial_positions['gripper_right_joint']}
+
+
+
+
+
+
+
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/macro.srdf.xacro b/unilabos/device_mesh/devices/benyao_arm/config/macro.srdf.xacro
new file mode 100644
index 0000000..aeb5677
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/macro.srdf.xacro
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/move_group.json b/unilabos/device_mesh/devices/benyao_arm/config/move_group.json
new file mode 100644
index 0000000..5be9ad3
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/move_group.json
@@ -0,0 +1,14 @@
+{
+ "arm":
+ {
+ "joint_names": [
+ "arm_base_joint",
+ "arm_link_1_joint",
+ "arm_link_2_joint",
+ "arm_link_3_joint",
+ "gripper_base_joint"
+ ],
+ "base_link_name": "device_link",
+ "end_effector_name": "gripper_base"
+ }
+}
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/moveit_controllers.yaml b/unilabos/device_mesh/devices/benyao_arm/config/moveit_controllers.yaml
new file mode 100644
index 0000000..70a1b55
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/moveit_controllers.yaml
@@ -0,0 +1,29 @@
+# MoveIt uses this configuration for controller management
+
+moveit_controller_manager: moveit_simple_controller_manager/MoveItSimpleControllerManager
+
+moveit_simple_controller_manager:
+ controller_names:
+ - arm_controller
+ - gripper_controller
+
+ arm_controller:
+ type: FollowJointTrajectory
+ action_ns: follow_joint_trajectory
+ default: true
+ joints:
+ - arm_base_joint
+ - arm_link_1_joint
+ - arm_link_2_joint
+ - arm_link_3_joint
+ - gripper_base_joint
+ action_ns: follow_joint_trajectory
+ default: true
+ gripper_controller:
+ type: FollowJointTrajectory
+ action_ns: follow_joint_trajectory
+ default: true
+ joints:
+ - gripper_right_joint
+ action_ns: follow_joint_trajectory
+ default: true
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/moveit_planners.yaml b/unilabos/device_mesh/devices/benyao_arm/config/moveit_planners.yaml
new file mode 100644
index 0000000..8560e1c
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/moveit_planners.yaml
@@ -0,0 +1,2 @@
+planner_configs:
+ - ompl_interface/OMPLPlanner
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/pilz_cartesian_limits.yaml b/unilabos/device_mesh/devices/benyao_arm/config/pilz_cartesian_limits.yaml
new file mode 100644
index 0000000..b2997ca
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/pilz_cartesian_limits.yaml
@@ -0,0 +1,6 @@
+# Limits for the Pilz planner
+cartesian_limits:
+ max_trans_vel: 1.0
+ max_trans_acc: 2.25
+ max_trans_dec: -5.0
+ max_rot_vel: 1.57
diff --git a/unilabos/device_mesh/devices/benyao_arm/config/ros2_controllers.yaml b/unilabos/device_mesh/devices/benyao_arm/config/ros2_controllers.yaml
new file mode 100644
index 0000000..9c68cbf
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/config/ros2_controllers.yaml
@@ -0,0 +1,39 @@
+# This config file is used by ros2_control
+controller_manager:
+ ros__parameters:
+ update_rate: 100 # Hz
+
+ arm_controller:
+ type: joint_trajectory_controller/JointTrajectoryController
+
+
+ gripper_controller:
+ type: joint_trajectory_controller/JointTrajectoryController
+
+
+ joint_state_broadcaster:
+ type: joint_state_broadcaster/JointStateBroadcaster
+
+arm_controller:
+ ros__parameters:
+ joints:
+ - arm_base_joint
+ - arm_link_1_joint
+ - arm_link_2_joint
+ - arm_link_3_joint
+ - gripper_base_joint
+ command_interfaces:
+ - position
+ state_interfaces:
+ - position
+ - velocity
+
+gripper_controller:
+ ros__parameters:
+ joints:
+ - gripper_right_joint
+ command_interfaces:
+ - position
+ state_interfaces:
+ - position
+ - velocity
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/benyao_arm/joint_limit.yaml b/unilabos/device_mesh/devices/benyao_arm/joint_limit.yaml
new file mode 100644
index 0000000..b141262
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/joint_limit.yaml
@@ -0,0 +1,44 @@
+joint_limits:
+
+ arm_base_joint:
+ effort: 50
+ velocity: 1.0
+ lower: 0
+ upper: 1.5
+
+ arm_link_1_joint:
+ effort: 50
+ velocity: 1.0
+ lower: 0
+ upper: 0.6
+
+ arm_link_2_joint:
+ effort: 50
+ velocity: 1.0
+ lower: !degrees -95
+ upper: !degrees 95
+
+ arm_link_3_joint:
+ effort: 50
+ velocity: 1.0
+ lower: !degrees -195
+ upper: !degrees 195
+
+ gripper_base_joint:
+ effort: 50
+ velocity: 1.0
+ lower: !degrees -95
+ upper: !degrees 95
+
+
+ gripper_right_joint:
+ effort: 50
+ velocity: 1.0
+ lower: 0
+ upper: 0.03
+
+ gripper_left_joint:
+ effort: 50
+ velocity: 1.0
+ lower: 0
+ upper: 0.03
diff --git a/unilabos/device_mesh/devices/benyao_arm/macro_device.xacro b/unilabos/device_mesh/devices/benyao_arm/macro_device.xacro
new file mode 100644
index 0000000..137c916
--- /dev/null
+++ b/unilabos/device_mesh/devices/benyao_arm/macro_device.xacro
@@ -0,0 +1,293 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/benyao_arm/meshes/arm_base.STL b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_base.STL
new file mode 100644
index 0000000..804e1c6
Binary files /dev/null and b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_base.STL differ
diff --git a/unilabos/device_mesh/devices/benyao_arm/meshes/arm_link_1.STL b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_link_1.STL
new file mode 100644
index 0000000..dd1d7c1
Binary files /dev/null and b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_link_1.STL differ
diff --git a/unilabos/device_mesh/devices/benyao_arm/meshes/arm_link_2.STL b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_link_2.STL
new file mode 100644
index 0000000..6042fa0
Binary files /dev/null and b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_link_2.STL differ
diff --git a/unilabos/device_mesh/devices/benyao_arm/meshes/arm_link_3.STL b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_link_3.STL
new file mode 100644
index 0000000..e8510fb
Binary files /dev/null and b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_link_3.STL differ
diff --git a/unilabos/device_mesh/devices/benyao_arm/meshes/arm_slideway.STL b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_slideway.STL
new file mode 100644
index 0000000..65737ab
Binary files /dev/null and b/unilabos/device_mesh/devices/benyao_arm/meshes/arm_slideway.STL differ
diff --git a/unilabos/device_mesh/devices/benyao_arm/meshes/gripper_base.STL b/unilabos/device_mesh/devices/benyao_arm/meshes/gripper_base.STL
new file mode 100644
index 0000000..5de88d0
Binary files /dev/null and b/unilabos/device_mesh/devices/benyao_arm/meshes/gripper_base.STL differ
diff --git a/unilabos/device_mesh/devices/benyao_arm/meshes/gripper_left.STL b/unilabos/device_mesh/devices/benyao_arm/meshes/gripper_left.STL
new file mode 100644
index 0000000..0a5fd52
Binary files /dev/null and b/unilabos/device_mesh/devices/benyao_arm/meshes/gripper_left.STL differ
diff --git a/unilabos/device_mesh/devices/benyao_arm/meshes/gripper_right.STL b/unilabos/device_mesh/devices/benyao_arm/meshes/gripper_right.STL
new file mode 100644
index 0000000..0c5ac69
Binary files /dev/null and b/unilabos/device_mesh/devices/benyao_arm/meshes/gripper_right.STL differ
diff --git a/unilabos/device_mesh/devices/opentrons_liquid_handler/macro_device.xacro b/unilabos/device_mesh/devices/opentrons_liquid_handler/macro_device.xacro
index 4e66055..f76f654 100644
--- a/unilabos/device_mesh/devices/opentrons_liquid_handler/macro_device.xacro
+++ b/unilabos/device_mesh/devices/opentrons_liquid_handler/macro_device.xacro
@@ -3,11 +3,10 @@
-
+ params="parent_link:='' station_name:='' device_name:='' x:=0 y:=0 z:=0 rx:=0 ry:=0 r:=0 mesh_path:=''">
-
+
diff --git a/unilabos/device_mesh/devices/slide_w140/macro_device.xacro b/unilabos/device_mesh/devices/slide_w140/macro_device.xacro
index 7e43242..d6d93f9 100644
--- a/unilabos/device_mesh/devices/slide_w140/macro_device.xacro
+++ b/unilabos/device_mesh/devices/slide_w140/macro_device.xacro
@@ -8,11 +8,11 @@
For more information, please see http://wiki.ros.org/sw_urdf_exporter -->
-
+
-
+
diff --git a/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/hotel.png b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/hotel.png
new file mode 100644
index 0000000..daecc63
Binary files /dev/null and b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/hotel.png differ
diff --git a/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/macro_device.xacro b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/macro_device.xacro
new file mode 100644
index 0000000..52c9536
--- /dev/null
+++ b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/macro_device.xacro
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/meshes/hotel.glb b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/meshes/hotel.glb
new file mode 100644
index 0000000..724b85f
Binary files /dev/null and b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/meshes/hotel.glb differ
diff --git a/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/meshes/hotel.stl b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/meshes/hotel.stl
new file mode 100644
index 0000000..59cb908
Binary files /dev/null and b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/meshes/hotel.stl differ
diff --git a/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/meta.json b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/meta.json
new file mode 100644
index 0000000..b8f35cb
--- /dev/null
+++ b/unilabos/device_mesh/devices/thermo_orbitor_rs2_hotel/meta.json
@@ -0,0 +1,10 @@
+{
+ "fileName": "thermo_orbitor_rs2_hotel",
+ "related": [
+ "thermo_skyline_stacker",
+ "thermo_cytomat2c_stacker_15",
+ "thermo_fisher_cytomat_stacker_16",
+ "thermo_cytomat2c_stacker_21",
+ "thermo_orbitor_rs2_hotel"
+ ]
+}
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/full_dev.urdf.xacro b/unilabos/device_mesh/devices/toyo_xyz/config/full_dev.urdf.xacro
new file mode 100644
index 0000000..29bd48d
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/full_dev.urdf.xacro
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/initial_positions.yaml b/unilabos/device_mesh/devices/toyo_xyz/config/initial_positions.yaml
new file mode 100644
index 0000000..d44ccee
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/initial_positions.yaml
@@ -0,0 +1,6 @@
+# Default initial positions for full_dev's ros2_control fake system
+
+initial_positions:
+ slider1_joint: 0
+ slider2_joint: 0
+ slider3_joint: 0
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/joint_limits.yaml b/unilabos/device_mesh/devices/toyo_xyz/config/joint_limits.yaml
new file mode 100644
index 0000000..251b26c
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/joint_limits.yaml
@@ -0,0 +1,25 @@
+# joint_limits.yaml allows the dynamics properties specified in the URDF to be overwritten or augmented as needed
+
+# For beginners, we downscale velocity and acceleration limits.
+# You can always specify higher scaling factors (<= 1.0) in your motion requests. # Increase the values below to 1.0 to always move at maximum speed.
+default_velocity_scaling_factor: 0.1
+default_acceleration_scaling_factor: 0.1
+
+# Specific joint properties can be changed with the keys [max_position, min_position, max_velocity, max_acceleration]
+# Joint limits can be turned off with [has_velocity_limits, has_acceleration_limits]
+joint_limits:
+ slider1_joint:
+ has_velocity_limits: false
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ slider2_joint:
+ has_velocity_limits: false
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
+ slider3_joint:
+ has_velocity_limits: false
+ max_velocity: 0
+ has_acceleration_limits: false
+ max_acceleration: 0
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/kinematics.yaml b/unilabos/device_mesh/devices/toyo_xyz/config/kinematics.yaml
new file mode 100644
index 0000000..d11fa7b
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/kinematics.yaml
@@ -0,0 +1,4 @@
+toyo_xyz:
+ kinematics_solver: lma_kinematics_plugin/LMAKinematicsPlugin
+ kinematics_solver_search_resolution: 0.0050000000000000001
+ kinematics_solver_timeout: 0.0050000000000000001
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/macro.ros2_control.xacro b/unilabos/device_mesh/devices/toyo_xyz/config/macro.ros2_control.xacro
new file mode 100644
index 0000000..5bc3404
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/macro.ros2_control.xacro
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+ mock_components/GenericSystem
+
+
+
+
+ ${initial_positions['slider1_joint']}
+
+
+
+
+
+
+ ${initial_positions['slider2_joint']}
+
+
+
+
+
+
+ ${initial_positions['slider3_joint']}
+
+
+
+
+
+
+
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/macro.srdf.xacro b/unilabos/device_mesh/devices/toyo_xyz/config/macro.srdf.xacro
new file mode 100644
index 0000000..753382f
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/macro.srdf.xacro
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/move_group.json b/unilabos/device_mesh/devices/toyo_xyz/config/move_group.json
new file mode 100644
index 0000000..d900674
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/move_group.json
@@ -0,0 +1,12 @@
+{
+ "toyo_xyz":
+ {
+ "joint_names": [
+ "slider1_joint",
+ "slider2_joint",
+ "slider3_joint"
+ ],
+ "base_link_name": "device_link",
+ "end_effector_name": "slider3_link"
+ }
+}
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/moveit_controllers.yaml b/unilabos/device_mesh/devices/toyo_xyz/config/moveit_controllers.yaml
new file mode 100644
index 0000000..0fcac51
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/moveit_controllers.yaml
@@ -0,0 +1,16 @@
+# MoveIt uses this configuration for controller management
+
+moveit_controller_manager: moveit_simple_controller_manager/MoveItSimpleControllerManager
+
+moveit_simple_controller_manager:
+ controller_names:
+ - toyo_xyz_controller
+
+ toyo_xyz_controller:
+ type: FollowJointTrajectory
+ action_ns: follow_joint_trajectory
+ default: true
+ joints:
+ - slider1_joint
+ - slider2_joint
+ - slider3_joint
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/pilz_cartesian_limits.yaml b/unilabos/device_mesh/devices/toyo_xyz/config/pilz_cartesian_limits.yaml
new file mode 100644
index 0000000..b2997ca
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/pilz_cartesian_limits.yaml
@@ -0,0 +1,6 @@
+# Limits for the Pilz planner
+cartesian_limits:
+ max_trans_vel: 1.0
+ max_trans_acc: 2.25
+ max_trans_dec: -5.0
+ max_rot_vel: 1.57
diff --git a/unilabos/device_mesh/devices/toyo_xyz/config/ros2_controllers.yaml b/unilabos/device_mesh/devices/toyo_xyz/config/ros2_controllers.yaml
new file mode 100644
index 0000000..1d1a552
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/config/ros2_controllers.yaml
@@ -0,0 +1,34 @@
+# This config file is used by ros2_control
+controller_manager:
+
+ ros__parameters:
+ update_rate: 100 # Hz
+
+ joint_state_broadcaster:
+ type: joint_state_broadcaster/JointStateBroadcaster
+ # action_ns: $(var device_id)
+ toyo_xyz_controller:
+ type: joint_trajectory_controller/JointTrajectoryController
+
+# joint_state_broadcaster:
+# ros__parameters: {}
+
+toyo_xyz_controller:
+ ros__parameters:
+ joints:
+ - slider1_joint
+ - slider2_joint
+ - slider3_joint
+ command_interfaces:
+ - position
+ state_interfaces:
+ - position
+ - velocity
+ allow_partial_joints_goal: false
+ open_loop_control: true
+ allow_integration_in_goal_trajectories: true
+ action_monitor_rate: 20.0
+ # goal_time: 0.0
+ # constraints:
+ # stopped_velocity_tolerance: 0.01
+ # goal_time: 0.0
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/toyo_xyz/joint_config.json b/unilabos/device_mesh/devices/toyo_xyz/joint_config.json
new file mode 100644
index 0000000..26bda26
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/joint_config.json
@@ -0,0 +1,14 @@
+{
+ "slider1_joint": {
+ "child":"slider1_link",
+ "axis" : "x"
+ },
+ "slider2_joint": {
+ "child":"slider2_link",
+ "axis" : "x"
+ },
+ "slider3_joint": {
+ "child":"slider3_link",
+ "axis" : "x"
+ }
+}
\ No newline at end of file
diff --git a/unilabos/device_mesh/devices/toyo_xyz/macro_device.xacro b/unilabos/device_mesh/devices/toyo_xyz/macro_device.xacro
new file mode 100644
index 0000000..5694c35
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/macro_device.xacro
@@ -0,0 +1,465 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/base2_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/base2_link.STL
new file mode 100755
index 0000000..ded0641
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/base2_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/base2_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/base2_link.fbx
new file mode 100644
index 0000000..a278cc6
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/base2_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/base3_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/base3_link.STL
new file mode 100755
index 0000000..d1dba51
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/base3_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/base3_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/base3_link.fbx
new file mode 100644
index 0000000..8c28d39
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/base3_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/base_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/base_link.STL
new file mode 100755
index 0000000..24205e5
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/base_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/base_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/base_link.fbx
new file mode 100644
index 0000000..5a24339
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/base_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/chain_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/chain_link.STL
new file mode 100755
index 0000000..fcbfdce
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/chain_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/chain_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/chain_link.fbx
new file mode 100644
index 0000000..8bd35db
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/chain_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/end2_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/end2_link.STL
new file mode 100755
index 0000000..1b72d5d
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/end2_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/end2_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/end2_link.fbx
new file mode 100644
index 0000000..0107961
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/end2_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/end3_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/end3_link.STL
new file mode 100755
index 0000000..ce0dd9f
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/end3_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/end3_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/end3_link.fbx
new file mode 100644
index 0000000..f0e55b5
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/end3_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/end_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/end_link.STL
new file mode 100755
index 0000000..6f5e504
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/end_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/end_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/end_link.fbx
new file mode 100644
index 0000000..4ba363c
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/end_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/fixed_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/fixed_link.STL
new file mode 100755
index 0000000..7a064cc
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/fixed_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/fixed_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/fixed_link.fbx
new file mode 100644
index 0000000..ea46d65
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/fixed_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/length1_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/length1_link.STL
new file mode 100755
index 0000000..9eb85cd
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/length1_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/length1_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/length1_link.fbx
new file mode 100644
index 0000000..5375fce
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/length1_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/length2_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/length2_link.STL
new file mode 100755
index 0000000..3ffad0f
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/length2_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/length2_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/length2_link.fbx
new file mode 100644
index 0000000..f94c5a6
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/length2_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/length3_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/length3_link.STL
new file mode 100755
index 0000000..1afcdd2
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/length3_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/length3_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/length3_link.fbx
new file mode 100644
index 0000000..a812b4c
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/length3_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/slider1_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider1_link.STL
new file mode 100755
index 0000000..9ef91e2
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider1_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/slider1_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider1_link.fbx
new file mode 100644
index 0000000..e2a7c86
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider1_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/slider2_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider2_link.STL
new file mode 100755
index 0000000..abd8c56
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider2_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/slider2_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider2_link.fbx
new file mode 100644
index 0000000..a46df10
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider2_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/slider3_link.STL b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider3_link.STL
new file mode 100755
index 0000000..a0bfb16
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider3_link.STL differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/meshes/slider3_link.fbx b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider3_link.fbx
new file mode 100644
index 0000000..6cec964
Binary files /dev/null and b/unilabos/device_mesh/devices/toyo_xyz/meshes/slider3_link.fbx differ
diff --git a/unilabos/device_mesh/devices/toyo_xyz/param_config.json b/unilabos/device_mesh/devices/toyo_xyz/param_config.json
new file mode 100644
index 0000000..457332b
--- /dev/null
+++ b/unilabos/device_mesh/devices/toyo_xyz/param_config.json
@@ -0,0 +1,20 @@
+{
+ "private_param":
+ {
+ "min_d1": 0.01 ,
+ "max_d1": 0.01 ,
+ "slider_d1": 0.135,
+ "min_d2": 0.01 ,
+ "max_d2": 0.01 ,
+ "slider_d2": 0.116,
+ "min_d3": 0.01 ,
+ "max_d3": 0.01 ,
+ "slider_d3": 0.09
+ },
+ "public_param":
+ {
+ "length1" :0.5,
+ "length2" :0.2,
+ "length3" :0.2
+ }
+}
\ No newline at end of file
diff --git a/unilabos/device_mesh/resource_visalization.py b/unilabos/device_mesh/resource_visalization.py
index b840789..cea7afc 100644
--- a/unilabos/device_mesh/resource_visalization.py
+++ b/unilabos/device_mesh/resource_visalization.py
@@ -1,13 +1,38 @@
+import json
import os
from pathlib import Path
+import re
+
+import yaml
from launch import LaunchService
from launch import LaunchDescription
from launch_ros.actions import Node as nd
import xacro
from lxml import etree
-
+from launch_param_builder import load_yaml
+from launch_ros.parameter_descriptions import ParameterFile
from unilabos.registry.registry import lab_registry
+from ament_index_python.packages import get_package_share_directory
+def get_pattern_matches(folder, pattern):
+ """Given all the files in the folder, find those that match the pattern.
+
+ If there are groups defined, the groups are returned. Otherwise the path to the matches are returned.
+ """
+ matches = []
+ if not folder.exists():
+ return matches
+ for child in folder.iterdir():
+ if not child.is_file():
+ continue
+ m = pattern.search(child.name)
+ if m:
+ groups = m.groups()
+ if groups:
+ matches.append(groups[0])
+ else:
+ matches.append(child)
+ return matches
class ResourceVisualization:
def __init__(self, device: dict, resource: dict, enable_rviz: bool = True):
@@ -31,9 +56,8 @@ class ResourceVisualization:
self.enable_rviz = enable_rviz
registry = lab_registry
- self.srdf_str = '''
-
-
+ self.srdf_str = '''
+
'''
@@ -43,23 +67,46 @@ class ResourceVisualization:
'''
self.root = etree.fromstring(self.robot_state_str)
+ self.root_srdf = etree.fromstring(self.srdf_str)
xacro_uri = self.root.nsmap["xacro"]
+ self.moveit_nodes = {}
+ self.moveit_nodes_kinematics = {}
+ self.moveit_controllers_yaml = {
+ "moveit_controller_manager": "moveit_simple_controller_manager/MoveItSimpleControllerManager",
+ "moveit_simple_controller_manager": {
+ "controller_names": []
+ }
+ }
+ self.ros2_controllers_yaml = {
+ "controller_manager": {
+ "ros__parameters": {
+ "update_rate": 100,
+ "joint_state_broadcaster": {
+ "type": "joint_state_broadcaster/JointStateBroadcaster",
+ }
+ }
+ }
+ }
+
# 遍历设备节点
for node in device.values():
- if node['type'] == 'device' and node['class'] != '':
- device_class = node['class']
- # 检查设备类型是否在注册表中
- if device_class not in registry.device_type_registry.keys():
- raise ValueError(f"设备类型 {device_class} 未在注册表中注册")
- elif node['type'] in self.resource_type:
- # print(registry.resource_type_registry)
- resource_class = node['class']
- if resource_class not in registry.resource_type_registry.keys():
- raise ValueError(f"资源类型 {resource_class} 未在注册表中注册")
- elif "model" in registry.resource_type_registry[resource_class].keys():
- model_config = registry.resource_type_registry[resource_class]['model']
+ if node['type'] in self.resource_type or (node['type'] == 'device' and node['class'] != ''):
+ model_config = {}
+ if node['type'] in self.resource_type:
+ resource_class = node['class']
+ if resource_class not in registry.resource_type_registry.keys():
+ raise ValueError(f"资源类型 {resource_class} 未在注册表中注册")
+ elif "model" in registry.resource_type_registry[resource_class].keys():
+ model_config = registry.resource_type_registry[resource_class]['model']
+ elif node['type'] == 'device' and node['class'] != '':
+ device_class = node['class']
+ if device_class not in registry.device_type_registry.keys():
+ raise ValueError(f"设备类型 {device_class} 未在注册表中注册")
+ elif "model" in registry.device_type_registry[device_class].keys():
+ model_config = registry.device_type_registry[device_class]['model']
+ if model_config:
if model_config['type'] == 'resource':
self.resource_model[node['id']] = {
'mesh': f"{str(self.mesh_path)}/resources/{model_config['mesh']}",
@@ -71,18 +118,45 @@ class ResourceVisualization:
'mesh_tf': model_config['children_mesh_tf']
}
elif model_config['type'] == 'device':
+
new_include = etree.SubElement(self.root, f"{{{xacro_uri}}}include")
new_include.set("filename", f"{str(self.mesh_path)}/devices/{model_config['mesh']}/macro_device.xacro")
new_dev = etree.SubElement(self.root, f"{{{xacro_uri}}}{model_config['mesh']}")
new_dev.set("parent_link", "world")
new_dev.set("mesh_path", str(self.mesh_path))
new_dev.set("device_name", node["id"]+"_")
- new_dev.set("station_name", node["parent"]+'_')
+ # if node["parent"] is not None:
+ # new_dev.set("station_name", node["parent"]+'_')
+
+ print('o'*20)
+ node["parent"]
+ node["id"]
+ print('o'*20)
new_dev.set("x",str(float(node["position"]["x"])/1000))
new_dev.set("y",str(float(node["position"]["y"])/1000))
new_dev.set("z",str(float(node["position"]["z"])/1000))
if "rotation" in node["config"]:
- new_dev.set("r",str(float(node["config"]["rotation"]["z"])/1000))
+ new_dev.set("rx",str(float(node["config"]["rotation"]["x"])))
+ new_dev.set("ry",str(float(node["config"]["rotation"]["y"])))
+ new_dev.set("r",str(float(node["config"]["rotation"]["z"])))
+ if "device_config" in node["config"]:
+ for key, value in node["config"]["device_config"].items():
+ new_dev.set(key, str(float(value)))
+
+ # 添加ros2_controller
+ if node['class'].startswith('moveit.'):
+ new_include_controller = etree.SubElement(self.root, f"{{{xacro_uri}}}include")
+ new_include_controller.set("filename", f"{str(self.mesh_path)}/devices/{model_config['mesh']}/config/macro.ros2_control.xacro")
+ new_controller = etree.SubElement(self.root, f"{{{xacro_uri}}}{model_config['mesh']}_ros2_control")
+ new_controller.set("device_name", node["id"]+"_")
+ new_controller.set("mesh_path", str(self.mesh_path))
+
+ # 添加moveit的srdf
+ new_include_srdf = etree.SubElement(self.root_srdf, f"{{{xacro_uri}}}include")
+ new_include_srdf.set("filename", f"{str(self.mesh_path)}/devices/{model_config['mesh']}/config/macro.srdf.xacro")
+ new_srdf = etree.SubElement(self.root_srdf, f"{{{xacro_uri}}}{model_config['mesh']}_srdf")
+ new_srdf.set("device_name", node["id"]+"_")
+ self.moveit_nodes[node["id"]] = model_config['mesh']
else:
print("错误的注册表类型!")
re = etree.tostring(self.root, encoding="unicode")
@@ -90,8 +164,37 @@ class ResourceVisualization:
xacro.process_doc(doc)
self.urdf_str = doc.toxml()
+ re_srdf = etree.tostring(self.root_srdf, encoding="unicode")
+ doc_srdf = xacro.parse(re_srdf)
+ xacro.process_doc(doc_srdf)
+ self.urdf_str_srdf = doc_srdf.toxml()
+ if self.moveit_nodes:
+ self.moveit_init()
- def create_launch_description(self, urdf_str: str) -> LaunchDescription:
+ def moveit_init(self):
+
+ for name, config in self.moveit_nodes.items():
+ controller_dict = yaml.safe_load(open(f"{str(self.mesh_path)}/devices/{config}/config/ros2_controllers.yaml", "r"))
+ moveit_dict = yaml.safe_load(open(f"{str(self.mesh_path)}/devices/{config}/config/moveit_controllers.yaml", "r"))
+ kinematics_dict = yaml.safe_load(open(f"{str(self.mesh_path)}/devices/{config}/config/kinematics.yaml", "r"))
+
+ for key_kinematics, value_kinematics in kinematics_dict.items():
+ self.moveit_nodes_kinematics[f'{name}_{key_kinematics}'] = value_kinematics
+
+ for key, value in controller_dict['controller_manager']['ros__parameters'].items():
+ if key == 'update_rate' or key == 'joint_state_broadcaster':
+ continue
+ self.ros2_controllers_yaml['controller_manager']['ros__parameters'][f"{name}_{key}"] = value
+ controller_dict[key]['ros__parameters']['joints'] = [f"{name}_{joint}" for joint in controller_dict[key]['ros__parameters']['joints']]
+ self.ros2_controllers_yaml[f"{name}_{key}"] = controller_dict[key]
+
+ for controller_name in moveit_dict['moveit_simple_controller_manager']['controller_names']:
+ self.moveit_controllers_yaml['moveit_simple_controller_manager']['controller_names'].append(f"{name}_{controller_name}")
+ moveit_dict['moveit_simple_controller_manager'][controller_name]['joints'] = [f"{name}_{joint}" for joint in moveit_dict['moveit_simple_controller_manager'][controller_name]['joints']]
+ self.moveit_controllers_yaml['moveit_simple_controller_manager'][f"{name}_{controller_name}"] = moveit_dict['moveit_simple_controller_manager'][controller_name]
+
+
+ def create_launch_description(self) -> LaunchDescription:
"""
创建launch描述,包含robot_state_publisher和move_group节点
@@ -101,10 +204,93 @@ class ResourceVisualization:
Returns:
LaunchDescription: launch描述对象
"""
+ moveit_configs_utils_path = Path(get_package_share_directory("moveit_configs_utils"))
+ default_folder = moveit_configs_utils_path / "default_configs"
+ planning_pattern = re.compile("^(.*)_planning.yaml$")
+ pipelines = []
-
+ for pipeline in get_pattern_matches(default_folder, planning_pattern):
+ if pipeline not in pipelines:
+ pipelines.append(pipeline)
+
+ if "ompl" in pipelines:
+ default_planning_pipeline = "ompl"
+ else:
+ default_planning_pipeline = pipelines[0]
+
+ planning_pipelines = {
+ "planning_pipelines": pipelines,
+ "default_planning_pipeline": default_planning_pipeline,
+ }
+
+ for pipeline in pipelines:
+ planning_pipelines[pipeline] = load_yaml(
+ default_folder / f"{pipeline}_planning.yaml"
+ )
+
+ if "ompl" in planning_pipelines:
+ ompl_config = planning_pipelines["ompl"]
+ if "planner_configs" not in ompl_config:
+ ompl_config.update(load_yaml(default_folder / "ompl_defaults.yaml"))
+
+ yaml.safe_dump(self.ros2_controllers_yaml, open(f"{str(self.mesh_path)}/ros2_controllers.yaml", "w"))
+
+ robot_description_planning = {
+ "default_velocity_scaling_factor": 0.1,
+ "default_acceleration_scaling_factor": 0.1,
+ "cartesian_limits": {
+ "max_trans_vel": 1.0,
+ "max_trans_acc": 2.25,
+ "max_trans_dec": -5.0,
+ "max_rot_vel": 1.57
+ }
+ }
# 解析URDF文件
- robot_description = urdf_str
+ robot_description = self.urdf_str
+ urdf_str_srdf = self.urdf_str_srdf
+
+ kinematics_dict = self.moveit_nodes_kinematics
+
+ if self.moveit_nodes:
+ controllers = []
+ ros2_controllers = ParameterFile(f"{str(self.mesh_path)}/ros2_controllers.yaml", allow_substs=True)
+
+ controllers.append(
+ nd(
+ package="controller_manager",
+ executable="ros2_control_node",
+ output='screen',
+ parameters=[
+ {"robot_description": robot_description},
+ ros2_controllers,
+ ]
+ )
+ )
+ for controller in self.moveit_controllers_yaml['moveit_simple_controller_manager']['controller_names']:
+ controllers.append(
+ nd(
+ package="controller_manager",
+ executable="spawner",
+ arguments=[f"{controller}", "--controller-manager", f"controller_manager"],
+ output="screen",
+ )
+ )
+ controllers.append(
+ nd(
+ package="controller_manager",
+ executable="spawner",
+ arguments=["joint_state_broadcaster", "--controller-manager", f"controller_manager"],
+ output="screen",
+ )
+ )
+ for i in controllers:
+ self.launch_description.add_action(i)
+ else:
+ ros2_controllers = None
+
+
+
+
# 创建robot_state_publisher节点
robot_state_publisher = nd(
@@ -115,23 +301,21 @@ class ResourceVisualization:
parameters=[{
'robot_description': robot_description,
'use_sim_time': False
- }]
+ },
+ # kinematics_dict
+ ]
)
- # joint_state_publisher_node = nd(
- # package='joint_state_publisher_gui', # 或 joint_state_publisher
- # executable='joint_state_publisher_gui',
- # name='joint_state_publisher',
- # output='screen'
- # )
# 创建move_group节点
move_group = nd(
package='moveit_ros_move_group',
executable='move_group',
output='screen',
parameters=[{
+ 'allow_trajectory_execution': True,
'robot_description': robot_description,
- 'robot_description_semantic': self.srdf_str,
+ 'robot_description_semantic': urdf_str_srdf,
+ 'robot_description_kinematics': kinematics_dict,
'capabilities': '',
'disable_capabilities': '',
'monitor_dynamics': False,
@@ -141,7 +325,13 @@ class ResourceVisualization:
'publish_geometry_updates': True,
'publish_state_updates': True,
'publish_transforms_updates': True,
- }]
+ # 'robot_description_planning': robot_description_planning,
+ },
+ self.moveit_controllers_yaml,
+ # ompl_planning_pipeline_config,
+ robot_description_planning,
+ planning_pipelines,
+ ]
)
# 将节点添加到launch描述中
@@ -156,7 +346,14 @@ class ResourceVisualization:
executable='rviz2',
name='rviz2',
arguments=['-d', f"{str(self.mesh_path)}/view_robot.rviz"],
- output='screen'
+ output='screen',
+ parameters=[
+ {'robot_description_kinematics': kinematics_dict,
+ },
+ robot_description_planning,
+ planning_pipelines,
+
+ ]
)
self.launch_description.add_action(rviz_node)
@@ -169,6 +366,11 @@ class ResourceVisualization:
Args:
urdf_str: URDF文件路径
"""
- launch_description = self.create_launch_description(self.urdf_str)
+ launch_description = self.create_launch_description()
+ # print('--------------------------------')
+ # print(self.moveit_controllers_yaml)
+ # print('--------------------------------')
+ # print(self.urdf_str)
+ # print('--------------------------------')
self.launch_service.include_launch_description(launch_description)
self.launch_service.run()
\ No newline at end of file
diff --git a/unilabos/device_mesh/ros2_controllers.yaml b/unilabos/device_mesh/ros2_controllers.yaml
new file mode 100644
index 0000000..7dbad85
--- /dev/null
+++ b/unilabos/device_mesh/ros2_controllers.yaml
@@ -0,0 +1,31 @@
+arm_slider_arm_controller:
+ ros__parameters:
+ command_interfaces:
+ - position
+ joints:
+ - arm_slider_arm_base_joint
+ - arm_slider_arm_link_1_joint
+ - arm_slider_arm_link_2_joint
+ - arm_slider_arm_link_3_joint
+ - arm_slider_gripper_base_joint
+ state_interfaces:
+ - position
+ - velocity
+arm_slider_gripper_controller:
+ ros__parameters:
+ command_interfaces:
+ - position
+ joints:
+ - arm_slider_gripper_right_joint
+ state_interfaces:
+ - position
+ - velocity
+controller_manager:
+ ros__parameters:
+ arm_slider_arm_controller:
+ type: joint_trajectory_controller/JointTrajectoryController
+ arm_slider_gripper_controller:
+ type: joint_trajectory_controller/JointTrajectoryController
+ joint_state_broadcaster:
+ type: joint_state_broadcaster/JointStateBroadcaster
+ update_rate: 100
diff --git a/unilabos/device_mesh/view_robot.rviz b/unilabos/device_mesh/view_robot.rviz
index 64f6b35..ad6241a 100644
--- a/unilabos/device_mesh/view_robot.rviz
+++ b/unilabos/device_mesh/view_robot.rviz
@@ -1,23 +1,15 @@
Panels:
- Class: rviz_common/Displays
- Help Height: 138
+ Help Height: 0
Name: Displays
Property Tree Widget:
Expanded:
- - /Global Options1
- - /TF1
- /TF1/Tree1
- - /RobotModel1
- - /PlanningScene1
- - /PlanningScene1/Scene Geometry1
- - /RobotState1
- - /RobotState1/Links1
- - /MotionPlanning1
- /MotionPlanning1/Scene Geometry1
- /MotionPlanning1/Scene Robot1
- /MotionPlanning1/Planning Request1
- Splitter Ratio: 0.5
- Tree Height: 345
+ Splitter Ratio: 0.5016146302223206
+ Tree Height: 575
- Class: rviz_common/Selection
Name: Selection
- Class: rviz_common/Tool Properties
@@ -93,7 +85,7 @@ Visualization Manager:
Value: false
Visual Enabled: true
- Class: moveit_rviz_plugin/PlanningScene
- Enabled: false
+ Enabled: true
Move Group Namespace: ""
Name: PlanningScene
Planning Scene Topic: /monitored_planning_scene
@@ -104,7 +96,7 @@ Visualization Manager:
Scene Display Time: 0.009999999776482582
Show Scene Geometry: true
Voxel Coloring: Z-Axis
- Voxel Rendering: Occupied Voxels
+ Voxel Rendering: Disabled
Scene Robot:
Attached Body Color: 150; 50; 150
Links:
@@ -113,10 +105,108 @@ Visualization Manager:
Expand Link Details: false
Expand Tree: false
Link Tree Style: Links in Alphabetic Order
+ arm_slider_arm_base:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_arm_link_1:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_arm_link_2:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_arm_link_3:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_arm_slideway:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_device_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ arm_slider_gripper_base:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_gripper_left:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_gripper_right:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_device_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ deck_first_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_fourth_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_main_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_second_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_socketTypeGenericSbsFootprint:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ deck_socketTypeHEPAModule:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ deck_third_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ hotel_base_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ hotel_device_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ hotel_socketTypeGenericSbsFootprint:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ world:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
Robot Alpha: 1
Show Robot Collision: false
Show Robot Visual: false
- Value: false
+ Value: true
- Attached Body Color: 150; 50; 150
Class: moveit_rviz_plugin/RobotState
Collision Enabled: false
@@ -166,43 +256,100 @@ Visualization Manager:
Expand Link Details: false
Expand Tree: false
Link Tree Style: Links in Alphabetic Order
- PLR_STATION_deck_device_link:
- Alpha: 1
- Show Axes: false
- Show Trail: false
- PLR_STATION_deck_first_link:
+ arm_slider_arm_base:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
- PLR_STATION_deck_fourth_link:
+ arm_slider_arm_link_1:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
- PLR_STATION_deck_main_link:
+ arm_slider_arm_link_2:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
- PLR_STATION_deck_second_link:
+ arm_slider_arm_link_3:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
- PLR_STATION_deck_socketTypeGenericSbsFootprint:
- Alpha: 1
- Show Axes: false
- Show Trail: false
- PLR_STATION_deck_socketTypeHEPAModule:
- Alpha: 1
- Show Axes: false
- Show Trail: false
- PLR_STATION_deck_third_link:
+ arm_slider_arm_slideway:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
+ arm_slider_device_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ arm_slider_gripper_base:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_gripper_left:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_gripper_right:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_device_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ deck_first_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_fourth_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_main_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_second_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_socketTypeGenericSbsFootprint:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ deck_socketTypeHEPAModule:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ deck_third_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ hotel_base_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ hotel_device_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ hotel_socketTypeGenericSbsFootprint:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
world:
Alpha: 1
Show Axes: false
@@ -230,7 +377,7 @@ Visualization Manager:
Goal State Color: 250; 128; 0
Interactive Marker Size: 0
Joint Violation Color: 255; 0; 255
- Planning Group: ""
+ Planning Group: arm_slider_arm
Query Goal State: false
Query Start State: false
Show Workspace: false
@@ -242,9 +389,9 @@ Visualization Manager:
Scene Alpha: 0.8999999761581421
Scene Color: 50; 230; 50
Scene Display Time: 0.009999999776482582
- Show Scene Geometry: true
- Voxel Coloring: Z-Axis
- Voxel Rendering: Occupied Voxels
+ Show Scene Geometry: false
+ Voxel Coloring: Cell Probability
+ Voxel Rendering: All Voxels
Scene Robot:
Attached Body Color: 150; 50; 150
Links:
@@ -253,43 +400,100 @@ Visualization Manager:
Expand Link Details: false
Expand Tree: false
Link Tree Style: Links in Alphabetic Order
- PLR_STATION_deck_device_link:
- Alpha: 1
- Show Axes: false
- Show Trail: false
- PLR_STATION_deck_first_link:
+ arm_slider_arm_base:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
- PLR_STATION_deck_fourth_link:
+ arm_slider_arm_link_1:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
- PLR_STATION_deck_main_link:
+ arm_slider_arm_link_2:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
- PLR_STATION_deck_second_link:
+ arm_slider_arm_link_3:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
- PLR_STATION_deck_socketTypeGenericSbsFootprint:
- Alpha: 1
- Show Axes: false
- Show Trail: false
- PLR_STATION_deck_socketTypeHEPAModule:
- Alpha: 1
- Show Axes: false
- Show Trail: false
- PLR_STATION_deck_third_link:
+ arm_slider_arm_slideway:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
+ arm_slider_device_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ arm_slider_gripper_base:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_gripper_left:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ arm_slider_gripper_right:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_device_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ deck_first_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_fourth_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_main_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_second_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ deck_socketTypeGenericSbsFootprint:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ deck_socketTypeHEPAModule:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ deck_third_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ hotel_base_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ Value: true
+ hotel_device_link:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
+ hotel_socketTypeGenericSbsFootprint:
+ Alpha: 1
+ Show Axes: false
+ Show Trail: false
world:
Alpha: 1
Show Axes: false
@@ -345,43 +549,43 @@ Visualization Manager:
Views:
Current:
Class: rviz_default_plugins/Orbit
- Distance: 1.0284695625305176
+ Distance: 2.622864246368408
Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Focal Point:
- X: 0.29730814695358276
- Y: 0.21228469908237457
- Z: 0.20008830726146698
+ X: -0.2880733013153076
+ Y: -0.16004444658756256
+ Z: -0.16730672121047974
Focal Shape Fixed Size: true
Focal Shape Size: 0.05000000074505806
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.009999999776482582
- Pitch: 0.38979560136795044
+ Pitch: 0.4297958016395569
Target Frame:
Value: Orbit (rviz)
- Yaw: 0.06074193865060806
+ Yaw: 0.3525616228580475
Saved: ~
Window Geometry:
Displays:
- collapsed: false
- Height: 1656
- Hide Left Dock: false
+ collapsed: true
+ Height: 1061
+ Hide Left Dock: true
Hide Right Dock: true
MotionPlanning:
- collapsed: false
+ collapsed: true
MotionPlanning - Trajectory Slider:
collapsed: false
- QMainWindow State: 000000ff00000000fd0000000400000000000003a3000005dcfc020000000bfb0000001200530065006c0065006300740069006f006e00000001e10000009b000000b000fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000006e000002510000018200fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb000000280020002d0020005400720061006a006500630074006f0072007900200053006c00690064006500720000000000ffffffff0000000000000000fb00000044004d006f00740069006f006e0050006c0061006e006e0069006e00670020002d0020005400720061006a006500630074006f0072007900200053006c00690064006500720000000000ffffffff0000007a00fffffffb0000001c004d006f00740069006f006e0050006c0061006e006e0069006e006701000002cb0000037f000002b800ffffff000000010000010f00000387fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003b000003870000013200fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004420000003efc0100000002fb0000000800540069006d00650100000000000004420000000000000000fb0000000800540069006d0065010000000000000450000000000000000000000627000005dc00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
+ QMainWindow State: 000000ff00000000fd0000000400000000000003a3000003f2fc020000000bfb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005d00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c00610079007300000000170000027b000000ca00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb000000280020002d0020005400720061006a006500630074006f0072007900200053006c00690064006500720000000000ffffffff0000000000000000fb00000044004d006f00740069006f006e0050006c0061006e006e0069006e00670020002d0020005400720061006a006500630074006f0072007900200053006c00690064006500720000000000ffffffff0000004300fffffffb0000001c004d006f00740069006f006e0050006c0061006e006e0069006e00670000000296000001730000013e00ffffff000000010000010f00000387fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003b00000387000000a100fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004420000003efc0100000002fb0000000800540069006d00650100000000000004420000000000000000fb0000000800540069006d0065010000000000000450000000000000000000000784000003f200000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730000000000ffffffff0000000000000000
Selection:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: true
- Width: 2518
- X: 385
- Y: 120
+ Width: 1924
+ X: 140
+ Y: 54
diff --git a/unilabos/devices/liquid_handling/biomek.py b/unilabos/devices/liquid_handling/biomek.py
new file mode 100644
index 0000000..ea71c6d
--- /dev/null
+++ b/unilabos/devices/liquid_handling/biomek.py
@@ -0,0 +1,1106 @@
+import json
+import pathlib
+from typing import Sequence, Optional, List, Union, Literal
+
+import requests
+from geometry_msgs.msg import Point
+from pylabrobot.liquid_handling import LiquidHandler
+from pylabrobot.resources import (
+ TipRack,
+ Container,
+ Coordinate,
+)
+from unilabos_msgs.msg import Resource
+
+from unilabos.ros.nodes.resource_tracker import DeviceNodeResourceTracker # type: ignore
+
+
+class LiquidHandlerBiomek:
+ """
+ Biomek液体处理器的实现类,继承自LiquidHandlerAbstract。
+ 该类用于处理Biomek液体处理器的特定操作。
+ """
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self._status = "Idle" # 初始状态为 Idle
+ self._success = False # 初始成功状态为 False
+ self._status_queue = kwargs.get("status_queue", None) # 状态队列
+ self.temp_protocol = {}
+ self.py32_path = "/opt/py32" # Biomek的Python 3.2路径
+
+ # 预定义的仪器分类
+ self.tip_racks = [
+ "BC230", "BC1025F", "BC50", "TipRack200", "TipRack1000",
+ "tip", "tips", "Tip", "Tips"
+ ]
+
+ self.reservoirs = [
+ "AgilentReservoir", "nest_12_reservoir_15ml", "nest_1_reservoir_195ml",
+ "reservoir", "Reservoir", "waste", "Waste"
+ ]
+
+ self.plates_96 = [
+ "BCDeep96Round", "Matrix96_750uL", "NEST 2ml Deep Well Plate", "nest_96_wellplate_100ul_pcr_full_skirt",
+ "nest_96_wellplate_200ul_flat", "Matrix96", "96", "plate", "Plate"
+ ]
+
+ self.aspirate_techniques = {
+ 'MC P300 high':{
+ 'Position': 'P1',
+ 'Height': -2.0,
+ 'Volume': '50',
+ 'liquidtype': 'Well Contents',
+ 'WellsX': 12,
+ 'LabwareClass': 'Matrix96_750uL',
+ 'AutoSelectPrototype': True,
+ 'ColsFirst': True,
+ 'CustomHeight': False,
+ 'DataSetPattern': False,
+ 'HeightFrom': 0,
+ 'LocalPattern': True,
+ 'Operation': 'Aspirate',
+ 'OverrideHeight': False,
+ 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True),
+ 'Prototype': 'MC P300 High',
+ 'ReferencedPattern': '',
+ 'RowsFirst': False,
+ 'SectionExpression': '',
+ 'SelectionInfo': (1,),
+ 'SetMark': True,
+ 'Source': True,
+ 'StartAtMark': False,
+ 'StartAtSelection': True,
+ 'UseExpression': False},
+ }
+
+ self.dispense_techniques = {
+ 'MC P300 high':{
+ 'Position': 'P11',
+ 'Height': -2.0,
+ 'Volume': '50',
+ 'liquidtype': 'Tip Contents',
+ 'WellsX': 12,
+ 'LabwareClass': 'Matrix96_750uL',
+ 'AutoSelectPrototype': True,
+ 'ColsFirst': True,
+ 'CustomHeight': False,
+ 'DataSetPattern': False,
+ 'HeightFrom': 0,
+ 'LocalPattern': True,
+ 'Operation': 'Dispense',
+ 'OverrideHeight': False,
+ 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True),
+ 'Prototype': 'MC P300 High',
+ 'ReferencedPattern': '',
+ 'RowsFirst': False,
+ 'SectionExpression': '',
+ 'SelectionInfo': (1,),
+ 'SetMark': True,
+ 'Source': False,
+ 'StartAtMark': False,
+ 'StartAtSelection': True,
+ 'UseExpression': False}
+ }
+
+ def _get_instrument_type(self, class_name: str) -> str:
+ """
+ 根据class_name判断仪器类型
+
+ Returns:
+ str: "tip_rack", "reservoir", "plate_96", 或 "unknown"
+ """
+ # 检查是否是枪头架
+ for tip_name in self.tip_racks:
+ if tip_name in class_name:
+ return "tip_rack"
+
+ # 检查是否是储液槽
+ for reservoir_name in self.reservoirs:
+ if reservoir_name in class_name:
+ return "reservoir"
+
+ # 检查是否是96孔板
+ for plate_name in self.plates_96:
+ if plate_name in class_name:
+ return "plate_96"
+
+ return "unknown"
+
+ @classmethod
+ def deserialize(cls, data: dict, allow_marshal: bool = False) -> LiquidHandler:
+ return LiquidHandler.deserialize(data, allow_marshal)
+
+ @property
+ def success(self):
+ """
+ 获取操作是否成功的状态。
+
+ Returns:
+ bool: 如果操作成功,返回True;否则返回False。
+ """
+ return self._success
+
+ def create_protocol(
+ self,
+ protocol_name: str,
+ protocol_description: str,
+ protocol_version: str,
+ protocol_author: str,
+ protocol_date: str,
+ protocol_type: str,
+ none_keys: List[str] = [],
+ ):
+ """
+ 创建一个新的协议。
+
+ Args:
+ protocol_name (str): 协议名称
+ protocol_description (str): 协议描述
+ protocol_version (str): 协议版本
+ protocol_author (str): 协议作者
+ protocol_date (str): 协议日期
+ protocol_type (str): 协议类型
+ none_keys (List[str]): 需要设置为None的键列表
+
+ Returns:
+ dict: 创建的协议字典
+ """
+ self.temp_protocol = {
+ "meta": {
+ "name": protocol_name,
+ "description": protocol_description,
+ "version": protocol_version,
+ "author": protocol_author,
+ "date": protocol_date,
+ "type": protocol_type,
+ },
+ "labwares": {},
+ "steps": [],
+ }
+ return self.temp_protocol
+
+ def run_protocol(self):
+ """
+ 执行创建的实验流程。
+ 工作站的完整执行流程是,
+ 从 create_protocol 开始,创建新的 method,
+ 随后执行 transfer_liquid 等操作向实验流程添加步骤,
+ 最后 run_protocol 执行整个方法。
+
+ Returns:
+ dict: 执行结果
+ """
+ #use popen or subprocess to create py32 process and communicate send the temp protocol to it
+ if not self.temp_protocol:
+ raise ValueError("No protocol created. Please create a protocol first.")
+
+ # 模拟执行协议
+ self._status = "Running"
+ self._success = True
+ # 在这里可以添加实际执行协议的逻辑
+
+ response = requests.post("localhost:5000/api/protocols", json=self.temp_protocol)
+
+ def create_resource(
+ self,
+ resource_tracker: DeviceNodeResourceTracker,
+ resources: list[Resource],
+ bind_parent_id: str,
+ bind_location: dict[str, float],
+ liquid_input_slot: list[int],
+ liquid_type: list[str],
+ liquid_volume: list[int],
+ slot_on_deck: int,
+ ):
+ """
+ 创建一个新的资源。
+
+ Args:
+ device_id (str): 设备ID
+ res_id (str): 资源ID
+ class_name (str): 资源类名
+ parent (str): 父级ID
+ bind_locations (Point): 绑定位置
+ liquid_input_slot (list[int]): 液体输入槽列表
+ liquid_type (list[str]): 液体类型列表
+ liquid_volume (list[int]): 液体体积列表
+ slot_on_deck (int): 甲板上的槽位
+
+ Returns:
+ dict: 创建的资源字典
+ """
+ # TODO:需要对好接口,下面这个是临时的
+ for resource in resources:
+ res_id = resource.id
+ class_name = resource.name
+ parent = bind_parent_id
+ liquid_input_slot = liquid_input_slot
+ liquid_type = liquid_type
+ liquid_volume = liquid_volume
+ slot_on_deck = slot_on_deck
+
+ resource = {
+ "id": res_id,
+ "class": class_name,
+ "parent": parent,
+ "bind_locations": bind_location,
+ "liquid_input_slot": liquid_input_slot,
+ "liquid_type": liquid_type,
+ "liquid_volume": liquid_volume,
+ "slot_on_deck": slot_on_deck,
+ }
+ self.temp_protocol["labwares"].append(resource)
+ return resources
+
+ def transfer_liquid(
+ self,
+ sources: Sequence[Container],
+ targets: Sequence[Container],
+ tip_racks: Sequence[TipRack],
+ *,
+ use_channels: Optional[List[int]] = None,
+ asp_vols: Union[List[float], float],
+ dis_vols: Union[List[float], float],
+ asp_flow_rates: Optional[List[Optional[float]]] = None,
+ dis_flow_rates: Optional[List[Optional[float]]] = None,
+ offsets: Optional[List[Coordinate]] = None,
+ touch_tip: bool = False,
+ liquid_height: Optional[List[Optional[float]]] = None,
+ blow_out_air_volume: Optional[List[Optional[float]]] = None,
+ spread: Literal["wide", "tight", "custom"] = "wide",
+ is_96_well: bool = False,
+ mix_stage: Optional[Literal["none", "before", "after", "both"]] = "none",
+ mix_times: Optional[int] = None,
+ mix_vol: Optional[int] = None,
+ mix_rate: Optional[int] = None,
+ mix_liquid_height: Optional[float] = None,
+ delays: Optional[List[int]] = None,
+ none_keys: List[str] = []
+ ):
+
+ transfer_params = {
+ "Span8": False,
+ "Pod": "Pod1",
+ "items": {},
+ "Wash": False,
+ "Dynamic?": True,
+ "AutoSelectActiveWashTechnique": False,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": False,
+ "ChangeTipsBetweenSources": False,
+ "DefaultCaption": "",
+ "UseExpression": False,
+ "LeaveTipsOn": False,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": False,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": False,
+ "ShowTransferDetails": True,
+ "Solvent": "Well Content",
+ "Span8Wash": False,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": False,
+ "SplitVolumeCleaning": False,
+ "Stop": "Destinations",
+ "TipLocation": "BC1025F",
+ "UseCurrentTips": False,
+ "UseDisposableTips": True,
+ "UseFixedTips": False,
+ "UseJIT": True,
+ "UseMandrelSelection": True,
+ "UseProbes": [True, True, True, True, True, True, True, True],
+ "WashCycles": "1",
+ "WashVolume": "110%",
+ "Wizard": False
+ }
+
+ items: dict = {}
+ for idx, (src, dst) in enumerate(zip(sources, targets)):
+ items[str(idx)] = {
+ "Source": str(src),
+ "Destination": str(dst),
+ "Volume": dis_vols[idx]
+ }
+ transfer_params["items"] = items
+
+ transfer_params["Solvent"] = "Water"
+ TipLocation = tip_racks[0].name
+ transfer_params["TipLocation"] = TipLocation
+
+ if len(tip_racks) == 1:
+ transfer_params['UseCurrentTips'] = True
+ elif len(tip_racks) > 1:
+ transfer_params["ChangeTipsBetweenDests"] = True
+
+ self.temp_protocol["steps"].append(transfer_params)
+
+ return
+
+ def instrument_setup_biomek(
+ self,
+ id: str,
+ parent: str,
+ slot_on_deck: str,
+ class_name: str,
+ liquid_type: list[str],
+ liquid_volume: list[int],
+ liquid_input_wells: list[str],
+ ):
+ """
+ 设置Biomek仪器的参数配置,按照DeckItems格式
+
+ 根据不同的仪器类型(容器、tip rack等)设置相应的参数结构
+ 位置作为键,配置列表作为值
+ """
+
+ # 判断仪器类型
+ instrument_type = self._get_instrument_type(class_name)
+
+ config = None # 初始化为None
+
+ if instrument_type == "reservoir":
+ # 储液槽类型配置
+ config = {
+ "Properties": {
+ "Name": id, # 使用id作为名称
+ "Device": "",
+ "liquidtype": liquid_type[0] if liquid_type else "Water",
+ "BarCode": "",
+ "SenseEveryTime": False
+ },
+ "Known": True,
+ "Class": f"LabwareClasses\\{class_name}",
+ "DataSets": {"Volume": {}},
+ "RuntimeDataSets": {"Volume": {}},
+ "EvalAmounts": (float(liquid_volume[0]),) if liquid_volume else (0,),
+ "Nominal": False,
+ "EvalLiquids": (liquid_type[0],) if liquid_type else ("Water",)
+ }
+
+ elif instrument_type == "plate_96":
+ # 96孔板类型配置
+ volume_per_well = float(liquid_volume[0]) if liquid_volume else 0
+ liquid_per_well = liquid_type[0] if liquid_type else "Water"
+
+ config = {
+ "Properties": {
+ "Name": id, # 使用id作为名称
+ "Device": "",
+ "liquidtype": liquid_per_well,
+ "BarCode": "",
+ "SenseEveryTime": False
+ },
+ "Known": True,
+ "Class": f"LabwareClasses\\{class_name}",
+ "DataSets": {"Volume": {}},
+ "RuntimeDataSets": {"Volume": {}},
+ "EvalAmounts": tuple([volume_per_well] * 96),
+ "Nominal": False,
+ "EvalLiquids": tuple([liquid_per_well] * 96)
+ }
+
+ elif instrument_type == "tip_rack":
+ # 枪头架类型配置
+ tip_config = {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": False,
+ "RT_Used": False,
+ "Dirty": False,
+ "RT_Dirty": False,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ }
+
+ config = {
+ "Tips": tip_config,
+ "RT_Tips": tip_config.copy(),
+ "Properties": {},
+ "Known": False,
+ "Class": f"LabwareClasses\\{class_name}",
+ "DataSets": {"Volume": {}},
+ "RuntimeDataSets": {"Volume": {}}
+ }
+
+ # 按照DeckItems格式存储:位置作为键,配置列表作为值
+ if config is not None:
+ self.temp_protocol["labwares"][slot_on_deck] = [config]
+ else:
+ # 空位置
+ self.temp_protocol["labwares"][slot_on_deck] = []
+
+ return
+
+ def transfer_biomek(
+ self,
+ source: str,
+ target: str,
+ tip_rack: str,
+ volume: float,
+ aspirate_techniques: str,
+ dispense_techniques: str,
+ ):
+ """
+ 处理Biomek的液体转移操作。
+
+ """
+ items = []
+
+ asp_params = self.aspirate_techniques.get(aspirate_techniques, {})
+ dis_params = self.dispense_techniques.get(dispense_techniques, {})
+
+ asp_params['Position'] = source
+ dis_params['Position'] = target
+ asp_params['Volume'] = str(volume)
+ dis_params['Volume'] = str(volume)
+
+ items.append(asp_params)
+ items.append(dis_params)
+
+ transfer_params = {
+ "Span8": False,
+ "Pod": "Pod1",
+ "items": [],
+ "Wash": False,
+ "Dynamic?": True,
+ "AutoSelectActiveWashTechnique": False,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": True,
+ "ChangeTipsBetweenSources": False,
+ "DefaultCaption": "",
+ "UseExpression": False,
+ "LeaveTipsOn": False,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": False,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": False,
+ "ShowTransferDetails": True,
+ "Solvent": "Water",
+ "Span8Wash": False,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": False,
+ "SplitVolumeCleaning": False,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": False,
+ "UseDisposableTips": False,
+ "UseFixedTips": False,
+ "UseJIT": True,
+ "UseMandrelSelection": True,
+ "UseProbes": [True, True, True, True, True, True, True, True],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": False
+ }
+ transfer_params["items"] = items
+ transfer_params["Solvent"] = 'Water'
+ transfer_params["TipLocation"] = tip_rack
+ tmp={'transfer': transfer_params}
+ self.temp_protocol["steps"].append(tmp)
+
+ return
+
+
+ def move_biomek(
+ self,
+ source: str,
+ target: str,
+ ):
+ """
+ 处理Biomek移动板子的操作。
+
+ """
+
+ move_params = {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": source,
+ "Target": target,
+ "LeaveBottomLabware": False,
+ }
+ self.temp_protocol["steps"].append(move_params)
+
+ return
+
+ def incubation_biomek(
+ self,
+ time: int,
+ ):
+ """
+ 处理Biomek的孵育操作。
+ """
+ incubation_params = {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": time,
+ "Mode": "TimedResource"
+ }
+ self.temp_protocol["steps"].append(incubation_params)
+
+ return
+
+ def oscillation_biomek(
+ self,
+ rpm: int,
+ time: int,
+ ):
+ """
+ 处理Biomek的振荡操作。
+ """
+ oscillation_params = {
+ 'Device': 'OrbitalShaker0',
+ 'Parameters': (str(rpm), '2', str(time), 'CounterClockwise'),
+ 'Command': 'Timed Shake'
+ }
+ self.temp_protocol["steps"].append(oscillation_params)
+
+ return
+
+
+if __name__ == "__main__":
+
+ print("=== Biomek完整流程测试 ===")
+ print("包含: 仪器设置 + 完整实验步骤")
+
+ # 完整的步骤信息(从biomek.py复制)
+ steps_info = '''
+ {
+ "steps": [
+ {
+ "step_number": 1,
+ "operation": "transfer",
+ "description": "转移PCR产物或酶促反应液至0.5ml 96孔板中",
+ "parameters": {
+ "source": "P1",
+ "target": "P11",
+ "tip_rack": "BC230",
+ "volume": 50
+ }
+ },
+ {
+ "step_number": 2,
+ "operation": "transfer",
+ "description": "加入2倍体积的Bind Beads BC至产物中",
+ "parameters": {
+ "source": "P2",
+ "target": "P11",
+ "tip_rack": "BC230",
+ "volume": 100
+ }
+ },
+ {
+ "step_number": 3,
+ "operation": "oscillation",
+ "description": "振荡混匀300秒",
+ "parameters": {
+ "rpm": 800,
+ "time": 300
+ }
+ },
+ {
+ "step_number": 4,
+ "operation": "move_labware",
+ "description": "转移至96孔磁力架上吸附3分钟",
+ "parameters": {
+ "source": "P11",
+ "target": "P12"
+ }
+ },
+ {
+ "step_number": 5,
+ "operation": "incubation",
+ "description": "吸附3分钟",
+ "parameters": {
+ "time": 180
+ }
+ },
+ {
+ "step_number": 6,
+ "operation": "transfer",
+ "description": "吸弃或倒除上清液",
+ "parameters": {
+ "source": "P12",
+ "target": "P22",
+ "tip_rack": "BC230",
+ "volume": 150
+ }
+ },
+ {
+ "step_number": 7,
+ "operation": "transfer",
+ "description": "加入300-500μl 75%乙醇",
+ "parameters": {
+ "source": "P3",
+ "target": "P12",
+ "tip_rack": "BC230",
+ "volume": 400
+ }
+ },
+ {
+ "step_number": 8,
+ "operation": "move_labware",
+ "description": "移动至振荡器进行振荡混匀",
+ "parameters": {
+ "source": "P12",
+ "target": "Orbital1"
+ }
+ },
+ {
+ "step_number": 9,
+ "operation": "oscillation",
+ "description": "振荡混匀60秒",
+ "parameters": {
+ "rpm": 800,
+ "time": 60
+ }
+ },
+ {
+ "step_number": 10,
+ "operation": "move_labware",
+ "description": "转移至96孔磁力架上吸附3分钟",
+ "parameters": {
+ "source": "Orbital1",
+ "target": "P12"
+ }
+ },
+ {
+ "step_number": 11,
+ "operation": "incubation",
+ "description": "吸附3分钟",
+ "parameters": {
+ "time": 180
+ }
+ },
+ {
+ "step_number": 12,
+ "operation": "transfer",
+ "description": "吸弃或倒弃废液",
+ "parameters": {
+ "source": "P12",
+ "target": "P22",
+ "tip_rack": "BC230",
+ "volume": 400
+ }
+ },
+ {
+ "step_number": 13,
+ "operation": "transfer",
+ "description": "重复加入75%乙醇",
+ "parameters": {
+ "source": "P3",
+ "target": "P12",
+ "tip_rack": "BC230",
+ "volume": 400
+ }
+ },
+ {
+ "step_number": 14,
+ "operation": "move_labware",
+ "description": "移动至振荡器进行振荡混匀",
+ "parameters": {
+ "source": "P12",
+ "target": "Orbital1"
+ }
+ },
+ {
+ "step_number": 15,
+ "operation": "oscillation",
+ "description": "振荡混匀60秒",
+ "parameters": {
+ "rpm": 800,
+ "time": 60
+ }
+ },
+ {
+ "step_number": 16,
+ "operation": "move_labware",
+ "description": "转移至96孔磁力架上吸附3分钟",
+ "parameters": {
+ "source": "Orbital1",
+ "target": "P12"
+ }
+ },
+ {
+ "step_number": 17,
+ "operation": "incubation",
+ "description": "吸附3分钟",
+ "parameters": {
+ "time": 180
+ }
+ },
+ {
+ "step_number": 18,
+ "operation": "transfer",
+ "description": "吸弃或倒弃废液",
+ "parameters": {
+ "source": "P12",
+ "target": "P22",
+ "tip_rack": "BC230",
+ "volume": 400
+ }
+ },
+ {
+ "step_number": 19,
+ "operation": "move_labware",
+ "description": "正放96孔板,空气干燥15分钟",
+ "parameters": {
+ "source": "P12",
+ "target": "P13"
+ }
+ },
+ {
+ "step_number": 20,
+ "operation": "incubation",
+ "description": "空气干燥15分钟",
+ "parameters": {
+ "time": 900
+ }
+ },
+ {
+ "step_number": 21,
+ "operation": "transfer",
+ "description": "加入30-50μl Elution Buffer",
+ "parameters": {
+ "source": "P4",
+ "target": "P13",
+ "tip_rack": "BC230",
+ "volume": 40
+ }
+ },
+ {
+ "step_number": 22,
+ "operation": "move_labware",
+ "description": "移动至振荡器进行振荡混匀",
+ "parameters": {
+ "source": "P13",
+ "target": "Orbital1"
+ }
+ },
+ {
+ "step_number": 23,
+ "operation": "oscillation",
+ "description": "振荡混匀60秒",
+ "parameters": {
+ "rpm": 800,
+ "time": 60
+ }
+ },
+ {
+ "step_number": 24,
+ "operation": "move_labware",
+ "description": "室温静置3分钟",
+ "parameters": {
+ "source": "Orbital1",
+ "target": "P13"
+ }
+ },
+ {
+ "step_number": 25,
+ "operation": "incubation",
+ "description": "室温静置3分钟",
+ "parameters": {
+ "time": 180
+ }
+ },
+ {
+ "step_number": 26,
+ "operation": "move_labware",
+ "description": "转移至96孔磁力架上吸附2分钟",
+ "parameters": {
+ "source": "P13",
+ "target": "P12"
+ }
+ },
+ {
+ "step_number": 27,
+ "operation": "incubation",
+ "description": "吸附2分钟",
+ "parameters": {
+ "time": 120
+ }
+ },
+ {
+ "step_number": 28,
+ "operation": "transfer",
+ "description": "将DNA转移至新的板中",
+ "parameters": {
+ "source": "P12",
+ "target": "P14",
+ "tip_rack": "BC230",
+ "volume": 40
+ }
+ }
+ ]
+ }
+'''
+ # 完整的labware配置信息
+ labware_with_liquid = '''
+ [
+ {
+ "id": "Tip Rack BC230 TL1",
+ "parent": "deck",
+ "slot_on_deck": "TL1",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 TL2",
+ "parent": "deck",
+ "slot_on_deck": "TL2",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 TL3",
+ "parent": "deck",
+ "slot_on_deck": "TL3",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 TL4",
+ "parent": "deck",
+ "slot_on_deck": "TL4",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 TL5",
+ "parent": "deck",
+ "slot_on_deck": "TL5",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 P5",
+ "parent": "deck",
+ "slot_on_deck": "P5",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 P6",
+ "parent": "deck",
+ "slot_on_deck": "P6",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 P15",
+ "parent": "deck",
+ "slot_on_deck": "P15",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 P16",
+ "parent": "deck",
+ "slot_on_deck": "P16",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "stock plate on P1",
+ "parent": "deck",
+ "slot_on_deck": "P1",
+ "class_name": "AgilentReservoir",
+ "liquid_type": ["PCR product"],
+ "liquid_volume": [5000],
+ "liquid_input_wells": ["A1"]
+ },
+ {
+ "id": "stock plate on P2",
+ "parent": "deck",
+ "slot_on_deck": "P2",
+ "class_name": "AgilentReservoir",
+ "liquid_type": ["bind beads"],
+ "liquid_volume": [100000],
+ "liquid_input_wells": ["A1"]
+ },
+ {
+ "id": "stock plate on P3",
+ "parent": "deck",
+ "slot_on_deck": "P3",
+ "class_name": "AgilentReservoir",
+ "liquid_type": ["75% ethanol"],
+ "liquid_volume": [100000],
+ "liquid_input_wells": ["A1"]
+ },
+ {
+ "id": "stock plate on P4",
+ "parent": "deck",
+ "slot_on_deck": "P4",
+ "class_name": "AgilentReservoir",
+ "liquid_type": ["Elution Buffer"],
+ "liquid_volume": [5000],
+ "liquid_input_wells": ["A1"]
+ },
+ {
+ "id": "working plate on P11",
+ "parent": "deck",
+ "slot_on_deck": "P11",
+ "class_name": "BCDeep96Round",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "working plate on P12",
+ "parent": "deck",
+ "slot_on_deck": "P12",
+ "class_name": "BCDeep96Round",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "working plate on P13",
+ "parent": "deck",
+ "slot_on_deck": "P13",
+ "class_name": "BCDeep96Round",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "working plate on P14",
+ "parent": "deck",
+ "slot_on_deck": "P14",
+ "class_name": "BCDeep96Round",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "waste on P22",
+ "parent": "deck",
+ "slot_on_deck": "P22",
+ "class_name": "AgilentReservoir",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "oscillation",
+ "parent": "deck",
+ "slot_on_deck": "Orbital1",
+ "class_name": "Orbital",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ }
+ ]
+ '''
+
+ # 创建handler实例
+ handler = LiquidHandlerBiomek()
+
+ # 创建协议
+ protocol = handler.create_protocol(
+ protocol_name="DNA纯化完整流程",
+ protocol_description="使用磁珠进行DNA纯化的完整自动化流程",
+ protocol_version="1.0",
+ protocol_author="Biomek系统",
+ protocol_date="2024-01-01",
+ protocol_type="DNA_purification"
+ )
+
+ print("\n=== 第一步:设置所有仪器 ===")
+ # 解析labware配置
+ labwares = json.loads(labware_with_liquid)
+
+ # 设置所有仪器
+ instrument_count = 0
+ for labware in labwares:
+ print(f"设置仪器: {labware['id']} ({labware['class_name']}) 在位置 {labware['slot_on_deck']}")
+ handler.instrument_setup_biomek(
+ id=labware['id'],
+ parent=labware['parent'],
+ slot_on_deck=labware['slot_on_deck'],
+ class_name=labware['class_name'],
+ liquid_type=labware['liquid_type'],
+ liquid_volume=labware['liquid_volume'],
+ liquid_input_wells=labware['liquid_input_wells']
+ )
+ instrument_count += 1
+
+ print(f"总共设置了 {instrument_count} 个仪器位置")
+
+ print("\n=== 第二步:执行实验步骤 ===")
+ # 解析步骤信息
+ input_steps = json.loads(steps_info)
+
+ # 执行所有步骤
+ step_count = 0
+ for step in input_steps['steps']:
+ operation = step['operation']
+ parameters = step['parameters']
+ description = step['description']
+
+ print(f"步骤 {step['step_number']}: {description}")
+
+ if operation == 'transfer':
+ handler.transfer_biomek(
+ source=parameters['source'],
+ target=parameters['target'],
+ volume=parameters['volume'],
+ tip_rack=parameters['tip_rack'],
+ aspirate_techniques='MC P300 high',
+ dispense_techniques='MC P300 high'
+ )
+ elif operation == 'move_labware':
+ handler.move_biomek(
+ source=parameters['source'],
+ target=parameters['target']
+ )
+ elif operation == 'oscillation':
+ handler.oscillation_biomek(
+ rpm=parameters['rpm'],
+ time=parameters['time']
+ )
+ elif operation == 'incubation':
+ handler.incubation_biomek(
+ time=parameters['time']
+ )
+
+ step_count += 1
+
+ print(f"总共执行了 {step_count} 个步骤")
+
+ print("\n=== 第三步:保存完整协议 ===")
+ # 获取脚本目录
+ script_dir = pathlib.Path(__file__).parent
+
+ # 保存完整协议
+ complete_output_path = script_dir / "complete_biomek_protocol_0608.json"
+ with open(complete_output_path, 'w', encoding='utf-8') as f:
+ json.dump(handler.temp_protocol, f, indent=4, ensure_ascii=False)
+
+ print(f"完整协议已保存到: {complete_output_path}")
+
+ print("\n=== 测试完成 ===")
+ print("完整的DNA纯化流程已成功转换为Biomek格式!")
diff --git a/unilabos/devices/liquid_handling/biomek.txt b/unilabos/devices/liquid_handling/biomek.txt
new file mode 100644
index 0000000..2d830a6
--- /dev/null
+++ b/unilabos/devices/liquid_handling/biomek.txt
@@ -0,0 +1,642 @@
+
+ 当前方法 Method0530 包含 36 个步骤
+
+ 步骤 0:
+ Bitmap: OStepUI.ocx,START
+ Let: {}
+ Weak: {}
+ Prompt: {}
+
+ 步骤 1:
+ BarcodeInput?: False
+ DeckItems: {'P1': [{'Properties': {'Name': '', 'Device': '', 'liquidtype': 'Water', 'BarCode': '', 'SenseEveryTime': False}, 'Known': True, 'Class': 'LabwareClasses\\Matrix96_750uL', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}, 'EvalAmounts': (500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0), 'Nominal': False, 'EvalLiquids': ('Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water')}], 'P10': [{'Tips': {'Class': 'TipClasses\\T50F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T50F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC50F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'P8': [], 'P9': [{'Tips': {'Class': 'TipClasses\\T50F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T50F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC50F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'P11': [{'Properties': {'Name': '', 'Device': '', 'liquidtype': 'Water', 'BarCode': '', 'SenseEveryTime': False}, 'Known': True, 'Class': 'LabwareClasses\\BCDeep96Round', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}, 'EvalAmounts': (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), 'Nominal': False, 'EvalLiquids': ('Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water')}], 'P12': [], 'P13': [{'Properties': {'Name': '', 'Device': '', 'liquidtype': 'Water', 'BarCode': '', 'SenseEveryTime': False}, 'Known': True, 'Class': 'LabwareClasses\\BCDeep96Round', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}, 'EvalAmounts': (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), 'Nominal': False, 'EvalLiquids': ('Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water')}], 'P14': [], 'P15': [], 'P16': [{'Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC1025F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'P17': [{'Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC1025F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'P18': [{'Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC1025F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'P19': [{'Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC1025F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'P20': [], 'P2': [{'Properties': {'Name': '', 'Device': '', 'liquidtype': 'Water', 'BarCode': '', 'SenseEveryTime': False}, 'Known': True, 'Class': 'LabwareClasses\\Matrix96_750uL', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}, 'EvalAmounts': (500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0), 'Nominal': False, 'EvalLiquids': ('Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water')}], 'P21': [], 'P22': [{'Properties': {'Name': '', 'Device': '', 'liquidtype': 'Water', 'BarCode': '', 'SenseEveryTime': False}, 'Known': True, 'Class': 'LabwareClasses\\AgilentReservoir', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}, 'EvalAmounts': (0.0,), 'Nominal': False, 'EvalLiquids': ('Water',)}], 'P23': [], 'P24': [], 'P25': [], 'P26': [], 'P27': [], 'P28': [{'Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC1025F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'P29': [{'Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC1025F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'P30': [], 'P3': [{'Properties': {'Name': '', 'Device': '', 'liquidtype': 'Water', 'BarCode': '', 'SenseEveryTime': False}, 'Known': True, 'Class': 'LabwareClasses\\AgilentReservoir', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}, 'EvalAmounts': (300000.0,), 'Nominal': False, 'EvalLiquids': ('Water',)}], 'P4': [{'Properties': {'Name': '', 'Device': '', 'liquidtype': 'Water', 'BarCode': '', 'SenseEveryTime': False}, 'Known': True, 'Class': 'LabwareClasses\\Matrix96_750uL', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}, 'EvalAmounts': (500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0), 'Nominal': False, 'EvalLiquids': ('Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water', 'Water')}], 'P5': [], 'P6': [], 'P7': [], 'TL1': [{'Tips': {'Class': 'TipClasses\\T230', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T230', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC230', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'TL2': [{'Tips': {'Class': 'TipClasses\\T230', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T230', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC230', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'TL3': [{'Tips': {'Class': 'TipClasses\\T230', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T230', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC230', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'TL4': [{'Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC1025F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'TL5': [{'Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'RT_Tips': {'Class': 'TipClasses\\T1025F', 'Contents': [], '_RT_Contents': [], 'Used': False, 'RT_Used': False, 'Dirty': False, 'RT_Dirty': False, 'MaxVolumeUsed': 0.0, 'RT_MaxVolumeUsed': 0.0}, 'Properties': {}, 'Known': False, 'Class': 'LabwareClasses\\BC1025F', 'DataSets': {'Volume': {}}, 'RuntimeDataSets': {'Volume': {}}}], 'TR1': [], 'WS1': 'Water'}
+ Layout: Multichannel
+ Pause?: True
+ PodSetup: {'LeftHasTips': False, 'LeftTipType': '', 'RightHasTips': False, 'RightTipType': ''}
+ SplitterPosition: 206
+ VerifyPodSetup?: True
+
+ 步骤 2:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P1', 'Height': -2.0, 'Volume': '50', 'liquidtype': 'Well Contents', 'WellsX': 12, 'LabwareClass': 'Matrix96_750uL', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P11', 'Height': -2.0, 'Volume': '50', 'liquidtype': 'Tip Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 50 µL from P1 to P11
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC230
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 3:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P2', 'Height': -2.0, 'Volume': '100', 'liquidtype': 'Well Contents', 'WellsX': 12, 'LabwareClass': 'Matrix96_750uL', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P11', 'Height': -2.0, 'Volume': '100', 'liquidtype': 'Tip Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 100 µL from P2 to P11
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC230
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 4:
+ Pod: Pod1
+ GripSide: A1 near
+ Source: P11
+ Target: Orbital1
+ LeaveBottomLabware: False
+
+ 步骤 5:
+ Device:
+ Parameters: ()
+ Command:
+
+ 步骤 6:
+ Device:
+ Parameters: ()
+ Command:
+
+ 步骤 7:
+ Pod: Pod1
+ GripSide: A1 near
+ Source: Orbital1
+ Target: P11
+ LeaveBottomLabware: False
+
+ 步骤 8:
+ Pod: Pod1
+ GripSide: A1 near
+ Source: P11
+ Target: P12
+ LeaveBottomLabware: False
+
+ 步骤 9:
+ Message: Paused
+ Location: the whole system
+ Time: 180
+ Mode: TimedResource
+
+ 步骤 10:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P12', 'Height': -2.0, 'Volume': '150', 'liquidtype': 'Well Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P22', 'Height': -2.0, 'Volume': '150', 'liquidtype': 'Tip Contents', 'LabwareClass': 'AgilentReservoir', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True,), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 150 µL from P12 to P22
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC230
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 11:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P3', 'Height': -2.0, 'Volume': '400', 'liquidtype': 'Well Contents', 'LabwareClass': 'AgilentReservoir', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True,), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P12', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Tip Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 200 µL from P3 to P12
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC1025F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 12:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P3', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Well Contents', 'LabwareClass': 'AgilentReservoir', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True,), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P12', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Tip Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 200 µL from P3 to P12
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC1025F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 13:
+ Pod: Pod1
+ GripSide: A1 near
+ Source: P12
+ Target: Orbital1
+ LeaveBottomLabware: False
+
+ 步骤 14:
+ Device:
+ Parameters: ()
+ Command:
+
+ 步骤 15:
+ Pod: Pod1
+ GripSide: A1 near
+ Source: Orbital1
+ Target: P12
+ LeaveBottomLabware: False
+
+ 步骤 16:
+ Message: Paused
+ Location: the whole system
+ Time: 180
+ Mode: TimedResource
+
+ 步骤 17:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P12', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Well Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P22', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Tip Contents', 'LabwareClass': 'AgilentReservoir', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True,), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 200 µL from P12 to P22
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC1025F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 18:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P12', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Well Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P22', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Tip Contents', 'LabwareClass': 'AgilentReservoir', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True,), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 200 µL from P12 to P22
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC1025F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 19:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P3', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Well Contents', 'LabwareClass': 'AgilentReservoir', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True,), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P12', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Tip Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 200 µL from P3 to P12
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC1025F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 20:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P3', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Well Contents', 'LabwareClass': 'AgilentReservoir', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True,), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P12', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Tip Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 200 µL from P3 to P12
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC1025F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 21:
+ Pod: Pod1
+ GripSide: A1 near
+ Source: P12
+ Target: Orbital1
+ LeaveBottomLabware: False
+
+ 步骤 22:
+ Device: OrbitalShaker0
+ Parameters: ('800', '3', '45', 'CounterClockwise', None)
+ Command: Timed Shake
+
+ 步骤 23:
+ Pod: Pod1
+ GripSide: A1 near
+ Source: Orbital1
+ Target: P12
+ LeaveBottomLabware: False
+
+ 步骤 24:
+ Message: Paused
+ Location: the whole system
+ Time: 180
+ Mode: TimedResource
+
+ 步骤 25:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P12', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Well Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P22', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Tip Contents', 'LabwareClass': 'AgilentReservoir', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True,), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 200 µL from P12 to P22
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC1025F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 26:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P12', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Well Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P22', 'Height': -2.0, 'Volume': '200', 'liquidtype': 'Tip Contents', 'LabwareClass': 'AgilentReservoir', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True,), 'Prototype': 'MC P300 High', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 200 µL from P12 to P22
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC1025F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 27:
+ Message: Paused
+ Location: the whole system
+ Time: 900
+ Mode: TimedResource
+
+ 步骤 28:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P4', 'Height': -2.0, 'Volume': '40', 'liquidtype': 'Well Contents', 'WellsX': 12, 'LabwareClass': 'Matrix96_750uL', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P12', 'Height': -2.0, 'Volume': '40', 'liquidtype': 'Tip Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 40 µL from P4 to P12
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC50F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 29:
+ Pod: Pod1
+ GripSide: A1 near
+ Source: P12
+ Target: Orbital1
+ LeaveBottomLabware: False
+
+ 步骤 30:
+ Device: OrbitalShaker0
+ Parameters: ('800', '3', '60', 'CounterClockwise', None)
+ Command: Timed Shake
+
+ 步骤 31:
+ Message: Paused
+ Location: the whole system
+ Time: 180
+ Mode: TimedResource
+
+ 步骤 32:
+ Pod: Pod1
+ GripSide: A1 near
+ Source: Orbital1
+ Target: P12
+ LeaveBottomLabware: False
+
+ 步骤 33:
+ Message: Paused
+ Location: the whole system
+ Time: 120
+ Mode: TimedResource
+
+ 步骤 34:
+ Span8: False
+ Pod: Pod1
+ Wash: False
+ items: [{'Position': 'P12', 'Height': -2.0, 'Volume': '40', 'liquidtype': 'Well Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Aspirate', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': True, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}, {'Position': 'P13', 'Height': -2.0, 'Volume': '40', 'liquidtype': 'Tip Contents', 'WellsX': 12, 'LabwareClass': 'BCDeep96Round', 'AutoSelectPrototype': True, 'ColsFirst': True, 'CustomHeight': False, 'DataSetPattern': False, 'HeightFrom': 0, 'LocalPattern': True, 'Operation': 'Dispense', 'OverrideHeight': False, 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True), 'Prototype': 'MC', 'ReferencedPattern': '', 'RowsFirst': False, 'SectionExpression': '', 'SelectionInfo': (1,), 'SetMark': True, 'Source': False, 'StartAtMark': False, 'StartAtSelection': True, 'UseExpression': False}]
+ Dynamic?: True
+ AutoSelectActiveWashTechnique: False
+ ActiveWashTechnique:
+ ChangeTipsBetweenDests: True
+ ChangeTipsBetweenSources: False
+ DefaultCaption: Transfer 40 µL from P12 to P13
+ UseExpression: False
+ LeaveTipsOn: False
+ MandrelExpression:
+ Repeats: 1
+ RepeatsByVolume: False
+ Replicates: 1
+ ShowTipHandlingDetails: True
+ ShowTransferDetails: True
+ Solvent: Water
+ Span8Wash: False
+ Span8WashVolume: 2
+ Span8WasteVolume: 1
+ SplitVolume: False
+ SplitVolumeCleaning: False
+ Stop: Destinations
+ TipLocation: BC50F
+ UseCurrentTips: False
+ UseDisposableTips: False
+ UseFixedTips: False
+ UseJIT: True
+ UseMandrelSelection: True
+ UseProbes: (True, True, True, True, True, True, True, True)
+ WashCycles: 4
+ WashVolume: 110%
+ Wizard: False
+
+ 步骤 35:
+ Type:
+ Bitmap: OStepUI.ocx,FINISH
+ cleardeck: True
+ cleardevices: True
+ cleanuppods: True
+ PodsToMaxZ: True
+ ClearGlobals: True
+ ParkPods: True
+ Authent: False
+ Collapsed: True
+ ConnectionString:
+ Password:
+ Path:
+ Report: False
+ Server:
+ TableName:
+ UserName:
+ Catalog:
diff --git a/unilabos/devices/liquid_handling/biomek_temporary_protocol.json b/unilabos/devices/liquid_handling/biomek_temporary_protocol.json
new file mode 100644
index 0000000..129c3ba
--- /dev/null
+++ b/unilabos/devices/liquid_handling/biomek_temporary_protocol.json
@@ -0,0 +1,2697 @@
+{
+ "meta": {},
+ "labwares": [],
+ "steps": [
+ {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ },
+ {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ },
+ {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ },
+ {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ },
+ {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ },
+ {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ },
+ {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ },
+ {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ },
+ {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ ]
+}
\ No newline at end of file
diff --git a/unilabos/devices/liquid_handling/biomek_test.py b/unilabos/devices/liquid_handling/biomek_test.py
new file mode 100644
index 0000000..1e56f18
--- /dev/null
+++ b/unilabos/devices/liquid_handling/biomek_test.py
@@ -0,0 +1,1010 @@
+# import requests
+from typing import List, Sequence, Optional, Union, Literal
+# from geometry_msgs.msg import Point
+# from unilabos_msgs.msg import Resource
+# from pylabrobot.resources import (
+# Resource,
+# TipRack,
+# Container,
+# Coordinate,
+# Well
+# )
+# from unilabos.ros.nodes.resource_tracker import DeviceNodeResourceTracker # type: ignore
+# from .liquid_handler_abstract import LiquidHandlerAbstract
+
+import json
+import pathlib
+from typing import Sequence, Optional, List, Union, Literal
+
+
+
+#class LiquidHandlerBiomek(LiquidHandlerAbstract):
+
+
+class LiquidHandlerBiomek:
+ """
+ Biomek液体处理器的实现类,继承自LiquidHandlerAbstract。
+ 该类用于处理Biomek液体处理器的特定操作。
+ """
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self._status = "Idle" # 初始状态为 Idle
+ self._success = False # 初始成功状态为 False
+ self._status_queue = kwargs.get("status_queue", None) # 状态队列
+ self.temp_protocol = {}
+ self.py32_path = "/opt/py32" # Biomek的Python 3.2路径
+
+ # 预定义的仪器分类
+ self.tip_racks = [
+ "BC230", "BC1025F", "BC50", "TipRack200", "TipRack1000",
+ "tip", "tips", "Tip", "Tips"
+ ]
+
+ self.reservoirs = [
+ "AgilentReservoir", "nest_12_reservoir_15ml", "nest_1_reservoir_195ml",
+ "reservoir", "Reservoir", "waste", "Waste"
+ ]
+
+ self.plates_96 = [
+ "BCDeep96Round", "Matrix96_750uL", "NEST 2ml Deep Well Plate", "nest_96_wellplate_100ul_pcr_full_skirt",
+ "nest_96_wellplate_200ul_flat", "Matrix96", "96", "plate", "Plate"
+ ]
+
+ self.aspirate_techniques = {
+ 'MC P300 high':{
+ 'Position': 'P1',
+ 'Height': -2.0,
+ 'Volume': '50',
+ 'liquidtype': 'Well Contents',
+ 'WellsX': 12,
+ 'LabwareClass': 'Matrix96_750uL',
+ 'AutoSelectPrototype': True,
+ 'ColsFirst': True,
+ 'CustomHeight': False,
+ 'DataSetPattern': False,
+ 'HeightFrom': 0,
+ 'LocalPattern': True,
+ 'Operation': 'Aspirate',
+ 'OverrideHeight': False,
+ 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True),
+ 'Prototype': 'MC P300 High',
+ 'ReferencedPattern': '',
+ 'RowsFirst': False,
+ 'SectionExpression': '',
+ 'SelectionInfo': (1,),
+ 'SetMark': True,
+ 'Source': True,
+ 'StartAtMark': False,
+ 'StartAtSelection': True,
+ 'UseExpression': False},
+ }
+
+ self.dispense_techniques = {
+ 'MC P300 high':{
+ 'Position': 'P11',
+ 'Height': -2.0,
+ 'Volume': '50',
+ 'liquidtype': 'Tip Contents',
+ 'WellsX': 12,
+ 'LabwareClass': 'Matrix96_750uL',
+ 'AutoSelectPrototype': True,
+ 'ColsFirst': True,
+ 'CustomHeight': False,
+ 'DataSetPattern': False,
+ 'HeightFrom': 0,
+ 'LocalPattern': True,
+ 'Operation': 'Dispense',
+ 'OverrideHeight': False,
+ 'Pattern': (True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True),
+ 'Prototype': 'MC P300 High',
+ 'ReferencedPattern': '',
+ 'RowsFirst': False,
+ 'SectionExpression': '',
+ 'SelectionInfo': (1,),
+ 'SetMark': True,
+ 'Source': False,
+ 'StartAtMark': False,
+ 'StartAtSelection': True,
+ 'UseExpression': False}
+ }
+
+
+ def _get_instrument_type(self, class_name: str) -> str:
+ """
+ 根据class_name判断仪器类型
+
+ Returns:
+ str: "tip_rack", "reservoir", "plate_96", 或 "unknown"
+ """
+ # 检查是否是枪头架
+ for tip_name in self.tip_racks:
+ if tip_name in class_name:
+ return "tip_rack"
+
+ # 检查是否是储液槽
+ for reservoir_name in self.reservoirs:
+ if reservoir_name in class_name:
+ return "reservoir"
+
+ # 检查是否是96孔板
+ for plate_name in self.plates_96:
+ if plate_name in class_name:
+ return "plate_96"
+
+ return "unknown"
+
+ def create_protocol(
+ self,
+ protocol_name: str,
+ protocol_description: str,
+ protocol_version: str,
+ protocol_author: str,
+ protocol_date: str,
+ protocol_type: str,
+ none_keys: List[str] = [],
+ ):
+ """
+ 创建一个新的协议。
+
+ Args:
+ protocol_name (str): 协议名称
+ protocol_description (str): 协议描述
+ protocol_version (str): 协议版本
+ protocol_author (str): 协议作者
+ protocol_date (str): 协议日期
+ protocol_type (str): 协议类型
+ none_keys (List[str]): 需要设置为None的键列表
+
+ Returns:
+ dict: 创建的协议字典
+ """
+ self.temp_protocol = {
+ "meta": {
+ "name": protocol_name,
+ "description": protocol_description,
+ "version": protocol_version,
+ "author": protocol_author,
+ "date": protocol_date,
+ "type": protocol_type,
+ },
+ "labwares": {}, # 改为字典格式以匹配DeckItems
+ "steps": [],
+ }
+ return self.temp_protocol
+
+# def run_protocol(self):
+# """
+# 执行创建的实验流程。
+# 工作站的完整执行流程是,
+# 从 create_protocol 开始,创建新的 method,
+# 随后执行 transfer_liquid 等操作向实验流程添加步骤,
+# 最后 run_protocol 执行整个方法。
+
+# Returns:
+# dict: 执行结果
+# """
+# #use popen or subprocess to create py32 process and communicate send the temp protocol to it
+# if not self.temp_protocol:
+# raise ValueError("No protocol created. Please create a protocol first.")
+
+# # 模拟执行协议
+# self._status = "Running"
+# self._success = True
+# # 在这里可以添加实际执行协议的逻辑
+
+# response = requests.post("localhost:5000/api/protocols", json=self.temp_protocol)
+
+# def create_resource(
+# self,
+# resource_tracker: DeviceNodeResourceTracker,
+# resources: list[Resource],
+# bind_parent_id: str,
+# bind_location: dict[str, float],
+# liquid_input_slot: list[int],
+# liquid_type: list[str],
+# liquid_volume: list[int],
+# slot_on_deck: int,
+# res_id,
+# class_name,
+# bind_locations,
+# parent
+# ):
+# """
+# 创建一个新的资源。
+
+# Args:
+# device_id (str): 设备ID
+# res_id (str): 资源ID
+# class_name (str): 资源类名
+# parent (str): 父级ID
+# bind_locations (Point): 绑定位置
+# liquid_input_slot (list[int]): 液体输入槽列表
+# liquid_type (list[str]): 液体类型列表
+# liquid_volume (list[int]): 液体体积列表
+# slot_on_deck (int): 甲板上的槽位
+
+# Returns:
+# dict: 创建的资源字典
+# """
+# # TODO:需要对好接口,下面这个是临时的
+# resource = {
+# "id": res_id,
+# "class": class_name,
+# "parent": parent,
+# "bind_locations": bind_locations.to_dict(),
+# "liquid_input_slot": liquid_input_slot,
+# "liquid_type": liquid_type,
+# "liquid_volume": liquid_volume,
+# "slot_on_deck": slot_on_deck,
+# }
+# self.temp_protocol["labwares"].append(resource)
+# return resource
+ def instrument_setup_biomek(
+ self,
+ id: str,
+ parent: str,
+ slot_on_deck: str,
+ class_name: str,
+ liquid_type: list[str],
+ liquid_volume: list[int],
+ liquid_input_wells: list[str],
+ ):
+ """
+ 设置Biomek仪器的参数配置,按照DeckItems格式
+
+ 根据不同的仪器类型(容器、tip rack等)设置相应的参数结构
+ 位置作为键,配置列表作为值
+ """
+
+ # 判断仪器类型
+ instrument_type = self._get_instrument_type(class_name)
+
+ config = None # 初始化为None
+
+ if instrument_type == "reservoir":
+ # 储液槽类型配置
+ config = {
+ "Properties": {
+ "Name": id, # 使用id作为名称
+ "Device": "",
+ "liquidtype": liquid_type[0] if liquid_type else "Water",
+ "BarCode": "",
+ "SenseEveryTime": False
+ },
+ "Known": True,
+ "Class": f"LabwareClasses\\{class_name}",
+ "DataSets": {"Volume": {}},
+ "RuntimeDataSets": {"Volume": {}},
+ "EvalAmounts": (float(liquid_volume[0]),) if liquid_volume else (0,),
+ "Nominal": False,
+ "EvalLiquids": (liquid_type[0],) if liquid_type else ("Water",)
+ }
+
+ elif instrument_type == "plate_96":
+ # 96孔板类型配置
+ volume_per_well = float(liquid_volume[0]) if liquid_volume else 0
+ liquid_per_well = liquid_type[0] if liquid_type else "Water"
+
+ config = {
+ "Properties": {
+ "Name": id, # 使用id作为名称
+ "Device": "",
+ "liquidtype": liquid_per_well,
+ "BarCode": "",
+ "SenseEveryTime": False
+ },
+ "Known": True,
+ "Class": f"LabwareClasses\\{class_name}",
+ "DataSets": {"Volume": {}},
+ "RuntimeDataSets": {"Volume": {}},
+ "EvalAmounts": tuple([volume_per_well] * 96),
+ "Nominal": False,
+ "EvalLiquids": tuple([liquid_per_well] * 96)
+ }
+
+ elif instrument_type == "tip_rack":
+ # 枪头架类型配置
+ tip_config = {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": False,
+ "RT_Used": False,
+ "Dirty": False,
+ "RT_Dirty": False,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ }
+
+ config = {
+ "Tips": tip_config,
+ "RT_Tips": tip_config.copy(),
+ "Properties": {},
+ "Known": False,
+ "Class": f"LabwareClasses\\{class_name}",
+ "DataSets": {"Volume": {}},
+ "RuntimeDataSets": {"Volume": {}}
+ }
+
+ # 按照DeckItems格式存储:位置作为键,配置列表作为值
+ if config is not None:
+ self.temp_protocol["labwares"][slot_on_deck] = [config]
+ else:
+ # 空位置
+ self.temp_protocol["labwares"][slot_on_deck] = []
+
+ return
+
+ def transfer_biomek(
+ self,
+ source: str,
+ target: str,
+ tip_rack: str,
+ volume: float,
+ aspirate_techniques: str,
+ dispense_techniques: str,
+ ):
+ """
+ 处理Biomek的液体转移操作。
+
+ """
+ items = []
+
+ asp_params = self.aspirate_techniques.get(aspirate_techniques, {})
+ dis_params = self.dispense_techniques.get(dispense_techniques, {})
+
+ asp_params['Position'] = source
+ dis_params['Position'] = target
+ asp_params['Volume'] = str(volume)
+ dis_params['Volume'] = str(volume)
+
+ items.append(asp_params)
+ items.append(dis_params)
+
+ transfer_params = {
+ "Span8": False,
+ "Pod": "Pod1",
+ "items": [],
+ "Wash": False,
+ "Dynamic?": True,
+ "AutoSelectActiveWashTechnique": False,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": True,
+ "ChangeTipsBetweenSources": False,
+ "DefaultCaption": "",
+ "UseExpression": False,
+ "LeaveTipsOn": False,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": False,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": False,
+ "ShowTransferDetails": True,
+ "Solvent": "Water",
+ "Span8Wash": False,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": False,
+ "SplitVolumeCleaning": False,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": False,
+ "UseDisposableTips": False,
+ "UseFixedTips": False,
+ "UseJIT": True,
+ "UseMandrelSelection": True,
+ "UseProbes": [True, True, True, True, True, True, True, True],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": False
+ }
+ transfer_params["items"] = items
+ transfer_params["Solvent"] = 'Water'
+ transfer_params["TipLocation"] = tip_rack
+ tmp={'transfer': transfer_params}
+ self.temp_protocol["steps"].append(tmp)
+
+ return
+
+ def move_biomek(
+ self,
+ source: str,
+ target: str,
+ ):
+ """
+ 处理Biomek移动板子的操作。
+
+ """
+
+ move_params = {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": source,
+ "Target": target,
+ "LeaveBottomLabware": False,
+ }
+ tmp={'move': move_params}
+ self.temp_protocol["steps"].append(tmp)
+
+ return
+
+ def incubation_biomek(
+ self,
+ time: int,
+ ):
+ """
+ 处理Biomek的孵育操作。
+ """
+ incubation_params = {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": time,
+ "Mode": "TimedResource"
+ }
+ tmp={'incubation': incubation_params}
+ self.temp_protocol["steps"].append(tmp)
+
+ return
+
+ def oscillation_biomek(
+ self,
+ rpm: int,
+ time: int,
+ ):
+ """
+ 处理Biomek的振荡操作。
+ """
+ oscillation_params = {
+ 'Device': 'OrbitalShaker0',
+ 'Parameters': (str(rpm), '2', str(time), 'CounterClockwise'),
+ 'Command': 'Timed Shake'
+ }
+ tmp={'oscillation': oscillation_params}
+ self.temp_protocol["steps"].append(tmp)
+
+ return
+
+
+
+if __name__ == "__main__":
+
+ print("=== Biomek完整流程测试 ===")
+ print("包含: 仪器设置 + 完整实验步骤")
+
+ # 完整的步骤信息(从biomek.py复制)
+ steps_info = '''
+ {
+ "steps": [
+ {
+ "step_number": 1,
+ "operation": "transfer",
+ "description": "转移PCR产物或酶促反应液至0.5ml 96孔板中",
+ "parameters": {
+ "source": "P1",
+ "target": "P11",
+ "tip_rack": "BC230",
+ "volume": 50
+ }
+ },
+ {
+ "step_number": 2,
+ "operation": "transfer",
+ "description": "加入2倍体积的Bind Beads BC至产物中",
+ "parameters": {
+ "source": "P2",
+ "target": "P11",
+ "tip_rack": "BC230",
+ "volume": 100
+ }
+ },
+ {
+ "step_number": 3,
+ "operation": "oscillation",
+ "description": "振荡混匀300秒",
+ "parameters": {
+ "rpm": 800,
+ "time": 300
+ }
+ },
+ {
+ "step_number": 4,
+ "operation": "move_labware",
+ "description": "转移至96孔磁力架上吸附3分钟",
+ "parameters": {
+ "source": "P11",
+ "target": "P12"
+ }
+ },
+ {
+ "step_number": 5,
+ "operation": "incubation",
+ "description": "吸附3分钟",
+ "parameters": {
+ "time": 180
+ }
+ },
+ {
+ "step_number": 6,
+ "operation": "transfer",
+ "description": "吸弃或倒除上清液",
+ "parameters": {
+ "source": "P12",
+ "target": "P22",
+ "tip_rack": "BC230",
+ "volume": 150
+ }
+ },
+ {
+ "step_number": 7,
+ "operation": "transfer",
+ "description": "加入300-500μl 75%乙醇",
+ "parameters": {
+ "source": "P3",
+ "target": "P12",
+ "tip_rack": "BC230",
+ "volume": 400
+ }
+ },
+ {
+ "step_number": 8,
+ "operation": "move_labware",
+ "description": "移动至振荡器进行振荡混匀",
+ "parameters": {
+ "source": "P12",
+ "target": "Orbital1"
+ }
+ },
+ {
+ "step_number": 9,
+ "operation": "oscillation",
+ "description": "振荡混匀60秒",
+ "parameters": {
+ "rpm": 800,
+ "time": 60
+ }
+ },
+ {
+ "step_number": 10,
+ "operation": "move_labware",
+ "description": "转移至96孔磁力架上吸附3分钟",
+ "parameters": {
+ "source": "Orbital1",
+ "target": "P12"
+ }
+ },
+ {
+ "step_number": 11,
+ "operation": "incubation",
+ "description": "吸附3分钟",
+ "parameters": {
+ "time": 180
+ }
+ },
+ {
+ "step_number": 12,
+ "operation": "transfer",
+ "description": "吸弃或倒弃废液",
+ "parameters": {
+ "source": "P12",
+ "target": "P22",
+ "tip_rack": "BC230",
+ "volume": 400
+ }
+ },
+ {
+ "step_number": 13,
+ "operation": "transfer",
+ "description": "重复加入75%乙醇",
+ "parameters": {
+ "source": "P3",
+ "target": "P12",
+ "tip_rack": "BC230",
+ "volume": 400
+ }
+ },
+ {
+ "step_number": 14,
+ "operation": "move_labware",
+ "description": "移动至振荡器进行振荡混匀",
+ "parameters": {
+ "source": "P12",
+ "target": "Orbital1"
+ }
+ },
+ {
+ "step_number": 15,
+ "operation": "oscillation",
+ "description": "振荡混匀60秒",
+ "parameters": {
+ "rpm": 800,
+ "time": 60
+ }
+ },
+ {
+ "step_number": 16,
+ "operation": "move_labware",
+ "description": "转移至96孔磁力架上吸附3分钟",
+ "parameters": {
+ "source": "Orbital1",
+ "target": "P12"
+ }
+ },
+ {
+ "step_number": 17,
+ "operation": "incubation",
+ "description": "吸附3分钟",
+ "parameters": {
+ "time": 180
+ }
+ },
+ {
+ "step_number": 18,
+ "operation": "transfer",
+ "description": "吸弃或倒弃废液",
+ "parameters": {
+ "source": "P12",
+ "target": "P22",
+ "tip_rack": "BC230",
+ "volume": 400
+ }
+ },
+ {
+ "step_number": 19,
+ "operation": "move_labware",
+ "description": "正放96孔板,空气干燥15分钟",
+ "parameters": {
+ "source": "P12",
+ "target": "P13"
+ }
+ },
+ {
+ "step_number": 20,
+ "operation": "incubation",
+ "description": "空气干燥15分钟",
+ "parameters": {
+ "time": 900
+ }
+ },
+ {
+ "step_number": 21,
+ "operation": "transfer",
+ "description": "加入30-50μl Elution Buffer",
+ "parameters": {
+ "source": "P4",
+ "target": "P13",
+ "tip_rack": "BC230",
+ "volume": 40
+ }
+ },
+ {
+ "step_number": 22,
+ "operation": "move_labware",
+ "description": "移动至振荡器进行振荡混匀",
+ "parameters": {
+ "source": "P13",
+ "target": "Orbital1"
+ }
+ },
+ {
+ "step_number": 23,
+ "operation": "oscillation",
+ "description": "振荡混匀60秒",
+ "parameters": {
+ "rpm": 800,
+ "time": 60
+ }
+ },
+ {
+ "step_number": 24,
+ "operation": "move_labware",
+ "description": "室温静置3分钟",
+ "parameters": {
+ "source": "Orbital1",
+ "target": "P13"
+ }
+ },
+ {
+ "step_number": 25,
+ "operation": "incubation",
+ "description": "室温静置3分钟",
+ "parameters": {
+ "time": 180
+ }
+ },
+ {
+ "step_number": 26,
+ "operation": "move_labware",
+ "description": "转移至96孔磁力架上吸附2分钟",
+ "parameters": {
+ "source": "P13",
+ "target": "P12"
+ }
+ },
+ {
+ "step_number": 27,
+ "operation": "incubation",
+ "description": "吸附2分钟",
+ "parameters": {
+ "time": 120
+ }
+ },
+ {
+ "step_number": 28,
+ "operation": "transfer",
+ "description": "将DNA转移至新的板中",
+ "parameters": {
+ "source": "P12",
+ "target": "P14",
+ "tip_rack": "BC230",
+ "volume": 40
+ }
+ }
+ ]
+ }
+'''
+ # 完整的labware配置信息
+ labware_with_liquid = '''
+ [
+ {
+ "id": "Tip Rack BC230 TL1",
+ "parent": "deck",
+ "slot_on_deck": "TL1",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 TL2",
+ "parent": "deck",
+ "slot_on_deck": "TL2",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 TL3",
+ "parent": "deck",
+ "slot_on_deck": "TL3",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 TL4",
+ "parent": "deck",
+ "slot_on_deck": "TL4",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 TL5",
+ "parent": "deck",
+ "slot_on_deck": "TL5",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 P5",
+ "parent": "deck",
+ "slot_on_deck": "P5",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 P6",
+ "parent": "deck",
+ "slot_on_deck": "P6",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 P15",
+ "parent": "deck",
+ "slot_on_deck": "P15",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "Tip Rack BC230 P16",
+ "parent": "deck",
+ "slot_on_deck": "P16",
+ "class_name": "BC230",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "stock plate on P1",
+ "parent": "deck",
+ "slot_on_deck": "P1",
+ "class_name": "AgilentReservoir",
+ "liquid_type": ["PCR product"],
+ "liquid_volume": [5000],
+ "liquid_input_wells": ["A1"]
+ },
+ {
+ "id": "stock plate on P2",
+ "parent": "deck",
+ "slot_on_deck": "P2",
+ "class_name": "AgilentReservoir",
+ "liquid_type": ["bind beads"],
+ "liquid_volume": [100000],
+ "liquid_input_wells": ["A1"]
+ },
+ {
+ "id": "stock plate on P3",
+ "parent": "deck",
+ "slot_on_deck": "P3",
+ "class_name": "AgilentReservoir",
+ "liquid_type": ["75% ethanol"],
+ "liquid_volume": [100000],
+ "liquid_input_wells": ["A1"]
+ },
+ {
+ "id": "stock plate on P4",
+ "parent": "deck",
+ "slot_on_deck": "P4",
+ "class_name": "AgilentReservoir",
+ "liquid_type": ["Elution Buffer"],
+ "liquid_volume": [5000],
+ "liquid_input_wells": ["A1"]
+ },
+ {
+ "id": "working plate on P11",
+ "parent": "deck",
+ "slot_on_deck": "P11",
+ "class_name": "BCDeep96Round",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "working plate on P12",
+ "parent": "deck",
+ "slot_on_deck": "P12",
+ "class_name": "BCDeep96Round",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "working plate on P13",
+ "parent": "deck",
+ "slot_on_deck": "P13",
+ "class_name": "BCDeep96Round",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "working plate on P14",
+ "parent": "deck",
+ "slot_on_deck": "P14",
+ "class_name": "BCDeep96Round",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "waste on P22",
+ "parent": "deck",
+ "slot_on_deck": "P22",
+ "class_name": "AgilentReservoir",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ },
+ {
+ "id": "oscillation",
+ "parent": "deck",
+ "slot_on_deck": "Orbital1",
+ "class_name": "Orbital",
+ "liquid_type": [],
+ "liquid_volume": [],
+ "liquid_input_wells": []
+ }
+ ]
+ '''
+
+ # 创建handler实例
+ handler = LiquidHandlerBiomek()
+
+ # 创建协议
+ protocol = handler.create_protocol(
+ protocol_name="DNA纯化完整流程",
+ protocol_description="使用磁珠进行DNA纯化的完整自动化流程",
+ protocol_version="1.0",
+ protocol_author="Biomek系统",
+ protocol_date="2024-01-01",
+ protocol_type="DNA_purification"
+ )
+
+ print("\n=== 第一步:设置所有仪器 ===")
+ # 解析labware配置
+ labwares = json.loads(labware_with_liquid)
+
+ # 设置所有仪器
+ instrument_count = 0
+ for labware in labwares:
+ print(f"设置仪器: {labware['id']} ({labware['class_name']}) 在位置 {labware['slot_on_deck']}")
+ handler.instrument_setup_biomek(
+ id=labware['id'],
+ parent=labware['parent'],
+ slot_on_deck=labware['slot_on_deck'],
+ class_name=labware['class_name'],
+ liquid_type=labware['liquid_type'],
+ liquid_volume=labware['liquid_volume'],
+ liquid_input_wells=labware['liquid_input_wells']
+ )
+ instrument_count += 1
+
+ print(f"总共设置了 {instrument_count} 个仪器位置")
+
+ print("\n=== 第二步:执行实验步骤 ===")
+ # 解析步骤信息
+ input_steps = json.loads(steps_info)
+
+ # 执行所有步骤
+ step_count = 0
+ for step in input_steps['steps']:
+ operation = step['operation']
+ parameters = step['parameters']
+ description = step['description']
+
+ print(f"步骤 {step['step_number']}: {description}")
+
+ if operation == 'transfer':
+ handler.transfer_biomek(
+ source=parameters['source'],
+ target=parameters['target'],
+ volume=parameters['volume'],
+ tip_rack=parameters['tip_rack'],
+ aspirate_techniques='MC P300 high',
+ dispense_techniques='MC P300 high'
+ )
+ elif operation == 'move_labware':
+ handler.move_biomek(
+ source=parameters['source'],
+ target=parameters['target']
+ )
+ elif operation == 'oscillation':
+ handler.oscillation_biomek(
+ rpm=parameters['rpm'],
+ time=parameters['time']
+ )
+ elif operation == 'incubation':
+ handler.incubation_biomek(
+ time=parameters['time']
+ )
+
+ step_count += 1
+
+ print(f"总共执行了 {step_count} 个步骤")
+
+ print("\n=== 第三步:保存完整协议 ===")
+ # 获取脚本目录
+ script_dir = pathlib.Path(__file__).parent
+
+ # 保存完整协议
+ complete_output_path = script_dir / "complete_biomek_protocol_0608.json"
+ with open(complete_output_path, 'w', encoding='utf-8') as f:
+ json.dump(handler.temp_protocol, f, indent=4, ensure_ascii=False)
+
+ print(f"完整协议已保存到: {complete_output_path}")
+
+ print("\n=== 测试完成 ===")
+ print("完整的DNA纯化流程已成功转换为Biomek格式!")
diff --git a/unilabos/devices/liquid_handling/complete_biomek_protocol.json b/unilabos/devices/liquid_handling/complete_biomek_protocol.json
new file mode 100644
index 0000000..2c0e95f
--- /dev/null
+++ b/unilabos/devices/liquid_handling/complete_biomek_protocol.json
@@ -0,0 +1,3760 @@
+{
+ "meta": {
+ "name": "DNA纯化完整流程",
+ "description": "使用磁珠进行DNA纯化的完整自动化流程",
+ "version": "1.0",
+ "author": "Biomek系统",
+ "date": "2024-01-01",
+ "type": "DNA_purification"
+ },
+ "labwares": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "Name": "Tip Rack BC230 on TL1",
+ "Position": "TL1"
+ },
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "Name": "Tip Rack BC230 on TL2",
+ "Position": "TL2"
+ },
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "Name": "Tip Rack BC230 on TL3",
+ "Position": "TL3"
+ },
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "Name": "Tip Rack BC230 on TL4",
+ "Position": "TL4"
+ },
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "Name": "Tip Rack BC230 on TL5",
+ "Position": "TL5"
+ },
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "Name": "Tip Rack BC230 on P5",
+ "Position": "P5"
+ },
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "Name": "Tip Rack BC230 on P6",
+ "Position": "P6"
+ },
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "Name": "Tip Rack BC230 on P15",
+ "Position": "P15"
+ },
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "Name": "Tip Rack BC230 on P16",
+ "Position": "P16"
+ },
+ {
+ "Properties": {
+ "Name": "stock plate on P1",
+ "Device": "",
+ "liquidtype": "master_mix",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\nest_12_reservoir_15ml",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 10000.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "master_mix"
+ ],
+ "Name": "stock plate on P1",
+ "Position": "P1"
+ },
+ {
+ "Properties": {
+ "Name": "stock plate on P2",
+ "Device": "",
+ "liquidtype": "bind beads",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\nest_12_reservoir_15ml",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 10000.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "bind beads"
+ ],
+ "Name": "stock plate on P2",
+ "Position": "P2"
+ },
+ {
+ "Properties": {
+ "Name": "stock plate on P3",
+ "Device": "",
+ "liquidtype": "ethyl alcohol",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\nest_12_reservoir_15ml",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 10000.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "ethyl alcohol"
+ ],
+ "Name": "stock plate on P3",
+ "Position": "P3"
+ },
+ {
+ "Properties": {
+ "Name": "elution buffer on P4",
+ "Device": "",
+ "liquidtype": "elution buffer",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\nest_12_reservoir_15ml",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 5000.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "elution buffer"
+ ],
+ "Name": "elution buffer on P4",
+ "Position": "P4"
+ },
+ {
+ "Properties": {
+ "Name": "working plate on P11",
+ "Device": "",
+ "liquidtype": "Water",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\NEST 2ml Deep Well Plate",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water"
+ ],
+ "Name": "working plate on P11",
+ "Position": "P11"
+ },
+ {
+ "Properties": {
+ "Name": "working plate on P13",
+ "Device": "",
+ "liquidtype": "Water",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\NEST 2ml Deep Well Plate",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0,
+ 500.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water"
+ ],
+ "Name": "working plate on P13",
+ "Position": "P13"
+ },
+ {
+ "Properties": {
+ "Name": "waste on P22",
+ "Device": "",
+ "liquidtype": "Water",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\nest_1_reservoir_195ml",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 0.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "Water"
+ ],
+ "Name": "waste on P22",
+ "Position": "P22"
+ }
+ ],
+ "steps": [
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P11",
+ "Target": "Orbital1",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "oscillation": {
+ "Device": "OrbitalShaker0",
+ "Parameters": [
+ "800",
+ "2",
+ "300",
+ "CounterClockwise"
+ ],
+ "Command": "Timed Shake"
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "Orbital1",
+ "Target": "P11",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P11",
+ "Target": "P12",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 180,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P12",
+ "Target": "Orbital1",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "oscillation": {
+ "Device": "OrbitalShaker0",
+ "Parameters": [
+ "800",
+ "2",
+ "45",
+ "CounterClockwise"
+ ],
+ "Command": "Timed Shake"
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "Orbital1",
+ "Target": "P12",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 180,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P12",
+ "Target": "Orbital1",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "oscillation": {
+ "Device": "OrbitalShaker0",
+ "Parameters": [
+ "800",
+ "2",
+ "45",
+ "CounterClockwise"
+ ],
+ "Command": "Timed Shake"
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "Orbital1",
+ "Target": "P12",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 180,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 900,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P12",
+ "Target": "Orbital1",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "oscillation": {
+ "Device": "OrbitalShaker0",
+ "Parameters": [
+ "800",
+ "2",
+ "60",
+ "CounterClockwise"
+ ],
+ "Command": "Timed Shake"
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "Orbital1",
+ "Target": "P12",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 180,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P13",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/unilabos/devices/liquid_handling/complete_biomek_protocol_0608.json b/unilabos/devices/liquid_handling/complete_biomek_protocol_0608.json
new file mode 100644
index 0000000..24b3d45
--- /dev/null
+++ b/unilabos/devices/liquid_handling/complete_biomek_protocol_0608.json
@@ -0,0 +1,4201 @@
+{
+ "meta": {
+ "name": "DNA纯化完整流程",
+ "description": "使用磁珠进行DNA纯化的完整自动化流程",
+ "version": "1.0",
+ "author": "Biomek系统",
+ "date": "2024-01-01",
+ "type": "DNA_purification"
+ },
+ "labwares": {
+ "TL1": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ }
+ }
+ ],
+ "TL2": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ }
+ }
+ ],
+ "TL3": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ }
+ }
+ ],
+ "TL4": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ }
+ }
+ ],
+ "TL5": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ }
+ }
+ ],
+ "P5": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ }
+ }
+ ],
+ "P6": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ }
+ }
+ ],
+ "P15": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ }
+ }
+ ],
+ "P16": [
+ {
+ "Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "RT_Tips": {
+ "Class": "TipClasses\\T230",
+ "Contents": [],
+ "_RT_Contents": [],
+ "Used": false,
+ "RT_Used": false,
+ "Dirty": false,
+ "RT_Dirty": false,
+ "MaxVolumeUsed": 0.0,
+ "RT_MaxVolumeUsed": 0.0
+ },
+ "Properties": {},
+ "Known": false,
+ "Class": "LabwareClasses\\BC230",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ }
+ }
+ ],
+ "P1": [
+ {
+ "Properties": {
+ "Name": "stock plate on P1",
+ "Device": "",
+ "liquidtype": "PCR product",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\AgilentReservoir",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 5000.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "PCR product"
+ ]
+ }
+ ],
+ "P2": [
+ {
+ "Properties": {
+ "Name": "stock plate on P2",
+ "Device": "",
+ "liquidtype": "bind beads",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\AgilentReservoir",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 100000.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "bind beads"
+ ]
+ }
+ ],
+ "P3": [
+ {
+ "Properties": {
+ "Name": "stock plate on P3",
+ "Device": "",
+ "liquidtype": "75% ethanol",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\AgilentReservoir",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 100000.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "75% ethanol"
+ ]
+ }
+ ],
+ "P4": [
+ {
+ "Properties": {
+ "Name": "stock plate on P4",
+ "Device": "",
+ "liquidtype": "Elution Buffer",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\AgilentReservoir",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 5000.0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "Elution Buffer"
+ ]
+ }
+ ],
+ "P11": [
+ {
+ "Properties": {
+ "Name": "working plate on P11",
+ "Device": "",
+ "liquidtype": "Water",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\BCDeep96Round",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water"
+ ]
+ }
+ ],
+ "P12": [
+ {
+ "Properties": {
+ "Name": "working plate on P12",
+ "Device": "",
+ "liquidtype": "Water",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\BCDeep96Round",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water"
+ ]
+ }
+ ],
+ "P13": [
+ {
+ "Properties": {
+ "Name": "working plate on P13",
+ "Device": "",
+ "liquidtype": "Water",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\BCDeep96Round",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water"
+ ]
+ }
+ ],
+ "P14": [
+ {
+ "Properties": {
+ "Name": "working plate on P14",
+ "Device": "",
+ "liquidtype": "Water",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\BCDeep96Round",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water",
+ "Water"
+ ]
+ }
+ ],
+ "P22": [
+ {
+ "Properties": {
+ "Name": "waste on P22",
+ "Device": "",
+ "liquidtype": "Water",
+ "BarCode": "",
+ "SenseEveryTime": false
+ },
+ "Known": true,
+ "Class": "LabwareClasses\\AgilentReservoir",
+ "DataSets": {
+ "Volume": {}
+ },
+ "RuntimeDataSets": {
+ "Volume": {}
+ },
+ "EvalAmounts": [
+ 0
+ ],
+ "Nominal": false,
+ "EvalLiquids": [
+ "Water"
+ ]
+ }
+ ],
+ "Orbital1": []
+ },
+ "steps": [
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P14",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P14",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "oscillation": {
+ "Device": "OrbitalShaker0",
+ "Parameters": [
+ "800",
+ "2",
+ "300",
+ "CounterClockwise"
+ ],
+ "Command": "Timed Shake"
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P11",
+ "Target": "P12",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 180,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P14",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P14",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P12",
+ "Target": "Orbital1",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "oscillation": {
+ "Device": "OrbitalShaker0",
+ "Parameters": [
+ "800",
+ "2",
+ "60",
+ "CounterClockwise"
+ ],
+ "Command": "Timed Shake"
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "Orbital1",
+ "Target": "P12",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 180,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P14",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P14",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P12",
+ "Target": "Orbital1",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "oscillation": {
+ "Device": "OrbitalShaker0",
+ "Parameters": [
+ "800",
+ "2",
+ "60",
+ "CounterClockwise"
+ ],
+ "Command": "Timed Shake"
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "Orbital1",
+ "Target": "P12",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 180,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P14",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P12",
+ "Target": "P13",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 900,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P14",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P13",
+ "Target": "Orbital1",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "oscillation": {
+ "Device": "OrbitalShaker0",
+ "Parameters": [
+ "800",
+ "2",
+ "60",
+ "CounterClockwise"
+ ],
+ "Command": "Timed Shake"
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "Orbital1",
+ "Target": "P13",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 180,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "move": {
+ "Pod": "Pod1",
+ "GripSide": "A1 near",
+ "Source": "P13",
+ "Target": "P12",
+ "LeaveBottomLabware": false
+ }
+ },
+ {
+ "incubation": {
+ "Message": "Paused",
+ "Location": "the whole system",
+ "Time": 120,
+ "Mode": "TimedResource"
+ }
+ },
+ {
+ "transfer": {
+ "Span8": false,
+ "Pod": "Pod1",
+ "items": [
+ {
+ "Position": "P12",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Well Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Aspirate",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": true,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ },
+ {
+ "Position": "P14",
+ "Height": -2.0,
+ "Volume": "40",
+ "liquidtype": "Tip Contents",
+ "WellsX": 12,
+ "LabwareClass": "Matrix96_750uL",
+ "AutoSelectPrototype": true,
+ "ColsFirst": true,
+ "CustomHeight": false,
+ "DataSetPattern": false,
+ "HeightFrom": 0,
+ "LocalPattern": true,
+ "Operation": "Dispense",
+ "OverrideHeight": false,
+ "Pattern": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "Prototype": "MC P300 High",
+ "ReferencedPattern": "",
+ "RowsFirst": false,
+ "SectionExpression": "",
+ "SelectionInfo": [
+ 1
+ ],
+ "SetMark": true,
+ "Source": false,
+ "StartAtMark": false,
+ "StartAtSelection": true,
+ "UseExpression": false
+ }
+ ],
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": false,
+ "ShowTransferDetails": true,
+ "Solvent": "Water",
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC230",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true
+ ],
+ "WashCycles": "4",
+ "WashVolume": "110%",
+ "Wizard": false
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/unilabos/devices/liquid_handling/converted protocol/sci-lucif-assay4_plr_background_tested.ipynb b/unilabos/devices/liquid_handling/converted protocol/sci-lucif-assay4_plr_background_tested.ipynb
index daf47e2..f380fc6 100644
--- a/unilabos/devices/liquid_handling/converted protocol/sci-lucif-assay4_plr_background_tested.ipynb
+++ b/unilabos/devices/liquid_handling/converted protocol/sci-lucif-assay4_plr_background_tested.ipynb
@@ -2,18 +2,18 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 9,
"id": "6e581f88",
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-06-08T15:32:44.429407Z",
+ "start_time": "2025-06-08T15:32:43.584559Z"
+ }
+ },
"source": [
"# NF‑κB Luciferase Reporter Assay – pylabrobot version\n",
"\n",
"import os\n",
"import sys\n",
- "os.getcwd()\n",
- "sys.path.append('/Users/guangxinzhang/Documents/Deep Potential/pylabrobot/myfile')\n",
- "\n",
"from pylabrobot.resources import Coordinate\n",
"from pylabrobot.liquid_handling.backends.chatterbox import LiquidHandlerChatterboxBackend\n",
"from pylabrobot.visualizer.visualizer import Visualizer\n",
@@ -24,33 +24,26 @@
" nest_1_reservoir_195ml,\n",
" opentrons_96_tiprack_300ul\n",
")\n",
- "from High_level_function.action_definition import DPLiquidHandler"
- ]
+ "from pylabrobot.liquid_handling import LiquidHandler"
+ ],
+ "outputs": [],
+ "execution_count": 1
},
{
"cell_type": "code",
- "execution_count": 10,
"id": "c3127d6e",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Setting up the liquid handler.\n",
- "Resource deck was assigned to the liquid handler.\n",
- "Resource trash_container was assigned to the liquid handler.\n",
- "Resource tiprack_1 was assigned to the liquid handler.\n",
- "Resource tiprack_4 was assigned to the liquid handler.\n",
- "Resource tiprack_8 was assigned to the liquid handler.\n",
- "Resource tiprack_11 was assigned to the liquid handler.\n",
- "Resource working_plate was assigned to the liquid handler.\n",
- "Resource reagent_stock was assigned to the liquid handler.\n",
- "Resource waste_liq was assigned to the liquid handler.\n"
- ]
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-06-08T15:32:45.234924Z",
+ "start_time": "2025-06-08T15:32:45.194957Z"
}
- ],
+ },
"source": [
+ "\n",
+ "# from pylabrobot.resources import set_volume_tracking\n",
+ "# from pylabrobot.resources import set_tip_tracking\n",
+ "# set_volume_tracking(enabled=True)\n",
+ "# set_tip_tracking(enabled=True)\n",
"# ──────────────────────────────────────\n",
"# User‑configurable constants (µL)\n",
"MEDIUM_VOL = 100 # volume of spent medium to remove\n",
@@ -62,7 +55,7 @@
"\n",
"# ──────────────────────────────────────\n",
"\n",
- "lh = DPLiquidHandler(backend=LiquidHandlerChatterboxBackend(), deck=OTDeck())\n",
+ "lh = LiquidHandler(backend=LiquidHandlerChatterboxBackend(), deck=OTDeck())\n",
"await lh.setup()\n",
"#vis = Visualizer(resource=lh)\n",
"#await vis.setup()\n",
@@ -88,14 +81,36 @@
"# 1‑channel waste reservoir at slot 9\n",
"waste_liq = nest_1_reservoir_195ml(name='waste_liq')\n",
"lh.deck.assign_child_at_slot(waste_liq, slot=9)"
- ]
+ ],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Setting up the liquid handler.\n",
+ "Resource deck was assigned to the liquid handler.\n",
+ "Resource trash_container was assigned to the liquid handler.\n",
+ "Resource tiprack_1 was assigned to the liquid handler.\n",
+ "Resource tiprack_4 was assigned to the liquid handler.\n",
+ "Resource tiprack_8 was assigned to the liquid handler.\n",
+ "Resource tiprack_11 was assigned to the liquid handler.\n",
+ "Resource working_plate was assigned to the liquid handler.\n",
+ "Resource reagent_stock was assigned to the liquid handler.\n",
+ "Resource waste_liq was assigned to the liquid handler.\n"
+ ]
+ }
+ ],
+ "execution_count": 2
},
{
"cell_type": "code",
- "execution_count": 11,
"id": "b5313453",
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-06-08T15:32:45.425953Z",
+ "start_time": "2025-06-08T15:32:45.420965Z"
+ }
+ },
"source": [
"pbs = reagent_stock[0][0]\n",
"lysis = reagent_stock[1][0]\n",
@@ -103,14 +118,19 @@
"waste_liq = waste_liq[0]\n",
"wells_name = [f\"A{i}\" for i in range(1, 13)]\n",
"cells_all = working_plate[wells_name] # A1–A12"
- ]
+ ],
+ "outputs": [],
+ "execution_count": 3
},
{
"cell_type": "code",
- "execution_count": 12,
"id": "e85d6752",
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-06-08T15:32:46.480024Z",
+ "start_time": "2025-06-08T15:32:46.473896Z"
+ }
+ },
"source": [
"working_plate_volumes = [\n",
" ('culture medium', MEDIUM_VOL) if i % 8 == 0 else (None, 0)\n",
@@ -119,14 +139,54 @@
"working_plate.set_well_liquids(working_plate_volumes)\n",
"reagent_info = [('PBS Buffer', 5000), ('Lysis Buffer', 5000), ('Luciferase Reagent', 5000)]+[ (None, 0) ]* 9\n",
"reagent_stock.set_well_liquids(reagent_info)\n",
- "lh.set_tiprack(list(tipracks.values()))"
- ]
+ "# lh.deck.set_tiprack(list(tipracks.values()))"
+ ],
+ "outputs": [],
+ "execution_count": 4
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-06-08T15:32:47.742983Z",
+ "start_time": "2025-06-08T15:32:47.731878Z"
+ }
+ },
+ "cell_type": "code",
+ "source": [
+ "# state = reagent_stock.serialize_all_state()\n",
+ "# print(state)\n",
+ "reagent_stock.load_all_state({'reagent_stock': {}, 'reagent_stock_A1': {'liquids': [['PBS Buffer', 5000]], 'pending_liquids': [], 'liquid_history': []}, 'reagent_stock_A2': {'liquids': [['Lysis Buffer', 5000]], 'pending_liquids': [['Lysis Buffer', 5000]], 'liquid_history': ['Lysis Buffer']}, 'reagent_stock_A3': {'liquids': [['Luciferase Reagent', 5000]], 'pending_liquids': [['Luciferase Reagent', 5000]], 'liquid_history': ['Luciferase Reagent']}, 'reagent_stock_A4': {'liquids': [[None, 0]], 'pending_liquids': [[None, 0]], 'liquid_history': [None]}, 'reagent_stock_A5': {'liquids': [[None, 0]], 'pending_liquids': [[None, 0]], 'liquid_history': [None]}, 'reagent_stock_A6': {'liquids': [[None, 0]], 'pending_liquids': [[None, 0]], 'liquid_history': [None]}, 'reagent_stock_A7': {'liquids': [[None, 0]], 'pending_liquids': [[None, 0]], 'liquid_history': [None]}, 'reagent_stock_A8': {'liquids': [[None, 0]], 'pending_liquids': [[None, 0]], 'liquid_history': [None]}, 'reagent_stock_A9': {'liquids': [[None, 0]], 'pending_liquids': [[None, 0]], 'liquid_history': [None]}, 'reagent_stock_A10': {'liquids': [[None, 0]], 'pending_liquids': [[None, 0]], 'liquid_history': [None]}, 'reagent_stock_A11': {'liquids': [[None, 0]], 'pending_liquids': [[None, 0]], 'liquid_history': [None]}, 'reagent_stock_A12': {'liquids': [[None, 0]], 'pending_liquids': [[None, 0]], 'liquid_history': [None]}})\n",
+ "\n",
+ "reagent_stock[0][0].tracker.liquids"
+ ],
+ "id": "cd6ad8fb6494f14a",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[('PBS Buffer', 5000)]"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 5
},
{
"cell_type": "code",
- "execution_count": 13,
"id": "9dbfb0e2",
- "metadata": {},
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-06-08T15:32:02.047523Z",
+ "start_time": "2025-06-08T15:32:02.042034Z"
+ }
+ },
+ "source": [
+ "from pylabrobot.resources import set_tip_tracking, set_volume_tracking\n",
+ "set_tip_tracking(True), set_volume_tracking(True)"
+ ],
"outputs": [
{
"data": {
@@ -134,185 +194,9106 @@
"(None, None)"
]
},
- "execution_count": 13,
+ "execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
- "source": [
- "from pylabrobot.resources import set_tip_tracking, set_volume_tracking\n",
- "set_tip_tracking(True), set_volume_tracking(True)"
- ]
+ "execution_count": 12
+ },
+ {
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-06-08T16:04:23.597819Z",
+ "start_time": "2025-06-08T16:04:23.427478Z"
+ }
+ },
+ "cell_type": "code",
+ "source": "lh.serialize()",
+ "id": "6b2801f34ac96ef6",
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'name': 'lh_deck',\n",
+ " 'type': 'LiquidHandler',\n",
+ " 'size_x': 624.3,\n",
+ " 'size_y': 565.2,\n",
+ " 'size_z': 900,\n",
+ " 'location': {'x': 0, 'y': 0, 'z': 0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'liquid_handler',\n",
+ " 'model': None,\n",
+ " 'children': [{'name': 'deck',\n",
+ " 'type': 'OTDeck',\n",
+ " 'size_x': 624.3,\n",
+ " 'size_y': 565.2,\n",
+ " 'size_z': 900,\n",
+ " 'location': {'x': 0, 'y': 0, 'z': 0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'deck',\n",
+ " 'children': [{'name': 'trash_container',\n",
+ " 'type': 'Resource',\n",
+ " 'size_x': 172.86,\n",
+ " 'size_y': 165.86,\n",
+ " 'size_z': 82,\n",
+ " 'location': {'x': 265.0, 'y': 271.5, 'z': 0.0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': None,\n",
+ " 'model': None,\n",
+ " 'children': [{'name': 'trash',\n",
+ " 'type': 'Trash',\n",
+ " 'size_x': 172.86,\n",
+ " 'size_y': 165.86,\n",
+ " 'size_z': 82,\n",
+ " 'location': {'x': 0, 'y': 0, 'z': 0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'trash',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'trash_container',\n",
+ " 'max_volume': 'Infinity',\n",
+ " 'material_z_thickness': 0,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None}],\n",
+ " 'parent_name': 'deck'},\n",
+ " {'name': 'tiprack_1',\n",
+ " 'type': 'TipRack',\n",
+ " 'size_x': 127.76,\n",
+ " 'size_y': 85.48,\n",
+ " 'size_z': 64.49,\n",
+ " 'location': {'x': 0.0, 'y': 0.0, 'z': 0.0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_rack',\n",
+ " 'model': 'Opentrons OT-2 96 Tip Rack 300 µL',\n",
+ " 'children': [{'name': 'tiprack_1_A1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 72.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 63.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 54.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 45.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 36.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 27.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 18.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_A12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 72.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_B12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 63.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_C12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 54.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_D12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 45.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_E12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 36.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_F12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 27.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_G12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 18.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_1_H12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_1',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}}],\n",
+ " 'parent_name': 'deck',\n",
+ " 'ordering': ['A1',\n",
+ " 'B1',\n",
+ " 'C1',\n",
+ " 'D1',\n",
+ " 'E1',\n",
+ " 'F1',\n",
+ " 'G1',\n",
+ " 'H1',\n",
+ " 'A2',\n",
+ " 'B2',\n",
+ " 'C2',\n",
+ " 'D2',\n",
+ " 'E2',\n",
+ " 'F2',\n",
+ " 'G2',\n",
+ " 'H2',\n",
+ " 'A3',\n",
+ " 'B3',\n",
+ " 'C3',\n",
+ " 'D3',\n",
+ " 'E3',\n",
+ " 'F3',\n",
+ " 'G3',\n",
+ " 'H3',\n",
+ " 'A4',\n",
+ " 'B4',\n",
+ " 'C4',\n",
+ " 'D4',\n",
+ " 'E4',\n",
+ " 'F4',\n",
+ " 'G4',\n",
+ " 'H4',\n",
+ " 'A5',\n",
+ " 'B5',\n",
+ " 'C5',\n",
+ " 'D5',\n",
+ " 'E5',\n",
+ " 'F5',\n",
+ " 'G5',\n",
+ " 'H5',\n",
+ " 'A6',\n",
+ " 'B6',\n",
+ " 'C6',\n",
+ " 'D6',\n",
+ " 'E6',\n",
+ " 'F6',\n",
+ " 'G6',\n",
+ " 'H6',\n",
+ " 'A7',\n",
+ " 'B7',\n",
+ " 'C7',\n",
+ " 'D7',\n",
+ " 'E7',\n",
+ " 'F7',\n",
+ " 'G7',\n",
+ " 'H7',\n",
+ " 'A8',\n",
+ " 'B8',\n",
+ " 'C8',\n",
+ " 'D8',\n",
+ " 'E8',\n",
+ " 'F8',\n",
+ " 'G8',\n",
+ " 'H8',\n",
+ " 'A9',\n",
+ " 'B9',\n",
+ " 'C9',\n",
+ " 'D9',\n",
+ " 'E9',\n",
+ " 'F9',\n",
+ " 'G9',\n",
+ " 'H9',\n",
+ " 'A10',\n",
+ " 'B10',\n",
+ " 'C10',\n",
+ " 'D10',\n",
+ " 'E10',\n",
+ " 'F10',\n",
+ " 'G10',\n",
+ " 'H10',\n",
+ " 'A11',\n",
+ " 'B11',\n",
+ " 'C11',\n",
+ " 'D11',\n",
+ " 'E11',\n",
+ " 'F11',\n",
+ " 'G11',\n",
+ " 'H11',\n",
+ " 'A12',\n",
+ " 'B12',\n",
+ " 'C12',\n",
+ " 'D12',\n",
+ " 'E12',\n",
+ " 'F12',\n",
+ " 'G12',\n",
+ " 'H12']},\n",
+ " {'name': 'tiprack_4',\n",
+ " 'type': 'TipRack',\n",
+ " 'size_x': 127.76,\n",
+ " 'size_y': 85.48,\n",
+ " 'size_z': 64.49,\n",
+ " 'location': {'x': 0.0, 'y': 90.5, 'z': 0.0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_rack',\n",
+ " 'model': 'Opentrons OT-2 96 Tip Rack 300 µL',\n",
+ " 'children': [{'name': 'tiprack_4_A1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 72.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 63.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 54.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 45.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 36.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 27.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 18.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_A12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 72.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_B12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 63.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_C12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 54.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_D12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 45.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_E12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 36.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_F12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 27.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_G12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 18.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_4_H12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_4',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}}],\n",
+ " 'parent_name': 'deck',\n",
+ " 'ordering': ['A1',\n",
+ " 'B1',\n",
+ " 'C1',\n",
+ " 'D1',\n",
+ " 'E1',\n",
+ " 'F1',\n",
+ " 'G1',\n",
+ " 'H1',\n",
+ " 'A2',\n",
+ " 'B2',\n",
+ " 'C2',\n",
+ " 'D2',\n",
+ " 'E2',\n",
+ " 'F2',\n",
+ " 'G2',\n",
+ " 'H2',\n",
+ " 'A3',\n",
+ " 'B3',\n",
+ " 'C3',\n",
+ " 'D3',\n",
+ " 'E3',\n",
+ " 'F3',\n",
+ " 'G3',\n",
+ " 'H3',\n",
+ " 'A4',\n",
+ " 'B4',\n",
+ " 'C4',\n",
+ " 'D4',\n",
+ " 'E4',\n",
+ " 'F4',\n",
+ " 'G4',\n",
+ " 'H4',\n",
+ " 'A5',\n",
+ " 'B5',\n",
+ " 'C5',\n",
+ " 'D5',\n",
+ " 'E5',\n",
+ " 'F5',\n",
+ " 'G5',\n",
+ " 'H5',\n",
+ " 'A6',\n",
+ " 'B6',\n",
+ " 'C6',\n",
+ " 'D6',\n",
+ " 'E6',\n",
+ " 'F6',\n",
+ " 'G6',\n",
+ " 'H6',\n",
+ " 'A7',\n",
+ " 'B7',\n",
+ " 'C7',\n",
+ " 'D7',\n",
+ " 'E7',\n",
+ " 'F7',\n",
+ " 'G7',\n",
+ " 'H7',\n",
+ " 'A8',\n",
+ " 'B8',\n",
+ " 'C8',\n",
+ " 'D8',\n",
+ " 'E8',\n",
+ " 'F8',\n",
+ " 'G8',\n",
+ " 'H8',\n",
+ " 'A9',\n",
+ " 'B9',\n",
+ " 'C9',\n",
+ " 'D9',\n",
+ " 'E9',\n",
+ " 'F9',\n",
+ " 'G9',\n",
+ " 'H9',\n",
+ " 'A10',\n",
+ " 'B10',\n",
+ " 'C10',\n",
+ " 'D10',\n",
+ " 'E10',\n",
+ " 'F10',\n",
+ " 'G10',\n",
+ " 'H10',\n",
+ " 'A11',\n",
+ " 'B11',\n",
+ " 'C11',\n",
+ " 'D11',\n",
+ " 'E11',\n",
+ " 'F11',\n",
+ " 'G11',\n",
+ " 'H11',\n",
+ " 'A12',\n",
+ " 'B12',\n",
+ " 'C12',\n",
+ " 'D12',\n",
+ " 'E12',\n",
+ " 'F12',\n",
+ " 'G12',\n",
+ " 'H12']},\n",
+ " {'name': 'tiprack_8',\n",
+ " 'type': 'TipRack',\n",
+ " 'size_x': 127.76,\n",
+ " 'size_y': 85.48,\n",
+ " 'size_z': 64.49,\n",
+ " 'location': {'x': 132.5, 'y': 181.0, 'z': 0.0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_rack',\n",
+ " 'model': 'Opentrons OT-2 96 Tip Rack 300 µL',\n",
+ " 'children': [{'name': 'tiprack_8_A1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 72.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 63.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 54.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 45.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 36.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 27.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 18.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_A12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 72.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_B12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 63.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_C12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 54.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_D12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 45.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_E12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 36.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_F12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 27.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_G12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 18.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_8_H12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_8',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}}],\n",
+ " 'parent_name': 'deck',\n",
+ " 'ordering': ['A1',\n",
+ " 'B1',\n",
+ " 'C1',\n",
+ " 'D1',\n",
+ " 'E1',\n",
+ " 'F1',\n",
+ " 'G1',\n",
+ " 'H1',\n",
+ " 'A2',\n",
+ " 'B2',\n",
+ " 'C2',\n",
+ " 'D2',\n",
+ " 'E2',\n",
+ " 'F2',\n",
+ " 'G2',\n",
+ " 'H2',\n",
+ " 'A3',\n",
+ " 'B3',\n",
+ " 'C3',\n",
+ " 'D3',\n",
+ " 'E3',\n",
+ " 'F3',\n",
+ " 'G3',\n",
+ " 'H3',\n",
+ " 'A4',\n",
+ " 'B4',\n",
+ " 'C4',\n",
+ " 'D4',\n",
+ " 'E4',\n",
+ " 'F4',\n",
+ " 'G4',\n",
+ " 'H4',\n",
+ " 'A5',\n",
+ " 'B5',\n",
+ " 'C5',\n",
+ " 'D5',\n",
+ " 'E5',\n",
+ " 'F5',\n",
+ " 'G5',\n",
+ " 'H5',\n",
+ " 'A6',\n",
+ " 'B6',\n",
+ " 'C6',\n",
+ " 'D6',\n",
+ " 'E6',\n",
+ " 'F6',\n",
+ " 'G6',\n",
+ " 'H6',\n",
+ " 'A7',\n",
+ " 'B7',\n",
+ " 'C7',\n",
+ " 'D7',\n",
+ " 'E7',\n",
+ " 'F7',\n",
+ " 'G7',\n",
+ " 'H7',\n",
+ " 'A8',\n",
+ " 'B8',\n",
+ " 'C8',\n",
+ " 'D8',\n",
+ " 'E8',\n",
+ " 'F8',\n",
+ " 'G8',\n",
+ " 'H8',\n",
+ " 'A9',\n",
+ " 'B9',\n",
+ " 'C9',\n",
+ " 'D9',\n",
+ " 'E9',\n",
+ " 'F9',\n",
+ " 'G9',\n",
+ " 'H9',\n",
+ " 'A10',\n",
+ " 'B10',\n",
+ " 'C10',\n",
+ " 'D10',\n",
+ " 'E10',\n",
+ " 'F10',\n",
+ " 'G10',\n",
+ " 'H10',\n",
+ " 'A11',\n",
+ " 'B11',\n",
+ " 'C11',\n",
+ " 'D11',\n",
+ " 'E11',\n",
+ " 'F11',\n",
+ " 'G11',\n",
+ " 'H11',\n",
+ " 'A12',\n",
+ " 'B12',\n",
+ " 'C12',\n",
+ " 'D12',\n",
+ " 'E12',\n",
+ " 'F12',\n",
+ " 'G12',\n",
+ " 'H12']},\n",
+ " {'name': 'tiprack_11',\n",
+ " 'type': 'TipRack',\n",
+ " 'size_x': 127.76,\n",
+ " 'size_y': 85.48,\n",
+ " 'size_z': 64.49,\n",
+ " 'location': {'x': 132.5, 'y': 271.5, 'z': 0.0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_rack',\n",
+ " 'model': 'Opentrons OT-2 96 Tip Rack 300 µL',\n",
+ " 'children': [{'name': 'tiprack_11_A1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H1',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 12.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H2',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 21.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H3',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 30.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H4',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 39.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H5',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 48.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H6',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 57.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H7',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 66.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H8',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 75.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H9',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 84.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 72.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 63.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 54.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 45.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 36.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 27.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 18.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H10',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 93.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 72.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 63.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 54.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 45.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 36.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 27.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531,\n",
+ " 'y': 18.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H11',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 102.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_A12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 72.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_B12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 63.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_C12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 54.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_D12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 45.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_E12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 36.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_F12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 27.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_G12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531,\n",
+ " 'y': 18.391,\n",
+ " 'z': 5.39,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}},\n",
+ " {'name': 'tiprack_11_H12',\n",
+ " 'type': 'TipSpot',\n",
+ " 'size_x': 3.698,\n",
+ " 'size_y': 3.698,\n",
+ " 'size_z': 0,\n",
+ " 'location': {'x': 111.531, 'y': 9.391, 'z': 5.39, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'tip_spot',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'tiprack_11',\n",
+ " 'prototype_tip': {'type': 'Tip',\n",
+ " 'total_tip_length': 59.3,\n",
+ " 'has_filter': False,\n",
+ " 'maximal_volume': 300.0,\n",
+ " 'fitting_depth': 7.47}}],\n",
+ " 'parent_name': 'deck',\n",
+ " 'ordering': ['A1',\n",
+ " 'B1',\n",
+ " 'C1',\n",
+ " 'D1',\n",
+ " 'E1',\n",
+ " 'F1',\n",
+ " 'G1',\n",
+ " 'H1',\n",
+ " 'A2',\n",
+ " 'B2',\n",
+ " 'C2',\n",
+ " 'D2',\n",
+ " 'E2',\n",
+ " 'F2',\n",
+ " 'G2',\n",
+ " 'H2',\n",
+ " 'A3',\n",
+ " 'B3',\n",
+ " 'C3',\n",
+ " 'D3',\n",
+ " 'E3',\n",
+ " 'F3',\n",
+ " 'G3',\n",
+ " 'H3',\n",
+ " 'A4',\n",
+ " 'B4',\n",
+ " 'C4',\n",
+ " 'D4',\n",
+ " 'E4',\n",
+ " 'F4',\n",
+ " 'G4',\n",
+ " 'H4',\n",
+ " 'A5',\n",
+ " 'B5',\n",
+ " 'C5',\n",
+ " 'D5',\n",
+ " 'E5',\n",
+ " 'F5',\n",
+ " 'G5',\n",
+ " 'H5',\n",
+ " 'A6',\n",
+ " 'B6',\n",
+ " 'C6',\n",
+ " 'D6',\n",
+ " 'E6',\n",
+ " 'F6',\n",
+ " 'G6',\n",
+ " 'H6',\n",
+ " 'A7',\n",
+ " 'B7',\n",
+ " 'C7',\n",
+ " 'D7',\n",
+ " 'E7',\n",
+ " 'F7',\n",
+ " 'G7',\n",
+ " 'H7',\n",
+ " 'A8',\n",
+ " 'B8',\n",
+ " 'C8',\n",
+ " 'D8',\n",
+ " 'E8',\n",
+ " 'F8',\n",
+ " 'G8',\n",
+ " 'H8',\n",
+ " 'A9',\n",
+ " 'B9',\n",
+ " 'C9',\n",
+ " 'D9',\n",
+ " 'E9',\n",
+ " 'F9',\n",
+ " 'G9',\n",
+ " 'H9',\n",
+ " 'A10',\n",
+ " 'B10',\n",
+ " 'C10',\n",
+ " 'D10',\n",
+ " 'E10',\n",
+ " 'F10',\n",
+ " 'G10',\n",
+ " 'H10',\n",
+ " 'A11',\n",
+ " 'B11',\n",
+ " 'C11',\n",
+ " 'D11',\n",
+ " 'E11',\n",
+ " 'F11',\n",
+ " 'G11',\n",
+ " 'H11',\n",
+ " 'A12',\n",
+ " 'B12',\n",
+ " 'C12',\n",
+ " 'D12',\n",
+ " 'E12',\n",
+ " 'F12',\n",
+ " 'G12',\n",
+ " 'H12']},\n",
+ " {'name': 'working_plate',\n",
+ " 'type': 'Plate',\n",
+ " 'size_x': 127.76,\n",
+ " 'size_y': 85.47,\n",
+ " 'size_z': 14.22,\n",
+ " 'location': {'x': 265.0, 'y': 90.5, 'z': 0.0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'plate',\n",
+ " 'model': 'Corning 96 Well Plate 360 µL Flat',\n",
+ " 'children': [{'name': 'working_plate_A1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 11.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 11.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 11.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 11.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 11.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 11.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 11.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 11.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A2',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 20.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B2',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 20.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C2',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 20.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D2',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 20.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E2',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 20.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F2',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 20.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G2',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 20.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H2',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 20.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A3',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 29.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B3',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 29.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C3',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 29.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D3',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 29.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E3',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 29.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F3',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 29.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G3',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 29.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H3',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 29.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A4',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 38.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B4',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 38.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C4',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 38.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D4',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 38.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E4',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 38.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F4',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 38.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G4',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 38.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H4',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 38.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A5',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 47.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B5',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 47.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C5',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 47.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D5',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 47.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E5',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 47.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F5',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 47.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G5',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 47.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H5',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 47.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A6',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 56.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B6',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 56.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C6',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 56.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D6',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 56.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E6',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 56.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F6',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 56.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G6',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 56.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H6',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 56.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A7',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 65.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B7',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 65.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C7',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 65.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D7',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 65.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E7',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 65.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F7',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 65.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G7',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 65.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H7',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 65.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A8',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 74.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B8',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 74.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C8',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 74.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D8',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 74.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E8',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 74.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F8',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 74.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G8',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 74.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H8',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 74.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A9',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 83.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B9',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 83.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C9',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 83.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D9',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 83.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E9',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 83.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F9',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 83.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G9',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 83.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H9',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 83.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A10',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 92.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B10',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 92.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C10',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 92.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D10',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 92.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E10',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 92.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F10',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 92.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G10',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 92.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H10',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 92.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A11',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 101.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B11',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 101.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C11',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 101.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D11',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 101.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E11',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 101.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F11',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 101.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G11',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 101.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H11',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 101.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_A12',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 110.9545,\n",
+ " 'y': 71.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_B12',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 110.9545,\n",
+ " 'y': 62.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_C12',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 110.9545,\n",
+ " 'y': 53.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_D12',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 110.9545,\n",
+ " 'y': 44.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_E12',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 110.9545,\n",
+ " 'y': 35.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_F12',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 110.9545,\n",
+ " 'y': 26.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_G12',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 110.9545,\n",
+ " 'y': 17.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'},\n",
+ " {'name': 'working_plate_H12',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 4.851,\n",
+ " 'size_y': 4.851,\n",
+ " 'size_z': 10.67,\n",
+ " 'location': {'x': 110.9545,\n",
+ " 'y': 8.8145,\n",
+ " 'z': 3.55,\n",
+ " 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'working_plate',\n",
+ " 'max_volume': 360,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'circle'}],\n",
+ " 'parent_name': 'deck',\n",
+ " 'ordering': ['A1',\n",
+ " 'B1',\n",
+ " 'C1',\n",
+ " 'D1',\n",
+ " 'E1',\n",
+ " 'F1',\n",
+ " 'G1',\n",
+ " 'H1',\n",
+ " 'A2',\n",
+ " 'B2',\n",
+ " 'C2',\n",
+ " 'D2',\n",
+ " 'E2',\n",
+ " 'F2',\n",
+ " 'G2',\n",
+ " 'H2',\n",
+ " 'A3',\n",
+ " 'B3',\n",
+ " 'C3',\n",
+ " 'D3',\n",
+ " 'E3',\n",
+ " 'F3',\n",
+ " 'G3',\n",
+ " 'H3',\n",
+ " 'A4',\n",
+ " 'B4',\n",
+ " 'C4',\n",
+ " 'D4',\n",
+ " 'E4',\n",
+ " 'F4',\n",
+ " 'G4',\n",
+ " 'H4',\n",
+ " 'A5',\n",
+ " 'B5',\n",
+ " 'C5',\n",
+ " 'D5',\n",
+ " 'E5',\n",
+ " 'F5',\n",
+ " 'G5',\n",
+ " 'H5',\n",
+ " 'A6',\n",
+ " 'B6',\n",
+ " 'C6',\n",
+ " 'D6',\n",
+ " 'E6',\n",
+ " 'F6',\n",
+ " 'G6',\n",
+ " 'H6',\n",
+ " 'A7',\n",
+ " 'B7',\n",
+ " 'C7',\n",
+ " 'D7',\n",
+ " 'E7',\n",
+ " 'F7',\n",
+ " 'G7',\n",
+ " 'H7',\n",
+ " 'A8',\n",
+ " 'B8',\n",
+ " 'C8',\n",
+ " 'D8',\n",
+ " 'E8',\n",
+ " 'F8',\n",
+ " 'G8',\n",
+ " 'H8',\n",
+ " 'A9',\n",
+ " 'B9',\n",
+ " 'C9',\n",
+ " 'D9',\n",
+ " 'E9',\n",
+ " 'F9',\n",
+ " 'G9',\n",
+ " 'H9',\n",
+ " 'A10',\n",
+ " 'B10',\n",
+ " 'C10',\n",
+ " 'D10',\n",
+ " 'E10',\n",
+ " 'F10',\n",
+ " 'G10',\n",
+ " 'H10',\n",
+ " 'A11',\n",
+ " 'B11',\n",
+ " 'C11',\n",
+ " 'D11',\n",
+ " 'E11',\n",
+ " 'F11',\n",
+ " 'G11',\n",
+ " 'H11',\n",
+ " 'A12',\n",
+ " 'B12',\n",
+ " 'C12',\n",
+ " 'D12',\n",
+ " 'E12',\n",
+ " 'F12',\n",
+ " 'G12',\n",
+ " 'H12']},\n",
+ " {'name': 'reagent_stock',\n",
+ " 'type': 'Plate',\n",
+ " 'size_x': 127.76,\n",
+ " 'size_y': 85.48,\n",
+ " 'size_z': 31.4,\n",
+ " 'location': {'x': 265.0, 'y': 0.0, 'z': 0.0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'plate',\n",
+ " 'model': 'NEST 12 Well Reservoir 15 mL',\n",
+ " 'children': [{'name': 'reagent_stock_A1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 10.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A2',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 19.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A3',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 28.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A4',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 37.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A5',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 46.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A6',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 55.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A7',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 64.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A8',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 73.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A9',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 82.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A10',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 91.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A11',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 100.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'},\n",
+ " {'name': 'reagent_stock_A12',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 8.2,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 26.85,\n",
+ " 'location': {'x': 109.28, 'y': 7.18, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'reagent_stock',\n",
+ " 'max_volume': 15000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'}],\n",
+ " 'parent_name': 'deck',\n",
+ " 'ordering': ['A1',\n",
+ " 'A2',\n",
+ " 'A3',\n",
+ " 'A4',\n",
+ " 'A5',\n",
+ " 'A6',\n",
+ " 'A7',\n",
+ " 'A8',\n",
+ " 'A9',\n",
+ " 'A10',\n",
+ " 'A11',\n",
+ " 'A12']},\n",
+ " {'name': 'waste_liq',\n",
+ " 'type': 'Plate',\n",
+ " 'size_x': 127.76,\n",
+ " 'size_y': 85.48,\n",
+ " 'size_z': 31.4,\n",
+ " 'location': {'x': 265.0, 'y': 181.0, 'z': 0.0, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'plate',\n",
+ " 'model': 'NEST 1 Well Reservoir 195 mL',\n",
+ " 'children': [{'name': 'waste_liq_A1',\n",
+ " 'type': 'Well',\n",
+ " 'size_x': 106.8,\n",
+ " 'size_y': 71.2,\n",
+ " 'size_z': 25,\n",
+ " 'location': {'x': 10.48, 'y': 7.14, 'z': 4.55, 'type': 'Coordinate'},\n",
+ " 'rotation': {'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation'},\n",
+ " 'category': 'well',\n",
+ " 'model': None,\n",
+ " 'children': [],\n",
+ " 'parent_name': 'waste_liq',\n",
+ " 'max_volume': 195000,\n",
+ " 'material_z_thickness': None,\n",
+ " 'compute_volume_from_height': None,\n",
+ " 'compute_height_from_volume': None,\n",
+ " 'bottom_type': 'unknown',\n",
+ " 'cross_section_type': 'rectangle'}],\n",
+ " 'parent_name': 'deck',\n",
+ " 'ordering': ['A1']}],\n",
+ " 'parent_name': 'lh_deck'}],\n",
+ " 'parent_name': None,\n",
+ " 'backend': {'type': 'LiquidHandlerChatterboxBackend', 'num_channels': 8}}"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "execution_count": 6
},
{
"cell_type": "code",
- "execution_count": 14,
"id": "70094125",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_A1 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A1 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_B1 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A2 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_C1 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A3 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_D1 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A4 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_E1 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A5 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_F1 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A6 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_G1 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A7 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_H1 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A8 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_A2 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A9 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_B2 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A10 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_C2 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A11 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n",
- "Picking up tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: tiprack_1_D2 0,0,0 Tip 300.0 7.47 59.3 No \n",
- "Aspirating:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 working_plate_A12 -2.5,0,0 0.2 None 0.2 \n",
- "[Well(name=waste_liq_A1, location=Coordinate(010.480, 007.140, 004.550), size_x=106.8, size_y=71.2, size_z=25, category=well)]\n",
- "Dispensing:\n",
- "pip# vol(ul) resource offset flow rate blowout lld_z \n",
- " p0: 100.0 waste_liq_A1 0,0,-5 3.0 None 0.0 \n",
- "Dropping tips:\n",
- "pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter \n",
- " p0: trash 0,0.0,0 Tip 300.0 7.47 59.3 No \n"
- ]
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2025-06-08T14:25:19.507693Z",
+ "start_time": "2025-06-08T14:25:18.487272Z"
}
- ],
+ },
"source": [
"await lh.remove_liquid(\n",
" vols=[MEDIUM_VOL]*12,\n",
@@ -323,7 +9304,21 @@
" flow_rates=[0.2,3],\n",
" offsets=[Coordinate(-2.5, 0, 0),Coordinate(0, 0, -5)]\n",
")"
- ]
+ ],
+ "outputs": [
+ {
+ "ename": "AttributeError",
+ "evalue": "'LiquidHandler' object has no attribute 'remove_liquid'",
+ "output_type": "error",
+ "traceback": [
+ "\u001B[31m---------------------------------------------------------------------------\u001B[39m",
+ "\u001B[31mAttributeError\u001B[39m Traceback (most recent call last)",
+ "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[6]\u001B[39m\u001B[32m, line 1\u001B[39m\n\u001B[32m----> \u001B[39m\u001B[32m1\u001B[39m \u001B[38;5;28;01mawait\u001B[39;00m \u001B[43mlh\u001B[49m\u001B[43m.\u001B[49m\u001B[43mremove_liquid\u001B[49m(\n\u001B[32m 2\u001B[39m vols=[MEDIUM_VOL]*\u001B[32m12\u001B[39m,\n\u001B[32m 3\u001B[39m sources=cells_all,\n\u001B[32m 4\u001B[39m waste_liquid=waste_liq,\n\u001B[32m 5\u001B[39m top=[-\u001B[32m0.2\u001B[39m],\n\u001B[32m 6\u001B[39m liquid_height=[\u001B[32m0.2\u001B[39m,\u001B[32m0\u001B[39m],\n\u001B[32m 7\u001B[39m flow_rates=[\u001B[32m0.2\u001B[39m,\u001B[32m3\u001B[39m],\n\u001B[32m 8\u001B[39m offsets=[Coordinate(-\u001B[32m2.5\u001B[39m, \u001B[32m0\u001B[39m, \u001B[32m0\u001B[39m),Coordinate(\u001B[32m0\u001B[39m, \u001B[32m0\u001B[39m, -\u001B[32m5\u001B[39m)]\n\u001B[32m 9\u001B[39m )\n",
+ "\u001B[31mAttributeError\u001B[39m: 'LiquidHandler' object has no attribute 'remove_liquid'"
+ ]
+ }
+ ],
+ "execution_count": 6
},
{
"cell_type": "code",
diff --git a/unilabos/devices/liquid_handling/liquid_handler_abstract.py b/unilabos/devices/liquid_handling/liquid_handler_abstract.py
index c349403..4faa042 100644
--- a/unilabos/devices/liquid_handling/liquid_handler_abstract.py
+++ b/unilabos/devices/liquid_handling/liquid_handler_abstract.py
@@ -6,13 +6,8 @@ import asyncio
import time
from pylabrobot.liquid_handling import LiquidHandler
-from pylabrobot.resources import (
- Resource,
- TipRack,
- Container,
- Coordinate,
- Well
-)
+from pylabrobot.resources import Resource, TipRack, Container, Coordinate, Well
+
class LiquidHandlerAbstract(LiquidHandler):
"""Extended LiquidHandler with additional operations."""
@@ -21,6 +16,19 @@ class LiquidHandlerAbstract(LiquidHandler):
# REMOVE LIQUID --------------------------------------------------
# ---------------------------------------------------------------
+ async def create_protocol(
+ self,
+ protocol_name: str,
+ protocol_description: str,
+ protocol_version: str,
+ protocol_author: str,
+ protocol_date: str,
+ protocol_type: str,
+ none_keys: List[str] = [],
+ ):
+ """Create a new protocol with the given metadata."""
+ pass
+
async def remove_liquid(
self,
vols: List[float],
@@ -35,26 +43,26 @@ class LiquidHandlerAbstract(LiquidHandler):
spread: Optional[Literal["wide", "tight", "custom"]] = "wide",
delays: Optional[List[int]] = None,
is_96_well: Optional[bool] = False,
- top: Optional[List(float)] = None,
- none_keys: List[str] = []
+ top: Optional[List[float]] = None,
+ none_keys: List[str] = [],
):
"""A complete *remove* (aspirate → waste) operation."""
trash = self.deck.get_trash_area()
try:
if is_96_well:
- pass # This mode is not verified
+ pass # This mode is not verified
else:
if len(vols) != len(sources):
raise ValueError("Length of `vols` must match `sources`.")
for src, vol in zip(sources, vols):
- self.move_to(src, dis_to_top=top[0] if top else 0)
+ await self.move_to(src, dis_to_top=top[0] if top else 0)
tip = next(self.current_tip)
await self.pick_up_tips(tip)
await self.aspirate(
resources=[src],
vols=[vol],
- use_channels=use_channels, # only aspirate96 used, default to None
+ use_channels=use_channels, # only aspirate96 used, default to None
flow_rates=[flow_rates[0]] if flow_rates else None,
offsets=[offsets[0]] if offsets else None,
liquid_height=[liquid_height[0]] if liquid_height else None,
@@ -64,15 +72,15 @@ class LiquidHandlerAbstract(LiquidHandler):
await self.custom_delay(seconds=delays[0] if delays else 0)
await self.dispense(
resources=waste_liquid,
- vols=[vol],
- use_channels=use_channels,
- flow_rates=[flow_rates[1]] if flow_rates else None,
- offsets=[offsets[1]] if offsets else None,
- liquid_height=[liquid_height[1]] if liquid_height else None,
- blow_out_air_volume=blow_out_air_volume[1] if blow_out_air_volume else None,
- spread=spread,
- )
- await self.discard_tips() # For now, each of tips is discarded after use
+ vols=[vol],
+ use_channels=use_channels,
+ flow_rates=[flow_rates[1]] if flow_rates else None,
+ offsets=[offsets[1]] if offsets else None,
+ liquid_height=[liquid_height[1]] if liquid_height else None,
+ blow_out_air_volume=blow_out_air_volume[1] if blow_out_air_volume else None,
+ spread=spread,
+ )
+ await self.discard_tips() # For now, each of tips is discarded after use
except Exception as e:
raise RuntimeError(f"Liquid removal failed: {e}") from e
@@ -100,13 +108,13 @@ class LiquidHandlerAbstract(LiquidHandler):
mix_vol: Optional[int] = None,
mix_rate: Optional[int] = None,
mix_liquid_height: Optional[float] = None,
- none_keys: List[str] = []
+ none_keys: List[str] = [],
):
"""A complete *add* (aspirate reagent → dispense into targets) operation."""
try:
if is_96_well:
- pass # This mode is not verified.
+ pass # This mode is not verified.
else:
if len(asp_vols) != len(targets):
raise ValueError("Length of `vols` must match `targets`.")
@@ -122,7 +130,7 @@ class LiquidHandlerAbstract(LiquidHandler):
offsets=[offsets[0]] if offsets else None,
liquid_height=[liquid_height[0]] if liquid_height else None,
blow_out_air_volume=[blow_out_air_volume[0]] if blow_out_air_volume else None,
- spread=spread
+ spread=spread,
)
if delays is not None:
await self.custom_delay(seconds=delays[0])
@@ -144,7 +152,8 @@ class LiquidHandlerAbstract(LiquidHandler):
mix_vol=mix_vol,
offsets=offsets if offsets else None,
height_to_bottom=mix_liquid_height if mix_liquid_height else None,
- mix_rate=mix_rate if mix_rate else None)
+ mix_rate=mix_rate if mix_rate else None,
+ )
if delays is not None:
await self.custom_delay(seconds=delays[1])
await self.touch_tip(targets[_])
@@ -158,13 +167,13 @@ class LiquidHandlerAbstract(LiquidHandler):
# ---------------------------------------------------------------
async def transfer_liquid(
self,
- asp_vols: Union[List[float], float],
- dis_vols: Union[List[float], float],
sources: Sequence[Container],
targets: Sequence[Container],
tip_racks: Sequence[TipRack],
*,
use_channels: Optional[List[int]] = None,
+ asp_vols: Union[List[float], float],
+ dis_vols: Union[List[float], float],
asp_flow_rates: Optional[List[Optional[float]]] = None,
dis_flow_rates: Optional[List[Optional[float]]] = None,
offsets: Optional[List[Coordinate]] = None,
@@ -179,7 +188,7 @@ class LiquidHandlerAbstract(LiquidHandler):
mix_rate: Optional[int] = None,
mix_liquid_height: Optional[float] = None,
delays: Optional[List[int]] = None,
- none_keys: List[str] = []
+ none_keys: List[str] = [],
):
"""Transfer liquid from each *source* well/plate to the corresponding *target*.
@@ -201,14 +210,15 @@ class LiquidHandlerAbstract(LiquidHandler):
# 96‑channel head mode
# ------------------------------------------------------------------
if is_96_well:
- pass # This mode is not verified
+ pass # This mode is not verified
else:
if not (len(asp_vols) == len(sources) and len(dis_vols) == len(targets)):
raise ValueError("`sources`, `targets`, and `vols` must have the same length.")
tip_iter = self.iter_tips(tip_racks)
- for src, tgt, asp_vol, asp_flow_rate, dis_vol, dis_flow_rate in (
- zip(sources, targets, asp_vols, asp_flow_rates, dis_vols, dis_flow_rates)):
+ for src, tgt, asp_vol, asp_flow_rate, dis_vol, dis_flow_rate in zip(
+ sources, targets, asp_vols, asp_flow_rates, dis_vols, dis_flow_rates
+ ):
tip = next(tip_iter)
await self.pick_up_tips(tip)
# Aspirate from source
@@ -247,9 +257,9 @@ class LiquidHandlerAbstract(LiquidHandler):
except Exception as exc:
raise RuntimeError(f"Liquid transfer failed: {exc}") from exc
-# ---------------------------------------------------------------
-# Helper utilities
-# ---------------------------------------------------------------
+ # ---------------------------------------------------------------
+ # Helper utilities
+ # ---------------------------------------------------------------
async def custom_delay(self, seconds=0, msg=None):
"""
@@ -266,28 +276,26 @@ class LiquidHandlerAbstract(LiquidHandler):
print(f"Done: {msg}")
print(f"Current time: {time.strftime('%H:%M:%S')}")
- async def touch_tip(self,
- targets: Sequence[Container],
- ):
+ async def touch_tip(self, targets: Sequence[Container]):
"""Touch the tip to the side of the well."""
await self.aspirate(
resources=[targets],
vols=[0],
use_channels=None,
flow_rates=None,
- offsets=[Coordinate(x=-targets.get_size_x()/2,y=0,z=0)],
+ offsets=[Coordinate(x=-targets.get_size_x() / 2, y=0, z=0)],
liquid_height=None,
- blow_out_air_volume=None
+ blow_out_air_volume=None,
)
- #await self.custom_delay(seconds=1) # In the simulation, we do not need to wait
+ # await self.custom_delay(seconds=1) # In the simulation, we do not need to wait
await self.aspirate(
resources=[targets],
vols=[0],
use_channels=None,
flow_rates=None,
- offsets=[Coordinate(x=targets.get_size_x()/2,y=0,z=0)],
+ offsets=[Coordinate(x=targets.get_size_x() / 2, y=0, z=0)],
liquid_height=None,
- blow_out_air_volume=None
+ blow_out_air_volume=None,
)
async def mix(
@@ -298,9 +306,9 @@ class LiquidHandlerAbstract(LiquidHandler):
height_to_bottom: Optional[float] = None,
offsets: Optional[Coordinate] = None,
mix_rate: Optional[float] = None,
- none_keys: List[str] = []
+ none_keys: List[str] = [],
):
- if mix_time is None: # No mixing required
+ if mix_time is None: # No mixing required
return
"""Mix the liquid in the target wells."""
for _ in range(mix_time):
@@ -333,7 +341,7 @@ class LiquidHandlerAbstract(LiquidHandler):
tip_iter = self.iter_tips(tip_racks)
self.current_tip = tip_iter
- async def move_to(self, well: Well, dis_to_top: float = 0 , channel: int = 0):
+ async def move_to(self, well: Well, dis_to_top: float = 0, channel: int = 0):
"""
Move a single channel to a specific well with a given z-height.
@@ -352,4 +360,3 @@ class LiquidHandlerAbstract(LiquidHandler):
await self.move_channel_x(channel, abs_loc.x)
await self.move_channel_y(channel, abs_loc.y)
await self.move_channel_z(channel, abs_loc.z + well_height + dis_to_top)
-
diff --git a/unilabos/devices/liquid_handling/test liquid handler/convert_biomek.py b/unilabos/devices/liquid_handling/test liquid handler/convert_biomek.py
new file mode 100644
index 0000000..712fdd9
--- /dev/null
+++ b/unilabos/devices/liquid_handling/test liquid handler/convert_biomek.py
@@ -0,0 +1,154 @@
+
+import json
+from typing import Sequence, Optional, List, Union, Literal
+json_path = "/Users/guangxinzhang/Documents/Deep Potential/opentrons/convert/protocols/enriched_steps/sci-lucif-assay4.json"
+
+with open(json_path, "r") as f:
+ data = json.load(f)
+
+transfer_example = data[0]
+#print(transfer_example)
+
+
+temp_protocol = []
+TipLocation = "BC1025F" # Assuming this is a fixed tip location for the transfer
+sources = transfer_example["sources"] # Assuming sources is a list of Container objects
+targets = transfer_example["targets"] # Assuming targets is a list of Container objects
+tip_racks = transfer_example["tip_racks"] # Assuming tip_racks is a list of TipRack objects
+asp_vols = transfer_example["asp_vols"] # Assuming asp_vols is a list of volumes
+solvent = "PBS"
+
+def transfer_liquid(
+ #self,
+ sources,#: Sequence[Container],
+ targets,#: Sequence[Container],
+ tip_racks,#: Sequence[TipRack],
+ TipLocation,
+ # *,
+ # use_channels: Optional[List[int]] = None,
+ asp_vols: Union[List[float], float],
+ solvent: Optional[str] = None,
+ # dis_vols: Union[List[float], float],
+ # asp_flow_rates: Optional[List[Optional[float]]] = None,
+ # dis_flow_rates: Optional[List[Optional[float]]] = None,
+ # offsets,#: Optional[List[]] = None,
+ # touch_tip: bool = False,
+ # liquid_height: Optional[List[Optional[float]]] = None,
+ # blow_out_air_volume: Optional[List[Optional[float]]] = None,
+ # spread: Literal["wide", "tight", "custom"] = "wide",
+ # is_96_well: bool = False,
+ # mix_stage: Optional[Literal["none", "before", "after", "both"]] = "none",
+ # mix_times,#: Optional[list() = None,
+ # mix_vol: Optional[int] = None,
+ # mix_rate: Optional[int] = None,
+ # mix_liquid_height: Optional[float] = None,
+ # delays: Optional[List[int]] = None,
+ # none_keys: List[str] = []
+ ):
+ # -------- Build Biomek transfer step --------
+ # 1) Construct default parameter scaffold (values mirror Biomek “Transfer” block).
+
+ transfer_params = {
+ "Span8": False,
+ "Pod": "Pod1",
+ "items": {}, # to be filled below
+ "Wash": False,
+ "Dynamic?": True,
+ "AutoSelectActiveWashTechnique": False,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": False,
+ "ChangeTipsBetweenSources": False,
+ "DefaultCaption": "", # filled after we know first pair/vol
+ "UseExpression": False,
+ "LeaveTipsOn": False,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": False,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": False,
+ "ShowTransferDetails": True,
+ "Solvent": "Water",
+ "Span8Wash": False,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": False,
+ "SplitVolumeCleaning": False,
+ "Stop": "Destinations",
+ "TipLocation": "BC1025F",
+ "UseCurrentTips": False,
+ "UseDisposableTips": True,
+ "UseFixedTips": False,
+ "UseJIT": True,
+ "UseMandrelSelection": True,
+ "UseProbes": [True, True, True, True, True, True, True, True],
+ "WashCycles": "1",
+ "WashVolume": "110%",
+ "Wizard": False
+ }
+
+ items: dict = {}
+ for idx, (src, dst) in enumerate(zip(sources, targets)):
+ items[str(idx)] = {
+ "Source": str(src),
+ "Destination": str(dst),
+ "Volume": asp_vols[idx]
+ }
+ transfer_params["items"] = items
+ transfer_params["Solvent"] = solvent if solvent else "Water"
+ transfer_params["TipLocation"] = TipLocation
+
+ if len(tip_racks) == 1:
+ transfer_params['UseCurrentTips'] = True
+ elif len(tip_racks) > 1:
+ transfer_params["ChangeTipsBetweenDests"] = True
+
+ return transfer_params
+
+action = transfer_liquid(sources=sources,targets=targets,tip_racks=tip_racks, asp_vols=asp_vols,solvent = solvent, TipLocation=TipLocation)
+print(json.dumps(action,indent=2))
+# print(action)
+
+
+
+
+"""
+ "transfer": {
+
+ "items": {},
+ "Wash": false,
+ "Dynamic?": true,
+ "AutoSelectActiveWashTechnique": false,
+ "ActiveWashTechnique": "",
+ "ChangeTipsBetweenDests": true,
+ "ChangeTipsBetweenSources": false,
+ "DefaultCaption": "Transfer 100 µL from P13 to P3",
+ "UseExpression": false,
+ "LeaveTipsOn": false,
+ "MandrelExpression": "",
+ "Repeats": "1",
+ "RepeatsByVolume": false,
+ "Replicates": "1",
+ "ShowTipHandlingDetails": true,
+ "ShowTransferDetails": true,
+
+ "Span8Wash": false,
+ "Span8WashVolume": "2",
+ "Span8WasteVolume": "1",
+ "SplitVolume": false,
+ "SplitVolumeCleaning": false,
+ "Stop": "Destinations",
+ "TipLocation": "BC1025F",
+ "UseCurrentTips": false,
+ "UseDisposableTips": false,
+ "UseFixedTips": false,
+ "UseJIT": true,
+ "UseMandrelSelection": true,
+ "UseProbes": [true, true, true, true, true, true, true, true],
+ "WashCycles": "3",
+ "WashVolume": "110%",
+ "Wizard": false
+"""
+
+
+
+
diff --git a/unilabos/devices/liquid_handling/test liquid handler/sci-lucif-assay4.json b/unilabos/devices/liquid_handling/test liquid handler/sci-lucif-assay4.json
new file mode 100644
index 0000000..012a160
--- /dev/null
+++ b/unilabos/devices/liquid_handling/test liquid handler/sci-lucif-assay4.json
@@ -0,0 +1,4033 @@
+[
+ {
+ "template": "transfer",
+ "sources": [
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ }
+ ],
+ "targets": [
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ }
+ ],
+ "tip_racks": [
+ {
+ "well": "A1",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A2",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A3",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A4",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A5",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A6",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A7",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A8",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A9",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A10",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A11",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ },
+ {
+ "well": "A12",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 8
+ }
+ ],
+ "use_channels": null,
+ "asp_vols": [
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0
+ ],
+ "asp_flow_rates": [
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8
+ ],
+ "disp_vols": [
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0,
+ 120.0
+ ],
+ "dis_flow_rates": [
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0
+ ],
+ "offsets": null,
+ "touch_tip": false,
+ "liquid_height": null,
+ "blow_out_air_volume": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "is_96_well": false,
+ "mix_stage": "none",
+ "mix_times": 0,
+ "mix_vol": null,
+ "mix_rate": null,
+ "mix_liquid_height": null,
+ "delays": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ ],
+ "top": [
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5
+ ],
+ "bottom": [
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null
+ ],
+ "move": [
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null
+ ],
+ "center": [
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false
+ ],
+ "move_to": [
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ }
+ ],
+ "mix_detail": [
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ }
+ ]
+ },
+ {
+ "template": "transfer",
+ "sources": [
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "reagent stock",
+ "slot": 3
+ }
+ ],
+ "targets": [
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ }
+ ],
+ "tip_racks": [
+ {
+ "well": "A1",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ }
+ ],
+ "use_channels": null,
+ "asp_vols": [
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0
+ ],
+ "asp_flow_rates": [
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0
+ ],
+ "disp_vols": [
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0,
+ 70.0
+ ],
+ "dis_flow_rates": [
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2
+ ],
+ "offsets": null,
+ "touch_tip": true,
+ "liquid_height": null,
+ "blow_out_air_volume": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "is_96_well": false,
+ "mix_stage": "none",
+ "mix_times": 0,
+ "mix_vol": null,
+ "mix_rate": null,
+ "mix_liquid_height": null,
+ "delays": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ ],
+ "top": [
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2,
+ null,
+ -2
+ ],
+ "bottom": [
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null
+ ],
+ "move": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ ],
+ "center": [
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false
+ ],
+ "move_to": [
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ }
+ ],
+ "mix_detail": [
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ }
+ ]
+ },
+ {
+ "template": "transfer",
+ "sources": [
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ }
+ ],
+ "targets": [
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ },
+ {
+ "well": "A1",
+ "labware": "waste",
+ "slot": 9
+ }
+ ],
+ "tip_racks": [
+ {
+ "well": "A2",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A3",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A4",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A5",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A6",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A7",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A8",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A9",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A10",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A11",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A12",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 11
+ },
+ {
+ "well": "A1",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ }
+ ],
+ "use_channels": null,
+ "asp_vols": [
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0
+ ],
+ "asp_flow_rates": [
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8,
+ 18.8
+ ],
+ "disp_vols": [
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0
+ ],
+ "dis_flow_rates": [
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0
+ ],
+ "offsets": null,
+ "touch_tip": false,
+ "liquid_height": null,
+ "blow_out_air_volume": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "is_96_well": false,
+ "mix_stage": "none",
+ "mix_times": 0,
+ "mix_vol": null,
+ "mix_rate": null,
+ "mix_liquid_height": null,
+ "delays": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ ],
+ "top": [
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5,
+ null,
+ -5
+ ],
+ "bottom": [
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null,
+ 0.2,
+ null
+ ],
+ "move": [
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null,
+ [
+ -2.5,
+ 0.0,
+ 0.0
+ ],
+ null
+ ],
+ "center": [
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false
+ ],
+ "move_to": [
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ -0.2
+ ],
+ "bottom": [
+ null
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ }
+ ],
+ "mix_detail": [
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ }
+ ]
+ },
+ {
+ "template": "transfer",
+ "sources": [
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "reagent stock",
+ "slot": 3
+ }
+ ],
+ "targets": [
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ }
+ ],
+ "tip_racks": [
+ {
+ "well": "A2",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ }
+ ],
+ "use_channels": null,
+ "asp_vols": [
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0
+ ],
+ "asp_flow_rates": [
+ 47.0,
+ 47.0,
+ 47.0,
+ 47.0,
+ 47.0,
+ 47.0,
+ 47.0,
+ 47.0,
+ 47.0,
+ 47.0,
+ 47.0,
+ 47.0
+ ],
+ "disp_vols": [
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0,
+ 30.0
+ ],
+ "dis_flow_rates": [
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2,
+ 28.2
+ ],
+ "offsets": null,
+ "touch_tip": true,
+ "liquid_height": null,
+ "blow_out_air_volume": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "is_96_well": false,
+ "mix_stage": "none",
+ "mix_times": 0,
+ "mix_vol": null,
+ "mix_rate": null,
+ "mix_liquid_height": null,
+ "delays": [
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 0
+ ],
+ "top": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ ],
+ "bottom": [
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5,
+ 0.5,
+ 5
+ ],
+ "move": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ ],
+ "center": [
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false
+ ],
+ "move_to": [
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ }
+ ],
+ "mix_detail": [
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ }
+ ]
+ },
+ {
+ "template": "transfer",
+ "sources": [
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "reagent stock",
+ "slot": 3
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ }
+ ],
+ "targets": [
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A1",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A2",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A3",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A4",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A5",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A6",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A7",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A8",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A9",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A10",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A11",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ },
+ {
+ "well": "A12",
+ "labware": "working plate",
+ "slot": 6
+ }
+ ],
+ "tip_racks": [
+ {
+ "well": "A3",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A4",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A5",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A6",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A7",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A8",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A9",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A10",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A11",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A12",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 1
+ },
+ {
+ "well": "A1",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 4
+ },
+ {
+ "well": "A2",
+ "type": "Opentrons OT-2 96 Tip Rack 300 \u00b5L",
+ "slot": 4
+ }
+ ],
+ "use_channels": null,
+ "asp_vols": [
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0
+ ],
+ "asp_flow_rates": [
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0
+ ],
+ "disp_vols": [
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0,
+ 75.0
+ ],
+ "dis_flow_rates": [
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0,
+ 282.0
+ ],
+ "offsets": null,
+ "touch_tip": true,
+ "liquid_height": null,
+ "blow_out_air_volume": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "is_96_well": false,
+ "mix_stage": "after",
+ "mix_times": [
+ 3
+ ],
+ "mix_vol": 75.0,
+ "mix_rate": null,
+ "mix_liquid_height": null,
+ "delays": [
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2
+ ],
+ "top": [
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5,
+ null,
+ -0.5
+ ],
+ "bottom": [
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null,
+ 0.5,
+ null
+ ],
+ "move": [
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ ],
+ "center": [
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false
+ ],
+ "move_to": [
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ }
+ ],
+ "mix_detail": [
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ },
+ {
+ "top": [],
+ "bottom": [],
+ "move": [],
+ "center": []
+ },
+ {
+ "top": [
+ null
+ ],
+ "bottom": [
+ 0.5
+ ],
+ "move": [
+ null
+ ],
+ "center": [
+ false
+ ]
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/unilabos/devices/pump_and_valve/solenoid_valve_mock.py b/unilabos/devices/pump_and_valve/solenoid_valve_mock.py
index 08820ca..b6735a3 100644
--- a/unilabos/devices/pump_and_valve/solenoid_valve_mock.py
+++ b/unilabos/devices/pump_and_valve/solenoid_valve_mock.py
@@ -5,22 +5,22 @@ class SolenoidValveMock:
def __init__(self, port: str = "COM6"):
self._status = "Idle"
self._valve_position = "OPEN"
-
+
@property
def status(self) -> str:
return self._status
-
+
@property
def valve_position(self) -> str:
return self._valve_position
def get_valve_position(self) -> str:
return self._valve_position
-
+
def set_valve_position(self, position):
self._status = "Busy"
time.sleep(5)
-
+
self._valve_position = position
time.sleep(5)
self._status = "Idle"
diff --git a/unilabos/devices/pump_and_valve/vacuum_pump_mock.py b/unilabos/devices/pump_and_valve/vacuum_pump_mock.py
index 13a0956..3565512 100644
--- a/unilabos/devices/pump_and_valve/vacuum_pump_mock.py
+++ b/unilabos/devices/pump_and_valve/vacuum_pump_mock.py
@@ -4,17 +4,15 @@ import time
class VacuumPumpMock:
def __init__(self, port: str = "COM6"):
self._status = "OPEN"
-
+
@property
def status(self) -> str:
return self._status
def get_status(self) -> str:
return self._status
-
+
def set_status(self, string):
- time.sleep(5)
-
self._status = string
time.sleep(5)
diff --git a/unilabos/devices/resource_container/__init__.py b/unilabos/devices/resource_container/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/unilabos/devices/resource_container/container.py b/unilabos/devices/resource_container/container.py
new file mode 100644
index 0000000..38b9a80
--- /dev/null
+++ b/unilabos/devices/resource_container/container.py
@@ -0,0 +1,9 @@
+
+class HotelContainer:
+ def __init__(self, rotation: dict, device_config: dict):
+ self.rotation = rotation
+ self.device_config = device_config
+ self.status = 'idle'
+
+ def get_rotation(self):
+ return self.rotation
diff --git a/unilabos/devices/ros_dev/lh_joint_config.json b/unilabos/devices/ros_dev/lh_joint_config.json
new file mode 100644
index 0000000..908cc54
--- /dev/null
+++ b/unilabos/devices/ros_dev/lh_joint_config.json
@@ -0,0 +1,38 @@
+{
+ "OTDeck":{
+ "joint_names":[
+ "first_joint",
+ "second_joint",
+ "third_joint",
+ "fourth_joint"
+ ],
+ "link_names":[
+ "first_link",
+ "second_link",
+ "third_link",
+ "fourth_link"
+ ],
+ "y":{
+ "first_joint":{
+ "factor":-0.001,
+ "offset":0.166
+ }
+ },
+ "x":{
+ "second_joint":{
+ "factor":-0.001,
+ "offset":0.1775
+ }
+ },
+ "z":{
+ "third_joint":{
+ "factor":0.001,
+ "offset":0.0
+ },
+ "fourth_joint":{
+ "factor":0.001,
+ "offset":0.0
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/unilabos/devices/ros_dev/liquid_handler_joint_publisher.py b/unilabos/devices/ros_dev/liquid_handler_joint_publisher.py
index e593f42..882b519 100644
--- a/unilabos/devices/ros_dev/liquid_handler_joint_publisher.py
+++ b/unilabos/devices/ros_dev/liquid_handler_joint_publisher.py
@@ -1,9 +1,12 @@
+import asyncio
import copy
+from pathlib import Path
+import threading
import rclpy
import json
import time
from rclpy.executors import MultiThreadedExecutor
-from rclpy.action import ActionServer
+from rclpy.action import ActionServer,ActionClient
from sensor_msgs.msg import JointState
from unilabos_msgs.action import SendCmd
from rclpy.action.server import ServerGoalHandle
@@ -11,9 +14,11 @@ from unilabos.ros.nodes.base_device_node import BaseROS2DeviceNode
from tf_transformations import quaternion_from_euler
from tf2_ros import TransformBroadcaster, Buffer, TransformListener
+from rclpy.node import Node
+import re
class LiquidHandlerJointPublisher(BaseROS2DeviceNode):
- def __init__(self,device_id:str, joint_config:dict, lh_id:str,resource_tracker, rate=50):
+ def __init__(self,resources_config:list, resource_tracker, rate=50, device_id:str = "lh_joint_publisher"):
super().__init__(
driver_instance=self,
device_id=device_id,
@@ -23,60 +28,118 @@ class LiquidHandlerJointPublisher(BaseROS2DeviceNode):
print_publish=False,
resource_tracker=resource_tracker,
)
-
- # joint_config_dict = {
- # "joint_names":[
- # "first_joint",
- # "second_joint",
- # "third_joint",
- # "fourth_joint"
- # ],
- # "y":{
- # "first_joint":{
- # "factor":-1,
- # "offset":0.0
- # }
- # },
- # "x":{
- # "second_joint":{
- # "factor":-1,
- # "offset":0.0
- # }
- # },
- # "z":{
- # "third_joint":{
- # "factor":1,
- # "offset":0.0
- # },
- # "fourth_joint":{
- # "factor":1,
- # "offset":0.0
- # }
- # }
- # }
-
+
+ # 初始化参数
self.j_msg = JointState()
- self.lh_id = lh_id
- # self.j_msg.name = joint_names
- self.joint_config = joint_config
- self.j_msg.position = [0.0 for i in range(len(joint_config['joint_names']))]
- self.j_msg.name = [f"{self.lh_id}_{x}" for x in joint_config['joint_names']]
- # self.joint_config = joint_config_dict
- # self.j_msg.position = [0.0 for i in range(len(joint_config_dict['joint_names']))]
- # self.j_msg.name = [f"{self.lh_id}_{x}" for x in joint_config_dict['joint_names']]
+ joint_config = json.load(open(f"{Path(__file__).parent.absolute()}/lh_joint_config.json", encoding="utf-8"))
+ self.resources_config = {x['id']:x for x in resources_config}
self.rate = rate
self.tf_buffer = Buffer()
self.tf_listener = TransformListener(self.tf_buffer, self)
self.j_pub = self.create_publisher(JointState,'/joint_states',10)
- self.create_timer(0.02,self.lh_joint_pub_callback)
+ self.create_timer(1,self.lh_joint_pub_callback)
+
+
+ self.resource_action = None
+
+ while self.resource_action is None:
+ self.resource_action = self.check_tf_update_actions()
+ time.sleep(1)
+
+ self.resource_action_client = ActionClient(self, SendCmd, self.resource_action)
+ while not self.resource_action_client.wait_for_server(timeout_sec=1.0):
+ self.get_logger().info('等待 TfUpdate 服务器...')
+
+ self.deck_list = []
+ self.lh_devices = {}
+ # 初始化设备ID与config信息
+ for resource in resources_config:
+ if resource['class'] == 'liquid_handler':
+ deck_id = resource['config']['data']['children'][0]['_resource_child_name']
+ deck_class = resource['config']['data']['children'][0]['_resource_type'].split(':')[-1]
+ key = f'{deck_id}'
+ # key = f'{resource["id"]}_{deck_id}'
+ self.lh_devices[key] = {
+ 'joint_msg':JointState(
+ name=[f'{key}_{x}' for x in joint_config[deck_class]['joint_names']],
+ position=[0.0 for _ in joint_config[deck_class]['joint_names']]
+ ),
+ 'joint_config':joint_config[deck_class]
+ }
+ self.deck_list.append(deck_id)
+
+ print('='*20)
+ print(self.lh_devices)
+ print('='*20)
self.j_action = ActionServer(
self,
SendCmd,
- "joint",
+ "hl_joint_action",
self.lh_joint_action_callback,
result_timeout=5000
)
+
+ def check_tf_update_actions(self):
+ topics = self.get_topic_names_and_types()
+
+
+ for topic_item in topics:
+
+ topic_name, topic_types = topic_item
+
+ if 'action_msgs/msg/GoalStatusArray' in topic_types:
+ # 删除 /_action/status 部分
+
+ base_name = topic_name.replace('/_action/status', '')
+ # 检查最后一个部分是否为 tf_update
+ parts = base_name.split('/')
+ if parts and parts[-1] == 'tf_update':
+ return base_name
+
+ return None
+
+
+ def find_resource_parent(self, resource_id:str):
+ # 遍历父辈,找到父辈的父辈,直到找到设备ID
+ parent_id = self.resources_config[resource_id]['parent']
+ try:
+ if parent_id in self.deck_list:
+ p_ = self.resources_config[parent_id]['parent']
+ str_ = f'{parent_id}'
+ return str(str_)
+ else:
+ return self.find_resource_parent(parent_id)
+ except Exception as e:
+ return None
+
+
+ def send_resource_action(self, resource_id_list:list[str], link_name:str):
+ goal_msg = SendCmd.Goal()
+ str_dict = {}
+ for resource in resource_id_list:
+ str_dict[resource] = link_name
+
+ goal_msg.command = json.dumps(str_dict)
+ self.resource_action_client.send_goal(goal_msg)
+
+ def resource_move(self, resource_id:str, link_name:str, channels:list[int]):
+ resource = resource_id.rsplit("_",1)
+
+ channel_list = ['A','B','C','D','E','F','G','H']
+
+ resource_list = []
+ match = re.match(r'([a-zA-Z_]+)(\d+)', resource[1])
+ if match:
+ number = match.group(2)
+ for channel in channels:
+ resource_list.append(f"{resource[0]}_{channel_list[channel]}{number}")
+
+ if len(resource_list) > 0:
+ self.send_resource_action(resource_list, link_name)
+
+
+
def lh_joint_action_callback(self,goal_handle: ServerGoalHandle):
"""Move a single joint
@@ -101,12 +164,13 @@ class LiquidHandlerJointPublisher(BaseROS2DeviceNode):
goal_handle.succeed()
except Exception as e:
- print(e)
+ print(f'Liquid handler action error: \n{e}')
goal_handle.abort()
result.success = False
-
+
return result
def inverse_kinematics(self, x, y, z,
+ parent_id,
x_joint:dict,
y_joint:dict,
z_joint:dict ):
@@ -117,77 +181,102 @@ class LiquidHandlerJointPublisher(BaseROS2DeviceNode):
x (float): x坐标
y (float): y坐标
z (float): z坐标
- x_joint (dict): x轴关节配置,包含plus和offset
- y_joint (dict): y轴关节配置,包含plus和offset
- z_joint (dict): z轴关节配置,包含plus和offset
+ x_joint (dict): x轴关节配置,包含factor和offset
+ y_joint (dict): y轴关节配置,包含factor和offset
+ z_joint (dict): z轴关节配置,包含factor和offset
Returns:
dict: 关节名称和对应位置的字典
"""
- joint_positions = copy.deepcopy(self.j_msg.position)
+ joint_positions = copy.deepcopy(self.lh_devices[parent_id]['joint_msg'].position)
+ z_index = 0
# 处理x轴关节
for joint_name, config in x_joint.items():
- index = self.j_msg.name.index(f"{self.lh_id}_{joint_name}")
+ index = self.lh_devices[parent_id]['joint_msg'].name.index(f"{parent_id}_{joint_name}")
joint_positions[index] = x * config["factor"] + config["offset"]
# 处理y轴关节
for joint_name, config in y_joint.items():
- index = self.j_msg.name.index(f"{self.lh_id}_{joint_name}")
+ index = self.lh_devices[parent_id]['joint_msg'].name.index(f"{parent_id}_{joint_name}")
joint_positions[index] = y * config["factor"] + config["offset"]
# 处理z轴关节
for joint_name, config in z_joint.items():
- index = self.j_msg.name.index(f"{self.lh_id}_{joint_name}")
+ index = self.lh_devices[parent_id]['joint_msg'].name.index(f"{parent_id}_{joint_name}")
joint_positions[index] = z * config["factor"] + config["offset"]
-
-
- return joint_positions
+ z_index = index
+
+ return joint_positions ,z_index
- def move_joints(self, resource_name, link_name, speed, x_joint=None, y_joint=None, z_joint=None):
+ def move_joints(self, resource_names, x, y, z, option, speed = 0.1 ,x_joint=None, y_joint=None, z_joint=None):
+ if isinstance(resource_names, list):
+ resource_name_ = resource_names[0]
+ else:
+ resource_name_ = resource_names
- transform = self.tf_buffer.lookup_transform(
- link_name,
- resource_name,
- rclpy.time.Time()
- )
- x,y,z = transform.transform.translation.x, transform.transform.translation.y, transform.transform.translation.z
+ parent_id = self.find_resource_parent(resource_name_)
+
+
+ print('!'*20)
+ print(parent_id)
+ print('!'*20)
if x_joint is None:
- x_joint_config = next(iter(self.joint_config['x'].items()))
- elif x_joint in self.joint_config['x']:
- x_joint_config = self.joint_config['x'][x_joint]
+ xa,xb = next(iter(self.lh_devices[parent_id]['joint_config']['x'].items()))
+ x_joint_config = {xa:xb}
+ elif x_joint in self.lh_devices[parent_id]['joint_config']['x']:
+ x_joint_config = self.lh_devices[parent_id]['joint_config']['x'][x_joint]
else:
raise ValueError(f"x_joint {x_joint} not in joint_config['x']")
if y_joint is None:
- y_joint_config = next(iter(self.joint_config['y'].items()))
- elif y_joint in self.joint_config['y']:
- y_joint_config = self.joint_config['y'][y_joint]
+ ya,yb = next(iter(self.lh_devices[parent_id]['joint_config']['y'].items()))
+ y_joint_config = {ya:yb}
+ elif y_joint in self.lh_devices[parent_id]['joint_config']['y']:
+ y_joint_config = self.lh_devices[parent_id]['joint_config']['y'][y_joint]
else:
raise ValueError(f"y_joint {y_joint} not in joint_config['y']")
if z_joint is None:
- z_joint_config = next(iter(self.joint_config['z'].items()))
- elif z_joint in self.joint_config['z']:
- z_joint_config = self.joint_config['z'][z_joint]
+ za, zb = next(iter(self.lh_devices[parent_id]['joint_config']['z'].items()))
+ z_joint_config = {za :zb}
+ elif z_joint in self.lh_devices[parent_id]['joint_config']['z']:
+ z_joint_config = self.lh_devices[parent_id]['joint_config']['z'][z_joint]
else:
raise ValueError(f"z_joint {z_joint} not in joint_config['z']")
- joint_positions_target = self.inverse_kinematics(x,y,z,x_joint_config,y_joint_config,z_joint_config)
+ joint_positions_target, z_index = self.inverse_kinematics(x,y,z,parent_id,x_joint_config,y_joint_config,z_joint_config)
+ joint_positions_target_zero = copy.deepcopy(joint_positions_target)
+ joint_positions_target_zero[z_index] = 0
+
+ self.move_to(joint_positions_target_zero, speed, parent_id)
+ self.move_to(joint_positions_target, speed, parent_id)
+ time.sleep(1)
+ if option == "pick":
+ link_name = self.lh_devices[parent_id]['joint_config']['link_names'][z_index]
+ link_name = f'{parent_id}_{link_name}'
+ self.resource_move(resource_name_, link_name, [0,1,2,3,4,5,6,7])
+ elif option == "drop_trash":
+ self.resource_move(resource_name_, "__trash", [0,1,2,3,4,5,6,7])
+ elif option == "drop":
+ self.resource_move(resource_name_, "world", [0,1,2,3,4,5,6,7])
+ self.move_to(joint_positions_target_zero, speed, parent_id)
+
+
+ def move_to(self, joint_positions ,speed, parent_id):
loop_flag = 0
-
- while loop_flag < len(self.joint_config['joint_names']):
+ while loop_flag < len(joint_positions):
loop_flag = 0
- for i in range(len(self.joint_config['joint_names'])):
- distance = joint_positions_target[i] - self.j_msg.position[i]
+ for i in range(len(joint_positions)):
+ distance = joint_positions[i] - self.lh_devices[parent_id]['joint_msg'].position[i]
if distance == 0:
loop_flag += 1
continue
minus_flag = distance/abs(distance)
if abs(distance) > speed/self.rate:
- self.j_msg.position[i] += minus_flag * speed/self.rate
+ self.lh_devices[parent_id]['joint_msg'].position[i] += minus_flag * speed/self.rate
else :
- self.j_msg.position[i] = joint_positions_target[i]
+ self.lh_devices[parent_id]['joint_msg'].position[i] = joint_positions[i]
loop_flag += 1
@@ -195,10 +284,103 @@ class LiquidHandlerJointPublisher(BaseROS2DeviceNode):
self.lh_joint_pub_callback()
time.sleep(1/self.rate)
-
def lh_joint_pub_callback(self):
- self.j_msg.header.stamp = self.get_clock().now().to_msg()
- self.j_pub.publish(self.j_msg)
+ for id, config in self.lh_devices.items():
+ config['joint_msg'].header.stamp = self.get_clock().now().to_msg()
+ self.j_pub.publish(config['joint_msg'])
+
+
+
+
+class JointStatePublisher(Node):
+ def __init__(self):
+ super().__init__('joint_state_publisher')
+
+ self.lh_action = None
+
+ while self.lh_action is None:
+ self.lh_action = self.check_hl_joint_actions()
+ time.sleep(1)
+
+ self.lh_action_client = ActionClient(self, SendCmd, self.lh_action)
+ while not self.lh_action_client.wait_for_server(timeout_sec=1.0):
+ self.get_logger().info('等待 TfUpdate 服务器...')
+
+
+
+ def check_hl_joint_actions(self):
+ topics = self.get_topic_names_and_types()
+
+
+ for topic_item in topics:
+
+ topic_name, topic_types = topic_item
+
+ if 'action_msgs/msg/GoalStatusArray' in topic_types:
+ # 删除 /_action/status 部分
+
+ base_name = topic_name.replace('/_action/status', '')
+ # 检查最后一个部分是否为 tf_update
+ parts = base_name.split('/')
+ if parts and parts[-1] == 'hl_joint_action':
+ return base_name
+
+ return None
+
+ def send_resource_action(self, resource_name, x,y,z,option, speed = 0.1,x_joint=None, y_joint=None, z_joint=None):
+ goal_msg = SendCmd.Goal()
+ str_dict = {
+ 'resource_names':resource_name,
+ 'x':x,
+ 'y':y,
+ 'z':z,
+ 'option':option,
+ 'speed':speed,
+ 'x_joint':x_joint,
+ 'y_joint':y_joint,
+ 'z_joint':z_joint
+ }
+
+
+ goal_msg.command = json.dumps(str_dict)
+
+ if not self.lh_action_client.wait_for_server(timeout_sec=5.0):
+ self.get_logger().error('Action server not available')
+ return None
+
+ try:
+ # 创建新的executor
+ executor = rclpy.executors.MultiThreadedExecutor()
+ executor.add_node(self)
+
+ # 发送目标
+ future = self.lh_action_client.send_goal_async(goal_msg)
+
+ # 使用executor等待结果
+ while not future.done():
+ executor.spin_once(timeout_sec=0.1)
+
+ handle = future.result()
+
+ if not handle.accepted:
+ self.get_logger().error('Goal was rejected')
+ return None
+
+ # 等待最终结果
+ result_future = handle.get_result_async()
+ while not result_future.done():
+ executor.spin_once(timeout_sec=0.1)
+
+ result = result_future.result()
+ return result
+
+ except Exception as e:
+ self.get_logger().error(f'Error during action execution: {str(e)}')
+ return None
+ finally:
+ # 清理executor
+ executor.remove_node(self)
+
def main():
diff --git a/unilabos/devices/ros_dev/moveit2.py b/unilabos/devices/ros_dev/moveit2.py
new file mode 100644
index 0000000..80bea9d
--- /dev/null
+++ b/unilabos/devices/ros_dev/moveit2.py
@@ -0,0 +1,2442 @@
+import copy
+import threading
+from enum import Enum
+from typing import Any, List, Optional, Tuple, Union
+
+import numpy as np
+from action_msgs.msg import GoalStatus
+from geometry_msgs.msg import Point, Pose, PoseStamped, Quaternion
+from moveit_msgs.action import ExecuteTrajectory, MoveGroup
+from moveit_msgs.msg import (
+ AllowedCollisionEntry,
+ AttachedCollisionObject,
+ CollisionObject,
+ Constraints,
+ JointConstraint,
+ MoveItErrorCodes,
+ OrientationConstraint,
+ PlanningScene,
+ PositionConstraint,
+)
+from moveit_msgs.srv import (
+ ApplyPlanningScene,
+ GetCartesianPath,
+ GetMotionPlan,
+ GetPlanningScene,
+ GetPositionFK,
+ GetPositionIK,
+)
+from rclpy.action import ActionClient
+from rclpy.callback_groups import CallbackGroup
+from rclpy.node import Node
+from rclpy.qos import (
+ QoSDurabilityPolicy,
+ QoSHistoryPolicy,
+ QoSProfile,
+ QoSReliabilityPolicy,
+)
+from rclpy.task import Future
+from sensor_msgs.msg import JointState
+from shape_msgs.msg import Mesh, MeshTriangle, SolidPrimitive
+from std_msgs.msg import Header, String
+from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint
+
+
+class MoveIt2State(Enum):
+ """
+ An enum the represents the current execution state of the MoveIt2 interface.
+ - IDLE: No motion is being requested or executed
+ - REQUESTING: Execution has been requested, but the request has not yet been
+ accepted.
+ - EXECUTING: Execution has been requested and accepted, and has not yet been
+ completed.
+ """
+
+ IDLE = 0
+ REQUESTING = 1
+ EXECUTING = 2
+
+
+class MoveIt2:
+ """
+ Python interface for MoveIt 2 that enables planning and execution of trajectories.
+ For execution, this interface requires that robot utilises JointTrajectoryController.
+ """
+
+ def __init__(
+ self,
+ node: Node,
+ joint_names: List[str],
+ base_link_name: str,
+ end_effector_name: str,
+ group_name: str = "arm",
+ execute_via_moveit: bool = False,
+ ignore_new_calls_while_executing: bool = False,
+ callback_group: Optional[CallbackGroup] = None,
+ follow_joint_trajectory_action_name: str = "DEPRECATED",
+ use_move_group_action: bool = False,
+ ):
+ """
+ Construct an instance of `MoveIt2` interface.
+ - `node` - ROS 2 node that this interface is attached to
+ - `joint_names` - List of joint names of the robot (can be extracted from URDF)
+ - `base_link_name` - Name of the robot base link
+ - `end_effector_name` - Name of the robot end effector
+ - `group_name` - Name of the planning group for robot arm
+ - [DEPRECATED] `execute_via_moveit` - Flag that enables execution via MoveGroup action (MoveIt 2)
+ FollowJointTrajectory action (controller) is employed otherwise
+ together with a separate planning service client
+ - `ignore_new_calls_while_executing` - Flag to ignore requests to execute new trajectories
+ while previous is still being executed
+ - `callback_group` - Optional callback group to use for ROS 2 communication (topics/services/actions)
+ - [DEPRECATED] `follow_joint_trajectory_action_name` - Name of the action server for the controller
+ - `use_move_group_action` - Flag that enables execution via MoveGroup action (MoveIt 2)
+ ExecuteTrajectory action is employed otherwise
+ together with a separate planning service client
+ """
+
+ self._node = node
+ self._callback_group = callback_group
+
+ # Check for deprecated parameters
+ if execute_via_moveit:
+ self._node.get_logger().warn(
+ "Parameter `execute_via_moveit` is deprecated. Please use `use_move_group_action` instead."
+ )
+ use_move_group_action = True
+ if follow_joint_trajectory_action_name != "DEPRECATED":
+ self._node.get_logger().warn(
+ "Parameter `follow_joint_trajectory_action_name` is deprecated. `MoveIt2` uses the `execute_trajectory` action instead."
+ )
+
+ # Create subscriber for current joint states
+ self._node.create_subscription(
+ msg_type=JointState,
+ topic="/joint_states",
+ callback=self.__joint_state_callback,
+ qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.BEST_EFFORT,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ callback_group=self._callback_group,
+ )
+
+ # Create action client for move action
+ self.__move_action_client = ActionClient(
+ node=self._node,
+ action_type=MoveGroup,
+ action_name="/move_action",
+ goal_service_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ result_service_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=5,
+ ),
+ cancel_service_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=5,
+ ),
+ feedback_sub_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.BEST_EFFORT,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ status_sub_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.BEST_EFFORT,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ callback_group=self._callback_group,
+ )
+
+ # Also create a separate service client for planning
+ self._plan_kinematic_path_service = self._node.create_client(
+ srv_type=GetMotionPlan,
+ srv_name="/plan_kinematic_path",
+ qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ callback_group=callback_group,
+ )
+ self.__kinematic_path_request = GetMotionPlan.Request()
+
+ # Create a separate service client for Cartesian planning
+ self._plan_cartesian_path_service = self._node.create_client(
+ srv_type=GetCartesianPath,
+ srv_name="/compute_cartesian_path",
+ qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ callback_group=callback_group,
+ )
+ self.__cartesian_path_request = GetCartesianPath.Request()
+
+ # Create action client for trajectory execution
+ self._execute_trajectory_action_client = ActionClient(
+ node=self._node,
+ action_type=ExecuteTrajectory,
+ action_name="/execute_trajectory",
+ goal_service_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ result_service_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=5,
+ ),
+ cancel_service_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=5,
+ ),
+ feedback_sub_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.BEST_EFFORT,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ status_sub_qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.BEST_EFFORT,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ callback_group=self._callback_group,
+ )
+
+ # Create a service for getting the planning scene
+ self._get_planning_scene_service = self._node.create_client(
+ srv_type=GetPlanningScene,
+ srv_name="/get_planning_scene",
+ qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ callback_group=callback_group,
+ )
+ self.__planning_scene = None
+ self.__old_planning_scene = None
+ self.__old_allowed_collision_matrix = None
+
+ # Create a service for applying the planning scene
+ self._apply_planning_scene_service = self._node.create_client(
+ srv_type=ApplyPlanningScene,
+ srv_name="/apply_planning_scene",
+ qos_profile=QoSProfile(
+ durability=QoSDurabilityPolicy.VOLATILE,
+ reliability=QoSReliabilityPolicy.RELIABLE,
+ history=QoSHistoryPolicy.KEEP_LAST,
+ depth=1,
+ ),
+ callback_group=callback_group,
+ )
+
+ self.__collision_object_publisher = self._node.create_publisher(
+ CollisionObject, "/collision_object", 10
+ )
+ self.__attached_collision_object_publisher = self._node.create_publisher(
+ AttachedCollisionObject, "/attached_collision_object", 10
+ )
+
+ self.__cancellation_pub = self._node.create_publisher(
+ String, "/trajectory_execution_event", 1
+ )
+
+ self.__joint_state_mutex = threading.Lock()
+ self.__joint_state = None
+ self.__new_joint_state_available = False
+ self.__move_action_goal = self.__init_move_action_goal(
+ frame_id=base_link_name,
+ group_name=group_name,
+ end_effector=end_effector_name,
+ )
+
+ # Flag to determine whether to execute trajectories via Move Group Action, or rather by calling
+ # the separate ExecuteTrajectory action
+ # Applies to `move_to_pose()` and `move_to_configuration()`
+ self.__use_move_group_action = use_move_group_action
+
+ # Flag that determines whether a new goal can be sent while the previous one is being executed
+ self.__ignore_new_calls_while_executing = ignore_new_calls_while_executing
+
+ # Store additional variables for later use
+ self.__joint_names = joint_names
+ self.__base_link_name = base_link_name
+ self.__end_effector_name = end_effector_name
+ self.__group_name = group_name
+
+ # Internal states that monitor the current motion requests and execution
+ self.__is_motion_requested = False
+ self.__is_executing = False
+ self.motion_suceeded = False
+ self.__execution_goal_handle = None
+ self.__last_error_code = None
+ self.__wait_until_executed_rate = self._node.create_rate(1000.0)
+ self.__execution_mutex = threading.Lock()
+
+ # Event that enables waiting until async future is done
+ self.__future_done_event = threading.Event()
+
+ #### Execution Polling Functions
+ def query_state(self) -> MoveIt2State:
+ with self.__execution_mutex:
+ if self.__is_motion_requested:
+ return MoveIt2State.REQUESTING
+ elif self.__is_executing:
+ return MoveIt2State.EXECUTING
+ else:
+ return MoveIt2State.IDLE
+
+ def cancel_execution(self):
+ if self.query_state() != MoveIt2State.EXECUTING:
+ self._node.get_logger().warn("Attempted to cancel without active goal.")
+ return None
+
+ cancel_string = String()
+ cancel_string.data = "stop"
+ self.__cancellation_pub.publish(cancel_string)
+
+ def get_execution_future(self) -> Optional[Future]:
+ if self.query_state() != MoveIt2State.EXECUTING:
+ self._node.get_logger().warn("Need active goal for future.")
+ return None
+
+ return self.__execution_goal_handle.get_result_async()
+
+ def get_last_execution_error_code(self) -> Optional[MoveItErrorCodes]:
+ return self.__last_error_code
+
+ ####
+
+ def move_to_pose(
+ self,
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ target_link: Optional[str] = None,
+ frame_id: Optional[str] = None,
+ tolerance_position: float = 0.001,
+ tolerance_orientation: float = 0.001,
+ weight_position: float = 1.0,
+ cartesian: bool = True,
+ weight_orientation: float = 1.0,
+ cartesian_max_step: float = 0.0025,
+ cartesian_fraction_threshold: float = 0.0,
+ ):
+ """
+ Plan and execute motion based on previously set goals. Optional arguments can be
+ passed in to internally use `set_pose_goal()` to define a goal during the call.
+ """
+
+ if isinstance(pose, PoseStamped):
+ pose_stamped = pose
+ elif isinstance(pose, Pose):
+ pose_stamped = PoseStamped(
+ header=Header(
+ stamp=self._node.get_clock().now().to_msg(),
+ frame_id=(
+ frame_id if frame_id is not None else self.__base_link_name
+ ),
+ ),
+ pose=pose,
+ )
+ else:
+ if not isinstance(position, Point):
+ position = Point(
+ x=float(position[0]), y=float(position[1]), z=float(position[2])
+ )
+ if not isinstance(quat_xyzw, Quaternion):
+ quat_xyzw = Quaternion(
+ x=float(quat_xyzw[0]),
+ y=float(quat_xyzw[1]),
+ z=float(quat_xyzw[2]),
+ w=float(quat_xyzw[3]),
+ )
+ pose_stamped = PoseStamped(
+ header=Header(
+ stamp=self._node.get_clock().now().to_msg(),
+ frame_id=(
+ frame_id if frame_id is not None else self.__base_link_name
+ ),
+ ),
+ pose=Pose(position=position, orientation=quat_xyzw),
+ )
+
+ if self.__use_move_group_action and not cartesian:
+ if self.__ignore_new_calls_while_executing and (
+ self.__is_motion_requested or self.__is_executing
+ ):
+ self._node.get_logger().warn(
+ "Controller is already following a trajectory. Skipping motion."
+ )
+ return
+
+ # Set goal
+ self.set_pose_goal(
+ position=pose_stamped.pose.position,
+ quat_xyzw=pose_stamped.pose.orientation,
+ frame_id=pose_stamped.header.frame_id,
+ target_link=target_link,
+ tolerance_position=tolerance_position,
+ tolerance_orientation=tolerance_orientation,
+ weight_position=weight_position,
+ weight_orientation=weight_orientation,
+ )
+ # Define starting state as the current state
+ if self.joint_state is not None:
+ self.__move_action_goal.request.start_state.joint_state = (
+ self.joint_state
+ )
+ # Send to goal to the server (async) - both planning and execution
+ self._send_goal_async_move_action()
+ # Clear all previous goal constrains
+ self.clear_goal_constraints()
+ self.clear_path_constraints()
+
+ else:
+ # Plan via MoveIt 2 and then execute directly with the controller
+ self.execute(
+ self.plan(
+ position=pose_stamped.pose.position,
+ quat_xyzw=pose_stamped.pose.orientation,
+ frame_id=pose_stamped.header.frame_id,
+ target_link=target_link,
+ tolerance_position=tolerance_position,
+ tolerance_orientation=tolerance_orientation,
+ weight_position=weight_position,
+ weight_orientation=weight_orientation,
+ cartesian=cartesian,
+ max_step=cartesian_max_step,
+ cartesian_fraction_threshold=cartesian_fraction_threshold,
+ )
+ )
+
+ def move_to_configuration(
+ self,
+ joint_positions: List[float],
+ joint_names: Optional[List[str]] = None,
+ tolerance: float = 0.001,
+ weight: float = 1.0,
+ cartesian: bool = False,
+ ):
+ """
+ Plan and execute motion based on previously set goals. Optional arguments can be
+ passed in to internally use `set_joint_goal()` to define a goal during the call.
+ """
+
+ if self.__use_move_group_action:
+ if self.__ignore_new_calls_while_executing and (
+ self.__is_motion_requested or self.__is_executing
+ ):
+ self._node.get_logger().warn(
+ "Controller is already following a trajectory. Skipping motion."
+ )
+ return
+
+ # Set goal
+ self.set_joint_goal(
+ joint_positions=joint_positions,
+ joint_names=joint_names,
+ tolerance=tolerance,
+ weight=weight,
+ )
+ # Define starting state as the current state
+ if self.joint_state is not None:
+ self.__move_action_goal.request.start_state.joint_state = (
+ self.joint_state
+ )
+ # Send to goal to the server (async) - both planning and execution
+ self._send_goal_async_move_action()
+ # Clear all previous goal constrains
+ self.clear_goal_constraints()
+ self.clear_path_constraints()
+
+ else:
+ # Plan via MoveIt 2 and then execute directly with the controller
+ self.execute(
+ self.plan(
+ joint_positions=joint_positions,
+ joint_names=joint_names,
+ tolerance_joint_position=tolerance,
+ weight_joint_position=weight,
+ cartesian=cartesian,
+ )
+ )
+
+ def plan(
+ self,
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ joint_positions: Optional[List[float]] = None,
+ joint_names: Optional[List[str]] = None,
+ frame_id: Optional[str] = None,
+ target_link: Optional[str] = None,
+ tolerance_position: float = 0.001,
+ tolerance_orientation: Union[float, Tuple[float, float, float]] = 0.001,
+ tolerance_joint_position: float = 0.001,
+ weight_position: float = 1.0,
+ weight_orientation: float = 1.0,
+ weight_joint_position: float = 1.0,
+ start_joint_state: Optional[Union[JointState, List[float]]] = None,
+ cartesian: bool = False,
+ max_step: float = 0.0025,
+ cartesian_fraction_threshold: float = 0.0,
+ ) -> Optional[JointTrajectory]:
+ """
+ Call plan_async and wait on future
+ """
+ future = self.plan_async(
+ **{
+ key: value
+ for key, value in locals().items()
+ if key not in ["self", "cartesian_fraction_threshold"]
+ }
+ )
+
+ if future is None:
+ return None
+
+ # 100ms sleep
+ rate = self._node.create_rate(10)
+ while not future.done():
+ rate.sleep()
+
+ return self.get_trajectory(
+ future,
+ cartesian=cartesian,
+ cartesian_fraction_threshold=cartesian_fraction_threshold,
+ )
+
+ def plan_async(
+ self,
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ joint_positions: Optional[List[float]] = None,
+ joint_names: Optional[List[str]] = None,
+ frame_id: Optional[str] = None,
+ target_link: Optional[str] = None,
+ tolerance_position: float = 0.001,
+ tolerance_orientation: Union[float, Tuple[float, float, float]] = 0.001,
+ tolerance_joint_position: float = 0.001,
+ weight_position: float = 1.0,
+ weight_orientation: float = 1.0,
+ weight_joint_position: float = 1.0,
+ start_joint_state: Optional[Union[JointState, List[float]]] = None,
+ cartesian: bool = False,
+ max_step: float = 0.0025,
+ ) -> Optional[Future]:
+ """
+ Plan motion based on previously set goals. Optional arguments can be passed in to
+ internally use `set_position_goal()`, `set_orientation_goal()` or `set_joint_goal()`
+ to define a goal during the call. If no trajectory is found within the timeout
+ duration, `None` is returned. To plan from the different position than the current
+ one, optional argument `start_` can be defined.
+ """
+
+ pose_stamped = None
+ if pose is not None:
+ if isinstance(pose, PoseStamped):
+ pose_stamped = pose
+ elif isinstance(pose, Pose):
+ pose_stamped = PoseStamped(
+ header=Header(
+ stamp=self._node.get_clock().now().to_msg(),
+ frame_id=(
+ frame_id if frame_id is not None else self.__base_link_name
+ ),
+ ),
+ pose=pose,
+ )
+
+ self.set_position_goal(
+ position=pose_stamped.pose.position,
+ frame_id=pose_stamped.header.frame_id,
+ target_link=target_link,
+ tolerance=tolerance_position,
+ weight=weight_position,
+ )
+ self.set_orientation_goal(
+ quat_xyzw=pose_stamped.pose.orientation,
+ frame_id=pose_stamped.header.frame_id,
+ target_link=target_link,
+ tolerance=tolerance_orientation,
+ weight=weight_orientation,
+ )
+ else:
+ if position is not None:
+ if not isinstance(position, Point):
+ position = Point(
+ x=float(position[0]), y=float(position[1]), z=float(position[2])
+ )
+
+ self.set_position_goal(
+ position=position,
+ frame_id=frame_id,
+ target_link=target_link,
+ tolerance=tolerance_position,
+ weight=weight_position,
+ )
+
+ if quat_xyzw is not None:
+ if not isinstance(quat_xyzw, Quaternion):
+ quat_xyzw = Quaternion(
+ x=float(quat_xyzw[0]),
+ y=float(quat_xyzw[1]),
+ z=float(quat_xyzw[2]),
+ w=float(quat_xyzw[3]),
+ )
+
+ self.set_orientation_goal(
+ quat_xyzw=quat_xyzw,
+ frame_id=frame_id,
+ target_link=target_link,
+ tolerance=tolerance_orientation,
+ weight=weight_orientation,
+ )
+
+ if joint_positions is not None:
+ self.set_joint_goal(
+ joint_positions=joint_positions,
+ joint_names=joint_names,
+ tolerance=tolerance_joint_position,
+ weight=weight_joint_position,
+ )
+
+ # Define starting state for the plan (default to the current state)
+ if start_joint_state is not None:
+ if isinstance(start_joint_state, JointState):
+ self.__move_action_goal.request.start_state.joint_state = (
+ start_joint_state
+ )
+ else:
+ self.__move_action_goal.request.start_state.joint_state = (
+ init_joint_state(
+ joint_names=self.__joint_names,
+ joint_positions=start_joint_state,
+ )
+ )
+ elif self.joint_state is not None:
+ self.__move_action_goal.request.start_state.joint_state = self.joint_state
+
+ # Plan trajectory asynchronously by service call
+ if cartesian:
+ future = self._plan_cartesian_path(
+ max_step=max_step,
+ frame_id=(
+ pose_stamped.header.frame_id
+ if pose_stamped is not None
+ else frame_id
+ ),
+ )
+ else:
+ # Use service
+ future = self._plan_kinematic_path()
+
+
+ # Clear all previous goal constrains
+ self.clear_goal_constraints()
+ self.clear_path_constraints()
+
+ return future
+
+ def get_trajectory(
+ self,
+ future: Future,
+ cartesian: bool = False,
+ cartesian_fraction_threshold: float = 0.0,
+ ) -> Optional[JointTrajectory]:
+ """
+ Takes in a future returned by plan_async and returns the trajectory if the future is done
+ and planning was successful, else None.
+
+ For cartesian plans, the plan is rejected if the fraction of the path that was completed is
+ less than `cartesian_fraction_threshold`.
+ """
+ if not future.done():
+ self._node.get_logger().warn(
+ "Cannot get trajectory because future is not done."
+ )
+ return None
+
+ res = future.result()
+
+ # Cartesian
+ if cartesian:
+ if MoveItErrorCodes.SUCCESS == res.error_code.val:
+ if res.fraction >= cartesian_fraction_threshold:
+ return res.solution.joint_trajectory
+ else:
+ self._node.get_logger().warn(
+ f"Planning failed! Cartesian planner completed {res.fraction} "
+ f"of the trajectory, less than the threshold {cartesian_fraction_threshold}."
+ )
+ return None
+ else:
+ self._node.get_logger().warn(
+ f"Planning failed! Error code: {res.error_code.val}."
+ )
+ return None
+
+ # Else Kinematic
+ res = res.motion_plan_response
+ if MoveItErrorCodes.SUCCESS == res.error_code.val:
+ return res.trajectory.joint_trajectory
+ else:
+ self._node.get_logger().warn(
+ f"Planning failed! Error code: {res.error_code.val}."
+ )
+ return None
+
+ def execute(self, joint_trajectory: JointTrajectory):
+ """
+ Execute joint_trajectory by communicating directly with the controller.
+ """
+
+ if self.__ignore_new_calls_while_executing and (
+ self.__is_motion_requested or self.__is_executing
+ ):
+ self._node.get_logger().warn(
+ "Controller is already following a trajectory. Skipping motion."
+ )
+ return
+
+ execute_trajectory_goal = init_execute_trajectory_goal(
+ joint_trajectory=joint_trajectory
+ )
+
+ if execute_trajectory_goal is None:
+ self._node.get_logger().warn(
+ "Cannot execute motion because the provided/planned trajectory is invalid."
+ )
+ return
+
+ self._send_goal_async_execute_trajectory(goal=execute_trajectory_goal)
+
+ def wait_until_executed(self) -> bool:
+ """
+ Wait until the previously requested motion is finalised through either a success or failure.
+ """
+
+ if not self.__is_motion_requested:
+ self._node.get_logger().warn(
+ "Cannot wait until motion is executed (no motion is in progress)."
+ )
+ return False
+
+ while self.__is_motion_requested or self.__is_executing:
+ self.__wait_until_executed_rate.sleep()
+
+ return self.motion_suceeded
+
+ def reset_controller(
+ self, joint_state: Union[JointState, List[float]], sync: bool = True
+ ):
+ """
+ Reset controller to a given `joint_state` by sending a dummy joint trajectory.
+ This is useful for simulated robots that allow instantaneous reset of joints.
+ """
+
+ if not isinstance(joint_state, JointState):
+ joint_state = init_joint_state(
+ joint_names=self.__joint_names,
+ joint_positions=joint_state,
+ )
+ joint_trajectory = init_dummy_joint_trajectory_from_state(joint_state)
+ execute_trajectory_goal = init_execute_trajectory_goal(
+ joint_trajectory=joint_trajectory
+ )
+
+ self._send_goal_async_execute_trajectory(
+ goal=execute_trajectory_goal,
+ wait_until_response=sync,
+ )
+
+ def set_pose_goal(
+ self,
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ frame_id: Optional[str] = None,
+ target_link: Optional[str] = None,
+ tolerance_position: float = 0.001,
+ tolerance_orientation: Union[float, Tuple[float, float, float]] = 0.001,
+ weight_position: float = 1.0,
+ weight_orientation: float = 1.0,
+ ):
+ """
+ This is direct combination of `set_position_goal()` and `set_orientation_goal()`.
+ """
+
+ if (pose is None) and (position is None or quat_xyzw is None):
+ raise ValueError(
+ "Either `pose` or `position` and `quat_xyzw` must be specified!"
+ )
+
+ if isinstance(pose, PoseStamped):
+ pose_stamped = pose
+ elif isinstance(pose, Pose):
+ pose_stamped = PoseStamped(
+ header=Header(
+ stamp=self._node.get_clock().now().to_msg(),
+ frame_id=(
+ frame_id if frame_id is not None else self.__base_link_name
+ ),
+ ),
+ pose=pose,
+ )
+ else:
+ if not isinstance(position, Point):
+ position = Point(
+ x=float(position[0]), y=float(position[1]), z=float(position[2])
+ )
+ if not isinstance(quat_xyzw, Quaternion):
+ quat_xyzw = Quaternion(
+ x=float(quat_xyzw[0]),
+ y=float(quat_xyzw[1]),
+ z=float(quat_xyzw[2]),
+ w=float(quat_xyzw[3]),
+ )
+ pose_stamped = PoseStamped(
+ header=Header(
+ stamp=self._node.get_clock().now().to_msg(),
+ frame_id=(
+ frame_id if frame_id is not None else self.__base_link_name
+ ),
+ ),
+ pose=Pose(position=position, orientation=quat_xyzw),
+ )
+
+ self.set_position_goal(
+ position=pose_stamped.pose.position,
+ frame_id=pose_stamped.header.frame_id,
+ target_link=target_link,
+ tolerance=tolerance_position,
+ weight=weight_position,
+ )
+ self.set_orientation_goal(
+ quat_xyzw=pose_stamped.pose.orientation,
+ frame_id=pose_stamped.header.frame_id,
+ target_link=target_link,
+ tolerance=tolerance_orientation,
+ weight=weight_orientation,
+ )
+
+ def create_position_constraint(
+ self,
+ position: Union[Point, Tuple[float, float, float]],
+ frame_id: Optional[str] = None,
+ target_link: Optional[str] = None,
+ tolerance: float = 0.001,
+ weight: float = 1.0,
+ ) -> PositionConstraint:
+ """
+ Create Cartesian position constraint of `target_link` with respect to `frame_id`.
+ - `frame_id` defaults to the base link
+ - `target_link` defaults to end effector
+ """
+
+ # Create new position constraint
+ constraint = PositionConstraint()
+
+ # Define reference frame and target link
+ constraint.header.frame_id = (
+ frame_id if frame_id is not None else self.__base_link_name
+ )
+ constraint.link_name = (
+ target_link if target_link is not None else self.__end_effector_name
+ )
+
+ # Define target position
+ constraint.constraint_region.primitive_poses.append(Pose())
+ if isinstance(position, Point):
+ constraint.constraint_region.primitive_poses[0].position = position
+ else:
+ constraint.constraint_region.primitive_poses[0].position.x = float(
+ position[0]
+ )
+ constraint.constraint_region.primitive_poses[0].position.y = float(
+ position[1]
+ )
+ constraint.constraint_region.primitive_poses[0].position.z = float(
+ position[2]
+ )
+
+ # Define goal region as a sphere with radius equal to the tolerance
+ constraint.constraint_region.primitives.append(SolidPrimitive())
+ constraint.constraint_region.primitives[0].type = 2 # Sphere
+ constraint.constraint_region.primitives[0].dimensions = [tolerance]
+
+ # Set weight of the constraint
+ constraint.weight = weight
+
+ return constraint
+
+ def set_position_goal(
+ self,
+ position: Union[Point, Tuple[float, float, float]],
+ frame_id: Optional[str] = None,
+ target_link: Optional[str] = None,
+ tolerance: float = 0.001,
+ weight: float = 1.0,
+ ):
+ """
+ Set Cartesian position goal of `target_link` with respect to `frame_id`.
+ - `frame_id` defaults to the base link
+ - `target_link` defaults to end effector
+ """
+
+ constraint = self.create_position_constraint(
+ position=position,
+ frame_id=frame_id,
+ target_link=target_link,
+ tolerance=tolerance,
+ weight=weight,
+ )
+
+ # Append to other constraints
+ self.__move_action_goal.request.goal_constraints[
+ -1
+ ].position_constraints.append(constraint)
+
+ def create_orientation_constraint(
+ self,
+ quat_xyzw: Union[Quaternion, Tuple[float, float, float, float]],
+ frame_id: Optional[str] = None,
+ target_link: Optional[str] = None,
+ tolerance: Union[float, Tuple[float, float, float]] = 0.001,
+ weight: float = 1.0,
+ parameterization: int = 0, # 0: Euler, 1: Rotation Vector
+ ) -> OrientationConstraint:
+ """
+ Create a Cartesian orientation constraint of `target_link` with respect to `frame_id`.
+ - `frame_id` defaults to the base link
+ - `target_link` defaults to end effector
+ """
+
+ # Create new position constraint
+ constraint = OrientationConstraint()
+
+ # Define reference frame and target link
+ constraint.header.frame_id = (
+ frame_id if frame_id is not None else self.__base_link_name
+ )
+ constraint.link_name = (
+ target_link if target_link is not None else self.__end_effector_name
+ )
+
+ # Define target orientation
+ if isinstance(quat_xyzw, Quaternion):
+ constraint.orientation = quat_xyzw
+ else:
+ constraint.orientation.x = float(quat_xyzw[0])
+ constraint.orientation.y = float(quat_xyzw[1])
+ constraint.orientation.z = float(quat_xyzw[2])
+ constraint.orientation.w = float(quat_xyzw[3])
+
+ # Define tolerances
+ if type(tolerance) == float:
+ tolerance_xyz = (tolerance, tolerance, tolerance)
+ else:
+ tolerance_xyz = tolerance
+ constraint.absolute_x_axis_tolerance = tolerance_xyz[0]
+ constraint.absolute_y_axis_tolerance = tolerance_xyz[1]
+ constraint.absolute_z_axis_tolerance = tolerance_xyz[2]
+
+ # Define parameterization (how to interpret the tolerance)
+ constraint.parameterization = parameterization
+
+ # Set weight of the constraint
+ constraint.weight = weight
+
+ return constraint
+
+ def set_orientation_goal(
+ self,
+ quat_xyzw: Union[Quaternion, Tuple[float, float, float, float]],
+ frame_id: Optional[str] = None,
+ target_link: Optional[str] = None,
+ tolerance: Union[float, Tuple[float, float, float]] = 0.001,
+ weight: float = 1.0,
+ parameterization: int = 0, # 0: Euler, 1: Rotation Vector
+ ):
+ """
+ Set Cartesian orientation goal of `target_link` with respect to `frame_id`.
+ - `frame_id` defaults to the base link
+ - `target_link` defaults to end effector
+ """
+
+ constraint = self.create_orientation_constraint(
+ quat_xyzw=quat_xyzw,
+ frame_id=frame_id,
+ target_link=target_link,
+ tolerance=tolerance,
+ weight=weight,
+ parameterization=parameterization,
+ )
+
+ # Append to other constraints
+ self.__move_action_goal.request.goal_constraints[
+ -1
+ ].orientation_constraints.append(constraint)
+
+ def create_joint_constraints(
+ self,
+ joint_positions: List[float],
+ joint_names: Optional[List[str]] = None,
+ tolerance: float = 0.001,
+ weight: float = 1.0,
+ ) -> List[JointConstraint]:
+ """
+ Creates joint space constraints. With `joint_names` specified, `joint_positions` can be
+ defined for specific joints in an arbitrary order. Otherwise, first **n** joints
+ passed into the constructor is used, where **n** is the length of `joint_positions`.
+ """
+
+ constraints = []
+
+ # Use default joint names if not specified
+ if joint_names == None:
+ joint_names = self.__joint_names
+
+ for i in range(len(joint_positions)):
+ # Create a new constraint for each joint
+ constraint = JointConstraint()
+
+ # Define joint name
+ constraint.joint_name = joint_names[i]
+
+ # Define the target joint position
+ constraint.position = joint_positions[i]
+
+ # Define telerances
+ constraint.tolerance_above = tolerance
+ constraint.tolerance_below = tolerance
+
+ # Set weight of the constraint
+ constraint.weight = weight
+
+ constraints.append(constraint)
+
+ return constraints
+
+ def set_joint_goal(
+ self,
+ joint_positions: List[float],
+ joint_names: Optional[List[str]] = None,
+ tolerance: float = 0.001,
+ weight: float = 1.0,
+ ):
+ """
+ Set joint space goal. With `joint_names` specified, `joint_positions` can be
+ defined for specific joints in an arbitrary order. Otherwise, first **n** joints
+ passed into the constructor is used, where **n** is the length of `joint_positions`.
+ """
+
+ constraints = self.create_joint_constraints(
+ joint_positions=joint_positions,
+ joint_names=joint_names,
+ tolerance=tolerance,
+ weight=weight,
+ )
+
+ # Append to other constraints
+ self.__move_action_goal.request.goal_constraints[-1].joint_constraints.extend(
+ constraints
+ )
+
+ def clear_goal_constraints(self):
+ """
+ Clear all goal constraints that were previously set.
+ Note that this function is called automatically after each `plan_kinematic_path()`.
+ """
+
+ self.__move_action_goal.request.goal_constraints = [Constraints()]
+
+ def create_new_goal_constraint(self):
+ """
+ Create a new set of goal constraints that will be set together with the request. Each
+ subsequent setting of goals with `set_joint_goal()`, `set_pose_goal()` and others will be
+ added under this newly created set of constraints.
+ """
+
+ self.__move_action_goal.request.goal_constraints.append(Constraints())
+
+ def set_path_joint_constraint(
+ self,
+ joint_positions: List[float],
+ joint_names: Optional[List[str]] = None,
+ tolerance: float = 0.001,
+ weight: float = 1.0,
+ ):
+ """
+ Set joint space path constraints. With `joint_names` specified, `joint_positions` can be
+ defined for specific joints in an arbitrary order. Otherwise, first **n** joints
+ passed into the constructor is used, where **n** is the length of `joint_positions`.
+ """
+
+ constraints = self.create_joint_constraints(
+ joint_positions=joint_positions,
+ joint_names=joint_names,
+ tolerance=tolerance,
+ weight=weight,
+ )
+
+ # Append to other constraints
+ self.__move_action_goal.request.path_constraints.joint_constraints.extend(
+ constraints
+ )
+
+ def set_path_position_constraint(
+ self,
+ position: Union[Point, Tuple[float, float, float]],
+ frame_id: Optional[str] = None,
+ target_link: Optional[str] = None,
+ tolerance: float = 0.001,
+ weight: float = 1.0,
+ ):
+ """
+ Set Cartesian position path constraint of `target_link` with respect to `frame_id`.
+ - `frame_id` defaults to the base link
+ - `target_link` defaults to end effector
+ """
+
+ constraint = self.create_position_constraint(
+ position=position,
+ frame_id=frame_id,
+ target_link=target_link,
+ tolerance=tolerance,
+ weight=weight,
+ )
+
+ # Append to other constraints
+ self.__move_action_goal.request.path_constraints.position_constraints.append(
+ constraint
+ )
+
+ def set_path_orientation_constraint(
+ self,
+ quat_xyzw: Union[Quaternion, Tuple[float, float, float, float]],
+ frame_id: Optional[str] = None,
+ target_link: Optional[str] = None,
+ tolerance: Union[float, Tuple[float, float, float]] = 0.001,
+ weight: float = 1.0,
+ parameterization: int = 0, # 0: Euler Angles, 1: Rotation Vector
+ ):
+ """
+ Set Cartesian orientation path constraint of `target_link` with respect to `frame_id`.
+ - `frame_id` defaults to the base link
+ - `target_link` defaults to end effector
+ """
+
+ constraint = self.create_orientation_constraint(
+ quat_xyzw=quat_xyzw,
+ frame_id=frame_id,
+ target_link=target_link,
+ tolerance=tolerance,
+ weight=weight,
+ parameterization=parameterization,
+ )
+
+ # Append to other constraints
+ self.__move_action_goal.request.path_constraints.orientation_constraints.append(
+ constraint
+ )
+
+ def clear_path_constraints(self):
+ """
+ Clear all path constraints that were previously set.
+ Note that this function is called automatically after each `plan_kinematic_path()`.
+ """
+
+ self.__move_action_goal.request.path_constraints = Constraints()
+
+ def compute_fk(
+ self,
+ joint_state: Optional[Union[JointState, List[float]]] = None,
+ fk_link_names: Optional[List[str]] = None,
+ ) -> Optional[Union[PoseStamped, List[PoseStamped]]]:
+ """
+ Call compute_fk_async and wait on future
+ """
+ future = self.compute_fk_async(
+ **{key: value for key, value in locals().items() if key != "self"}
+ )
+
+ if future is None:
+ return None
+
+ # 100ms sleep
+ rate = self._node.create_rate(10)
+ while not future.done():
+ rate.sleep()
+
+ return self.get_compute_fk_result(future, fk_link_names=fk_link_names)
+
+ def get_compute_fk_result(
+ self,
+ future: Future,
+ fk_link_names: Optional[List[str]] = None,
+ ) -> Optional[Union[PoseStamped, List[PoseStamped]]]:
+ """
+ Takes in a future returned by compute_fk_async and returns the poses
+ if the future is done and successful, else None.
+ """
+ if not future.done():
+ self._node.get_logger().warn(
+ "Cannot get FK result because future is not done."
+ )
+ return None
+
+ res = future.result()
+
+ if MoveItErrorCodes.SUCCESS == res.error_code.val:
+ if fk_link_names is None:
+ return res.pose_stamped[0]
+ else:
+ return res.pose_stamped
+ else:
+ self._node.get_logger().warn(
+ f"FK computation failed! Error code: {res.error_code.val}."
+ )
+ return None
+
+ def compute_fk_async(
+ self,
+ joint_state: Optional[Union[JointState, List[float]]] = None,
+ fk_link_names: Optional[List[str]] = None,
+ ) -> Optional[Future]:
+ """
+ Compute forward kinematics for all `fk_link_names` in a given `joint_state`.
+ - `fk_link_names` defaults to end-effector
+ - `joint_state` defaults to the current joint state
+ """
+
+ if not hasattr(self, "__compute_fk_client"):
+ self.__init_compute_fk()
+
+ if fk_link_names is None:
+ self.__compute_fk_req.fk_link_names = [self.__end_effector_name]
+ else:
+ self.__compute_fk_req.fk_link_names = fk_link_names
+
+ if joint_state is not None:
+ if isinstance(joint_state, JointState):
+ self.__compute_fk_req.robot_state.joint_state = joint_state
+ else:
+ self.__compute_fk_req.robot_state.joint_state = init_joint_state(
+ joint_names=self.__joint_names,
+ joint_positions=joint_state,
+ )
+ elif self.joint_state is not None:
+ self.__compute_fk_req.robot_state.joint_state = self.joint_state
+
+ stamp = self._node.get_clock().now().to_msg()
+ self.__compute_fk_req.header.stamp = stamp
+
+ if not self.__compute_fk_client.service_is_ready():
+ self._node.get_logger().warn(
+ f"Service '{self.__compute_fk_client.srv_name}' is not yet available. Better luck next time!"
+ )
+ return None
+
+ return self.__compute_fk_client.call_async(self.__compute_fk_req)
+
+ def compute_ik(
+ self,
+ position: Union[Point, Tuple[float, float, float]],
+ quat_xyzw: Union[Quaternion, Tuple[float, float, float, float]],
+ start_joint_state: Optional[Union[JointState, List[float]]] = None,
+ constraints: Optional[Constraints] = None,
+ wait_for_server_timeout_sec: Optional[float] = 1.0,
+ ) -> Optional[JointState]:
+ """
+ Call compute_ik_async and wait on future
+ """
+ future = self.compute_ik_async(
+ **{key: value for key, value in locals().items() if key != "self"}
+ )
+
+ if future is None:
+ return None
+
+ # 10ms sleep
+ rate = self._node.create_rate(10)
+ while not future.done():
+ rate.sleep()
+
+ return self.get_compute_ik_result(future)
+
+ def get_compute_ik_result(
+ self,
+ future: Future,
+ ) -> Optional[JointState]:
+ """
+ Takes in a future returned by compute_ik_async and returns the joint states
+ if the future is done and successful, else None.
+ """
+ if not future.done():
+ self._node.get_logger().warn(
+ "Cannot get IK result because future is not done."
+ )
+ return None
+
+ res = future.result()
+
+ if MoveItErrorCodes.SUCCESS == res.error_code.val:
+ return res.solution.joint_state
+ else:
+ self._node.get_logger().warn(
+ f"IK computation failed! Error code: {res.error_code.val}."
+ )
+ return None
+
+ def compute_ik_async(
+ self,
+ position: Union[Point, Tuple[float, float, float]],
+ quat_xyzw: Union[Quaternion, Tuple[float, float, float, float]],
+ start_joint_state: Optional[Union[JointState, List[float]]] = None,
+ constraints: Optional[Constraints] = None,
+ wait_for_server_timeout_sec: Optional[float] = 1.0,
+ ) -> Optional[Future]:
+ """
+ Compute inverse kinematics for the given pose. To indicate beginning of the search space,
+ `start_joint_state` can be specified. Furthermore, `constraints` can be imposed on the
+ computed IK.
+ - `start_joint_state` defaults to current joint state.
+ - `constraints` defaults to None.
+ """
+
+ if not hasattr(self, "__compute_ik_client"):
+ self.__init_compute_ik()
+
+ if isinstance(position, Point):
+ self.__compute_ik_req.ik_request.pose_stamped.pose.position = position
+ else:
+ self.__compute_ik_req.ik_request.pose_stamped.pose.position.x = float(
+ position[0]
+ )
+ self.__compute_ik_req.ik_request.pose_stamped.pose.position.y = float(
+ position[1]
+ )
+ self.__compute_ik_req.ik_request.pose_stamped.pose.position.z = float(
+ position[2]
+ )
+ if isinstance(quat_xyzw, Quaternion):
+ self.__compute_ik_req.ik_request.pose_stamped.pose.orientation = quat_xyzw
+ else:
+ self.__compute_ik_req.ik_request.pose_stamped.pose.orientation.x = float(
+ quat_xyzw[0]
+ )
+ self.__compute_ik_req.ik_request.pose_stamped.pose.orientation.y = float(
+ quat_xyzw[1]
+ )
+ self.__compute_ik_req.ik_request.pose_stamped.pose.orientation.z = float(
+ quat_xyzw[2]
+ )
+ self.__compute_ik_req.ik_request.pose_stamped.pose.orientation.w = float(
+ quat_xyzw[3]
+ )
+
+ if start_joint_state is not None:
+ if isinstance(start_joint_state, JointState):
+ self.__compute_ik_req.ik_request.robot_state.joint_state = (
+ start_joint_state
+ )
+ else:
+ self.__compute_ik_req.ik_request.robot_state.joint_state = (
+ init_joint_state(
+ joint_names=self.__joint_names,
+ joint_positions=start_joint_state,
+ )
+ )
+ elif self.joint_state is not None:
+ self.__compute_ik_req.ik_request.robot_state.joint_state = self.joint_state
+
+ if constraints is not None:
+ self.__compute_ik_req.ik_request.constraints = constraints
+
+ stamp = self._node.get_clock().now().to_msg()
+ self.__compute_ik_req.ik_request.pose_stamped.header.stamp = stamp
+
+ if not self.__compute_ik_client.wait_for_service(
+ timeout_sec=wait_for_server_timeout_sec
+ ):
+ self._node.get_logger().warn(
+ f"Service '{self.__compute_ik_client.srv_name}' is not yet available. Better luck next time!"
+ )
+ return None
+
+ return self.__compute_ik_client.call_async(self.__compute_ik_req)
+
+ def reset_new_joint_state_checker(self):
+ """
+ Reset checker of the new joint state.
+ """
+
+ self.__joint_state_mutex.acquire()
+ self.__new_joint_state_available = False
+ self.__joint_state_mutex.release()
+
+ def force_reset_executing_state(self):
+ """
+ Force reset of internal states that block execution while `ignore_new_calls_while_executing` is being
+ used. This function is applicable only in a very few edge-cases, so it should almost never be used.
+ """
+
+ self.__execution_mutex.acquire()
+ self.__is_motion_requested = False
+ self.__is_executing = False
+ self.__execution_mutex.release()
+
+ def add_collision_primitive(
+ self,
+ id: str,
+ primitive_type: int,
+ dimensions: Tuple[float, float, float],
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ frame_id: Optional[str] = None,
+ operation: int = CollisionObject.ADD,
+ ):
+ """
+ Add collision object with a primitive geometry specified by its dimensions.
+
+ `primitive_type` can be one of the following:
+ - `SolidPrimitive.BOX`
+ - `SolidPrimitive.SPHERE`
+ - `SolidPrimitive.CYLINDER`
+ - `SolidPrimitive.CONE`
+ """
+
+ if (pose is None) and (position is None or quat_xyzw is None):
+ raise ValueError(
+ "Either `pose` or `position` and `quat_xyzw` must be specified!"
+ )
+
+ if isinstance(pose, PoseStamped):
+ pose_stamped = pose
+ elif isinstance(pose, Pose):
+ pose_stamped = PoseStamped(
+ header=Header(
+ stamp=self._node.get_clock().now().to_msg(),
+ frame_id=(
+ frame_id if frame_id is not None else self.__base_link_name
+ ),
+ ),
+ pose=pose,
+ )
+ else:
+ if not isinstance(position, Point):
+ position = Point(
+ x=float(position[0]), y=float(position[1]), z=float(position[2])
+ )
+ if not isinstance(quat_xyzw, Quaternion):
+ quat_xyzw = Quaternion(
+ x=float(quat_xyzw[0]),
+ y=float(quat_xyzw[1]),
+ z=float(quat_xyzw[2]),
+ w=float(quat_xyzw[3]),
+ )
+ pose_stamped = PoseStamped(
+ header=Header(
+ stamp=self._node.get_clock().now().to_msg(),
+ frame_id=(
+ frame_id if frame_id is not None else self.__base_link_name
+ ),
+ ),
+ pose=Pose(position=position, orientation=quat_xyzw),
+ )
+
+ msg = CollisionObject(
+ header=pose_stamped.header,
+ id=id,
+ operation=operation,
+ pose=pose_stamped.pose,
+ )
+
+ msg.primitives.append(
+ SolidPrimitive(type=primitive_type, dimensions=dimensions)
+ )
+
+ self.__collision_object_publisher.publish(msg)
+
+ def add_collision_box(
+ self,
+ id: str,
+ size: Tuple[float, float, float],
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ frame_id: Optional[str] = None,
+ operation: int = CollisionObject.ADD,
+ ):
+ """
+ Add collision object with a box geometry specified by its size.
+ """
+
+ assert len(size) == 3, "Invalid size of the box!"
+
+ self.add_collision_primitive(
+ id=id,
+ primitive_type=SolidPrimitive.BOX,
+ dimensions=size,
+ pose=pose,
+ position=position,
+ quat_xyzw=quat_xyzw,
+ frame_id=frame_id,
+ operation=operation,
+ )
+
+ def add_collision_sphere(
+ self,
+ id: str,
+ radius: float,
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ frame_id: Optional[str] = None,
+ operation: int = CollisionObject.ADD,
+ ):
+ """
+ Add collision object with a sphere geometry specified by its radius.
+ """
+
+ if quat_xyzw is None:
+ quat_xyzw = Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
+
+ self.add_collision_primitive(
+ id=id,
+ primitive_type=SolidPrimitive.SPHERE,
+ dimensions=[
+ radius,
+ ],
+ pose=pose,
+ position=position,
+ quat_xyzw=quat_xyzw,
+ frame_id=frame_id,
+ operation=operation,
+ )
+
+ def add_collision_cylinder(
+ self,
+ id: str,
+ height: float,
+ radius: float,
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ frame_id: Optional[str] = None,
+ operation: int = CollisionObject.ADD,
+ ):
+ """
+ Add collision object with a cylinder geometry specified by its height and radius.
+ """
+
+ self.add_collision_primitive(
+ id=id,
+ primitive_type=SolidPrimitive.CYLINDER,
+ dimensions=[height, radius],
+ pose=pose,
+ position=position,
+ quat_xyzw=quat_xyzw,
+ frame_id=frame_id,
+ operation=operation,
+ )
+
+ def add_collision_cone(
+ self,
+ id: str,
+ height: float,
+ radius: float,
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ frame_id: Optional[str] = None,
+ operation: int = CollisionObject.ADD,
+ ):
+ """
+ Add collision object with a cone geometry specified by its height and radius.
+ """
+
+ self.add_collision_primitive(
+ id=id,
+ primitive_type=SolidPrimitive.CONE,
+ dimensions=[height, radius],
+ pose=pose,
+ position=position,
+ quat_xyzw=quat_xyzw,
+ frame_id=frame_id,
+ operation=operation,
+ )
+
+ def add_collision_mesh(
+ self,
+ filepath: Optional[str],
+ id: str,
+ pose: Optional[Union[PoseStamped, Pose]] = None,
+ position: Optional[Union[Point, Tuple[float, float, float]]] = None,
+ quat_xyzw: Optional[
+ Union[Quaternion, Tuple[float, float, float, float]]
+ ] = None,
+ frame_id: Optional[str] = None,
+ operation: int = CollisionObject.ADD,
+ scale: Union[float, Tuple[float, float, float]] = 1.0,
+ mesh: Optional[Any] = None,
+ ):
+ """
+ Add collision object with a mesh geometry. Either `filepath` must be
+ specified or `mesh` must be provided.
+ Note: This function required 'trimesh' Python module to be installed.
+ """
+
+ # Load the mesh
+ try:
+ import trimesh
+ except ImportError as err:
+ raise ImportError(
+ "Python module 'trimesh' not found! Please install it manually in order "
+ "to add collision objects into the MoveIt 2 planning scene."
+ ) from err
+
+ # Check the parameters
+ if (pose is None) and (position is None or quat_xyzw is None):
+ raise ValueError(
+ "Either `pose` or `position` and `quat_xyzw` must be specified!"
+ )
+ if (filepath is None and mesh is None) or (
+ filepath is not None and mesh is not None
+ ):
+ raise ValueError("Exactly one of `filepath` or `mesh` must be specified!")
+ if mesh is not None and not isinstance(mesh, trimesh.Trimesh):
+ raise ValueError("`mesh` must be an instance of `trimesh.Trimesh`!")
+
+ if isinstance(pose, PoseStamped):
+ pose_stamped = pose
+ elif isinstance(pose, Pose):
+ pose_stamped = PoseStamped(
+ header=Header(
+ stamp=self._node.get_clock().now().to_msg(),
+ frame_id=(
+ frame_id if frame_id is not None else self.__base_link_name
+ ),
+ ),
+ pose=pose,
+ )
+ else:
+ if not isinstance(position, Point):
+ position = Point(
+ x=float(position[0]), y=float(position[1]), z=float(position[2])
+ )
+ if not isinstance(quat_xyzw, Quaternion):
+ quat_xyzw = Quaternion(
+ x=float(quat_xyzw[0]),
+ y=float(quat_xyzw[1]),
+ z=float(quat_xyzw[2]),
+ w=float(quat_xyzw[3]),
+ )
+ pose_stamped = PoseStamped(
+ header=Header(
+ stamp=self._node.get_clock().now().to_msg(),
+ frame_id=(
+ frame_id if frame_id is not None else self.__base_link_name
+ ),
+ ),
+ pose=Pose(position=position, orientation=quat_xyzw),
+ )
+
+ msg = CollisionObject(
+ header=pose_stamped.header,
+ id=id,
+ operation=operation,
+ pose=pose_stamped.pose,
+ )
+
+ if filepath is not None:
+ mesh = trimesh.load(filepath)
+
+ # Scale the mesh
+ if isinstance(scale, float):
+ scale = (scale, scale, scale)
+ if not (scale[0] == scale[1] == scale[2] == 1.0):
+ # If the mesh was passed in as a parameter, make a copy of it to
+ # avoid transforming the original.
+ if filepath is not None:
+ mesh = mesh.copy()
+ # Transform the mesh
+ transform = np.eye(4)
+ np.fill_diagonal(transform, scale)
+ mesh.apply_transform(transform)
+
+ msg.meshes.append(
+ Mesh(
+ triangles=[MeshTriangle(vertex_indices=face) for face in mesh.faces],
+ vertices=[
+ Point(x=vert[0], y=vert[1], z=vert[2]) for vert in mesh.vertices
+ ],
+ )
+ )
+
+ self.__collision_object_publisher.publish(msg)
+
+ def remove_collision_object(self, id: str):
+ """
+ Remove collision object specified by its `id`.
+ """
+
+ msg = CollisionObject()
+ msg.id = id
+ msg.operation = CollisionObject.REMOVE
+ msg.header.stamp = self._node.get_clock().now().to_msg()
+ self.__collision_object_publisher.publish(msg)
+
+ def remove_collision_mesh(self, id: str):
+ """
+ Remove collision mesh specified by its `id`.
+ Identical to `remove_collision_object()`.
+ """
+
+ self.remove_collision_object(id)
+
+ def attach_collision_object(
+ self,
+ id: str,
+ link_name: Optional[str] = None,
+ touch_links: List[str] = [],
+ weight: float = 0.0,
+ ):
+ """
+ Attach collision object to the robot.
+ """
+
+ if link_name is None:
+ link_name = self.__end_effector_name
+
+ msg = AttachedCollisionObject(
+ object=CollisionObject(id=id, operation=CollisionObject.ADD)
+ )
+ msg.link_name = link_name
+ msg.touch_links = touch_links
+ msg.weight = weight
+
+ self.__attached_collision_object_publisher.publish(msg)
+
+ def detach_collision_object(self, id: int):
+ """
+ Detach collision object from the robot.
+ """
+
+ msg = AttachedCollisionObject(
+ object=CollisionObject(id=id, operation=CollisionObject.REMOVE)
+ )
+ self.__attached_collision_object_publisher.publish(msg)
+
+ def detach_all_collision_objects(self):
+ """
+ Detach collision object from the robot.
+ """
+
+ msg = AttachedCollisionObject(
+ object=CollisionObject(operation=CollisionObject.REMOVE)
+ )
+ self.__attached_collision_object_publisher.publish(msg)
+
+ def move_collision(
+ self,
+ id: str,
+ position: Union[Point, Tuple[float, float, float]],
+ quat_xyzw: Union[Quaternion, Tuple[float, float, float, float]],
+ frame_id: Optional[str] = None,
+ ):
+ """
+ Move collision object specified by its `id`.
+ """
+
+ msg = CollisionObject()
+
+ if not isinstance(position, Point):
+ position = Point(
+ x=float(position[0]), y=float(position[1]), z=float(position[2])
+ )
+ if not isinstance(quat_xyzw, Quaternion):
+ quat_xyzw = Quaternion(
+ x=float(quat_xyzw[0]),
+ y=float(quat_xyzw[1]),
+ z=float(quat_xyzw[2]),
+ w=float(quat_xyzw[3]),
+ )
+
+ pose = Pose()
+ pose.position = position
+ pose.orientation = quat_xyzw
+ msg.pose = pose
+ msg.id = id
+ msg.operation = CollisionObject.MOVE
+ msg.header.frame_id = (
+ frame_id if frame_id is not None else self.__base_link_name
+ )
+ msg.header.stamp = self._node.get_clock().now().to_msg()
+
+ self.__collision_object_publisher.publish(msg)
+
+ def update_planning_scene(self) -> bool:
+ """
+ Gets the current planning scene. Returns whether the service call was
+ successful.
+ """
+
+ if not self._get_planning_scene_service.service_is_ready():
+ self._node.get_logger().warn(
+ f"Service '{self._get_planning_scene_service.srv_name}' is not yet available. Better luck next time!"
+ )
+ return False
+ self.__planning_scene = self._get_planning_scene_service.call(
+ GetPlanningScene.Request()
+ ).scene
+ return True
+
+ def allow_collisions(self, id: str, allow: bool) -> Optional[Future]:
+ """
+ Takes in the ID of an element in the planning scene. Modifies the allowed
+ collision matrix to (dis)allow collisions between that object and all other
+ object.
+
+ If `allow` is True, a plan will succeed even if the robot collides with that object.
+ If `allow` is False, a plan will fail if the robot collides with that object.
+ Returns whether it successfully updated the allowed collision matrix.
+
+ Returns the future of the service call.
+ """
+ # Update the planning scene
+ if not self.update_planning_scene():
+ return None
+ allowed_collision_matrix = self.__planning_scene.allowed_collision_matrix
+ self.__old_allowed_collision_matrix = copy.deepcopy(allowed_collision_matrix)
+
+ # Get the location in the allowed collision matrix of the object
+ j = None
+ if id not in allowed_collision_matrix.entry_names:
+ allowed_collision_matrix.entry_names.append(id)
+ else:
+ j = allowed_collision_matrix.entry_names.index(id)
+ # For all other objects, (dis)allow collisions with the object with `id`
+ for i in range(len(allowed_collision_matrix.entry_values)):
+ if j is None:
+ allowed_collision_matrix.entry_values[i].enabled.append(allow)
+ elif i != j:
+ allowed_collision_matrix.entry_values[i].enabled[j] = allow
+ # For the object with `id`, (dis)allow collisions with all other objects
+ allowed_collision_entry = AllowedCollisionEntry(
+ enabled=[allow for _ in range(len(allowed_collision_matrix.entry_names))]
+ )
+ if j is None:
+ allowed_collision_matrix.entry_values.append(allowed_collision_entry)
+ else:
+ allowed_collision_matrix.entry_values[j] = allowed_collision_entry
+
+ # Apply the new planning scene
+ if not self._apply_planning_scene_service.service_is_ready():
+ self._node.get_logger().warn(
+ f"Service '{self._apply_planning_scene_service.srv_name}' is not yet available. Better luck next time!"
+ )
+ return None
+ return self._apply_planning_scene_service.call_async(
+ ApplyPlanningScene.Request(scene=self.__planning_scene)
+ )
+
+ def process_allow_collision_future(self, future: Future) -> bool:
+ """
+ Return whether the allow collision service call is done and has succeeded
+ or not. If it failed, reset the allowed collision matrix to the old one.
+ """
+ if not future.done():
+ return False
+
+ # Get response
+ resp = future.result()
+
+ # If it failed, restore the old planning scene
+ if not resp.success:
+ self.__planning_scene.allowed_collision_matrix = (
+ self.__old_allowed_collision_matrix
+ )
+
+ return resp.success
+
+ def clear_all_collision_objects(self) -> Optional[Future]:
+ """
+ Removes all attached and un-attached collision objects from the planning scene.
+
+ Returns a future for the ApplyPlanningScene service call.
+ """
+ # Update the planning scene
+ if not self.update_planning_scene():
+ return None
+ self.__old_planning_scene = copy.deepcopy(self.__planning_scene)
+
+ # Remove all collision objects from the planning scene
+ self.__planning_scene.world.collision_objects = []
+ self.__planning_scene.robot_state.attached_collision_objects = []
+
+ # Apply the new planning scene
+ if not self._apply_planning_scene_service.service_is_ready():
+ self._node.get_logger().warn(
+ f"Service '{self._apply_planning_scene_service.srv_name}' is not yet available. Better luck next time!"
+ )
+ return None
+ return self._apply_planning_scene_service.call_async(
+ ApplyPlanningScene.Request(scene=self.__planning_scene)
+ )
+
+ def cancel_clear_all_collision_objects_future(self, future: Future):
+ """
+ Cancel the clear all collision objects service call.
+ """
+ self._apply_planning_scene_service.remove_pending_request(future)
+
+ def process_clear_all_collision_objects_future(self, future: Future) -> bool:
+ """
+ Return whether the clear all collision objects service call is done and has succeeded
+ or not. If it failed, restore the old planning scene.
+ """
+ if not future.done():
+ return False
+
+ # Get response
+ resp = future.result()
+
+ # If it failed, restore the old planning scene
+ if not resp.success:
+ self.__planning_scene = self.__old_planning_scene
+
+ return resp.success
+
+ def __joint_state_callback(self, msg: JointState):
+ # Update only if all relevant joints are included in the message
+ for joint_name in self.joint_names:
+ if not joint_name in msg.name:
+ return
+
+ self.__joint_state_mutex.acquire()
+ self.__joint_state = msg
+ self.__new_joint_state_available = True
+ self.__joint_state_mutex.release()
+
+ def _plan_kinematic_path(self) -> Optional[Future]:
+ # Reuse request from move action goal
+ self.__kinematic_path_request.motion_plan_request = (
+ self.__move_action_goal.request
+ )
+
+ stamp = self._node.get_clock().now().to_msg()
+ self.__kinematic_path_request.motion_plan_request.workspace_parameters.header.stamp = (
+ stamp
+ )
+ for (
+ constraints
+ ) in self.__kinematic_path_request.motion_plan_request.goal_constraints:
+ for position_constraint in constraints.position_constraints:
+ position_constraint.header.stamp = stamp
+ for orientation_constraint in constraints.orientation_constraints:
+ orientation_constraint.header.stamp = stamp
+
+ if not self._plan_kinematic_path_service.service_is_ready():
+ self._node.get_logger().warn(
+ f"Service '{self._plan_kinematic_path_service.srv_name}' is not yet available. Better luck next time!"
+ )
+ return None
+
+ return self._plan_kinematic_path_service.call_async(
+ self.__kinematic_path_request
+ )
+
+ def _plan_cartesian_path(
+ self,
+ max_step: float = 0.0025,
+ frame_id: Optional[str] = None,
+ ) -> Optional[Future]:
+ # Reuse request from move action goal
+ self.__cartesian_path_request.start_state = (
+ self.__move_action_goal.request.start_state
+ )
+
+ # The below attributes were introduced in Iron and do not exist in Humble.
+ if hasattr(self.__cartesian_path_request, "max_velocity_scaling_factor"):
+ self.__cartesian_path_request.max_velocity_scaling_factor = (
+ self.__move_action_goal.request.max_velocity_scaling_factor
+ )
+ if hasattr(self.__cartesian_path_request, "max_acceleration_scaling_factor"):
+ self.__cartesian_path_request.max_acceleration_scaling_factor = (
+ self.__move_action_goal.request.max_acceleration_scaling_factor
+ )
+
+ self.__cartesian_path_request.group_name = (
+ self.__move_action_goal.request.group_name
+ )
+ self.__cartesian_path_request.link_name = self.__end_effector_name
+ self.__cartesian_path_request.max_step = max_step
+
+ self.__cartesian_path_request.header.frame_id = (
+ frame_id if frame_id is not None else self.__base_link_name
+ )
+
+ stamp = self._node.get_clock().now().to_msg()
+ self.__cartesian_path_request.header.stamp = stamp
+
+ self.__cartesian_path_request.path_constraints = (
+ self.__move_action_goal.request.path_constraints
+ )
+ for (
+ position_constraint
+ ) in self.__cartesian_path_request.path_constraints.position_constraints:
+ position_constraint.header.stamp = stamp
+ for (
+ orientation_constraint
+ ) in self.__cartesian_path_request.path_constraints.orientation_constraints:
+ orientation_constraint.header.stamp = stamp
+ # no header in joint_constraint message type
+
+ target_pose = Pose()
+ target_pose.position = (
+ self.__move_action_goal.request.goal_constraints[-1]
+ .position_constraints[-1]
+ .constraint_region.primitive_poses[0]
+ .position
+ )
+ target_pose.orientation = (
+ self.__move_action_goal.request.goal_constraints[-1]
+ .orientation_constraints[-1]
+ .orientation
+ )
+
+ self.__cartesian_path_request.waypoints = [target_pose]
+
+ if not self._plan_cartesian_path_service.service_is_ready():
+ self._node.get_logger().warn(
+ f"Service '{self._plan_cartesian_path_service.srv_name}' is not yet available. Better luck next time!"
+ )
+ return None
+
+ return self._plan_cartesian_path_service.call_async(
+ self.__cartesian_path_request
+ )
+
+ def _send_goal_async_move_action(self):
+ self.__execution_mutex.acquire()
+ stamp = self._node.get_clock().now().to_msg()
+ self.__move_action_goal.request.workspace_parameters.header.stamp = stamp
+ if not self.__move_action_client.server_is_ready():
+ self._node.get_logger().warn(
+ f"Action server '{self.__move_action_client._action_name}' is not yet available. Better luck next time!"
+ )
+ return
+
+ self.__last_error_code = None
+ self.__is_motion_requested = True
+ self.__send_goal_future_move_action = self.__move_action_client.send_goal_async(
+ goal=self.__move_action_goal,
+ feedback_callback=None,
+ )
+
+ self.__send_goal_future_move_action.add_done_callback(
+ self.__response_callback_move_action
+ )
+
+ self.__execution_mutex.release()
+
+ def __response_callback_move_action(self, response):
+ self.__execution_mutex.acquire()
+ goal_handle = response.result()
+ if not goal_handle.accepted:
+ self._node.get_logger().warn(
+ f"Action '{self.__move_action_client._action_name}' was rejected."
+ )
+ self.__is_motion_requested = False
+ return
+
+ self.__execution_goal_handle = goal_handle
+ self.__is_executing = True
+ self.__is_motion_requested = False
+
+ self.__get_result_future_move_action = goal_handle.get_result_async()
+ self.__get_result_future_move_action.add_done_callback(
+ self.__result_callback_move_action
+ )
+ self.__execution_mutex.release()
+
+ def __result_callback_move_action(self, res):
+ self.__execution_mutex.acquire()
+ if res.result().status != GoalStatus.STATUS_SUCCEEDED:
+ self._node.get_logger().warn(
+ f"Action '{self.__move_action_client._action_name}' was unsuccessful: {res.result().status}."
+ )
+ self.motion_suceeded = False
+ else:
+ self.motion_suceeded = True
+
+ self.__last_error_code = res.result().result.error_code
+
+ self.__execution_goal_handle = None
+ self.__is_executing = False
+ self.__execution_mutex.release()
+
+ def _send_goal_async_execute_trajectory(
+ self,
+ goal: ExecuteTrajectory,
+ wait_until_response: bool = False,
+ ):
+ self.__execution_mutex.acquire()
+
+ if not self._execute_trajectory_action_client.server_is_ready():
+ self._node.get_logger().warn(
+ f"Action server '{self._execute_trajectory_action_client._action_name}' is not yet available. Better luck next time!"
+ )
+ return
+
+ self.__last_error_code = None
+ self.__is_motion_requested = True
+ self.__send_goal_future_execute_trajectory = (
+ self._execute_trajectory_action_client.send_goal_async(
+ goal=goal,
+ feedback_callback=None,
+ )
+ )
+
+ self.__send_goal_future_execute_trajectory.add_done_callback(
+ self.__response_callback_execute_trajectory
+ )
+ self.__execution_mutex.release()
+
+ def __response_callback_execute_trajectory(self, response):
+ self.__execution_mutex.acquire()
+ goal_handle = response.result()
+ if not goal_handle.accepted:
+ self._node.get_logger().warn(
+ f"Action '{self._execute_trajectory_action_client._action_name}' was rejected."
+ )
+ self.__is_motion_requested = False
+ return
+
+ self.__execution_goal_handle = goal_handle
+ self.__is_executing = True
+ self.__is_motion_requested = False
+
+ self.__get_result_future_execute_trajectory = goal_handle.get_result_async()
+ self.__get_result_future_execute_trajectory.add_done_callback(
+ self.__result_callback_execute_trajectory
+ )
+ self.__execution_mutex.release()
+
+ def __response_callback_with_event_set_execute_trajectory(self, response):
+ self.__future_done_event.set()
+
+ def __result_callback_execute_trajectory(self, res):
+ self.__execution_mutex.acquire()
+ if res.result().status != GoalStatus.STATUS_SUCCEEDED:
+ self._node.get_logger().warn(
+ f"Action '{self._execute_trajectory_action_client._action_name}' was unsuccessful: {res.result().status}."
+ )
+ self.motion_suceeded = False
+ else:
+ self.motion_suceeded = True
+
+ self.__last_error_code = res.result().result.error_code
+
+ self.__execution_goal_handle = None
+ self.__is_executing = False
+ self.__execution_mutex.release()
+
+ @classmethod
+ def __init_move_action_goal(
+ cls, frame_id: str, group_name: str, end_effector: str
+ ) -> MoveGroup.Goal:
+ move_action_goal = MoveGroup.Goal()
+ move_action_goal.request.workspace_parameters.header.frame_id = frame_id
+ # move_action_goal.request.workspace_parameters.header.stamp = "Set during request"
+ move_action_goal.request.workspace_parameters.min_corner.x = -1.0
+ move_action_goal.request.workspace_parameters.min_corner.y = -1.0
+ move_action_goal.request.workspace_parameters.min_corner.z = -1.0
+ move_action_goal.request.workspace_parameters.max_corner.x = 1.0
+ move_action_goal.request.workspace_parameters.max_corner.y = 1.0
+ move_action_goal.request.workspace_parameters.max_corner.z = 1.0
+ # move_action_goal.request.start_state = "Set during request"
+ move_action_goal.request.goal_constraints = [Constraints()]
+ move_action_goal.request.path_constraints = Constraints()
+ # move_action_goal.request.trajectory_constraints = "Ignored"
+ # move_action_goal.request.reference_trajectories = "Ignored"
+ move_action_goal.request.pipeline_id = ""
+ move_action_goal.request.planner_id = ""
+ move_action_goal.request.group_name = group_name
+ move_action_goal.request.num_planning_attempts = 3
+ move_action_goal.request.allowed_planning_time = 0.5
+ move_action_goal.request.max_velocity_scaling_factor = 0.0
+ move_action_goal.request.max_acceleration_scaling_factor = 0.0
+ # Note: Attribute was renamed in Iron (https://github.com/ros-planning/moveit_msgs/pull/130)
+ if hasattr(move_action_goal.request, "cartesian_speed_limited_link"):
+ move_action_goal.request.cartesian_speed_limited_link = end_effector
+ else:
+ move_action_goal.request.cartesian_speed_end_effector_link = end_effector
+ move_action_goal.request.max_cartesian_speed = 0.0
+
+ # move_action_goal.planning_options.planning_scene_diff = "Ignored"
+ move_action_goal.planning_options.plan_only = False
+ # move_action_goal.planning_options.look_around = "Ignored"
+ # move_action_goal.planning_options.look_around_attempts = "Ignored"
+ # move_action_goal.planning_options.max_safe_execution_cost = "Ignored"
+ # move_action_goal.planning_options.replan = "Ignored"
+ # move_action_goal.planning_options.replan_attempts = "Ignored"
+ # move_action_goal.planning_options.replan_delay = "Ignored"
+
+ return move_action_goal
+
+ def __init_compute_fk(self):
+ self.__compute_fk_client = self._node.create_client(
+ srv_type=GetPositionFK,
+ srv_name="/compute_fk",
+ callback_group=self._callback_group,
+ )
+
+ self.__compute_fk_req = GetPositionFK.Request()
+ self.__compute_fk_req.header.frame_id = self.__base_link_name
+ # self.__compute_fk_req.header.stamp = "Set during request"
+ # self.__compute_fk_req.fk_link_names = "Set during request"
+ # self.__compute_fk_req.robot_state.joint_state = "Set during request"
+ # self.__compute_fk_req.robot_state.multi_dof_ = "Ignored"
+ # self.__compute_fk_req.robot_state.attached_collision_objects = "Ignored"
+ self.__compute_fk_req.robot_state.is_diff = False
+
+ def __init_compute_ik(self):
+ # Service client for IK
+ self.__compute_ik_client = self._node.create_client(
+ srv_type=GetPositionIK,
+ srv_name="/compute_ik",
+ callback_group=self._callback_group,
+ )
+
+ self.__compute_ik_req = GetPositionIK.Request()
+ self.__compute_ik_req.ik_request.group_name = self.__group_name
+ # self.__compute_ik_req.ik_request.robot_state.joint_state = "Set during request"
+ # self.__compute_ik_req.ik_request.robot_state.multi_dof_ = "Ignored"
+ # self.__compute_ik_req.ik_request.robot_state.attached_collision_objects = "Ignored"
+ self.__compute_ik_req.ik_request.robot_state.is_diff = False
+ # self.__compute_ik_req.ik_request.constraints = "Set during request OR Ignored"
+ self.__compute_ik_req.ik_request.avoid_collisions = True
+ # self.__compute_ik_req.ik_request.ik_link_name = "Ignored"
+ self.__compute_ik_req.ik_request.pose_stamped.header.frame_id = (
+ self.__base_link_name
+ )
+ # self.__compute_ik_req.ik_request.pose_stamped.header.stamp = "Set during request"
+ # self.__compute_ik_req.ik_request.pose_stamped.pose = "Set during request"
+ # self.__compute_ik_req.ik_request.ik_link_names = "Ignored"
+ # self.__compute_ik_req.ik_request.pose_stamped_vector = "Ignored"
+ # self.__compute_ik_req.ik_request.timeout.sec = "Ignored"
+ # self.__compute_ik_req.ik_request.timeout.nanosec = "Ignored"
+
+ @property
+ def planning_scene(self) -> Optional[PlanningScene]:
+ return self.__planning_scene
+
+ @property
+ def follow_joint_trajectory_action_client(self) -> str:
+ return self.__follow_joint_trajectory_action_client
+
+ @property
+ def end_effector_name(self) -> str:
+ return self.__end_effector_name
+
+ @property
+ def base_link_name(self) -> str:
+ return self.__base_link_name
+
+ @property
+ def joint_names(self) -> List[str]:
+ return self.__joint_names
+
+ @property
+ def joint_state(self) -> Optional[JointState]:
+ self.__joint_state_mutex.acquire()
+ joint_state = self.__joint_state
+ self.__joint_state_mutex.release()
+ return joint_state
+
+ @property
+ def new_joint_state_available(self):
+ return self.__new_joint_state_available
+
+ @property
+ def max_velocity(self) -> float:
+ return self.__move_action_goal.request.max_velocity_scaling_factor
+
+ @max_velocity.setter
+ def max_velocity(self, value: float):
+ self.__move_action_goal.request.max_velocity_scaling_factor = value
+
+ @property
+ def max_acceleration(self) -> float:
+ return self.__move_action_goal.request.max_acceleration_scaling_factor
+
+ @max_acceleration.setter
+ def max_acceleration(self, value: float):
+ self.__move_action_goal.request.max_acceleration_scaling_factor = value
+
+ @property
+ def num_planning_attempts(self) -> int:
+ return self.__move_action_goal.request.num_planning_attempts
+
+ @num_planning_attempts.setter
+ def num_planning_attempts(self, value: int):
+ self.__move_action_goal.request.num_planning_attempts = value
+
+ @property
+ def allowed_planning_time(self) -> float:
+ return self.__move_action_goal.request.allowed_planning_time
+
+ @allowed_planning_time.setter
+ def allowed_planning_time(self, value: float):
+ self.__move_action_goal.request.allowed_planning_time = value
+
+ @property
+ def cartesian_avoid_collisions(self) -> bool:
+ return self.__cartesian_path_request.request.avoid_collisions
+
+ @cartesian_avoid_collisions.setter
+ def cartesian_avoid_collisions(self, value: bool):
+ self.__cartesian_path_request.avoid_collisions = value
+
+ @property
+ def cartesian_jump_threshold(self) -> float:
+ return self.__cartesian_path_request.request.jump_threshold
+
+ @cartesian_jump_threshold.setter
+ def cartesian_jump_threshold(self, value: float):
+ self.__cartesian_path_request.jump_threshold = value
+
+ @property
+ def cartesian_prismatic_jump_threshold(self) -> float:
+ return self.__cartesian_path_request.request.prismatic_jump_threshold
+
+ @cartesian_prismatic_jump_threshold.setter
+ def cartesian_prismatic_jump_threshold(self, value: float):
+ self.__cartesian_path_request.prismatic_jump_threshold = value
+
+ @property
+ def cartesian_revolute_jump_threshold(self) -> float:
+ return self.__cartesian_path_request.request.revolute_jump_threshold
+
+ @cartesian_revolute_jump_threshold.setter
+ def cartesian_revolute_jump_threshold(self, value: float):
+ self.__cartesian_path_request.revolute_jump_threshold = value
+
+ @property
+ def pipeline_id(self) -> int:
+ return self.__move_action_goal.request.pipeline_id
+
+ @pipeline_id.setter
+ def pipeline_id(self, value: str):
+ self.__move_action_goal.request.pipeline_id = value
+
+ @property
+ def planner_id(self) -> int:
+ return self.__move_action_goal.request.planner_id
+
+ @planner_id.setter
+ def planner_id(self, value: str):
+ self.__move_action_goal.request.planner_id = value
+
+
+def init_joint_state(
+ joint_names: List[str],
+ joint_positions: Optional[List[str]] = None,
+ joint_velocities: Optional[List[str]] = None,
+ joint_effort: Optional[List[str]] = None,
+) -> JointState:
+ joint_state = JointState()
+
+ joint_state.name = joint_names
+ joint_state.position = (
+ joint_positions if joint_positions is not None else [0.0] * len(joint_names)
+ )
+ joint_state.velocity = (
+ joint_velocities if joint_velocities is not None else [0.0] * len(joint_names)
+ )
+ joint_state.effort = (
+ joint_effort if joint_effort is not None else [0.0] * len(joint_names)
+ )
+
+ return joint_state
+
+
+def init_execute_trajectory_goal(
+ joint_trajectory: JointTrajectory,
+) -> Optional[ExecuteTrajectory.Goal]:
+ if joint_trajectory is None:
+ return None
+
+ execute_trajectory_goal = ExecuteTrajectory.Goal()
+
+ execute_trajectory_goal.trajectory.joint_trajectory = joint_trajectory
+
+ return execute_trajectory_goal
+
+
+def init_dummy_joint_trajectory_from_state(
+ joint_state: JointState, duration_sec: int = 0, duration_nanosec: int = 0
+) -> JointTrajectory:
+ joint_trajectory = JointTrajectory()
+ joint_trajectory.joint_names = joint_state.name
+
+ point = JointTrajectoryPoint()
+ point.positions = joint_state.position
+ point.velocities = joint_state.velocity
+ point.accelerations = [0.0] * len(joint_trajectory.joint_names)
+ point.effort = joint_state.effort
+ point.time_from_start.sec = duration_sec
+ point.time_from_start.nanosec = duration_nanosec
+ joint_trajectory.points.append(point)
+
+ return joint_trajectory
diff --git a/unilabos/devices/ros_dev/moveit_interface.py b/unilabos/devices/ros_dev/moveit_interface.py
new file mode 100644
index 0000000..d065403
--- /dev/null
+++ b/unilabos/devices/ros_dev/moveit_interface.py
@@ -0,0 +1,384 @@
+import json
+import time
+from copy import deepcopy
+from pathlib import Path
+
+from moveit_msgs.msg import JointConstraint, Constraints
+from rclpy.action import ActionClient
+from tf2_ros import Buffer, TransformListener
+from unilabos_msgs.action import SendCmd
+
+from unilabos.devices.ros_dev.moveit2 import MoveIt2
+from unilabos.ros.nodes.base_device_node import BaseROS2DeviceNode
+
+
+class MoveitInterface:
+ _ros_node: BaseROS2DeviceNode
+ tf_buffer: Buffer
+ tf_listener: TransformListener
+
+ def __init__(self, moveit_type, joint_poses, rotation=None, device_config=None):
+ self.device_config = device_config
+ self.rotation = rotation
+ self.data_config = json.load(
+ open(
+ f"{Path(__file__).parent.parent.parent.absolute()}/device_mesh/devices/{moveit_type}/config/move_group.json",
+ encoding="utf-8",
+ )
+ )
+ self.arm_move_flag = False
+ self.move_option = ["pick", "place", "side_pick", "side_place"]
+ self.joint_poses = joint_poses
+ self.cartesian_flag = False
+ self.mesh_group = ["reactor", "sample", "beaker"]
+ self.moveit2 = {}
+ self.resource_action = None
+ self.resource_client = None
+ self.resource_action_ok = False
+
+
+ def post_init(self, ros_node: BaseROS2DeviceNode):
+ self._ros_node = ros_node
+ self.tf_buffer = Buffer()
+ self.tf_listener = TransformListener(self.tf_buffer, self._ros_node)
+
+ for move_group, config in self.data_config.items():
+
+ base_link_name = f"{self._ros_node.device_id}_{config['base_link_name']}"
+ end_effector_name = f"{self._ros_node.device_id}_{config['end_effector_name']}"
+ joint_names = [f"{self._ros_node.device_id}_{name}" for name in config["joint_names"]]
+
+ self.moveit2[f"{move_group}"] = MoveIt2(
+ node=self._ros_node,
+ joint_names=joint_names,
+ base_link_name=base_link_name,
+ end_effector_name=end_effector_name,
+ group_name=f"{self._ros_node.device_id}_{move_group}",
+ callback_group=self._ros_node.callback_group,
+ use_move_group_action=True,
+ ignore_new_calls_while_executing=True,
+ )
+ self.moveit2[f"{move_group}"].allowed_planning_time = 3.0
+
+ self._ros_node.create_timer(1, self.wait_for_resource_action, callback_group=self._ros_node.callback_group)
+
+
+ def wait_for_resource_action(self):
+ if not self.resource_action_ok:
+
+ while self.resource_action is None:
+ self.resource_action = self.check_tf_update_actions()
+ time.sleep(1)
+ self.resource_client = ActionClient(self._ros_node, SendCmd, self.resource_action)
+ self.resource_action_ok = True
+ while not self.resource_client.wait_for_server(timeout_sec=5.0):
+ self._ros_node.lab_logger().info("等待 TfUpdate 服务器...")
+
+ def check_tf_update_actions(self):
+ topics = self._ros_node.get_topic_names_and_types()
+ for topic_item in topics:
+ topic_name, topic_types = topic_item
+ if "action_msgs/msg/GoalStatusArray" in topic_types:
+ # 删除 /_action/status 部分
+
+ base_name = topic_name.replace("/_action/status", "")
+ # 检查最后一个部分是否为 tf_update
+ parts = base_name.split("/")
+ if parts and parts[-1] == "tf_update":
+ return base_name
+
+ return None
+
+ def set_position(self, command):
+ """使用moveit 移动到指定点
+ Args:
+ command: A JSON-formatted string that includes quaternion, speed, position
+
+ position (list) : 点的位置 [x,y,z]
+ quaternion (list) : 点的姿态(四元数) [x,y,z,w]
+ move_group (string) : The move group moveit will plan
+ speed (float) : The speed of the movement, speed > 0
+ retry (int) : Retry times when moveit plan fails
+
+ Returns:
+ None
+ """
+
+ result = SendCmd.Result()
+ cmd_str = command.replace("'", '"')
+ cmd_dict = json.loads(cmd_str)
+ self.moveit_task(**cmd_dict)
+ return result
+
+ def moveit_task(
+ self, move_group, position, quaternion, speed=1, retry=10, cartesian=False, target_link=None, offsets=[0, 0, 0]
+ ):
+
+ speed_ = float(max(0.1, min(speed, 1)))
+
+ self.moveit2[move_group].max_velocity = speed_
+ self.moveit2[move_group].max_acceleration = speed_
+
+ re_ = False
+
+ pose_result = [x + y for x, y in zip(position, offsets)]
+ # print(pose_result)
+
+ while retry > -1 and not re_:
+
+ self.moveit2[move_group].move_to_pose(
+ target_link=target_link,
+ position=pose_result,
+ quat_xyzw=quaternion,
+ cartesian=cartesian,
+ # cartesian_fraction_threshold=0.0,
+ cartesian_max_step=0.01,
+ weight_position=1.0,
+ )
+ re_ = self.moveit2[move_group].wait_until_executed()
+ retry += -1
+
+ return re_
+
+ def moveit_joint_task(self, move_group, joint_positions, joint_names=None, speed=1, retry=10):
+
+ re_ = False
+
+ joint_positions_ = [float(x) for x in joint_positions]
+
+ speed_ = float(max(0.1, min(speed, 1)))
+
+ self.moveit2[move_group].max_velocity = speed_
+ self.moveit2[move_group].max_acceleration = speed_
+
+ while retry > -1 and not re_:
+
+ self.moveit2[move_group].move_to_configuration(joint_positions=joint_positions_, joint_names=joint_names)
+ re_ = self.moveit2[move_group].wait_until_executed()
+
+ retry += -1
+ print(self.moveit2[move_group].compute_fk(joint_positions))
+ return re_
+
+ def resource_manager(self, resource, parent_link):
+ goal_msg = SendCmd.Goal()
+ str_dict = {}
+ str_dict[resource] = parent_link
+
+ goal_msg.command = json.dumps(str_dict)
+ assert self.resource_client is not None
+ self.resource_client.send_goal(goal_msg)
+
+ return True
+
+ def pick_and_place(self, command: str):
+ """
+ Using MoveIt to make the robotic arm pick or place materials to a target point.
+
+ Args:
+ command: A JSON-formatted string that includes option, target, speed, lift_height, mt_height
+
+ *option (string) : Action type: pick/place/side_pick/side_place
+ *move_group (string): The move group moveit will plan
+ *status(string) : Target pose
+ resource(string) : The target resource
+ x_distance (float) : The distance to the target in x direction(meters)
+ y_distance (float) : The distance to the target in y direction(meters)
+ lift_height (float) : The height at which the material should be lifted(meters)
+ retry (float) : Retry times when moveit plan fails
+ speed (float) : The speed of the movement, speed > 0
+ Returns:
+ None
+ """
+ result = SendCmd.Result()
+
+ try:
+ cmd_str = str(command).replace("'", '"')
+ cmd_dict = json.loads(cmd_str)
+
+ if cmd_dict["option"] in self.move_option:
+ option_index = self.move_option.index(cmd_dict["option"])
+ place_flag = option_index % 2
+
+ config = {}
+ function_list = []
+
+ status = cmd_dict["status"]
+ joint_positions_ = self.joint_poses[cmd_dict["move_group"]][status]
+
+ config.update({k: cmd_dict[k] for k in ["speed", "retry", "move_group"] if k in cmd_dict})
+
+ # 夹取
+ if not place_flag:
+ if "target" in cmd_dict.keys():
+ function_list.append(lambda: self.resource_manager(cmd_dict["resource"], cmd_dict["target"]))
+ else:
+ function_list.append(
+ lambda: self.resource_manager(
+ cmd_dict["resource"], self.moveit2[cmd_dict["move_group"]].end_effector_name
+ )
+ )
+ else:
+ function_list.append(lambda: self.resource_manager(cmd_dict["resource"], "world"))
+
+ constraints = []
+ if "constraints" in cmd_dict.keys():
+
+ for i in range(len(cmd_dict["constraints"])):
+ v = float(cmd_dict["constraints"][i])
+ if v > 0:
+ constraints.append(
+ JointConstraint(
+ joint_name=self.moveit2[cmd_dict["move_group"]].joint_names[i],
+ position=joint_positions_[i],
+ tolerance_above=v,
+ tolerance_below=v,
+ weight=1.0,
+ )
+ )
+
+ if "lift_height" in cmd_dict.keys():
+ retval = None
+ retry = config.get("retry", 10)
+ while retval is None and retry > 0:
+ retval = self.moveit2[cmd_dict["move_group"]].compute_fk(joint_positions_)
+ time.sleep(0.1)
+ retry -= 1
+ if retval is None:
+ result.success = False
+ return result
+ pose = [retval.pose.position.x, retval.pose.position.y, retval.pose.position.z]
+ quaternion = [
+ retval.pose.orientation.x,
+ retval.pose.orientation.y,
+ retval.pose.orientation.z,
+ retval.pose.orientation.w,
+ ]
+
+ function_list = [
+ lambda: self.moveit_task(
+ position=[retval.pose.position.x, retval.pose.position.y, retval.pose.position.z],
+ quaternion=quaternion,
+ **config,
+ cartesian=self.cartesian_flag,
+ )
+ ] + function_list
+
+ pose[2] += float(cmd_dict["lift_height"])
+ function_list.append(
+ lambda: self.moveit_task(
+ position=pose, quaternion=quaternion, **config, cartesian=self.cartesian_flag
+ )
+ )
+ end_pose = pose
+
+ if "x_distance" in cmd_dict.keys() or "y_distance" in cmd_dict.keys():
+ if "x_distance" in cmd_dict.keys():
+ deep_pose = deepcopy(pose)
+ deep_pose[0] += float(cmd_dict["x_distance"])
+ elif "y_distance" in cmd_dict.keys():
+ deep_pose = deepcopy(pose)
+ deep_pose[1] += float(cmd_dict["y_distance"])
+
+ function_list = [
+ lambda: self.moveit_task(
+ position=pose, quaternion=quaternion, **config, cartesian=self.cartesian_flag
+ )
+ ] + function_list
+ function_list.append(
+ lambda: self.moveit_task(
+ position=deep_pose, quaternion=quaternion, **config, cartesian=self.cartesian_flag
+ )
+ )
+ end_pose = deep_pose
+
+ retval_ik = None
+ retry = config.get("retry", 10)
+ while retval_ik is None and retry > 0:
+ retval_ik = self.moveit2[cmd_dict["move_group"]].compute_ik(
+ position=end_pose, quat_xyzw=quaternion, constraints=Constraints(joint_constraints=constraints)
+ )
+ time.sleep(0.1)
+ retry -= 1
+ if retval_ik is None:
+ result.success = False
+ return result
+ position_ = [
+ retval_ik.position[retval_ik.name.index(i)]
+ for i in self.moveit2[cmd_dict["move_group"]].joint_names
+ ]
+ function_list = [
+ lambda: self.moveit_joint_task(
+ joint_positions=position_,
+ joint_names=self.moveit2[cmd_dict["move_group"]].joint_names,
+ **config,
+ )
+ ] + function_list
+ else:
+ function_list = [
+ lambda: self.moveit_joint_task(**config, joint_positions=joint_positions_)
+ ] + function_list
+
+ for i in range(len(function_list)):
+ if i == 0:
+ self.cartesian_flag = False
+ else:
+ self.cartesian_flag = True
+
+ re = function_list[i]()
+ if not re:
+ print(i, re)
+ result.success = False
+ return result
+ result.success = True
+
+ except Exception as e:
+ print(e)
+ self.cartesian_flag = False
+ result.success = False
+
+ return result
+
+ def set_status(self, command: str):
+ """
+ Goto home position
+
+ Args:
+ command: A JSON-formatted string that includes speed
+ *status (string) : The joint status moveit will plan
+ *move_group (string): The move group moveit will plan
+ separate (list) : The joint index to be separated
+ lift_height (float) : The height at which the material should be lifted(meters)
+ x_distance (float) : The distance to the target in x direction(meters)
+ y_distance (float) : The distance to the target in y direction(meters)
+ speed (float) : The speed of the movement, speed > 0
+ retry (float) : Retry times when moveit plan fails
+
+ Returns:
+ None
+ """
+
+ result = SendCmd.Result()
+
+ try:
+ cmd_str = command.replace("'", '"')
+ cmd_dict = json.loads(cmd_str)
+ config = {}
+ config["move_group"] = cmd_dict["move_group"]
+ if "speed" in cmd_dict.keys():
+ config["speed"] = cmd_dict["speed"]
+ if "retry" in cmd_dict.keys():
+ config["retry"] = cmd_dict["retry"]
+
+ status = cmd_dict["status"]
+ joint_positions_ = self.joint_poses[cmd_dict["move_group"]][status]
+ re = self.moveit_joint_task(**config, joint_positions=joint_positions_)
+ if not re:
+ result.success = False
+ return result
+ result.success = True
+ except Exception as e:
+ print(e)
+ result.success = False
+
+ return result
diff --git a/unilabos/registry/device_comms/modbus_ioboard.yaml b/unilabos/registry/device_comms/modbus_ioboard.yaml
index 1473241..b1d04ee 100644
--- a/unilabos/registry/device_comms/modbus_ioboard.yaml
+++ b/unilabos/registry/device_comms/modbus_ioboard.yaml
@@ -5,6 +5,6 @@ io_snrd:
type: python
hardware_interface:
name: modbus_client
- extra_info: address
+ extra_info: []
read: read_io_coil
write: write_io_coil
\ No newline at end of file
diff --git a/unilabos/registry/devices/hotel.yaml b/unilabos/registry/devices/hotel.yaml
new file mode 100644
index 0000000..0f92511
--- /dev/null
+++ b/unilabos/registry/devices/hotel.yaml
@@ -0,0 +1,9 @@
+hotel.thermo_orbitor_rs2_hotel:
+ description: Thermo Orbitor RS2 Hotel
+ class:
+ module: unilabos.devices.resource_container.container:HotelContainer
+ type: python
+ model:
+ type: device
+ mesh: thermo_orbitor_rs2_hotel
+
diff --git a/unilabos/registry/devices/liquid_handler.yaml b/unilabos/registry/devices/liquid_handler.yaml
index bcddae5..bb94b59 100644
--- a/unilabos/registry/devices/liquid_handler.yaml
+++ b/unilabos/registry/devices/liquid_handler.yaml
@@ -1,5 +1,6 @@
liquid_handler:
description: Liquid handler device controlled by pylabrobot
+ icon: icon_yiyezhan.webp
class:
module: unilabos.devices.liquid_handling.liquid_handler_abstract:LiquidHandlerAbstract
type: python
@@ -22,8 +23,8 @@ liquid_handler:
is_96_well: is_96_well
top: top
none_keys: none_keys
- feedback: { }
- result: { }
+ feedback: {}
+ result: {}
add_liquid:
type: LiquidHandlerAdd
goal:
@@ -43,8 +44,8 @@ liquid_handler:
mix_rate: mix_rate
mix_liquid_height: mix_liquid_height
none_keys: none_keys
- feedback: { }
- result: { }
+ feedback: {}
+ result: {}
transfer_liquid:
type: LiquidHandlerTransfer
goal:
@@ -69,8 +70,8 @@ liquid_handler:
mix_liquid_height: mix_liquid_height
delays: delays
none_keys: none_keys
- feedback: { }
- result: { }
+ feedback: {}
+ result: {}
mix:
type: LiquidHandlerMix
goal:
@@ -81,16 +82,16 @@ liquid_handler:
offsets: offsets
mix_rate: mix_rate
none_keys: none_keys
- feedback: { }
- result: { }
+ feedback: {}
+ result: {}
move_to:
type: LiquidHandlerMoveTo
goal:
well: well
dis_to_top: dis_to_top
channel: channel
- feedback: { }
- result: { }
+ feedback: {}
+ result: {}
aspirate:
type: LiquidHandlerAspirate
goal:
@@ -245,6 +246,21 @@ liquid_handler:
target_vols: target_vols
aspiration_flow_rate: aspiration_flow_rate
dispense_flow_rates: dispense_flow_rates
+ handles:
+ input:
+ - handler_key: liquid-input
+ label: Liquid Input
+ data_type: resource
+ io_type: target
+ data_source: handle
+ data_key: liquid
+ output:
+ - handler_key: liquid-output
+ label: Liquid Output
+ data_type: resource
+ io_type: source
+ data_source: executor
+ data_key: liquid
schema:
type: object
properties:
@@ -272,3 +288,174 @@ liquid_handler.revvity:
status: status
result:
success: success
+
+liquid_handler.biomek:
+ description: Biomek液体处理器设备,基于pylabrobot控制
+ icon: icon_yiyezhan.webp
+ class:
+ module: unilabos.devices.liquid_handling.biomek:LiquidHandlerBiomek
+ type: python
+ status_types: {}
+ action_value_mappings:
+ create_protocol:
+ type: LiquidHandlerProtocolCreation
+ goal:
+ protocol_name: protocol_name
+ protocol_description: protocol_description
+ protocol_version: protocol_version
+ protocol_author: protocol_author
+ protocol_date: protocol_date
+ protocol_type: protocol_type
+ none_keys: none_keys
+ feedback: {}
+ result: {}
+ run_protocol:
+ type: EmptyIn
+ goal: {}
+ feedback: {}
+ result: {}
+ transfer_liquid:
+ type: LiquidHandlerTransfer
+ goal:
+ asp_vols: asp_vols
+ dis_vols: dis_vols
+ sources: sources
+ targets: targets
+ tip_racks: tip_racks
+ use_channels: use_channels
+ asp_flow_rates: asp_flow_rates
+ dis_flow_rates: dis_flow_rates
+ offsets: offsets
+ touch_tip: touch_tip
+ liquid_height: liquid_height
+ blow_out_air_volume: blow_out_air_volume
+ spread: spread
+ is_96_well: is_96_well
+ mix_stage: mix_stage
+ mix_times: mix_times
+ mix_vol: mix_vol
+ mix_rate: mix_rate
+ mix_liquid_height: mix_liquid_height
+ delays: delays
+ none_keys: none_keys
+ feedback: {}
+ result: {}
+ handles:
+ input:
+ - handler_key: liquid-input
+ label: Liquid Input
+ data_type: resource
+ io_type: target
+ data_source: handle
+ data_key: liquid
+ output:
+ - handler_key: liquid-output
+ label: Liquid Output
+ data_type: resource
+ io_type: source
+ data_source: executor
+ data_key: liquid
+ transfer_biomek:
+ type: LiquidHandlerTransferBiomek
+ goal:
+ sources: sources
+ targets: targets
+ tip_rack: tip_rack
+ volume: volume
+ aspirate_techniques: aspirate_techniques
+ dispense_techniques: dispense_techniques
+ feedback: {}
+ result: {}
+ handles:
+ input:
+ - handler_key: sources
+ label: sources
+ data_type: resource
+ data_source: handle
+ data_key: liquid
+ - handler_key: targets
+ label: targets
+ data_type: resource
+ data_source: executor
+ data_key: liquid
+ - handler_key: tip_rack
+ label: tip_rack
+ data_type: resource
+ data_source: executor
+ data_key: liquid
+ output:
+ - handler_key: sources_out
+ label: sources
+ data_type: resource
+ data_source: handle
+ data_key: liquid
+ - handler_key: targets_out
+ label: targets
+ data_type: resource
+ data_source: executor
+ data_key: liquid
+ oscillation_biomek:
+ type: LiquidHandlerOscillateBiomek
+ goal:
+ rpm: rpm
+ time: time
+ feedback: {}
+ result: {}
+ handles:
+ input:
+ - handler_key: plate
+ label: plate
+ data_type: resource
+ data_source: handle
+ data_key: liquid
+ output:
+ - handler_key: plate_out
+ label: plate
+ data_type: resource
+ data_source: handle
+ data_key: liquid
+ move_biomek:
+ type: LiquidHandlerMoveBiomek
+ goal:
+ source: sources
+ target: targets
+ feedback: {}
+ result:
+ name: name
+ handles:
+ input:
+ - handler_key: sources
+ label: sources
+ data_type: resource
+ data_source: handle
+ data_key: liquid
+ output:
+ - handler_key: targets
+ label: targets
+ data_type: resource
+ data_source: handle
+ data_key: liquid
+ incubation_biomek:
+ type: LiquidHandlerIncubateBiomek
+ goal:
+ time: time
+ feedback: {}
+ result: {}
+ handles:
+ input:
+ - handler_key: plate
+ label: plate
+ data_type: resource
+ data_source: handle
+ data_key: liquid
+ output:
+ - handler_key: plate_out
+ label: plate
+ data_type: resource
+ data_source: handle
+ data_key: liquid
+ schema:
+ type: object
+ properties: {}
+ required: []
+ additionalProperties: false
diff --git a/unilabos/registry/devices/moveit_config.yaml b/unilabos/registry/devices/moveit_config.yaml
new file mode 100644
index 0000000..6236855
--- /dev/null
+++ b/unilabos/registry/devices/moveit_config.yaml
@@ -0,0 +1,56 @@
+moveit.toyo_xyz:
+ description: Toyo XYZ
+ class:
+ module: unilabos.devices.ros_dev.moveit_interface:MoveitInterface
+ type: python
+ action_value_mappings:
+ set_position:
+ type: SendCmd
+ goal:
+ command: command
+ feedback: { }
+ result: { }
+ pick_and_place:
+ type: SendCmd
+ goal:
+ command: command
+ feedback: { }
+ result: { }
+ set_status:
+ type: SendCmd
+ goal:
+ command: command
+ feedback: { }
+ result: { }
+
+ model:
+ type: device
+ mesh: toyo_xyz
+
+moveit.arm_slider:
+ description: Arm with Slider
+ model:
+ type: device
+ mesh: arm_slider
+ class:
+ module: unilabos.devices.ros_dev.moveit_interface:MoveitInterface
+ type: python
+ action_value_mappings:
+ set_position:
+ type: SendCmd
+ goal:
+ command: command
+ feedback: {}
+ result: {}
+ pick_and_place:
+ type: SendCmd
+ goal:
+ command: command
+ feedback: {}
+ result: {}
+ set_status:
+ type: SendCmd
+ goal:
+ command: command
+ feedback: {}
+ result: {}
diff --git a/unilabos/registry/devices/pump_and_valve.yaml b/unilabos/registry/devices/pump_and_valve.yaml
index 5fdd860..fd5dd98 100644
--- a/unilabos/registry/devices/pump_and_valve.yaml
+++ b/unilabos/registry/devices/pump_and_valve.yaml
@@ -23,20 +23,51 @@ syringe_pump_with_valve.runze:
type: string
description: The position of the valve
required:
- - status
- - position
- - valve_position
+ - status
+ - position
+ - valve_position
additionalProperties: false
-
solenoid_valve.mock:
description: Mock solenoid valve
class:
module: unilabos.devices.pump_and_valve.solenoid_valve_mock:SolenoidValveMock
type: python
+ status_types:
+ status: String
+ valve_position: String
+ action_value_mappings:
+ open:
+ type: EmptyIn
+ goal: {}
+ feedback: {}
+ result: {}
+ close:
+ type: EmptyIn
+ goal: {}
+ feedback: {}
+ result: {}
+ handles:
+ input:
+ - handler_key: fluid-input
+ label: Fluid Input
+ data_type: fluid
+ output:
+ - handler_key: fluid-output
+ label: Fluid Output
+ data_type: fluid
+ init_param_schema:
+ type: object
+ properties:
+ port:
+ type: string
+ description: "通信端口"
+ default: "COM6"
+ required:
+ - port
solenoid_valve:
description: Solenoid valve
class:
module: unilabos.devices.pump_and_valve.solenoid_valve:SolenoidValve
- type: python
\ No newline at end of file
+ type: python
diff --git a/unilabos/registry/devices/vacuum_and_purge.yaml b/unilabos/registry/devices/vacuum_and_purge.yaml
index 37a62ae..6bdff16 100644
--- a/unilabos/registry/devices/vacuum_and_purge.yaml
+++ b/unilabos/registry/devices/vacuum_and_purge.yaml
@@ -22,6 +22,30 @@ vacuum_pump.mock:
string: string
feedback: {}
result: {}
+ handles:
+ input:
+ - handler_key: fluid-input
+ label: Fluid Input
+ data_type: fluid
+ io_type: target
+ data_source: handle
+ data_key: fluid_in
+ output:
+ - handler_key: fluid-output
+ label: Fluid Output
+ data_type: fluid
+ io_type: source
+ data_source: executor
+ data_key: fluid_out
+ init_param_schema:
+ type: object
+ properties:
+ port:
+ type: string
+ description: "通信端口"
+ default: "COM6"
+ required:
+ - port
gas_source.mock:
description: Mock gas source
@@ -46,4 +70,28 @@ gas_source.mock:
goal:
string: string
feedback: {}
- result: {}
\ No newline at end of file
+ result: {}
+ handles:
+ input:
+ - handler_key: fluid-input
+ label: Fluid Input
+ data_type: fluid
+ io_type: target
+ data_source: handle
+ data_key: fluid_in
+ output:
+ - handler_key: fluid-output
+ label: Fluid Output
+ data_type: fluid
+ io_type: source
+ data_source: executor
+ data_key: fluid_out
+ init_param_schema:
+ type: object
+ properties:
+ port:
+ type: string
+ description: "通信端口"
+ default: "COM6"
+ required:
+ - port
\ No newline at end of file
diff --git a/unilabos/registry/devices/work_station.yaml b/unilabos/registry/devices/work_station.yaml
index fadfd5e..d3a3733 100644
--- a/unilabos/registry/devices/work_station.yaml
+++ b/unilabos/registry/devices/work_station.yaml
@@ -4,4 +4,4 @@ workstation:
module: unilabos.ros.nodes.presets.protocol_node:ROS2ProtocolNode
type: ros2
schema:
- properties: {}
\ No newline at end of file
+ properties: {}
diff --git a/unilabos/registry/registry.py b/unilabos/registry/registry.py
index c68e0d8..03d4899 100644
--- a/unilabos/registry/registry.py
+++ b/unilabos/registry/registry.py
@@ -25,9 +25,7 @@ class Registry:
self.ResourceCreateFromOuterEasy = self._replace_type_with_class(
"ResourceCreateFromOuterEasy", "host_node", f"动作 create_resource"
)
- self.EmptyIn = self._replace_type_with_class(
- "EmptyIn", "host_node", f""
- )
+ self.EmptyIn = self._replace_type_with_class("EmptyIn", "host_node", f"")
self.device_type_registry = {}
self.resource_type_registry = {}
self._setup_called = False # 跟踪setup是否已调用
@@ -66,6 +64,7 @@ class Registry:
"goal_default": yaml.safe_load(
io.StringIO(get_yaml_from_goal_type(self.ResourceCreateFromOuter.Goal))
),
+ "handles": {},
},
"create_resource": {
"type": self.ResourceCreateFromOuterEasy,
@@ -86,6 +85,15 @@ class Registry:
"goal_default": yaml.safe_load(
io.StringIO(get_yaml_from_goal_type(self.ResourceCreateFromOuterEasy.Goal))
),
+ "handles": {
+ "output": [{
+ "handler_key": "labware",
+ "label": "Labware",
+ "data_type": "resource",
+ "data_source": "handle",
+ "data_key": "liquid"
+ }]
+ },
},
"test_latency": {
"type": self.EmptyIn,
@@ -94,11 +102,14 @@ class Registry:
"result": {"latency_ms": "latency_ms", "time_diff_ms": "time_diff_ms"},
"schema": ros_action_to_json_schema(self.EmptyIn),
"goal_default": {},
+ "handles": {},
},
},
},
"icon": "icon_device.webp",
"registry_type": "device",
+ "handles": [],
+ "init_param_schema": {},
"schema": {"properties": {}, "additionalProperties": False, "type": "object"},
"file_path": "/",
}
@@ -132,6 +143,10 @@ class Registry:
resource_info["description"] = ""
if "icon" not in resource_info:
resource_info["icon"] = ""
+ if "handles" not in resource_info:
+ resource_info["handles"] = []
+ if "init_param_schema" not in resource_info:
+ resource_info["init_param_schema"] = {}
resource_info["registry_type"] = "resource"
self.resource_type_registry.update(data)
logger.debug(
@@ -194,6 +209,10 @@ class Registry:
device_config["description"] = ""
if "icon" not in device_config:
device_config["icon"] = ""
+ if "handles" not in device_config:
+ device_config["handles"] = []
+ if "init_param_schema" not in device_config:
+ device_config["init_param_schema"] = {}
device_config["registry_type"] = "device"
if "class" in device_config:
# 处理状态类型
@@ -206,6 +225,8 @@ class Registry:
# 处理动作值映射
if "action_value_mappings" in device_config["class"]:
for action_name, action_config in device_config["class"]["action_value_mappings"].items():
+ if "handles" not in action_config:
+ action_config["handles"] = []
if "type" in action_config:
action_config["type"] = self._replace_type_with_class(
action_config["type"], device_id, f"动作 {action_name}"
diff --git a/unilabos/resources/graphio.py b/unilabos/resources/graphio.py
index 9a31add..cca7a35 100644
--- a/unilabos/resources/graphio.py
+++ b/unilabos/resources/graphio.py
@@ -9,7 +9,7 @@ try:
from pylabrobot.resources.resource import Resource as ResourcePLR
except ImportError:
pass
-
+from typing import Union, get_origin, get_args
physical_setup_graph: nx.Graph = None
@@ -298,7 +298,6 @@ def nested_dict_to_list(nested_dict: dict) -> list[dict]: # FIXME 是tree?
return result
-
def convert_resources_to_type(
resources_list: list[dict], resource_type: type, *, plr_model: bool = False
) -> Union[list[dict], dict, None, "ResourcePLR"]:
@@ -320,9 +319,13 @@ def convert_resources_to_type(
return resource_ulab_to_plr(resources_list, plr_model)
resources_tree = dict_to_tree({r["id"]: r for r in resources_list})
return resource_ulab_to_plr(resources_tree[0], plr_model)
- elif isinstance(resource_type, list) and all(issubclass(t, ResourcePLR) for t in resource_type):
- resources_tree = dict_to_tree({r["id"]: r for r in resources_list})
- return [resource_ulab_to_plr(r, plr_model) for r in resources_tree]
+ elif isinstance(resource_type, list) :
+ if all((get_origin(t) is Union) for t in resource_type):
+ resources_tree = dict_to_tree({r["id"]: r for r in resources_list})
+ return [resource_ulab_to_plr(r, plr_model) for r in resources_tree]
+ elif all(issubclass(t, ResourcePLR) for t in resource_type):
+ resources_tree = dict_to_tree({r["id"]: r for r in resources_list})
+ return [resource_ulab_to_plr(r, plr_model) for r in resources_tree]
else:
return None
@@ -343,9 +346,13 @@ def convert_resources_from_type(resources_list, resource_type: type) -> Union[li
elif isinstance(resource_type, type) and issubclass(resource_type, ResourcePLR):
resources_tree = [resource_plr_to_ulab(resources_list)]
return tree_to_list(resources_tree)
- elif isinstance(resource_type, list) and all(issubclass(t, ResourcePLR) for t in resource_type):
- resources_tree = [resource_plr_to_ulab(r) for r in resources_list]
- return tree_to_list(resources_tree)
+ elif isinstance(resource_type, list) :
+ if all((get_origin(t) is Union) for t in resource_type):
+ resources_tree = [resource_plr_to_ulab(r) for r in resources_list]
+ return tree_to_list(resources_tree)
+ elif all(issubclass(t, ResourcePLR) for t in resource_type):
+ resources_tree = [resource_plr_to_ulab(r) for r in resources_list]
+ return tree_to_list(resources_tree)
else:
return None
diff --git a/unilabos/ros/main_slave_run.py b/unilabos/ros/main_slave_run.py
index c4c5a17..bbd6359 100644
--- a/unilabos/ros/main_slave_run.py
+++ b/unilabos/ros/main_slave_run.py
@@ -6,9 +6,9 @@ import time
from typing import Optional, Dict, Any, List
import rclpy
-from unilabos.ros.nodes.presets.joint_republisher import JointRepublisher
from unilabos.ros.nodes.presets.resource_mesh_manager import ResourceMeshManager
from unilabos.ros.nodes.resource_tracker import DeviceNodeResourceTracker
+from unilabos.devices.ros_dev.liquid_handler_joint_publisher import LiquidHandlerJointPublisher
from unilabos_msgs.msg import Resource # type: ignore
from unilabos_msgs.srv import ResourceAdd, SerialCommand # type: ignore
from rclpy.executors import MultiThreadedExecutor
@@ -69,19 +69,23 @@ def main(
)
if visual != "disable":
+ from unilabos.ros.nodes.presets.joint_republisher import JointRepublisher
+
resource_mesh_manager = ResourceMeshManager(
resources_mesh_config,
resources_config,
- resource_tracker= DeviceNodeResourceTracker(),
+ resource_tracker = host_node.resource_tracker,
device_id = 'resource_mesh_manager',
)
joint_republisher = JointRepublisher(
'joint_republisher',
- DeviceNodeResourceTracker()
+ host_node.resource_tracker
)
-
+ lh_joint_pub = LiquidHandlerJointPublisher(resources_config=resources_config,
+ resource_tracker=host_node.resource_tracker)
executor.add_node(resource_mesh_manager)
executor.add_node(joint_republisher)
+ executor.add_node(lh_joint_pub)
thread = threading.Thread(target=executor.spin, daemon=True, name="host_executor_thread")
thread.start()
@@ -121,6 +125,7 @@ def slave(
executor.add_node(n)
if visual != "disable":
+ from unilabos.ros.nodes.presets.joint_republisher import JointRepublisher
resource_mesh_manager = ResourceMeshManager(
resources_mesh_config,
resources_config,
diff --git a/unilabos/ros/msgs/message_converter.py b/unilabos/ros/msgs/message_converter.py
index 11c7afd..62ab606 100644
--- a/unilabos/ros/msgs/message_converter.py
+++ b/unilabos/ros/msgs/message_converter.py
@@ -131,7 +131,7 @@ _msg_converter: Dict[Type, Any] = {
Bool: lambda x: Bool(data=bool(x)),
str: str,
String: lambda x: String(data=str(x)),
- Point: lambda x: Point(x=x.x, y=x.y, z=x.z),
+ Point: lambda x: Point(x=x.x, y=x.y, z=x.z) if not isinstance(x, dict) else Point(x=x.get("x", 0.0), y=x.get("y", 0.0), z=x.get("z", 0.0)),
Resource: lambda x: Resource(
id=x.get("id", ""),
name=x.get("name", ""),
@@ -141,7 +141,7 @@ _msg_converter: Dict[Type, Any] = {
type=x.get("type", ""),
category=x.get("class", "") or x.get("type", ""),
pose=(
- Pose(position=Point(x=float(x.get("position", {}).get("x", 0)), y=float(x.get("position", {}).get("y", 0)), z=float(x.get("position", {}).get("z", 0))))
+ Pose(position=Point(x=float(x.get("position", {}).get("x", 0.0)), y=float(x.get("position", {}).get("y", 0.0)), z=float(x.get("position", {}).get("z", 0.0))))
if x.get("position", None) is not None
else Pose()
),
diff --git a/unilabos/ros/nodes/base_device_node.py b/unilabos/ros/nodes/base_device_node.py
index 28b67aa..eafdd71 100644
--- a/unilabos/ros/nodes/base_device_node.py
+++ b/unilabos/ros/nodes/base_device_node.py
@@ -1,5 +1,4 @@
import copy
-import functools
import json
import threading
import time
@@ -20,16 +19,29 @@ from rclpy.service import Service
from unilabos_msgs.action import SendCmd
from unilabos_msgs.srv._serial_command import SerialCommand_Request, SerialCommand_Response
-from unilabos.resources.graphio import convert_resources_to_type, convert_resources_from_type, resource_ulab_to_plr, \
- initialize_resources, list_to_nested_dict, dict_to_tree, resource_plr_to_ulab, tree_to_list
+from unilabos.resources.graphio import (
+ convert_resources_to_type,
+ convert_resources_from_type,
+ resource_ulab_to_plr,
+ initialize_resources,
+ dict_to_tree,
+ resource_plr_to_ulab,
+ tree_to_list,
+)
from unilabos.ros.msgs.message_converter import (
convert_to_ros_msg,
convert_from_ros_msg,
convert_from_ros_msg_with_mapping,
- convert_to_ros_msg_with_mapping, ros_action_to_json_schema,
+ convert_to_ros_msg_with_mapping,
)
-from unilabos_msgs.srv import ResourceAdd, ResourceGet, ResourceDelete, ResourceUpdate, ResourceList, \
- SerialCommand # type: ignore
+from unilabos_msgs.srv import (
+ ResourceAdd,
+ ResourceGet,
+ ResourceDelete,
+ ResourceUpdate,
+ ResourceList,
+ SerialCommand,
+) # type: ignore
from unilabos_msgs.msg import Resource # type: ignore
from unilabos.ros.nodes.resource_tracker import DeviceNodeResourceTracker
@@ -37,7 +49,7 @@ from unilabos.ros.x.rclpyx import get_event_loop
from unilabos.ros.utils.driver_creator import ProtocolNodeCreator, PyLabRobotCreator, DeviceClassCreator
from unilabos.utils.async_util import run_async_func
from unilabos.utils.log import info, debug, warning, error, critical, logger
-from unilabos.utils.type_check import get_type_class, TypeEncoder
+from unilabos.utils.type_check import get_type_class, TypeEncoder, serialize_result_info
T = TypeVar("T")
@@ -292,7 +304,9 @@ class BaseROS2DeviceNode(Node, Generic[T]):
self.create_ros_action_server(action_name, action_value_mapping)
# 创建线程池执行器
- self._executor = ThreadPoolExecutor(max_workers=max(len(action_value_mappings), 1), thread_name_prefix=f"ROSDevice{self.device_id}")
+ self._executor = ThreadPoolExecutor(
+ max_workers=max(len(action_value_mappings), 1), thread_name_prefix=f"ROSDevice{self.device_id}"
+ )
# 创建资源管理客户端
self._resource_clients: Dict[str, Client] = {
@@ -329,12 +343,14 @@ class BaseROS2DeviceNode(Node, Generic[T]):
ADD_LIQUID_TYPE = other_calling_param.pop("ADD_LIQUID_TYPE", [])
LIQUID_VOLUME = other_calling_param.pop("LIQUID_VOLUME", [])
LIQUID_INPUT_SLOT = other_calling_param.pop("LIQUID_INPUT_SLOT", [])
- slot = other_calling_param.pop("slot", -1)
- if slot >= 0: # slot为负数的时候采用assign方法
+ slot = other_calling_param.pop("slot", "-1")
+ if slot != "-1": # slot为负数的时候采用assign方法
other_calling_param["slot"] = slot
# 本地拿到这个物料,可能需要先做初始化?
if isinstance(resources, list):
- if len(resources) == 1 and isinstance(resources[0], list) and not initialize_full: # 取消,不存在的情况
+ if (
+ len(resources) == 1 and isinstance(resources[0], list) and not initialize_full
+ ): # 取消,不存在的情况
# 预先initialize过,以整组的形式传入
request.resources = [convert_to_ros_msg(Resource, resource_) for resource_ in resources[0]]
elif initialize_full:
@@ -349,6 +365,25 @@ class BaseROS2DeviceNode(Node, Generic[T]):
response = rclient.call(request)
# 应该先add_resource了
res.response = "OK"
+ # 如果driver自己就有assign的方法,那就使用driver自己的assign方法
+ if hasattr(self.driver_instance, "create_resource"):
+ create_resource_func = getattr(self.driver_instance, "create_resource")
+ try:
+ ret = create_resource_func(
+ resource_tracker=self.resource_tracker,
+ resources=request.resources,
+ bind_parent_id=bind_parent_id,
+ bind_location=location,
+ liquid_input_slot=LIQUID_INPUT_SLOT,
+ liquid_type=ADD_LIQUID_TYPE,
+ liquid_volume=LIQUID_VOLUME,
+ slot_on_deck=slot,
+ )
+ res.response = serialize_result_info("", True, ret)
+ except Exception as e:
+ traceback.print_exc()
+ res.response = serialize_result_info(traceback.format_exc(), False, {})
+ return res
# 接下来该根据bind_parent_id进行assign了,目前只有plr可以进行assign,不然没有办法输入到物料系统中
resource = self.resource_tracker.figure_resource({"name": bind_parent_id})
# request.resources = [convert_to_ros_msg(Resource, resources)]
@@ -359,6 +394,7 @@ class BaseROS2DeviceNode(Node, Generic[T]):
from pylabrobot.resources import Coordinate
from pylabrobot.resources import OTDeck
from pylabrobot.resources import Plate
+
contain_model = not isinstance(resource, Deck)
if isinstance(resource, ResourcePLR):
# resources.list()
@@ -366,25 +402,39 @@ class BaseROS2DeviceNode(Node, Generic[T]):
plr_instance = resource_ulab_to_plr(resources_tree[0], contain_model)
if isinstance(plr_instance, Plate):
empty_liquid_info_in = [(None, 0)] * plr_instance.num_items
- for liquid_type, liquid_volume, liquid_input_slot in zip(ADD_LIQUID_TYPE, LIQUID_VOLUME, LIQUID_INPUT_SLOT):
+ for liquid_type, liquid_volume, liquid_input_slot in zip(
+ ADD_LIQUID_TYPE, LIQUID_VOLUME, LIQUID_INPUT_SLOT
+ ):
empty_liquid_info_in[liquid_input_slot] = (liquid_type, liquid_volume)
plr_instance.set_well_liquids(empty_liquid_info_in)
if isinstance(resource, OTDeck) and "slot" in other_calling_param:
+ other_calling_param["slot"] = int(other_calling_param["slot"])
resource.assign_child_at_slot(plr_instance, **other_calling_param)
else:
- _discard_slot = other_calling_param.pop("slot", -1)
- resource.assign_child_resource(plr_instance, Coordinate(location["x"], location["y"], location["z"]), **other_calling_param)
- request2.resources = [convert_to_ros_msg(Resource, r) for r in tree_to_list([resource_plr_to_ulab(resource)])]
+ _discard_slot = other_calling_param.pop("slot", "-1")
+ resource.assign_child_resource(
+ plr_instance,
+ Coordinate(location["x"], location["y"], location["z"]),
+ **other_calling_param,
+ )
+ request2.resources = [
+ convert_to_ros_msg(Resource, r) for r in tree_to_list([resource_plr_to_ulab(resource)])
+ ]
rclient2.call(request2)
# 发送给ResourceMeshManager
action_client = ActionClient(
- self, SendCmd, "/devices/resource_mesh_manager/add_resource_mesh", callback_group=self.callback_group
+ self,
+ SendCmd,
+ "/devices/resource_mesh_manager/add_resource_mesh",
+ callback_group=self.callback_group,
)
goal = SendCmd.Goal()
- goal.command = json.dumps({
- "resources": resources,
- "bind_parent_id": bind_parent_id,
- })
+ goal.command = json.dumps(
+ {
+ "resources": resources,
+ "bind_parent_id": bind_parent_id,
+ }
+ )
future = action_client.send_goal_async(goal, goal_uuid=uuid.uuid4())
def done_cb(*args):
@@ -401,10 +451,16 @@ class BaseROS2DeviceNode(Node, Generic[T]):
# noinspection PyTypeChecker
self._service_server: Dict[str, Service] = {
"query_host_name": self.create_service(
- SerialCommand, f"/srv{self.namespace}/query_host_name", query_host_name_cb, callback_group=self.callback_group
+ SerialCommand,
+ f"/srv{self.namespace}/query_host_name",
+ query_host_name_cb,
+ callback_group=self.callback_group,
),
"append_resource": self.create_service(
- SerialCommand, f"/srv{self.namespace}/append_resource", append_resource, callback_group=self.callback_group
+ SerialCommand,
+ f"/srv{self.namespace}/append_resource",
+ append_resource,
+ callback_group=self.callback_group,
),
}
@@ -433,6 +489,7 @@ class BaseROS2DeviceNode(Node, Generic[T]):
registered_devices[self.device_id] = device_info
from unilabos.config.config import BasicConfig
from unilabos.ros.nodes.presets.host_node import HostNode
+
if not BasicConfig.is_host_mode:
sclient = self.create_client(SerialCommand, "/node_info_update")
# 启动线程执行发送任务
@@ -440,7 +497,7 @@ class BaseROS2DeviceNode(Node, Generic[T]):
target=self.send_slave_node_info,
args=(sclient,),
daemon=True,
- name=f"ROSDevice{self.device_id}_send_slave_node_info"
+ name=f"ROSDevice{self.device_id}_send_slave_node_info",
).start()
else:
host_node = HostNode.get_instance(0)
@@ -451,12 +508,18 @@ class BaseROS2DeviceNode(Node, Generic[T]):
sclient.wait_for_service()
request = SerialCommand.Request()
from unilabos.config.config import BasicConfig
- request.command = json.dumps({
- "SYNC_SLAVE_NODE_INFO": {
- "machine_name": BasicConfig.machine_name,
- "type": "slave",
- "edge_device_id": self.device_id
- }}, ensure_ascii=False, cls=TypeEncoder)
+
+ request.command = json.dumps(
+ {
+ "SYNC_SLAVE_NODE_INFO": {
+ "machine_name": BasicConfig.machine_name,
+ "type": "slave",
+ "edge_device_id": self.device_id,
+ }
+ },
+ ensure_ascii=False,
+ cls=TypeEncoder,
+ )
# 发送异步请求并等待结果
future = sclient.call_async(request)
@@ -529,6 +592,11 @@ class BaseROS2DeviceNode(Node, Generic[T]):
"""创建动作执行回调函数"""
async def execute_callback(goal_handle: ServerGoalHandle):
+ # 初始化结果信息变量
+ execution_error = ""
+ execution_success = False
+ action_return_value = None
+
self.lab_logger().info(f"执行动作: {action_name}")
goal = goal_handle.request
@@ -568,7 +636,11 @@ class BaseROS2DeviceNode(Node, Generic[T]):
current_resources.extend(response.resources)
else:
r = ResourceGet.Request()
- r.id = action_kwargs[k]["id"] if v == "unilabos_msgs/Resource" else action_kwargs[k][0]["id"]
+ r.id = (
+ action_kwargs[k]["id"]
+ if v == "unilabos_msgs/Resource"
+ else action_kwargs[k][0]["id"]
+ )
r.with_children = True
response = await self._resource_clients["resource_get"].call_async(r)
current_resources.extend(response.resources)
@@ -591,7 +663,19 @@ class BaseROS2DeviceNode(Node, Generic[T]):
if asyncio.iscoroutinefunction(ACTION):
try:
self.lab_logger().info(f"异步执行动作 {ACTION}")
- future = ROS2DeviceNode.run_async_func(ACTION, **action_kwargs)
+ future = ROS2DeviceNode.run_async_func(ACTION, trace_error=False, **action_kwargs)
+
+ def _handle_future_exception(fut):
+ nonlocal execution_error, execution_success, action_return_value
+ try:
+ action_return_value = fut.result()
+ execution_success = True
+ except Exception as e:
+ execution_error = traceback.format_exc()
+ error(f"异步任务 {ACTION.__name__} 报错了")
+ error(traceback.format_exc())
+
+ future.add_done_callback(_handle_future_exception)
except Exception as e:
self.lab_logger().error(f"创建异步任务失败: {traceback.format_exc()}")
raise e
@@ -600,9 +684,12 @@ class BaseROS2DeviceNode(Node, Generic[T]):
future = self._executor.submit(ACTION, **action_kwargs)
def _handle_future_exception(fut):
+ nonlocal execution_error, execution_success, action_return_value
try:
- fut.result()
+ action_return_value = fut.result()
+ execution_success = True
except Exception as e:
+ execution_error = traceback.format_exc()
error(f"同步任务 {ACTION.__name__} 报错了")
error(traceback.format_exc())
@@ -659,16 +746,23 @@ class BaseROS2DeviceNode(Node, Generic[T]):
self.lab_logger().info(f"更新资源状态: {k}")
r = ResourceUpdate.Request()
# 仅当action_kwargs[k]不为None时尝试转换
- akv = action_kwargs[k]
+ akv = action_kwargs[k] # 已经是完成转换的物料了,只需要转换成ros msg Resource了
apv = action_paramtypes[k]
final_type = get_type_class(apv)
if final_type is None:
continue
try:
- r.resources = [
- convert_to_ros_msg(Resource, self.resource_tracker.root_resource(rs))
- for rs in convert_resources_from_type(akv, final_type) # type: ignore # FIXME # 考虑反查到最大的
- ]
+ seen = set()
+ unique_resources = []
+ for rs in akv:
+ res = self.resource_tracker.parent_resource(rs) # 获取 resource 对象
+ if id(res) not in seen:
+ seen.add(id(res))
+ converted_list = convert_resources_from_type([res], final_type)
+ unique_resources.extend([convert_to_ros_msg(Resource, converted) for converted in converted_list])
+
+ r.resources = unique_resources
+
response = await self._resource_clients["resource_update"].call_async(r)
self.lab_logger().debug(f"资源更新结果: {response}")
except Exception as e:
@@ -693,6 +787,8 @@ class BaseROS2DeviceNode(Node, Generic[T]):
for attr_name in result_msg_types.keys():
if attr_name in ["success", "reached_goal"]:
setattr(result_msg, attr_name, True)
+ elif attr_name == "return_info":
+ setattr(result_msg, attr_name, serialize_result_info(execution_error, execution_success, action_return_value))
self.lab_logger().info(f"动作 {action_name} 完成并返回结果")
return result_msg
@@ -738,8 +834,8 @@ class ROS2DeviceNode:
return cls._loop
@classmethod
- def run_async_func(cls, func, **kwargs):
- return run_async_func(func, loop=cls._loop, **kwargs)
+ def run_async_func(cls, func, trace_error=True, **kwargs):
+ return run_async_func(func, loop=cls._loop, trace_error=trace_error, **kwargs)
@property
def driver_instance(self):
@@ -791,7 +887,11 @@ class ROS2DeviceNode:
self.resource_tracker = DeviceNodeResourceTracker()
# use_pylabrobot_creator 使用 cls的包路径检测
- use_pylabrobot_creator = driver_class.__module__.startswith("pylabrobot") or driver_class.__name__ == "LiquidHandlerAbstract"
+ use_pylabrobot_creator = (
+ driver_class.__module__.startswith("pylabrobot")
+ or driver_class.__name__ == "LiquidHandlerAbstract"
+ or driver_class.__name__ == "LiquidHandlerBiomek"
+ )
# TODO: 要在创建之前预先请求服务器是否有当前id的物料,放到resource_tracker中,让pylabrobot进行创建
# 创建设备类实例
@@ -830,6 +930,12 @@ class ROS2DeviceNode:
)
self._ros_node: BaseROS2DeviceNode
self._ros_node.lab_logger().info(f"初始化完成 {self._ros_node.uuid} {self.driver_is_ros}")
+ self.driver_instance._ros_node = self._ros_node # type: ignore
+ if hasattr(self.driver_instance, "post_init"):
+ try:
+ self.driver_instance.post_init(self._ros_node) # type: ignore
+ except Exception as e:
+ self._ros_node.lab_logger().error(f"设备后初始化失败: {e}")
def _start_loop(self):
def run_event_loop():
diff --git a/unilabos/ros/nodes/presets/host_node.py b/unilabos/ros/nodes/presets/host_node.py
index 732e8bb..712e9b3 100644
--- a/unilabos/ros/nodes/presets/host_node.py
+++ b/unilabos/ros/nodes/presets/host_node.py
@@ -151,7 +151,7 @@ class HostNode(BaseROS2DeviceNode):
mqtt_client.publish_registry(device_info["id"], device_info)
for resource_info in lab_registry.obtain_registry_resource_info():
mqtt_client.publish_registry(resource_info["id"], resource_info)
-
+ time.sleep(1) # 等待MQTT连接稳定
# 首次发现网络中的设备
self._discover_devices()
@@ -203,8 +203,12 @@ class HostNode(BaseROS2DeviceNode):
try:
for bridge in self.bridges:
if hasattr(bridge, "resource_add"):
- self.lab_logger().info("[Host Node-Resource] Adding resources to bridge.")
- resource_add_res = bridge.resource_add(add_schema(resource_with_parent_name))
+ resource_start_time = time.time()
+ resource_add_res = bridge.resource_add(add_schema(resource_with_parent_name), True)
+ resource_end_time = time.time()
+ self.lab_logger().info(
+ f"[Host Node-Resource] 物料上传 {round(resource_end_time - resource_start_time, 5) * 1000} ms"
+ )
except Exception as ex:
self.lab_logger().error("[Host Node-Resource] 添加物料出错!")
self.lab_logger().error(traceback.format_exc())
@@ -338,6 +342,7 @@ class HostNode(BaseROS2DeviceNode):
bind_locations: list[Point],
other_calling_params: list[str],
):
+ responses = []
for resource, device_id, bind_parent_id, bind_location, other_calling_param in zip(
resources, device_ids, bind_parent_ids, bind_locations, other_calling_params
):
@@ -363,8 +368,8 @@ class HostNode(BaseROS2DeviceNode):
ensure_ascii=False,
)
response = sclient.call(request)
- pass
- pass
+ responses.append(response)
+ return responses
def create_resource(
self,
@@ -376,7 +381,7 @@ class HostNode(BaseROS2DeviceNode):
liquid_input_slot: list[int],
liquid_type: list[str],
liquid_volume: list[int],
- slot_on_deck: int,
+ slot_on_deck: str,
):
init_new_res = initialize_resource(
{
@@ -610,13 +615,21 @@ class HostNode(BaseROS2DeviceNode):
"""获取结果回调"""
result_msg = future.result().result
result_data = convert_from_ros_msg(result_msg)
+ status = "success"
+ try:
+ ret = json.loads(result_data.get("return_info", "{}")) # 确保返回信息是有效的JSON
+ suc = ret.get("suc", False)
+ if not suc:
+ status = "failed"
+ except json.JSONDecodeError:
+ status = "failed"
self.lab_logger().info(f"[Host Node] Result for {action_id} ({uuid_str}): success")
self.lab_logger().debug(f"[Host Node] Result data: {result_data}")
if uuid_str:
for bridge in self.bridges:
if hasattr(bridge, "publish_job_status"):
- bridge.publish_job_status(result_data, uuid_str, "success")
+ bridge.publish_job_status(result_data, uuid_str, status, result_data.get("return_info", "{}"))
def cancel_goal(self, goal_uuid: str) -> None:
"""取消目标"""
@@ -856,7 +869,6 @@ class HostNode(BaseROS2DeviceNode):
测试网络延迟的action实现
通过5次ping-pong机制校对时间误差并计算实际延迟
"""
- import time
import uuid as uuid_module
self.lab_logger().info("=" * 60)
diff --git a/unilabos/ros/nodes/presets/protocol_node.py b/unilabos/ros/nodes/presets/protocol_node.py
index c4dfd08..23e08d0 100644
--- a/unilabos/ros/nodes/presets/protocol_node.py
+++ b/unilabos/ros/nodes/presets/protocol_node.py
@@ -1,6 +1,7 @@
import time
import asyncio
import traceback
+from types import MethodType
from typing import Union
import rclpy
@@ -87,7 +88,10 @@ class ROS2ProtocolNode(BaseROS2DeviceNode):
# 如果硬件接口是字符串,通过通信设备提供
if isinstance(name, str) and name in self.sub_devices:
+ communicate_device = self.sub_devices[name]
+ communicate_hardware_info = communicate_device.ros_node_instance._hardware_interface
self._setup_hardware_proxy(d, self.sub_devices[name], read, write)
+ self.lab_logger().info(f"\n通信代理:为子设备{device_id}\n 添加了{read}方法(来源:{name} {communicate_hardware_info['write']}) \n 添加了{write}方法(来源:{name} {communicate_hardware_info['read']})")
def _setup_protocol_names(self, protocol_type):
# 处理协议类型
@@ -241,20 +245,23 @@ class ROS2ProtocolNode(BaseROS2DeviceNode):
def _setup_hardware_proxy(self, device: ROS2DeviceNode, communication_device: ROS2DeviceNode, read_method, write_method):
"""为设备设置硬件接口代理"""
- extra_info = [getattr(device.driver_instance, info) for info in communication_device.ros_node_instance._hardware_interface.get("extra_info", [])]
- write_func = getattr(communication_device.ros_node_instance, communication_device.ros_node_instance._hardware_interface["write"])
- read_func = getattr(communication_device.ros_node_instance, communication_device.ros_node_instance._hardware_interface["read"])
+ # extra_info = [getattr(device.driver_instance, info) for info in communication_device.ros_node_instance._hardware_interface.get("extra_info", [])]
+ write_func = getattr(communication_device.driver_instance, communication_device.ros_node_instance._hardware_interface["write"])
+ read_func = getattr(communication_device.driver_instance, communication_device.ros_node_instance._hardware_interface["read"])
- def _read():
- return read_func(*extra_info)
+ def _read(*args, **kwargs):
+ return read_func(*args, **kwargs)
- def _write(command):
- return write_func(*extra_info, command)
+ def _write(*args, **kwargs):
+ return write_func(*args, **kwargs)
if read_method:
- setattr(device.driver_instance, read_method, _read)
+ bound_read = MethodType(_read, device.driver_instance)
+ setattr(device.driver_instance, read_method, bound_read)
+
if write_method:
- setattr(device.driver_instance, write_method, _write)
+ bound_write = MethodType(_write, device.driver_instance)
+ setattr(device.driver_instance, write_method, bound_write)
async def _update_resources(self, goal, protocol_kwargs):
diff --git a/unilabos/ros/nodes/presets/resource_mesh_manager.py b/unilabos/ros/nodes/presets/resource_mesh_manager.py
index c149581..dadb49a 100644
--- a/unilabos/ros/nodes/presets/resource_mesh_manager.py
+++ b/unilabos/ros/nodes/presets/resource_mesh_manager.py
@@ -91,8 +91,11 @@ class ResourceMeshManager(BaseROS2DeviceNode):
self.__collision_object_publisher = self.create_publisher(
CollisionObject, "/collision_object", 10
)
+ self.__planning_scene_publisher = self.create_publisher(
+ PlanningScene, "/planning_scene", 10
+ )
self.__attached_collision_object_publisher = self.create_publisher(
- AttachedCollisionObject, "/attached_collision_object", 10
+ AttachedCollisionObject, "/attached_collision_object", 0
)
# 创建一个Action Server用于修改resource_tf_dict
@@ -121,7 +124,8 @@ class ResourceMeshManager(BaseROS2DeviceNode):
"""检查move_group节点是否已初始化完成"""
# 获取当前可用的节点列表
-
+ if len(self.resource_tf_dict) == 0:
+ return
tf_ready = self.tf_buffer.can_transform("world", next(iter(self.resource_tf_dict.keys())), rclpy.time.Time(),rclpy.duration.Duration(seconds=2))
# if tf_ready:
@@ -129,8 +133,7 @@ class ResourceMeshManager(BaseROS2DeviceNode):
self.move_group_ready = True
self.publish_resource_tf()
self.add_resource_collision_meshes(self.resource_tf_dict)
-
- # time.sleep(1)
+
def add_resource_mesh_callback(self, goal_handle : ServerGoalHandle):
tf_update_msg = goal_handle.request
@@ -147,7 +150,7 @@ class ResourceMeshManager(BaseROS2DeviceNode):
"""刷新资源配置"""
registry = lab_registry
- resource_config = json.loads(resource_config_str)
+ resource_config = json.loads(resource_config_str.replace("'",'"'))
if resource_config['id'] in self.resource_config_dict:
self.get_logger().info(f'资源 {resource_config["id"]} 已存在')
@@ -158,7 +161,7 @@ class ResourceMeshManager(BaseROS2DeviceNode):
self.resource_model[resource_config['id']] = {
'mesh': f"{str(self.mesh_path)}/device_mesh/resources/{model_config['mesh']}",
'mesh_tf': model_config['mesh_tf']}
- if model_config['children_mesh'] is not None:
+ if 'children_mesh' in model_config.keys():
self.resource_model[f"{resource_config['id']}_"] = {
'mesh': f"{str(self.mesh_path)}/device_mesh/resources/{model_config['children_mesh']}",
'mesh_tf': model_config['children_mesh_tf']
@@ -187,7 +190,8 @@ class ResourceMeshManager(BaseROS2DeviceNode):
pass
elif parent is not None and resource_id in self.resource_model:
- parent_link = f"{self.resource_config_dict[parent]['parent']}_{parent}_device_link".replace("None","")
+ # parent_link = f"{self.resource_config_dict[parent]['parent']}_{parent}_device_link".replace("None_","")
+ parent_link = f"{parent}_device_link".replace("None_","")
else:
@@ -297,7 +301,7 @@ class ResourceMeshManager(BaseROS2DeviceNode):
"world",
resource_id,
rclpy.time.Time(seconds=0),
- rclpy.duration.Duration(seconds=5)
+ # rclpy.duration.Duration(seconds=5)
)
# 提取当前位姿信息
@@ -344,9 +348,7 @@ class ResourceMeshManager(BaseROS2DeviceNode):
self.resource_pose_publisher.publish(changed_poses_msg)
self.zero_count += 1
-
-
-
+
def _is_pose_equal(self, pose1, pose2, tolerance=1e-7):
"""
比较两个位姿是否相等(考虑浮点数精度)
@@ -386,14 +388,24 @@ class ResourceMeshManager(BaseROS2DeviceNode):
self.__planning_scene = self._get_planning_scene_service.call(
GetPlanningScene.Request()
).scene
-
- for resource_id, target_parent in cmd_dict.items():
+ self.__planning_scene.is_diff = True
+ planning_scene = PlanningScene()
+ planning_scene.is_diff = True
+ planning_scene.robot_state.is_diff = True
+ # time_start = self.get_clock().now()
+ time_start = rclpy.time.Time(seconds=0)
+ count = 0
+ for resource_id, target_parent in cmd_dict.items():
+ parent_id = target_parent
+ if target_parent == '__trash':
+ parent_id = 'world'
# 获取从resource_id到target_parent的转换
transform = self.tf_buffer.lookup_transform(
- target_parent,
+ parent_id,
resource_id,
- rclpy.time.Time(seconds=0)
+ time_start,
+ timeout=rclpy.duration.Duration(seconds=10)
)
# 提取转换中的位置和旋转信息
@@ -411,26 +423,62 @@ class ResourceMeshManager(BaseROS2DeviceNode):
}
self.resource_tf_dict[resource_id] = {
- "parent": target_parent,
+ "parent": parent_id,
"position": position,
"rotation": rotation
}
+
# self.attach_collision_object(id=resource_id,link_name=target_parent)
- collision_object = AttachedCollisionObject(
+ # time.sleep(0.02)
+ operation_attach = CollisionObject.ADD
+ operation_world = CollisionObject.REMOVE
+ if target_parent == 'world':
+ operation_attach = CollisionObject.REMOVE
+ operation_world = CollisionObject.ADD
+ elif target_parent == '__trash':
+ operation_attach = CollisionObject.REMOVE
+
+ world_object = CollisionObject(
id=resource_id,
- link_name=target_parent,
+ operation=operation_world
+ )
+ if target_parent != '__trash':
+ planning_scene.world.collision_objects.append(world_object)
+
+
+ collision_object = AttachedCollisionObject(
object=CollisionObject(
id=resource_id,
- operation=CollisionObject.ADD
+ operation=operation_attach
)
)
-
- self.__planning_scene.robot_state.attached_collision_objects.append(collision_object)
+ if target_parent != 'world' and target_parent != '__trash':
+ collision_object.link_name = target_parent
+ planning_scene.robot_state.attached_collision_objects.append(collision_object)
+
+ count += 1
+
+ if count > 30:
+ req = ApplyPlanningScene.Request()
+ req.scene = planning_scene
+ self.publish_resource_tf()
+ self._apply_planning_scene_service.call(req)
+ self.__planning_scene_publisher.publish(planning_scene)
+ count = 0
+
+ planning_scene = PlanningScene()
+ planning_scene.is_diff = True
+ planning_scene.robot_state.is_diff = True
+
req = ApplyPlanningScene.Request()
- req.scene = self.__planning_scene
- self._apply_planning_scene_service.call_async(req)
+ req.scene = planning_scene
self.publish_resource_tf()
+ self._apply_planning_scene_service.call(req)
+ self.__planning_scene_publisher.publish(planning_scene)
+
+ # self.__collision_object_publisher.publish(CollisionObject())
+
except Exception as e:
self.get_logger().error(f"更新资源TF字典失败: {e}")
@@ -440,18 +488,22 @@ class ResourceMeshManager(BaseROS2DeviceNode):
return SendCmd.Result(success=True)
+
def add_resource_collision_meshes(self,resource_tf_dict:dict):
"""
遍历资源配置字典,为每个在resource_model中有对应模型的资源添加碰撞网格
该方法检查每个资源ID是否在self.resource_model中有对应的3D模型文件路径,
- 如果有,则调用add_collision_mesh方法将其添加到碰撞环境中。
+
"""
self.get_logger().info('开始添加资源碰撞网格')
self.__planning_scene = self._get_planning_scene_service.call(
GetPlanningScene.Request()
).scene
+ planning_scene = PlanningScene()
+ planning_scene.is_diff = True
+ count = 0
for resource_id, tf_info in resource_tf_dict.items():
if resource_id in self.resource_model:
@@ -479,7 +531,8 @@ class ResourceMeshManager(BaseROS2DeviceNode):
quat_xyzw=q,
frame_id=resource_id
)
- self.__planning_scene.world.collision_objects.append(collision_object)
+ count += 1
+ planning_scene.world.collision_objects.append(collision_object)
elif f"{tf_info['parent']}_" in self.resource_model:
# 获取资源的父级框架ID
id_ = f"{tf_info['parent']}_"
@@ -507,14 +560,26 @@ class ResourceMeshManager(BaseROS2DeviceNode):
quat_xyzw=q,
frame_id=resource_id
)
+ count += 1
+ planning_scene.world.collision_objects.append(collision_object)
- self.__planning_scene.world.collision_objects.append(collision_object)
+ if count > 30:
+ req = ApplyPlanningScene.Request()
+ req.scene = planning_scene
+ self.publish_resource_tf()
+ self._apply_planning_scene_service.call(req)
+ self.__planning_scene_publisher.publish(planning_scene)
+ count = 0
+
+ planning_scene = PlanningScene()
+ planning_scene.is_diff = True
req = ApplyPlanningScene.Request()
- req.scene = self.__planning_scene
- self._apply_planning_scene_service.call_async(req)
-
-
+ req.scene = planning_scene
+ self.publish_resource_tf()
+ self._apply_planning_scene_service.call(req)
+ self.__planning_scene_publisher.publish(planning_scene)
+
self.get_logger().info('资源碰撞网格添加完成')
@@ -959,9 +1024,6 @@ class ResourceMeshManager(BaseROS2DeviceNode):
Attach collision object to the robot.
"""
- if link_name is None:
- link_name = self.__end_effector_name
-
msg = AttachedCollisionObject(
object=CollisionObject(id=id, operation=CollisionObject.ADD)
)
diff --git a/unilabos/ros/nodes/resource_tracker.py b/unilabos/ros/nodes/resource_tracker.py
index 04b5437..ff1a779 100644
--- a/unilabos/ros/nodes/resource_tracker.py
+++ b/unilabos/ros/nodes/resource_tracker.py
@@ -1,3 +1,5 @@
+from typing import List, Tuple, Any
+
from unilabos.utils.log import logger
@@ -5,12 +7,12 @@ class DeviceNodeResourceTracker(object):
def __init__(self):
self.resources = []
- self.root_resource2resource = {}
+ self.resource2parent_resource = {}
pass
- def root_resource(self, resource):
- if id(resource) in self.root_resource2resource:
- return self.root_resource2resource[id(resource)]
+ def parent_resource(self, resource):
+ if id(resource) in self.resource2parent_resource:
+ return self.resource2parent_resource[id(resource)]
else:
return resource
@@ -44,20 +46,21 @@ class DeviceNodeResourceTracker(object):
self.loop_find_resource(r, resource_cls_type, identifier_key, getattr(query_resource, identifier_key))
)
assert len(res_list) == 1, f"{query_resource} 找到多个资源,请检查资源是否唯一: {res_list}"
- self.root_resource2resource[id(query_resource)] = res_list[0]
+ self.resource2parent_resource[id(query_resource)] = res_list[0][0]
+ self.resource2parent_resource[id(res_list[0][1])] = res_list[0][0]
# 后续加入其他对比方式
- return res_list[0]
+ return res_list[0][1]
- def loop_find_resource(self, resource, target_resource_cls_type, identifier_key, compare_value):
+ def loop_find_resource(self, resource, target_resource_cls_type, identifier_key, compare_value, parent_res=None) -> List[Tuple[Any, Any]]:
res_list = []
# print(resource, target_resource_cls_type, identifier_key, compare_value)
children = getattr(resource, "children", [])
for child in children:
- res_list.extend(self.loop_find_resource(child, target_resource_cls_type, identifier_key, compare_value))
+ res_list.extend(self.loop_find_resource(child, target_resource_cls_type, identifier_key, compare_value, resource))
if target_resource_cls_type == type(resource) or target_resource_cls_type == dict:
if hasattr(resource, identifier_key):
if getattr(resource, identifier_key) == compare_value:
- res_list.append(resource)
+ res_list.append((parent_res, resource))
return res_list
def filter_find_list(self, res_list, compare_std_dict):
diff --git a/unilabos/ros/utils/driver_creator.py b/unilabos/ros/utils/driver_creator.py
index 1218725..9f223f9 100644
--- a/unilabos/ros/utils/driver_creator.py
+++ b/unilabos/ros/utils/driver_creator.py
@@ -105,40 +105,41 @@ class PyLabRobotCreator(DeviceClassCreator[T]):
return nested_dict_to_list(resource), Resource
return resource, source_type
- def _process_resource_references(self, data: Any, to_dict=False) -> Any:
+ def _process_resource_references(self, data: Any, to_dict=False, states=None, prefix_path="") -> Any:
"""
递归处理资源引用,替换_resource_child_name对应的资源
Args:
data: 需要处理的数据,可能是字典、列表或其他类型
- to_dict: 转换成对应的实例,还是转换成对应的字典
+ to_dict: 是否返回字典形式的资源
+ states: 用于保存所有资源状态
+ prefix_path: 当前递归路径
Returns:
处理后的数据
"""
from pylabrobot.resources import Deck, Resource
+ if states is None:
+ states = {}
if isinstance(data, dict):
- # 检查是否包含资源引用
if "_resource_child_name" in data:
child_name = data["_resource_child_name"]
if child_name in self.children:
- # 找到了对应的资源
resource = self.children[child_name]
-
- # 检查是否需要转换资源类型
if "_resource_type" in data:
type_path = data["_resource_type"]
try:
- # 尝试导入指定的类型
target_type = import_manager.get_class(type_path)
contain_model = not issubclass(target_type, Deck)
resource, target_type = self._process_resource_mapping(resource, target_type)
- # 在截图中格式,是deserialize,所以这里要转成plr resource可deserialize的字典
- # 这样后面执行deserialize的时候能够正确反序列化对应的物料
resource_instance: Resource = resource_ulab_to_plr(resource, contain_model)
+
+ # 使用 prefix_path 作为 key 存储资源状态
if to_dict:
- return resource_instance.serialize()
+ serialized = resource_instance.serialize()
+ states[prefix_path] = resource_instance.serialize_all_state()
+ return serialized
else:
self.resource_tracker.add_resource(resource_instance)
return resource_instance
@@ -151,18 +152,21 @@ class PyLabRobotCreator(DeviceClassCreator[T]):
else:
logger.warning(f"找不到资源引用 '{child_name}',保持原值不变")
- # 递归处理字典的每个值
+ # 递归处理每个键值
result = {}
for key, value in data.items():
- result[key] = self._process_resource_references(value, to_dict)
+ new_prefix = f"{prefix_path}.{key}" if prefix_path else key
+ result[key] = self._process_resource_references(value, to_dict, states, new_prefix)
return result
- # 处理列表类型
elif isinstance(data, list):
- return [self._process_resource_references(item, to_dict) for item in data]
+ return [
+ self._process_resource_references(item, to_dict, states, f"{prefix_path}[{i}]")
+ for i, item in enumerate(data)
+ ]
- # 其他类型直接返回
- return data
+ else:
+ return data
def create_instance(self, data: Dict[str, Any]) -> Optional[T]:
"""
@@ -187,10 +191,18 @@ class PyLabRobotCreator(DeviceClassCreator[T]):
logger.debug(f"自动补充 _resource_type: {data[param_name]['_resource_type']}")
# 首先处理资源引用
- processed_data = self._process_resource_references(data, to_dict=True)
+ states = {}
+ processed_data = self._process_resource_references(data, to_dict=True, states=states)
try:
self.device_instance = deserialize_method(**processed_data)
+ all_states = self.device_instance.serialize_all_state()
+ for k, v in states.items():
+ logger.debug(f"PyLabRobot反序列化设置状态:{k}")
+ for kk, vv in all_states.items():
+ if kk not in v:
+ v[kk] = vv
+ self.device_instance.deck.load_all_state(v)
self.resource_tracker.add_resource(self.device_instance)
self.post_create()
return self.device_instance # type: ignore
@@ -225,6 +237,10 @@ class PyLabRobotCreator(DeviceClassCreator[T]):
if hasattr(self.device_instance, "setup") and asyncio.iscoroutinefunction(getattr(self.device_instance, "setup")):
from unilabos.ros.nodes.base_device_node import ROS2DeviceNode
def done_cb(*args):
+ from pylabrobot.resources import set_volume_tracking
+ # from pylabrobot.resources import set_tip_tracking
+ set_volume_tracking(enabled=True)
+ # set_tip_tracking(enabled=True) # 序列化tip_spot has为False
logger.debug(f"PyLabRobot设备实例 {self.device_instance} 设置完成")
from unilabos.config.config import BasicConfig
if BasicConfig.vis_2d_enable:
diff --git a/unilabos/utils/async_util.py b/unilabos/utils/async_util.py
index ce97f5a..0f50a73 100644
--- a/unilabos/utils/async_util.py
+++ b/unilabos/utils/async_util.py
@@ -5,7 +5,7 @@ from asyncio import get_event_loop
from unilabos.utils.log import error
-def run_async_func(func, *, loop=None, **kwargs):
+def run_async_func(func, *, loop=None, trace_error=True, **kwargs):
if loop is None:
loop = get_event_loop()
@@ -17,5 +17,6 @@ def run_async_func(func, *, loop=None, **kwargs):
error(traceback.format_exc())
future = asyncio.run_coroutine_threadsafe(func(**kwargs), loop)
- future.add_done_callback(_handle_future_exception)
- return future
\ No newline at end of file
+ if trace_error:
+ future.add_done_callback(_handle_future_exception)
+ return future
diff --git a/unilabos/utils/type_check.py b/unilabos/utils/type_check.py
index 7366652..578eb93 100644
--- a/unilabos/utils/type_check.py
+++ b/unilabos/utils/type_check.py
@@ -1,4 +1,4 @@
-import collections
+import collections.abc
import json
from typing import get_origin, get_args
@@ -21,3 +21,46 @@ class TypeEncoder(json.JSONEncoder):
return str(obj)[8:-2]
return super().default(obj)
+
+class ResultInfoEncoder(json.JSONEncoder):
+ """专门用于处理任务执行结果信息的JSON编码器"""
+
+ def default(self, obj):
+ # 优先处理类型对象
+ if isinstance(obj, type):
+ return str(obj)[8:-2]
+
+ # 对于无法序列化的对象,统一转换为字符串
+ try:
+ # 尝试调用 __dict__ 或者其他序列化方法
+ if hasattr(obj, "__dict__"):
+ return obj.__dict__
+ elif hasattr(obj, "_asdict"): # namedtuple
+ return obj._asdict()
+ elif hasattr(obj, "to_dict"):
+ return obj.to_dict()
+ elif hasattr(obj, "dict"):
+ return obj.dict()
+ else:
+ # 如果都不行,转换为字符串
+ return str(obj)
+ except Exception:
+ # 如果转换失败,直接返回字符串表示
+ return str(obj)
+
+
+def serialize_result_info(error: str, suc: bool, return_value=None) -> str:
+ """
+ 序列化任务执行结果信息
+
+ Args:
+ error: 错误信息字符串
+ suc: 是否成功的布尔值
+ return_value: 返回值,可以是任何类型
+
+ Returns:
+ JSON字符串格式的结果信息
+ """
+ result_info = {"error": error, "suc": suc, "return_value": return_value}
+
+ return json.dumps(result_info, ensure_ascii=False, cls=ResultInfoEncoder)
diff --git a/unilabos_msgs/CMakeLists.txt b/unilabos_msgs/CMakeLists.txt
index 48cdfec..dc0d5d4 100644
--- a/unilabos_msgs/CMakeLists.txt
+++ b/unilabos_msgs/CMakeLists.txt
@@ -34,6 +34,7 @@ set(action_files
"action/HeatChill.action"
"action/HeatChillStart.action"
"action/HeatChillStop.action"
+
"action/Filter.action"
"action/Add.action"
"action/Centrifuge.action"
@@ -45,6 +46,8 @@ set(action_files
"action/StopPurge.action"
"action/StopStir.action"
"action/Transfer.action"
+
+ "action/LiquidHandlerProtocolCreation.action"
"action/LiquidHandlerAspirate.action"
"action/LiquidHandlerDiscardTips.action"
"action/LiquidHandlerDispense.action"
@@ -60,6 +63,11 @@ set(action_files
"action/LiquidHandlerStamp.action"
"action/LiquidHandlerTransfer.action"
+ "action/LiquidHandlerTransferBiomek.action"
+ "action/LiquidHandlerIncubateBiomek.action"
+ "action/LiquidHandlerMoveBiomek.action"
+ "action/LiquidHandlerOscillateBiomek.action"
+
"action/LiquidHandlerAdd.action"
"action/LiquidHandlerMix.action"
"action/LiquidHandlerMoveTo.action"
diff --git a/unilabos_msgs/action/AGVTransfer.action b/unilabos_msgs/action/AGVTransfer.action
index 06c8c8e..0c301f4 100644
--- a/unilabos_msgs/action/AGVTransfer.action
+++ b/unilabos_msgs/action/AGVTransfer.action
@@ -4,6 +4,7 @@ string from_repo_position
Resource to_repo
string to_repo_position
---
+string return_info
bool success
---
string status
diff --git a/unilabos_msgs/action/Clean.action b/unilabos_msgs/action/Clean.action
index 093a0da..8fb9be1 100644
--- a/unilabos_msgs/action/Clean.action
+++ b/unilabos_msgs/action/Clean.action
@@ -5,6 +5,7 @@ float64 volume # Optional. Volume of solvent to clean vessel with.
float64 temp # Optional. Temperature to heat vessel to while cleaning.
int32 repeats # Optional. Number of cleaning cycles to perform.
---
+string return_info
bool success
---
string status
diff --git a/unilabos_msgs/action/EmptyIn.action b/unilabos_msgs/action/EmptyIn.action
index c44b70c..e7f59d0 100644
--- a/unilabos_msgs/action/EmptyIn.action
+++ b/unilabos_msgs/action/EmptyIn.action
@@ -1,4 +1,4 @@
---
-
+string return_info
---
\ No newline at end of file
diff --git a/unilabos_msgs/action/EvacuateAndRefill.action b/unilabos_msgs/action/EvacuateAndRefill.action
index ed138dd..22ffc65 100644
--- a/unilabos_msgs/action/EvacuateAndRefill.action
+++ b/unilabos_msgs/action/EvacuateAndRefill.action
@@ -3,6 +3,7 @@ string vessel
string gas
int32 repeats
---
+string return_info
bool success
---
string status
diff --git a/unilabos_msgs/action/Evaporate.action b/unilabos_msgs/action/Evaporate.action
index 9638a9a..45887f2 100644
--- a/unilabos_msgs/action/Evaporate.action
+++ b/unilabos_msgs/action/Evaporate.action
@@ -5,6 +5,7 @@ float64 temp
float64 time
float64 stir_speed
---
+string return_info
bool success
---
string status
diff --git a/unilabos_msgs/action/FloatSingleInput.action b/unilabos_msgs/action/FloatSingleInput.action
index 2542d31..52feed7 100644
--- a/unilabos_msgs/action/FloatSingleInput.action
+++ b/unilabos_msgs/action/FloatSingleInput.action
@@ -1,4 +1,5 @@
float64 float_in
---
+string return_info
bool success
---
\ No newline at end of file
diff --git a/unilabos_msgs/action/HeatChill.action b/unilabos_msgs/action/HeatChill.action
index 1c7f841..87ebf52 100644
--- a/unilabos_msgs/action/HeatChill.action
+++ b/unilabos_msgs/action/HeatChill.action
@@ -6,6 +6,7 @@ bool stir
float64 stir_speed
string purpose
---
+string return_info
bool success
---
string status
\ No newline at end of file
diff --git a/unilabos_msgs/action/HeatChillStart.action b/unilabos_msgs/action/HeatChillStart.action
index f928693..565bad1 100644
--- a/unilabos_msgs/action/HeatChillStart.action
+++ b/unilabos_msgs/action/HeatChillStart.action
@@ -3,6 +3,7 @@ string vessel
float64 temp
string purpose
---
+string return_info
bool success
---
string status
\ No newline at end of file
diff --git a/unilabos_msgs/action/HeatChillStop.action b/unilabos_msgs/action/HeatChillStop.action
index 88fc029..280ca15 100644
--- a/unilabos_msgs/action/HeatChillStop.action
+++ b/unilabos_msgs/action/HeatChillStop.action
@@ -1,6 +1,7 @@
# Organic
string vessel
---
+string return_info
bool success
---
string status
\ No newline at end of file
diff --git a/unilabos_msgs/action/IntSingleInput.action b/unilabos_msgs/action/IntSingleInput.action
index 0f8b7aa..23aeec6 100644
--- a/unilabos_msgs/action/IntSingleInput.action
+++ b/unilabos_msgs/action/IntSingleInput.action
@@ -1,4 +1,5 @@
int32 int_input
---
+string return_info
bool success
---
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerAdd.action b/unilabos_msgs/action/LiquidHandlerAdd.action
index 0611b27..a17a61c 100644
--- a/unilabos_msgs/action/LiquidHandlerAdd.action
+++ b/unilabos_msgs/action/LiquidHandlerAdd.action
@@ -15,6 +15,7 @@ int32 mix_rate
float64 mix_liquid_height
string[] none_keys
---
+string return_info
bool success
---
# 反馈
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerAspirate.action b/unilabos_msgs/action/LiquidHandlerAspirate.action
index 9ba1706..b855861 100644
--- a/unilabos_msgs/action/LiquidHandlerAspirate.action
+++ b/unilabos_msgs/action/LiquidHandlerAspirate.action
@@ -7,5 +7,6 @@ float64[] liquid_height
float64[] blow_out_air_volume
string spread
---
+string return_info
bool success
---
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerDiscardTips.action b/unilabos_msgs/action/LiquidHandlerDiscardTips.action
index a7c6f8a..c2d290d 100644
--- a/unilabos_msgs/action/LiquidHandlerDiscardTips.action
+++ b/unilabos_msgs/action/LiquidHandlerDiscardTips.action
@@ -3,6 +3,7 @@
int32[] use_channels
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerDispense.action b/unilabos_msgs/action/LiquidHandlerDispense.action
index 73c4d0f..e06e375 100644
--- a/unilabos_msgs/action/LiquidHandlerDispense.action
+++ b/unilabos_msgs/action/LiquidHandlerDispense.action
@@ -8,6 +8,7 @@ int32[] blow_out_air_volume
string spread
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerDropTips.action b/unilabos_msgs/action/LiquidHandlerDropTips.action
index 76a5625..46f7e49 100644
--- a/unilabos_msgs/action/LiquidHandlerDropTips.action
+++ b/unilabos_msgs/action/LiquidHandlerDropTips.action
@@ -6,6 +6,7 @@ geometry_msgs/Point[] offsets
bool allow_nonzero_volume
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerDropTips96.action b/unilabos_msgs/action/LiquidHandlerDropTips96.action
index b4b7dfc..a32891f 100644
--- a/unilabos_msgs/action/LiquidHandlerDropTips96.action
+++ b/unilabos_msgs/action/LiquidHandlerDropTips96.action
@@ -5,6 +5,7 @@ geometry_msgs/Point offset
bool allow_nonzero_volume
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerIncubateBiomek.action b/unilabos_msgs/action/LiquidHandlerIncubateBiomek.action
new file mode 100644
index 0000000..da9d703
--- /dev/null
+++ b/unilabos_msgs/action/LiquidHandlerIncubateBiomek.action
@@ -0,0 +1,6 @@
+int32 time
+
+---
+string return_info
+bool success
+---
diff --git a/unilabos_msgs/action/LiquidHandlerMix.action b/unilabos_msgs/action/LiquidHandlerMix.action
index 81d1b71..99abe93 100644
--- a/unilabos_msgs/action/LiquidHandlerMix.action
+++ b/unilabos_msgs/action/LiquidHandlerMix.action
@@ -6,6 +6,7 @@ geometry_msgs/Point[] offsets
float64 mix_rate
string[] none_keys
---
+string return_info
bool success
---
# 反馈
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerMoveBiomek.action b/unilabos_msgs/action/LiquidHandlerMoveBiomek.action
new file mode 100644
index 0000000..9c75206
--- /dev/null
+++ b/unilabos_msgs/action/LiquidHandlerMoveBiomek.action
@@ -0,0 +1,7 @@
+string sources
+string targets
+
+---
+string return_info
+bool success
+---
diff --git a/unilabos_msgs/action/LiquidHandlerMoveLid.action b/unilabos_msgs/action/LiquidHandlerMoveLid.action
index 41a51e5..0c5d747 100644
--- a/unilabos_msgs/action/LiquidHandlerMoveLid.action
+++ b/unilabos_msgs/action/LiquidHandlerMoveLid.action
@@ -12,6 +12,7 @@ string put_direction
float64 pickup_distance_from_top
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerMovePlate.action b/unilabos_msgs/action/LiquidHandlerMovePlate.action
index ea7503a..6ad283d 100644
--- a/unilabos_msgs/action/LiquidHandlerMovePlate.action
+++ b/unilabos_msgs/action/LiquidHandlerMovePlate.action
@@ -13,6 +13,7 @@ string put_direction
float64 pickup_distance_from_top
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerMoveResource.action b/unilabos_msgs/action/LiquidHandlerMoveResource.action
index aaffa96..776d6ce 100644
--- a/unilabos_msgs/action/LiquidHandlerMoveResource.action
+++ b/unilabos_msgs/action/LiquidHandlerMoveResource.action
@@ -12,6 +12,7 @@ string get_direction
string put_direction
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerMoveTo.action b/unilabos_msgs/action/LiquidHandlerMoveTo.action
index 740d0fc..0a9e1fe 100644
--- a/unilabos_msgs/action/LiquidHandlerMoveTo.action
+++ b/unilabos_msgs/action/LiquidHandlerMoveTo.action
@@ -2,6 +2,7 @@ Resource well
float64 dis_to_top
int32 channel
---
+string return_info
bool success
---
# 反馈
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerOscillateBiomek.action b/unilabos_msgs/action/LiquidHandlerOscillateBiomek.action
new file mode 100644
index 0000000..b07eb76
--- /dev/null
+++ b/unilabos_msgs/action/LiquidHandlerOscillateBiomek.action
@@ -0,0 +1,7 @@
+int32 rpm
+int32 time
+
+---
+string return_info
+bool success
+---
diff --git a/unilabos_msgs/action/LiquidHandlerPickUpTips.action b/unilabos_msgs/action/LiquidHandlerPickUpTips.action
index 096bf17..89287d9 100644
--- a/unilabos_msgs/action/LiquidHandlerPickUpTips.action
+++ b/unilabos_msgs/action/LiquidHandlerPickUpTips.action
@@ -5,6 +5,7 @@ int32[] use_channels
geometry_msgs/Point[] offsets
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerPickUpTips96.action b/unilabos_msgs/action/LiquidHandlerPickUpTips96.action
index 761349a..63a60b4 100644
--- a/unilabos_msgs/action/LiquidHandlerPickUpTips96.action
+++ b/unilabos_msgs/action/LiquidHandlerPickUpTips96.action
@@ -4,6 +4,7 @@ Resource tip_rack
geometry_msgs/Point offset
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerProtocolCreation.action b/unilabos_msgs/action/LiquidHandlerProtocolCreation.action
new file mode 100644
index 0000000..c63525a
--- /dev/null
+++ b/unilabos_msgs/action/LiquidHandlerProtocolCreation.action
@@ -0,0 +1,10 @@
+string protocol_name
+string protocol_description
+string protocol_version
+string protocol_author
+string protocol_date
+string protocol_type
+string[] none_keys
+---
+string return_info
+---
diff --git a/unilabos_msgs/action/LiquidHandlerRemove.action b/unilabos_msgs/action/LiquidHandlerRemove.action
index e6b43c5..2b2656e 100644
--- a/unilabos_msgs/action/LiquidHandlerRemove.action
+++ b/unilabos_msgs/action/LiquidHandlerRemove.action
@@ -12,6 +12,7 @@ bool is_96_well
float64[] top
string[] none_keys
---
+string return_info
bool success
---
# 反馈
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerReturnTips.action b/unilabos_msgs/action/LiquidHandlerReturnTips.action
index 25d1596..0c3b366 100644
--- a/unilabos_msgs/action/LiquidHandlerReturnTips.action
+++ b/unilabos_msgs/action/LiquidHandlerReturnTips.action
@@ -4,6 +4,7 @@ int32[] use_channels
bool allow_nonzero_volume
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerReturnTips96.action b/unilabos_msgs/action/LiquidHandlerReturnTips96.action
index fd20d71..da670e5 100644
--- a/unilabos_msgs/action/LiquidHandlerReturnTips96.action
+++ b/unilabos_msgs/action/LiquidHandlerReturnTips96.action
@@ -3,6 +3,7 @@
bool allow_nonzero_volume
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerStamp.action b/unilabos_msgs/action/LiquidHandlerStamp.action
index a7db4bf..383eee3 100644
--- a/unilabos_msgs/action/LiquidHandlerStamp.action
+++ b/unilabos_msgs/action/LiquidHandlerStamp.action
@@ -7,6 +7,7 @@ float64 aspiration_flow_rate
float64 dispense_flow_rate
---
# 结果字段
+string return_info
bool success
---
# 反馈字段
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerTransfer.action b/unilabos_msgs/action/LiquidHandlerTransfer.action
index 39df59b..6130f20 100644
--- a/unilabos_msgs/action/LiquidHandlerTransfer.action
+++ b/unilabos_msgs/action/LiquidHandlerTransfer.action
@@ -20,6 +20,7 @@ float64 mix_liquid_height
int32[] delays
string[] none_keys
---
+string return_info
bool success
---
# 反馈
\ No newline at end of file
diff --git a/unilabos_msgs/action/LiquidHandlerTransferBiomek.action b/unilabos_msgs/action/LiquidHandlerTransferBiomek.action
new file mode 100644
index 0000000..65db264
--- /dev/null
+++ b/unilabos_msgs/action/LiquidHandlerTransferBiomek.action
@@ -0,0 +1,11 @@
+string sources
+string targets
+string tip_rack
+float64 volume
+string aspirate_technique
+string dispense_technique
+
+---
+string return_info
+bool success
+---
diff --git a/unilabos_msgs/action/Point3DSeparateInput.action b/unilabos_msgs/action/Point3DSeparateInput.action
index 4e15e8f..5d24125 100644
--- a/unilabos_msgs/action/Point3DSeparateInput.action
+++ b/unilabos_msgs/action/Point3DSeparateInput.action
@@ -2,5 +2,6 @@ float64 x
float64 y
float64 z
---
+string return_info
bool success
---
\ No newline at end of file
diff --git a/unilabos_msgs/action/PumpTransfer.action b/unilabos_msgs/action/PumpTransfer.action
index bbe6cb1..69d22b6 100644
--- a/unilabos_msgs/action/PumpTransfer.action
+++ b/unilabos_msgs/action/PumpTransfer.action
@@ -10,6 +10,7 @@ float64 rinsing_volume
int32 rinsing_repeats
bool solid
---
+string return_info
bool success
---
string status
diff --git a/unilabos_msgs/action/ResourceCreateFromOuter.action b/unilabos_msgs/action/ResourceCreateFromOuter.action
index e0eeb1c..5733075 100644
--- a/unilabos_msgs/action/ResourceCreateFromOuter.action
+++ b/unilabos_msgs/action/ResourceCreateFromOuter.action
@@ -4,5 +4,6 @@ string[] bind_parent_ids
geometry_msgs/Point[] bind_locations
string[] other_calling_params
---
+string return_info
bool success
---
\ No newline at end of file
diff --git a/unilabos_msgs/action/ResourceCreateFromOuterEasy.action b/unilabos_msgs/action/ResourceCreateFromOuterEasy.action
index cc832a7..420602e 100644
--- a/unilabos_msgs/action/ResourceCreateFromOuterEasy.action
+++ b/unilabos_msgs/action/ResourceCreateFromOuterEasy.action
@@ -6,7 +6,8 @@ geometry_msgs/Point bind_locations
int32[] liquid_input_slot
string[] liquid_type
float32[] liquid_volume
-int32 slot_on_deck
+string slot_on_deck
---
+string return_info
bool success
---
diff --git a/unilabos_msgs/action/SendCmd.action b/unilabos_msgs/action/SendCmd.action
index cc88320..6f453f6 100644
--- a/unilabos_msgs/action/SendCmd.action
+++ b/unilabos_msgs/action/SendCmd.action
@@ -1,6 +1,7 @@
# Simple
string command
---
+string return_info
bool success
---
string status
diff --git a/unilabos_msgs/action/Separate.action b/unilabos_msgs/action/Separate.action
index 502b420..fe8976a 100644
--- a/unilabos_msgs/action/Separate.action
+++ b/unilabos_msgs/action/Separate.action
@@ -13,6 +13,7 @@ float64 stir_time # Optional. Time stir for after adding solvent, before separat
float64 stir_speed # Optional. Speed to stir at after adding solvent, before separation of phases.
float64 settling_time # Optional. Time
---
+string return_info
bool success
---
string status
diff --git a/unilabos_msgs/action/SolidDispenseAddPowderTube.action b/unilabos_msgs/action/SolidDispenseAddPowderTube.action
index 674c4ff..db0924e 100644
--- a/unilabos_msgs/action/SolidDispenseAddPowderTube.action
+++ b/unilabos_msgs/action/SolidDispenseAddPowderTube.action
@@ -2,6 +2,7 @@ int32 powder_tube_number
string target_tube_position
float64 compound_mass
---
+string return_info
float64 actual_mass_mg
bool success
---
\ No newline at end of file
diff --git a/unilabos_msgs/action/Stir.action b/unilabos_msgs/action/Stir.action
index defbed3..9542f9d 100644
--- a/unilabos_msgs/action/Stir.action
+++ b/unilabos_msgs/action/Stir.action
@@ -3,6 +3,7 @@ float64 stir_time
float64 stir_speed
float64 settling_time
---
+string return_info
bool success
---
string status
\ No newline at end of file
diff --git a/unilabos_msgs/action/StrSingleInput.action b/unilabos_msgs/action/StrSingleInput.action
index bb762a5..bac365b 100644
--- a/unilabos_msgs/action/StrSingleInput.action
+++ b/unilabos_msgs/action/StrSingleInput.action
@@ -1,4 +1,5 @@
string string
---
+string return_info
bool success
---
\ No newline at end of file
diff --git a/unilabos_msgs/action/WorkStationRun.action b/unilabos_msgs/action/WorkStationRun.action
index ea75668..5ca9fd4 100644
--- a/unilabos_msgs/action/WorkStationRun.action
+++ b/unilabos_msgs/action/WorkStationRun.action
@@ -3,6 +3,7 @@ string wf_name
string params
Resource resource
---
+string return_info
bool success
---
string status