rdworks 0.50.1__py3-none-any.whl → 0.52.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 CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = '0.50.1'
1
+ __version__ = '0.52.1'
2
2
 
3
3
  from rdworks.conf import Conf
4
4
  from rdworks.mol import Mol
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
@@ -299,6 +355,15 @@ class Conf:
299
355
  return True
300
356
 
301
357
 
358
+ def charge(self) -> int:
359
+ """Returns molecular formal charge.
360
+
361
+ Returns:
362
+ int: charge
363
+ """
364
+ return self.charge
365
+
366
+
302
367
  def positions(self) -> np.array:
303
368
  """Returns the coordinates.
304
369
 
rdworks/microstates.py ADDED
@@ -0,0 +1,138 @@
1
+ import numpy as np
2
+ import math
3
+ import itertools
4
+
5
+ from types import SimpleNamespace
6
+ from rdworks import Conf, Mol
7
+ from rdworks.xtb.wrapper import GFN2xTB
8
+
9
+
10
+ kT = 0.001987 * 298.0 # (kcal/mol K), standard condition
11
+ C = math.log(10) * kT
12
+
13
+
14
+
15
+ class Microstates():
16
+
17
+ def __init__(self, origin: Mol, calculator: str = 'xTB'):
18
+ self.origin = origin
19
+ self.calculator = calculator
20
+ self.basic_sites = []
21
+ self.acidic_sites = []
22
+ self.states = []
23
+ self.mols = []
24
+ self.reference = None
25
+
26
+ # read QupKake results
27
+ for conf in self.origin:
28
+ print(conf.props)
29
+ pka = conf.props.get('pka', None)
30
+ if pka is None:
31
+ # no protonation/deprotonation sites
32
+ continue
33
+ if isinstance(pka, str) and pka.startswith('tensor'):
34
+ # ex. 'tensor(9.5784)'
35
+ pka = float(pka.replace('tensor(','').replace(')',''))
36
+ if conf.props.get('pka_type') == 'basic':
37
+ self.basic_sites.append(conf.props.get('idx'))
38
+ elif conf.props.get('pka_type') == 'acidic':
39
+ self.acidic_sites.append(conf.props.get('idx'))
40
+
41
+ # enumerate protonation/deprotonation sites to generate microstates
42
+
43
+ np = len(self.basic_sites)
44
+ nd = len(self.acidic_sites)
45
+ P = [c for n in range(np+1) for c in itertools.combinations(self.basic_sites, n)]
46
+ D = [c for n in range(nd+1) for c in itertools.combinations(self.acidic_sites, n)]
47
+
48
+ PD = list(itertools.product(P, D))
49
+
50
+ for (p, d) in PD:
51
+ conf = self.origin.confs[0].copy()
52
+ conf = conf.protonate(p).deprotonate(d).optimize(calculator=calculator)
53
+ charge = len(p) - len(d)
54
+ self.states.append(SimpleNamespace(
55
+ charge=charge,
56
+ protonation_sites=p,
57
+ deprotonation_sites=d,
58
+ conf=conf,
59
+ smiles=Mol(conf).smiles,
60
+ delta_m=None,
61
+ PE=None))
62
+
63
+ # sort microstates by ascending charges
64
+ self.states = sorted(self.states, key=lambda x: x.charge)
65
+
66
+
67
+ @staticmethod
68
+ def Boltzmann_weighted_average(potential_energies: list) -> float:
69
+ """Calculate Boltzmann weighted average potential energy at pH 0.
70
+
71
+ Args:
72
+ potential_energies (list): a list of potential energies.
73
+
74
+ Returns:
75
+ float: Boltzmann weighted average potential energy.
76
+ """
77
+ pe_array = np.array(potential_energies)
78
+ pe = pe_array - min(potential_energies)
79
+ Boltzmann_factors = np.exp(-pe/kT)
80
+ Z = np.sum(Boltzmann_factors)
81
+ p = Boltzmann_factors/Z
82
+
83
+ return float(np.dot(p, pe_array))
84
+
85
+
86
+ def potential_energy(self) -> None:
87
+ for microstate in self.states:
88
+ mol = Mol(microstate.conf).make_confs(n=4).optimize_confs()
89
+ # mol = mol.drop_confs(similar=True, similar_rmsd=0.3, verbose=True)
90
+ # mol = mol.optimize_confs(calculator=calculator)
91
+ # mol = mol.drop_confs(k=10, window=15.0, verbose=True)
92
+ PE = []
93
+ for conf in mol.confs:
94
+ conf = conf.optimize(calculator=self.calculator, verbose=True)
95
+ # GFN2xTB requires 3D coordinates
96
+ # xtb = GFN2xTB(conf.rdmol).singlepoint(water='cpcmx', verbose=True)
97
+ xtb = GFN2xTB(conf.rdmol).singlepoint(verbose=True)
98
+ PE.append(xtb.PE)
99
+ # SimpleNamespace(
100
+ # PE = datadict['total energy'] * hartree2kcalpermol,
101
+ # Gsolv = Gsolv,
102
+ # charges = datadict['partial charges'],
103
+ # wbo = Wiberg_bond_orders,
104
+ # )
105
+ print("PE=", PE)
106
+ microstate.PE = self.Boltzmann_weighted_average(PE)
107
+ print("Boltzmann weighted=", microstate.PE)
108
+
109
+ self.mols.append(mol)
110
+ print("microstate.energy", microstate)
111
+
112
+
113
+ def populations(self, pH: float) -> list[tuple]:
114
+ # set the lowest dG as the reference
115
+ self.reference = self.states[np.argmin([microstate.PE for microstate in self.states])]
116
+ for microstate in self.states:
117
+ microstate.delta_m = microstate.charge - self.reference.charge
118
+ dG = []
119
+ for microstate in self.states:
120
+ dG.append((microstate.PE - self.reference.PE) + microstate.delta_m * C * pH)
121
+ dG = np.array(dG)
122
+
123
+ print("dG=", dG)
124
+ Boltzmann_factors = np.exp(-dG/kT)
125
+ Z = np.sum(Boltzmann_factors)
126
+ p = Boltzmann_factors/Z
127
+ idx_p = sorted(list(enumerate(p)), key=lambda x: x[1], reverse=True)
128
+ # [(0, p0), (1, p1), ...]
129
+
130
+ return idx_p
131
+
132
+
133
+ def count(self) -> int:
134
+ return len(self.states)
135
+
136
+
137
+ def get_mol(self, idx: int) -> Mol:
138
+ return self.mols[idx]
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/readin.py CHANGED
@@ -232,6 +232,7 @@ def read_sdf(path:str | Path, std:bool=False, confs:bool=False, props:bool=True,
232
232
  # start a new molecule
233
233
  rdmol_2d = Chem.RemoveHs(rdmol)
234
234
  AllChem.Compute2DCoords(rdmol_2d)
235
+ # initialize a new molecule with the H-removed 2D
235
236
  new_mol = Mol(rdmol_2d, isomer_name, std=False) # atom indices remain unchanged.
236
237
  new_conf = Conf(rdmol)
237
238
  new_conf.props.update(props)
rdworks/xtb/wrapper.py CHANGED
@@ -11,6 +11,7 @@ from pathlib import Path
11
11
  from types import SimpleNamespace
12
12
 
13
13
  from rdkit import Chem
14
+ from rdkit.Chem import rdmolops
14
15
  from rdkit.Geometry import Point3D
15
16
 
16
17
 
@@ -32,6 +33,7 @@ class GFN2xTB:
32
33
  assert self.is_xtb_ready(), "xtb is not accessible"
33
34
 
34
35
  self.rdmol = molecule
36
+ self.charge = rdmolops.GetFormalCharge(self.rdmol)
35
37
  self.natoms = molecule.GetNumAtoms()
36
38
  self.symbols = [ atom.GetSymbol() for atom in molecule.GetAtoms() ]
37
39
  self.positions = molecule.GetConformer().GetPositions().tolist()
@@ -74,7 +76,8 @@ class GFN2xTB:
74
76
  test_geometry = os.path.join(temp_dir, 'coord')
75
77
  with open(test_geometry, 'w') as f:
76
78
  f.write('\n'.join(h2o))
77
- proc = subprocess.run(['xtb', test_geometry, '--opt'],
79
+ proc = subprocess.run(['xtb', test_geometry, '--opt'],
80
+ cwd=temp_dir,
78
81
  capture_output=True,
79
82
  text=True)
80
83
  assert proc.returncode == 0
@@ -117,14 +120,15 @@ $ cp -r xtb-dist/share /usr/local/ """)
117
120
  bool: True if the --cpcmx option is working, False otherwise.
