rdworks 0.43.3__py3-none-any.whl → 0.45.2__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.43.3'
1
+ __version__ = '0.45.2'
2
2
 
3
3
  from rdworks.conf import Conf
4
4
  from rdworks.mol import Mol
rdworks/conf.py CHANGED
@@ -210,7 +210,7 @@ class Conf:
210
210
 
211
211
  if calculator.lower() == 'xTB'.lower():
212
212
  water = kwargs.get('water', None)
213
- result = GFN2xTB(self.rdmol).optimize(water=water)
213
+ results = GFN2xTB(self.rdmol).optimize(water=water)
214
214
  # SimpleNamespace(
215
215
  # PE = datadict['total energy'] * hartree2kcalpermol,
216
216
  # charges = datadict['partial charges'],
@@ -218,8 +218,8 @@ class Conf:
218
218
  # geometry = rdmol_opt,
219
219
  # )
220
220
  try:
221
- self.rdmol = result.geometry
222
- PE_final = result.PE
221
+ self.rdmol = results.geometry
222
+ PE_final = results.PE
223
223
  retcode = 0
224
224
  except:
225
225
  retcode = 1
@@ -382,7 +382,14 @@ class Conf:
382
382
  if isinstance(calculator, str):
383
383
  if calculator.lower() == 'xTB'.lower():
384
384
  water = kwargs.get('water', None)
385
- PE = GFN2xTB(self.rdmol).singlepoint(water=water)
385
+ results = GFN2xTB(self.rdmol).singlepoint(water=water)
386
+ # SimpleNamespace(
387
+ # PE = datadict['total energy'] * hartree2kcalpermol,
388
+ # Gsolv = Gsolv,
389
+ # charges = datadict['partial charges'],
390
+ # wbo = Wiberg_bond_orders,
391
+ # )
392
+ PE = results.PE
386
393
 
387
394
  elif calculator.lower() == 'MMFF94'.lower() or calculator.lower() == 'MMFF'.lower():
388
395
  mp = Chem.rdForceFieldHelpers.MMFFGetMoleculeProperties(self.rdmol, mmffVariant='MMFF94')
@@ -677,6 +684,42 @@ class Conf:
677
684
  return '\n'.join(lines)
678
685
 
679
686
 
687
+ def to_turbomole_coord(self, bohr: bool = False) -> str:
688
+ """Returns TURBOMOLE coord file formatted strings.
689
+
690
+ Turbomole coord file format:
691
+
692
+ - It starts with the keyword `$coord`.
693
+ - Each line after the $coord line specifies an atom, consisting of:
694
+ - Three real numbers representing the Cartesian coordinates (x, y, z).
695
+ - A string for the element name.
696
+ - Optional: an "f" label at the end to indicate that the atom's coordinates are frozen during optimization.
697
+ - Coordinates can be given in Bohr (default), Ångström (`$coord angs`), or fractional coordinates (`$coord frac`).
698
+ - Optional data groups like periodicity (`$periodic`), lattice parameters (`$lattice`), and cell parameters (`$cell`) can also be included.
699
+ - Regarding precision:
700
+ The precision of the coordinates is crucial for accurate calculations, especially geometry optimizations.
701
+ Tools like the TURBOMOLEOptimizer might check for differences in atomic positions with a tolerance of 1e-13.
702
+
703
+ Args:
704
+ bohr (bool): whether to use Bohr units of the coordinates. Defaults to False.
705
+ Otherwise, Angstrom units will be used.
706
+
707
+ Returns:
708
+ str: TURBOMOLE coord formatted file.
709
+ """
710
+ if bohr:
711
+ lines = ["$coord"]
712
+ else:
713
+ lines = ["$coord angs"]
714
+
715
+ for (x, y, z), e in zip(self.positions(), self.symbols()):
716
+ lines.append(f"{x:20.15f} {y:20.15f} {z:20.15f} {e}")
717
+
718
+ lines.append("$end")
719
+
720
+ return '\n'.join(lines)
721
+
722
+
680
723
  def to_sdf(self, props:bool=True) -> str:
