Initial commit

This commit is contained in:
Junhan Chang
2025-04-17 15:19:47 +08:00
parent a47a3f5c3a
commit c78ac482d8
262 changed files with 39871 additions and 0 deletions

View File

View File

@@ -0,0 +1,9 @@
io_snrd:
class:
module: unilabos.device_comms.SRND_16_IO:SRND_16_IO
type: python
hardware_interface:
name: modbus_client
extra_info: address
read: read_io_coil
write: write_io_coil

View File

@@ -0,0 +1,6 @@
serial:
class:
module: unilabos.ros.nodes.presets:ROS2SerialNode
type: ros2
schema:
properties: {}

View File

@@ -0,0 +1,23 @@
# 光学表征设备:红外、紫外可见、拉曼等
raman_home_made:
class:
module: unilabos.devices.raman_uv.home_made_raman:RamanObj
type: python
status_types:
status: String
action_value_mappings:
raman_cmd:
type: SendCmd
goal:
command: command
feedback: {}
result:
success: success
schema:
properties:
status:
type: string
required:
- status
additionalProperties: false
type: object

View File

@@ -0,0 +1,189 @@
liquid_handler:
class:
module: pylabrobot.liquid_handling:LiquidHandler
type: python
status_types:
name: String
action_value_mappings:
aspirate:
type: LiquidHandlerAspirate
goal:
resources: resources
vols: vols
use_channels: use_channels
flow_rates: flow_rates
end_delay: end_delay
offsets: offsets
liquid_height: liquid_height
blow_out_air_volume: blow_out_air_volume
feedback: {}
result:
name: name
discard_tips:
type: LiquidHandlerDiscardTips
goal:
use_channels: use_channels
feedback: {}
result:
name: name
dispense:
type: LiquidHandlerDispense
goal:
resources: resources
vols: vols
use_channels: use_channels
flow_rates: flow_rates
offsets: offsets
blow_out_air_volume: blow_out_air_volume
spread: spread
feedback: {}
result:
name: name
drop_tips:
type: LiquidHandlerDropTips
goal:
tip_spots: tip_spots
use_channels: use_channels
offsets: offsets
allow_nonzero_volume: allow_nonzero_volume
feedback: {}
result:
name: name
drop_tips96:
type: LiquidHandlerDropTips96
goal:
tip_rack: tip_rack
offset: offset
allow_nonzero_volume: allow_nonzero_volume
feedback: {}
result:
name: name
move_lid:
type: LiquidHandlerMoveLid
goal:
lid: lid
to: to
intermediate_locations: intermediate_locations
resource_offset: resource_offset
destination_offset: destination_offset
pickup_direction: pickup_direction
drop_direction: drop_direction
get_direction: get_direction
put_direction: put_direction
pickup_distance_from_top: pickup_distance_from_top
feedback: {}
result:
name: name
move_plate:
type: LiquidHandlerMovePlate
goal:
plate: plate
to: to
intermediate_locations: intermediate_locations
resource_offset: resource_offset
pickup_offset: pickup_offset
destination_offset: destination_offset
pickup_direction: pickup_direction
drop_direction: drop_direction
get_direction: get_direction
put_direction: put_direction
feedback: {}
result:
name: name
move_resource:
type: LiquidHandlerMoveResource
goal:
resource: resource
to: to
intermediate_locations: intermediate_locations
resource_offset: resource_offset
destination_offset: destination_offset
pickup_distance_from_top: pickup_distance_from_top
pickup_direction: pickup_direction
drop_direction: drop_direction
get_direction: get_direction
put_direction: put_direction
feedback: {}
result:
name: name
pick_up_tips:
type: LiquidHandlerPickUpTips
goal:
tip_spots: tip_spots
use_channels: use_channels
offsets: offsets
feedback: {}
result:
name: name
pick_up_tips96:
type: LiquidHandlerPickUpTips96
goal:
tip_rack: tip_rack
offset: offset
feedback: {}
result:
name: name
return_tips:
type: LiquidHandlerReturnTips
goal:
use_channels: use_channels
allow_nonzero_volume: allow_nonzero_volume
feedback: {}
result:
name: name
return_tips96:
type: LiquidHandlerReturnTips96
goal:
allow_nonzero_volume: allow_nonzero_volume
feedback: {}
result:
name: name
stamp:
type: LiquidHandlerStamp
goal:
source: source
target: target
volume: volume
aspiration_flow_rate: aspiration_flow_rate
dispense_flow_rate: dispense_flow_rate
feedback: {}
result:
name: name
transfer:
type: LiquidHandlerTransfer
goal:
source: source
targets: targets
source_vol: source_vol
ratios: ratios
target_vols: target_vols
aspiration_flow_rate: aspiration_flow_rate
dispense_flow_rates: dispense_flow_rates
schema:
type: object
properties:
status:
type: string
description: 液体处理仪器当前状态
required:
- status
additionalProperties: false
liquid_handler.revvity:
class:
module: unilabos.devices.liquid_handling.revvity:Revvity
type: python
status_types:
status: String
action_value_mappings:
run:
type: WorkStationRun
goal:
wf_name: file_path
params: params
resource: resource
feedback:
status: status
result:
success: success

