mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2026-02-07 23:45:10 +00:00
action to resource & 0.9.12
This commit is contained in:
@@ -154,12 +154,153 @@ def find_filtrate_vessel(G: nx.DiGraph, filtrate_vessel: str = "") -> str:
|
||||
debug_print(f"⚠️ 使用默认滤液容器: waste_workup")
|
||||
return "waste_workup"
|
||||
|
||||
def extract_vessel_id(vessel: Union[str, dict]) -> str:
|
||||
"""
|
||||
从vessel参数中提取vessel_id
|
||||
|
||||
Args:
|
||||
vessel: vessel字典或vessel_id字符串
|
||||
|
||||
Returns:
|
||||
str: vessel_id
|
||||
"""
|
||||
if isinstance(vessel, dict):
|
||||
vessel_id = vessel.get("id", "")
|
||||
debug_print(f"🔧 从vessel字典提取ID: {vessel_id}")
|
||||
return vessel_id
|
||||
elif isinstance(vessel, str):
|
||||
debug_print(f"🔧 vessel参数为字符串: {vessel}")
|
||||
return vessel
|
||||
else:
|
||||
debug_print(f"⚠️ 无效的vessel参数类型: {type(vessel)}")
|
||||
return ""
|
||||
|
||||
def get_vessel_display_info(vessel: Union[str, dict]) -> str:
|
||||
"""
|
||||
获取容器的显示信息(用于日志)
|
||||
|
||||
Args:
|
||||
vessel: vessel字典或vessel_id字符串
|
||||
|
||||
Returns:
|
||||
str: 显示信息
|
||||
"""
|
||||
if isinstance(vessel, dict):
|
||||
vessel_id = vessel.get("id", "unknown")
|
||||
vessel_name = vessel.get("name", "")
|
||||
if vessel_name:
|
||||
return f"{vessel_id} ({vessel_name})"
|
||||
else:
|
||||
return vessel_id
|
||||
else:
|
||||
return str(vessel)
|
||||
|
||||
def get_vessel_liquid_volume(vessel: dict) -> float:
|
||||
"""
|
||||
获取容器中的液体体积 - 支持vessel字典
|
||||
|
||||
Args:
|
||||
vessel: 容器字典
|
||||
|
||||
Returns:
|
||||
float: 液体体积(mL)
|
||||
"""
|
||||
if not vessel or "data" not in vessel:
|
||||
debug_print(f"⚠️ 容器数据为空,返回 0.0mL")
|
||||
return 0.0
|
||||
|
||||
vessel_data = vessel["data"]
|
||||
vessel_id = vessel.get("id", "unknown")
|
||||
|
||||
debug_print(f"🔍 读取容器 '{vessel_id}' 体积数据: {vessel_data}")
|
||||
|
||||
# 检查liquid_volume字段
|
||||
if "liquid_volume" in vessel_data:
|
||||
liquid_volume = vessel_data["liquid_volume"]
|
||||
|
||||
# 处理列表格式
|
||||
if isinstance(liquid_volume, list):
|
||||
if len(liquid_volume) > 0:
|
||||
volume = liquid_volume[0]
|
||||
if isinstance(volume, (int, float)):
|
||||
debug_print(f"✅ 容器 '{vessel_id}' 体积: {volume}mL (列表格式)")
|
||||
return float(volume)
|
||||
|
||||
# 处理直接数值格式
|
||||
elif isinstance(liquid_volume, (int, float)):
|
||||
debug_print(f"✅ 容器 '{vessel_id}' 体积: {liquid_volume}mL (数值格式)")
|
||||
return float(liquid_volume)
|
||||
|
||||
# 检查其他可能的体积字段
|
||||
volume_keys = ['current_volume', 'total_volume', 'volume']
|
||||
for key in volume_keys:
|
||||
if key in vessel_data:
|
||||
try:
|
||||
volume = float(vessel_data[key])
|
||||
if volume > 0:
|
||||
debug_print(f"✅ 容器 '{vessel_id}' 体积: {volume}mL (字段: {key})")
|
||||
return volume
|
||||
except (ValueError, TypeError):
|
||||
continue
|
||||
|
||||
debug_print(f"⚠️ 无法获取容器 '{vessel_id}' 的体积,返回默认值 0.0mL")
|
||||
return 0.0
|
||||
|
||||
def update_vessel_volume(vessel: dict, G: nx.DiGraph, new_volume: float, description: str = "") -> None:
|
||||
"""
|
||||
更新容器体积(同时更新vessel字典和图节点)
|
||||
|
||||
Args:
|
||||
vessel: 容器字典
|
||||
G: 网络图
|
||||
new_volume: 新体积
|
||||
description: 更新描述
|
||||
"""
|
||||
vessel_id = vessel.get("id", "unknown")
|
||||
|
||||
if description:
|
||||
debug_print(f"🔧 更新容器体积 - {description}")
|
||||
|
||||
# 更新vessel字典中的体积
|
||||
if "data" in vessel:
|
||||
if "liquid_volume" in vessel["data"]:
|
||||
current_volume = vessel["data"]["liquid_volume"]
|
||||
if isinstance(current_volume, list):
|
||||
if len(current_volume) > 0:
|
||||
vessel["data"]["liquid_volume"][0] = new_volume
|
||||
else:
|
||||
vessel["data"]["liquid_volume"] = [new_volume]
|
||||
else:
|
||||
vessel["data"]["liquid_volume"] = new_volume
|
||||
else:
|
||||
vessel["data"]["liquid_volume"] = new_volume
|
||||
else:
|
||||
vessel["data"] = {"liquid_volume": new_volume}
|
||||
|
||||
# 同时更新图中的容器数据
|
||||
if vessel_id in G.nodes():
|
||||
if 'data' not in G.nodes[vessel_id]:
|
||||
G.nodes[vessel_id]['data'] = {}
|
||||
|
||||
vessel_node_data = G.nodes[vessel_id]['data']
|
||||
current_node_volume = vessel_node_data.get('liquid_volume', 0.0)
|
||||
|
||||
if isinstance(current_node_volume, list):
|
||||
if len(current_node_volume) > 0:
|
||||
G.nodes[vessel_id]['data']['liquid_volume'][0] = new_volume
|
||||
else:
|
||||
G.nodes[vessel_id]['data']['liquid_volume'] = [new_volume]
|
||||
else:
|
||||
G.nodes[vessel_id]['data']['liquid_volume'] = new_volume
|
||||
|
||||
debug_print(f"📊 容器 '{vessel_id}' 体积已更新为: {new_volume:.2f}mL")
|
||||
|
||||
def generate_wash_solid_protocol(
|
||||
G: nx.DiGraph,
|
||||
vessel: str,
|
||||
vessel: Union[str, dict], # 🔧 修改:支持vessel字典
|
||||
solvent: str,
|
||||
volume: Union[float, str] = "50",
|
||||
filtrate_vessel: str = "",
|
||||
filtrate_vessel: Union[str, dict] = "", # 🔧 修改:支持vessel字典
|
||||
temp: float = 25.0,
|
||||
stir: bool = False,
|
||||
stir_speed: float = 0.0,
|
||||
@@ -172,21 +313,58 @@ def generate_wash_solid_protocol(
|
||||
**kwargs
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
生成固体清洗协议(精简版)
|
||||
生成固体清洗协议 - 支持vessel字典和体积运算
|
||||
|
||||
Args:
|
||||
G: 有向图,节点为设备和容器,边为流体管道
|
||||
vessel: 清洗容器字典(从XDL传入)或容器ID字符串
|
||||
solvent: 清洗溶剂名称
|
||||
volume: 溶剂体积(每次清洗)
|
||||
filtrate_vessel: 滤液收集容器字典或容器ID字符串
|
||||
temp: 清洗温度(°C)
|
||||
stir: 是否搅拌
|
||||
stir_speed: 搅拌速度(RPM)
|
||||
time: 搅拌时间
|
||||
repeats: 清洗重复次数
|
||||
volume_spec: 体积规格(small/medium/large)
|
||||
repeats_spec: 重复次数规格(few/several/many)
|
||||
mass: 固体质量(用于计算溶剂用量)
|
||||
event: 事件描述
|
||||
**kwargs: 其他可选参数
|
||||
|
||||
Returns:
|
||||
List[Dict[str, Any]]: 固体清洗操作的动作序列
|
||||
"""
|
||||
|
||||
# 🔧 核心修改:从vessel参数中提取vessel_id
|
||||
vessel_id = extract_vessel_id(vessel)
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
|
||||
# 🔧 处理filtrate_vessel参数
|
||||
filtrate_vessel_id = extract_vessel_id(filtrate_vessel) if filtrate_vessel else ""
|
||||
|
||||
debug_print("🧼" * 20)
|
||||
debug_print("🚀 开始生成固体清洗协议 ✨")
|
||||
debug_print("🚀 开始生成固体清洗协议(支持vessel字典和体积运算)✨")
|
||||
debug_print(f"📝 输入参数:")
|
||||
debug_print(f" 🥽 vessel: {vessel}")
|
||||
debug_print(f" 🥽 vessel: {vessel_display} (ID: {vessel_id})")
|
||||
debug_print(f" 🧪 solvent: {solvent}")
|
||||
debug_print(f" 💧 volume: {volume}")
|
||||
debug_print(f" 🗑️ filtrate_vessel: {filtrate_vessel_id}")
|
||||
debug_print(f" ⏰ time: {time}")
|
||||
debug_print(f" 🔄 repeats: {repeats}")
|
||||
debug_print("🧼" * 20)
|
||||
|
||||
# 🔧 新增:记录清洗前的容器状态
|
||||
debug_print("🔍 记录清洗前容器状态...")
|
||||
if isinstance(vessel, dict):
|
||||
original_volume = get_vessel_liquid_volume(vessel)
|
||||
debug_print(f"📊 清洗前液体体积: {original_volume:.2f}mL")
|
||||
else:
|
||||
original_volume = 0.0
|
||||
debug_print(f"📊 vessel为字符串格式,无法获取体积信息")
|
||||
|
||||
# 📋 快速验证
|
||||
if not vessel or vessel not in G.nodes():
|
||||
if not vessel_id or vessel_id not in G.nodes(): # 🔧 使用 vessel_id
|
||||
debug_print("❌ 容器验证失败! 😱")
|
||||
raise ValueError("vessel 参数无效")
|
||||
|
||||
@@ -225,8 +403,10 @@ def generate_wash_solid_protocol(
|
||||
debug_print("📍 步骤2: 查找设备... 🔍")
|
||||
try:
|
||||
solvent_source = find_solvent_source(G, solvent)
|
||||
actual_filtrate_vessel = find_filtrate_vessel(G, filtrate_vessel)
|
||||
actual_filtrate_vessel = find_filtrate_vessel(G, filtrate_vessel_id)
|
||||
debug_print(f"🎉 设备配置完成 ✨")
|
||||
debug_print(f" 🧪 溶剂源: {solvent_source}")
|
||||
debug_print(f" 🗑️ 滤液容器: {actual_filtrate_vessel}")
|
||||
except Exception as e:
|
||||
debug_print(f"❌ 设备查找失败: {str(e)} 😭")
|
||||
raise ValueError(f"设备查找失败: {str(e)}")
|
||||
@@ -235,6 +415,10 @@ def generate_wash_solid_protocol(
|
||||
debug_print("📍 步骤3: 生成清洗动作... 🧼")
|
||||
action_sequence = []
|
||||
|
||||
# 🔧 新增:体积变化跟踪变量
|
||||
current_volume = original_volume
|
||||
total_solvent_used = 0.0
|
||||
|
||||
for cycle in range(final_repeats):
|
||||
debug_print(f" 🔄 第{cycle+1}/{final_repeats}次清洗...")
|
||||
|
||||
@@ -242,10 +426,11 @@ def generate_wash_solid_protocol(
|
||||
try:
|
||||
from .pump_protocol import generate_pump_protocol_with_rinsing
|
||||
|
||||
debug_print(f" 💧 添加溶剂: {final_volume}mL {solvent}")
|
||||
transfer_actions = generate_pump_protocol_with_rinsing(
|
||||
G=G,
|
||||
from_vessel=solvent_source,
|
||||
to_vessel=vessel,
|
||||
to_vessel=vessel_id, # 🔧 使用 vessel_id
|
||||
volume=final_volume,
|
||||
amount="",
|
||||
time=0.0,
|
||||
@@ -261,17 +446,26 @@ def generate_wash_solid_protocol(
|
||||
if transfer_actions:
|
||||
action_sequence.extend(transfer_actions)
|
||||
debug_print(f" ✅ 转移动作: {len(transfer_actions)}个 🚚")
|
||||
|
||||
# 🔧 新增:更新体积 - 添加溶剂后
|
||||
current_volume += final_volume
|
||||
total_solvent_used += final_volume
|
||||
|
||||
if isinstance(vessel, dict):
|
||||
update_vessel_volume(vessel, G, current_volume,
|
||||
f"第{cycle+1}次清洗添加{final_volume}mL溶剂后")
|
||||
|
||||
except Exception as e:
|
||||
debug_print(f" ❌ 转移失败: {str(e)} 😞")
|
||||
|
||||
# 2. 搅拌(如果需要)
|
||||
if stir and final_time > 0:
|
||||
debug_print(f" 🌪️ 搅拌: {final_time}s @ {stir_speed}RPM")
|
||||
stir_action = {
|
||||
"device_id": "stirrer_1",
|
||||
"action_name": "stir",
|
||||
"action_kwargs": {
|
||||
"vessel": vessel,
|
||||
"vessel": vessel_id, # 🔧 使用 vessel_id
|
||||
"time": str(time),
|
||||
"stir_time": final_time,
|
||||
"stir_speed": stir_speed,
|
||||
@@ -282,11 +476,12 @@ def generate_wash_solid_protocol(
|
||||
debug_print(f" ✅ 搅拌动作: {final_time}s, {stir_speed}RPM 🌪️")
|
||||
|
||||
# 3. 过滤
|
||||
debug_print(f" 🌊 过滤到: {actual_filtrate_vessel}")
|
||||
filter_action = {
|
||||
"device_id": "filter_1",
|
||||
"action_name": "filter",
|
||||
"action_kwargs": {
|
||||
"vessel": vessel,
|
||||
"vessel": vessel_id, # 🔧 使用 vessel_id
|
||||
"filtrate_vessel": actual_filtrate_vessel,
|
||||
"temp": temp,
|
||||
"volume": final_volume
|
||||
@@ -295,6 +490,15 @@ def generate_wash_solid_protocol(
|
||||
action_sequence.append(filter_action)
|
||||
debug_print(f" ✅ 过滤动作: → {actual_filtrate_vessel} 🌊")
|
||||
|
||||
# 🔧 新增:更新体积 - 过滤后(液体被滤除)
|
||||
# 假设滤液完全被移除,固体残留在容器中
|
||||
filtered_volume = current_volume * 0.9 # 假设90%的液体被过滤掉
|
||||
current_volume = current_volume - filtered_volume
|
||||
|
||||
if isinstance(vessel, dict):
|
||||
update_vessel_volume(vessel, G, current_volume,
|
||||
f"第{cycle+1}次清洗过滤后")
|
||||
|
||||
# 4. 等待(缩短时间)
|
||||
wait_time = 5.0 # 🕐 缩短等待时间:10s → 5s
|
||||
action_sequence.append({
|
||||
@@ -303,14 +507,146 @@ def generate_wash_solid_protocol(
|
||||
})
|
||||
debug_print(f" ✅ 等待: {wait_time}s ⏰")
|
||||
|
||||
# 🔧 新增:清洗完成后的最终状态报告
|
||||
if isinstance(vessel, dict):
|
||||
final_volume_vessel = get_vessel_liquid_volume(vessel)
|
||||
else:
|
||||
final_volume_vessel = current_volume
|
||||
|
||||
# 🎊 总结
|
||||
debug_print("🧼" * 20)
|
||||
debug_print(f"🎉 固体清洗协议生成完成! ✨")
|
||||
debug_print(f"📊 总动作数: {len(action_sequence)} 个")
|
||||
debug_print(f"🥽 清洗容器: {vessel}")
|
||||
debug_print(f"🧪 使用溶剂: {solvent}")
|
||||
debug_print(f"💧 清洗体积: {final_volume}mL × {final_repeats}次")
|
||||
debug_print(f"📊 协议统计:")
|
||||
debug_print(f" 📋 总动作数: {len(action_sequence)} 个")
|
||||
debug_print(f" 🥽 清洗容器: {vessel_display}")
|
||||
debug_print(f" 🧪 使用溶剂: {solvent}")
|
||||
debug_print(f" 💧 单次体积: {final_volume}mL")
|
||||
debug_print(f" 🔄 清洗次数: {final_repeats}次")
|
||||
debug_print(f" 💧 总溶剂用量: {total_solvent_used:.2f}mL")
|
||||
debug_print(f"📊 体积变化统计:")
|
||||
debug_print(f" - 清洗前体积: {original_volume:.2f}mL")
|
||||
debug_print(f" - 清洗后体积: {final_volume_vessel:.2f}mL")
|
||||
debug_print(f" - 溶剂总用量: {total_solvent_used:.2f}mL")
|
||||
debug_print(f"⏱️ 预计总时间: {(final_time + 5) * final_repeats / 60:.1f} 分钟")
|
||||
debug_print("🧼" * 20)
|
||||
|
||||
return action_sequence
|
||||
return action_sequence
|
||||
|
||||
# 🔧 新增:便捷函数
|
||||
def wash_with_water(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
volume: Union[float, str] = "50",
|
||||
repeats: int = 2) -> List[Dict[str, Any]]:
|
||||
"""用水清洗固体"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"💧 水洗固体: {vessel_display} ({repeats} 次)")
|
||||
return generate_wash_solid_protocol(G, vessel, "water", volume=volume, repeats=repeats)
|
||||
|
||||
def wash_with_ethanol(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
volume: Union[float, str] = "30",
|
||||
repeats: int = 1) -> List[Dict[str, Any]]:
|
||||
"""用乙醇清洗固体"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"🍺 乙醇洗固体: {vessel_display} ({repeats} 次)")
|
||||
return generate_wash_solid_protocol(G, vessel, "ethanol", volume=volume, repeats=repeats)
|
||||
|
||||
def wash_with_acetone(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
volume: Union[float, str] = "25",
|
||||
repeats: int = 1) -> List[Dict[str, Any]]:
|
||||
"""用丙酮清洗固体"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"💨 丙酮洗固体: {vessel_display} ({repeats} 次)")
|
||||
return generate_wash_solid_protocol(G, vessel, "acetone", volume=volume, repeats=repeats)
|
||||
|
||||
def wash_with_ether(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
volume: Union[float, str] = "40",
|
||||
repeats: int = 2) -> List[Dict[str, Any]]:
|
||||
"""用乙醚清洗固体"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"🌬️ 乙醚洗固体: {vessel_display} ({repeats} 次)")
|
||||
return generate_wash_solid_protocol(G, vessel, "diethyl_ether", volume=volume, repeats=repeats)
|
||||
|
||||
def wash_with_cold_solvent(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
solvent: str, volume: Union[float, str] = "30",
|
||||
repeats: int = 1) -> List[Dict[str, Any]]:
|
||||
"""用冷溶剂清洗固体"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"❄️ 冷{solvent}洗固体: {vessel_display} ({repeats} 次)")
|
||||
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume,
|
||||
temp=5.0, repeats=repeats)
|
||||
|
||||
def wash_with_hot_solvent(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
solvent: str, volume: Union[float, str] = "50",
|
||||
repeats: int = 1) -> List[Dict[str, Any]]:
|
||||
"""用热溶剂清洗固体"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"🔥 热{solvent}洗固体: {vessel_display} ({repeats} 次)")
|
||||
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume,
|
||||
temp=60.0, repeats=repeats)
|
||||
|
||||
def wash_with_stirring(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
solvent: str, volume: Union[float, str] = "50",
|
||||
stir_time: Union[str, float] = "5 min",
|
||||
repeats: int = 1) -> List[Dict[str, Any]]:
|
||||
"""带搅拌的溶剂清洗"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"🌪️ 搅拌清洗: {vessel_display} with {solvent} ({repeats} 次)")
|
||||
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume,
|
||||
stir=True, stir_speed=200.0,
|
||||
time=stir_time, repeats=repeats)
|
||||
|
||||
def thorough_wash(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
solvent: str, volume: Union[float, str] = "50") -> List[Dict[str, Any]]:
|
||||
"""彻底清洗(多次重复)"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"🔄 彻底清洗: {vessel_display} with {solvent} (5 次)")
|
||||
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume, repeats=5)
|
||||
|
||||
def quick_rinse(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
solvent: str, volume: Union[float, str] = "20") -> List[Dict[str, Any]]:
|
||||
"""快速冲洗(单次,小体积)"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"⚡ 快速冲洗: {vessel_display} with {solvent}")
|
||||
return generate_wash_solid_protocol(G, vessel, solvent, volume=volume, repeats=1)
|
||||
|
||||
def sequential_wash(G: nx.DiGraph, vessel: Union[str, dict],
|
||||
solvents: list, volume: Union[float, str] = "40") -> List[Dict[str, Any]]:
|
||||
"""连续多溶剂清洗"""
|
||||
vessel_display = get_vessel_display_info(vessel)
|
||||
debug_print(f"📝 连续清洗: {vessel_display} with {' → '.join(solvents)}")
|
||||
|
||||
action_sequence = []
|
||||
for solvent in solvents:
|
||||
wash_actions = generate_wash_solid_protocol(G, vessel, solvent,
|
||||
volume=volume, repeats=1)
|
||||
action_sequence.extend(wash_actions)
|
||||
|
||||
return action_sequence
|
||||
|
||||
# 测试函数
|
||||
def test_wash_solid_protocol():
|
||||
"""测试固体清洗协议"""
|
||||
debug_print("🧪 === WASH SOLID PROTOCOL 测试 === ✨")
|
||||
|
||||
# 测试vessel参数处理
|
||||
debug_print("🔧 测试vessel参数处理...")
|
||||
|
||||
# 测试字典格式
|
||||
vessel_dict = {"id": "filter_flask_1", "name": "过滤瓶1",
|
||||
"data": {"liquid_volume": 25.0}}
|
||||
vessel_id = extract_vessel_id(vessel_dict)
|
||||
vessel_display = get_vessel_display_info(vessel_dict)
|
||||
volume = get_vessel_liquid_volume(vessel_dict)
|
||||
debug_print(f" 字典格式: {vessel_dict}")
|
||||
debug_print(f" → ID: {vessel_id}, 显示: {vessel_display}, 体积: {volume}mL")
|
||||
|
||||
# 测试字符串格式
|
||||
vessel_str = "filter_flask_2"
|
||||
vessel_id = extract_vessel_id(vessel_str)
|
||||
vessel_display = get_vessel_display_info(vessel_str)
|
||||
debug_print(f" 字符串格式: {vessel_str}")
|
||||
debug_print(f" → ID: {vessel_id}, 显示: {vessel_display}")
|
||||
|
||||
debug_print("✅ 测试完成 🎉")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_wash_solid_protocol()
|
||||
Reference in New Issue
Block a user