118
121
  """
119
122
  if GFN2xTB.is_xtb_ready():
120
- cmd = ['xtb', '--cpcmx']
121
- proc = subprocess.run(cmd, capture_output=True, text=True)
122
- # we are expecting an error because no input file is given
123
- assert proc.returncode != 0
124
- for line in proc.stdout.split('\n'):
125
- line = line.strip()
126
- if 'CPCM-X library was not included' in line:
127
- return False
123
+ with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
124
+ cmd = ['xtb', '--cpcmx']
125
+ proc = subprocess.run(cmd, cwd=temp_dir, capture_output=True, text=True)
126
+ # we are expecting an error because no input file is given
127
+ assert proc.returncode != 0
128
+ for line in proc.stdout.split('\n'):
129
+ line = line.strip()
130
+ if 'CPCM-X library was not included' in line:
131
+ return False
128
132
 
129
133
  return True
130
134
 
@@ -150,12 +154,13 @@ $ cp -r xtb-dist/share /usr/local/ """)
150
154
  str | None: version statement.
151
155
  """
152
156
  if GFN2xTB.is_xtb_ready():
153
- cmd = ['xtb', '--version']
154
- proc = subprocess.run(cmd, capture_output=True, text=True)
155
- assert proc.returncode == 0, "GFN2xTB() Error: xtb not available"
156
- match = re.search('xtb\s+version\s+(?P<version>[\d.]+)', proc.stdout)
157
- if match:
158
- return match.group('version')
157
+ with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
158
+ cmd = ['xtb', '--version']
159
+ proc = subprocess.run(cmd, cwd=temp_dir, capture_output=True, text=True)
160
+ assert proc.returncode == 0, "GFN2xTB() Error: xtb not available"
161
+ match = re.search('xtb\s+version\s+(?P<version>[\d.]+)', proc.stdout)
162
+ if match:
163
+ return match.group('version')
159
164
 
160
165
  return None
161
166
 
@@ -265,109 +270,56 @@ $ cp -r xtb-dist/share /usr/local/ """)
265
270
  return Wiberg_bond_orders