View File

@@ -0,0 +1,71 @@
separator.homemade:
class:
module: unilabos.devices.separator.homemade_grbl_conductivity:Separator_Controller
type: python
status_types:
sensordata: Float64
status: String
action_value_mappings:
stir:
type: Stir
goal:
stir_time: stir_time,
stir_speed: stir_speed
settling_time": settling_time
feedback:
status: status
result:
success: success
valve_open_cmd:
type: SendCmd
goal:
command: command
feedback:
status: status
result":
success: success
schema:
type: object
properties:
status:
type: string
description: The status of the device
sensordata:
type: number
description: 电导传感器数据
required:
- status
- sensordata
additionalProperties: false
rotavap.one:
class:
module: unilabos.devices.rotavap.rotavap_one:RotavapOne
type: python
status_types:
pump_time: Float64
rotate_time: Float64
action_value_mappings:
set_timer:
type: SendCmd
goal:
command: command
feedback: {}
result:
success: success
schema:
type: object
properties:
temperature:
type: number
description: 旋蒸水浴温度
pump_time:
type: number
description: The pump time of the device
rotate_time:
type: number
description: The rotate time of the device
required:
- pump_time
- rotate_time
additionalProperties: false

View File

@@ -0,0 +1,35 @@
syringe_pump_with_valve.runze:
class:
module: unilabos.devices.pump_and_valve.runze_backbone:RunzeSyringePump
type: python
schema:
type: object
properties:
status:
type: string
description: The status of the device
position:
type: number
description: The volume of the syringe
speed_max:
type: number
description: The speed of the syringe
valve_position:
type: string
description: The position of the valve
required:
- status
- position
- valve_position
additionalProperties: false
solenoid_valve.mock:
class:
module: unilabos.devices.pump_and_valve.solenoid_valve_mock:SolenoidValveMock
type: python
solenoid_valve:
class:
module: unilabos.devices.pump_and_valve.solenoid_valve:SolenoidValve
type: python

View File

@@ -0,0 +1,28 @@
# 仙工智能底盘(知行使用)
agv.SEER:
class:
module: unilabos.devices.agv.agv_navigator:AgvNavigator
type: python
status_types:
pose: Float64MultiArray
status: String
action_value_mappings:
send_nav_task:
type: SendCmd
goal:
command: command
feedback: {}
result:
success: success
schema:
properties:
pose:
type: array
items:
type: number
status:
type: string
required:
- status
additionalProperties: false
type: object

View File

@@ -0,0 +1,36 @@
robotic_arm.UR:
class:
module: unilabos.devices.agv.ur_arm_task:UrArmTask
type: python
status_types:
arm_pose: Float64MultiArray
gripper_pose: Float64
arm_status: String
gripper_status: String
action_value_mappings:
move_pos_task:
type: SendCmd
goal:
command: command
feedback: {}
result:
success: success
schema:
properties:
arm_pose:
type: array
items:
type: number
gripper_pose:
type: number
arm_status:
type: string
description: 机械臂设备状态
gripper_status:
type: string
description: 机械爪设备状态
required:
- arm_status
- gripper_status
additionalProperties: false
type: object

View File

@@ -0,0 +1,36 @@
gripper.mock:
class:
module: unilabos.devices.gripper.mock:MockGripper
type: python
status_types:
position: Float64
torque: Float64
status: String
action_value_mappings:
push_to:
type: GripperCommand
goal:
command.position: position
command.max_effort: torque
feedback:
position: position
effort: torque
result:
position: position
effort: torque
gripper.misumi_rz:
class:
module: unilabos.devices.motor:Grasp.EleGripper
type: python
status_types:
status: String
action_value_mappings:
execute_command_from_outer:
type: SendCmd
goal:
command: command
feedback: {}
result:
success: success