681
724
  """Returns the SDF-formatted strings.
682
725
 
rdworks/xtb/wrapper.py CHANGED
@@ -4,6 +4,8 @@ import subprocess
4
4
  import json
5
5
  import tempfile
6
6
  import logging
7
+ import shutil
8
+ import re
7
9
 
8
10
  from pathlib import Path
9
11
  from types import SimpleNamespace
@@ -12,7 +14,7 @@ from rdkit import Chem
12
14
  from rdkit.Geometry import Point3D
13
15
 
14
16
 
15
- main_logger = logging.getLogger()
17
+ logger = logging.getLogger()
16
18
 
17
19
  # In ASE, the default energy unit is eV (electron volt).
18
20
  # It will be converted to kcal/mol
@@ -23,13 +25,15 @@ ev2kcalpermol = 23.060547830619026
23
25
 
24
26
 
25
27
  class GFN2xTB:
26
- def __init__(self, molecule: Chem.Mol | None = None, ncores: int = 4):
27
- if isinstance(molecule, Chem.Mol):
28
- assert molecule.GetConformer().Is3D(), "requires 3D coordinates"
29
- self.rdmol = molecule
30
- self.natoms = molecule.GetNumAtoms()
31
- self.symbols = [ atom.GetSymbol() for atom in molecule.GetAtoms() ]
32
- self.positions = molecule.GetConformer().GetPositions().tolist()
28
+ def __init__(self, molecule: Chem.Mol, ncores: int = 8):
29
+ assert isinstance(molecule, Chem.Mol), "molecule is not rdkit.Chem.Mol type"
30
+ assert molecule.GetConformer().Is3D(), "molecule is not a 3D conformer"
31
+ assert self.is_xtb_ready(), "xtb is not accessible"
32
+
33
+ self.rdmol = molecule
34
+ self.natoms = molecule.GetNumAtoms()
35
+ self.symbols = [ atom.GetSymbol() for atom in molecule.GetAtoms() ]
36
+ self.positions = molecule.GetConformer().GetPositions().tolist()
33
37
 
34
38
  # Parallelisation
35
39
  os.environ['OMP_STACKSIZE'] = '4G'
@@ -58,6 +62,45 @@ class GFN2xTB:
58
62
  return None
59
63
 
60
64
 
65
+ def is_xtb_ready(self, cmd: str = 'xtb') -> bool:
66
+ """Check if xtb is available.
67
+
68
+ Returns:
69
+ bool: True if `xtb` is available, False otherwise.
70
+ """
71
+ return shutil.which(cmd) is not None
72
+
73
+
74
+ def is_cpx_ready(self, cmd: str = 'cpx') -> bool:
75
+ """Checks if the CPCM-X command-line tool, `cpx`, is accessible in the system.
76
+
77
+ Returns:
78
+ bool: True if the cpx is found, False otherwise.
79
+ """
80
+ return shutil.which(cmd) is not None
81
+
82
+
83
+ def is_cpcmx_ready(self) -> bool:
84
+ """Checks if xtb works with the `--cpcmx` option.
85
+
86
+ xtb distributed by the conda does not include CPCM-X function (as of June 17, 2025).
87
+ xtb installed from the github source codes by using meson and ninja includes it.
88
+
89
+ Returns:
90
+ bool: True if the --cpcmx option is working, False otherwise.
91
+ """
92
+ cmd = ['xtb', '--cpcmx']
93
+ proc = subprocess.run(cmd, capture_output=True, text=True)
94
+ # we are expecting an error because no input file is given
95
+ assert proc.returncode != 0
96
+ for line in proc.stdout.split('\n'):
97
+ line = line.strip()
98
+ if 'CPCM-X library was not included' in line:
99
+ return False
100
+
101
+ return True
102
+
103
+
61
104
  def to_xyz(self) -> str:
62
105
  """Export to XYZ formatted string.
63
106
 
@@ -71,17 +114,53 @@ class GFN2xTB:
71
114
  return '\n'.join(lines)
72
115
 
73
116
 
