From e63c15997c74875e334de3ce2979b5845e2768c4 Mon Sep 17 00:00:00 2001 From: Guangxin Zhang Date: Wed, 4 Jun 2025 21:29:54 +0800 Subject: [PATCH] New transfer_biomek --- unilabos/devices/liquid_handling/biomek.py | 634 ++++++++++++++++-- .../devices/liquid_handling/biomek_test.py | 366 +++++++--- 2 files changed, 867 insertions(+), 133 deletions(-) diff --git a/unilabos/devices/liquid_handling/biomek.py b/unilabos/devices/liquid_handling/biomek.py index c0bde755..4f0a3137 100644 --- a/unilabos/devices/liquid_handling/biomek.py +++ b/unilabos/devices/liquid_handling/biomek.py @@ -1,7 +1,7 @@ import requests from typing import List, Sequence, Optional, Union, Literal from geometry_msgs.msg import Point -from unilabos_msgs.msg import Resource +#from unilabos_msgs.msg import Resource from pylabrobot.resources import ( TipRack, @@ -29,25 +29,45 @@ class LiquidHandlerBiomek(LiquidHandlerAbstract): self._status_queue = kwargs.get("status_queue", None) # 状态队列 self.temp_protocol = {} self.py32_path = "/opt/py32" # Biomek的Python 3.2路径 - self.technique = { + self.aspirate_techniques = { 'MC P300 high':{ - "use_channels": "Span8", - "asp_vols": [50], - "asp_flow_rates": 50, - "dis_flow_rates": 50, - "offsets": None, - "touch_tip": True, - "liquid_height": 20, - "blow_out_air_volume": 20, - "spread": "wide", - "is_96_well": True, - "mix_stage": "none", - "mix_times": None, - "mix_vol": None, - "mix_rate": None, - "mix_liquid_height": None, - "delays": None, - "none_keys": [] + "Solvent": "Water", + } + } + self.dispense_techniques = { + 'MC P300 high':{ + "Span8": False, + "Pod": "Pod1", + "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, + "Span8Wash": False, + "Span8WashVolume": "2", + "Span8WasteVolume": "1", + "SplitVolume": False, + "SplitVolumeCleaning": False, + "Stop": "Destinations", + "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 } } @@ -171,8 +191,6 @@ class LiquidHandlerBiomek(LiquidHandlerAbstract): sources: Sequence[Container], targets: Sequence[Container], tip_racks: Sequence[TipRack], - solvent: Optional[str] = None, - TipLocation :str = None, *, use_channels: Optional[List[int]] = None, asp_vols: Union[List[float], float], @@ -213,7 +231,7 @@ class LiquidHandlerBiomek(LiquidHandlerAbstract): "Replicates": "1", "ShowTipHandlingDetails": False, "ShowTransferDetails": True, - "Solvent": "Water", + "Solvent": "Well Content", "Span8Wash": False, "Span8WashVolume": "2", "Span8WasteVolume": "1", @@ -240,7 +258,9 @@ class LiquidHandlerBiomek(LiquidHandlerAbstract): "Volume": dis_vols[idx] } transfer_params["items"] = items + transfer_params["Solvent"] = solvent if solvent else "Water" + TipLocation = tip_racks[0].name transfer_params["TipLocation"] = TipLocation if len(tip_racks) == 1: @@ -251,30 +271,564 @@ class LiquidHandlerBiomek(LiquidHandlerAbstract): self.temp_protocol["steps"].append(transfer_params) return - + def transfer_biomek( self, - parameters: dict, - technique: str, + source: str, + target: str, + tip_rack: str, + volume: float, + aspirate_techniques: str, + dispense_techniques: str, ): """ 处理Biomek的液体转移操作。 """ - sources = parameters.get("source") - targets = parameters.get("target") - tip_rack = parameters.get("tip_rack") - volume = parameters.get("volume") - liquid_type = parameters.get("liquid_type", "Well Content") - other_params = self.technique.get(technique, {}) + + asp_params = self.aspirate_techniques.get(aspirate_techniques, {}) + dis_params = self.dispense_techniques.get(dispense_techniques, {}) - self.transfer_liquid( - sources=[sources], - targets=[targets], - TipLocation=tip_rack, - tip_racks=[tip_rack], - solvent=liquid_type, - dis_vols=[volume], - **other_params - ) + transfer_params = { + "Span8": False, + "Pod": "Pod1", + "items": {}, + "Wash": False, + "Dynamic?": True, + "AutoSelectActiveWashTechnique": False, + "ActiveWashTechnique": "", + "ChangeTipsBetweenDests": False, + "ChangeTipsBetweenSources": True, + "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": "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 = {} + items["Source"] = source + items["Destination"] = target + items["Volume"] = volume + transfer_params["items"] = items + transfer_params["Solvent"] = asp_params['Solvent'] + transfer_params["TipLocation"] = tip_rack + transfer_params.update(asp_params) + transfer_params.update(dis_params) + self.temp_protocol["steps"].append(transfer_params) + return + +steps_info = ''' +{ + "steps": [ + { + "step_number": 1, + "operation": "transfer", + "description": "转移PCR产物或酶促反应液至0.05ml 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": "move_labware", + "description": "移动P11至Orbital1用于振荡混匀", + "parameters": { + "source": "P11", + "target": "Orbital1" + } + }, + { + "step_number": 4, + "operation": "oscillation", + "description": "在Orbital1上振荡混匀Bind Beads BC与PCR产物(700-900rpm,300秒)", + "parameters": { + "rpm": 800, + "time": 300 + } + }, + { + "step_number": 5, + "operation": "move_labware", + "description": "移动混匀后的板回P11", + "parameters": { + "source": "Orbital1", + "target": "P11" + } + }, + { + "step_number": 6, + "operation": "move_labware", + "description": "将P11移动到磁力架(P12)吸附3分钟", + "parameters": { + "source": "P11", + "target": "P12" + } + }, + { + "step_number": 7, + "operation": "incubation", + "description": "磁力架上室温静置3分钟完成吸附", + "parameters": { + "time": 180 + } + }, + { + "step_number": 8, + "operation": "transfer", + "description": "去除上清液至废液槽", + "parameters": { + "source": "P12", + "target": "P22", + "tip_rack": "BC230", + "volume": 150 + } + }, + { + "step_number": 9, + "operation": "transfer", + "description": "加入300-500μl 75%乙醇清洗", + "parameters": { + "source": "P3", + "target": "P12", + "tip_rack": "BC230", + "volume": 400 + } + }, + { + "step_number": 10, + "operation": "move_labware", + "description": "移动清洗板到Orbital1进行振荡", + "parameters": { + "source": "P12", + "target": "Orbital1" + } + }, + { + "step_number": 11, + "operation": "oscillation", + "description": "乙醇清洗液振荡混匀(700-900rpm, 45秒)", + "parameters": { + "rpm": 800, + "time": 45 + } + }, + { + "step_number": 12, + "operation": "move_labware", + "description": "振荡后将板移回磁力架P12吸附", + "parameters": { + "source": "Orbital1", + "target": "P12" + } + }, + { + "step_number": 13, + "operation": "incubation", + "description": "吸附3分钟", + "parameters": { + "time": 180 + } + }, + { + "step_number": 14, + "operation": "transfer", + "description": "去除乙醇上清液至废液槽", + "parameters": { + "source": "P12", + "target": "P22", + "tip_rack": "BC230", + "volume": 400 + } + }, + { + "step_number": 15, + "operation": "transfer", + "description": "第二次加入300-500μl 75%乙醇清洗", + "parameters": { + "source": "P3", + "target": "P12", + "tip_rack": "BC230", + "volume": 400 + } + }, + { + "step_number": 16, + "operation": "move_labware", + "description": "再次移动清洗板到Orbital1振荡", + "parameters": { + "source": "P12", + "target": "Orbital1" + } + }, + { + "step_number": 17, + "operation": "oscillation", + "description": "再次乙醇清洗液振荡混匀(700-900rpm, 45秒)", + "parameters": { + "rpm": 800, + "time": 45 + } + }, + { + "step_number": 18, + "operation": "move_labware", + "description": "振荡后板送回磁力架P12吸附", + "parameters": { + "source": "Orbital1", + "target": "P12" + } + }, + { + "step_number": 19, + "operation": "incubation", + "description": "再次吸附3分钟", + "parameters": { + "time": 180 + } + }, + { + "step_number": 20, + "operation": "transfer", + "description": "去除乙醇上清液至废液槽", + "parameters": { + "source": "P12", + "target": "P22", + "tip_rack": "BC230", + "volume": 400 + } + }, + { + "step_number": 21, + "operation": "incubation", + "description": "空气干燥15分钟", + "parameters": { + "time": 900 + } + }, + { + "step_number": 22, + "operation": "transfer", + "description": "加30-50μl Elution Buffer洗脱", + "parameters": { + "source": "P4", + "target": "P12", + "tip_rack": "BC230", + "volume": 40 + } + }, + { + "step_number": 23, + "operation": "move_labware", + "description": "移动到Orbital1振荡混匀(60秒)", + "parameters": { + "source": "P12", + "target": "Orbital1" + } + }, + { + "step_number": 24, + "operation": "oscillation", + "description": "Elution Buffer振荡混匀(700-900rpm, 60秒)", + "parameters": { + "rpm": 800, + "time": 60 + } + }, + { + "step_number": 25, + "operation": "move_labware", + "description": "振荡后送回磁力架P12", + "parameters": { + "source": "Orbital1", + "target": "P12" + } + }, + { + "step_number": 26, + "operation": "incubation", + "description": "室温静置3分钟(洗脱反应)", + "parameters": { + "time": 180 + } + }, + { + "step_number": 27, + "operation": "transfer", + "description": "将上清液(DNA)转移到新板(P13)", + "parameters": { + "source": "P12", + "target": "P13", + "tip_rack": "BC230", + "volume": 40 + } + } + ] +} +''' + + +labware_with_liquid = ''' +[ { + "id": "stock plate on P1", + "parent": "deck", + "slot_on_deck": "P1", + "class_name": "nest_12_reservoir_15ml", + "liquid_type": [ + "master_mix" + ], + "liquid_volume": [10000], + "liquid_input_wells": [ + "A1" + ] + }, + { + "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 on TL3", + "parent": "deck", + "slot_on_deck": "TL3", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on TL4", + "parent": "deck", + "slot_on_deck": "TL4", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on TL5", + "parent": "deck", + "slot_on_deck": "TL5", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on P5", + "parent": "deck", + "slot_on_deck": "P5", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on P6", + "parent": "deck", + "slot_on_deck": "P6", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on P7", + "parent": "deck", + "slot_on_deck": "P7", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on P8", + "parent": "deck", + "slot_on_deck": "P8", + "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 4", + "parent": "deck", + "slot_on_deck": "P2", + "class_name": "nest_12_reservoir_15ml", + "liquid_type": [ + "bind beads" + ], + "liquid_volume": [10000], + "liquid_input_wells": [ + "A1" + ] + }, + { + "id": "stock plate on P2", + "parent": "deck", + "slot_on_deck": "P2", + "class_name": "nest_12_reservoir_15ml", + "liquid_type": [ + "bind beads" + ], + "liquid_volume": [10000], + "liquid_input_wells": [ + "A1" + ] + }, + { + "id": "stock plate on P3", + "parent": "deck", + "slot_on_deck": "P3", + "class_name": "nest_12_reservoir_15ml", + "liquid_type": [ + "ethyl alcohol" + ], + "liquid_volume": [10000], + "liquid_input_wells": [ + "A1" + ] + }, + + { + "id": "oscillation", + "parent": "deck", + "slot_on_deck": "Orbital1", + "class_name": "Orbital", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "working plate on P11", + "parent": "deck", + "slot_on_deck": "P11", + "class_name": "NEST 2ml Deep Well Plate", + "liquid_type": [ + ], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "magnetics module on P12", + "parent": "deck", + "slot_on_deck": "P12", + "class_name": "magnetics module", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "working plate on P13", + "parent": "deck", + "slot_on_deck": "P13", + "class_name": "NEST 2ml Deep Well Plate", + "liquid_type": [ + ], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "waste on P22", + "parent": "deck", + "slot_on_deck": "P22", + "class_name": "nest_1_reservoir_195ml", + "liquid_type": [ + ], + "liquid_volume": [], + "liquid_input_wells": [ + ] + } +] + +''' + +handler = LiquidHandlerBiomek() +handler.temp_protocol = { + "meta": {}, + "labwares": [], + "steps": [] +} + +input_steps = json.loads(steps_info) +labwares = json.loads(labware_with_liquid) + +for step in input_steps['steps']: + if step['operation'] != 'transfer': + continue + parameters = step['parameters'] + tip_rack=parameters['tip_rack'] + # 找到labwares中与tip_rack匹配的项的id + tip_rack_id = [lw['id'] for lw in labwares if lw['class_name'] == tip_rack][0] + + handler.transfer_biomek(source=parameters['source'], + target=parameters['target'], + volume=parameters['volume'], + tip_rack=tip_rack_id, + aspirate_techniques='MC P300 high', + dispense_techniques='MC P300 high' + ) +print(json.dumps(handler.temp_protocol['steps'],indent=4, ensure_ascii=False)) + diff --git a/unilabos/devices/liquid_handling/biomek_test.py b/unilabos/devices/liquid_handling/biomek_test.py index 1aa01cec..54db6dfc 100644 --- a/unilabos/devices/liquid_handling/biomek_test.py +++ b/unilabos/devices/liquid_handling/biomek_test.py @@ -296,25 +296,45 @@ class LiquidHandlerBiomek: self._status_queue = kwargs.get("status_queue", None) # 状态队列 self.temp_protocol = {} self.py32_path = "/opt/py32" # Biomek的Python 3.2路径 - self.technique = { + self.aspirate_techniques = { 'MC P300 high':{ - "use_channels": "Span8", - "asp_vols": [50], - "asp_flow_rates": 50, - "dis_flow_rates": 50, - "offsets": None, - "touch_tip": True, - "liquid_height": 20, - "blow_out_air_volume": 20, - "spread": "wide", - "is_96_well": True, - "mix_stage": "none", - "mix_times": None, - "mix_vol": None, - "mix_rate": None, - "mix_liquid_height": None, - "delays": None, - "none_keys": [] + "Solvent": "Water", + } + } + self.dispense_techniques = { + 'MC P300 high':{ + "Span8": False, + "Pod": "Pod1", + "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, + "Span8Wash": False, + "Span8WashVolume": "2", + "Span8WasteVolume": "1", + "SplitVolume": False, + "SplitVolumeCleaning": False, + "Stop": "Destinations", + "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 } } @@ -425,34 +445,24 @@ class LiquidHandlerBiomek: # } # self.temp_protocol["labwares"].append(resource) # return resource + - def transfer_liquid( - self, - sources: Sequence[Container], - targets: Sequence[Container], - tip_racks: Sequence[TipRack], - solvent: Optional[str] = None, - TipLocation :str = None, - *, - 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] = [] + def transfer_biomek( + self, + source: str, + target: str, + tip_rack: str, + volume: float, + aspirate_techniques: str, + dispense_techniques: str, ): + """ + 处理Biomek的液体转移操作。 + + """ + + asp_params = self.aspirate_techniques.get(aspirate_techniques, {}) + dis_params = self.dispense_techniques.get(dispense_techniques, {}) transfer_params = { "Span8": False, @@ -463,7 +473,7 @@ class LiquidHandlerBiomek: "AutoSelectActiveWashTechnique": False, "ActiveWashTechnique": "", "ChangeTipsBetweenDests": False, - "ChangeTipsBetweenSources": False, + "ChangeTipsBetweenSources": True, "DefaultCaption": "", "UseExpression": False, "LeaveTipsOn": False, @@ -493,61 +503,220 @@ class LiquidHandlerBiomek: } items: dict = {} - for idx, (src, dst) in enumerate(zip(sources, targets)): - items[str(idx)] = { - "Source": str(src), - "Destination": str(dst), - "Volume": dis_vols[idx] - } + items["Source"] = source + items["Destination"] = target + items["Volume"] = volume 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 - + transfer_params["Solvent"] = asp_params['Solvent'] + transfer_params["TipLocation"] = tip_rack + transfer_params.update(asp_params) + transfer_params.update(dis_params) self.temp_protocol["steps"].append(transfer_params) return - - def transfer_biomek( - self, - parameters: dict, - technique: str, - ): - """ - 创建一个Biomek液体处理器的转移步骤。 - Args: - step_number (int): 步骤编号 - operation (str): 操作类型 - description (str): 步骤描述 - parameters (dict): 步骤参数 +labware_with_liquid = ''' +[ { + "id": "stock plate on P1", + "parent": "deck", + "slot_on_deck": "P1", + "class_name": "nest_12_reservoir_15ml", + "liquid_type": [ + "master_mix" + ], + "liquid_volume": [10000], + "liquid_input_wells": [ + "A1" + ] + }, + { + "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 on TL3", + "parent": "deck", + "slot_on_deck": "TL3", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on TL4", + "parent": "deck", + "slot_on_deck": "TL4", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on TL5", + "parent": "deck", + "slot_on_deck": "TL5", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on P5", + "parent": "deck", + "slot_on_deck": "P5", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on P6", + "parent": "deck", + "slot_on_deck": "P6", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on P7", + "parent": "deck", + "slot_on_deck": "P7", + "class_name": "BC230", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "Tip Rack BC230 on P8", + "parent": "deck", + "slot_on_deck": "P8", + "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 4", + "parent": "deck", + "slot_on_deck": "P2", + "class_name": "nest_12_reservoir_15ml", + "liquid_type": [ + "bind beads" + ], + "liquid_volume": [10000], + "liquid_input_wells": [ + "A1" + ] + }, + { + "id": "stock plate on P2", + "parent": "deck", + "slot_on_deck": "P2", + "class_name": "nest_12_reservoir_15ml", + "liquid_type": [ + "bind beads" + ], + "liquid_volume": [10000], + "liquid_input_wells": [ + "A1" + ] + }, + { + "id": "stock plate on P3", + "parent": "deck", + "slot_on_deck": "P3", + "class_name": "nest_12_reservoir_15ml", + "liquid_type": [ + "ethyl alcohol" + ], + "liquid_volume": [10000], + "liquid_input_wells": [ + "A1" + ] + }, - Returns: - dict: 创建的转移步骤字典 - """ - - sources = parameters.get("source") - targets = parameters.get("target") - tip_rack = parameters.get("tip_rack") - volume = parameters.get("volume") - liquid_type = parameters.get("liquid_type", "Well Content") - other_params = self.technique.get(technique, {}) + { + "id": "oscillation", + "parent": "deck", + "slot_on_deck": "Orbital1", + "class_name": "Orbital", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "working plate on P11", + "parent": "deck", + "slot_on_deck": "P11", + "class_name": "NEST 2ml Deep Well Plate", + "liquid_type": [ + ], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "magnetics module on P12", + "parent": "deck", + "slot_on_deck": "P12", + "class_name": "magnetics module", + "liquid_type": [], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "working plate on P13", + "parent": "deck", + "slot_on_deck": "P13", + "class_name": "NEST 2ml Deep Well Plate", + "liquid_type": [ + ], + "liquid_volume": [], + "liquid_input_wells": [ + ] + }, + { + "id": "waste on P22", + "parent": "deck", + "slot_on_deck": "P22", + "class_name": "nest_1_reservoir_195ml", + "liquid_type": [ + ], + "liquid_volume": [], + "liquid_input_wells": [ + ] + } +] + +''' - self.transfer_liquid( - sources=[sources], - targets=[targets], - TipLocation=tip_rack, - tip_racks=[tip_rack], - solvent=liquid_type, - dis_vols=[volume], - **other_params - ) - return handler = LiquidHandlerBiomek() @@ -556,13 +725,24 @@ handler.temp_protocol = { "labwares": [], "steps": [] } + input_steps = json.loads(steps_info) +labwares = json.loads(labware_with_liquid) for step in input_steps['steps']: if step['operation'] != 'transfer': continue parameters = step['parameters'] - handler.transfer_biomek(parameters, technique='MC P300 high') + tip_rack=parameters['tip_rack'] + # 找到labwares中与tip_rack匹配的项的id + tip_rack_id = [lw['id'] for lw in labwares if lw['class_name'] == tip_rack][0] + handler.transfer_biomek(source=parameters['source'], + target=parameters['target'], + volume=parameters['volume'], + tip_rack=tip_rack_id, + aspirate_techniques='MC P300 high', + dispense_techniques='MC P300 high' + ) print(json.dumps(handler.temp_protocol['steps'],indent=4, ensure_ascii=False))