计算化学公社

 找回密码 Forget password
 注册 Register
Views: 5283|回复 Reply: 9
打印 Print 上一主题 Last thread 下一主题 Next thread

[Python] 【求助】想用python写一个提取Gaussian偶合常数计算结果的脚本

[复制链接 Copy URL]

70

帖子

0

威望

4770

eV
积分
4840

Level 6 (一方通行)

跳转到指定楼层 Go to specific reply
楼主
各位老师好:
我在做Gaussian偶合常数计算的时候,发现手动提取偶合常数计算值非常耗时,尤其当涉及到要提取多个原子对的计算结果、以及当分子存在多构象(需要做构象平均时),手动提取更是耗时,于是萌生了想要写一个脚本来提取计算结果的想法。
断断续续自学python有一小阵了,但是当要自己写脚本来解决实际问题的时候,还是有点发懵。我的初步想法是:把偶合常数计算结果对应的所有行【如Total nuclear spin-spin coupling J (Hz): 下面的行】从文件中提取出来,经过一系列操作,最后用numpy生成一个二维数组。当给出一对原子编号(a,b)时,就可以通过array[a][b]索引出对应的偶合常数。
目前,“提取偶合常数计算结果对应的行”问题不大,但是“转换二维数组”捣鼓了好一阵也搞不定。
现在,想请教各位老师:(1)首先,我是不是把这个问题弄的太复杂了?(2)其次,能不能请各位老师针对这个需求给我一些关键的思路?谢谢!
(PS:附件中附了一个我之前用B972/pcJ-1做偶合常数计算的输出文件,由于关键词里面写了readatoms,仅指定计算了个别原子,所以计算结果里面大部分是0。但形式跟计算所有原子时并没有差别)
非常非常感谢!

sscc-test.log

420.25 KB, 下载次数 Times of downloads: 23

490

帖子

2

威望

5122

eV
积分
5652

Level 6 (一方通行)

2#
发表于 Post on 2019-8-26 08:23:10 | 只看该作者 Only view this author
可以参考一下Multiwfn中读取Overlap矩阵的子程序,具体可以参考Multiwfn源代码中,util.f90文件中的“subroutine readmatgau”子程序。

评分 Rate

参与人数
Participants 1
eV +1 收起 理由
Reason
sobereva + 1

查看全部评分 View all ratings

339

帖子

0

威望

5049

eV
积分
5388

Level 6 (一方通行)

3#
发表于 Post on 2019-8-26 10:56:49 | 只看该作者 Only view this author
用pandas的concat函数做数据拼接:把原子编号作为Dataframes的index和colomn names,做横向拼接,你就会得到一个64*64的Dataframe,就搞定了

3097

帖子

29

威望

1万

eV
积分
17094

Level 6 (一方通行)

4#
发表于 Post on 2019-8-26 11:41:53 | 只看该作者 Only view this author

  1. def lower_triangle_to_full_matrix(input_lists):
  2.     # convert a lower triangle lists (diagonal included) to a full matrix
  3.     dim = len(input_lists[-1])
  4.     ret = [["" for x in range(dim)] for y in range(dim)]
  5.     for x in range(dim):
  6.         for y in range(dim):
  7.             if x<=y:
  8.                 ret[x][y] = input_lists[y][x]
  9.             else:
  10.                 ret[x][y] = input_lists[x][y]
  11.     return ret




  12. def read_lower_triangle_matrix(column_count,input_lines):
  13.     import numpy as np

  14.     # Read in Gaussian output lower triangle matrix and generate a 2D-python-list
  15.     # example input at the end of input (it should not include the title, e.g. spin-spin coupling J (Hz), but include table headers, e.g. 1 2 3 4 5)
  16.     # without text to number conversion

  17.     discard_lines = [0]+[sum(list(range(column_count+1,0,-5))[:(x+1)]) for x in range(int(column_count/5))] # Table headers to delete
  18.     input_lines = [line.split()[1:] for count,line in enumerate(input_lines.splitlines()) if count not in discard_lines] # delete table headers (vertical and horizontal)
  19.     lines_to_merge = [[x]+list(range(column_count-5,0,-5))[:int(x/5)] for x in range(column_count)]
  20.     lines_to_merge = [list(np.cumsum(x)) for x in lines_to_merge]
  21.     lower_triangle = [sum([input_lines[line_count] for line_count in x],[]) for x in lines_to_merge]
  22.     return lower_triangle_to_full_matrix(lower_triangle)
