Files
Uni-Lab-OS/.cursor/skills/add-resource/SKILL.md
2026-03-06 16:54:31 +08:00

11 KiB
Raw Blame History

name, description
name description
add-resource Guide for adding new resources (materials, bottles, carriers, decks, warehouses) to Uni-Lab-OS (添加新物料/资源). Covers Bottle, Carrier, Deck, WareHouse definitions and registry YAML. Use when the user wants to add resources, define materials, create a deck layout, add bottles/carriers/plates, or mentions 物料/资源/resource/bottle/carrier/deck/plate/warehouse.

添加新物料资源

Uni-Lab-OS 的资源体系基于 PyLabRobot通过扩展实现 Bottle、Carrier、WareHouse、Deck 等实验室物料管理。


第一步:确认资源类型

向用户确认需要添加的资源类型:

类型 基类 用途 示例
Bottle Well (PyLabRobot) 单个容器(瓶、小瓶、烧杯、反应器) 试剂瓶、粉末瓶
BottleCarrier ItemizedCarrier 多槽位载架(放多个 Bottle 6 位试剂架、枪头盒
WareHouse ItemizedCarrier 堆栈/仓库(放多个 Carrier 4x4 堆栈
Deck Deck (PyLabRobot) 工作站台面(放多个 WareHouse 反应站 Deck

层级关系: DeckWareHouseBottleCarrierBottle

还需确认:

  • 资源所属的项目/场景(如 bioyond、battery、通用
  • 尺寸参数(直径、高度、最大容积等)
  • 布局参数(行列数、间距等)

第二步:创建资源定义

文件位置

unilabos/resources/
├── <project>/          # 按项目分组
│   ├── bottles.py      # Bottle 工厂函数
│   ├── bottle_carriers.py  # Carrier 工厂函数
│   ├── warehouses.py   # WareHouse 工厂函数
│   └── decks.py        # Deck 类定义
├── itemized_carrier.py # Bottle, BottleCarrier, ItemizedCarrier 基类
├── warehouse.py        # WareHouse 基类
└── container.py        # 通用容器

2A. 添加 Bottle工厂函数

from unilabos.resources.itemized_carrier import Bottle


def My_Reagent_Bottle(
    name: str,
    diameter: float = 70.0,     # 瓶体直径 (mm)
    height: float = 120.0,      # 瓶体高度 (mm)
    max_volume: float = 500000.0,  # 最大容积 (μL)
    barcode: str = None,
) -> Bottle:
    """创建试剂瓶"""
    return Bottle(
        name=name,
        diameter=diameter,
        height=height,
        max_volume=max_volume,
        barcode=barcode,
        model="My_Reagent_Bottle",  # 唯一标识,用于注册表和物料映射
    )

Bottle 参数:

  • name: 实例名称(运行时唯一)
  • diameter: 瓶体直径 (mm)
  • height: 瓶体高度 (mm)
  • max_volume: 最大容积 (μL注意单位500mL = 500000)
  • barcode: 条形码(可选)
  • model: 模型标识,与注册表 key 一致

2B. 添加 BottleCarrier工厂函数

from pylabrobot.resources import ResourceHolder
from pylabrobot.resources.carrier import create_ordered_items_2d

from unilabos.resources.itemized_carrier import BottleCarrier


def My_6SlotCarrier(name: str) -> BottleCarrier:
    """创建 3x2 六槽位载架"""
    sites = create_ordered_items_2d(
        klass=ResourceHolder,
        num_items_x=3,       # 列数
        num_items_y=2,       # 行数
        dx=10.0,             # X 起始偏移
        dy=10.0,             # Y 起始偏移
        dz=5.0,              # Z 偏移
        item_dx=42.0,        # X 间距
        item_dy=35.0,        # Y 间距
        size_x=20.0,         # 槽位宽
        size_y=20.0,         # 槽位深
        size_z=50.0,         # 槽位高
    )
    carrier = BottleCarrier(
        name=name,
        size_x=146.0,        # 载架总宽
        size_y=80.0,         # 载架总深
        size_z=55.0,         # 载架总高
        sites=sites,
        model="My_6SlotCarrier",
    )
    carrier.num_items_x = 3
    carrier.num_items_y = 2
    carrier.num_items_z = 1

    # 预装 Bottle可选
    ordering = ["A01", "A02", "A03", "B01", "B02", "B03"]
    for i in range(6):
        carrier[i] = My_Reagent_Bottle(f"{ordering[i]}")

    return carrier

2C. 添加 WareHouse工厂函数

from unilabos.resources.warehouse import warehouse_factory


def my_warehouse_4x4(name: str) -> "WareHouse":
    """创建 4行x4列 堆栈仓库"""
    return warehouse_factory(
        name=name,
        num_items_x=4,            # 列数
        num_items_y=4,            # 行数
        num_items_z=1,            # 层数(通常为 1
        dx=137.0,                 # X 起始偏移
        dy=96.0,                  # Y 起始偏移
        dz=120.0,                 # Z 起始偏移
        item_dx=137.0,            # X 间距
        item_dy=125.0,            # Y 间距
        item_dz=10.0,             # Z 间距(多层时用)
        resource_size_x=127.0,    # 槽位宽
        resource_size_y=85.0,     # 槽位深
        resource_size_z=100.0,    # 槽位高
        model="my_warehouse_4x4",
    )

warehouse_factory 参数说明:

参数 说明
num_items_x/y/z 列数/行数/层数
dx, dy, dz 第一个槽位的起始坐标偏移
item_dx, item_dy, item_dz 相邻槽位间距
resource_size_x/y/z 单个槽位的物理尺寸
col_offset 列命名偏移(如设 4 则从 A05 开始)
row_offset 行命名偏移(如设 5 则从 F 行开始)
layout 排序方式:"col-major"(列优先,默认)/ "row-major"(行优先)
removed_positions 要移除的位置索引列表

自动生成 ResourceHolder 槽位,命名规则为 A01, B01, C01, D01, A02, ...(列优先)或 A01, A02, A03, A04, B01, ...(行优先)。

2D. 添加 Deck类定义

from pylabrobot.resources import Deck, Coordinate


class MyStation_Deck(Deck):
    def __init__(
        self,
        name: str = "MyStation_Deck",
        size_x: float = 2700.0,
        size_y: float = 1080.0,
        size_z: float = 1500.0,
        category: str = "deck",
        setup: bool = False,
    ) -> None:
        super().__init__(name=name, size_x=size_x, size_y=size_y, size_z=size_z)
        if setup:
            self.setup()

    def setup(self) -> None:
        self.warehouses = {
            "仓库A": my_warehouse_4x4("仓库A"),
            "仓库B": my_warehouse_4x4("仓库B"),
        }
        self.warehouse_locations = {
            "仓库A": Coordinate(-200.0, 400.0, 0.0),
            "仓库B": Coordinate(2350.0, 400.0, 0.0),
        }
        for wh_name, wh in self.warehouses.items():
            self.assign_child_resource(wh, location=self.warehouse_locations[wh_name])

Deck 要点:

  • 继承 pylabrobot.resources.Deck
  • setup() 创建 WareHouse 并通过 assign_child_resource 放置到指定坐标
  • setup 参数控制是否在构造时自动调用 setup()(图文件中通过 config.setup: true 触发)

第三步:创建注册表 YAML

路径:unilabos/registry/resources/<project>/<type>.yaml

Bottle 注册

My_Reagent_Bottle:
  category:
  - bottles
  class:
    module: unilabos.resources.my_project.bottles:My_Reagent_Bottle
    type: pylabrobot
  description: 我的试剂瓶
  handles: []
  icon: ''
  init_param_schema: {}
  version: 1.0.0

Carrier 注册

My_6SlotCarrier:
  category:
  - bottle_carriers
  class:
    module: unilabos.resources.my_project.bottle_carriers:My_6SlotCarrier
    type: pylabrobot
  handles: []
  icon: ''
  init_param_schema: {}
  version: 1.0.0

Deck 注册

MyStation_Deck:
  category:
  - deck
  class:
    module: unilabos.resources.my_project.decks:MyStation_Deck
    type: pylabrobot
  description: 我的工作站 Deck
  handles: []
  icon: ''
  init_param_schema: {}
  registry_type: resource
  version: 1.0.0

注册表规则:

  • class.module 格式为 python.module.path:ClassName_or_FunctionName
  • class.type 固定为 pylabrobot
  • KeyMy_Reagent_Bottle)必须与工厂函数名 / 类名一致
  • category 按类型标注(bottles, bottle_carriers, deck 等)

第四步:在图文件中引用

Deck 在工作站中的引用

工作站节点通过 deck 字段引用Deck 作为子节点:

{
    "id": "my_station",
    "children": ["my_deck"],
    "deck": {
        "data": {
            "_resource_child_name": "my_deck",
            "_resource_type": "unilabos.resources.my_project.decks:MyStation_Deck"
        }
    }
},
{
    "id": "my_deck",
    "parent": "my_station",
    "type": "deck",
    "class": "MyStation_Deck",
    "config": {"type": "MyStation_Deck", "setup": true}
}

物料类型映射(外部系统对接时)

如果工作站需要与外部系统同步物料,在 config 中配置 material_type_mappings

"material_type_mappings": {
    "My_Reagent_Bottle": ["试剂瓶", "external-type-uuid"],
    "My_6SlotCarrier": ["六槽载架", "external-type-uuid"]
}

第五步:注册 PLR 扩展(如需要)

如果添加了新的 Deck 类,需要在 unilabos/resources/plr_additional_res_reg.py 中导入,使 find_subclass 能发现它:

def register():
    from unilabos.resources.my_project.decks import MyStation_Deck

第六步:验证

# 1. 资源可导入
python -c "from unilabos.resources.my_project.bottles import My_Reagent_Bottle; print(My_Reagent_Bottle('test'))"

# 2. Deck 可创建
python -c "
from unilabos.resources.my_project.decks import MyStation_Deck
d = MyStation_Deck('test', setup=True)
print(d.children)
"

# 3. 启动测试
unilab -g <graph>.json --complete_registry

工作流清单

资源接入进度:
- [ ] 1. 确定资源类型Bottle / Carrier / WareHouse / Deck
- [ ] 2. 创建资源定义(工厂函数/类)
- [ ] 3. 创建注册表 YAML (unilabos/registry/resources/<project>/<type>.yaml)
- [ ] 4. 在图文件中引用(如需要)
- [ ] 5. 注册 PLR 扩展Deck 类需要)
- [ ] 6. 验证

高级模式

实现复杂资源系统时,详见 reference.md:类继承体系完整图、序列化/反序列化流程、Bioyond 物料双向同步、非瓶类资源ElectrodeSheet / Magazine、仓库工厂 layout 模式。


现有资源参考

项目 Bottles Carriers WareHouses Decks
bioyond bioyond/bottles.py bioyond/bottle_carriers.py bioyond/warehouses.py, YB_warehouses.py bioyond/decks.py
battery battery/bottle_carriers.py
通用 warehouse.py

关键路径

内容 路径
Bottle/Carrier 基类 unilabos/resources/itemized_carrier.py
WareHouse 基类 + 工厂 unilabos/resources/warehouse.py
PLR 注册 unilabos/resources/plr_additional_res_reg.py
资源注册表 unilabos/registry/resources/
图文件加载 unilabos/resources/graphio.py
资源跟踪器 unilabos/resources/resource_tracker.py