74
- def load_xyz(self, geometry_path: Path) -> Chem.Mol:
117
+ def to_turbomole_coord(self, bohr: bool = False) -> str:
118
+ """Returns TURBOMOLE coord file formatted strings.
119
+
120
+ Turbomole coord file format:
121
+
122
+ - It starts with the keyword `$coord`.
123
+ - Each line after the $coord line specifies an atom, consisting of:
124
+ - Three real numbers representing the Cartesian coordinates (x, y, z).
125
+ - A string for the element name.
126
+ - Optional: an "f" label at the end to indicate that the atom's coordinates are frozen during optimization.
127
+ - Coordinates can be given in Bohr (default), Ångström (`$coord angs`), or fractional coordinates (`$coord frac`).
128
+ - Optional data groups like periodicity (`$periodic`), lattice parameters (`$lattice`), and cell parameters (`$cell`) can also be included.
129
+ - Regarding precision:
130
+ The precision of the coordinates is crucial for accurate calculations, especially geometry optimizations.
131
+ Tools like the TURBOMOLEOptimizer might check for differences in atomic positions with a tolerance of 1e-13.
132
+
133
+ Args:
134
+ bohr (bool): whether to use Bohr units of the coordinates. Defaults to False.
135
+ Otherwise, Angstrom units will be used.
136
+
137
+ Returns:
138
+ str: TURBOMOLE coord formatted file.
139
+ """
140
+ if bohr:
141
+ lines = ["$coord"]
142
+ else:
143
+ lines = ["$coord angs"]
144
+
145
+ for (x, y, z), e in zip(self.positions, self.symbols):
146
+ lines.append(f"{x:20.15f} {y:20.15f} {z:20.15f} {e}")
147
+
148
+ lines.append("$end")
149
+
150
+ return '\n'.join(lines)
151
+
152
+
153
+ def load_xyz(self, geometry_input_path: Path) -> Chem.Mol:
75
154
  """Load geometry.
76
155
 
77
156
  Args:
78
- geometry_path (Path): pathlib.Path to the xyz
157
+ geometry_input_path (Path): pathlib.Path to the xyz
79
158
 
80
159
  Returns:
81
160
  Chem.Mol: rdkit Chem.Mol object.
82
161
  """
83
162
  rdmol_opt = Chem.Mol(self.rdmol)
84
- with open(geometry_path, 'r') as f:
163
+ with open(geometry_input_path, 'r') as f:
85
164
  for lineno, line in enumerate(f):
86
165
  if lineno == 0:
87
166
  assert int(line.strip()) == self.natoms
@@ -100,6 +179,8 @@ class GFN2xTB:
100
179
  def load_wbo(self, wbo_path: Path) -> dict[tuple[int, int], float]:
