3 from __future__
import division
4 from __future__
import print_function
5 from __future__
import absolute_import
6 from builtins
import zip
7 from builtins
import range
10 from .molecule
import Molecule, Elements
11 from .nifty
import isint, isfloat
13 np.set_printoptions(precision=4)
16 print(
'\n'.join([
'%-3s' % M.elem[ii] +
' '.join([
'% 7.3f' % j
for j
in i])
for ii, i
in enumerate(mode)]))
27 for line
in open(gauout).readlines():
28 line = line.strip().expandtabs()
31 if re.match(
"^[0-9]+ +[0-9]+ +[0-9]+( +[-+]?([0-9]*\.)?[0-9]+){3}$", line):
34 elemThis.append(Elements[int(sline[1])])
35 xyz.append([float(i)
for i
in sline[3:]])
39 elif elem != elemThis:
40 logger.error(
'Gaussian output parser will not work if successive calculations have different numbers of atoms!\n')
45 elif XMode == 0
and "Coordinates (Angstroms)" in line:
48 if line.strip().startswith(
'Frequencies'):
52 if 'Frequencies' in line:
54 frqs += [float(i)
for i
in s[2:]]
55 if re.match(
'^[ \t]*Atom', line):
57 readmodes = [[]
for i
in range(nfrq)]
58 if 'IR Inten' in line:
59 intens += [float(i)
for i
in s[3:]]
60 if 'Imaginary Frequencies' in line:
64 if len(s) != nfrq*3+2:
69 readmodes[i].append([float(s[j])
for j
in range(2+3*i,5+3*i)])
70 if VModeNxt
is not None: VMode = VModeNxt
71 unnorm = [np.array(i)
for i
in modes]
72 return np.array(frqs), [i/np.linalg.norm(i)
for i
in unnorm], np.array(intens), elem, xyz
77 xyzpath = os.path.join(os.path.split(os.path.abspath(tcout))[0], scrdir,
'CentralGeometry.initcond.xyz')
78 tcdat = os.path.join(os.path.split(os.path.abspath(tcout))[0], scrdir,
'Frequencies.dat')
79 if not os.path.exists(xyzpath):
80 raise RuntimeError(
"%s doesn't exist; please provide a scratch folder to this function" % xyzpath)
81 if not os.path.exists(tcdat):
82 raise RuntimeError(
"%s doesn't exist; please provide a scratch folder to this function" % tcdat)
89 for line
in open(tcout):
90 if 'Vibrational Frequencies/Thermochemical Analysis After Removing Rotation and Translation' in line:
94 if len(ls) == 8
and ls[0].isdigit():
95 freqs.append(float(ls[2]))
96 intensities.append(float(ls[3]))
97 elif len(ls) == 3
and ls[2].endswith(
'i'):
98 freqs.append(-1*float(ls[2][:-1]))
99 intensities.append(0.0)
100 if line.strip() ==
'':
102 if found_vib
is False:
103 raise RuntimeError(
"No frequency data was found in file %s" % filename)
105 for lineNumber, line
in enumerate(open(tcdat).readlines()):
108 numAtoms = int(s[-1])
109 elif lineNumber == 1:
110 numModes = int(s[-1])
112 frqs = np.zeros(numModes, dtype=float)
113 unnorm = [np.zeros(3*numAtoms, dtype=float)
for i
in range(numModes)]
116 modeNumbers = [int(i)
for i
in s]
117 elif lineCounter == 1:
118 theseFrqs = [float(i)
for i
in s]
119 if len(theseFrqs) != len(modeNumbers):
120 raise RuntimeError(
'Parser error! Expected # frequencies to equal # modes')
121 for i
in range(len(theseFrqs)):
122 frqs[modeNumbers[i]] = theseFrqs[i]
123 elif lineCounter >= 3:
124 if lineCounter%3 == 0:
126 raise RuntimeError(
'Parser error! Expected integer at start of line')
127 disps = [float(i)
for i
in s[1:]]
129 disps = [float(i)
for i
in s]
131 if len(disps) != len(modeNumbers):
132 raise RuntimeError(
'Parser error! Expected # displacements to equal # modes')
133 for i
in range(len(disps)):
134 unnorm[modeNumbers[i]][lineCounter-3] = disps[i]
135 if idx == 3*numAtoms-1:
138 if np.max(np.abs(np.array(frqs)-np.array(freqs))) > 1.0:
139 raise RuntimeError(
"Inconsistent frequencies from TeraChem output and scratch")
140 return np.array(frqs), [i/np.linalg.norm(i)
for i
in unnorm], np.array(intensities), Mxyz.elem, Mxyz.xyzs[0]
151 for line
in open(qcout).readlines():
152 line = line.strip().expandtabs()
155 if re.match(
"^[0-9]+ +[A-Z][A-Za-z]?( +[-+]?([0-9]*\.)?[0-9]+){3}$", line):
158 elemThis.append(sline[1])
159 xyz.append([float(i)
for i
in sline[2:]])
163 elif elem != elemThis:
164 logger.error(
'Q-Chem output parser will not work if successive calculations have different numbers of atoms!\n')
169 elif XMode == 0
and re.match(
"Standard Nuclear Orientation".lower(), line.lower()):
172 if 'VIBRATIONAL ANALYSIS' in line:
174 if VMode > 0
and line.strip().startswith(
'Mode:'):
178 if 'Frequency:' in line:
180 frqs += [float(i)
for i
in s[1:]]
181 if re.match(
'^X +Y +Z', line):
183 readmodes = [[]
for i
in range(nfrq)]
184 if 'IR Intens:' in line:
185 intens += [float(i)
for i
in s[2:]]
186 if 'Imaginary Frequencies' in line:
190 if len(s) != nfrq*3+1:
192 modes += readmodes[:]
193 elif 'TransDip' not in s:
194 for i
in range(nfrq):
195 readmodes[i].append([float(s[j])
for j
in range(1+3*i,4+3*i)])
196 if VModeNxt
is not None: VMode = VModeNxt
197 unnorm = [np.array(i)
for i
in modes]
198 return np.array(frqs), [i/np.linalg.norm(i)
for i
in unnorm], np.array(intens), elem, xyz
210 for line
in open(psiout).readlines():
212 if 'Frequency:' in line:
214 if line.split()[-1].endswith(
'i'):
215 frqs.append(-1*float(line.split()[-1][:-1]))
218 frqs.append(float(line.split()[-1]))
220 if re.match(
'^[ \t]+X', line):
227 modes.append(readmode[:])
231 readmode.append([float(i)/np.sqrt(m)
for i
in s[1:4]])
232 if VModeNxt
is not None: VMode = VModeNxt
237 xyz.append([float(i)
for i
in s[1:4]])
241 xyzs.append(np.array(xyz))
244 if line.strip().startswith(
"Geometry (in Angstrom)"):
246 EMode = len(elem) == 0
247 unnorm = [np.array(i)
for i
in modes]
248 return np.array(frqs), [i/np.linalg.norm(i)
for i
in unnorm], np.zeros_like(frqs), elem, np.array(xyzs[-1])
251 """ Read ForceBalance-formatted vibrational data from a vdata.txt file. """ 260 for line
in open(vfnm):
261 line = line.split(
'#')[0]
263 if len(s) == 1
and na == -1:
265 xyz = np.zeros((na, 3))
269 elif an < na
and len(s) == 4:
271 xyz[an, :] = np.array([float(i)
for i
in s[1:]])
274 ref_eigvals.append(float(s[0]))
275 ref_eigvecs.append(np.zeros((na, 3)))
278 ref_eigvecs[-1][an, :] = np.array([float(i)
for i
in s])
283 logger.info(line +
'\n')
284 logger.error(
"This line doesn't comply with our vibration file format!\n")
287 ref_eigvals = np.array(ref_eigvals)
288 ref_eigvecs = np.array(ref_eigvecs)
289 for v2
in ref_eigvecs:
290 v2 /= np.linalg.norm(v2)
291 return ref_eigvals, ref_eigvecs, np.zeros_like(ref_eigvals), elem, xyz
294 """ Apply harmonic vibrational scaling factors. """ 306 print(
" Freq(Old) Freq(New) RawShift NewShift DShift")
322 att = (frq-div)/(frq-hscal*div)
323 shift = (hscal - 1.0) * frq
325 print(
"%10.3f %10.3f % 9.3f % 9.3f % 8.3f" % (frq, frq+newshift, shift, newshift, newshift-shift))
326 newfrq = frq+newshift
335 att = (frq-div)/(frq-lscal*div)
336 shift = (lscal - 1.0) * frq
338 print(
"%10.3f %10.3f % 9.3f % 9.3f % 8.3f" % (frq, frq+newshift, shift, newshift, newshift-shift))
339 newfrq = frq+newshift
343 return np.array([scale_one(i)
for i
in arr])
347 for line
in open(fout):
348 if 'TeraChem' in line:
350 elif 'Q-Chem' in line:
354 elif 'Gaussian' in line:
356 elif 'ForceBalance' in line:
359 raise RuntimeError(
'Cannot determine format')
363 psifrqs, psimodes, _, __, ___ =
read_frq_gen(sys.argv[1])
365 gaufrqs, gaumodes, _, __, ___ =
read_frq_gen(sys.argv[3])
366 for i, j, ii, jj, iii, jjj
in zip(psifrqs, psimodes, qcfrqs, qcmodes, gaufrqs, gaumodes):
367 print(
"PsiFreq:", i,
"QCFreq", ii,
"GauFreq", iii)
368 print(
"PsiMode:", np.linalg.norm(j))
370 print(
"QCMode:", np.linalg.norm(jj))
371 if np.linalg.norm(j - jj) < np.linalg.norm(j + jj):
375 print(
"GauMode:", np.linalg.norm(jjj))
376 if np.linalg.norm(j - jjj) < np.linalg.norm(j + jjj):
381 print(
"DMode (QC-Gau):", end=
' ')
382 if np.linalg.norm(jj - jjj) < np.linalg.norm(jj + jjj):
383 print(np.linalg.norm(jj - jjj))
386 print(np.linalg.norm(jj + jjj))
389 print(
"DMode (QC-Psi):", end=
' ')
390 if np.linalg.norm(jj - j) < np.linalg.norm(jj + j):
391 print(np.linalg.norm(jj - j))
394 print(np.linalg.norm(jj + j))
397 if __name__ ==
"__main__":
def read_frq_tc(tcout, scrdir='scr')
Lee-Ping's general file format conversion class.
def isint(word)
ONLY matches integers! If you have a decimal point? None shall pass!
def scale_freqs(arr)
Apply harmonic vibrational scaling factors.
def isfloat(word)
Matches ANY number; it can be a decimal, scientific notation, integer, or what have you...
def read_frq_fb(vfnm)
Read ForceBalance-formatted vibrational data from a vdata.txt file.