复制代码
很早之前写的,仅供参考

评分 Rate

参与人数
Participants 2
eV +6 收起 理由
Reason
liyunecho + 3
sobereva + 3

查看全部评分 View all ratings

70

帖子

0

威望

4770

eV
积分
4840

Level 6 (一方通行)

5#
 楼主 Author| 发表于 Post on 2019-8-26 13:08:46 | 只看该作者 Only view this author
让你变成回忆 发表于 2019-8-26 08:23
可以参考一下Multiwfn中读取Overlap矩阵的子程序,具体可以参考Multiwfn源代码中,util.f90文件中的“subro ...

非常感谢您的指点,我记得Multiwfn是用Fortran写的,目前的确还没有相关的编程基础,等python再学熟悉一点,后续我会再学Fortran的。依然感谢您!

70

帖子

0

威望

4770

eV
积分
4840

Level 6 (一方通行)

6#
 楼主 Author| 发表于 Post on 2019-8-26 13:09:37 | 只看该作者 Only view this author
chrinide 发表于 2019-8-26 10:56
用pandas的concat函数做数据拼接:把原子编号作为Dataframes的index和colomn names,做横向拼接,你就会得 ...

非常感谢您,我马上去了解一下pandas的concat函数,太感谢了

70

帖子

0

威望

4770

eV
积分
4840

Level 6 (一方通行)

7#
 楼主 Author| 发表于 Post on 2019-8-26 13:13:08 | 只看该作者 Only view this author
liyuanhe211 发表于 2019-8-26 11:41
很早之前写的,仅供参考

非常感谢李老师,我好好研究一下您提供的代码,实在太感谢您了!

3753

帖子

3

威望

1万

eV
积分
19663

Level 6 (一方通行)

围观吃瓜群众

8#
发表于 Post on 2019-8-26 17:07:36 | 只看该作者 Only view this author
本帖最后由 卡开发发 于 2019-8-26 22:10 编辑

