rowan-python 3.0.11__py3-none-any.whl → 3.0.12__py3-none-any.whl
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.
- {rowan_python-3.0.11.dist-info → rowan_python-3.0.12.dist-info}/METADATA +1 -1
- {rowan_python-3.0.11.dist-info → rowan_python-3.0.12.dist-info}/RECORD +4 -6
- rowan/rowan_rdkit/__init__.py +0 -29
- rowan/rowan_rdkit/chem_utils.py +0 -1019
- {rowan_python-3.0.11.dist-info → rowan_python-3.0.12.dist-info}/WHEEL +0 -0
- {rowan_python-3.0.11.dist-info → rowan_python-3.0.12.dist-info}/licenses/LICENSE +0 -0
|
@@ -11,8 +11,6 @@ rowan/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
11
11
|
rowan/types.py,sha256=rCAnUlCsemyBK9Bbus0pL-THoqNqJIQHaMoDferIfFU,471
|
|
12
12
|
rowan/user.py,sha256=Tnwz1-u_92ACt1xATQegtMj3FcosFsAG4m-4YuAkiyg,5955
|
|
13
13
|
rowan/utils.py,sha256=c1s6Ze-OqLtfvrD23OV60otskejmj-CD88nNf8_nFcw,3636
|
|
14
|
-
rowan/rowan_rdkit/__init__.py,sha256=EATX2VRzywzKxqkpCUMTf7RNQLkWsfi5VcCNDW6EIiw,503
|
|
15
|
-
rowan/rowan_rdkit/chem_utils.py,sha256=ZWdLziT59Qr5JzjvV789CAyRq0m5JIawsOP4RxUbQQA,35529
|
|
16
14
|
rowan/workflows/__init__.py,sha256=CM3GKDTafp6vl79dWqSOvkVfwH1Ty8zuc8yzi65ABxM,4438
|
|
17
15
|
rowan/workflows/admet.py,sha256=0_wIwXXLfHF-3kgGx_1EM1ljjaYHLeEijJ-GbMYxpL8,2904
|
|
18
16
|
rowan/workflows/analogue_docking.py,sha256=LJpbbaug0tZ9Cg-m0b7EgGH5hJ5894fHOC16Wefx7mE,9206
|
|
@@ -51,7 +49,7 @@ rowan/workflows/solvent_dependent_conformers.py,sha256=ovvnhCE4xlkpdhccLHEq7oBJR
|
|
|
51
49
|
rowan/workflows/spin_states.py,sha256=c0y2cwO9NE8DmxmQ9ZouA5QoBhxgZiTYFIqhC-geVAo,7382
|
|
52
50
|
rowan/workflows/strain.py,sha256=N-CoOT-hjYzjYTMYR9Uzoy4EhnrLQEOeDNSNphsUIXQ,6380
|
|
53
51
|
rowan/workflows/tautomer_search.py,sha256=GB96BjvVsJDgLCTH4S4nkAlBoCvKud_18Y3PTY9Q528,5779
|
|
54
|
-
rowan_python-3.0.
|
|
55
|
-
rowan_python-3.0.
|
|
56
|
-
rowan_python-3.0.
|
|
57
|
-
rowan_python-3.0.
|
|
52
|
+
rowan_python-3.0.12.dist-info/METADATA,sha256=0pcHHITAsvBIWYCiohdeX3Tc11wdjBMa81rTkyuxI8M,1601
|
|
53
|
+
rowan_python-3.0.12.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
54
|
+
rowan_python-3.0.12.dist-info/licenses/LICENSE,sha256=i05z7xEhyrg6f8j0lR3XYjShnF-MJGFQ-DnpsZ8yiVI,1084
|
|
55
|
+
rowan_python-3.0.12.dist-info/RECORD,,
|
rowan/rowan_rdkit/__init__.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from .chem_utils import (
|
|
2
|
-
batch_charges,
|
|
3
|
-
batch_conformers,
|
|
4
|
-
batch_energy,
|
|
5
|
-
batch_optimize,
|
|
6
|
-
batch_pka,
|
|
7
|
-
batch_tautomers,
|
|
8
|
-
run_charges,
|
|
9
|
-
run_conformers,
|
|
10
|
-
run_energy,
|
|
11
|
-
run_optimize,
|
|
12
|
-
run_pka,
|
|
13
|
-
run_tautomers,
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
__all__ = [
|
|
17
|
-
"batch_charges",
|
|
18
|
-
"batch_conformers",
|
|
19
|
-
"batch_energy",
|
|
20
|
-
"batch_optimize",
|
|
21
|
-
"batch_pka",
|
|
22
|
-
"batch_tautomers",
|
|
23
|
-
"run_charges",
|
|
24
|
-
"run_conformers",
|
|
25
|
-
"run_energy",
|
|
26
|
-
"run_optimize",
|
|
27
|
-
"run_pka",
|
|
28
|
-
"run_tautomers",
|
|
29
|
-
]
|
rowan/rowan_rdkit/chem_utils.py
DELETED
|
@@ -1,1019 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import copy
|
|
3
|
-
import logging
|
|
4
|
-
import time
|
|
5
|
-
from typing import Iterable, Literal, TypedDict
|
|
6
|
-
|
|
7
|
-
import numpy as np
|
|
8
|
-
import stjames
|
|
9
|
-
from rdkit import Chem
|
|
10
|
-
from rdkit.Chem import AllChem
|
|
11
|
-
|
|
12
|
-
import rowan
|
|
13
|
-
from rowan.types import RdkitMol
|
|
14
|
-
from rowan.utils import ATOMIC_NUMBER_TO_ATOMIC_SYMBOL, get_api_key
|
|
15
|
-
|
|
16
|
-
pKaMode = Literal["reckless", "rapid", "careful"]
|
|
17
|
-
TautomerMode = Literal["reckless", "rapid", "careful"]
|
|
18
|
-
ConformerMode = Literal["reckless", "rapid"]
|
|
19
|
-
FAST_METHODS: list[stjames.Method] = [
|
|
20
|
-
*stjames.method.XTB_METHODS,
|
|
21
|
-
*stjames.method.NNP_METHODS,
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class ConversionError(ValueError):
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class NoConformersError(Exception):
|
|
30
|
-
pass
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class MethodTooSlowError(Exception):
|
|
34
|
-
pass
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class ChargesResult(TypedDict):
|
|
38
|
-
conformer_index: int
|
|
39
|
-
charges: list[float]
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
ChargesResults = list[ChargesResult]
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class ConformerResult(TypedDict):
|
|
46
|
-
molecule: RdkitMol
|
|
47
|
-
energies: list[float]
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
class PKaResult(TypedDict):
|
|
51
|
-
element: str
|
|
52
|
-
index: int
|
|
53
|
-
pKa: float
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
class PKaResults(TypedDict):
|
|
57
|
-
acidic_pkas: list[PKaResult]
|
|
58
|
-
basic_pkas: list[PKaResult]
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class TautomerResult(TypedDict):
|
|
62
|
-
molecule: RdkitMol
|
|
63
|
-
predicted_relative_energy: float
|
|
64
|
-
weight: float
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
TautomerResults = list[TautomerResult]
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class ConformerEnergyResult(TypedDict):
|
|
71
|
-
conformer_index: int
|
|
72
|
-
energy: float
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
class OptimizeResult(TypedDict):
|
|
76
|
-
molecule: RdkitMol
|
|
77
|
-
energies: list[float]
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def apply_nest_asyncio() -> None:
|
|
81
|
-
try:
|
|
82
|
-
asyncio.get_running_loop()
|
|
83
|
-
except RuntimeError:
|
|
84
|
-
return
|
|
85
|
-
try:
|
|
86
|
-
import nest_asyncio # type: ignore [import-untyped]
|
|
87
|
-
|
|
88
|
-
nest_asyncio.apply()
|
|
89
|
-
except ImportError:
|
|
90
|
-
pass
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
# actually apply it
|
|
94
|
-
apply_nest_asyncio()
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def _get_rdkit_mol_from_uuid(calculation_uuid: str) -> RdkitMol:
|
|
98
|
-
calc = rowan.retrieve_calculation(calculation_uuid)
|
|
99
|
-
if calc.molecule is None:
|
|
100
|
-
raise ValueError(f"Calculation {calculation_uuid} has no molecules")
|
|
101
|
-
return Chem.MolFromXYZBlock(calc.molecule.to_xyz()) # type: ignore[attr-defined]
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def _embed_rdkit_mol(rdkm: RdkitMol) -> RdkitMol:
|
|
105
|
-
try:
|
|
106
|
-
AllChem.SanitizeMol(rdkm) # type: ignore[attr-defined]
|
|
107
|
-
except Exception as e:
|
|
108
|
-
raise ValueError("Molecule could not be generated -- invalid chemistry!") from e
|
|
109
|
-
|
|
110
|
-
rdkm = AllChem.AddHs(rdkm) # type: ignore[attr-defined]
|
|
111
|
-
try:
|
|
112
|
-
assert AllChem.EmbedMolecule(rdkm, maxAttempts=200) >= 0 # type: ignore[attr-defined]
|
|
113
|
-
except AssertionError as e:
|
|
114
|
-
status1 = AllChem.EmbedMolecule(rdkm, maxAttempts=200, useRandomCoords=True) # type: ignore[attr-defined]
|
|
115
|
-
if status1 < 0:
|
|
116
|
-
raise ValueError("Cannot embed molecule!") from e
|
|
117
|
-
try:
|
|
118
|
-
assert AllChem.MMFFOptimizeMolecule(rdkm, maxIters=200) >= 0 # type: ignore[attr-defined, call-arg]
|
|
119
|
-
except AssertionError:
|
|
120
|
-
pass
|
|
121
|
-
|
|
122
|
-
return rdkm
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def _rdkit_to_stjames(rdkm: RdkitMol, cid: int = 0) -> stjames.Molecule:
|
|
126
|
-
return stjames.Molecule.from_rdkit(rdkm, cid=cid)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def run_pka(
|
|
130
|
-
mol: RdkitMol,
|
|
131
|
-
mode: pKaMode = "rapid",
|
|
132
|
-
timeout: int = 600,
|
|
133
|
-
name: str = "pKa API Workflow",
|
|
134
|
-
pka_range: tuple[int, int] = (2, 12),
|
|
135
|
-
deprotonate_elements: list[int] | None = None,
|
|
136
|
-
protonate_elements: list[int] | None = None,
|
|
137
|
-
folder_uuid: str | None = None,
|
|
138
|
-
) -> PKaResults:
|
|
139
|
-
"""
|
|
140
|
-
Calculate the pKa of a Molecule.
|
|
141
|
-
|
|
142
|
-
:param mol: RDKit Molecule
|
|
143
|
-
:param mode: pKa calculation Mode. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
144
|
-
for options.
|
|
145
|
-
:param timeout: time in seconds before the Workflow times out
|
|
146
|
-
:param name: name for the job
|
|
147
|
-
:param pka_range: range of pKa values to calculate
|
|
148
|
-
:param deprotonate_elements: elements to deprotonate
|
|
149
|
-
:param protonate_elements: elements to protonate
|
|
150
|
-
:param folder_uuid: folder UUID
|
|
151
|
-
:returns: dictionary of pKa values indexed by atom
|
|
152
|
-
"""
|
|
153
|
-
protonate_elements = protonate_elements or [7]
|
|
154
|
-
deprotonate_elements = deprotonate_elements or [7, 8, 16]
|
|
155
|
-
|
|
156
|
-
return asyncio.run(
|
|
157
|
-
_single_pka(
|
|
158
|
-
mol,
|
|
159
|
-
mode,
|
|
160
|
-
timeout,
|
|
161
|
-
name,
|
|
162
|
-
pka_range,
|
|
163
|
-
deprotonate_elements,
|
|
164
|
-
protonate_elements,
|
|
165
|
-
folder_uuid,
|
|
166
|
-
)
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
def batch_pka(
|
|
171
|
-
mols: Iterable[RdkitMol],
|
|
172
|
-
mode: pKaMode = "rapid",
|
|
173
|
-
timeout: int = 600,
|
|
174
|
-
name: str = "pKa API Workflow",
|
|
175
|
-
pka_range: tuple[int, int] = (2, 12),
|
|
176
|
-
deprotonate_elements: list[int] | None = None,
|
|
177
|
-
protonate_elements: list[int] | None = None,
|
|
178
|
-
folder_uuid: str | None = None,
|
|
179
|
-
) -> list[PKaResults]:
|
|
180
|
-
"""
|
|
181
|
-
Calculate the pKa of a batch of Molecules.
|
|
182
|
-
|
|
183
|
-
:param mols: list of RDKit Molecules
|
|
184
|
-
:param mode: pKa calculation mode. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
185
|
-
for options.
|
|
186
|
-
:param timeout: time in seconds before the Workflow times out
|
|
187
|
-
:param name: name for the job
|
|
188
|
-
:param pka_range: range of pKa values to calculate
|
|
189
|
-
:param deprotonate_elements: elements to deprotonate
|
|
190
|
-
:param protonate_elements: elements to protonate
|
|
191
|
-
:returns: list of dictionary of pKa values indexed by atom
|
|
192
|
-
"""
|
|
193
|
-
protonate_elements = protonate_elements or [7]
|
|
194
|
-
deprotonate_elements = deprotonate_elements or [7, 8, 16]
|
|
195
|
-
|
|
196
|
-
async def _run():
|
|
197
|
-
tasks = [
|
|
198
|
-
_single_pka(
|
|
199
|
-
mol,
|
|
200
|
-
mode,
|
|
201
|
-
timeout,
|
|
202
|
-
name,
|
|
203
|
-
pka_range,
|
|
204
|
-
deprotonate_elements,
|
|
205
|
-
protonate_elements,
|
|
206
|
-
folder_uuid,
|
|
207
|
-
)
|
|
208
|
-
for mol in mols
|
|
209
|
-
]
|
|
210
|
-
return await asyncio.gather(*tasks)
|
|
211
|
-
|
|
212
|
-
return asyncio.run(_run())
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
async def _single_pka(
|
|
216
|
-
mol: RdkitMol,
|
|
217
|
-
mode: pKaMode = "rapid",
|
|
218
|
-
timeout: int = 600,
|
|
219
|
-
name: str = "pKa API Workflow",
|
|
220
|
-
pka_range: tuple[int, int] = (2, 12),
|
|
221
|
-
deprotonate_elements: list[int] | None = None,
|
|
222
|
-
protonate_elements: list[int] | None = None,
|
|
223
|
-
folder_uuid: str | None = None,
|
|
224
|
-
) -> PKaResults:
|
|
225
|
-
"""
|
|
226
|
-
Calculate the pKa of a Molecule.
|
|
227
|
-
|
|
228
|
-
:param mol: RDKit Molecule
|
|
229
|
-
:param mode: pKa calculation mode. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
230
|
-
for options.
|
|
231
|
-
:param timeout: time in seconds before the Workflow times out
|
|
232
|
-
:param name: name for the job
|
|
233
|
-
:param pka_range: range of pKa values to calculate
|
|
234
|
-
:param deprotonate_elements: elements to deprotonate
|
|
235
|
-
:param protonate_elements: elements to protonate
|
|
236
|
-
:param folder_uuid: folder UUID
|
|
237
|
-
:returns: dictionary of pKa values
|
|
238
|
-
"""
|
|
239
|
-
get_api_key()
|
|
240
|
-
protonate_elements = protonate_elements or [7]
|
|
241
|
-
deprotonate_elements = deprotonate_elements or [7, 8, 16]
|
|
242
|
-
|
|
243
|
-
post = rowan.submit_workflow(
|
|
244
|
-
name=name,
|
|
245
|
-
workflow_type="pka",
|
|
246
|
-
initial_molecule=_rdkit_to_stjames(mol),
|
|
247
|
-
workflow_data={
|
|
248
|
-
"pka_range": pka_range,
|
|
249
|
-
"deprotonate_elements": deprotonate_elements,
|
|
250
|
-
"deprotonate_atoms": [],
|
|
251
|
-
"protonate_elements": protonate_elements,
|
|
252
|
-
"protonate_atoms": [],
|
|
253
|
-
"mode": mode,
|
|
254
|
-
},
|
|
255
|
-
folder_uuid=folder_uuid,
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
start = time.time()
|
|
259
|
-
while not post.is_finished():
|
|
260
|
-
await asyncio.sleep(5)
|
|
261
|
-
if time.time() - start > timeout:
|
|
262
|
-
raise TimeoutError("Workflow timed out")
|
|
263
|
-
|
|
264
|
-
data = rowan.retrieve_workflow(post.uuid).data
|
|
265
|
-
|
|
266
|
-
if not data:
|
|
267
|
-
raise Exception("Could not retrieve workflow data")
|
|
268
|
-
|
|
269
|
-
acidic_pkas: list[PKaResult] = []
|
|
270
|
-
for microstate in data.get("conjugate_bases", []):
|
|
271
|
-
atomic_number = data.get("initial_molecule", {})["atoms"][microstate["atom_index"] - 1][
|
|
272
|
-
"atomic_number"
|
|
273
|
-
]
|
|
274
|
-
acidic_pkas.append(
|
|
275
|
-
{
|
|
276
|
-
"element": ATOMIC_NUMBER_TO_ATOMIC_SYMBOL[str(atomic_number)],
|
|
277
|
-
"index": microstate["atom_index"],
|
|
278
|
-
"pKa": round(microstate["pka"], 2),
|
|
279
|
-
}
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
basic_pkas: list[PKaResult] = []
|
|
283
|
-
for microstate in data.get("conjugate_bases", []):
|
|
284
|
-
atomic_number = data.get("initial_molecule", {})["atoms"][microstate["atom_index"] - 1][
|
|
285
|
-
"atomic_number"
|
|
286
|
-
]
|
|
287
|
-
|
|
288
|
-
basic_pkas.append(
|
|
289
|
-
{
|
|
290
|
-
"element": ATOMIC_NUMBER_TO_ATOMIC_SYMBOL[str(atomic_number)],
|
|
291
|
-
"index": microstate["atom_index"],
|
|
292
|
-
"pKa": round(microstate["pka"], 2),
|
|
293
|
-
}
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
return {"acidic_pkas": acidic_pkas, "basic_pkas": basic_pkas}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
def run_tautomers(
|
|
300
|
-
mol: RdkitMol,
|
|
301
|
-
mode: TautomerMode = "reckless",
|
|
302
|
-
timeout: int = 600,
|
|
303
|
-
name: str = "Tautomers API Workflow",
|
|
304
|
-
folder_uuid: str | None = None,
|
|
305
|
-
) -> TautomerResults:
|
|
306
|
-
"""
|
|
307
|
-
Generate possible tautomers of a Molecule.
|
|
308
|
-
|
|
309
|
-
:param mol: RDKit Molecule
|
|
310
|
-
:param mode: Tautomer mode. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
311
|
-
for options.
|
|
312
|
-
:param timeout: time in seconds before the Workflow times out
|
|
313
|
-
:param name: name for the job
|
|
314
|
-
:param folder_uuid: folder UUID
|
|
315
|
-
:returns: list of dictionaries containing RDKit Molecule, relative energies, and weights
|
|
316
|
-
"""
|
|
317
|
-
return asyncio.run(_single_tautomers(mol, mode, timeout, name, folder_uuid))
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
def batch_tautomers(
|
|
321
|
-
mols: Iterable[RdkitMol],
|
|
322
|
-
mode: TautomerMode = "reckless",
|
|
323
|
-
timeout: int = 600,
|
|
324
|
-
name: str = "Tautomers API Workflow",
|
|
325
|
-
folder_uuid: str | None = None,
|
|
326
|
-
) -> list[TautomerResults]:
|
|
327
|
-
"""
|
|
328
|
-
Generate possible tautomers of a Molecule.
|
|
329
|
-
|
|
330
|
-
:param mols: RDKit Molecule
|
|
331
|
-
:param mode: Tautomer mode. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
332
|
-
for options.
|
|
333
|
-
:param timeout: time in seconds before the Workflow times out
|
|
334
|
-
:param name: name for the job
|
|
335
|
-
:param folder_uuid: folder UUID
|
|
336
|
-
:returns: List of lists of dicts containing RDKit Molecule, relative energies, and weights.
|
|
337
|
-
"""
|
|
338
|
-
|
|
339
|
-
async def _run():
|
|
340
|
-
tasks = [_single_tautomers(mol, mode, timeout, name, folder_uuid) for mol in mols]
|
|
341
|
-
return await asyncio.gather(*tasks)
|
|
342
|
-
|
|
343
|
-
return asyncio.run(_run())
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
async def _single_tautomers(
|
|
347
|
-
mol: RdkitMol,
|
|
348
|
-
mode: TautomerMode = "reckless",
|
|
349
|
-
timeout: int = 600,
|
|
350
|
-
name: str = "Tautomers API Workflow",
|
|
351
|
-
folder_uuid: str | None = None,
|
|
352
|
-
) -> TautomerResults:
|
|
353
|
-
"""
|
|
354
|
-
Generate possible tautomers of a Molecule.
|
|
355
|
-
|
|
356
|
-
:param mol: RDKit Molecule
|
|
357
|
-
:param mode: Tautomer mode
|
|
358
|
-
:param timeout: time in seconds before the Workflow times out
|
|
359
|
-
:param name: name for the job
|
|
360
|
-
:param folder_uuid: folder UUID
|
|
361
|
-
:returns: dictionaries containing RDKit Molecule, relative energy, and weight
|
|
362
|
-
"""
|
|
363
|
-
get_api_key()
|
|
364
|
-
|
|
365
|
-
post = rowan.submit_workflow(
|
|
366
|
-
name=name,
|
|
367
|
-
workflow_type="tautomers",
|
|
368
|
-
initial_molecule=_rdkit_to_stjames(mol),
|
|
369
|
-
workflow_data={"mode": mode},
|
|
370
|
-
folder_uuid=folder_uuid,
|
|
371
|
-
)
|
|
372
|
-
|
|
373
|
-
start = time.time()
|
|
374
|
-
while not post.is_finished():
|
|
375
|
-
await asyncio.sleep(5)
|
|
376
|
-
if time.time() - start > timeout:
|
|
377
|
-
raise TimeoutError("Workflow timed out")
|
|
378
|
-
|
|
379
|
-
data = rowan.retrieve_workflow(post.uuid).data
|
|
380
|
-
|
|
381
|
-
if not data:
|
|
382
|
-
raise Exception("Could not retrieve workflow data")
|
|
383
|
-
|
|
384
|
-
return [
|
|
385
|
-
{
|
|
386
|
-
"molecule": _get_rdkit_mol_from_uuid(tautomer["structures"][0]["uuid"]),
|
|
387
|
-
"predicted_relative_energy": round(tautomer["predicted_relative_energy"], 2),
|
|
388
|
-
"weight": round(tautomer["weight"], 5),
|
|
389
|
-
}
|
|
390
|
-
for tautomer in data.get("tautomers", [])
|
|
391
|
-
]
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
def run_energy(
|
|
395
|
-
mol: RdkitMol,
|
|
396
|
-
method: str = "aimnet2_wb97md3",
|
|
397
|
-
engine: str = "aimnet2",
|
|
398
|
-
mode: str = "auto",
|
|
399
|
-
timeout: int = 600,
|
|
400
|
-
name: str = "Energy API Workflow",
|
|
401
|
-
folder_uuid: str | None = None,
|
|
402
|
-
) -> list[ConformerEnergyResult]:
|
|
403
|
-
"""
|
|
404
|
-
Computes the energy for the given molecule.
|
|
405
|
-
|
|
406
|
-
:param mol: RDKit Molecule
|
|
407
|
-
:param method: Method to use for the calculation.
|
|
408
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
409
|
-
:param engine: Engine to run the energy. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
|
|
410
|
-
:param mode: Mode to run the energy. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
411
|
-
for options.
|
|
412
|
-
:param timeout: time in seconds before the Workflow times out
|
|
413
|
-
:param name: name for the job
|
|
414
|
-
:param folder_uuid: folder UUID
|
|
415
|
-
:raises MethodTooSlowError: if the method is invalid
|
|
416
|
-
:returns: dictionary with the energy in Hartree and the conformer index
|
|
417
|
-
"""
|
|
418
|
-
return asyncio.run(_single_energy(mol, method, engine, mode, timeout, name, folder_uuid))
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
def batch_energy(
|
|
422
|
-
mols: Iterable[RdkitMol],
|
|
423
|
-
method: str = "aimnet2_wb97md3",
|
|
424
|
-
engine: str = "aimnet2",
|
|
425
|
-
mode: str = "auto",
|
|
426
|
-
timeout: int = 600,
|
|
427
|
-
name: str = "Energy API Workflow",
|
|
428
|
-
folder_uuid: str | None = None,
|
|
429
|
-
) -> list[list[ConformerEnergyResult]]:
|
|
430
|
-
"""
|
|
431
|
-
Computes the energy for the given molecule.
|
|
432
|
-
|
|
433
|
-
:param mols: RDKit Molecule
|
|
434
|
-
:param method: Method to use for the calculation.
|
|
435
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
436
|
-
:param engine: Engine to run the energy. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
|
|
437
|
-
:param mode: Mode to run the energy. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
438
|
-
for options.
|
|
439
|
-
:param timeout: time in seconds before the Workflow times out
|
|
440
|
-
:param name: name for the job
|
|
441
|
-
:param folder_uuid: folder UUID
|
|
442
|
-
:raises MethodTooSlowError: if the method is invalid
|
|
443
|
-
:returns: list of dictionaries with the energy in Hartree and the conformer index
|
|
444
|
-
"""
|
|
445
|
-
|
|
446
|
-
async def _run():
|
|
447
|
-
tasks = [
|
|
448
|
-
_single_energy(mol, method, engine, mode, timeout, name, folder_uuid) for mol in mols
|
|
449
|
-
]
|
|
450
|
-
return await asyncio.gather(*tasks)
|
|
451
|
-
|
|
452
|
-
return asyncio.run(_run())
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
async def _single_energy(
|
|
456
|
-
mol: RdkitMol,
|
|
457
|
-
method: str = "aimnet2_wb97md3",
|
|
458
|
-
engine: str = "aimnet2",
|
|
459
|
-
mode: str = "auto",
|
|
460
|
-
timeout: int = 600,
|
|
461
|
-
name: str = "Energy API Workflow",
|
|
462
|
-
folder_uuid: str | None = None,
|
|
463
|
-
) -> list[ConformerEnergyResult]:
|
|
464
|
-
"""
|
|
465
|
-
Computes the energy for the given molecule.
|
|
466
|
-
|
|
467
|
-
:param mol: RDKit Molecule
|
|
468
|
-
:param method: Method to use for the calculation.
|
|
469
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
470
|
-
:param engine: Engine to run the energy. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
|
|
471
|
-
:param mode: Mode to run the energy
|
|
472
|
-
:param timeout: time in seconds before the Workflow times out
|
|
473
|
-
:param name: name for the job
|
|
474
|
-
:param folder_uuid: folder UUID
|
|
475
|
-
:raises MethodTooSlowError: if the method is invalid
|
|
476
|
-
:returns: dictionary with the energy in Hartree and the conformer index
|
|
477
|
-
"""
|
|
478
|
-
get_api_key()
|
|
479
|
-
method = stjames.Method(method)
|
|
480
|
-
|
|
481
|
-
if mol.GetNumConformers() == 0: # type: ignore[call-arg]
|
|
482
|
-
mol = _embed_rdkit_mol(mol)
|
|
483
|
-
if mol.GetNumConformers() == 0: # type: ignore[call-arg]
|
|
484
|
-
raise NoConformersError("This molecule has no conformers")
|
|
485
|
-
|
|
486
|
-
if method not in FAST_METHODS:
|
|
487
|
-
raise MethodTooSlowError(
|
|
488
|
-
"This method is too slow; try running this through our web interface."
|
|
489
|
-
)
|
|
490
|
-
|
|
491
|
-
workflow_uuids = []
|
|
492
|
-
for conformer in mol.GetConformers():
|
|
493
|
-
cid = conformer.GetId() # type: ignore[call-arg]
|
|
494
|
-
stjames_mol = _rdkit_to_stjames(mol, cid)
|
|
495
|
-
post = rowan.submit_workflow(
|
|
496
|
-
name=name,
|
|
497
|
-
workflow_type="basic_calculation",
|
|
498
|
-
initial_molecule=stjames_mol,
|
|
499
|
-
workflow_data={
|
|
500
|
-
"settings": {
|
|
501
|
-
"method": method.value,
|
|
502
|
-
"corrections": [],
|
|
503
|
-
"tasks": ["energy"],
|
|
504
|
-
"mode": mode,
|
|
505
|
-
"opt_settings": {"constraints": []},
|
|
506
|
-
},
|
|
507
|
-
"engine": engine,
|
|
508
|
-
},
|
|
509
|
-
folder_uuid=folder_uuid,
|
|
510
|
-
)
|
|
511
|
-
|
|
512
|
-
workflow_uuids.append(post.uuid)
|
|
513
|
-
|
|
514
|
-
start = time.time()
|
|
515
|
-
while not all(rowan.retrieve_workflow(uuid).is_finished() for uuid in workflow_uuids):
|
|
516
|
-
await asyncio.sleep(5)
|
|
517
|
-
if time.time() - start > timeout:
|
|
518
|
-
raise TimeoutError("Workflow timed out")
|
|
519
|
-
|
|
520
|
-
results = [rowan.retrieve_workflow(uuid).data for uuid in workflow_uuids]
|
|
521
|
-
|
|
522
|
-
energies: list[float] = []
|
|
523
|
-
for data in results:
|
|
524
|
-
if data is not None:
|
|
525
|
-
calc = rowan.retrieve_calculation(data["calculation_uuid"])
|
|
526
|
-
if calc.energy is not None:
|
|
527
|
-
energies.append(calc.energy)
|
|
528
|
-
|
|
529
|
-
return [{"conformer_index": index, "energy": energy} for index, energy in enumerate(energies)]
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
def run_optimize(
|
|
533
|
-
mol: RdkitMol,
|
|
534
|
-
method: str = "aimnet2_wb97md3",
|
|
535
|
-
engine: str = "aimnet2",
|
|
536
|
-
mode: str = "auto",
|
|
537
|
-
return_energies: bool = False,
|
|
538
|
-
timeout: int = 600,
|
|
539
|
-
name: str = "Optimize API Workflow",
|
|
540
|
-
folder_uuid: str | None = None,
|
|
541
|
-
) -> OptimizeResult:
|
|
542
|
-
"""
|
|
543
|
-
Optimize each of a molecule's conformers and then return the molecule.
|
|
544
|
-
|
|
545
|
-
:param mol: RDKit Molecule
|
|
546
|
-
:param method: Method to use for the calculation.
|
|
547
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
548
|
-
:param engine: Engine to run the optimization. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
|
|
549
|
-
:param return_energies: whether to return energies in Hartree too
|
|
550
|
-
:param mode: Mode to run the optimization. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
551
|
-
for options.
|
|
552
|
-
:param timeout: time in seconds before the Workflow times out
|
|
553
|
-
:param name: name for the job
|
|
554
|
-
:param folder_uuid: folder UUID
|
|
555
|
-
:raises MethodTooSlowError: if the method is invalid
|
|
556
|
-
:returns: dictionary with the optimized conformer(s) and optional list of energies per conformer
|
|
557
|
-
"""
|
|
558
|
-
return asyncio.run(
|
|
559
|
-
_single_optimize(mol, method, engine, mode, return_energies, timeout, name, folder_uuid)
|
|
560
|
-
)
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
def batch_optimize(
|
|
564
|
-
mols: Iterable[RdkitMol],
|
|
565
|
-
method: str = "aimnet2_wb97md3",
|
|
566
|
-
engine: str = "aimnet2",
|
|
567
|
-
mode: str = "auto",
|
|
568
|
-
return_energies: bool = False,
|
|
569
|
-
timeout: int = 600,
|
|
570
|
-
name: str = "Optimize API Workflow",
|
|
571
|
-
folder_uuid: str | None = None,
|
|
572
|
-
) -> list[OptimizeResult]:
|
|
573
|
-
"""
|
|
574
|
-
Optimize each of a Molecule's conformers and then return the Molecule.
|
|
575
|
-
|
|
576
|
-
:param mols: input Molecule
|
|
577
|
-
:param method: Method to use for the calculation.
|
|
578
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
579
|
-
:param engine: Engine to run the optimization. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
|
|
580
|
-
:param mode: Mode to run the optimization. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
581
|
-
for options.
|
|
582
|
-
:param return_energies: whether to return energies in Hartree too
|
|
583
|
-
:param timeout: time in seconds before the Workflow times out
|
|
584
|
-
:param name: name for the job
|
|
585
|
-
:param folder_uuid: folder UUID
|
|
586
|
-
:raises MethodTooSlowError: if the method is invalid
|
|
587
|
-
:returns: dictionaries with optimized conformer(s) and optional list of energies per conformer
|
|
588
|
-
"""
|
|
589
|
-
|
|
590
|
-
async def _run():
|
|
591
|
-
tasks = [
|
|
592
|
-
_single_optimize(mol, method, engine, mode, return_energies, timeout, name, folder_uuid)
|
|
593
|
-
for mol in mols
|
|
594
|
-
]
|
|
595
|
-
return await asyncio.gather(*tasks)
|
|
596
|
-
|
|
597
|
-
return asyncio.run(_run())
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
async def _single_optimize(
|
|
601
|
-
mol: RdkitMol,
|
|
602
|
-
method: str = "aimnet2_wb97md3",
|
|
603
|
-
engine: str = "aimnet2",
|
|
604
|
-
mode: str = "auto",
|
|
605
|
-
return_energies: bool = False,
|
|
606
|
-
timeout: int = 600,
|
|
607
|
-
name: str = "Optimize API Workflow",
|
|
608
|
-
folder_uuid: str | None = None,
|
|
609
|
-
) -> OptimizeResult:
|
|
610
|
-
"""
|
|
611
|
-
Optimize each of a molecule's conformers and then return the molecule.
|
|
612
|
-
|
|
613
|
-
:param mol: RDKit Molecule
|
|
614
|
-
:param method: Method to use for the calculation.
|
|
615
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
616
|
-
:param engine: Engine to run the optimization. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
|
|
617
|
-
:param mode: Mode to run the optimization. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
618
|
-
:param return_energies: whether to return energies in Hartree too
|
|
619
|
-
:param timeout: time in seconds before the Workflow times out
|
|
620
|
-
:param name: name for the job
|
|
621
|
-
:param folder_uuid: folder UUID
|
|
622
|
-
:raises MethodTooSlowError: if the method is invalid
|
|
623
|
-
:returns: dictionary with the optimized conformer(s) and optional list of energies per conformer
|
|
624
|
-
"""
|
|
625
|
-
get_api_key()
|
|
626
|
-
method = stjames.Method(method)
|
|
627
|
-
|
|
628
|
-
if mol.GetNumConformers() == 0: # type: ignore[call-arg]
|
|
629
|
-
mol = _embed_rdkit_mol(mol)
|
|
630
|
-
if mol.GetNumConformers() == 0: # type: ignore[call-arg]
|
|
631
|
-
raise NoConformersError("This molecule has no conformers")
|
|
632
|
-
|
|
633
|
-
if method not in FAST_METHODS:
|
|
634
|
-
raise MethodTooSlowError(
|
|
635
|
-
"This method is too slow; try running this through our web interface."
|
|
636
|
-
)
|
|
637
|
-
|
|
638
|
-
optimized_mol = copy.deepcopy(mol)
|
|
639
|
-
|
|
640
|
-
workflow_uuids = []
|
|
641
|
-
for conformer in mol.GetConformers():
|
|
642
|
-
cid = conformer.GetId() # type: ignore[call-arg]
|
|
643
|
-
stjames_mol = _rdkit_to_stjames(mol, cid)
|
|
644
|
-
|
|
645
|
-
post = rowan.submit_workflow(
|
|
646
|
-
name=name,
|
|
647
|
-
workflow_type="basic_calculation",
|
|
648
|
-
initial_molecule=stjames_mol,
|
|
649
|
-
workflow_data={
|
|
650
|
-
"settings": {
|
|
651
|
-
"method": method.value,
|
|
652
|
-
"corrections": [],
|
|
653
|
-
"tasks": ["optimize"],
|
|
654
|
-
"mode": mode,
|
|
655
|
-
"opt_settings": {"constraints": []},
|
|
656
|
-
},
|
|
657
|
-
"engine": engine,
|
|
658
|
-
},
|
|
659
|
-
folder_uuid=folder_uuid,
|
|
660
|
-
)
|
|
661
|
-
|
|
662
|
-
workflow_uuids.append(post.uuid)
|
|
663
|
-
|
|
664
|
-
start = time.time()
|
|
665
|
-
while not all(rowan.retrieve_workflow(uuid).is_finished() for uuid in workflow_uuids):
|
|
666
|
-
await asyncio.sleep(5)
|
|
667
|
-
if time.time() - start > timeout:
|
|
668
|
-
raise TimeoutError("Workflow timed out")
|
|
669
|
-
|
|
670
|
-
results = [rowan.retrieve_workflow(uuid).data for uuid in workflow_uuids]
|
|
671
|
-
calculations = [
|
|
672
|
-
rowan.retrieve_calculation(data["calculation_uuid"]) for data in results if data is not None
|
|
673
|
-
]
|
|
674
|
-
optimized_positions: list[list[tuple[float, float, float]]] = []
|
|
675
|
-
energies: list[float] = []
|
|
676
|
-
for calc in calculations:
|
|
677
|
-
if calc.molecule is not None:
|
|
678
|
-
optimized_positions.append([atom.position for atom in calc.molecule.atoms])
|
|
679
|
-
if calc.energy is not None:
|
|
680
|
-
energies.append(calc.energy)
|
|
681
|
-
|
|
682
|
-
for i, conformer in enumerate(optimized_mol.GetConformers()):
|
|
683
|
-
conformer.SetPositions(np.array(optimized_positions[i])) # type: ignore[attr-defined]
|
|
684
|
-
|
|
685
|
-
return {
|
|
686
|
-
"molecule": mol,
|
|
687
|
-
"energies": energies if return_energies else [],
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
def run_conformers(
|
|
692
|
-
mol: RdkitMol,
|
|
693
|
-
num_conformers=10,
|
|
694
|
-
method: str = "aimnet2_wb97md3",
|
|
695
|
-
mode: str = "rapid",
|
|
696
|
-
return_energies: bool = False,
|
|
697
|
-
timeout: int = 600,
|
|
698
|
-
name: str = "Conformer API Workflow",
|
|
699
|
-
folder_uuid: str | None = None,
|
|
700
|
-
) -> ConformerResult:
|
|
701
|
-
"""
|
|
702
|
-
Generate conformers for a Molecule.
|
|
703
|
-
|
|
704
|
-
:param mol: RDKit Molecule
|
|
705
|
-
:param num_conformers: number of conformers to generate
|
|
706
|
-
:param method: Method to use for the calculation.
|
|
707
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
708
|
-
:param mode: Mode for conformer generation. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
709
|
-
for options.
|
|
710
|
-
:param return_energies: whether to return energies in Hartree too
|
|
711
|
-
:param timeout: time in seconds before the Workflow times out
|
|
712
|
-
:param name: name for the job
|
|
713
|
-
:param folder_uuid: folder UUID
|
|
714
|
-
:returns: dictionary with the RDKit Molecule and energies
|
|
715
|
-
"""
|
|
716
|
-
return asyncio.run(
|
|
717
|
-
_single_conformers(
|
|
718
|
-
mol,
|
|
719
|
-
num_conformers,
|
|
720
|
-
method,
|
|
721
|
-
mode,
|
|
722
|
-
return_energies,
|
|
723
|
-
timeout,
|
|
724
|
-
name,
|
|
725
|
-
folder_uuid,
|
|
726
|
-
)
|
|
727
|
-
)
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
def batch_conformers(
|
|
731
|
-
mols: Iterable[RdkitMol],
|
|
732
|
-
num_conformers=10,
|
|
733
|
-
method: str = "aimnet2_wb97md3",
|
|
734
|
-
mode: str = "rapid",
|
|
735
|
-
return_energies: bool = False,
|
|
736
|
-
timeout: int = 600,
|
|
737
|
-
name: str = "Conformer API Workflow",
|
|
738
|
-
folder_uuid: str | None = None,
|
|
739
|
-
) -> list[ConformerResult]:
|
|
740
|
-
"""
|
|
741
|
-
Generate conformers for a Molecule.
|
|
742
|
-
|
|
743
|
-
:param mols: RDKit molecule object
|
|
744
|
-
:param num_conformers: number of conformers to generate
|
|
745
|
-
:param method: Method to use for the calculation.
|
|
746
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
747
|
-
:param mode: conformer generation mode. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
748
|
-
for options.
|
|
749
|
-
:param return_energies: whether to return energies in Hartree too
|
|
750
|
-
:param timeout: time in seconds before the Workflow times out
|
|
751
|
-
:param name: name for the job
|
|
752
|
-
:returns: list of dictonaries with RDKit Molecule and energies
|
|
753
|
-
"""
|
|
754
|
-
|
|
755
|
-
async def _run():
|
|
756
|
-
tasks = [
|
|
757
|
-
_single_conformers(
|
|
758
|
-
mol,
|
|
759
|
-
num_conformers,
|
|
760
|
-
method,
|
|
761
|
-
mode,
|
|
762
|
-
return_energies,
|
|
763
|
-
timeout,
|
|
764
|
-
name,
|
|
765
|
-
folder_uuid,
|
|
766
|
-
)
|
|
767
|
-
for mol in mols
|
|
768
|
-
]
|
|
769
|
-
return await asyncio.gather(*tasks)
|
|
770
|
-
|
|
771
|
-
return asyncio.run(_run())
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
async def _single_conformers(
|
|
775
|
-
mol: RdkitMol,
|
|
776
|
-
num_conformers=10,
|
|
777
|
-
method: str = "aimnet2_wb97md3",
|
|
778
|
-
mode: str = "rapid",
|
|
779
|
-
return_energies: bool = False,
|
|
780
|
-
timeout: int = 600,
|
|
781
|
-
name: str = "Conformer API Workflow",
|
|
782
|
-
folder_uuid: str | None = None,
|
|
783
|
-
) -> ConformerResult:
|
|
784
|
-
"""
|
|
785
|
-
Generate conformers for a molecule.
|
|
786
|
-
|
|
787
|
-
:param mol: RDKit Molecule
|
|
788
|
-
:param num_conformers: number of conformers to generate
|
|
789
|
-
:param method: Method to use for the calculation.
|
|
790
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
791
|
-
:param mode: conformer generation mode. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
792
|
-
for options.
|
|
793
|
-
:param return_energies: whether to return energies in Hartree too
|
|
794
|
-
:param timeout: time in seconds before the Workflow times out
|
|
795
|
-
:param name: name for the job
|
|
796
|
-
:param folder_uuid: folder UUID
|
|
797
|
-
:returns: dictionary with RDKit molecule and energies
|
|
798
|
-
"""
|
|
799
|
-
get_api_key()
|
|
800
|
-
method = stjames.Method(method)
|
|
801
|
-
|
|
802
|
-
if mol.GetNumConformers() == 0: # type: ignore[call-arg]
|
|
803
|
-
mol = _embed_rdkit_mol(mol)
|
|
804
|
-
if mol.GetNumConformers() == 0: # type: ignore[call-arg]
|
|
805
|
-
raise NoConformersError("This molecule has no conformers")
|
|
806
|
-
|
|
807
|
-
if method not in FAST_METHODS:
|
|
808
|
-
raise MethodTooSlowError(
|
|
809
|
-
"This method is too slow; try running this through our web interface."
|
|
810
|
-
)
|
|
811
|
-
|
|
812
|
-
post = rowan.submit_workflow(
|
|
813
|
-
name=name,
|
|
814
|
-
workflow_type="conformer_search",
|
|
815
|
-
initial_molecule=_rdkit_to_stjames(mol),
|
|
816
|
-
workflow_data={
|
|
817
|
-
"conf_gen_mode": "rapid",
|
|
818
|
-
"mode": mode,
|
|
819
|
-
"mso_mode": "manual",
|
|
820
|
-
"multistage_opt_settings": {
|
|
821
|
-
"mode": "manual",
|
|
822
|
-
"optimization_settings": [
|
|
823
|
-
{
|
|
824
|
-
"method": method.value,
|
|
825
|
-
"tasks": ["optimize"],
|
|
826
|
-
"corrections": [],
|
|
827
|
-
"mode": "auto",
|
|
828
|
-
}
|
|
829
|
-
],
|
|
830
|
-
"solvent": None,
|
|
831
|
-
"transition_state": False,
|
|
832
|
-
"constraints": [],
|
|
833
|
-
},
|
|
834
|
-
},
|
|
835
|
-
folder_uuid=folder_uuid,
|
|
836
|
-
)
|
|
837
|
-
|
|
838
|
-
start = time.time()
|
|
839
|
-
while not post.is_finished():
|
|
840
|
-
await asyncio.sleep(5)
|
|
841
|
-
if time.time() - start > timeout:
|
|
842
|
-
raise TimeoutError("Workflow timed out")
|
|
843
|
-
|
|
844
|
-
data = rowan.retrieve_workflow(post.uuid).data
|
|
845
|
-
|
|
846
|
-
if data is None:
|
|
847
|
-
raise NoConformersError("This molecule has no conformers")
|
|
848
|
-
|
|
849
|
-
sorted_data = sorted(
|
|
850
|
-
zip(data["energies"], data["conformer_uuids"], strict=True),
|
|
851
|
-
key=lambda x: x[0],
|
|
852
|
-
)
|
|
853
|
-
|
|
854
|
-
if len(sorted_data) < num_conformers:
|
|
855
|
-
logging.warning(
|
|
856
|
-
"Number of conformers requested is greater than number of conformers available"
|
|
857
|
-
)
|
|
858
|
-
num_conformers = min(num_conformers, len(sorted_data))
|
|
859
|
-
|
|
860
|
-
# Extract the UUIDs of the lowest n energies
|
|
861
|
-
lowest_n_uuids = [item[1][0] for item in sorted_data[:num_conformers]]
|
|
862
|
-
lowest_energies = [item[0] for item in sorted_data[:num_conformers]]
|
|
863
|
-
|
|
864
|
-
AllChem.EmbedMultipleConfs(mol, numConfs=num_conformers) # type: ignore[attr-defined]
|
|
865
|
-
|
|
866
|
-
for i, conformer in enumerate(mol.GetConformers()):
|
|
867
|
-
calc = rowan.retrieve_calculation(lowest_n_uuids[i])
|
|
868
|
-
if calc.molecule is None:
|
|
869
|
-
raise ValueError(f"Calculation {lowest_n_uuids[i]} has no molecules")
|
|
870
|
-
pos = [atom.position for atom in calc.molecule.atoms]
|
|
871
|
-
conformer.SetPositions(np.array(pos)) # type: ignore[attr-defined]
|
|
872
|
-
|
|
873
|
-
return {
|
|
874
|
-
"molecule": mol,
|
|
875
|
-
"energies": lowest_energies if return_energies else [],
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
def run_charges(
|
|
880
|
-
mol: RdkitMol,
|
|
881
|
-
method: str = "aimnet2_wb97md3",
|
|
882
|
-
engine: str = "aimnet2",
|
|
883
|
-
mode: str = "auto",
|
|
884
|
-
timeout: int = 600,
|
|
885
|
-
name: str = "Charges API Workflow",
|
|
886
|
-
folder_uuid: str | None = None,
|
|
887
|
-
) -> ChargesResults:
|
|
888
|
-
"""
|
|
889
|
-
Computes atom-centered charges for the given Molecule.
|
|
890
|
-
|
|
891
|
-
:param mol: RDKit Molecule
|
|
892
|
-
:param method: Method to use for the calculation.
|
|
893
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
894
|
-
:param engine: Engine to run the charges. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
|
|
895
|
-
:param mode: Mode to run the calculation in. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
896
|
-
for options.
|
|
897
|
-
:param timeout: timeout in seconds
|
|
898
|
-
:param name: name of the job
|
|
899
|
-
:param folder_uuid: folder UUID
|
|
900
|
-
:raises MethodTooSlowError: if the method is invalid
|
|
901
|
-
:returns: dictionary with the charges and the conformer index
|
|
902
|
-
"""
|
|
903
|
-
return asyncio.run(_single_charges(mol, method, engine, mode, timeout, name, folder_uuid))
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
def batch_charges(
|
|
907
|
-
mols: Iterable[RdkitMol],
|
|
908
|
-
method: str = "aimnet2_wb97md3",
|
|
909
|
-
engine: str = "aimnet2",
|
|
910
|
-
mode: str = "auto",
|
|
911
|
-
timeout: int = 600,
|
|
912
|
-
name: str = "Charges API Workflow",
|
|
913
|
-
folder_uuid: str | None = None,
|
|
914
|
-
) -> list[ChargesResults]:
|
|
915
|
-
"""
|
|
916
|
-
Computes atom-centered charges for the given Molecules.
|
|
917
|
-
|
|
918
|
-
:param mols: RDKit Molecule
|
|
919
|
-
:param method: Method to use for the calculation.
|
|
920
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
921
|
-
:param engine: Engine to run the charges. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
|
|
922
|
-
:param mode: Mode to run the calculation in. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
923
|
-
for options.
|
|
924
|
-
:param timeout: timeout in seconds
|
|
925
|
-
:param name: name of the job
|
|
926
|
-
:param folder_uuid: folder UUID
|
|
927
|
-
:raises MethodTooSlowError: if the method is invalid
|
|
928
|
-
:returns: list of dictionaries with the charges and the conformer index
|
|
929
|
-
"""
|
|
930
|
-
|
|
931
|
-
async def _run():
|
|
932
|
-
tasks = [
|
|
933
|
-
_single_charges(mol, method, engine, mode, timeout, name, folder_uuid) for mol in mols
|
|
934
|
-
]
|
|
935
|
-
return await asyncio.gather(*tasks)
|
|
936
|
-
|
|
937
|
-
return asyncio.run(_run())
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
async def _single_charges(
|
|
941
|
-
mol: RdkitMol,
|
|
942
|
-
method: str = "aimnet2_wb97md3",
|
|
943
|
-
engine: str = "aimnet2",
|
|
944
|
-
mode: str = "auto",
|
|
945
|
-
timeout: int = 600,
|
|
946
|
-
name: str = "Energy API Workflow",
|
|
947
|
-
folder_uuid: str | None = None,
|
|
948
|
-
) -> ChargesResults:
|
|
949
|
-
"""
|
|
950
|
-
Computes atom-centered charges for the given Molecule.
|
|
951
|
-
|
|
952
|
-
:param mol: RDKit Molecule
|
|
953
|
-
:param method: Method to use for the calculation.
|
|
954
|
-
See [list of available methods](https://github.com/rowansci/stjames-public/blob/master/stjames/method.py)
|
|
955
|
-
:param engine: Engine to run the charges. See [list of available engines](https://github.com/rowansci/stjames-public/blob/master/stjames/engine.py)
|
|
956
|
-
:param mode: Mode to run the calculation in. See [list of available modes](https://github.com/rowansci/stjames-public/blob/master/stjames/mode.py)
|
|
957
|
-
for options.
|
|
958
|
-
:param timeout: timeout in seconds
|
|
959
|
-
:param name: name of the job
|
|
960
|
-
:param folder_uuid: folder UUID
|
|
961
|
-
:raises MethodTooSlowError: if the method is invalid
|
|
962
|
-
:returns: dictionary with the charges and the conformer index
|
|
963
|
-
"""
|
|
964
|
-
get_api_key()
|
|
965
|
-
method = stjames.Method(method)
|
|
966
|
-
|
|
967
|
-
if mol.GetNumConformers() == 0: # type: ignore[call-arg]
|
|
968
|
-
mol = _embed_rdkit_mol(mol)
|
|
969
|
-
if mol.GetNumConformers() == 0: # type: ignore[call-arg]
|
|
970
|
-
raise NoConformersError("This molecule has no conformers")
|
|
971
|
-
|
|
972
|
-
if method not in FAST_METHODS:
|
|
973
|
-
raise MethodTooSlowError(
|
|
974
|
-
"This method is too slow; try running this through our web interface."
|
|
975
|
-
)
|
|
976
|
-
|
|
977
|
-
workflow_uuids = []
|
|
978
|
-
for conformer in mol.GetConformers():
|
|
979
|
-
cid = conformer.GetId() # type: ignore[call-arg]
|
|
980
|
-
|
|
981
|
-
post = rowan.submit_workflow(
|
|
982
|
-
name=name,
|
|
983
|
-
workflow_type="basic_calculation",
|
|
984
|
-
initial_molecule=_rdkit_to_stjames(mol, cid),
|
|
985
|
-
workflow_data={
|
|
986
|
-
"settings": {
|
|
987
|
-
"method": method.value,
|
|
988
|
-
"corrections": [],
|
|
989
|
-
"tasks": ["charge"],
|
|
990
|
-
"mode": mode,
|
|
991
|
-
"opt_settings": {"constraints": []},
|
|
992
|
-
},
|
|
993
|
-
"engine": engine,
|
|
994
|
-
},
|
|
995
|
-
folder_uuid=folder_uuid,
|
|
996
|
-
)
|
|
997
|
-
|
|
998
|
-
workflow_uuids.append(post.uuid)
|
|
999
|
-
|
|
1000
|
-
start = time.time()
|
|
1001
|
-
while not all(rowan.retrieve_workflow(uuid).is_finished() for uuid in workflow_uuids):
|
|
1002
|
-
await asyncio.sleep(5)
|
|
1003
|
-
if time.time() - start > timeout:
|
|
1004
|
-
raise TimeoutError("Workflow timed out")
|
|
1005
|
-
|
|
1006
|
-
def grab_charges(uuid: str) -> list[float]:
|
|
1007
|
-
"""Grab mulliken charges by UUID of workflow."""
|
|
1008
|
-
data = rowan.retrieve_workflow(uuid).data
|
|
1009
|
-
if data is None:
|
|
1010
|
-
raise KeyError("Workflow data not found")
|
|
1011
|
-
calc = rowan.retrieve_calculation(data["calculation_uuid"])
|
|
1012
|
-
if calc.molecule is None or calc.molecule.charges is None:
|
|
1013
|
-
raise KeyError("Calculation has no charges")
|
|
1014
|
-
return calc.molecule.charges
|
|
1015
|
-
|
|
1016
|
-
return [
|
|
1017
|
-
{"conformer_index": i, "charges": grab_charges(uuid)}
|
|
1018
|
-
for i, uuid in enumerate(workflow_uuids)
|
|
1019
|
-
]
|
|
File without changes
|
|
File without changes
|