rdworks 0.53.1__py3-none-any.whl → 0.55.1__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.
- rdworks/__init__.py +4 -5
- rdworks/{workflow.py → complete.py} +3 -4
- rdworks/conf.py +2 -2
- rdworks/microstates.py +30 -15
- rdworks/xtb/wrapper.py +7 -6
- {rdworks-0.53.1.dist-info → rdworks-0.55.1.dist-info}/METADATA +1 -1
- {rdworks-0.53.1.dist-info → rdworks-0.55.1.dist-info}/RECORD +10 -11
- rdworks/pka.py +0 -38
- {rdworks-0.53.1.dist-info → rdworks-0.55.1.dist-info}/WHEEL +0 -0
- {rdworks-0.53.1.dist-info → rdworks-0.55.1.dist-info}/licenses/LICENSE +0 -0
- {rdworks-0.53.1.dist-info → rdworks-0.55.1.dist-info}/top_level.txt +0 -0
rdworks/__init__.py
CHANGED
@@ -1,16 +1,15 @@
|
|
1
|
-
__version__ = '0.
|
1
|
+
__version__ = '0.55.1'
|
2
2
|
|
3
3
|
from rdworks.conf import Conf
|
4
4
|
from rdworks.mol import Mol
|
5
5
|
from rdworks.mollibr import MolLibr
|
6
6
|
|
7
|
-
from rdworks.workflow import complete_stereoisomers, complete_tautomers
|
8
|
-
|
9
|
-
from rdworks.ionized import IonizedStates
|
10
|
-
|
11
7
|
from rdworks.readin import read_csv, merge_csv, read_dataframe, read_smi, read_sdf, read_mae
|
12
8
|
from rdworks.std import desalt_smiles, standardize_smiles, standardize
|
13
9
|
|
10
|
+
from rdworks.complete import complete_stereoisomers, complete_tautomers
|
11
|
+
from rdworks.ionized import IonizedStates
|
12
|
+
|
14
13
|
from rdworks.rgroup import expand_rgroup, most_common, most_common_in_NP
|
15
14
|
from rdworks.scaffold import scaffold_network, scaffold_tree, BRICS_fragmented, BRICS_fragment_indices
|
16
15
|
from rdworks.matchedseries import MatchedSeries
|
@@ -1,8 +1,5 @@
|
|
1
|
-
|
1
|
+
from rdworks import Mol, MolLibr
|
2
2
|
from rdworks.stereoisomers import enumerate_stereoisomers, enumerate_ring_bond_stereoisomers
|
3
|
-
from rdworks.mol import Mol
|
4
|
-
from rdworks.mollibr import MolLibr
|
5
|
-
|
6
3
|
from rdkit import Chem
|
7
4
|
from rdkit.Chem.MolStandardize import rdMolStandardize
|
8
5
|
|
@@ -26,6 +23,8 @@ def complete_stereoisomers(molecular_input: str | Chem.Mol | Mol,
|
|
26
23
|
Returns:
|
27
24
|
MolLibr: a library of complete stereoisomers.
|
28
25
|
"""
|
26
|
+
from rdworks import Mol, MolLibr
|
27
|
+
|
29
28
|
if isinstance(molecular_input, Mol):
|
30
29
|
if name:
|
31
30
|
mol = molecular_input.rename(name)
|
rdworks/conf.py
CHANGED
@@ -546,9 +546,9 @@ class Conf:
|
|
546
546
|
conf = frag_conf.copy()
|
547
547
|
conf.set_torsion(*frag_ijkl, angle) # atoms bonded to `l` move.
|
548
548
|
conf = conf.optimize(calculator, fmax, **kwargs)
|
549
|
+
data['angle'].append(angle)
|
549
550
|
# conf.optimize() updates coordinates and conf.props:
|
550
551
|
# `E_tot_init(kcal/mol)`, `E_tot(kcal/mol)`, `Converged`.
|
551
|
-
data['angle'].append(angle)
|
552
552
|
data['init'].append(conf.props['E_tot_init(kcal/mol)'])
|
553
553
|
data['last'].append(conf.props['E_tot(kcal/mol)'])
|
554
554
|
data['Converged'].append(conf.props['Converged'])
|
@@ -562,9 +562,9 @@ class Conf:
|
|
562
562
|
conf = ref_conf.copy()
|
563
563
|
conf.set_torsion(*indices, angle) # atoms bonded to `l` move.
|
564
564
|
conf = conf.optimize(calculator, fmax, **kwargs)
|
565
|
+
data['angle'].append(angle)
|
565
566
|
# conf.optimize() updates coordinates and conf.props:
|
566
567
|
# `E_tot_init(kcal/mol)`, `E_tot(kcal/mol)`, `Converged`.
|
567
|
-
data['angle'].append(conf.props['angle'])
|
568
568
|
data['init'].append(conf.props['E_tot_init(kcal/mol)'])
|
569
569
|
data['last'].append(conf.props['E_tot(kcal/mol)'])
|
570
570
|
data['Converged'].append(conf.props['Converged'])
|
rdworks/microstates.py
CHANGED
@@ -1,11 +1,22 @@
|
|
1
1
|
import numpy as np
|
2
2
|
import math
|
3
3
|
import itertools
|
4
|
+
import logging
|
4
5
|
|
5
6
|
from types import SimpleNamespace
|
7
|
+
from pathlib import Path
|
6
8
|
from rdworks import Conf, Mol
|
7
9
|
from rdworks.xtb.wrapper import GFN2xTB
|
8
10
|
|
11
|
+
from rdkit import Chem
|
12
|
+
from rdkit.Chem import (
|
13
|
+
AllChem, RemoveHs, CanonSmiles, MolFromSmarts,
|
14
|
+
GetFormalCharge, RWMol, AddHs, SanitizeMol,
|
15
|
+
MolToSmiles, MolFromSmiles,
|
16
|
+
)
|
17
|
+
|
18
|
+
logger = logging.getLogger(__name__)
|
19
|
+
|
9
20
|
|
10
21
|
kT = 0.001987 * 298.0 # (kcal/mol K), standard condition
|
11
22
|
C = math.log(10) * kT
|
@@ -23,9 +34,10 @@ class Microstates():
|
|
23
34
|
self.mols = []
|
24
35
|
self.reference = None
|
25
36
|
|
26
|
-
|
37
|
+
|
38
|
+
def enumerate(self) -> None:
|
39
|
+
# Qu pKake results must be stored at .confs
|
27
40
|
for conf in self.origin:
|
28
|
-
print(conf.props)
|
29
41
|
pka = conf.props.get('pka', None)
|
30
42
|
if pka is None:
|
31
43
|
# no protonation/deprotonation sites
|
@@ -49,7 +61,7 @@ class Microstates():
|
|
49
61
|
|
50
62
|
for (p, d) in PD:
|
51
63
|
conf = self.origin.confs[0].copy()
|
52
|
-
conf = conf.protonate(p).deprotonate(d).optimize(calculator=calculator)
|
64
|
+
conf = conf.protonate(p).deprotonate(d).optimize(calculator=self.calculator)
|
53
65
|
charge = len(p) - len(d)
|
54
66
|
self.states.append(SimpleNamespace(
|
55
67
|
charge=charge,
|
@@ -83,7 +95,7 @@ class Microstates():
|
|
83
95
|
return float(np.dot(p, pe_array))
|
84
96
|
|
85
97
|
|
86
|
-
def
|
98
|
+
def populate(self) -> None:
|
87
99
|
for microstate in self.states:
|
88
100
|
mol = Mol(microstate.conf).make_confs(n=4).optimize_confs()
|
89
101
|
# mol = mol.drop_confs(similar=True, similar_rmsd=0.3, verbose=True)
|
@@ -94,23 +106,21 @@ class Microstates():
|
|
94
106
|
conf = conf.optimize(calculator=self.calculator, verbose=True)
|
95
107
|
# GFN2xTB requires 3D coordinates
|
96
108
|
# xtb = GFN2xTB(conf.rdmol).singlepoint(water='cpcmx', verbose=True)
|
97
|
-
|
98
|
-
|
109
|
+
PE.append(conf.potential_energy(calculator=self.calculator))
|
110
|
+
# xtb = GFN2xTB(conf.rdmol).singlepoint(verbose=True)
|
99
111
|
# SimpleNamespace(
|
100
112
|
# PE = datadict['total energy'] * hartree2kcalpermol,
|
101
113
|
# Gsolv = Gsolv,
|
102
114
|
# charges = datadict['partial charges'],
|
103
115
|
# wbo = Wiberg_bond_orders,
|
104
116
|
# )
|
105
|
-
print("PE=", PE)
|
106
117
|
microstate.PE = self.Boltzmann_weighted_average(PE)
|
107
|
-
|
108
|
-
|
118
|
+
logger.info(f"PE= {PE}")
|
119
|
+
logger.info(f"Boltzmann weighted= {microstate.PE}")
|
109
120
|
self.mols.append(mol)
|
110
|
-
print("microstate.energy", microstate)
|
111
121
|
|
112
122
|
|
113
|
-
def
|
123
|
+
def get_populations(self, pH: float) -> list[tuple]:
|
114
124
|
# set the lowest dG as the reference
|
115
125
|
self.reference = self.states[np.argmin([microstate.PE for microstate in self.states])]
|
116
126
|
for microstate in self.states:
|
@@ -120,7 +130,7 @@ class Microstates():
|
|
120
130
|
dG.append((microstate.PE - self.reference.PE) + microstate.delta_m * C * pH)
|
121
131
|
dG = np.array(dG)
|
122
132
|
|
123
|
-
|
133
|
+
logger.info(f"dG= {dG}")
|
124
134
|
Boltzmann_factors = np.exp(-dG/kT)
|
125
135
|
Z = np.sum(Boltzmann_factors)
|
126
136
|
p = Boltzmann_factors/Z
|
@@ -128,11 +138,16 @@ class Microstates():
|
|
128
138
|
# [(0, p0), (1, p1), ...]
|
129
139
|
|
130
140
|
return idx_p
|
141
|
+
|
142
|
+
|
143
|
+
def get_ensemble(self) -> list[Mol]:
|
144
|
+
return self.mols
|
145
|
+
|
146
|
+
|
147
|
+
def get_mol(self, idx: int) -> Mol:
|
148
|
+
return self.mols[idx]
|
131
149
|
|
132
150
|
|
133
151
|
def count(self) -> int:
|
134
152
|
return len(self.states)
|
135
153
|
|
136
|
-
|
137
|
-
def get_mol(self, idx: int) -> Mol:
|
138
|
-
return self.mols[idx]
|
rdworks/xtb/wrapper.py
CHANGED
@@ -79,7 +79,8 @@ class GFN2xTB:
|
|
79
79
|
proc = subprocess.run(['xtb', test_geometry, '--opt'],
|
80
80
|
cwd=temp_dir,
|
81
81
|
capture_output=True,
|
82
|
-
text=True
|
82
|
+
text=True,
|
83
|
+
encoding='utf-8')
|
83
84
|
assert proc.returncode == 0
|
84
85
|
|
85
86
|
return True
|
@@ -122,7 +123,7 @@ $ cp -r xtb-dist/share /usr/local/ """)
|
|
122
123
|
if GFN2xTB.is_xtb_ready():
|
123
124
|
with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
|
124
125
|
cmd = ['xtb', '--cpcmx']
|
125
|
-
proc = subprocess.run(cmd, cwd=temp_dir, capture_output=True, text=True)
|
126
|
+
proc = subprocess.run(cmd, cwd=temp_dir, capture_output=True, text=True, encoding='utf-8')
|
126
127
|
# we are expecting an error because no input file is given
|
127
128
|
assert proc.returncode != 0
|
128
129
|
for line in proc.stdout.split('\n'):
|
@@ -156,7 +157,7 @@ $ cp -r xtb-dist/share /usr/local/ """)
|
|
156
157
|
if GFN2xTB.is_xtb_ready():
|
157
158
|
with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
|
158
159
|
cmd = ['xtb', '--version']
|
159
|
-
proc = subprocess.run(cmd, cwd=temp_dir, capture_output=True, text=True)
|
160
|
+
proc = subprocess.run(cmd, cwd=temp_dir, capture_output=True, text=True, encoding='utf-8')
|
160
161
|
assert proc.returncode == 0, "GFN2xTB() Error: xtb not available"
|
161
162
|
match = re.search('xtb\s+version\s+(?P<version>[\d.]+)', proc.stdout)
|
162
163
|
if match:
|
@@ -358,7 +359,7 @@ $ cp -r xtb-dist/share /usr/local/ """)
|
|
358
359
|
|
359
360
|
# 'xtbout.json', 'xtbrestart', 'xtbtopo.mol', 'charges', and 'wbo' files will be
|
360
361
|
# created in the current working directory.
|
361
|
-
proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
|
362
|
+
proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True, encoding='utf-8')
|
362
363
|
# if proc.returncode == 0:
|
363
364
|
# print("Standard Output:")
|
364
365
|
# print(proc.stdout)
|
@@ -461,7 +462,7 @@ $ cp -r xtb-dist/share /usr/local/ """)
|
|
461
462
|
if verbose:
|
462
463
|
logger.info(f"optimize() {' '.join(cmd+options)}")
|
463
464
|
|
464
|
-
proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
|
465
|
+
proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True, encoding='utf-8')
|
465
466
|
|
466
467
|
if proc.returncode == 0 and xtbout_path.is_file():
|
467
468
|
with open(xtbout_path, 'r') as f:
|
@@ -527,7 +528,7 @@ $ cp -r xtb-dist/share /usr/local/ """)
|
|
527
528
|
elif water == 'alpb':
|
528
529
|
options += ['--alpb', 'water']
|
529
530
|
|
530
|
-
proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
|
531
|
+
proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True, encoding='utf-8')
|
531
532
|
# output files: xtb_esp.cosmo, xtb_esp.dat, xtb_esp_profile.dat
|
532
533
|
|
533
534
|
if proc.returncode == 0 and xtb_esp_dat.is_file():
|
@@ -1,13 +1,13 @@
|
|
1
|
-
rdworks/__init__.py,sha256=
|
2
|
-
rdworks/
|
1
|
+
rdworks/__init__.py,sha256=uWC5GaxWQpax4cYBDNiFaYul630ZKhLHVvtZTQYX-Dg,1356
|
2
|
+
rdworks/complete.py,sha256=rTd7iBGmNwSoylx8VmBqcqqPIEeCHxiCO2TPo00_UnA,3147
|
3
|
+
rdworks/conf.py,sha256=_4SxHJiaOdK_4KY9adxvQTfzJFudvAQoHRgvejmfyGc,36365
|
3
4
|
rdworks/descriptor.py,sha256=34T_dQ6g8v3u-ym8TLKbQtxIIV5TEo-d3pdedq3o-cg,2106
|
4
5
|
rdworks/display.py,sha256=JR0gR26UpH-JCxVOaqXZCUj2MiGZSrx9Me87FncspVI,13469
|
5
6
|
rdworks/ionized.py,sha256=_t-Ajssv1rytV4Y_KsSbxfnsBKqy-EusbhNUtaWcV6o,7681
|
6
7
|
rdworks/matchedseries.py,sha256=A3ON4CUpQV159mu9VqgNiJ8uoQ9ePOry9d3ra4NCAgc,10377
|
7
|
-
rdworks/microstates.py,sha256=
|
8
|
+
rdworks/microstates.py,sha256=hf_5UDDgZxJGnrqRiv2fbS1j3zq7LMccHSOJbpEgjX8,5503
|
8
9
|
rdworks/mol.py,sha256=4gNjs_ryNNWThMekV794uwjjBE-JLGGWcdyMaS9-xP8,71369
|
9
10
|
rdworks/mollibr.py,sha256=X4UBO6Ga-QmNS7RwUiaDYAx0Q5hnWs71yTkEpH02Qb4,37696
|
10
|
-
rdworks/pka.py,sha256=NVJVfpcNEMlX5QRyLBgUM7GIT7VMjO-llAR4LWc8J2c,1656
|
11
11
|
rdworks/readin.py,sha256=b1BHchQMC5EgQd3C05n72t_aa_9u0iKQWyyIqjyfkPc,11809
|
12
12
|
rdworks/rgroup.py,sha256=ivF2gzmRtt339rxEnkv2KfnCs0CUdBbnSje7Y54rtFI,57996
|
13
13
|
rdworks/scaffold.py,sha256=60T5YacyxZsEpDo_J5Qxulm2YNQO4EQR8PcNUwjn1QU,22026
|
@@ -17,7 +17,6 @@ rdworks/testdata.py,sha256=TmbNPA-ju6nTBt_Yts4EJUFmL9Cd6DCVXrDF42QLlHw,1732
|
|
17
17
|
rdworks/torsion.py,sha256=UUaYOvNS89SlLFauYiAboUqysy32EN0_Gktc4xxuDQI,18788
|
18
18
|
rdworks/units.py,sha256=nljKPHcr6IWoAp0CkL7y1gSNDd6a07NeVfxXwSMuHQM,365
|
19
19
|
rdworks/utils.py,sha256=d2Sio8WTlGPsmBOHIYDCMWg_7X4rTWjJQAqzd7ywo2A,14191
|
20
|
-
rdworks/workflow.py,sha256=MtP9QUGgCKMyI3G4vp8sokos_UyaQvTHFOEPUJresZU,3139
|
21
20
|
rdworks/xml.py,sha256=aaMhwVRGvt1VzasaKDnkYnZ4kp2cIgvGb1CsmMgwQ_c,10704
|
22
21
|
rdworks/autograph/__init__.py,sha256=0Qfjwo0h4Q0n08zsqHRbuNOZms6MuNXnWErnQpQ6Px0,140
|
23
22
|
rdworks/autograph/autograph.py,sha256=frjsUaCTOD-Z1lYPzOxRoTtqMMiYroWAy6tSwKn3CUA,8769
|
@@ -66,9 +65,9 @@ rdworks/predefined/misc/reactive-part-2.xml,sha256=0vNTMwWrrQmxBpbgbyRHx8sVs83cq
|
|
66
65
|
rdworks/predefined/misc/reactive-part-3.xml,sha256=LgWHSEbRTVmgBoIO45xbTo1xQJs0Xu51j3JnIapRYo4,3094
|
67
66
|
rdworks/predefined/misc/reactive.xml,sha256=syedoQ6VYUfRLnxy99ObuDniJ_a_WhrWAJbTKFfJ6VY,11248
|
68
67
|
rdworks/xtb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
69
|
-
rdworks/xtb/wrapper.py,sha256=
|
70
|
-
rdworks-0.
|
71
|
-
rdworks-0.
|
72
|
-
rdworks-0.
|
73
|
-
rdworks-0.
|
74
|
-
rdworks-0.
|
68
|
+
rdworks/xtb/wrapper.py,sha256=YpZY8SJ9Lrp3I3_GAVawSb_4_Zc8hcJtF5l7-I-Wbys,22048
|
69
|
+
rdworks-0.55.1.dist-info/licenses/LICENSE,sha256=UOkJSBqYyQUvtCp7a-vdCANeEcLE2dnTie_eB1By5SY,1074
|
70
|
+
rdworks-0.55.1.dist-info/METADATA,sha256=9Do_0fPpQCuHbz-hq-OvSeKLcH6Qsf_YPYlyRkQYBZM,1967
|
71
|
+
rdworks-0.55.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
72
|
+
rdworks-0.55.1.dist-info/top_level.txt,sha256=05C98HbvBK2axUBogC_hAT_CdpOeQYGnQ6vRAgawr8s,8
|
73
|
+
rdworks-0.55.1.dist-info/RECORD,,
|
rdworks/pka.py
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
"""This module is an implementation in progress of the decision tree method for pKa prediction.
|
2
|
-
|
3
|
-
Crippen, J. Chem. Inf. Model., Vol. 48, No. 10, 2008, 2042-2053.
|
4
|
-
|
5
|
-
The SMARTS patterns and pKa values were taken from the supporting information of the paper.
|
6
|
-
These "MOE SMARTS" were converted to generic SMARTS which relied on use of some recursive SMARTS patterns.
|
7
|
-
The first data row then describes nodes 1, and then the tree expands out based on decisions of SMARTS-matching:
|
8
|
-
if node 2 is yes to pattern [#8,#16,#34,#52,#84;H]C(=O) - giving pKa 3.68 and range 5.96
|
9
|
-
node 3 is no to the same pattern - giving pKa 7.21 and range 17.32
|
10
|
-
Then nodes 4,5 are under 2 and 6,7 are under 3, etc, etc until the leaf nodes are reached
|
11
|
-
"""
|
12
|
-
|
13
|
-
|
14
|
-
import importlib.resources
|
15
|
-
from collections import namedtuple
|
16
|
-
from typing import Union
|
17
|
-
|
18
|
-
from rdkit import Chem
|
19
|
-
from rdkit.Chem import AllChem
|
20
|
-
|
21
|
-
datadir = importlib.resources.files('rdworks.predefined')
|
22
|
-
DecisionTreeNode = namedtuple('DecisionTree', ('node', 'parent', 'child', 'FP', 'SMARTS', 'YN', 'pKa', 'pKa_range'))
|
23
|
-
decision_tree = []
|
24
|
-
with open(datadir / "pKa_decision_tree.ext", "r") as f:
|
25
|
-
for line in f:
|
26
|
-
if (not line) or line.startswith('#'):
|
27
|
-
continue
|
28
|
-
decision_tree.append(DecisionTreeNode(line.strip().split()))
|
29
|
-
|
30
|
-
|
31
|
-
def decision_tree_pKa(rdmol:Chem.Mol) -> Union[float, None]:
|
32
|
-
pKa = None
|
33
|
-
for _ in decision_tree:
|
34
|
-
patt = Chem.MolFromSmarts(_.SMARTS) # make an RDKit query molecule
|
35
|
-
match = rdmol.HasSubstructMatch(patt) # check if we have a match for our test molecule
|
36
|
-
# pKa = float(values[6])
|
37
|
-
# pKa_range = float(values[7])
|
38
|
-
return pKa
|
File without changes
|
File without changes
|
File without changes
|