This commit is contained in:
2025-10-09 09:43:34 +08:00
parent e6141689c1
commit 5d1a4d04f2
4 changed files with 179 additions and 59 deletions

19
softBV/out/Br.csv Normal file
View File

@@ -0,0 +1,19 @@
filename,formula,conductivity(e-3S/m)
1080005.cif,Cs3Li2Br5,21.23
1147619.cif,Li3YBr6,20.00
1147621.cif,Li3InBr6,7.23
1211043.cif,LiFeBr4,11.60
1222492.cif,Li3ErBr6,29.61
1222679.cif,Li2MnBr4,9.68
2033990.cif,CsLi2Br3,9.71
22967.cif,Li2FeBr4,11.21
23057.cif,CsLiBr2,5.12
2763849.cif,Cs3Li2Br5,121.34
28237.cif,RbLiBr2,3.46
28250.cif,Li2MnBr4,12.25
28326.cif,LiGaBr4,1.56
28327.cif,LiGaBr3,8.32
28829.cif,Li2ZnBr4,15.71
37873.cif,Li3ErBr6,10.90
580554.cif,CsLi3Br4,38.40
606680.cif,CsLi2Br3,20.63
1 filename formula conductivity(e-3S/m)
2 1080005.cif Cs3Li2Br5 21.23
3 1147619.cif Li3YBr6 20.00
4 1147621.cif Li3InBr6 7.23
5 1211043.cif LiFeBr4 11.60
6 1222492.cif Li3ErBr6 29.61
7 1222679.cif Li2MnBr4 9.68
8 2033990.cif CsLi2Br3 9.71
9 22967.cif Li2FeBr4 11.21
10 23057.cif CsLiBr2 5.12
11 2763849.cif Cs3Li2Br5 121.34
12 28237.cif RbLiBr2 3.46
13 28250.cif Li2MnBr4 12.25
14 28326.cif LiGaBr4 1.56
15 28327.cif LiGaBr3 8.32
16 28829.cif Li2ZnBr4 15.71
17 37873.cif Li3ErBr6 10.90
18 580554.cif CsLi3Br4 38.40
19 606680.cif CsLi2Br3 20.63

View File

