diff --git a/test/resources/bioyond_materials_liquidhandling_1.json b/test/resources/bioyond_materials_liquidhandling_1.json new file mode 100644 index 00000000..dacf75da --- /dev/null +++ b/test/resources/bioyond_materials_liquidhandling_1.json @@ -0,0 +1,265 @@ +[ + { + "id": "3a1c62c4-c3d2-b803-b72d-7f1153ffef3b", + "typeName": "试剂瓶", + "code": "0004-00050", + "barCode": "", + "name": "NMP", + "quantity": 287.16699029126215, + "lockQuantity": 285.16699029126215, + "unit": "毫升", + "status": 1, + "isUse": false, + "locations": [ + { + "id": "3a14198c-c2d0-efce-0939-69ca5a7dfd39", + "whid": "3a14198c-c2cc-0290-e086-44a428fba248", + "whName": "试剂堆栈", + "code": "0001-0008", + "x": 2, + "y": 4, + "z": 1, + "quantity": 0 + } + ], + "detail": [] + }, + { + "id": "3a1cdefe-0e03-1bc1-1296-dae1905c4108", + "typeName": "试剂瓶", + "code": "0004-00052", + "barCode": "", + "name": "NMP", + "quantity": 386.8990291262136, + "lockQuantity": 45.89902912621359, + "unit": "毫升", + "status": 1, + "isUse": false, + "locations": [ + { + "id": "3a14198c-c2d0-f3e7-871a-e470d144296f", + "whid": "3a14198c-c2cc-0290-e086-44a428fba248", + "whName": "试剂堆栈", + "code": "0001-0005", + "x": 2, + "y": 1, + "z": 1, + "quantity": 0 + } + ], + "detail": [] + }, + { + "id": "3a1cdefe-0e03-68a4-bcb3-02fc6ba72d1b", + "typeName": "试剂瓶", + "code": "0004-00053", + "barCode": "", + "name": "NMP", + "quantity": 400.0, + "lockQuantity": 0.0, + "unit": "", + "status": 1, + "isUse": false, + "locations": [ + { + "id": "3a14198c-c2d0-2070-efc8-44e245f10c6f", + "whid": "3a14198c-c2cc-0290-e086-44a428fba248", + "whName": "试剂堆栈", + "code": "0001-0006", + "x": 2, + "y": 2, + "z": 1, + "quantity": 0 + } + ], + "detail": [] + }, + { + "id": "3a1cdefe-d5e0-3fa1-cc72-fda6276ae38d", + "typeName": "10%分装小瓶", + "code": "0005-00513", + "barCode": "", + "name": "10%分装小瓶", + "quantity": 1.0, + "lockQuantity": 1.0, + "unit": "个", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cdefe-d5e0-561f-73b6-f8501f814dbb", + "typeName": "90%分装小瓶", + "code": "0006-00497", + "barCode": "", + "name": "90%分装小瓶", + "quantity": 1.0, + "lockQuantity": 1.0, + "unit": "个", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cdefe-d5e0-81cf-7dad-2e51cab9ffd6", + "typeName": "90%分装小瓶", + "code": "0006-00496", + "barCode": "", + "name": "90%分装小瓶", + "quantity": 1.0, + "lockQuantity": 1.0, + "unit": "个", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cdefe-d5e0-94ae-f770-27847e73ad38", + "typeName": "90%分装小瓶", + "code": "0006-00498", + "barCode": "", + "name": "90%分装小瓶", + "quantity": 1.0, + "lockQuantity": 1.0, + "unit": "个", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cdefe-d5e0-c632-c7da-02d385b18628", + "typeName": "10%分装小瓶", + "code": "0005-00514", + "barCode": "", + "name": "10%分装小瓶", + "quantity": 1.0, + "lockQuantity": 1.0, + "unit": "个", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cdefe-d5e0-d850-5439-4499f20f07fe", + "typeName": "分装板", + "code": "0007-00185", + "barCode": "", + "name": "1010", + "quantity": 1.0, + "lockQuantity": 2.0, + "unit": "块", + "status": 1, + "isUse": false, + "locations": [ + { + "id": "3a14198e-6929-46fe-841e-03dd753f1e4a", + "whid": "3a14198e-6928-121f-7ca6-88ad3ae7e6a0", + "whName": "粉末堆栈", + "code": "0002-0009", + "x": 3, + "y": 1, + "z": 1, + "quantity": 0 + } + ], + "detail": [ + { + "id": "3a1cdefe-d5e0-28a4-f5d0-f7e2436c575f", + "detailMaterialId": "3a1cdefe-d5e0-94ae-f770-27847e73ad38", + "code": null, + "name": "90%分装小瓶", + "quantity": "1", + "lockQuantity": "1", + "unit": "个", + "x": 2, + "y": 3, + "z": 1, + "associateId": null + }, + { + "id": "3a1cdefe-d5e0-3ed6-3607-133df89baf5b", + "detailMaterialId": "3a1cdefe-d5e0-f2fa-66bf-94c565d852fb", + "code": null, + "name": "10%分装小瓶", + "quantity": "1", + "lockQuantity": "1", + "unit": "个", + "x": 1, + "y": 3, + "z": 1, + "associateId": null + }, + { + "id": "3a1cdefe-d5e0-72b6-e015-be7b93cf09eb", + "detailMaterialId": "3a1cdefe-d5e0-81cf-7dad-2e51cab9ffd6", + "code": null, + "name": "90%分装小瓶", + "quantity": "1", + "lockQuantity": "1", + "unit": "个", + "x": 2, + "y": 1, + "z": 1, + "associateId": null + }, + { + "id": "3a1cdefe-d5e0-81d3-ad30-48134afc9ce7", + "detailMaterialId": "3a1cdefe-d5e0-3fa1-cc72-fda6276ae38d", + "code": null, + "name": "10%分装小瓶", + "quantity": "1", + "lockQuantity": "1", + "unit": "个", + "x": 1, + "y": 1, + "z": 1, + "associateId": null + }, + { + "id": "3a1cdefe-d5e0-dbdf-d966-9a8926fe1e06", + "detailMaterialId": "3a1cdefe-d5e0-c632-c7da-02d385b18628", + "code": null, + "name": "10%分装小瓶", + "quantity": "1", + "lockQuantity": "1", + "unit": "个", + "x": 1, + "y": 2, + "z": 1, + "associateId": null + }, + { + "id": "3a1cdefe-d5e0-f099-b260-e3089a2d08c3", + "detailMaterialId": "3a1cdefe-d5e0-561f-73b6-f8501f814dbb", + "code": null, + "name": "90%分装小瓶", + "quantity": "1", + "lockQuantity": "1", + "unit": "个", + "x": 2, + "y": 2, + "z": 1, + "associateId": null + } + ] + }, + { + "id": "3a1cdefe-d5e0-f2fa-66bf-94c565d852fb", + "typeName": "10%分装小瓶", + "code": "0005-00515", + "barCode": "", + "name": "10%分装小瓶", + "quantity": 1.0, + "lockQuantity": 1.0, + "unit": "个", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + } +] \ No newline at end of file diff --git a/test/resources/bioyond_materials_liquidhandling_2.json b/test/resources/bioyond_materials_liquidhandling_2.json new file mode 100644 index 00000000..9f56d426 --- /dev/null +++ b/test/resources/bioyond_materials_liquidhandling_2.json @@ -0,0 +1,216 @@ +[ + { + "id": "3a1cde21-a4f4-4f95-6221-eaafc2ae6a8d", + "typeName": "样品瓶", + "code": "0002-00407", + "barCode": "", + "name": "ODA", + "quantity": 25.0, + "lockQuantity": 2.0, + "unit": "克", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cde21-a4f4-7887-9258-e8f8ab7c8a7a", + "typeName": "样品板", + "code": "0008-00160", + "barCode": "", + "name": "1010sample", + "quantity": 1.0, + "lockQuantity": 27.69187, + "unit": "块", + "status": 1, + "isUse": false, + "locations": [ + { + "id": "3a14198e-6929-4379-affa-9a2935c17f99", + "whid": "3a14198e-6928-121f-7ca6-88ad3ae7e6a0", + "whName": "粉末堆栈", + "code": "0002-0002", + "x": 1, + "y": 2, + "z": 1, + "quantity": 0 + } + ], + "detail": [ + { + "id": "3a1cde21-a4f4-0339-f2b6-8e680ad7e8c7", + "detailMaterialId": "3a1cde21-a4f4-ab37-f7a2-ecc3bc083e7c", + "code": null, + "name": "MPDA", + "quantity": "10.505", + "lockQuantity": "-0.0174", + "unit": "克", + "x": 2, + "y": 1, + "z": 1, + "associateId": null + }, + { + "id": "3a1cde21-a4f4-a21a-23cf-bb7857b41947", + "detailMaterialId": "3a1cde21-a4f4-99c7-55e7-c80c7320e300", + "code": null, + "name": "ODA", + "quantity": "1.795", + "lockQuantity": "2.0093", + "unit": "克", + "x": 1, + "y": 1, + "z": 1, + "associateId": null + }, + { + "id": "3a1cde21-a4f4-af1b-ba0b-2874836800e9", + "detailMaterialId": "3a1cde21-a4f4-4f95-6221-eaafc2ae6a8d", + "code": null, + "name": "ODA", + "quantity": "25", + "lockQuantity": "2", + "unit": "克", + "x": 1, + "y": 2, + "z": 1, + "associateId": null + } + ] + }, + { + "id": "3a1cde21-a4f4-99c7-55e7-c80c7320e300", + "typeName": "样品瓶", + "code": "0002-00406", + "barCode": "", + "name": "ODA", + "quantity": 1.795, + "lockQuantity": 2.00927, + "unit": "克", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cde21-a4f4-ab37-f7a2-ecc3bc083e7c", + "typeName": "样品瓶", + "code": "0002-00408", + "barCode": "", + "name": "MPDA", + "quantity": 10.505, + "lockQuantity": -0.0174, + "unit": "克", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cdeff-c92a-08f6-c822-732ab734154c", + "typeName": "样品板", + "code": "0008-00161", + "barCode": "", + "name": "1010sample2", + "quantity": 1.0, + "lockQuantity": 3.0, + "unit": "块", + "status": 1, + "isUse": false, + "locations": [ + { + "id": "3a14198e-6929-31f0-8a22-0f98f72260df", + "whid": "3a14198e-6928-121f-7ca6-88ad3ae7e6a0", + "whName": "粉末堆栈", + "code": "0002-0001", + "x": 1, + "y": 1, + "z": 1, + "quantity": 0 + } + ], + "detail": [ + { + "id": "3a1cdeff-c92b-3ace-9623-0bcdef6fa07d", + "detailMaterialId": "3a1cdeff-c92b-d084-2a96-5d62746d9321", + "code": null, + "name": "BTDA1", + "quantity": "0.362", + "lockQuantity": "14.494", + "unit": "克", + "x": 1, + "y": 1, + "z": 1, + "associateId": null + }, + { + "id": "3a1cdeff-c92b-856e-f481-792b91b6dbde", + "detailMaterialId": "3a1cdeff-c92b-30f2-f907-8f5e2fe0586b", + "code": null, + "name": "BTDA3", + "quantity": "1.935", + "lockQuantity": "13.067", + "unit": "克", + "x": 1, + "y": 2, + "z": 1, + "associateId": null + }, + { + "id": "3a1cdeff-c92b-d144-c5e5-ab9d94e21187", + "detailMaterialId": "3a1cdeff-c92b-519f-a70f-0bb71af537a7", + "code": null, + "name": "BTDA2", + "quantity": "1.903", + "lockQuantity": "13.035", + "unit": "克", + "x": 2, + "y": 1, + "z": 1, + "associateId": null + } + ] + }, + { + "id": "3a1cdeff-c92b-30f2-f907-8f5e2fe0586b", + "typeName": "样品瓶", + "code": "0002-00411", + "barCode": "", + "name": "BTDA3", + "quantity": 1.935, + "lockQuantity": 13.067, + "unit": "克", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cdeff-c92b-519f-a70f-0bb71af537a7", + "typeName": "样品瓶", + "code": "0002-00410", + "barCode": "", + "name": "BTDA2", + "quantity": 1.903, + "lockQuantity": 13.035, + "unit": "克", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + }, + { + "id": "3a1cdeff-c92b-d084-2a96-5d62746d9321", + "typeName": "样品瓶", + "code": "0002-00409", + "barCode": "", + "name": "BTDA1", + "quantity": 0.362, + "lockQuantity": 14.494, + "unit": "克", + "status": 1, + "isUse": false, + "locations": [], + "detail": [] + } +] \ No newline at end of file diff --git a/test/resources/bioyond_materials.json b/test/resources/bioyond_materials_reaction.json similarity index 98% rename from test/resources/bioyond_materials.json rename to test/resources/bioyond_materials_reaction.json index 9e6d7f6d..10e4d442 100644 --- a/test/resources/bioyond_materials.json +++ b/test/resources/bioyond_materials_reaction.json @@ -1,5 +1,4 @@ -{ - "data": [ +[ { "id": "3a1c67a9-aed7-b94d-9e24-bfdf10c8baa9", "typeName": "烧杯", @@ -191,8 +190,4 @@ } ] } - ], - "code": 1, - "message": "", - "timestamp": 1758560573511 -} \ No newline at end of file + ] \ No newline at end of file diff --git a/test/resources/test_converter_bioyond.py b/test/resources/test_converter_bioyond.py index 1044a8d0..01e9f7da 100644 --- a/test/resources/test_converter_bioyond.py +++ b/test/resources/test_converter_bioyond.py @@ -2,6 +2,7 @@ import pytest import json import os +from pylabrobot.resources import Resource as ResourcePLR from unilabos.resources.graphio import resource_bioyond_to_plr from unilabos.registry.registry import lab_registry @@ -14,22 +15,62 @@ type_mapping = { "烧杯": "BIOYOND_PolymerStation_1FlaskCarrier", "试剂瓶": "BIOYOND_PolymerStation_1BottleCarrier", "样品板": "BIOYOND_PolymerStation_6VialCarrier", + "分装板": "BIOYOND_PolymerStation_6VialCarrier", + "样品瓶": "BIOYOND_PolymerStation_Solid_Stock", + "90%分装小瓶": "BIOYOND_PolymerStation_Solid_Vial", + "10%分装小瓶": "BIOYOND_PolymerStation_Liquid_Vial", } +type_uuid_mapping = { + "烧杯": "BIOYOND_PolymerStation_1FlaskCarrier", + "试剂瓶": "BIOYOND_PolymerStation_1BottleCarrier", + "样品板": "BIOYOND_PolymerStation_6VialCarrier", + "分装板": "3a14196e-5dfe-6e21-0c79-fe2036d052c4", + "样品瓶": "3a14196a-cf7d-8aea-48d8-b9662c7dba94", + "90%分装小瓶": "3a14196c-cdcf-088d-dc7d-5cf38f0ad9ea", + "10%分装小瓶": "3a14196c-76be-2279-4e22-7310d69aed68", +} + + @pytest.fixture -def bioyond_materials() -> list[dict]: +def bioyond_materials_reaction() -> list[dict]: print("加载 BioYond 物料数据...") print(os.getcwd()) - with open("bioyond_materials.json", "r", encoding="utf-8") as f: - data = json.load(f)["data"] + with open("bioyond_materials_reaction.json", "r", encoding="utf-8") as f: + data = json.load(f) print(f"加载了 {len(data)} 条物料数据") return data -def test_bioyond_to_plr(bioyond_materials) -> list[dict]: +@pytest.fixture +def bioyond_materials_liquidhandling_1() -> list[dict]: + print("加载 BioYond 物料数据...") + print(os.getcwd()) + with open("bioyond_materials_liquidhandling_1.json", "r", encoding="utf-8") as f: + data = json.load(f) + print(f"加载了 {len(data)} 条物料数据") + return data + + +@pytest.fixture +def bioyond_materials_liquidhandling_2() -> list[dict]: + print("加载 BioYond 物料数据...") + print(os.getcwd()) + with open("bioyond_materials_liquidhandling_2.json", "r", encoding="utf-8") as f: + data = json.load(f) + print(f"加载了 {len(data)} 条物料数据") + return data + + +@pytest.mark.parametrize("materials_fixture", [ + "bioyond_materials_reaction", + "bioyond_materials_liquidhandling_1", +]) +def test_bioyond_to_plr(materials_fixture, request) -> list[dict]: + materials = request.getfixturevalue(materials_fixture) deck = BIOYOND_PolymerReactionStation_Deck("test_deck") - print("将 BioYond 物料数据转换为 PLR 格式...") - output = resource_bioyond_to_plr(bioyond_materials, type_mapping=type_mapping, deck=deck) + output = resource_bioyond_to_plr(materials, type_mapping=type_mapping, deck=deck) print(deck.summary()) print([resource.serialize() for resource in output]) print([resource.serialize_all_state() for resource in output]) + json.dump(deck.serialize(), open("test.json", "w", encoding="utf-8"), indent=4) diff --git a/unilabos/resources/bioyond/bottle_carriers.py b/unilabos/resources/bioyond/bottle_carriers.py index 9f88b88d..f56c2f13 100644 --- a/unilabos/resources/bioyond/bottle_carriers.py +++ b/unilabos/resources/bioyond/bottle_carriers.py @@ -1,7 +1,13 @@ from pylabrobot.resources import create_homogeneous_resources, Coordinate, ResourceHolder, create_ordered_items_2d from unilabos.resources.itemized_carrier import Bottle, BottleCarrier -from unilabos.resources.bioyond.bottles import BIOYOND_PolymerStation_Solid_Vial, BIOYOND_PolymerStation_Solution_Beaker, BIOYOND_PolymerStation_Reagent_Bottle +from unilabos.resources.bioyond.bottles import ( + BIOYOND_PolymerStation_Solid_Stock, + BIOYOND_PolymerStation_Solid_Vial, + BIOYOND_PolymerStation_Liquid_Vial, + BIOYOND_PolymerStation_Solution_Beaker, + BIOYOND_PolymerStation_Reagent_Bottle +) # 命名约定:试剂瓶-Bottle,烧杯-Beaker,烧瓶-Flask,小瓶-Vial @@ -92,6 +98,57 @@ def BIOYOND_Electrolyte_1BottleCarrier(name: str) -> BottleCarrier: return carrier +def BIOYOND_PolymerStation_6StockCarrier(name: str) -> BottleCarrier: + """6瓶载架 - 2x3布局""" + + # 载架尺寸 (mm) + carrier_size_x = 127.8 + carrier_size_y = 85.5 + carrier_size_z = 50.0 + + # 瓶位尺寸 + bottle_diameter = 20.0 + bottle_spacing_x = 42.0 # X方向间距 + bottle_spacing_y = 35.0 # Y方向间距 + + # 计算起始位置 (居中排列) + start_x = (carrier_size_x - (3 - 1) * bottle_spacing_x - bottle_diameter) / 2 + start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2 + + sites = create_ordered_items_2d( + klass=ResourceHolder, + num_items_x=3, + num_items_y=2, + dx=start_x, + dy=start_y, + dz=5.0, + item_dx=bottle_spacing_x, + item_dy=bottle_spacing_y, + + size_x=bottle_diameter, + size_y=bottle_diameter, + size_z=carrier_size_z, + ) + for k, v in sites.items(): + v.name = f"{name}_{v.name}" + + carrier = BottleCarrier( + name=name, + size_x=carrier_size_x, + size_y=carrier_size_y, + size_z=carrier_size_z, + sites=sites, + model="BIOYOND_PolymerStation_6VialCarrier", + ) + carrier.num_items_x = 3 + carrier.num_items_y = 2 + carrier.num_items_z = 1 + ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序 + for i in range(6): + carrier[i] = BIOYOND_PolymerStation_Solid_Stock(f"{name}_vial_{ordering[i]}") + return carrier + + def BIOYOND_PolymerStation_6VialCarrier(name: str) -> BottleCarrier: """6瓶载架 - 2x3布局""" @@ -138,8 +195,10 @@ def BIOYOND_PolymerStation_6VialCarrier(name: str) -> BottleCarrier: carrier.num_items_y = 2 carrier.num_items_z = 1 ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序 - for i in range(6): - carrier[i] = BIOYOND_PolymerStation_Solid_Vial(f"{name}_vial_{ordering[i]}") + for i in range(3): + carrier[i] = BIOYOND_PolymerStation_Solid_Vial(f"{name}_solidvial_{ordering[i]}") + for i in range(3, 6): + carrier[i] = BIOYOND_PolymerStation_Liquid_Vial(f"{name}_liquidvial_{ordering[i]}") return carrier diff --git a/unilabos/resources/bioyond/bottles.py b/unilabos/resources/bioyond/bottles.py index 1afac18c..7d241a73 100644 --- a/unilabos/resources/bioyond/bottles.py +++ b/unilabos/resources/bioyond/bottles.py @@ -2,12 +2,30 @@ from unilabos.resources.itemized_carrier import Bottle, BottleCarrier # 工厂函数 -def BIOYOND_PolymerStation_Solid_Vial( +def BIOYOND_PolymerStation_Solid_Stock( name: str, diameter: float = 20.0, height: float = 100.0, max_volume: float = 30000.0, # 30mL barcode: str = None, +) -> Bottle: + """创建粉末瓶""" + return Bottle( + name=name, + diameter=diameter, + height=height, + max_volume=max_volume, + barcode=barcode, + model="BIOYOND_PolymerStation_Solid_Stock", + ) + + +def BIOYOND_PolymerStation_Solid_Vial( + name: str, + diameter: float = 25.0, + height: float = 60.0, + max_volume: float = 30000.0, # 30mL + barcode: str = None, ) -> Bottle: """创建粉末瓶""" return Bottle( @@ -20,6 +38,24 @@ def BIOYOND_PolymerStation_Solid_Vial( ) +def BIOYOND_PolymerStation_Liquid_Vial( + name: str, + diameter: float = 25.0, + height: float = 60.0, + max_volume: float = 30000.0, # 30mL + barcode: str = None, +) -> Bottle: + """创建滴定液瓶""" + return Bottle( + name=name, + diameter=diameter, + height=height, + max_volume=max_volume, + barcode=barcode, + model="BIOYOND_PolymerStation_Liquid_Vial", + ) + + def BIOYOND_PolymerStation_Solution_Beaker( name: str, diameter: float = 60.0, diff --git a/unilabos/resources/graphio.py b/unilabos/resources/graphio.py index 5f2feea6..e71c81db 100644 --- a/unilabos/resources/graphio.py +++ b/unilabos/resources/graphio.py @@ -614,6 +614,11 @@ def resource_bioyond_to_plr(bioyond_materials: list[dict], type_mapping: dict = bottle.tracker.liquids = [ (detail["name"], float(detail.get("quantity", 0)) if detail.get("quantity") else 0) ] + else: + bottle = plr_material[0] if plr_material.capacity > 0 else plr_material + bottle.tracker.liquids = [ + (material["name"], float(material.get("quantity", 0)) if material.get("quantity") else 0) + ] plr_materials.append(plr_material) @@ -633,6 +638,36 @@ def resource_bioyond_to_plr(bioyond_materials: list[dict], type_mapping: dict = return plr_materials +def resource_plr_to_bioyond(plr_materials: list[ResourcePLR], type_mapping: dict = {}, warehouse_mapping: dict = {}) -> list[dict]: + bioyond_materials = [] + for plr_material in plr_materials: + material = { + "name": plr_material.name, + "typeName": plr_material.__class__.__name__, + "code": plr_material.code, + "quantity": 0, + "detail": [], + "locations": [], + } + if hasattr(plr_material, "capacity") and plr_material.capacity > 1: + for idx in range(plr_material.capacity): + bottle = plr_material[idx] + detail = { + "x": (idx // (plr_material.num_items_x * plr_material.num_items_y)) + 1, + "y": ((idx % (plr_material.num_items_x * plr_material.num_items_y)) // plr_material.num_items_x) + 1, + "z": (idx % plr_material.num_items_x) + 1, + "code": bottle.code if hasattr(bottle, "code") else "", + "quantity": sum(qty for _, qty in bottle.tracker.liquids) if hasattr(bottle, "tracker") else 0, + } + material["detail"].append(detail) + material["quantity"] = 1.0 + else: + bottle = plr_material[0] if plr_material.capacity > 0 else plr_material + material["quantity"] = sum(qty for _, qty in bottle.tracker.liquids) if hasattr(plr_material, "tracker") else 0 + bioyond_materials.append(material) + return bioyond_materials + + def initialize_resource(resource_config: dict, resource_type: Any = None) -> Union[list[dict], ResourcePLR]: """Initializes a resource based on its configuration. diff --git a/unilabos/resources/itemized_carrier.py b/unilabos/resources/itemized_carrier.py index 997ad068..6d5c2980 100644 --- a/unilabos/resources/itemized_carrier.py +++ b/unilabos/resources/itemized_carrier.py @@ -5,15 +5,19 @@ Automated Liquid Handling Station Resource Classes - Simplified Version from __future__ import annotations -from typing import Dict, Optional +from typing import Dict, List, Optional, TypeVar, Union, Sequence, Tuple + +import pylabrobot -from pylabrobot.resources.coordinate import Coordinate -from pylabrobot.resources.container import Container -from pylabrobot.resources.resource_holder import ResourceHolder from pylabrobot.resources import Resource as ResourcePLR +from pylabrobot.resources import Well, ResourceHolder +from pylabrobot.resources.coordinate import Coordinate -class Bottle(Container): +LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + +class Bottle(Well): """瓶子类 - 简化版,不追踪瓶盖""" def __init__( @@ -37,6 +41,8 @@ class Bottle(Container): max_volume=max_volume, category=category, model=model, + bottom_type="flat", + cross_section_type="circle" ) self.diameter = diameter self.height = height @@ -50,13 +56,6 @@ class Bottle(Container): "barcode": self.barcode, } - -from string import ascii_uppercase as LETTERS -from typing import Dict, List, Optional, Type, TypeVar, Union, Sequence, Tuple - -import pylabrobot -from pylabrobot.resources.resource_holder import ResourceHolder - T = TypeVar("T", bound=ResourceHolder) S = TypeVar("S", bound=ResourceHolder)