101
180
  """Load Wiberg bond order.
102
181
 
182
+ singlepoint() creates a wbo output file.
183
+
103
184
  Args:
104
185
  wbo_path (Path): path to the wbo file.
105
186
 
@@ -125,6 +206,104 @@ class GFN2xTB:
125
206
  return Wiberg_bond_orders
126
207
 
127
208
 
209
+ def cpx(self, verbose: bool = False) -> float | None:
210
+ """Runs cpx and returns Gsolv (kcal/mol)
211
+
212
+ Warning:
213
+ Solvation energy obtained from `xtb --cpcmx water` differs from
214
+ `cpx --solvent water` (difference between gas.out and solv.out in terms of total energy).
215
+ There are other correction terms not clearly defined in the output files.
216
+ So, this method is not reliable and should be discarded
217
+
218
+ Returns:
219
+ float or None: Gsolv energy in kcal/mol or None.
220
+ """
221
+ with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
222
+ workdir = Path(temp_dir)
223
+ if verbose:
224
+ logger.info(f'xtb.cpx workdir= {temp_dir}')
225
+
226
+ geometry_input_path = workdir / 'coord'
227
+ geometry_output_path = workdir / 'xtbtopo.mol'
228
+ gas_out_path = workdir / 'gas.out'
229
+ solv_out_path = workdir / 'solv.out'
230
+ wbo_path = workdir / 'wbo'
231
+
232
+ with open(geometry_input_path, 'w') as f:
233
+ f.write(self.to_turbomole_coord())
234
+
235
+ cmd = ['cpx']
236
+ options = ['--solvent', 'water']
237
+
238
+ proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
239
+ # cpx creates the following files:
240
+ # charges gas.energy solute_sigma.txt solvent_sigma.txt xtbtopo.mol
241
+ # coord gas.out solute_sigma3.txt solvent_sigma3.txt
242
+ # error solute.cosmo solv.out wbo
243
+
244
+ # example of solv.out
245
+ # :::::::::::::::::::::::::::::::::::::::::::::::::::::
246
+ # :: SUMMARY ::
247
+ # :::::::::::::::::::::::::::::::::::::::::::::::::::::
248
+ # :: total energy -119.507131639760 Eh ::
249
+ # :: w/o Gsasa/hb/shift -119.494560363045 Eh ::
250
+ # :: gradient norm 0.084154442395 Eh/a0 ::
251
+ # :: HOMO-LUMO gap 2.966157362876 eV ::
252
+ # ::.................................................::
253
+ # :: SCC energy -121.121278922798 Eh ::
254
+ # :: -> isotropic ES 0.180705208303 Eh ::
255
+ # :: -> anisotropic ES 0.003924951393 Eh ::
256
+ # :: -> anisotropic XC 0.040710819025 Eh ::
257
+ # :: -> dispersion -0.088336282215 Eh ::
258
+ # :: -> Gsolv -0.039236762590 Eh ::
259
+ # :: -> Gelec -0.026665485874 Eh ::
260
+ # :: -> Gsasa -0.012571276716 Eh ::
261
+ # :: -> Ghb 0.000000000000 Eh ::
262
+ # :: -> Gshift 0.000000000000 Eh ::
263
+ # :: repulsion energy 1.614147283037 Eh ::
264
+ # :: add. restraining 0.000000000000 Eh ::
265
+ # :: total charge -0.000000000000 e ::
266
+ # :::::::::::::::::::::::::::::::::::::::::::::::::::::
267
+
268
+ # example gas.out
269
+ # :::::::::::::::::::::::::::::::::::::::::::::::::::::
270
+ # :: SUMMARY ::
271
+ # :::::::::::::::::::::::::::::::::::::::::::::::::::::
272
+ # :: total energy -119.473726280382 Eh ::
273
+ # :: gradient norm 0.085445002241 Eh/a0 ::
274
+ # :: HOMO-LUMO gap 2.562893747102 eV ::
275
+ # ::.................................................::
276
+ # :: SCC energy -121.087873563419 Eh ::
277
+ # :: -> isotropic ES 0.152557320965 Eh ::
278
+ # :: -> anisotropic ES 0.007343156635 Eh ::
279
+ # :: -> anisotropic XC 0.039625076440 Eh ::
280
+ # :: -> dispersion -0.088605122696 Eh ::
281
+ # :: repulsion energy 1.614147283037 Eh ::
282
+ # :: add. restraining 0.000000000000 Eh ::
283
+ # :: total charge -0.000000000000 e ::
284
+ # :::::::::::::::::::::::::::::::::::::::::::::::::::::
285
+
286
+ if proc.returncode == 0:
287
+ total_energy_solv = None
288
+ total_energy_gas = None
289
+
290
+ with open(solv_out_path, 'r') as f:
291
+ for line in f:
292
+ if 'total energy' in line:
293
+ m = re.search(r"total energy\s+(?P<solv>[-+]?\d*\.?\d+)\s+Eh", line)
294
+ total_energy_solv = float(m.group('solv'))
295
+ with open(gas_out_path, 'r') as f:
296
+ for line in f:
297
+ if 'total energy' in line:
298
+ m = re.search(r"total energy\s+(?P<gas>[-+]?\d*.?\d+)\s+Eh", line)
299
+ total_energy_gas = float(m.group('gas'))
300
+
301
+ if total_energy_solv and total_energy_gas:
302
+ return (total_energy_solv - total_energy_gas) * hartree2kcalpermol
303
+
304
+ return None
305
+
306
+
128
307
  def singlepoint(self, water: str | None = None, verbose: bool = False) -> SimpleNamespace:
129
308
  """Calculate single point energy.
130
309
 
@@ -142,25 +321,33 @@ class GFN2xTB:
142
321
  with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
143
322
  workdir = Path(temp_dir)
144
323
  if verbose:
145
- main_logger.info(f'xtb.singlepoint workdir= {temp_dir}')
324
+ logger.info(f'xtb.singlepoint workdir= {temp_dir}')
146
325
 
147
- geometry_path = workdir / 'geometry.xyz'
326
+ geometry_input_path = workdir / 'geometry.xyz'
148
327
  xtbout_path = workdir / 'xtbout.json'
328
+ stdout_path = workdir / 'fort.6'
149
329
  wbo_path = workdir / 'wbo'
330
+ geometry_output_path = workdir / 'xtbtopo.mol'
150
331
 
151
- with open(geometry_path, 'w') as geometry:
332
+ with open(geometry_input_path, 'w') as geometry:
152
333
  geometry.write(self.to_xyz())
