webmo 1.3.3__tar.gz → 1.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {webmo-1.3.3/webmo.egg-info → webmo-1.4.2}/PKG-INFO +2 -2
- {webmo-1.3.3 → webmo-1.4.2}/webmo/__init__.py +1 -1
- {webmo-1.3.3 → webmo-1.4.2}/webmo/gui.py +12 -0
- {webmo-1.3.3 → webmo-1.4.2}/webmo/spectrum.py +9 -6
- webmo-1.4.2/webmo/util.py +287 -0
- {webmo-1.3.3 → webmo-1.4.2}/webmo/webmo_rest.py +3 -15
- {webmo-1.3.3 → webmo-1.4.2/webmo.egg-info}/PKG-INFO +2 -2
- webmo-1.3.3/webmo/util.py +0 -25
- {webmo-1.3.3 → webmo-1.4.2}/LICENSE +0 -0
- {webmo-1.3.3 → webmo-1.4.2}/README.md +0 -0
- {webmo-1.3.3 → webmo-1.4.2}/setup.cfg +0 -0
- {webmo-1.3.3 → webmo-1.4.2}/setup.py +0 -0
- {webmo-1.3.3 → webmo-1.4.2}/webmo.egg-info/SOURCES.txt +0 -0
- {webmo-1.3.3 → webmo-1.4.2}/webmo.egg-info/dependency_links.txt +0 -0
- {webmo-1.3.3 → webmo-1.4.2}/webmo.egg-info/requires.txt +0 -0
- {webmo-1.3.3 → webmo-1.4.2}/webmo.egg-info/top_level.txt +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: webmo
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.2
|
|
4
4
|
Summary: A Python-based interface to WebMO
|
|
5
5
|
Home-page: https://github.com/jrschmidt2/webmo-python
|
|
6
|
-
Download-URL: https://github.com/jrschmidt2/webmo-python/archive/refs/tags/1.
|
|
6
|
+
Download-URL: https://github.com/jrschmidt2/webmo-python/archive/refs/tags/1.4.2.tar.gz
|
|
7
7
|
Author: J.R. Schmidt
|
|
8
8
|
Author-email: schmidt@webmo.net
|
|
9
9
|
License: MIT
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
from .webmo_rest import WebMOREST
|
|
2
|
-
__version__ = "1.
|
|
2
|
+
__version__ = "1.4.2"
|
|
@@ -50,6 +50,8 @@ class JupyterGUI(_WebMOGUIBase):
|
|
|
50
50
|
#fail silently, since this should never happen in Jupyter
|
|
51
51
|
pass #print('ipywidgets not found; disabling support for JupyterGUI')
|
|
52
52
|
|
|
53
|
+
import time
|
|
54
|
+
|
|
53
55
|
def __init__(self, template, query_vars, additional_vars=None):
|
|
54
56
|
"""Constructor for JupyterGUI
|
|
55
57
|
|
|
@@ -66,6 +68,7 @@ class JupyterGUI(_WebMOGUIBase):
|
|
|
66
68
|
|
|
67
69
|
_WebMOGUIBase.__init__(self, template, query_vars, additional_vars)
|
|
68
70
|
self._widgets = []
|
|
71
|
+
self._display_time = -1
|
|
69
72
|
|
|
70
73
|
for var in query_vars:
|
|
71
74
|
if template['variables'][var]['type'] == 'checkbox':
|
|
@@ -93,11 +96,20 @@ class JupyterGUI(_WebMOGUIBase):
|
|
|
93
96
|
|
|
94
97
|
def display(self):
|
|
95
98
|
|
|
99
|
+
self._display_time = self.time.time()
|
|
100
|
+
|
|
96
101
|
for widget in self._widgets:
|
|
97
102
|
display(widget)
|
|
98
103
|
|
|
99
104
|
def get_variables(self):
|
|
100
105
|
|
|
106
|
+
MIN_INPUT_TIME = 1.0
|
|
107
|
+
# sanity check to make sure user has had time to input something
|
|
108
|
+
# fail this call during re-execution of entire notebook at once
|
|
109
|
+
elapsed_time = self.time.time() - self._display_time
|
|
110
|
+
if self._display_time == -1 or elapsed_time < MIN_INPUT_TIME:
|
|
111
|
+
raise RuntimeError('Must provide JupyterGUI input before calling get_variables')
|
|
112
|
+
|
|
101
113
|
# add in additional user-specified variables
|
|
102
114
|
if (self._additional_vars != None):
|
|
103
115
|
variables = {**self._additional_vars}
|
|
@@ -330,8 +330,10 @@ def voigt_line(center, intensity, width=10, q=0.5, start=0, stop=4000, step=1):
|
|
|
330
330
|
Returns:
|
|
331
331
|
(x,y): a tuple of the x and y numpy arrays of the specified line
|
|
332
332
|
"""
|
|
333
|
-
if (
|
|
334
|
-
|
|
333
|
+
if (q <= 0):
|
|
334
|
+
return(gauss_line(center, intensity, width, start, stop, step))
|
|
335
|
+
elif (q >= 1):
|
|
336
|
+
return(lorentz_line(center,intensity,width,start,stop,step))
|
|
335
337
|
|
|
336
338
|
x = np.arange(start=start, stop=stop, step=step)
|
|
337
339
|
vfunc = np.vectorize(_arb_voigt(center, intensity, q, width))
|
|
@@ -345,7 +347,7 @@ def _arb_gaussian(center, intensity, width=10):
|
|
|
345
347
|
from math import sqrt, pi, exp, log
|
|
346
348
|
|
|
347
349
|
sigma = (width / (2 * sqrt(2 * log(2))))
|
|
348
|
-
l = lambda x: intensity * (1/sigma*sqrt(2*pi)) * exp(-((x-center)**2/(2*sigma**2)))
|
|
350
|
+
l = lambda x: intensity * (1/(sigma*sqrt(2*pi))) * exp(-((x-center)**2/(2*sigma**2)))
|
|
349
351
|
|
|
350
352
|
return l
|
|
351
353
|
|
|
@@ -403,7 +405,7 @@ def lorentz_line(center, intensity, width=10, start=0, stop=4000, step=1):
|
|
|
403
405
|
vfunc = np.vectorize(_arb_lorentz(center, intensity, width))
|
|
404
406
|
return((x,vfunc(x)))
|
|
405
407
|
|
|
406
|
-
def construct_spectrum(points, intensities, lineshape="gauss", width=10, start=0, stop=4000, step=1):
|
|
408
|
+
def construct_spectrum(points, intensities, lineshape="gauss", frac_loren=0.5, width=10, start=0, stop=4000, step=1):
|
|
407
409
|
"""Construct an entire spectrum plot of data
|
|
408
410
|
|
|
409
411
|
This function returns a pair of numpy arrays that make a spectrum; an x axis
|
|
@@ -415,6 +417,7 @@ def construct_spectrum(points, intensities, lineshape="gauss", width=10, start=0
|
|
|
415
417
|
intensities([float]): a list of corresponding peak intensities - the order must
|
|
416
418
|
match `points`
|
|
417
419
|
lineshape(string,optional): the desired lineshape. The options are "gauss", "lorentz", and "voigt"
|
|
420
|
+
frac_loren(float,optional): the fraction lorentzian of the voigt lineshape, if specified
|
|
418
421
|
width(float,optional): the full width half max of each peak
|
|
419
422
|
start(float,optional): the starting point of the returned array
|
|
420
423
|
stop(float,optional): the ending point of the returned array
|
|
@@ -428,10 +431,10 @@ def construct_spectrum(points, intensities, lineshape="gauss", width=10, start=0
|
|
|
428
431
|
linefuncs = {
|
|
429
432
|
"gauss": gauss_line,
|
|
430
433
|
"lorentz": lorentz_line,
|
|
431
|
-
"voigt": voigt_line
|
|
434
|
+
"voigt": lambda x, y, **kwargs: voigt_line(x,y,q=frac_loren, **kwargs)
|
|
432
435
|
}
|
|
433
436
|
if (lineshape not in linefuncs.keys()):
|
|
434
|
-
|
|
437
|
+
raise AssertionError("invalid lineshape specified")
|
|
435
438
|
else:
|
|
436
439
|
linefunc = linefuncs[lineshape]
|
|
437
440
|
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
def xyz_from_name(name):
|
|
4
|
+
"""Obtains an XYZ-formatted geometry for the molecule name via PubChem lookup.
|
|
5
|
+
|
|
6
|
+
Arguments:
|
|
7
|
+
name(str): The name of the molecule.
|
|
8
|
+
|
|
9
|
+
Returns:
|
|
10
|
+
A string containing the molecule's XYZ-formatted geometry.
|
|
11
|
+
"""
|
|
12
|
+
import pubchempy as pcp
|
|
13
|
+
|
|
14
|
+
results = pcp.get_compounds(name, 'name', record_type='3d')
|
|
15
|
+
if (len(results) == 0):
|
|
16
|
+
raise ValueError("Specified molecule could not be found in PubChem")
|
|
17
|
+
|
|
18
|
+
record = results[0]
|
|
19
|
+
geom = ""
|
|
20
|
+
for atom in record.atoms:
|
|
21
|
+
element = atom.element
|
|
22
|
+
x = float(atom.x)
|
|
23
|
+
y = float(atom.y)
|
|
24
|
+
z = float(atom.z)
|
|
25
|
+
geom += f"{element}\t{x:f}\t{y:f}\t{z:f}\n"
|
|
26
|
+
|
|
27
|
+
return geom
|
|
28
|
+
|
|
29
|
+
def get_energy(results, include_units=False):
|
|
30
|
+
"""Returns the molecular energy from the job results. This should correspond to the ground state energy
|
|
31
|
+
at molecule at the requested level of theory.
|
|
32
|
+
|
|
33
|
+
Requires WebMO 25 or higher.
|
|
34
|
+
|
|
35
|
+
Arguments:
|
|
36
|
+
dict(results): A dictionary of job results, obtained from get_job_results.
|
|
37
|
+
bool(include_units): Whether to include the units with the returned energy (e.g. 1.5 vs. "1.5 Hartree")
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The molecular energy.
|
|
41
|
+
"""
|
|
42
|
+
properties = results['properties']
|
|
43
|
+
|
|
44
|
+
if not 'method_energy_name' in properties.keys():
|
|
45
|
+
raise RuntimeError('Cannot locate "method_energy_name" in results')
|
|
46
|
+
method_energy_name = properties['method_energy_name'].lower().replace(' ', '_') + '_energy'
|
|
47
|
+
|
|
48
|
+
found = False
|
|
49
|
+
#also check related key names, since Gaussian prepends some things occasionally
|
|
50
|
+
for key in [method_energy_name, 'r' + method_energy_name, 'u' + method_energy_name, 'ro' + method_energy_name]:
|
|
51
|
+
if key in properties:
|
|
52
|
+
energy = properties[key]['value']
|
|
53
|
+
units = properties[key]['units']
|
|
54
|
+
found = True
|
|
55
|
+
|
|
56
|
+
if not found:
|
|
57
|
+
raise RuntimeError('Could not locate "' + method_energy_name + '" in results')
|
|
58
|
+
|
|
59
|
+
if include_units:
|
|
60
|
+
energy = f"{energy} {units}"
|
|
61
|
+
|
|
62
|
+
return energy
|
|
63
|
+
|
|
64
|
+
def get_energies(results, include_units=False):
|
|
65
|
+
"""Returns a dictionary of available energies from the job results.
|
|
66
|
+
|
|
67
|
+
Arguments:
|
|
68
|
+
dict(results): A dictionary of job results, obtained from get_job_results.
|
|
69
|
+
bool(include_units): Whether to include the units with the returned energy (e.g. 1.5 vs. "1.5 Hartree")
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
A dictionary of available energies.
|
|
73
|
+
"""
|
|
74
|
+
properties = results['properties']
|
|
75
|
+
energies = {}
|
|
76
|
+
|
|
77
|
+
for key in properties.keys():
|
|
78
|
+
index = key.find('_energy')
|
|
79
|
+
|
|
80
|
+
if key.endswith('_energy'):
|
|
81
|
+
index = key.find('_energy')
|
|
82
|
+
energy_type = key[:index]
|
|
83
|
+
|
|
84
|
+
if include_units:
|
|
85
|
+
energies[energy_type] = f"{properties[key]['value']} {properties[key]['units']}"
|
|
86
|
+
else:
|
|
87
|
+
energies[energy_type] = properties[key]['value']
|
|
88
|
+
|
|
89
|
+
return energies
|
|
90
|
+
|
|
91
|
+
def get_geometry(results):
|
|
92
|
+
"""Returns the XYZ-formatted final geometry from the job results.
|
|
93
|
+
|
|
94
|
+
Arguments:
|
|
95
|
+
dict(results): A dictionary of job results, obtained from get_job_results.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
The XYZ-formatted final geometry as a string.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
geom = ""
|
|
103
|
+
index = 0
|
|
104
|
+
for element in results['symbols']:
|
|
105
|
+
|
|
106
|
+
x = results['geometry'][index]
|
|
107
|
+
y = results['geometry'][index + 1]
|
|
108
|
+
z = results['geometry'][index + 2]
|
|
109
|
+
|
|
110
|
+
geom += f"{element}\t{x:f}\t{y:f}\t{z:f}\n"
|
|
111
|
+
index += 3
|
|
112
|
+
|
|
113
|
+
return geom
|
|
114
|
+
|
|
115
|
+
def get_stoichiometry(results):
|
|
116
|
+
"""Returns the stoichiometry from the job results.
|
|
117
|
+
|
|
118
|
+
Arguments:
|
|
119
|
+
dict(results): A dictionary of job results, obtained from get_job_results.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
The stoichiometry as a string.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
properties = results['properties']
|
|
126
|
+
return properties['stoichiometry']
|
|
127
|
+
|
|
128
|
+
def get_dipole_moment(results):
|
|
129
|
+
"""Returns the dipole moment from the job results.
|
|
130
|
+
|
|
131
|
+
Arguments:
|
|
132
|
+
dict(results): A dictionary of job results, obtained from get_job_results.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
The magnitude of the dipole moment.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
from math import sqrt
|
|
139
|
+
|
|
140
|
+
properties = results['properties']
|
|
141
|
+
dipole = properties['dipole_moment']
|
|
142
|
+
mag = sqrt(dipole[0]**2 + dipole[1]**2 + dipole[2]**2)
|
|
143
|
+
|
|
144
|
+
return mag
|
|
145
|
+
|
|
146
|
+
def get_property(results, property_name):
|
|
147
|
+
"""Returns an arbitrary calculated property from the job results.
|
|
148
|
+
|
|
149
|
+
Arguments:
|
|
150
|
+
dict(results): A dictionary of job results, obtained from get_job_results.
|
|
151
|
+
str(property_name): The name of the desired property
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
The value of the calculated property (scalar or dictionary).
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
properties = results['properties']
|
|
158
|
+
return properties[property_name]
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def get_bond_length(results, index1, index2):
|
|
162
|
+
"""Returns the specified bond length between two atoms from the job results OR an xyz-formatted string.
|
|
163
|
+
|
|
164
|
+
Arguments:
|
|
165
|
+
dict(results): A dictionary of job results obtained from get_job_results OR an xyz-formatted string.
|
|
166
|
+
index1(int): The one-based index of the first atom of the bonded pair
|
|
167
|
+
index2(int): The one-based index of the second atom of the bonded pair
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
The calculated bond length.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
if not isinstance(results, dict):
|
|
174
|
+
geom = _xyz_to_array(results)
|
|
175
|
+
else:
|
|
176
|
+
geom = results['geometry']
|
|
177
|
+
|
|
178
|
+
#convert to 0 index
|
|
179
|
+
index1 -= 1
|
|
180
|
+
index2 -= 1
|
|
181
|
+
|
|
182
|
+
atom1 = np.array(geom[index1*3:index1*3 + 3])
|
|
183
|
+
atom2 = np.array(geom[index2*3:index2*3 + 3])
|
|
184
|
+
|
|
185
|
+
return np.linalg.norm(atom1 - atom2)
|
|
186
|
+
|
|
187
|
+
def get_bond_angle(results, index1, index2, index3):
|
|
188
|
+
"""Returns the specified bond angle between three atoms from the job results OR an xyz-formatted string.
|
|
189
|
+
|
|
190
|
+
Arguments:
|
|
191
|
+
dict(results): A dictionary of job results obtained from get_job_results OR an xyz-formatted string.
|
|
192
|
+
index1(int): The one-based index of the first atom
|
|
193
|
+
index2(int): The one-based index of the second atom
|
|
194
|
+
index3(int): The one-based index of the third atom
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
The calculated bond angle.
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
if not isinstance(results, dict):
|
|
201
|
+
geom = _xyz_to_array(results)
|
|
202
|
+
else:
|
|
203
|
+
geom = results['geometry']
|
|
204
|
+
|
|
205
|
+
#convert to 0 index
|
|
206
|
+
index1 -= 1
|
|
207
|
+
index2 -= 1
|
|
208
|
+
index3 -= 1
|
|
209
|
+
|
|
210
|
+
atom1 = np.array(geom[index1*3:index1*3 + 3])
|
|
211
|
+
atom2 = np.array(geom[index2*3:index2*3 + 3])
|
|
212
|
+
atom3 = np.array(geom[index3*3:index3*3 + 3])
|
|
213
|
+
|
|
214
|
+
vec1 = atom1 - atom2
|
|
215
|
+
vec2 = atom3 - atom2
|
|
216
|
+
|
|
217
|
+
vec1 /= np.linalg.norm(vec1)
|
|
218
|
+
vec2 /= np.linalg.norm(vec2)
|
|
219
|
+
|
|
220
|
+
return np.arccos(np.dot(vec1,vec2))*180./np.pi
|
|
221
|
+
|
|
222
|
+
def get_dihedral_angle(results, index1, index2, index3, index4):
|
|
223
|
+
"""Returns the specified dihedral angle between four atoms from the job results OR an xyz-formatted string.
|
|
224
|
+
|
|
225
|
+
Arguments:
|
|
226
|
+
dict(results): A dictionary of job results obtained from get_job_results OR an xyz-formatted string.
|
|
227
|
+
index1(int): The one-based index of the first atom
|
|
228
|
+
index2(int): The one-based index of the second atom
|
|
229
|
+
index3(int): The one-based index of the third atom
|
|
230
|
+
index4(int): The one-based index of the fourth atom
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
The calculated dihedral angle.
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
if not isinstance(results, dict):
|
|
237
|
+
geom = _xyz_to_array(results)
|
|
238
|
+
else:
|
|
239
|
+
geom = results['geometry']
|
|
240
|
+
|
|
241
|
+
#convert to 0 index
|
|
242
|
+
index1 -= 1
|
|
243
|
+
index2 -= 1
|
|
244
|
+
index3 -= 1
|
|
245
|
+
index4 -= 1
|
|
246
|
+
|
|
247
|
+
atom1 = np.array(geom[index1*3:index1*3 + 3])
|
|
248
|
+
atom2 = np.array(geom[index2*3:index2*3 + 3])
|
|
249
|
+
atom3 = np.array(geom[index3*3:index3*3 + 3])
|
|
250
|
+
atom4 = np.array(geom[index4*3:index4*3 + 3])
|
|
251
|
+
|
|
252
|
+
b1 = atom1 - atom2
|
|
253
|
+
b2 = atom2 - atom3
|
|
254
|
+
b3 = atom3 - atom4
|
|
255
|
+
|
|
256
|
+
b1 /= np.linalg.norm(b1)
|
|
257
|
+
b2 /= np.linalg.norm(b2)
|
|
258
|
+
b3 /= np.linalg.norm(b3)
|
|
259
|
+
|
|
260
|
+
n1 = np.cross(b1, b2)
|
|
261
|
+
n2 = np.cross(b2, b3)
|
|
262
|
+
m = np.cross(n1, b2)
|
|
263
|
+
|
|
264
|
+
x = np.dot(n1, n2)
|
|
265
|
+
y = np.dot(m, n2)
|
|
266
|
+
|
|
267
|
+
return np.arctan2(y, x)*180./np.pi
|
|
268
|
+
|
|
269
|
+
def _xyz_to_array(xyz):
|
|
270
|
+
xyz = xyz.strip()
|
|
271
|
+
|
|
272
|
+
try:
|
|
273
|
+
#throw exception if NOT a number, indicating that our XYZ file has no header
|
|
274
|
+
tokens = xyz.split()
|
|
275
|
+
int(tokens[0])
|
|
276
|
+
#this XYZ formatted string is proper, containing a header that must be removed
|
|
277
|
+
xyz = xyz.split("\n",2)[2]
|
|
278
|
+
except ValueError:
|
|
279
|
+
pass
|
|
280
|
+
|
|
281
|
+
#process the actual geometry of the XYZ file, converting into an array
|
|
282
|
+
geom = xyz.split()
|
|
283
|
+
#remove the element names, leaving only an array of positions
|
|
284
|
+
del geom[0::4]
|
|
285
|
+
|
|
286
|
+
#convert to an array of floats and return
|
|
287
|
+
return np.array(geom,dtype=float)
|
|
@@ -621,22 +621,10 @@ class WebMOREST:
|
|
|
621
621
|
#
|
|
622
622
|
# Helper functions
|
|
623
623
|
#
|
|
624
|
-
def wait_for_job(self,
|
|
625
|
-
"""Waits for completion of the specified WebMO
|
|
624
|
+
def wait_for_job(self, *job_numbers, poll_frequency=5):
|
|
625
|
+
"""Waits for completion of the specified WebMO jobs(s)
|
|
626
626
|
|
|
627
|
-
This call blocks until the specified WebMO job
|
|
628
|
-
|
|
629
|
-
Arguments:
|
|
630
|
-
job_number(int): The job number to wait for
|
|
631
|
-
poll_frequency(int, optional): The frequency at which to check the job status (default is 5s)
|
|
632
|
-
"""
|
|
633
|
-
|
|
634
|
-
self.wait_for_jobs([job_number], poll_frequency)
|
|
635
|
-
|
|
636
|
-
def wait_for_jobs(self, job_numbers, poll_frequency=5):
|
|
637
|
-
"""Waits for completion of the specified list of WebMO jobs
|
|
638
|
-
|
|
639
|
-
This call blocks until the specified WebMO jobs have all finished executing (successfully or not)
|
|
627
|
+
This call blocks until the specified WebMO job(s) have all finished executing (successfully or not)
|
|
640
628
|
|
|
641
629
|
Arguments:
|
|
642
630
|
job_numbers(list): A list of job numbers which will be waited upon
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: webmo
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.2
|
|
4
4
|
Summary: A Python-based interface to WebMO
|
|
5
5
|
Home-page: https://github.com/jrschmidt2/webmo-python
|
|
6
|
-
Download-URL: https://github.com/jrschmidt2/webmo-python/archive/refs/tags/1.
|
|
6
|
+
Download-URL: https://github.com/jrschmidt2/webmo-python/archive/refs/tags/1.4.2.tar.gz
|
|
7
7
|
Author: J.R. Schmidt
|
|
8
8
|
Author-email: schmidt@webmo.net
|
|
9
9
|
License: MIT
|
webmo-1.3.3/webmo/util.py
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
def xyz_from_name(name):
|
|
2
|
-
"""Obtains an XYZ-formatted geometry for the molecule name via PubChem lookup.
|
|
3
|
-
|
|
4
|
-
Arguments:
|
|
5
|
-
name(str): The name of the molecule.
|
|
6
|
-
|
|
7
|
-
Returns:
|
|
8
|
-
A string containing the molecule's XYZ-formatted geometry.
|
|
9
|
-
"""
|
|
10
|
-
import pubchempy as pcp
|
|
11
|
-
|
|
12
|
-
results = pcp.get_compounds(name, 'name', record_type='3d')
|
|
13
|
-
if (len(results) == 0):
|
|
14
|
-
raise ValueError("Specified molecule could not be found in PubChem")
|
|
15
|
-
|
|
16
|
-
record = results[0]
|
|
17
|
-
geom = ""
|
|
18
|
-
for atom in record.atoms:
|
|
19
|
-
element = atom.element
|
|
20
|
-
x = float(atom.x)
|
|
21
|
-
y = float(atom.y)
|
|
22
|
-
z = float(atom.z)
|
|
23
|
-
geom += f"{element}\t{x:f}\t{y:f}\t{z:f}\n"
|
|
24
|
-
|
|
25
|
-
return geom
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|