rdworks 0.49.1__py3-none-any.whl → 0.51.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 +1 -1
- rdworks/conf.py +56 -0
- rdworks/mol.py +42 -0
- rdworks/xtb/wrapper.py +44 -7
- {rdworks-0.49.1.dist-info → rdworks-0.51.1.dist-info}/METADATA +1 -1
- {rdworks-0.49.1.dist-info → rdworks-0.51.1.dist-info}/RECORD +9 -9
- {rdworks-0.49.1.dist-info → rdworks-0.51.1.dist-info}/WHEEL +0 -0
- {rdworks-0.49.1.dist-info → rdworks-0.51.1.dist-info}/licenses/LICENSE +0 -0
- {rdworks-0.49.1.dist-info → rdworks-0.51.1.dist-info}/top_level.txt +0 -0
rdworks/__init__.py
CHANGED
rdworks/conf.py
CHANGED
@@ -270,6 +270,62 @@ class Conf:
|
|
270
270
|
return self.sync(ase_atoms.get_positions())
|
271
271
|
|
272
272
|
|
273
|
+
def protonate(self, atom_indices: list[int]) -> Self:
|
274
|
+
"""Protonate given non-hydrogen atoms.
|
275
|
+
|
276
|
+
Args:
|
277
|
+
atom_indices (list[int]): atom indices of non-hydrogen atoms to protonate.
|
278
|
+
|
279
|
+
Returns:
|
280
|
+
Self: self.
|
281
|
+
"""
|
282
|
+
for idx in atom_indices:
|
283
|
+
atom = self.rdmol.GetAtomWithIdx(idx)
|
284
|
+
h = atom.GetNumExplicitHs()
|
285
|
+
c = atom.GetFormalCharge()
|
286
|
+
atom.SetNumExplicitHs(h+1)
|
287
|
+
atom.SetFormalCharge(c+1)
|
288
|
+
Chem.SanitizeMol(self.rdmol)
|
289
|
+
self.rdmol = Chem.AddHs(self.rdmol, addCoords=True)
|
290
|
+
# The Chem.AddHs function in RDKit returns a new Mol object with hydrogens added to the molecule.
|
291
|
+
# It modifies the input molecule by adding hydrogens,
|
292
|
+
# but the original molecule remains unchanged.
|
293
|
+
|
294
|
+
return self
|
295
|
+
|
296
|
+
|
297
|
+
def deprotonate(self, atom_indices: list[int]) -> Self:
|
298
|
+
"""Deprotonate given non-hydrogen atoms.
|
299
|
+
|
300
|
+
Args:
|
301
|
+
atom_indices (list[int]): atom indices of non-hydrogen atoms to deprotonate.
|
302
|
+
|
303
|
+
Returns:
|
304
|
+
Self: self.
|
305
|
+
"""
|
306
|
+
for idx in atom_indices:
|
307
|
+
bonded_H_idx = None
|
308
|
+
atom = self.rdmol.GetAtomWithIdx(idx)
|
309
|
+
h = atom.GetNumExplicitHs()
|
310
|
+
if h-1 >= 0 :
|
311
|
+
atom.SetNumExplicitHs(h-1) # (h-1) must be unsigned int
|
312
|
+
c = atom.GetFormalCharge()
|
313
|
+
atom.SetFormalCharge(c-1)
|
314
|
+
neighbors = atom.GetNeighbors()
|
315
|
+
|
316
|
+
for neighbor in neighbors:
|
317
|
+
if neighbor.GetAtomicNum() == 1:
|
318
|
+
bonded_H_idx = neighbor.GetIdx()
|
319
|
+
break
|
320
|
+
|
321
|
+
if bonded_H_idx is not None:
|
322
|
+
edit_mol = Chem.EditableMol(self.rdmol)
|
323
|
+
edit_mol.RemoveAtom(bonded_H_idx)
|
324
|
+
self.rdmol = edit_mol.GetMol()
|
325
|
+
Chem.SanitizeMol(self.rdmol)
|
326
|
+
|
327
|
+
return self
|
328
|
+
|
273
329
|
|
274
330
|
##################################################
|
275
331
|
### Endpoint methods
|
rdworks/mol.py
CHANGED
@@ -1619,4 +1619,46 @@ class Mol:
|
|
1619
1619
|
self.props = data['props']
|
1620
1620
|
self.confs = [Conf().deserialize(_) for _ in data['confs']] # for 3D conformers (iterable)
|
1621
1621
|
|
1622
|
+
return self
|
1623
|
+
|
1624
|
+
def from_molblock(self, molblock: str) -> Self:
|
1625
|
+
"""Initialize a new Mol object from MolBlock.
|
1626
|
+
|
1627
|
+
Args:
|
1628
|
+
molblock (str): MolBlock string
|
1629
|
+
|
1630
|
+
Raises:
|
1631
|
+
ValueError: invalid MolBlock
|
1632
|
+
|
1633
|
+
Returns:
|
1634
|
+
Self: self.
|
1635
|
+
"""
|
1636
|
+
molecule = Chem.MolFromMolBlock(molblock)
|
1637
|
+
try:
|
1638
|
+
self.rdmol, _ = clean_2d(molecule, reset_isotope=True, remove_H=True)
|
1639
|
+
self.smiles = Chem.MolToSmiles(self.rdmol)
|
1640
|
+
self.confs = [Conf(x) for x in _]
|
1641
|
+
except:
|
1642
|
+
raise ValueError(f'Mol() Error: invalid MolBlock string')
|
1643
|
+
|
1644
|
+
assert self.smiles and self.rdmol, "Mol() Error: invalid molecule"
|
1645
|
+
|
1646
|
+
name = self.rdmol.GetProp('_Name')
|
1647
|
+
|
1648
|
+
rdDepictor.Compute2DCoords(self.rdmol)
|
1649
|
+
|
1650
|
+
try:
|
1651
|
+
self.name = str(name)
|
1652
|
+
except:
|
1653
|
+
self.name = 'untitled'
|
1654
|
+
|
1655
|
+
self.rdmol.SetProp('_Name', self.name) # _Name can't be None
|
1656
|
+
self.InChIKey = generate_inchi_key(self.rdmol)
|
1657
|
+
self.props.update({
|
1658
|
+
'aka' : [], # <-- to be set by MolLibr.unique()
|
1659
|
+
'atoms' : self.rdmol.GetNumAtoms(), # hydrogens not excluded?
|
1660
|
+
'charge': rdmolops.GetFormalCharge(self.rdmol),
|
1661
|
+
"nrb" : Descriptors.NumRotatableBonds(self.rdmol),
|
1662
|
+
})
|
1663
|
+
|
1622
1664
|
return self
|
rdworks/xtb/wrapper.py
CHANGED
@@ -59,6 +59,43 @@ class GFN2xTB:
|
|
59
59
|
return shutil.which('xtb') is not None
|
60
60
|
|
61
61
|
|
62
|
+
@staticmethod
|
63
|
+
def is_optimize_ready() -> bool:
|
64
|
+
try:
|
65
|
+
h2o = [
|
66
|
+
'$coord',
|
67
|
+
' 0.00000000000000 0.00000000000000 -0.73578586109551 o',
|
68
|
+
' 1.44183152868459 0.00000000000000 0.36789293054775 h',
|
69
|
+
'-1.44183152868459 0.00000000000000 0.36789293054775 h',
|
70
|
+
'$end',
|
71
|
+
]
|
72
|
+
|
73
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
74
|
+
test_geometry = os.path.join(temp_dir, 'coord')
|
75
|
+
with open(test_geometry, 'w') as f:
|
76
|
+
f.write('\n'.join(h2o))
|
77
|
+
proc = subprocess.run(['xtb', test_geometry, '--opt'],
|
78
|
+
capture_output=True,
|
79
|
+
text=True)
|
80
|
+
assert proc.returncode == 0
|
81
|
+
|
82
|
+
return True
|
83
|
+
|
84
|
+
except:
|
85
|
+
print("""
|
86
|
+
Conda installed xTB has the Fortran runtime error in geometry optimization.
|
87
|
+
Please install xtb using the compiled binary:
|
88
|
+
|
89
|
+
$ wget https://github.com/grimme-lab/xtb/releases/download/v6.7.1/xtb-6.7.1-linux-x86_64.tar.xz
|
90
|
+
$ tar -xf xtb-6.7.1-linux-x86_64.tar.xz
|
91
|
+
$ cp -r xtb-dist/bin/* /usr/local/bin/
|
92
|
+
$ cp -r xtb-dist/lib/* /usr/local/lib/
|
93
|
+
$ cp -r xtb-dist/include/* /usr/local/include/
|
94
|
+
$ cp -r xtb-dist/share /usr/local/ """)
|
95
|
+
|
96
|
+
return False
|
97
|
+
|
98
|
+
|
62
99
|
@staticmethod
|
63
100
|
def is_cpx_ready() -> bool:
|
64
101
|
"""Checks if the CPCM-X command-line tool, `cpx`, is accessible in the system.
|
@@ -70,7 +107,7 @@ class GFN2xTB:
|
|
70
107
|
|
71
108
|
|
72
109
|
@staticmethod
|
73
|
-
def
|
110
|
+
def is_cpcmx_ready() -> bool:
|
74
111
|
"""Checks if xtb works with the `--cpcmx` option.
|
75
112
|
|
76
113
|
xtb distributed by the conda does not include CPCM-X function (as of June 17, 2025).
|
@@ -101,7 +138,8 @@ class GFN2xTB:
|
|
101
138
|
"""
|
102
139
|
return all([GFN2xTB.is_xtb_ready(),
|
103
140
|
GFN2xTB.is_cpx_ready(),
|
104
|
-
GFN2xTB.
|
141
|
+
GFN2xTB.is_cpcmx_ready(),
|
142
|
+
GFN2xTB.is_optimize_ready()])
|
105
143
|
|
106
144
|
|
107
145
|
@staticmethod
|
@@ -115,10 +153,9 @@ class GFN2xTB:
|
|
115
153
|
cmd = ['xtb', '--version']
|
116
154
|
proc = subprocess.run(cmd, capture_output=True, text=True)
|
117
155
|
assert proc.returncode == 0, "GFN2xTB() Error: xtb not available"
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
return line
|
156
|
+
match = re.search('xtb\s+version\s+(?P<version>[\d.]+)', proc.stdout)
|
157
|
+
if match:
|
158
|
+
return match.group('version')
|
122
159
|
|
123
160
|
return None
|
124
161
|
|
@@ -362,7 +399,7 @@ class GFN2xTB:
|
|
362
399
|
elif water == 'alpb':
|
363
400
|
options += ['--alpb', 'water']
|
364
401
|
# it does not provide Gsolv contribution to the total energy
|
365
|
-
elif water == 'cpcmx' and self.
|
402
|
+
elif water == 'cpcmx' and self.is_cpcmx_ready():
|
366
403
|
options += ['--cpcmx', 'water']
|
367
404
|
|
368
405
|
if verbose:
|
@@ -1,10 +1,10 @@
|
|
1
|
-
rdworks/__init__.py,sha256=
|
2
|
-
rdworks/conf.py,sha256=
|
1
|
+
rdworks/__init__.py,sha256=97yHJt3kMGu9bPYMVL98USE3E9kkAxZmupT77BGkX6s,1391
|
2
|
+
rdworks/conf.py,sha256=aHpVa3PcbECk-IP6pdxqT2Q9T4eykqoozcgaGRnZdLk,36210
|
3
3
|
rdworks/descriptor.py,sha256=34T_dQ6g8v3u-ym8TLKbQtxIIV5TEo-d3pdedq3o-cg,2106
|
4
4
|
rdworks/display.py,sha256=JR0gR26UpH-JCxVOaqXZCUj2MiGZSrx9Me87FncspVI,13469
|
5
5
|
rdworks/ionized.py,sha256=_t-Ajssv1rytV4Y_KsSbxfnsBKqy-EusbhNUtaWcV6o,7681
|
6
6
|
rdworks/matchedseries.py,sha256=A3ON4CUpQV159mu9VqgNiJ8uoQ9ePOry9d3ra4NCAgc,10377
|
7
|
-
rdworks/mol.py,sha256
|
7
|
+
rdworks/mol.py,sha256=-zjAsBETNUbP4_n8p6how40NhZB24icMYhas1kYPqCc,70064
|
8
8
|
rdworks/mollibr.py,sha256=X4UBO6Ga-QmNS7RwUiaDYAx0Q5hnWs71yTkEpH02Qb4,37696
|
9
9
|
rdworks/pka.py,sha256=NVJVfpcNEMlX5QRyLBgUM7GIT7VMjO-llAR4LWc8J2c,1656
|
10
10
|
rdworks/readin.py,sha256=0bnVcZcAmSLqc6zu1mYcv0LdBv2agQfOpKGwpSRL9VE,11742
|
@@ -65,9 +65,9 @@ rdworks/predefined/misc/reactive-part-2.xml,sha256=0vNTMwWrrQmxBpbgbyRHx8sVs83cq
|
|
65
65
|
rdworks/predefined/misc/reactive-part-3.xml,sha256=LgWHSEbRTVmgBoIO45xbTo1xQJs0Xu51j3JnIapRYo4,3094
|
66
66
|
rdworks/predefined/misc/reactive.xml,sha256=syedoQ6VYUfRLnxy99ObuDniJ_a_WhrWAJbTKFfJ6VY,11248
|
67
67
|
rdworks/xtb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
68
|
-
rdworks/xtb/wrapper.py,sha256=
|
69
|
-
rdworks-0.
|
70
|
-
rdworks-0.
|
71
|
-
rdworks-0.
|
72
|
-
rdworks-0.
|
73
|
-
rdworks-0.
|
68
|
+
rdworks/xtb/wrapper.py,sha256=w_SX3q7D4_peHERFzONesG8c-a6UTRzfBLx313D8rNE,23638
|
69
|
+
rdworks-0.51.1.dist-info/licenses/LICENSE,sha256=UOkJSBqYyQUvtCp7a-vdCANeEcLE2dnTie_eB1By5SY,1074
|
70
|
+
rdworks-0.51.1.dist-info/METADATA,sha256=nlzLbvfGJYCScwVL1Mub2lFFhsDvETxIQFs5UIBdZ90,1967
|
71
|
+
rdworks-0.51.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
72
|
+
rdworks-0.51.1.dist-info/top_level.txt,sha256=05C98HbvBK2axUBogC_hAT_CdpOeQYGnQ6vRAgawr8s,8
|
73
|
+
rdworks-0.51.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|