View File

@@ -0,0 +1,55 @@
linear_motion.grbl:
class:
module: unilabos.devices.cnc.grbl_sync:GrblCNC
type: python
action_value_mappings:
move_through_points: &move_through_points
type: NavigateThroughPoses
goal:
poses[].pose.position: positions[]
feedback:
current_pose.pose.position: position
navigation_time.sec: time_spent
estimated_time_remaining.sec: time_remaining
number_of_poses_remaining: pose_number_remaining
result: {}
set_spindle_speed:
type: SingleJointPosition
goal:
position: spindle_speed
feedback:
position: spindle_speed
result: {}
schema:
type: object
properties:
position:
type: array
items:
type: number
description: The position of the device
spindle_speed:
type: number
description: The spindle speed of the device
required:
- position
- spindle_speed
additionalProperties: false
motor.iCL42:
class:
module: unilabos.devices.motor.iCL42:iCL42Driver
type: python
status_types:
motor_position: Int64
is_executing_run: Bool
success: Bool
action_value_mappings:
execute_command_from_outer:
type: SendCmd
goal:
command: command
feedback: {}
result:
success: success

View File

@@ -0,0 +1,62 @@
heaterstirrer.dalong:
class:
module: unilabos.devices.heaterstirrer.dalong:HeaterStirrer_DaLong
type: python
status_types:
temp: Float64
temp_warning: Float64
stir_speed: Float64
action_value_mappings:
set_temp_warning:
type: SendCmd
goal:
command: temp
feedback: {}
result:
success: success
set_temp_target:
type: SendCmd
goal:
command: temp
feedback: {}
result:
success: success
heatchill:
type: HeatChill
goal:
vessel: vessel
temp: temp
time: time
purpose: purpose
feedback:
status: status
result:
success: success
chiller:
class:
module: unilabos.devices.temperature.chiller:Chiller
type: python
action_value_mappings:
set_temperature:
type: SendCmd
goal:
command: command
feedback: {}
result:
success: success
tempsensor:
class:
module: unilabos.devices.temperature.sensor_node:TempSensorNode
type: python
status_types:
value: Float64
warning: Float64
action_value_mappings:
set_warning:
type: SendCmd
goal:
command: command
feedback: {}
result:
success: success

View File

@@ -0,0 +1,9 @@
vacuum_pump.mock:
class:
module: unilabos.devices.pump_and_valve.vacuum_pump_mock:VacuumPumpMock
type: python
gas_source.mock:
class:
module: unilabos.devices.pump_and_valve.vacuum_pump_mock:VacuumPumpMock
type: python

View File

@@ -0,0 +1,6 @@
workstation:
class:
module: unilabos.ros.nodes.presets.protocol_node:ROS2ProtocolNode
type: ros2
schema:
properties: {}

View File