266
271
 
267
272
 
268
- def cpx(self, verbose: bool = False) -> float | None:
269
- """Runs cpx and returns Gsolv (kcal/mol)
270
-
271
- Warning:
272
- Solvation energy obtained from `xtb --cpcmx water` differs from
273
- `cpx --solvent water` (difference between gas.out and solv.out in terms of total energy).
274
- There are other correction terms not clearly defined in the output files.
275
- So, this method is not reliable and should be discarded
276
-
277
- Returns:
278
- float or None: Gsolv energy in kcal/mol or None.
279
- """
280
- with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
281
- workdir = Path(temp_dir)
282
- if verbose:
283
- logger.info(f'xtb.cpx workdir= {temp_dir}')
284
-
285
- geometry_input_path = workdir / 'coord'
286
- geometry_output_path = workdir / 'xtbtopo.mol'
287
- gas_out_path = workdir / 'gas.out'
288
- solv_out_path = workdir / 'solv.out'
289
- wbo_path = workdir / 'wbo'
290
-
291
- with open(geometry_input_path, 'w') as f:
292
- f.write(self.to_turbomole_coord())
293
-
294
- cmd = ['cpx']
295
- options = ['--solvent', 'water']
296
-
297
- proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
298
- # cpx creates the following files:
299
- # charges gas.energy solute_sigma.txt solvent_sigma.txt xtbtopo.mol
300
- # coord gas.out solute_sigma3.txt solvent_sigma3.txt
301
- # error solute.cosmo solv.out wbo
302
-
303
- # example of solv.out
304
- # :::::::::::::::::::::::::::::::::::::::::::::::::::::
305
- # :: SUMMARY ::
306
- # :::::::::::::::::::::::::::::::::::::::::::::::::::::
307
- # :: total energy -119.507131639760 Eh ::
308
- # :: w/o Gsasa/hb/shift -119.494560363045 Eh ::
309
- # :: gradient norm 0.084154442395 Eh/a0 ::
310
- # :: HOMO-LUMO gap 2.966157362876 eV ::
311
- # ::.................................................::
312
- # :: SCC energy -121.121278922798 Eh ::
313
- # :: -> isotropic ES 0.180705208303 Eh ::
314
- # :: -> anisotropic ES 0.003924951393 Eh ::
315
- # :: -> anisotropic XC 0.040710819025 Eh ::
316
- # :: -> dispersion -0.088336282215 Eh ::
317
- # :: -> Gsolv -0.039236762590 Eh ::
318
- # :: -> Gelec -0.026665485874 Eh ::
319
- # :: -> Gsasa -0.012571276716 Eh ::
320
- # :: -> Ghb 0.000000000000 Eh ::
321
- # :: -> Gshift 0.000000000000 Eh ::
322
- # :: repulsion energy 1.614147283037 Eh ::
323
- # :: add. restraining 0.000000000000 Eh ::
324
- # :: total charge -0.000000000000 e ::
325
- # :::::::::::::::::::::::::::::::::::::::::::::::::::::
326
-
327
- # example gas.out
328
- # :::::::::::::::::::::::::::::::::::::::::::::::::::::
329
- # :: SUMMARY ::
330
- # :::::::::::::::::::::::::::::::::::::::::::::::::::::
331
- # :: total energy -119.473726280382 Eh ::
332
- # :: gradient norm 0.085445002241 Eh/a0 ::
333
- # :: HOMO-LUMO gap 2.562893747102 eV ::
334
- # ::.................................................::
335
- # :: SCC energy -121.087873563419 Eh ::
336
- # :: -> isotropic ES 0.152557320965 Eh ::
337
- # :: -> anisotropic ES 0.007343156635 Eh ::
338
- # :: -> anisotropic XC 0.039625076440 Eh ::
339
- # :: -> dispersion -0.088605122696 Eh ::
340
- # :: repulsion energy 1.614147283037 Eh ::
341
- # :: add. restraining 0.000000000000 Eh ::
342
- # :: total charge -0.000000000000 e ::
343
- # :::::::::::::::::::::::::::::::::::::::::::::::::::::
344
-
345
- if proc.returncode == 0:
346
- total_energy_solv = None
347
- total_energy_gas = None
348
-
349
- with open(solv_out_path, 'r') as f:
350
- for line in f:
351
- if 'total energy' in line:
352
- m = re.search(r"total energy\s+(?P<solv>[-+]?\d*\.?\d+)\s+Eh", line)
353
- total_energy_solv = float(m.group('solv'))
354
- with open(gas_out_path, 'r') as f:
355
- for line in f:
356
- if 'total energy' in line:
357
- m = re.search(r"total energy\s+(?P<gas>[-+]?\d*.?\d+)\s+Eh", line)
358
- total_energy_gas = float(m.group('gas'))
359
-
360
- if total_energy_solv and total_energy_gas:
361
- return (total_energy_solv - total_energy_gas) * hartree2kcalpermol
362
-
363
- return None
364
-
365
-
366
273
  def singlepoint(self, water: str | None = None, verbose: bool = False) -> SimpleNamespace:
367
274
  """Calculate single point energy.
368
275
 
369
276
  Total energy from xtb output in atomic units (Eh, hartree) is converted to kcal/mol.
370
277
 
278
+ Options:
279
+ ```sh
280
+ -c, --chrg INT
281
+ specify molecular charge as INT, overrides .CHRG file and xcontrol option
282
+
283
+ --scc, --sp
284
+ performs a single point calculation
285
+
286
+ --gfn INT
287
+ specify parametrisation of GFN-xTB (default = 2)
288
+
289
+ --json
290
+ write xtbout.json file
291
+
292
+ --alpb SOLVENT [STATE]
293
+ analytical linearized Poisson-Boltzmann (ALPB) model,
294
+ available solvents are acetone, acetonitrile, aniline, benzaldehyde,
295
+ benzene, ch2cl2, chcl3, cs2, dioxane, dmf, dmso, ether, ethylacetate, furane,
296
+ hexandecane, hexane, methanol, nitromethane, octanol, woctanol, phenol, toluene,
297
+ thf, water.
298
+ The solvent input is not case-sensitive. The Gsolv
299
+ reference state can be chosen as reference, bar1M, or gsolv (default).
300
+
301
+ -g, --gbsa SOLVENT [STATE]
302
+ generalized born (GB) model with solvent accessable surface (SASA) model,
303
+ available solvents are acetone, acetonitrile, benzene (only GFN1-xTB), CH2Cl2,
304
+ CHCl3, CS2, DMF (only GFN2-xTB), DMSO, ether, H2O, methanol,
305
+ n-hexane (only GFN2-xTB), THF and toluene.
306
+ The solvent input is not case-sensitive.
307
+ The Gsolv reference state can be chosen as reference, bar1M, or gsolv (default).
308
+
309
+ --cosmo SOLVENT/EPSILON
310
+ domain decomposition conductor-like screening model (ddCOSMO),
311
+ available solvents are all solvents that are available for alpb.
312
+ Additionally, the dielectric constant can be set manually or an ideal conductor
313
+ can be chosen by setting epsilon to infinity.
314
+
315
+ --tmcosmo SOLVENT/EPSILON
316
+ same as --cosmo, but uses TM convention for writing the .cosmo files.
317
+
318
+ --cpcmx SOLVENT
319
+ extended conduction-like polarizable continuum solvation model (CPCM-X),
320
+ available solvents are all solvents included in the Minnesota Solvation Database.
321
+ ```
322
+
371
323
  Args:
372
324
  water (str, optional) : water solvation model (choose 'gbsa' or 'alpb')
373
325
  alpb: ALPB solvation model (Analytical Linearized Poisson-Boltzmann).
@@ -389,8 +341,7 @@ $ cp -r xtb-dist/share /usr/local/ """)
389
341
  geometry.write(self.to_xyz())
