diff --git a/unilabos/devices/liquid_handling/liquid_handler_abstract.py b/unilabos/devices/liquid_handling/liquid_handler_abstract.py index 4586f808..1963e417 100644 --- a/unilabos/devices/liquid_handling/liquid_handler_abstract.py +++ b/unilabos/devices/liquid_handling/liquid_handler_abstract.py @@ -593,6 +593,7 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware): available_tips[idx] = tipSpot continue # 一般移动液体有两种方式,一对多和多对多 + print("channel_num", self.channel_num) if self.channel_num == 8: tip_prefix = list(available_tips.values())[0].name.split('_')[0] @@ -601,8 +602,11 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware): available_cols.sort() available_tips_dict = {tip.name: tip for tip in available_tips.values()} tips_to_use = [available_tips_dict[f"{tip_prefix}_{chr(65 + i)}{available_cols[0]}"] for i in range(8)] + print("tips_to_use", tips_to_use) await self.pick_up_tips(tips_to_use, use_channels=list(range(0, 8))) + print("source_wells", source_wells) await self.aspirate(source_wells, [unit_volume] * 8, use_channels=list(range(0, 8))) + print("target_wells", target_wells) await self.dispense(target_wells, [unit_volume] * 8, use_channels=list(range(0, 8))) await self.discard_tips(use_channels=list(range(0, 8))) @@ -610,7 +614,10 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware): for num_well in range(len(target_wells)): tip_to_use = available_tips[list(available_tips.keys())[num_well]] + print("tip_to_use", tip_to_use) await self.pick_up_tips([tip_to_use], use_channels=[0]) + print("source_wells", source_wells) + print("target_wells", target_wells) if len(source_wells) == 1: await self.aspirate([source_wells[0]], [unit_volume], use_channels=[0]) else: diff --git a/unilabos/devices/liquid_handling/prcxi/abstract_protocol.py b/unilabos/devices/liquid_handling/prcxi/abstract_protocol.py index 83def461..b09d1b94 100644 --- a/unilabos/devices/liquid_handling/prcxi/abstract_protocol.py +++ b/unilabos/devices/liquid_handling/prcxi/abstract_protocol.py @@ -5,7 +5,7 @@ import json import socket import time from typing import Any, List, Dict, Optional, TypedDict, Union, Sequence, Iterator, Literal - +import pprint as pp from pylabrobot.liquid_handling import ( LiquidHandlerBackend, Pickup, @@ -25,6 +25,7 @@ from pylabrobot.liquid_handling.standard import ( ResourceDrop, ) from pylabrobot.resources import Tip, Deck, Plate, Well, TipRack, Resource, Container, Coordinate, TipSpot, Trash +from traitlets import Int from unilabos.devices.liquid_handling.liquid_handler_abstract import LiquidHandlerAbstract @@ -445,10 +446,11 @@ class LabResource: from typing import Dict, Any +import time class DefaultLayout: - + def __init__(self, product_name: str = "PRCXI9300"): - self.labresource = None + self.labresource = {} if product_name not in ["PRCXI9300", "PRCXI9320"]: raise ValueError(f"Unsupported product_name: {product_name}. Only 'PRCXI9300' and 'PRCXI9320' are supported.") @@ -458,12 +460,32 @@ class DefaultLayout: self.layout = [1, 2, 3, 4, 5, 6] self.trash_slot = 3 self.waste_liquid_slot = 6 + elif product_name == "PRCXI9320": self.rows = 3 self.columns = 4 - self.layout = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - self.trash_slot = 3 + self.layout = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + self.trash_slot = 16 self.waste_liquid_slot = 12 + self.default_layout = {"MatrixId":f"{time.time()}","MatrixName":f"{time.time()}","MatrixCount":16,"WorkTablets": + [{"Number": 1, "Code": "T1", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 2, "Code": "T2", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 3, "Code": "T3", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 4, "Code": "T4", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 5, "Code": "T5", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 6, "Code": "T6", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 7, "Code": "T7", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 8, "Code": "T8", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 9, "Code": "T9", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 10, "Code": "T10", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 11, "Code": "T11", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 12, "Code": "T12", "Material": {"uuid": "730067cf07ae43849ddf4034299030e9", "materialEnum": 0}}, # 这个设置成废液槽,用储液槽表示 + {"Number": 13, "Code": "T13", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 14, "Code": "T14", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 15, "Code": "T15", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 16, "Code": "T16", "Material": {"uuid": "730067cf07ae43849ddf4034299030e9", "materialEnum": 0}} # 这个设置成垃圾桶,用储液槽表示 +] +} def get_layout(self) -> Dict[str, Any]: return { @@ -479,90 +501,121 @@ class DefaultLayout: def get_waste_liquid_slot(self) -> int: return self.waste_liquid_slot - - def set_liquid_handler_layout(self, product_name: str): - if product_name == "PRCXI9300": - self.rows = 2 - self.columns = 3 - self.layout = [1, 2, 3, 4, 5, 6] - self.trash_slot = 3 - self.waste_liquid_slot = 6 - elif product_name == "PRCXI9320": - self.rows = 3 - self.columns = 4 - self.layout = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - self.trash_slot = 3 - self.waste_liquid_slot = 12 + def add_lab_resource(self, material_info): + self.labresource = material_info - def set_trash_slot(self, slot: int): - self.trash_slot = slot - - def set_waste_liquid_slot(self, slot: int): - self.waste_liquid_slot = slot - - def add_lab_resource(self, lab_resource: LabResource): - self.labresource = lab_resource.get_resources_info() - - def recommend_layout(self, needs: Dict[str, Any]) -> Dict[str, Any]: + def recommend_layout(self, needs: Dict[str, int]) -> Dict[str, Any]: """根据 needs 推荐布局""" - liquid_info = needs['liquid_setup'] - tip_info = needs['totals_by_tip'] # 修改这里:直接访问 totals_by_tip - print("当前实验所需物料信息:", liquid_info) - print("当前实验所需枪头信息:", tip_info) - print(self.labresource) + for k, v in needs.items(): + if k not in self.labresource: + raise ValueError(f"Material {k} not found in lab resources.") + + # 预留位置12和16不动 + reserved_positions = {12, 16} + available_positions = [i for i in range(1, 17) if i not in reserved_positions] + + # 计算总需求 + total_needed = sum(needs.values()) + if total_needed > len(available_positions): + raise ValueError(f"需要 {total_needed} 个位置,但只有 {len(available_positions)} 个可用位置(排除位置12和16)") + + # 依次分配位置 + current_pos = 0 + for material_name, count in needs.items(): + material_uuid = self.labresource[material_name]['uuid'] + material_enum = self.labresource[material_name]['materialEnum'] + + for _ in range(count): + if current_pos >= len(available_positions): + raise ValueError("位置不足,无法分配更多物料") + + position = available_positions[current_pos] + # 找到对应的tablet并更新 + for tablet in self.default_layout['WorkTablets']: + if tablet['Number'] == position: + tablet['Material']['uuid'] = material_uuid + tablet['Material']['materialEnum'] = material_enum + break + + current_pos += 1 + + return self.default_layout - for liquid in liquid_info: - # total_volume = liquid.values() - print(liquid) - #print(f"资源 {liquid} 需要的总体积: {total_volume}") if __name__ == "__main__": - # ---- 资源:SUP 供液(X),中间板 R1(4 孔空),目标板 R2(4 孔空)---- - sup = MaterialResource("SUP", slot=5, well=[1], liquid_id="X", volume=10000) - r1 = MaterialResource("R1", slot=6, well=[1,2,3,4,5,6,7,8]) - r2 = MaterialResource("R2", slot=7, well=[1,2,3,4,5,6,7,8]) - - pm = ProtocolManager() - # 步骤1:SUP -> R1,1->N 扇出,每孔 50 uL(总 200 uL) - pm.add_transfer(sup, r1, unit_volume=10.0) - # 步骤2:R1 -> R2,N->N 对应,每对 25 uL(总 100 uL;来自 R1 中已存在的混合物 X) - pm.add_transfer(r1, r2, unit_volume=120.0) - - out = pm.compute_min_initials_with_tips() + with open("prcxi_material.json", "r") as f: + material_info = json.load(f) + + layout = DefaultLayout("PRCXI9320") + layout.add_lab_resource(material_info) + plan = layout.recommend_layout({ + "10μL加长 Tip头": 2, + "300μL Tip头": 2, + "96深孔板": 2, + }) - # layout_planer = DefaultLayout('PRCXI9320') - # print(layout_planer.get_layout()) - # print("回推最小需求:", out["liquid_setup"]) # {'SUP': {'X': 200.0}} - # print("步骤枪头建议:", out["step_tips"]) # [{'idx':0,'tip':'TIP_200uL','unit_volume':50.0}, {'idx':1,'tip':'TIP_50uL','unit_volume':25.0}] +# if __name__ == "__main__": +# # ---- 资源:SUP 供液(X),中间板 R1(4 孔空),目标板 R2(4 孔空)---- +# # sup = MaterialResource("SUP", slot=5, well=[1], liquid_id="X", volume=10000) +# # r1 = MaterialResource("R1", slot=6, well=[1,2,3,4,5,6,7,8]) +# # r2 = MaterialResource("R2", slot=7, well=[1,2,3,4,5,6,7,8]) -# # 实际执行(可选) -# transfer_liquid(sup, r1, unit_volume=50.0) -# transfer_liquid(r1, r2, unit_volume=25.0) -# print("执行后 SUP:", sup.get_resource()) # 总体积 -200 -# print("执行后 R1:", r1.get_resource()) # 每孔 25 uL(50 进 -25 出) -# print("执行后 R2:", r2.get_resource()) # 每孔 25 uL +# # pm = ProtocolManager() +# # # 步骤1:SUP -> R1,1->N 扇出,每孔 50 uL(总 200 uL) +# # pm.add_transfer(sup, r1, unit_volume=10.0) +# # # 步骤2:R1 -> R2,N->N 对应,每对 25 uL(总 100 uL;来自 R1 中已存在的混合物 X) +# # pm.add_transfer(r1, r2, unit_volume=120.0) + +# # out = pm.compute_min_initials_with_tips() +# # # layout_planer = DefaultLayout('PRCXI9320') +# # # print(layout_planer.get_layout()) +# # # print("回推最小需求:", out["liquid_setup"]) # {'SUP': {'X': 200.0}} +# # # print("步骤枪头建议:", out["step_tips"]) # [{'idx':0,'tip':'TIP_200uL','unit_volume':50.0}, {'idx':1,'tip':'TIP_50uL','unit_volume':25.0}] + +# # # # 实际执行(可选) +# # # transfer_liquid(sup, r1, unit_volume=50.0) +# # # transfer_liquid(r1, r2, unit_volume=25.0) +# # # print("执行后 SUP:", sup.get_resource()) # 总体积 -200 +# # # print("执行后 R1:", r1.get_resource()) # 每孔 25 uL(50 进 -25 出) +# # # print("执行后 R2:", r2.get_resource()) # 每孔 25 uL - from pylabrobot.resources.opentrons.tube_racks import * - from pylabrobot.resources.opentrons.plates import * - from pylabrobot.resources.opentrons.tip_racks import * - from pylabrobot.resources.opentrons.reservoirs import * +# # from pylabrobot.resources.opentrons.tube_racks import * +# # from pylabrobot.resources.opentrons.plates import * +# # from pylabrobot.resources.opentrons.tip_racks import * +# # from pylabrobot.resources.opentrons.reservoirs import * - plate = [locals()['nest_96_wellplate_2ml_deep'](name="thermoscientificnunc_96_wellplate_2000ul"), locals()['corning_96_wellplate_360ul_flat'](name="corning_96_wellplate_360ul_flat")] - tiprack = [locals()['opentrons_96_tiprack_300ul'](name="opentrons_96_tiprack_300ul"), locals()['opentrons_96_tiprack_1000ul'](name="opentrons_96_tiprack_1000ul")] - trash = [locals()['axygen_1_reservoir_90ml'](name="axygen_1_reservoir_90ml")] +# # plate = [locals()['nest_96_wellplate_2ml_deep'](name="thermoscientificnunc_96_wellplate_2000ul"), locals()['corning_96_wellplate_360ul_flat'](name="corning_96_wellplate_360ul_flat")] +# # tiprack = [locals()['opentrons_96_tiprack_300ul'](name="opentrons_96_tiprack_300ul"), locals()['opentrons_96_tiprack_1000ul'](name="opentrons_96_tiprack_1000ul")] +# # trash = [locals()['axygen_1_reservoir_90ml'](name="axygen_1_reservoir_90ml")] + +# # from pprint import pprint + +# # lab_resource = LabResource() +# # lab_resource.add_tipracks(tiprack) +# # lab_resource.add_plates(plate) +# # lab_resource.add_trash(trash) + +# # layout_planer = DefaultLayout('PRCXI9300') +# # layout_planer.add_lab_resource(lab_resource) +# # layout_planer.recommend_layout(out) + +# with open("prcxi_material.json", "r") as f: +# material_info = json.load(f) +# # print("当前实验物料信息:", material_info) + +# layout = DefaultLayout("PRCXI9320") +# layout.add_lab_resource(material_info) +# print(layout.default_layout['WorkTablets']) +# # plan = layout.recommend_layout({ +# # "10μL加长 Tip头": 2, +# # "300μL Tip头": 2, +# # "96深孔板": 2, +# # }) - from pprint import pprint - lab_resource = LabResource() - lab_resource.add_tipracks(tiprack) - lab_resource.add_plates(plate) - lab_resource.add_trash(trash) - layout_planer = DefaultLayout('PRCXI9300') - layout_planer.add_lab_resource(lab_resource) - layout_planer.recommend_layout(out) \ No newline at end of file diff --git a/unilabos/devices/liquid_handling/prcxi/prcxi.py b/unilabos/devices/liquid_handling/prcxi/prcxi.py index f1652f89..bc70d927 100644 --- a/unilabos/devices/liquid_handling/prcxi/prcxi.py +++ b/unilabos/devices/liquid_handling/prcxi/prcxi.py @@ -808,7 +808,7 @@ class PRCXI9300Api: return self.call("IMatrix", "GetWorkTabletMatrixById", [matrix_id]) def add_WorkTablet_Matrix(self, matrix: MatrixInfo): - return self.call("IMatrix", "AddWorkTabletMatrix", [matrix]) + return self.call("IMatrix", "AddWorkTabletMatrix2", [matrix]) def Load(self, dosage: int, plate_no: int, is_whole_plate: bool, hole_row: int, hole_col: int, blending_times: int, balance_height: int, plate_or_hole: str, hole_numbers: str, assist_fun1: str = "", assist_fun2: str = "", @@ -971,6 +971,102 @@ class PRCXI9300Api: "HoleNumbers": hole_numbers, "LiquidDispensingMethod": liquid_method, } + +class DefaultLayout: + + def __init__(self, product_name: str = "PRCXI9300"): + self.labresource = {} + if product_name not in ["PRCXI9300", "PRCXI9320"]: + raise ValueError(f"Unsupported product_name: {product_name}. Only 'PRCXI9300' and 'PRCXI9320' are supported.") + + if product_name == "PRCXI9300": + self.rows = 2 + self.columns = 3 + self.layout = [1, 2, 3, 4, 5, 6] + self.trash_slot = 3 + self.waste_liquid_slot = 6 + + elif product_name == "PRCXI9320": + self.rows = 3 + self.columns = 4 + self.layout = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + self.trash_slot = 16 + self.waste_liquid_slot = 12 + self.default_layout = {"MatrixId":f"{time.time()}","MatrixName":f"{time.time()}","MatrixCount":16,"WorkTablets": + [{"Number": 1, "Code": "T1", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 2, "Code": "T2", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 3, "Code": "T3", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 4, "Code": "T4", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 5, "Code": "T5", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 6, "Code": "T6", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 7, "Code": "T7", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 8, "Code": "T8", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 9, "Code": "T9", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 10, "Code": "T10", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 11, "Code": "T11", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 12, "Code": "T12", "Material": {"uuid": "730067cf07ae43849ddf4034299030e9", "materialEnum": 0}}, # 这个设置成废液槽,用储液槽表示 + {"Number": 13, "Code": "T13", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 14, "Code": "T14", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 15, "Code": "T15", "Material": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": 0}}, + {"Number": 16, "Code": "T16", "Material": {"uuid": "730067cf07ae43849ddf4034299030e9", "materialEnum": 0}} # 这个设置成垃圾桶,用储液槽表示 +] +} + + def get_layout(self) -> Dict[str, Any]: + return { + "rows": self.rows, + "columns": self.columns, + "layout": self.layout, + "trash_slot": self.trash_slot, + "waste_liquid_slot": self.waste_liquid_slot + } + + def get_trash_slot(self) -> int: + return self.trash_slot + + def get_waste_liquid_slot(self) -> int: + return self.waste_liquid_slot + + def add_lab_resource(self, material_info): + self.labresource = material_info + + def recommend_layout(self, needs: Dict[str, int]) -> Dict[str, Any]: + """根据 needs 推荐布局""" + for k, v in needs.items(): + if k not in self.labresource: + raise ValueError(f"Material {k} not found in lab resources.") + + # 预留位置12和16不动 + reserved_positions = {12, 16} + available_positions = [i for i in range(1, 17) if i not in reserved_positions] + + # 计算总需求 + total_needed = sum(needs.values()) + if total_needed > len(available_positions): + raise ValueError(f"需要 {total_needed} 个位置,但只有 {len(available_positions)} 个可用位置(排除位置12和16)") + + # 依次分配位置 + current_pos = 0 + for material_name, count in needs.items(): + material_uuid = self.labresource[material_name]['uuid'] + material_enum = self.labresource[material_name]['materialEnum'] + + for _ in range(count): + if current_pos >= len(available_positions): + raise ValueError("位置不足,无法分配更多物料") + + position = available_positions[current_pos] + # 找到对应的tablet并更新 + for tablet in self.default_layout['WorkTablets']: + if tablet['Number'] == position: + tablet['Material']['uuid'] = material_uuid + tablet['Material']['materialEnum'] = material_enum + break + + current_pos += 1 + + return self.default_layout + if __name__ == "__main__": @@ -1299,10 +1395,13 @@ if __name__ == "__main__": # from pylabrobot.resources import set_tip_tracking set_volume_tracking(enabled=True) - plate_2_liquids = handler.set_group("water", [plate2.children[0]], [300]) - #print(plate_2_liquids) + +# 第一种情景:一个孔往多个孔加液 + # plate_2_liquids = handler.set_group("water", [plate2.children[0]], [300]) + # plate5_liquids = handler.set_group("master_mix", plate5.children[:23], [100]*23) +# 第二个情景:多个孔往多个孔加液(但是个数得对应) + plate_2_liquids = handler.set_group("water", plate2.children[:23], [300]*23) plate5_liquids = handler.set_group("master_mix", plate5.children[:23], [100]*23) - #print(plate5_liquids) # plate11.set_well_liquids([("Water", 100) if (i % 8 == 0 and i // 8 < 6) else (None, 100) for i in range(96)]) # Set liquids for every 8 wells in plate8 @@ -1314,7 +1413,6 @@ if __name__ == "__main__": # print(plate11.get_well(0).tracker.get_used_volume()) asyncio.run(handler.create_protocol(protocol_name="Test Protocol")) # Initialize the backend and setup the connection - asyncio.run(handler.transfer_group("water", "master_mix", 10)) # Reset tip tracking @@ -1326,7 +1424,7 @@ if __name__ == "__main__": # # asyncio.run(handler.run_protocol()) # asyncio.run(handler.dispense([plate1.children[0]],[10],[0])) # print(plate1.children[0]) - # # asyncio.run(handler.run_protocol()) + # asyncio.run(handler.run_protocol()) # asyncio.run(handler.mix([plate1.children[0]], mix_time=3, mix_vol=5, height_to_bottom=0.5, offsets=Coordinate(0, 0, 0), mix_rate=100)) # print(plate1.children[0]) # asyncio.run(handler.discard_tips([0])) @@ -1421,3 +1519,28 @@ if __name__ == "__main__": # # # input("Press Enter to continue...") # Wait for user input before proceeding # # # print("PRCXI9300Handler initialized with deck and host settings.") + + +# 一些推荐版位组合的测试样例: + + + + with open("prcxi_material.json", "r") as f: + material_info = json.load(f) + + layout = DefaultLayout("PRCXI9320") + layout.add_lab_resource(material_info) + MatrixLayout_1 = layout.recommend_layout({ + "96 细胞培养皿": 3, + "12道储液槽": 1, + "200μL Tip头": 1, + "10μL加长 Tip头": 1, + }) + print(MatrixLayout_1) + MatrixLayout_2 = layout.recommend_layout({ + "96深孔板": 4, + "12道储液槽": 1, + "200μL Tip头": 1, + "10μL加长 Tip头": 1, + }) + diff --git a/unilabos/devices/liquid_handling/prcxi/prcxi_material.json b/unilabos/devices/liquid_handling/prcxi/prcxi_material.json new file mode 100644 index 00000000..8401e86a --- /dev/null +++ b/unilabos/devices/liquid_handling/prcxi/prcxi_material.json @@ -0,0 +1,31 @@ +{ + "Tip头适配器 1250uL": {"uuid": "3b6f33ffbf734014bcc20e3c63e124d4", "materialEnum": "0"}, + "ZHONGXI 适配器 300uL": {"uuid": "7c822592b360451fb59690e49ac6b181", "materialEnum": "0"}, + "吸头10ul 适配器": {"uuid": "8cc3dce884ac41c09f4570d0bcbfb01c", "materialEnum": "0"}, + "1250μL Tip头": {"uuid": "7960f49ddfe9448abadda89bd1556936", "materialEnum": "0"}, + "10μL Tip头": {"uuid": "45f2ed3ad925484d96463d675a0ebf66", "materialEnum": "0"}, + "10μL加长 Tip头": {"uuid": "068b3815e36b4a72a59bae017011b29f", "materialEnum": "1"}, + "1000μL Tip头": {"uuid": "80652665f6a54402b2408d50b40398df", "materialEnum": "1"}, + "300μL Tip头": {"uuid": "076250742950465b9d6ea29a225dfb00", "materialEnum": "1"}, + "200μL Tip头": {"uuid": "7a73bb9e5c264515a8fcbe88aed0e6f7", "materialEnum": "0"}, + "0.2ml PCR板": {"uuid": "73bb9b10bc394978b70e027bf45ce2d3", "materialEnum": "0"}, + "2.2ml 深孔板": {"uuid": "ca877b8b114a4310b429d1de4aae96ee", "materialEnum": "0"}, + "储液槽": {"uuid": "04211a2dc93547fe9bf6121eac533650", "materialEnum": "0"}, + "全裙边 PCR适配器": {"uuid": "4a043a07c65a4f9bb97745e1f129b165", "materialEnum": "3"}, + "储液槽 适配器": {"uuid": "6bdfdd7069df453896b0806df50f2f4d", "materialEnum": "0"}, + "300ul深孔板适配器": {"uuid": "9a439bed8f3344549643d6b3bc5a5eb4", "materialEnum": "0"}, + "10ul专用深孔板适配器": {"uuid": "4dc8d6ecfd0449549683b8ef815a861b", "materialEnum": "0"}, + "爱津": {"uuid": "b01627718d3341aba649baa81c2c083c", "materialEnum": "0"}, + "适配器": {"uuid": "adfabfffa8f24af5abfbba67b8d0f973", "materialEnum": "0"}, + "废弃槽": {"uuid": "730067cf07ae43849ddf4034299030e9", "materialEnum": "0"}, + "96深孔板": {"uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": "0"}, + "384板": {"uuid": "853dcfb6226f476e8b23c250217dc7da", "materialEnum": "0"}, + "4道储液槽": {"uuid": "01953864f6f140ccaa8ddffd4f3e46f5", "materialEnum": "0"}, + "48孔深孔板": {"uuid": "026c5d5cf3d94e56b4e16b7fb53a995b", "materialEnum": "2"}, + "12道储液槽": {"uuid": "0f1639987b154e1fac78f4fb29a1f7c1", "materialEnum": "0"}, + "HPLC料盘": {"uuid": "548bbc3df0d4447586f2c19d2c0c0c55", "materialEnum": "0"}, + "ep适配器": {"uuid": "e146697c395e4eabb3d6b74f0dd6aaf7", "materialEnum": "0"}, + "30mm适配器": {"uuid": "a0757a90d8e44e81a68f306a608694f2", "materialEnum": "0"}, + "细菌培养皿": {"uuid": "b05b3b2aafd94ec38ea0cd3215ecea8f", "materialEnum": "4"}, + "96 细胞培养皿":{ "uuid": "57b1e4711e9e4a32b529f3132fc5931f", "materialEnum": "0"} +} \ No newline at end of file