@@ -0,0 +1,176 @@
import os
import sys
from pathlib import Path
from typing import Any
import yaml
from unilabos.utils import logger
from unilabos.ros.msgs.message_converter import msg_converter_manager
from unilabos.utils.decorator import singleton
DEFAULT_PATHS = [Path(__file__).absolute().parent]
@singleton
class Registry:
def __init__(self, registry_paths=None):
self.registry_paths = DEFAULT_PATHS.copy() # 使用copy避免修改默认值
if registry_paths:
self.registry_paths.extend(registry_paths)
self.device_type_registry = {}
self.resource_type_registry = {}
self._setup_called = False # 跟踪setup是否已调用
# 其他状态变量
# self.is_host_mode = False # 移至BasicConfig中
def setup(self):
# 检查是否已调用过setup
if self._setup_called:
logger.critical("[UniLab Registry] setup方法已被调用过不允许多次调用")
return
# 标记setup已被调用
self._setup_called = True
logger.debug(f"[UniLab Registry] ----------Setup----------")
self.registry_paths = [Path(path).absolute() for path in self.registry_paths]
for i, path in enumerate(self.registry_paths):
sys_path = path.parent
logger.debug(f"[UniLab Registry] Path {i+1}/{len(self.registry_paths)}: {sys_path}")
sys.path.append(str(sys_path))
self.load_device_types(path)
self.load_resource_types(path)
logger.info("[UniLab Registry] 注册表设置完成")
def load_resource_types(self, path: os.PathLike):
abs_path = Path(path).absolute()
resource_path = abs_path / "resources"
files = list(resource_path.glob("*/*.yaml"))
logger.debug(f"[UniLab Registry] resources: {resource_path.exists()}, total: {len(files)}")
current_resource_number = len(self.resource_type_registry) + 1
for i, file in enumerate(files):
data = yaml.safe_load(open(file, encoding="utf-8"))
if data:
# 为每个资源添加文件路径信息
for resource_id, resource_info in data.items():
# 添加文件路径 - 使用规范化的完整文件路径
resource_info["file_path"] = str(file.absolute()).replace("\\", "/")
self.resource_type_registry.update(data)
logger.debug(
f"[UniLab Registry] Resource-{current_resource_number} File-{i+1}/{len(files)} "
+ f"Add {list(data.keys())}"
)
current_resource_number += 1
else:
logger.debug(f"[UniLab Registry] Res File-{i+1}/{len(files)} Not Valid YAML File: {file.absolute()}")
def _replace_type_with_class(self, type_name: str, device_id: str, field_name: str) -> Any:
"""
将类型名称替换为实际的类对象
Args:
type_name: 类型名称
device_id: 设备ID用于错误信息
field_name: 字段名称,用于错误信息
Returns:
找到的类对象或原始字符串
Raises:
SystemExit: 如果找不到类型则终止程序
"""
# 如果类型名为空,跳过替换
if not type_name or type_name == "":
logger.warning(f"[UniLab Registry] 设备 {device_id}{field_name} 类型为空,跳过替换")
return type_name
if "." in type_name:
type_class = msg_converter_manager.get_class(type_name)
else:
type_class = msg_converter_manager.search_class(type_name)
if type_class:
return type_class
else:
logger.error(f"[UniLab Registry] 无法找到类型 '{type_name}' 用于设备 {device_id}{field_name}")
sys.exit(1)
def load_device_types(self, path: os.PathLike):
abs_path = Path(path).absolute()
devices_path = abs_path / "devices"
device_comms_path = abs_path / "device_comms"
files = list(devices_path.glob("*.yaml")) + list(device_comms_path.glob("*.yaml"))
logger.debug(
f"[UniLab Registry] devices: {devices_path.exists()}, device_comms: {device_comms_path.exists()}, "
+ f"total: {len(files)}"
)
current_device_number = len(self.device_type_registry) + 1
for i, file in enumerate(files):
data = yaml.safe_load(open(file, encoding="utf-8"))
if data:
# 在添加到注册表前处理类型替换
for device_id, device_config in data.items():
# 添加文件路径信息 - 使用规范化的完整文件路径
device_config["file_path"] = str(file.absolute()).replace("\\", "/")
if "class" in device_config:
# 处理状态类型
if "status_types" in device_config["class"]:
for status_name, status_type in device_config["class"]["status_types"].items():
device_config["class"]["status_types"][status_name] = self._replace_type_with_class(
status_type, device_id, f"状态 {status_name}"
)
# 处理动作值映射
if "action_value_mappings" in device_config["class"]:
for action_name, action_config in device_config["class"]["action_value_mappings"].items():
if "type" in action_config:
action_config["type"] = self._replace_type_with_class(
action_config["type"], device_id, f"动作 {action_name}"
)
self.device_type_registry.update(data)
for device_id in data.keys():
logger.debug(
f"[UniLab Registry] Device-{current_device_number} File-{i+1}/{len(files)} Add {device_id} "
+ f"[{data[device_id].get('name', '未命名设备')}]"
)
current_device_number += 1
else:
logger.debug(
f"[UniLab Registry] Device File-{i+1}/{len(files)} Not Valid YAML File: {file.absolute()}"
)
# 全局单例实例
lab_registry = Registry()
def build_registry(registry_paths=None):
"""
构建或获取Registry单例实例
Args:
registry_paths: 额外的注册表路径列表
Returns:
Registry实例
"""
logger.info("[UniLab Registry] 构建注册表实例")
# 由于使用了单例,这里不需要重新创建实例
global lab_registry
# 如果有额外路径添加到registry_paths
if registry_paths:
current_paths = lab_registry.registry_paths.copy()
# 检查是否有新路径需要添加
for path in registry_paths:
if path not in current_paths:
lab_registry.registry_paths.append(path)
# 初始化注册表
lab_registry.setup()
return lab_registry

