Materials Studio在执行dmol3模块中结构优化任务时,任务结束后会产生一系列的输出文件,其中sdf文件中存储了结构优化后的结构总能量信息。我们在科研任务中可能需要执行很多结构优化任务,对这些任务结果进行批量处理非常重要,因此实现批量从sdf文件中提取出总能量信息非常重要。这能极大地提高我们处理数据的精度以及节省处理时间。
【实现结果】
首先我们来看一下sdf文件中的信息结构,例如以下文件:
Materials Studio SDF calculation TCVAMP81A 98 0 0 0 0 0 1 V2000 -1.2295 2.1304 0.0000 C 0 0 -7.3777 7.1010 0.0000 C 0 0 ..... M END >BIOVIA, TYPE=DOUBLE, VERSION=1 -3732.25912662 > BIOVIA, TYPE=DOUBLE, VERSION=1 -28.59233110 > BIOVIA, TYPE=DOUBLE, VERSION=1 -0.22252685 > BIOVIA, TYPE=DOUBLE, VERSION=1 -0.11128326 > BIOVIA, TYPE=DOUBLE, VERSION=1 0.11124359 > BIOVIA, TYPE=STATUS, VERSION=1 SUCCESS $$$$
这份sdf文件里面我们只需要提取出这段信息的-3732.25912662。可以发现这个数值是在TOTAL ENERGY字符的下下一行
>BIOVIA, TYPE=DOUBLE, VERSION=1 -3732.25912662
那么代码思路可以设计为:
- 进入文件所在文件夹,将文件名存储在列表中
- 使用readlines()函数逐行读取sdf文件内容,并使用strip()去掉每行两端的空格,将内容存储在列表中
- 识别sdf文件中是否有"SUCCESS"字符,用于判断MS所执行的优化任务是否顺利执行
- 根据总能量数值分布特点,提取其索引,并存储在一个空列表中
- 将文件名及对应总能量按列存储在csv文件
'''
该函数用于读取Materials Studio优化任务后产生的sdf文件,并从该文件提取出结构的最后总能量
'''
import os
import csv
def filter_energy(files_path,exp_path):
'''
files_path:存储了sdf文件的文件夹所在路径
exp_path:存储了sdf文件的文件夹名字
'''
path=os.path.join(files_path,exp_path)#sdf文件所在文件夹路径
save_path=os.path.join(path,exp_path+'.csv')#新建csv文件存储路径
files= os.listdir(path)#遍历文件夹中的所有文件,将文件名存储在列表中
energy=[]#新建空列表用于存储提取的总能量
for file in files: #遍历文件夹中的sdf文件
file_path = os.path.join(path,file)
with open(file_path,'r') as f:#打开sdf文件
lines=f.readlines()#按行读取文件,并按行存储为列表
new_lines=[]#新建空列表,用于存储去掉每行前后空格的字符串
for line in lines:#遍历存储了文件信息的列表
line = line.strip()#去掉每个元素中的前后空格
new_lines.append(line)#将去掉了前后空格的字符串存储在新列表中
#print(new_lines)
if "SUCCESS" in new_lines:#判断sdf文件中是否有"SUCCESS"字符串,用于判断MS所执行的任务是否成功
title_index=new_lines.index('> ')#找到字符串"> "所在索引
energy_index=title_index+2#由于在sdf文件中,总能量数值在TOTAL ENERGY这行的下下一行,所以索引加2
energy.append(new_lines[energy_index])#根据总能量索引提取总能量数值,并添加到空列表中
else:
energy.append("failed")#如果sdf文件中没有"SUCCESS"字符串,说明MS所执行的任务没有成功完成,所以不会有总能量信息
#将前面存储了文件名及相应总能量的列表按列存储在csv文件中
rows = zip(files,energy)
with open(save_path, "w", newline='') as f:
writer = csv.writer(f)
for row in rows:
writer.writerow(row)
filter_energy("D:software_output_filesquntum_experimentcheck_results_yjysdf_files","sdf_of_1Vac1N-H")