390
342
 
391
343
  cmd = ['xtb', geometry_input_path.as_posix()]
392
-
393
- options = ['--gfn', '2', '--json']
344
+ options = ['-c', str(self.charge), '--sp', '--gfn', '2', '--json']
394
345
 
395
346
  if water is not None and isinstance(water, str):
396
347
  if water == 'gbsa':
@@ -408,7 +359,6 @@ $ cp -r xtb-dist/share /usr/local/ """)
408
359
  # 'xtbout.json', 'xtbrestart', 'xtbtopo.mol', 'charges', and 'wbo' files will be
409
360
  # created in the current working directory.
410
361
  proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
411
-
412
362
  # if proc.returncode == 0:
413
363
  # print("Standard Output:")
414
364
  # print(proc.stdout)
@@ -438,6 +388,8 @@ $ cp -r xtb-dist/share /usr/local/ """)
438
388
  Wiberg_bond_orders = self.load_wbo(wbo_path)
439
389
 
440
390
  return SimpleNamespace(
391
+ natoms = self.natoms,
392
+ charge = self.charge,
441
393
  PE = datadict['total energy'] * hartree2kcalpermol,
442
394
  Gsolv = Gsolv,
443
395
  charges = datadict['partial charges'],
@@ -452,12 +404,29 @@ $ cp -r xtb-dist/share /usr/local/ """)
452
404
  def optimize(self, water: str | None = None, verbose: bool = False) -> SimpleNamespace:
453
405
  """Optimize geometry.
454
406
 
455
- Fortran runtime errror:
456
- At line 852 of file ../src/optimizer.f90 (unit = 6, file = 'stdout')
457
- Fortran runtime error: Missing comma between descriptors
458
- (1x,"("f7.2"%)")
459
- ^
460
- Error termination.
407
+ Options:
408
+ ```sh
409
+ -c, --chrg INT
410
+ specify molecular charge as INT, overrides .CHRG file and xcontrol option
411
+ -o, --opt [LEVEL]
412
+ call ancopt(3) to perform a geometry optimization, levels from crude, sloppy,
413
+ loose, normal (default), tight, verytight to extreme can be chosen
414
+ --gfn INT
415
+ specify parametrisation of GFN-xTB (default = 2)
416
+ --json
417
+ write xtbout.json file
418
+ ```
419
+
420
+ Notes:
421
+ Conda installed xtb has Fortran runtime error when optimizing geometry.
422
+ ```sh
423
+ Fortran runtime errror:
424
+ At line 852 of file ../src/optimizer.f90 (unit = 6, file = 'stdout')
425
+ Fortran runtime error: Missing comma between descriptors
426
+ (1x,"("f7.2"%)")
427
+ ^
428
+ Error termination.
429
+ ```
461
430
 
462
431
  Args:
463
432
  water (str, optional) : water solvation model (choose 'gbsa' or 'alpb')
@@ -479,8 +448,7 @@ $ cp -r xtb-dist/share /usr/local/ """)
479
448
  geometry.write(self.to_xyz())
480
449
 
481
450
  cmd = ['xtb', geometry_input_path.as_posix()]
482
-
483
- options = ['--opt', '--gfn', '2', '--json']
451
+ options = ['-c', str(self.charge), '-o', 'normal', '--gfn', '2', '--json']
484
452
 
485
453
  if water is not None and isinstance(water, str):
486
454
  if water == 'gbsa':
@@ -503,6 +471,8 @@ $ cp -r xtb-dist/share /usr/local/ """)
503
471
  rdmol_opt = self.load_xyz(geometry_output_path)