153
334
 
154
- cmd = ['xtb', geometry_path.as_posix()]
335
+ cmd = ['xtb', geometry_input_path.as_posix()]
155
336
 
156
337
  options = ['--gfn', '2', '--json']
157
338
 
339
+ Gsolv = None
340
+
158
341
  if water is not None and isinstance(water, str):
159
342
  if water == 'gbsa':
160
343
  options += ['--gbsa', 'H2O']
344
+ # it does not provide Gsolv contribution to the total energy
161
345
  elif water == 'alpb':
162
346
  options += ['--alpb', 'water']
163
-
347
+ # it does not provide Gsolv contribution to the total energy
348
+ elif water == 'cpcmx' and self.is_cpcmx_ready():
349
+ options += ['--cpcmx', 'water']
350
+
164
351
  # 'xtbout.json', 'xtbrestart', 'xtbtopo.mol', 'charges', and 'wbo' files will be
165
352
  # created in the current working directory.
166
353
  proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
@@ -172,16 +359,31 @@ class GFN2xTB:
172
359
  # print("Error:")
173
360
  # print(proc.stderr)
174
361
 
175
- if proc.returncode == 0 and xtbout_path.is_file():
176
- with open(xtbout_path, 'r') as f:
177
- datadict = json.load(f) # takes the file object as input
178
-
362
+ if proc.returncode == 0:
363
+ if xtbout_path.is_file():
364
+ with open(xtbout_path, 'r') as f:
365
+ datadict = json.load(f) # takes the file object as input
366
+
367
+ if (water is not None) and (Gsolv is None) and stdout_path.is_file():
368
+ # Free Energy contributions: [Eh] [kcal/mol]
369
+ # -------------------------------------------------------------------------
370
+ # solvation free energy (dG_solv): -0.92587E-03 -0.58099
371
+ # gas phase energy (E) -0.52068E+01
372
+ # -------------------------------------------------------------------------
373
+ # total free energy (dG) -0.52077E+01
374
+ with open(stdout_path, 'r') as f:
375
+ for line in f:
376
+ if 'solvation free energy' in line:
377
+ m = re.search(r"solvation free energy \(dG_solv\)\:\s+[-+]?\d*\.?\d+E[-+]?\d*\s+(?P<kcalpermol>[-+]?\d*\.?\d+)", line)
378
+ Gsolv = float(m.group('kcalpermol'))
379
+
179
380
  Wiberg_bond_orders = self.load_wbo(wbo_path)
180
381
 
181
382
  return SimpleNamespace(
182
- PE = datadict['total energy'] * hartree2kcalpermol,
383
+ PE = datadict['total energy'] * hartree2kcalpermol,
384
+ Gsolv = Gsolv,
183
385
  charges = datadict['partial charges'],
184
- wbo = Wiberg_bond_orders,
386
+ wbo = Wiberg_bond_orders,
185
387
  )
186
388
 
187
389
  # something went wrong if it reaches here
@@ -210,17 +412,17 @@ class GFN2xTB:
210
412
  with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
211
413
  workdir = Path(temp_dir)
212
414
  if verbose:
213
- main_logger.info(f'xtb.optimize workdir= {temp_dir}')
415
+ logger.info(f'xtb.optimize workdir= {temp_dir}')
214
416
 
215
- geometry_path = workdir / 'geometry.xyz'
417
+ geometry_input_path = workdir / 'geometry.xyz'
216
418
  xtbout_path = workdir / 'xtbout.json'
217
- xtbopt_path = workdir / 'xtbopt.xyz'
419
+ geometry_output_path = workdir / 'xtbopt.xyz'
218
420
  wbo_path = workdir / 'wbo'
219
421
 
220
- with open(geometry_path, 'w') as geometry:
422
+ with open(geometry_input_path, 'w') as geometry:
221
423
  geometry.write(self.to_xyz())
222
424
 
223
- cmd = ['xtb', geometry_path.as_posix()]
425
+ cmd = ['xtb', geometry_input_path.as_posix()]
224
426
 
225
427
  options = ['--opt', '--gfn', '2', '--json']
226
428
 
@@ -229,6 +431,8 @@ class GFN2xTB:
229
431
  options += ['--gbsa', 'H2O']
230
432
  elif water == 'alpb':