View File

@@ -0,0 +1,4 @@
OTDeck:
class:
module: pylabrobot.resources.opentrons.deck:OTDeck
type: pylabrobot

View File

@@ -0,0 +1,4 @@
Opentrons_96_adapter_Vb:
class:
module: pylabrobot.resources.opentrons.plate_adapters:Opentrons_96_adapter_Vb
type: pylabrobot

View File

@@ -0,0 +1,74 @@
corning_6_wellplate_16point8ml_flat:
class:
module: pylabrobot.resources.opentrons.plates:corning_6_wellplate_16point8ml_flat
type: pylabrobot
corning_12_wellplate_6point9ml_flat:
class:
module: pylabrobot.resources.opentrons.plates:corning_12_wellplate_6point9ml_flat
type: pylabrobot
corning_24_wellplate_3point4ml_flat:
class:
module: pylabrobot.resources.opentrons.plates:corning_24_wellplate_3point4ml_flat
type: pylabrobot
corning_48_wellplate_1point6ml_flat:
class:
module: pylabrobot.resources.opentrons.plates:corning_48_wellplate_1point6ml_flat
type: pylabrobot
corning_96_wellplate_360ul_flat:
class:
module: pylabrobot.resources.opentrons.plates:corning_96_wellplate_360ul_flat
type: pylabrobot
corning_384_wellplate_112ul_flat:
class:
module: pylabrobot.resources.opentrons.plates:corning_384_wellplate_112ul_flat
type: pylabrobot
nest_96_wellplate_2ml_deep:
class:
module: pylabrobot.resources.opentrons.plates:nest_96_wellplate_2ml_deep
type: pylabrobot
nest_96_wellplate_200ul_flat:
class:
module: pylabrobot.resources.opentrons.plates:nest_96_wellplate_200ul_flat
type: pylabrobot
nest_96_wellplate_100ul_pcr_full_skirt:
class:
module: pylabrobot.resources.opentrons.plates:nest_96_wellplate_100ul_pcr_full_skirt
type: pylabrobot
appliedbiosystemsmicroamp_384_wellplate_40ul:
class:
module: pylabrobot.resources.opentrons.plates:appliedbiosystemsmicroamp_384_wellplate_40ul
type: pylabrobot
thermoscientificnunc_96_wellplate_1300ul:
class:
module: pylabrobot.resources.opentrons.plates:thermoscientificnunc_96_wellplate_1300ul
type: pylabrobot
thermoscientificnunc_96_wellplate_2000ul:
class:
module: pylabrobot.resources.opentrons.plates:thermoscientificnunc_96_wellplate_2000ul
type: pylabrobot
usascientific_96_wellplate_2point4ml_deep:
class:
module: pylabrobot.resources.opentrons.plates:usascientific_96_wellplate_2point4ml_deep
type: pylabrobot
biorad_96_wellplate_200ul_pcr:
class:
module: pylabrobot.resources.opentrons.plates:biorad_96_wellplate_200ul_pcr
type: pylabrobot
biorad_384_wellplate_50ul:
class:
module: pylabrobot.resources.opentrons.plates:biorad_384_wellplate_50ul
type: pylabrobot

View File

@@ -0,0 +1,29 @@
agilent_1_reservoir_290ml:
class:
module: pylabrobot.resources.opentrons.reserviors:agilent_1_reservoir_290ml
type: pylabrobot
axygen_1_reservoir_90ml:
class:
module: pylabrobot.resources.opentrons.reserviors:axygen_1_reservoir_90ml
type: pylabrobot
nest_12_reservoir_15ml:
class:
module: pylabrobot.resources.opentrons.reserviors:nest_12_reservoir_15ml
type: pylabrobot
nest_1_reservoir_195ml:
class:
module: pylabrobot.resources.opentrons.reserviors:nest_1_reservoir_195ml
type: pylabrobot
nest_1_reservoir_290ml:
class:
module: pylabrobot.resources.opentrons.reserviors:nest_1_reservoir_290ml
type: pylabrobot
usascientific_12_reservoir_22ml:
class:
module: pylabrobot.resources.opentrons.reserviors:usascientific_12_reservoir_22ml
type: pylabrobot