@@ -3,17 +3,16 @@ import sys
import subprocess
import re
import csv
import argparse
from pathlib import Path
# --- 配置区 ---
# softBV.x 可执行文件的路径,请根据你的实际情况修改
# 使用 Path.home() 来自动获取用户家目录,比 '~' 更可靠
SOFTBV_EXECUTABLE = Path.home() / "tool/softBV-GUI_linux/bin/softBV.x"
# 固定的命令参数
MOBILE_ION = "Li"
ION_VALENCE = "1"
SF_VALUE = "1000"
# 输出CSV文件的名称
OUTPUT_CSV_FILE = "conductivity_results.csv"
@@ -33,47 +32,73 @@ def check_executable():
sys.exit(1)
def get_formula_from_cif_line2(cif_path):
"""
通过读取CIF文件的第二行来提取化学式。
期望的格式是 'data_FORMULA'
"""
try:
with open(cif_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
if len(lines) > 1:
second_line = lines[1].strip() # .strip() 去除首尾空白和换行符
if second_line.lower().startswith('data_'):
# 提取 'data_' 之后的内容作为化学式
return second_line[5:]
else:
print(f"\n警告: 文件 {cif_path.name} 的第二行格式不正确 (不是以'data_'开头)。", file=sys.stderr)
return "FormatError"
else:
print(f"\n警告: 文件 {cif_path.name} 行数不足2行。", file=sys.stderr)
return "FileTooShort"
except Exception as e:
print(f"\n警告: 读取文件 {cif_path.name} 时发生错误: {e}", file=sys.stderr)
return "ReadError"
def parse_conductivity(output_text):
"""
从 softBV.x 的输出文本中解析电导率(conductivity)。
使用正则表达式来匹配 'MD: conductivity = <value>' 格式的行。
"""
# 正则表达式解释:
# ^ - 匹配行首
# \s* - 匹配任意数量的空白字符
# MD: conductivity - 匹配字面字符串
# \s*=\s* - 匹配等号,前后可以有任意空白
# ([-\d.eE+]+) - 捕获组1: 匹配并捕获一个或多个数字、点、'e'/'E'、'+'/'-' (科学计数法)
"""从 softBV.x 的输出文本中解析并格式化电导率"""
pattern = re.compile(r"^\s*MD: conductivity\s*=\s*([-\d.eE+]+)", re.MULTILINE)
match = pattern.search(output_text)
if match:
# 返回捕获到的第一个组 (也就是数值部分)
return match.group(1)
conductivity_str = match.group(1)
try:
conductivity_val = float(conductivity_str)
# 将单位从 S/m 转换为 1e-3 S/m (mS/m), 需要乘以 1000
conductivity_ms_m = conductivity_val * 1000
# 格式化为两位小数的字符串
return f"{conductivity_ms_m:.2f}"
except ValueError:
return "ValueError"
else:
# 如果没有找到匹配的行,返回 None
return None
def main():
"""主函数"""
# 1. 检查命令行参数
if len(sys.argv) != 2:
print(f"用法: python {sys.argv[0]} <cif_folder_name>")
print(f"例如: python {sys.argv[0]} Br")
sys.exit(1)
parser = argparse.ArgumentParser(
description="运行 softBV.x 计算电导率并汇总到CSV文件。",
formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument("folder", type=str, help="包含CIF文件的目标文件夹路径。")
parser.add_argument(
"-t", "--temperature",
type=int,
default=1000,
help="模拟温度 (K),对应 softBV.x 的最后一个参数。\n默认值: 1000"
)
args = parser.parse_args()
target_folder = Path(sys.argv[1])
target_folder = Path(args.folder)
temperature = str(args.temperature)
# 检查目标文件夹是否存在
if not target_folder.is_dir():
print(f"错误: 文件夹 '{target_folder}' 不存在。")
sys.exit(1)
# 检查 softBV.x 是否配置正确
check_executable()
# 2. 查找所有 .cif 文件
cif_files = sorted(list(target_folder.glob("*.cif")))
if not cif_files:
@@ -81,61 +106,45 @@ def main():
return
print(f"'{target_folder}' 中找到 {len(cif_files)} 个 .cif 文件,开始处理...")
print(f"模拟温度设置为: {temperature} K")
results = [] # 用于存储 (文件名, 电导率)
results = []
# 3. 遍历文件,执行命令并提取数据
for cif_file in cif_files:
print(f" -> 正在处理: {cif_file} ...", end="", flush=True)
# 构建命令
# 使用新的函数获取化学式
formula = get_formula_from_cif_line2(cif_file)
command = [
str(SOFTBV_EXECUTABLE),
"--md",
str(cif_file),
MOBILE_ION,
ION_VALENCE,
SF_VALUE
str(SOFTBV_EXECUTABLE), "--md", str(cif_file),
MOBILE_ION, ION_VALENCE, temperature
]
try:
# 执行命令并捕获输出
# capture_output=True 将 stdout 和 stderr 分别捕获
# text=True (或 encoding='utf-8') 将输出解码为字符串
# check=True 如果命令返回非零退出码 (表示错误),则会抛出异常
process_result = subprocess.run(
command,
capture_output=True,
text=True,
check=True,
timeout=300 # 设置一个超时时间例如300秒防止程序卡死
command, capture_output=True, text=True, check=True, timeout=300
)
# 从标准输出中解析数据
conductivity = parse_conductivity(process_result.stdout)
if conductivity is not None:
results.append((cif_file.name, conductivity))
print(f" 成功, conductivity = {conductivity}")
results.append([cif_file.name, formula, conductivity])
print(f" 成功, Formula: {formula}, Conductivity: {conductivity} (x10^-3 S/m)")
else:
print(" 失败 (无法在输出中找到conductivity)")
# 你也可以选择将错误信息记录下来
# results.append((cif_file.name, "Error: Not Found"))
results.append([cif_file.name, formula, "NotFound"])
except subprocess.CalledProcessError as e:
# 命令执行失败
print(f" 失败 (命令执行错误)")
print(f" 错误信息: {e.stderr.strip()}")
# results.append((cif_file.name, "Error: Execution Failed"))
print(f" 错误信息: {e.stderr.strip()}", file=sys.stderr)
results.append([cif_file.name, formula, "ExecError"])
except subprocess.TimeoutExpired:
print(f" 失败 (命令执行超时)")
# results.append((cif_file.name, "Error: Timeout"))
results.append([cif_file.name, formula, "Timeout"])
except Exception as e:
# 其他未知错误
print(f" 失败 (发生未知错误: {e})")
# results.append((cif_file.name, f"Error: {e}"))
print(f" 失败 (发生未知错误: {e})", file=sys.stderr)
results.append([cif_file.name, formula, "UnknownError"])
# 4. 将结果写入CSV文件
if not results:
print("没有成功处理任何文件不生成CSV。")
return
@@ -145,9 +154,7 @@ def main():
try:
with open(OUTPUT_CSV_FILE, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
# 写入表头
writer.writerow(['filename', 'conductivity'])
# 写入数据
writer.writerow(['filename', 'formula', 'conductivity(e-3S/m)'])
writer.writerows(results)
print("CSV文件已成功生成")
except IOError as e: