forked from NicoRicardi/cubetools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cubediff.py
executable file
·137 lines (124 loc) · 3.81 KB
/
cubediff.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/python
###########################################################
#
# ./cubediff file1 file2
# output=file2-file1
# [file1] cube file (generated by regular Q-Chem plotter)
# [file2] cube file (generated by libwfa)
#
# !! Make sure that file1 is generated using N+1 points
# (as compared to the libwfa plot) in the same box.
#
###########################################################
import sys, re
import cubicle as cl
from string import Template
filename = sys.argv[1]
file_ref = sys.argv[2]
ext = filename[:-5]
ext_ref = file_ref[:-5]
cubelist = []
###### Parse cube headers ######
### (File 1) ENVIRONMENT
header = []
pointnums = []
head_pattern = '^\s*(\d+)\s+(-?\d+\.\d+\s*){3}\n'
natm = 1
with open(filename) as g:
for j,line in enumerate(g):
if j == 2:
natm = int(line.split()[0])
if j == natm+4+2:
break
header.append(line)
with open(filename) as f:
cube = f.read()
head_str = ''.join(header) # string of total header (File 1)
for i,head in enumerate(re.finditer(head_pattern,head_str,flags=re.MULTILINE)):
if i >= 1:
pointnums.append(head.group(1))
pnums = list(map(int,pointnums))
### (File 2) TOTAL SYSTEM
header_ref = []
with open(file_ref) as ref:
for j,line in enumerate(ref):
if j == 2:
natm = int(line.split()[0])
if j == natm+4+2:
break
header_ref.append(line)
head_ref_str = ''.join(header_ref) # string of total header (File 2)
###### Parse cube data ######
pattern2 = '(-?\d+\.?\d+[Ee]\ *[-+]?\ *\d+\s*){' + re.escape(str(pnums[2])) + '}'
cubelist.append([])
xcnt = 0
ycnt = 0
for xy,m in enumerate(re.finditer(pattern2,cube)):
if xy % pnums[1] == 0 and xy > 0:
xcnt += 1
ycnt = 0
cubelist.append([]) # append empty list for x
s = m.group().split()
s = list(map(float,s))
cubelist[xcnt].append(s)
ycnt += 1
###### Manipulating cube file ######
del_last = True
# delete last
if del_last == True:
for x in range(pnums[0]):
if x == pnums[0]-1:
del cubelist[x]
continue
for y in range(pnums[1]):
if y == pnums[1]-1:
del cubelist[x][y]
continue
for z in range(pnums[2]):
if z == pnums[2]-1:
del cubelist[x][y][z]
continue
else:
#delete first
for x in reversed(range(pnums[0])):
if x == 0:
del cubelist[x]
continue
for y in reversed(range(pnums[1])):
if y == 0:
del cubelist[x][y]
continue
for z in reversed(range(pnums[2])):
if z == 0:
del cubelist[x][y][z]
continue
# new number of points
for n in range(3):
pnums[n] = pnums[n]-1
###### Write new cube file ######
new_file = filename[:-5]+"_new.cube"
with open(new_file, "w") as out:
out.write(head_ref_str)
for x in range(pnums[0]):
for y in range(pnums[1]):
for z in range(pnums[2]):
if (z+1) % 6 == 0 or z == pnums[2]-1:
out.write(" {0:.9E}\n".format(cubelist[x][y][z]))
else:
out.write(" {0:.9E}".format(cubelist[x][y][z]))
###### Subtract from reference ######
calc = "1.0*"+file_ref+" -1.0*"+new_file
output = file_ref[:-5] + "_diff.cube"
with open(output, "w") as diff:
diff.write(cl.compute_cube(calc))
###### Write Jmol input ######
jmol = Template("""load ${fn}
background white
isosurface ID diff cutoff 0.005 sign "${fn}"
color $$diff translucent 0.5
print "Pausing script to reorientate molecule. Resume with '&plot'."
throw context plot
write image 1024 786 png ${png}
""")
with open(output[:-5]+".spt", "w") as jm:
jm.write(jmol.substitute(fn=output,png=output[:-5]+".png"))