View File

@@ -0,0 +1,64 @@
eppendorf_96_tiprack_1000ul_eptips:
class:
module: pylabrobot.resources.opentrons.tip_racks:eppendorf_96_tiprack_1000ul_eptips
type: pylabrobot
tipone_96_tiprack_200ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:tipone_96_tiprack_200ul
type: pylabrobot
opentrons_96_tiprack_300ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:opentrons_96_tiprack_300ul
type: pylabrobot
opentrons_96_tiprack_10ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:opentrons_96_tiprack_10ul
type: pylabrobot
opentrons_96_filtertiprack_10ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:opentrons_96_filtertiprack_10ul
type: pylabrobot
geb_96_tiprack_10ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:geb_96_tiprack_10ul
type: pylabrobot
opentrons_96_filtertiprack_200ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:opentrons_96_filtertiprack_200ul
type: pylabrobot
eppendorf_96_tiprack_10ul_eptips:
class:
module: pylabrobot.resources.opentrons.tip_racks:eppendorf_96_tiprack_10ul_eptips
type: pylabrobot
opentrons_96_tiprack_1000ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:opentrons_96_tiprack_1000ul
type: pylabrobot
opentrons_96_tiprack_20ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:opentrons_96_tiprack_20ul
type: pylabrobot
opentrons_96_filtertiprack_1000ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:opentrons_96_filtertiprack_1000ul
type: pylabrobot
opentrons_96_filtertiprack_20ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:opentrons_96_filtertiprack_20ul
type: pylabrobot
geb_96_tiprack_1000ul:
class:
module: pylabrobot.resources.opentrons.tip_racks:geb_96_tiprack_1000ul
type: pylabrobot

View File

@@ -0,0 +1,99 @@
opentrons_24_tuberack_eppendorf_2ml_safelock_snapcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_eppendorf_2ml_safelock_snapcap
type: pylabrobot
opentrons_24_tuberack_eppendorf_2ml_safelock_snapcap_acrylic:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_eppendorf_2ml_safelock_snapcap_acrylic
type: pylabrobot
opentrons_6_tuberack_falcon_50ml_conical:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_6_tuberack_falcon_50ml_conical
type: pylabrobot
opentrons_15_tuberack_nest_15ml_conical:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_15_tuberack_nest_15ml_conical
type: pylabrobot
opentrons_24_tuberack_nest_2ml_screwcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_nest_2ml_screwcap
type: pylabrobot
opentrons_24_tuberack_generic_0point75ml_snapcap_acrylic:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_generic_0point75ml_snapcap_acrylic
type: pylabrobot
opentrons_10_tuberack_nest_4x50ml_6x15ml_conical:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_10_tuberack_nest_4x50ml_6x15ml_conical
type: pylabrobot
opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical_acrylic:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical_acrylic
type: pylabrobot
opentrons_24_tuberack_nest_1point5ml_screwcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_nest_1point5ml_screwcap
type: pylabrobot
opentrons_24_tuberack_nest_1point5ml_snapcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_nest_1point5ml_snapcap
type: pylabrobot
opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical
type: pylabrobot
opentrons_24_tuberack_nest_2ml_snapcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_nest_2ml_snapcap
type: pylabrobot
opentrons_24_tuberack_nest_0point5ml_screwcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_nest_0point5ml_screwcap
type: pylabrobot
opentrons_24_tuberack_eppendorf_1point5ml_safelock_snapcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_eppendorf_1point5ml_safelock_snapcap
type: pylabrobot
opentrons_6_tuberack_nest_50ml_conical:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_6_tuberack_nest_50ml_conical
type: pylabrobot
opentrons_15_tuberack_falcon_15ml_conical:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_15_tuberack_falcon_15ml_conical
type: pylabrobot
opentrons_24_tuberack_generic_2ml_screwcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_tuberack_generic_2ml_screwcap
type: pylabrobot
opentrons_96_well_aluminum_block:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_96_well_aluminum_block
type: pylabrobot
opentrons_24_aluminumblock_generic_2ml_screwcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_aluminumblock_generic_2ml_screwcap
type: pylabrobot
opentrons_24_aluminumblock_nest_1point5ml_snapcap:
class:
module: pylabrobot.resources.opentrons.tube_racks:opentrons_24_aluminumblock_nest_1point5ml_snapcap
type: pylabrobot