mirror of
https://github.com/deepmodeling/Uni-Lab-OS
synced 2026-03-25 17:39:02 +00:00
- separate_protocol: 修复vessel_id字符串解包crash和tuple truthy or逻辑错误
- heatchill_protocol: 修复vessel字段传入enriched dict而非vessel_id的问题
- hydrogenate_protocol: 修复5处vessel格式错误(裸字符串→{"id": vessel_id})
- 三个文件同时完成debug_print统一和工具函数去重
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
196 lines
6.3 KiB
Python
196 lines
6.3 KiB
Python
from typing import List, Dict, Any, Union
|
||
import networkx as nx
|
||
from .utils.vessel_parser import get_vessel, find_connected_heatchill
|
||
from .utils.unit_parser import parse_time_input, parse_temperature_input
|
||
from .utils.logger_util import debug_print
|
||
|
||
|
||
def validate_and_fix_params(temp: float, time: float, stir_speed: float) -> tuple:
|
||
"""验证和修正参数"""
|
||
if temp < -50.0 or temp > 300.0:
|
||
debug_print(f"⚠️ 温度 {temp}°C 超出范围,修正为 25°C")
|
||
temp = 25.0
|
||
|
||
if time < 0:
|
||
debug_print(f"⚠️ 时间 {time}s 无效,修正为 300s")
|
||
time = 300.0
|
||
|
||
if stir_speed < 0 or stir_speed > 1500.0:
|
||
debug_print(f"⚠️ 搅拌速度 {stir_speed} RPM 超出范围,修正为 300 RPM")
|
||
stir_speed = 300.0
|
||
|
||
return temp, time, stir_speed
|
||
|
||
def generate_heat_chill_protocol(
|
||
G: nx.DiGraph,
|
||
vessel: dict, # 🔧 修改:从字符串改为字典类型
|
||
temp: float = 25.0,
|
||
time: Union[str, float] = "300",
|
||
temp_spec: str = "",
|
||
time_spec: str = "",
|
||
pressure: str = "",
|
||
reflux_solvent: str = "",
|
||
stir: bool = False,
|
||
stir_speed: float = 300.0,
|
||
purpose: str = "",
|
||
**kwargs
|
||
) -> List[Dict[str, Any]]:
|
||
"""
|
||
生成加热/冷却操作的协议序列 - 支持vessel字典
|
||
|
||
Args:
|
||
G: 设备图
|
||
vessel: 容器字典(从XDL传入)
|
||
temp: 目标温度 (°C)
|
||
time: 加热时间(支持字符串如 "30 min")
|
||
temp_spec: 温度规格说明(优先级高于temp)
|
||
time_spec: 时间规格说明(优先级高于time)
|
||
pressure: 压力设置
|
||
reflux_solvent: 回流溶剂
|
||
stir: 是否搅拌
|
||
stir_speed: 搅拌速度 (RPM)
|
||
purpose: 操作目的说明
|
||
**kwargs: 其他参数(兼容性)
|
||
|
||
Returns:
|
||
List[Dict[str, Any]]: 加热/冷却操作的动作序列
|
||
"""
|
||
|
||
# 🔧 核心修改:从字典中提取容器ID
|
||
vessel_id, vessel_data = get_vessel(vessel)
|
||
|
||
debug_print(f"开始生成加热冷却协议: vessel={vessel_id}, temp={temp}°C, "
|
||
f"time={time}, stir={stir} ({stir_speed} RPM), purpose='{purpose}'")
|
||
|
||
# 参数验证
|
||
if not vessel_id:
|
||
raise ValueError("vessel 参数不能为空")
|
||
|
||
if vessel_id not in G.nodes():
|
||
raise ValueError(f"容器 '{vessel_id}' 不存在于系统中")
|
||
|
||
# 参数解析
|
||
# 温度解析:优先使用 temp_spec
|
||
final_temp = parse_temperature_input(temp_spec, temp) if temp_spec else temp
|
||
|
||
# 时间解析:优先使用 time_spec
|
||
final_time = parse_time_input(time_spec) if time_spec else parse_time_input(time)
|
||
|
||
# 参数修正
|
||
final_temp, final_time, stir_speed = validate_and_fix_params(final_temp, final_time, stir_speed)
|
||
|
||
debug_print(f"最终参数: temp={final_temp}°C, time={final_time}s, stir_speed={stir_speed} RPM")
|
||
|
||
# 查找设备
|
||
try:
|
||
heatchill_id = find_connected_heatchill(G, vessel_id)
|
||
debug_print(f"使用加热设备: {heatchill_id}")
|
||
except Exception as e:
|
||
raise ValueError(f"无法找到加热设备: {str(e)}")
|
||
|
||
# 生成动作
|
||
# 模拟运行时间优化
|
||
original_time = final_time
|
||
simulation_time_limit = 100.0 # 模拟运行时间限制:100秒
|
||
|
||
if final_time > simulation_time_limit:
|
||
final_time = simulation_time_limit
|
||
debug_print(f"模拟运行优化: {original_time}s → {final_time}s (限制为{simulation_time_limit}s)")
|
||
|
||
action_sequence = []
|
||
heatchill_action = {
|
||
"device_id": heatchill_id,
|
||
"action_name": "heat_chill",
|
||
"action_kwargs": {
|
||
"vessel": {"id": vessel_id},
|
||
"temp": float(final_temp),
|
||
"time": float(final_time),
|
||
"stir": bool(stir),
|
||
"stir_speed": float(stir_speed),
|
||
"purpose": str(purpose or f"加热到 {final_temp}°C") + (f" (模拟时间: {final_time}s)" if original_time != final_time else "")
|
||
}
|
||
}
|
||
action_sequence.append(heatchill_action)
|
||
|
||
debug_print(f"加热冷却协议生成完成: {len(action_sequence)} 个动作, "
|
||
f"vessel={vessel_id}, temp={final_temp}°C, time={final_time}s")
|
||
|
||
return action_sequence
|
||
|
||
def generate_heat_chill_to_temp_protocol(
|
||
G: nx.DiGraph,
|
||
vessel: dict, # 🔧 修改参数类型
|
||
temp: float = 25.0,
|
||
time: Union[str, float] = 100.0,
|
||
**kwargs
|
||
) -> List[Dict[str, Any]]:
|
||
"""生成加热到指定温度的协议(简化版)"""
|
||
vessel_id, _ = get_vessel(vessel)
|
||
debug_print(f"生成加热到温度协议: {vessel_id} → {temp}°C")
|
||
return generate_heat_chill_protocol(G, vessel, temp, time, **kwargs)
|
||
|
||
def generate_heat_chill_start_protocol(
|
||
G: nx.DiGraph,
|
||
vessel: dict, # 🔧 修改参数类型
|
||
temp: float = 25.0,
|
||
purpose: str = "",
|
||
**kwargs
|
||
) -> List[Dict[str, Any]]:
|
||
"""生成开始加热操作的协议序列"""
|
||
|
||
# 🔧 核心修改:从字典中提取容器ID
|
||
vessel_id, _ = get_vessel(vessel)
|
||
|
||
debug_print(f"生成启动加热协议: vessel={vessel_id}, temp={temp}°C")
|
||
|
||
# 基础验证
|
||
if not vessel_id or vessel_id not in G.nodes():
|
||
raise ValueError("vessel 参数无效")
|
||
|
||
# 查找设备
|
||
heatchill_id = find_connected_heatchill(G, vessel_id)
|
||
|
||
# 生成动作
|
||
action_sequence = [{
|
||
"device_id": heatchill_id,
|
||
"action_name": "heat_chill_start",
|
||
"action_kwargs": {
|
||
"temp": temp,
|
||
"purpose": purpose or f"开始加热到 {temp}°C",
|
||
"vessel": {"id": vessel_id},
|
||
}
|
||
}]
|
||
|
||
debug_print(f"启动加热协议生成完成")
|
||
return action_sequence
|
||
|
||
def generate_heat_chill_stop_protocol(
|
||
G: nx.DiGraph,
|
||
vessel: dict, # 🔧 修改参数类型
|
||
**kwargs
|
||
) -> List[Dict[str, Any]]:
|
||
"""生成停止加热操作的协议序列"""
|
||
|
||
# 🔧 核心修改:从字典中提取容器ID
|
||
vessel_id, _ = get_vessel(vessel)
|
||
|
||
debug_print(f"生成停止加热协议: vessel={vessel_id}")
|
||
|
||
# 基础验证
|
||
if not vessel_id or vessel_id not in G.nodes():
|
||
raise ValueError("vessel 参数无效")
|
||
|
||
# 查找设备
|
||
heatchill_id = find_connected_heatchill(G, vessel_id)
|
||
|
||
# 生成动作
|
||
action_sequence = [{
|
||
"device_id": heatchill_id,
|
||
"action_name": "heat_chill_stop",
|
||
"action_kwargs": {
|
||
}
|
||
}]
|
||
|
||
debug_print(f"停止加热协议生成完成")
|
||
return action_sequence
|