diff --git a/test/experiments/comprehensive_protocol/comprehensive_station.json b/test/experiments/comprehensive_protocol/comprehensive_station.json index 071d913..0d9f5c7 100644 --- a/test/experiments/comprehensive_protocol/comprehensive_station.json +++ b/test/experiments/comprehensive_protocol/comprehensive_station.json @@ -680,7 +680,7 @@ "type": "fluid", "port": { "multiway_valve_1": "5", - "rotavap_1": "sample_in" + "rotavap_1": "samplein" } }, { @@ -770,7 +770,7 @@ "type": "transport", "port": { "multiway_valve_2": "4", - "filter_1": "filter_in" + "filter_1": "filterin" } }, { @@ -800,7 +800,7 @@ "type": "fluid", "port": { "multiway_valve_2": "6", - "separator_1": "separator_in" + "separator_1": "separatorin" } }, { @@ -809,7 +809,7 @@ "target": "collection_bottle_3", "type": "fluid", "port": { - "separator_1": "bottom_phase_out", + "separator_1": "bottomphaseout", "collection_bottle_3": "top" } }, @@ -859,7 +859,7 @@ "target": "waste_bottle_2", "type": "fluid", "port": { - "separator_1": "top_phase_out", + "separator_1": "topphaseout", "waste_bottle_2": "top" } }, @@ -879,7 +879,7 @@ "target": "collection_bottle_1", "type": "transport", "port": { - "filter_1": "filtrate_out", + "filter_1": "filtrateout", "collection_bottle_1": "top" } }, @@ -889,7 +889,7 @@ "target": "waste_bottle_1", "type": "transport", "port": { - "filter_1": "retentate_out", + "filter_1": "retentateout", "waste_bottle_1": "top" } } diff --git a/unilabos/compile/evacuateandrefill_protocol.py b/unilabos/compile/evacuateandrefill_protocol.py index 96e057d..aa44df6 100644 --- a/unilabos/compile/evacuateandrefill_protocol.py +++ b/unilabos/compile/evacuateandrefill_protocol.py @@ -5,38 +5,138 @@ from .pump_protocol import generate_pump_protocol_with_rinsing, generate_pump_pr def find_gas_source(G: nx.DiGraph, gas: str) -> str: - """根据气体名称查找对应的气源""" - # 按照命名规则查找气源 + """ + 根据气体名称查找对应的气源,支持多种匹配模式: + 1. 容器名称匹配 + 2. 气体类型匹配(data.gas_type) + 3. 默认气源 + """ + print(f"EVACUATE_REFILL: 正在查找气体 '{gas}' 的气源...") + + # 第一步:通过容器名称匹配 gas_source_patterns = [ f"gas_source_{gas}", f"gas_{gas}", f"flask_{gas}", - f"{gas}_source" + f"{gas}_source", + f"source_{gas}", + f"reagent_bottle_{gas}", + f"bottle_{gas}" ] for pattern in gas_source_patterns: if pattern in G.nodes(): + print(f"EVACUATE_REFILL: 通过名称匹配找到气源: {pattern}") return pattern - # 模糊匹配 - for node in G.nodes(): - node_class = G.nodes[node].get('class', '') or '' - if 'gas_source' in node_class and gas.lower() in node.lower(): - return node - if node.startswith('flask_') and gas.lower() in node.lower(): - return node + # 第二步:通过气体类型匹配 (data.gas_type) + for node_id in G.nodes(): + node_data = G.nodes[node_id] + node_class = node_data.get('class', '') or '' + + # 检查是否是气源设备 + if ('gas_source' in node_class or + 'gas' in node_id.lower() or + node_id.startswith('flask_')): + + # 检查 data.gas_type + data = node_data.get('data', {}) + gas_type = data.get('gas_type', '') + + if gas_type.lower() == gas.lower(): + print(f"EVACUATE_REFILL: 通过气体类型匹配找到气源: {node_id} (gas_type: {gas_type})") + return node_id + + # 检查 config.gas_type + config = node_data.get('config', {}) + config_gas_type = config.get('gas_type', '') + + if config_gas_type.lower() == gas.lower(): + print(f"EVACUATE_REFILL: 通过配置气体类型匹配找到气源: {node_id} (config.gas_type: {config_gas_type})") + return node_id - # 查找所有可用的气源 - available_gas_sources = [ + # 第三步:查找所有可用的气源设备 + available_gas_sources = [] + for node_id in G.nodes(): + node_data = G.nodes[node_id] + node_class = node_data.get('class', '') or '' + + if ('gas_source' in node_class or + 'gas' in node_id.lower() or + (node_id.startswith('flask_') and any(g in node_id.lower() for g in ['air', 'nitrogen', 'argon']))): + + data = node_data.get('data', {}) + gas_type = data.get('gas_type', 'unknown') + available_gas_sources.append(f"{node_id} (gas_type: {gas_type})") + + print(f"EVACUATE_REFILL: 可用气源列表: {available_gas_sources}") + + # 第四步:如果找不到特定气体,使用默认的第一个气源 + default_gas_sources = [ node for node in G.nodes() if ((G.nodes[node].get('class') or '').startswith('virtual_gas_source') - or ('gas' in node and 'source' in node) - or (node.startswith('flask_') and any(g in node.lower() for g in ['air', 'nitrogen', 'argon', 'vacuum']))) + or 'gas_source' in node) ] + if default_gas_sources: + default_source = default_gas_sources[0] + print(f"EVACUATE_REFILL: ⚠️ 未找到特定气体 '{gas}',使用默认气源: {default_source}") + return default_source + raise ValueError(f"找不到气体 '{gas}' 对应的气源。可用气源: {available_gas_sources}") +def find_gas_source_by_any_match(G: nx.DiGraph, gas: str) -> str: + """ + 增强版气源查找,支持各种匹配方式的别名函数 + """ + return find_gas_source(G, gas) + + +def get_gas_source_type(G: nx.DiGraph, gas_source: str) -> str: + """获取气源的气体类型""" + if gas_source not in G.nodes(): + return "unknown" + + node_data = G.nodes[gas_source] + data = node_data.get('data', {}) + config = node_data.get('config', {}) + + # 检查多个可能的字段 + gas_type = (data.get('gas_type') or + config.get('gas_type') or + data.get('gas') or + config.get('gas') or + "air") # 默认为空气 + + return gas_type + + +def find_vessels_by_gas_type(G: nx.DiGraph, gas: str) -> List[str]: + """ + 根据气体类型查找所有匹配的容器/气源 + """ + matching_vessels = [] + + for node_id in G.nodes(): + node_data = G.nodes[node_id] + + # 检查容器名称匹配 + if gas.lower() in node_id.lower(): + matching_vessels.append(f"{node_id} (名称匹配)") + continue + + # 检查气体类型匹配 + data = node_data.get('data', {}) + config = node_data.get('config', {}) + + gas_type = data.get('gas_type', '') or config.get('gas_type', '') + if gas_type.lower() == gas.lower(): + matching_vessels.append(f"{node_id} (gas_type: {gas_type})") + + return matching_vessels + + def find_vacuum_pump(G: nx.DiGraph) -> str: """查找真空泵设备""" vacuum_pumps = [ diff --git a/unilabos/registry/devices/virtual_device.yaml b/unilabos/registry/devices/virtual_device.yaml index 5efc117..953be1a 100644 --- a/unilabos/registry/devices/virtual_device.yaml +++ b/unilabos/registry/devices/virtual_device.yaml @@ -631,7 +631,7 @@ virtual_filter: data_source: handle data_type: transport description: 需要过滤的样品容器 - handler_key: filter_in + handler_key: filterin io_type: target label: filter_in side: NORTH @@ -639,7 +639,7 @@ virtual_filter: data_source: handle data_type: transport description: 滤液出口 - handler_key: filtrate_out + handler_key: filtrateout io_type: source label: filtrate_out side: SOUTH @@ -647,7 +647,7 @@ virtual_filter: data_source: handle data_type: transport description: 滤渣/固体出口 - handler_key: retentate_out + handler_key: retentateout io_type: source label: retentate_out side: EAST @@ -2433,7 +2433,7 @@ virtual_rotavap: data_source: handle data_type: fluid description: 样品连接口 - handler_key: sample_in + handler_key: samplein io_type: target label: sample_in side: NORTH @@ -2441,7 +2441,7 @@ virtual_rotavap: data_source: handle data_type: fluid description: 浓缩产物出口 - handler_key: product_out + handler_key: productout io_type: source label: product_out side: SOUTH @@ -2449,7 +2449,7 @@ virtual_rotavap: data_source: handle data_type: fluid description: 冷凝溶剂出口 - handler_key: solvent_out + handler_key: solventout io_type: source label: solvent_out side: EAST @@ -2774,7 +2774,7 @@ virtual_separator: data_source: handle data_type: fluid description: 需要分离的混合液体输入口 - handler_key: separator_in + handler_key: separatorin io_type: target label: separator_in side: NORTH @@ -2782,7 +2782,7 @@ virtual_separator: data_source: executor data_type: fluid description: 下相(重相)液体输出口 - handler_key: bottom_phase_out + handler_key: bottomphaseout io_type: source label: bottom_phase_out side: SOUTH @@ -2790,7 +2790,7 @@ virtual_separator: data_source: executor data_type: fluid description: 上相(轻相)液体输出口 - handler_key: top_phase_out + handler_key: topphaseout io_type: source label: top_phase_out side: EAST diff --git a/unilabos/registry/devices/work_station.yaml b/unilabos/registry/devices/work_station.yaml index 3b2765b..2866160 100644 --- a/unilabos/registry/devices/work_station.yaml +++ b/unilabos/registry/devices/work_station.yaml @@ -271,7 +271,7 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel - data_key: reagent data_source: handle @@ -282,7 +282,7 @@ workstation: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -373,13 +373,13 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel output: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -460,7 +460,7 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel - data_key: solvent data_source: handle @@ -471,7 +471,7 @@ workstation: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -580,7 +580,7 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel - data_key: solvent data_source: handle @@ -591,7 +591,7 @@ workstation: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -675,7 +675,7 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel - data_key: solvent data_source: handle @@ -686,7 +686,7 @@ workstation: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -766,13 +766,13 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel output: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -875,13 +875,13 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel output: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -992,7 +992,7 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel - data_key: vessel data_source: handle @@ -1003,7 +1003,7 @@ workstation: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel - data_key: vessel data_source: executor @@ -1102,12 +1102,12 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel + handler_key: FromVessel label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel + handler_key: ToVessel label: To Vessel - data_key: solvent data_source: handle @@ -1118,12 +1118,12 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel_out + handler_key: FromVesselOut label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel_out + handler_key: ToVesselOut label: To Vessel result: {} schema: @@ -1211,13 +1211,13 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel output: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -1288,13 +1288,13 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel output: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -1352,13 +1352,13 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel output: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -1428,12 +1428,12 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel + handler_key: FromVessel label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel + handler_key: ToVessel label: To Vessel - data_key: solvent data_source: handle @@ -1444,12 +1444,12 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel_out + handler_key: FromVesselOut label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel_out + handler_key: ToVesselOut label: To Vessel result: {} schema: @@ -1569,23 +1569,23 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel + handler_key: FromVessel label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel + handler_key: ToVessel label: To Vessel output: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel_out + handler_key: FromVesselOut label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel_out + handler_key: ToVesselOut label: To Vessel result: {} schema: @@ -1673,12 +1673,12 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel + handler_key: FromVessel label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel + handler_key: ToVessel label: To Vessel - data_key: solvent data_source: handle @@ -1689,12 +1689,12 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel_out + handler_key: FromVesselOut label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel_out + handler_key: ToVesselOut label: To Vessel result: {} schema: @@ -1823,13 +1823,13 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel output: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -1900,13 +1900,13 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel output: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -1964,13 +1964,13 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel output: - data_key: vessel data_source: executor data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel result: {} schema: @@ -2046,12 +2046,12 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel + handler_key: FromVessel label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel + handler_key: ToVessel label: To Vessel - data_key: solvent data_source: handle @@ -2062,12 +2062,12 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: from_vessel_out + handler_key: FromVesselOut label: From Vessel - data_key: vessel data_source: executor data_type: resource - handler_key: to_vessel_out + handler_key: ToVesselOut label: To Vessel result: {} schema: @@ -2173,7 +2173,7 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel + handler_key: Vessel label: Vessel - data_key: solvent data_source: handle @@ -2189,7 +2189,7 @@ workstation: - data_key: vessel data_source: handle data_type: resource - handler_key: vessel_out + handler_key: VesselOut label: Vessel Out - data_key: vessel data_source: executor