提供个土方法:你可以按照数据的顺序去生成index=[atom_i,atom_j](i>=j),然后数据data直接用正则表达式抓,然后给定i、j就data(index.index([i,j]))。
  1. import re
  2. import sys
  3. import ast
  4. #作者:卡开发发
  5. #日期:2019-08-26
  6. #使用方法:read.py *.log [i,j]
  7. #*.log为Gaussian输出文件,[i,j]分别是行和列指标
  8. #(python指标从0开始,所以比Gaussian对应的指标减去1)
  9. #比如LZ附件的"Total nuclear spin-spin coupling J (Hz)"的[48,30]为-0.245622D+00
  10. #read.py sscc-test.log. [47,29]结果输出为:
  11. #-0.245622D+00
  12. #其余根据需要可进一步进行修改

  13. #get_link用于得到特定link的输出
  14. def get_link(num,text):
  15.         #通过输出文件开头的Initial command:...字段获得Gaussian的目录
  16.         gdir=re.findall('Initial\scommand:\n\s(.*)l1\.exe',text)[0]
  17.         #选择Enter xxx.exe和Leave Link xxx之间的内容
  18.         head='\(Enter\s'+gdir+'l'+str(num)+'\.exe\)\n'
  19.         tail='\n\sLeave\sLink\s.?'+str(num)+'\sat\s'
  20.         link=re.findall(head+'(.*)'+tail,text,re.S)[0]
  21.         return link

  22. #get_info用于从link1002输出的部分读取结果
  23. def get_info(text):
  24.         #选择density=...到最后的内容
  25.         info_=re.findall('density=\s*\d*.\d*\n(.*)',text,re.S)[0]
  26.         #选择...(Hz):为标题和数据的分隔
  27.         sep='\s\D*\s\(Hz\):'
  28.         titles=re.findall(sep,info_,re.S)
  29.         infos_=re.split(sep,info_,re.S)[1:]
  30.         #数据通过分割后以字典形式保存
  31.         infos=[]
  32.         for i in range(10):
  33.                 #数据分割后会被按照顺序排列为一维数组
  34.                 #[[0,0],[1,0],[1,1],[2,1]...[5,4],[6,0]...[6,4],[7,0]...]
  35.                 data=re.findall('\s(.\d\.\d*D.\d\d)',infos_[i],re.S)
  36.                 info={'title':titles[i],'data':data}
  37.                 infos.append(info)
  38.         return infos

  39. #gen_index用于生成与数据一维数组对应的序号
  40. def gen_index(natoms):
  41.         #先产生一个下三角阵,满足i>=j
  42.         #[0,0]
  43.         #[1,0][1,1]
  44.         #[2,0][2,1][2,2]
  45.         #...
  46.         #[9,0][9,1]... ... [9,9]
  47.         #... ...
  48.         mat=[]
  49.         for i in range(natoms):
  50.                 for j in range(natoms):
  51.                         if i>=j:
  52.                                 mat.append([i,j])
  53.         #按j指标范围的顺序重新排列成一维
  54.         #[0,0],[1,0],[1,1],[2,1]...[5,4],[6,0]...[6,4]... #k=0
  55.         #[5,5],[6,5],[6,6],[7,5]...[10,0]...[10,9][11,0]...[11,9] #k=1
  56.         #...
  57.         index=[]
  58.         for k in range(natoms//5+1):
  59.                 for num in mat:
  60.                         if k*5<=num[1]<(k+1)*5:
  61.                                 index.append(num)
  62.         return index

  63. #打开文件,运行参数1用来存放输出文件名
  64. f=open(sys.argv[1],'r')
  65. text=f.read()
  66. #读取link101输出内容来获取原子数目,通过原子数目生成对应的序号
  67. link101=get_link(101,text)
  68. natoms=int(re.findall('NAtoms=\s*(\d*)\sNQM=',link101)[0])
  69. index=gen_index(natoms)
  70. #读取link1002输出内容来获取我们需要的数据
  71. link1002=get_link(1002,text)
  72. infos=get_info(link1002)
  73. #运行参数2用来存放我们指定的序号,以数组形式
  74. index_=ast.literal_eval(sys.argv[2])
  75. #输出序号对应的值
  76. #此处infos[-1]为"Total nuclear spin-spin coupling J (Hz)",也能换成别的
  77. print(infos[-1]['data'][index.index(index_)])
复制代码


日常打哑谜&&探寻更多可能。
原理问题不公开讨论,非商业性质讨论欢迎私聊。不做培*,不接代*,不接*发谢谢。

70

帖子

0

威望

4770

eV
积分
4840

Level 6 (一方通行)

9#
 楼主 Author| 发表于 Post on 2019-8-27 01:37:12 | 只看该作者 Only view this author
卡开发发 发表于 2019-8-26 17:07
提供个土方法:你可以按照数据的顺序去生成index=[atom_i,atom_j](i>=j),然后数据data直接用正则表达式 ...

太感谢卡开发发老师了,之前实在没敢奢求有大神能帮我写出直接能用的脚本,感谢您的无私付出,我明天好好学习下这个脚本!
这两天我一直在捣鼓这个事情,也希望后面能把自己手头这个写完,哪怕代码丑一点
再次感谢您!

3753

帖子

3

威望

1万

eV
积分
19663

Level 6 (一方通行)

围观吃瓜群众

10#
发表于 Post on 2019-8-27 01:40:01 | 只看该作者 Only view this author
happyknighthawk 发表于 2019-8-27 01:37
太感谢卡开发发老师了,之前实在没敢奢求有大神能帮我写出直接能用的脚本,感谢您的无私付出,我明天好好 ...

没关系啊,我也是初学。大家一起讨论,程序一起研究,这样知识学到手才会有点带感
日常打哑谜&&探寻更多可能。
原理问题不公开讨论,非商业性质讨论欢迎私聊。不做培*,不接代*,不接*发谢谢。

本版积分规则 Credits rule

手机版 Mobile version|北京科音自然科学研究中心 Beijing Kein Research Center for Natural Sciences|京公网安备 11010502035419号|计算化学公社 — 北京科音旗下高水平计算化学交流论坛 ( 京ICP备14038949号-1 )|网站地图

GMT+8, 2025-8-12 21:51 , Processed in 0.814705 second(s), 24 queries , Gzip On.

快速回复 返回顶部 返回列表 Return to list