231
433
  options += ['--alpb', 'water']
434
+ elif water == 'cpcmx':
435
+ logger.warning('optimize with --cpcmx option is not implemented in xtb yet')
232
436
 
233
437
  proc = subprocess.run(cmd + options, cwd=temp_dir, capture_output=True, text=True)
234
438
 
@@ -237,7 +441,7 @@ class GFN2xTB:
237
441
  datadict = json.load(f) # takes the file object as input
238
442
 
239
443
  Wiberg_bond_orders = self.load_wbo(wbo_path)
240
- rdmol_opt = self.load_xyz(xtbopt_path)
444
+ rdmol_opt = self.load_xyz(geometry_output_path)
241
445
 
242
446
  return SimpleNamespace(
243
447
  PE = datadict['total energy'] * hartree2kcalpermol,
@@ -276,15 +480,15 @@ class GFN2xTB:
276
480
  with tempfile.TemporaryDirectory() as temp_dir: # tmpdir is a string
277
481
  workdir = Path(temp_dir)
278
482
  if verbose:
279
- main_logger.info(f'xtb.optimize workdir= {temp_dir}')
483
+ logger.info(f'xtb.optimize workdir= {temp_dir}')
280
484
 
281
- geometry_path = workdir / 'geometry.xyz'
485
+ geometry_input_path = workdir / 'geometry.xyz'
282
486
  xtb_esp_dat = workdir / 'xtb_esp_dat'
283
487
 
284
- with open(geometry_path, 'w') as geometry:
488
+ with open(geometry_input_path, 'w') as geometry:
285
489
  geometry.write(self.to_xyz())
286
490
 
287
- cmd = ['xtb', geometry_path.as_posix()]
491
+ cmd = ['xtb', geometry_input_path.as_posix()]
288
492
 
289
493
  options = ['--esp', '--gfn', '2']
290
494
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rdworks
3
- Version: 0.43.3
3
+ Version: 0.45.2
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,5 +1,5 @@
1
- rdworks/__init__.py,sha256=0vesrJlo_AqSgeVT7zQFhvL7caqZ6YIsv7gUB1O9nAU,1368
2
- rdworks/conf.py,sha256=CvG_X2dYUt02HKei9JqA9K_ZttzJXqXEozD1cLAAkfs,32122
1
+ rdworks/__init__.py,sha256=SK_EU8Z7TY12w-fszqAQN03x6MydoGabg98zBOetlLI,1368
2
+ rdworks/conf.py,sha256=iQLb3Qg3pjGiiMVMJ5-d57BC1id3zxEhEGlhhrLrA_c,34162
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=5oIjMRpkX792RIpEEE2Ir96icfFaN_h21mSihhfQPAw,6713
@@ -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=I0nW89vlJZ5Za5pCjIpjsEOFbTm7HpeNGiPgssheWn8,11350
69
- rdworks-0.43.3.dist-info/licenses/LICENSE,sha256=UOkJSBqYyQUvtCp7a-vdCANeEcLE2dnTie_eB1By5SY,1074
70
- rdworks-0.43.3.dist-info/METADATA,sha256=03DcKDuVgWC7eW7MZShOW9zKfQBBqGqrHYFxvsucNgE,1967
71
- rdworks-0.43.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
- rdworks-0.43.3.dist-info/top_level.txt,sha256=05C98HbvBK2axUBogC_hAT_CdpOeQYGnQ6vRAgawr8s,8
73
- rdworks-0.43.3.dist-info/RECORD,,
68
+ rdworks/xtb/wrapper.py,sha256=GqcseDk_sgmKbmKvDvObjNTk0tvAWYd7ZxjnLq0uVK0,21596
69
+ rdworks-0.45.2.dist-info/licenses/LICENSE,sha256=UOkJSBqYyQUvtCp7a-vdCANeEcLE2dnTie_eB1By5SY,1074
70
+ rdworks-0.45.2.dist-info/METADATA,sha256=DfyxepI-h3XBWrwQzzCLVQWBXs-mc5snQ4LIKbGzW4w,1967
71
+ rdworks-0.45.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
+ rdworks-0.45.2.dist-info/top_level.txt,sha256=05C98HbvBK2axUBogC_hAT_CdpOeQYGnQ6vRAgawr8s,8
73
+ rdworks-0.45.2.dist-info/RECORD,,