504
472
 
505
473
  return SimpleNamespace(
474
+ natoms = self.natoms,
475
+ charge = self.charge,
506
476
  PE = datadict['total energy'] * hartree2kcalpermol,
507
477
  charges = datadict['partial charges'],
508
478
  wbo = Wiberg_bond_orders,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rdworks
3
- Version: 0.50.1
3
+ Version: 0.52.1
4
4
  Summary: Routine tasks built on RDKit and other tools
5
5
  Author-email: Sung-Hun Bae <sunghun.bae@gmail.com>
6
6
  Maintainer-email: Sung-Hun Bae <sunghun.bae@gmail.com>
@@ -1,13 +1,14 @@
1
- rdworks/__init__.py,sha256=cELiDVknzDSz59Afufwk8LssqIuPLWLsxO73NISKfLY,1391
2
- rdworks/conf.py,sha256=iQLb3Qg3pjGiiMVMJ5-d57BC1id3zxEhEGlhhrLrA_c,34162
1
+ rdworks/__init__.py,sha256=nSkNkfvjtAeom2f5SYdS-XCnglYeC-wcGuGVubrv3nQ,1391
2
+ rdworks/conf.py,sha256=eH_a3ywmmJiPtnvgk86ykurYOx879AHg80-Dn8z1X70,36379
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=UPLLJbfn1cPhcedrGW7tL_bk1QpG3BfpjCOhop0tmBY,68663
7
+ rdworks/microstates.py,sha256=T206JgeB3d23MX3sRCrxVj2arxlSILYecBTKaD1VcoE,5109
8
+ rdworks/mol.py,sha256=-zjAsBETNUbP4_n8p6how40NhZB24icMYhas1kYPqCc,70064
8
9
  rdworks/mollibr.py,sha256=X4UBO6Ga-QmNS7RwUiaDYAx0Q5hnWs71yTkEpH02Qb4,37696
9
10
  rdworks/pka.py,sha256=NVJVfpcNEMlX5QRyLBgUM7GIT7VMjO-llAR4LWc8J2c,1656
10
- rdworks/readin.py,sha256=0bnVcZcAmSLqc6zu1mYcv0LdBv2agQfOpKGwpSRL9VE,11742
11
+ rdworks/readin.py,sha256=b1BHchQMC5EgQd3C05n72t_aa_9u0iKQWyyIqjyfkPc,11809
11
12
  rdworks/rgroup.py,sha256=ivF2gzmRtt339rxEnkv2KfnCs0CUdBbnSje7Y54rtFI,57996
12
13
  rdworks/scaffold.py,sha256=60T5YacyxZsEpDo_J5Qxulm2YNQO4EQR8PcNUwjn1QU,22026
13
14
  rdworks/std.py,sha256=qOVS_lGogueLKh4rsbrsYIMR0c7z_xh6BqLEzD4X9sE,7938
@@ -65,9 +66,9 @@ rdworks/predefined/misc/reactive-part-2.xml,sha256=0vNTMwWrrQmxBpbgbyRHx8sVs83cq
65
66
  rdworks/predefined/misc/reactive-part-3.xml,sha256=LgWHSEbRTVmgBoIO45xbTo1xQJs0Xu51j3JnIapRYo4,3094
66
67
  rdworks/predefined/misc/reactive.xml,sha256=syedoQ6VYUfRLnxy99ObuDniJ_a_WhrWAJbTKFfJ6VY,11248
67
68
  rdworks/xtb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
- rdworks/xtb/wrapper.py,sha256=w_SX3q7D4_peHERFzONesG8c-a6UTRzfBLx313D8rNE,23638
69
- rdworks-0.50.1.dist-info/licenses/LICENSE,sha256=UOkJSBqYyQUvtCp7a-vdCANeEcLE2dnTie_eB1By5SY,1074
70
- rdworks-0.50.1.dist-info/METADATA,sha256=Rh6pJzHolql4Q3OJot3eO8OQ7K2R9nPqpPc3Vwt3l0Y,1967
71
- rdworks-0.50.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
- rdworks-0.50.1.dist-info/top_level.txt,sha256=05C98HbvBK2axUBogC_hAT_CdpOeQYGnQ6vRAgawr8s,8
73
- rdworks-0.50.1.dist-info/RECORD,,
69
+ rdworks/xtb/wrapper.py,sha256=p_ddunnjtxe3F2yN7RC2mvSUDnw7fNBhGm1bZVMAWAE,21901
70
+ rdworks-0.52.1.dist-info/licenses/LICENSE,sha256=UOkJSBqYyQUvtCp7a-vdCANeEcLE2dnTie_eB1By5SY,1074
71
+ rdworks-0.52.1.dist-info/METADATA,sha256=M47Khc8DU4es8jrzYzp4x4ZyM6ap6NwHrmbJqw5lK5Y,1967
72
+ rdworks-0.52.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
73
+ rdworks-0.52.1.dist-info/top_level.txt,sha256=05C98HbvBK2axUBogC_hAT_CdpOeQYGnQ6vRAgawr8s,8
74
+ rdworks-0.52.1.dist-info/RECORD,,