rdworks 0.36.4__tar.gz → 0.37.1__tar.gz

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.
Files changed (84) hide show
  1. {rdworks-0.36.4 → rdworks-0.37.1}/PKG-INFO +1 -1
  2. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/__init__.py +1 -1
  3. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/conf.py +133 -7
  4. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/mol.py +36 -95
  5. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/std.py +2 -0
  6. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks.egg-info/PKG-INFO +1 -1
  7. {rdworks-0.36.4 → rdworks-0.37.1}/tests/test_basics.py +3 -0
  8. {rdworks-0.36.4 → rdworks-0.37.1}/LICENSE +0 -0
  9. {rdworks-0.36.4 → rdworks-0.37.1}/README.md +0 -0
  10. {rdworks-0.36.4 → rdworks-0.37.1}/pyproject.toml +0 -0
  11. {rdworks-0.36.4 → rdworks-0.37.1}/setup.cfg +0 -0
  12. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/autograph/__init__.py +0 -0
  13. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/autograph/autograph.py +0 -0
  14. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/autograph/centroid.py +0 -0
  15. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/autograph/dynamictreecut.py +0 -0
  16. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/autograph/nmrclust.py +0 -0
  17. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/autograph/rckmeans.py +0 -0
  18. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/bitqt/__init__.py +0 -0
  19. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/bitqt/bitqt.py +0 -0
  20. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/descriptor.py +0 -0
  21. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/display.py +0 -0
  22. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/ionized.py +0 -0
  23. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/matchedseries.py +0 -0
  24. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/mollibr.py +0 -0
  25. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/pka.py +0 -0
  26. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Asinex_fragment.xml +0 -0
  27. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Astex_RO3.xml +0 -0
  28. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Baell2010_PAINS/Baell2010A.xml +0 -0
  29. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Baell2010_PAINS/Baell2010B.xml +0 -0
  30. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Baell2010_PAINS/Baell2010C.xml +0 -0
  31. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Baell2010_PAINS/PAINS-less-than-015-hits.xml +0 -0
  32. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Baell2010_PAINS/PAINS-less-than-150-hits.xml +0 -0
  33. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Baell2010_PAINS/PAINS-more-than-150-hits.xml +0 -0
  34. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Baell2010_PAINS/makexml.py +0 -0
  35. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Brenk2008_Dundee/makexml.py +0 -0
  36. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/CNS.xml +0 -0
  37. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ChEMBL_Walters/BMS.xml +0 -0
  38. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ChEMBL_Walters/Dundee.xml +0 -0
  39. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ChEMBL_Walters/Glaxo.xml +0 -0
  40. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ChEMBL_Walters/Inpharmatica.xml +0 -0
  41. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ChEMBL_Walters/LINT.xml +0 -0
  42. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ChEMBL_Walters/MLSMR.xml +0 -0
  43. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ChEMBL_Walters/PAINS.xml +0 -0
  44. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ChEMBL_Walters/SureChEMBL.xml +0 -0
  45. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ChEMBL_Walters/makexml.py +0 -0
  46. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Hann1999_Glaxo/Hann1999.xml +0 -0
  47. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Hann1999_Glaxo/Hann1999Acid.xml +0 -0
  48. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Hann1999_Glaxo/Hann1999Base.xml +0 -0
  49. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Hann1999_Glaxo/Hann1999ElPh.xml +0 -0
  50. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Hann1999_Glaxo/Hann1999NuPh.xml +0 -0
  51. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Hann1999_Glaxo/makexml.py +0 -0
  52. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Kazius2005/Kazius2005.xml +0 -0
  53. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/Kazius2005/makexml.py +0 -0
  54. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ZINC_druglike.xml +0 -0
  55. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ZINC_fragment.xml +0 -0
  56. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ZINC_leadlike.xml +0 -0
  57. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/fragment.xml +0 -0
  58. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ionized/simple_smarts_pattern.csv +0 -0
  59. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/ionized/smarts_pattern.csv +0 -0
  60. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/misc/makexml.py +0 -0
  61. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/misc/reactive-part-2.xml +0 -0
  62. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/misc/reactive-part-3.xml +0 -0
  63. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/predefined/misc/reactive.xml +0 -0
  64. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/readin.py +0 -0
  65. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/rgroup.py +0 -0
  66. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/scaffold.py +0 -0
  67. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/stereoisomers.py +0 -0
  68. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/tautomers.py +0 -0
  69. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/torsion.py +0 -0
  70. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/units.py +0 -0
  71. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/utils.py +0 -0
  72. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/xml.py +0 -0
  73. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/xtb/__init__.py +0 -0
  74. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks/xtb/wrapper.py +0 -0
  75. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks.egg-info/SOURCES.txt +0 -0
  76. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks.egg-info/dependency_links.txt +0 -0
  77. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks.egg-info/requires.txt +0 -0
  78. {rdworks-0.36.4 → rdworks-0.37.1}/src/rdworks.egg-info/top_level.txt +0 -0
  79. {rdworks-0.36.4 → rdworks-0.37.1}/tests/test_decimals.py +0 -0
  80. {rdworks-0.36.4 → rdworks-0.37.1}/tests/test_gypsumdl.py +0 -0
  81. {rdworks-0.36.4 → rdworks-0.37.1}/tests/test_iupac_name.py +0 -0
  82. {rdworks-0.36.4 → rdworks-0.37.1}/tests/test_nn_xtb.py +0 -0
  83. {rdworks-0.36.4 → rdworks-0.37.1}/tests/test_web.py +0 -0
  84. {rdworks-0.36.4 → rdworks-0.37.1}/tests/test_xtb_wrapper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rdworks
3
- Version: 0.36.4
3
+ Version: 0.37.1
4
4
  Summary: Frequently used 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,4 +1,4 @@
1
- __version__ = '0.36.4'
1
+ __version__ = '0.37.1'
2
2
 
3
3
  from rdworks.conf import Conf
4
4
  from rdworks.mol import Mol
@@ -3,6 +3,7 @@ import copy
3
3
  import json
4
4
  import numpy as np
5
5
  import ase
6
+ import itertools
6
7
 
7
8
  from collections.abc import Callable
8
9
  from typing import Self
@@ -15,6 +16,8 @@ from rdkit.Chem import rdMolTransforms, AllChem, rdMolAlign, rdmolops
15
16
  from rdkit.Chem.Draw import rdMolDraw2D
16
17
  from PIL import Image
17
18
 
19
+ from rdworks.std import clean_2d
20
+ from rdworks.torsion import get_torsion_atoms, create_torsion_fragment
18
21
  from rdworks.units import ev2kcalpermol, pm2angstrom
19
22
  from rdworks.utils import recursive_round
20
23
  from rdworks.xtb.wrapper import GFN2xTB
@@ -387,7 +390,124 @@ class Conf:
387
390
  raise RuntimeError("ASE calculator error")
388
391
 
389
392
 
390
- def torsion_angle(self, i:int, j:int, k:int, l:int) -> float:
393
+ def torsion_atoms(self, strict: bool = True) -> dict[int, tuple]:
394
+ """Determine torsion/dihedral angle atoms (i-j-k-l) and rotating group for each rotatable bond (j-k).
395
+
396
+ Args:
397
+ strict (bool): whether to exclude amide/imide/ester/acid bonds.
398
+
399
+ Returns:
400
+ {torsion_key: (i, j, k, l), ...,}
401
+ """
402
+ return {i: d[:4] for i, d in enumerate(get_torsion_atoms(self.rdmol, strict))}
403
+
404
+
405
+ def torsion_energies(self,
406
+ calculator: str | Callable,
407
+ torsion_key: int | None = None,
408
+ simplify: bool = True,
409
+ fmax: float = 0.05,
410
+ interval: float = 20.0,
411
+ use_converged_only: bool = True,
412
+ **kwargs,
413
+ ) -> Self:
414
+ """Calculates potential energy profiles for each torsion angle using ASE optimizer.
415
+
416
+ It uses the first conformer as a reference.
417
+
418
+ Args:
419
+ calculator (str | Callable): 'MMFF', 'UFF', or ASE calculator.
420
+ torsion_key (int | None): torsion index to calculate. Defaults to None (all).
421
+ simplify (bool, optional): whether to use fragment surrogate. Defaults to True.
422
+ fmax (float, optional): fmax of ASE optimizer. Defaults to 0.05.
423
+ interval (float, optional): interval of torsion angles in degree. Defaults to 15.0.
424
+ use_converged_only (bool, optional): whether to use only converged data. Defaults to True.
425
+
426
+ Returns:
427
+ Self: modified self.
428
+ """
429
+
430
+ if torsion_key is None:
431
+ torsion_atoms_indices = self.torsion_atoms()
432
+ # {0: (5, 4, 3, 1)}
433
+ else:
434
+ torsion_atoms_indices = {torsion_key: self.torsion_atoms()[torsion_key]}
435
+
436
+ ref_conf = self.copy()
437
+
438
+ data = {}
439
+
440
+ if simplify:
441
+ for tk, indices in torsion_atoms_indices.items():
442
+ frag, frag_ijkl = create_torsion_fragment(ref_conf.rdmol, indices)
443
+ frag_conf = Conf(frag)
444
+ data[tk] = {'indices': indices, 'angle':[], 'init':[], 'last':[], 'Converged':[]}
445
+ for angle in np.arange(-180.0, 180.0, interval):
446
+ # Iterated numpy.ndarray does not contain the last 180: -180., ..., (180).
447
+ conf = frag_conf.copy()
448
+ conf.props.update({'torsion_key': tk, 'angle': float(angle)})
449
+ conf.set_torsion(*frag_ijkl, angle) # atoms bonded to `l` move.
450
+ conf = conf.optimize(calculator, fmax, **kwargs)
451
+ # conf.optimize() updates coordinates and conf.props:
452
+ # `angle`, `E_tot_init(kcal/mol)`, `E_tot(kcal/mol)`, `Converged`.
453
+ tk = conf.props['torsion_key']
454
+ data[tk]['angle'].append(conf.props['angle'])
455
+ data[tk]['init'].append(conf.props['E_tot_init(kcal/mol)'])
456
+ data[tk]['last'].append(conf.props['E_tot(kcal/mol)'])
457
+ data[tk]['Converged'].append(conf.props['Converged'])
458
+ frag_cleaned, _ = clean_2d(frag, reset_isotope=True, remove_H=True)
459
+ # to serialize the molecule
460
+ data[tk]['frag'] = Chem.MolToMolBlock(frag_cleaned)
461
+ data[tk]['frag_indices'] = frag_ijkl
462
+
463
+ else:
464
+ # mol.confs will be populated with torsion conformers.
465
+ # It is designed for a batch optimization in the future.
466
+ torsion_angle_confs = []
467
+ for tk, indices in torsion_atoms_indices.items():
468
+ data[tk] = {'indices': indices, 'angle':[], 'init':[], 'last':[], 'Converged':[]}
469
+ for angle in np.arange(-180.0, 180.0, interval):
470
+ # Iterated numpy.ndarray does not contain the last 180: -180., ..., (180).
471
+ x = ref_conf.copy()
472
+ x.props.update({'torsion_key': tk, 'angle': float(angle)})
473
+ x.set_torsion(*indices, angle) # atoms bonded to `l` move.
474
+ torsion_angle_confs.append(x)
475
+
476
+ # Calculate relaxation energies
477
+ for conf in torsion_angle_confs:
478
+ conf = conf.optimize(calculator, fmax, **kwargs)
479
+ # conf.optimize() updates coordinates and conf.props:
480
+ # `angle`, `E_tot_init(kcal/mol)`, `E_tot(kcal/mol)`, `Converged`.
481
+ tk = conf.props['torsion_key']
482
+ data[tk]['angle'].append(conf.props['angle'])
483
+ data[tk]['init'].append(conf.props['E_tot_init(kcal/mol)'])
484
+ data[tk]['last'].append(conf.props['E_tot(kcal/mol)'])
485
+ data[tk]['Converged'].append(conf.props['Converged'])
486
+
487
+ # Post-processing
488
+ torsion_energy_profiles = {}
489
+ for tk, dictdata in data.items():
490
+ if use_converged_only:
491
+ dictdata['angle'] = list(itertools.compress(dictdata['angle'], dictdata['Converged']))
492
+ dictdata['init'] = list(itertools.compress(dictdata['init'], dictdata['Converged']))
493
+ dictdata['last'] = list(itertools.compress(dictdata['last'], dictdata['Converged']))
494
+ relax = np.array(dictdata['init']) - np.median(dictdata['last'])
495
+ E_rel = relax - np.min(relax)
496
+ torsion_energy_profiles[tk] = {
497
+ 'indices' : dictdata['indices'],
498
+ 'angle' : np.round(np.array(dictdata['angle']), 1).tolist(), # np.ndarray -> list for serialization
499
+ 'E_rel(kcal/mol)': np.round(E_rel, 2).tolist(), # np.ndarray -> list for serialization
500
+ 'frag' : dictdata.get('frag', None),
501
+ 'frag_indices' : dictdata.get('frag_indices', None),
502
+ }
503
+
504
+ self.props['torsion'] = torsion_energy_profiles
505
+ self.props['torsion_calculator'] = str(calculator)
506
+
507
+ return self
508
+
509
+
510
+ def torsion_angle(self, i: int, j: int, k: int, l: int) -> float:
391
511
  """Get dihedral angle (i-j-k-l) in degrees.
392
512
 
393
513
  Args:
@@ -419,8 +539,10 @@ class Conf:
419
539
  return json.dumps(self.props)
420
540
 
421
541
 
422
- def serialize(self, decimals:int=3) -> str:
423
- """Serialize information necessary to rebuild.
542
+ def serialize(self, decimals: int = 3) -> str:
543
+ """Serialize information necessary to rebuild a Conf object.
544
+ Args:
545
+ decimals (int, optional): number of decimal places for float data type. Defaults to 3.
424
546
 
425
547
  Returns:
426
548
  str: serialized string for json.loads()
@@ -435,14 +557,18 @@ class Conf:
435
557
  return serialized
436
558
 
437
559
 
438
- def deserialize(self, serialized:str) -> Self:
439
- """De-serialize information and rebuild.
560
+ def deserialize(self, serialized: str) -> Self:
561
+ """De-serialize information and rebuild a Conf object.
562
+
563
+ Example:
564
+ serialized = conf1.serialize()
565
+ conf2 = Conf().deserialize(serialized)
440
566
 
441
567
  Args:
442
- serialized (str): _description_
568
+ serialized (str): serialized string.
443
569
 
444
570
  Returns:
445
- Self: _description_
571
+ Self: modified self.
446
572
  """
447
573
  data = json.loads(serialized)
448
574
 
@@ -942,18 +942,6 @@ class Mol:
942
942
  return [atom.GetAtomicNum() for atom in self.rdmol.GetAtoms()]
943
943
 
944
944
 
945
- def torsion_atoms(self, strict: bool = True) -> dict[int, tuple]:
946
- """Determine torsion/dihedral angle atoms (i-j-k-l) and rotating group for each rotatable bond (j-k).
947
-
948
- Args:
949
- strict (bool): whether to exclude amide/imide/ester/acid bonds.
950
-
951
- Returns:
952
- {torsion_key: (i, j, k, l), ...,}
953
- """
954
- return {i: d[:4] for i, d in enumerate(get_torsion_atoms(self.rdmol, strict))}
955
-
956
-
957
945
  def compute(self, **kwargs) -> Self:
958
946
  """Change settings for parallel computing.
959
947
 
@@ -972,6 +960,18 @@ class Mol:
972
960
  return self
973
961
 
974
962
 
963
+ def torsion_atoms(self, strict: bool = True) -> dict[int, tuple]:
964
+ """Determine torsion/dihedral angle atoms (i-j-k-l) and rotating group for each rotatable bond (j-k).
965
+
966
+ Args:
967
+ strict (bool): whether to exclude amide/imide/ester/acid bonds.
968
+
969
+ Returns:
970
+ {torsion_key: (i, j, k, l), ...,}
971
+ """
972
+ return {i: d[:4] for i, d in enumerate(get_torsion_atoms(self.rdmol, strict))}
973
+
974
+
975
975
  def torsion_energies(self,
976
976
  calculator: str | Callable,
977
977
  torsion_key: int | None = None,
@@ -997,87 +997,16 @@ class Mol:
997
997
  Self: modified self.
998
998
  """
999
999
  assert self.count() > 0, "torsion_energies() requires at least one conformer"
1000
-
1001
- self = self.compute(**kwargs)
1002
-
1003
- if torsion_key is None:
1004
- torsion_atoms_indices = self.torsion_atoms()
1005
- # {0: (5, 4, 3, 1)}
1006
- else:
1007
- torsion_atoms_indices = {torsion_key: self.torsion_atoms()[torsion_key]}
1008
-
1009
1000
  ref_conf = self.confs[0].copy()
1010
-
1011
- data = {}
1012
-
1013
- if simplify:
1014
- for tk, indices in torsion_atoms_indices.items():
1015
- frag, frag_ijkl = create_torsion_fragment(ref_conf.rdmol, indices)
1016
- frag_conf = Conf(frag)
1017
- data[tk] = {'indices': indices, 'angle':[], 'init':[], 'last':[], 'Converged':[]}
1018
- for angle in np.arange(-180.0, 180.0, interval):
1019
- # Iterated numpy.ndarray does not contain the last 180: -180., ..., (180).
1020
- conf = frag_conf.copy()
1021
- conf.props.update({'torsion_key': tk, 'angle': float(angle)})
1022
- conf.set_torsion(*frag_ijkl, angle) # atoms bonded to `l` move.
1023
- conf = conf.optimize(calculator, fmax, **kwargs)
1024
- # conf.optimize() updates coordinates and conf.props:
1025
- # `angle`, `E_tot_init(kcal/mol)`, `E_tot(kcal/mol)`, `Converged`.
1026
- tk = conf.props['torsion_key']
1027
- data[tk]['angle'].append(conf.props['angle'])
1028
- data[tk]['init'].append(conf.props['E_tot_init(kcal/mol)'])
1029
- data[tk]['last'].append(conf.props['E_tot(kcal/mol)'])
1030
- data[tk]['Converged'].append(conf.props['Converged'])
1031
- frag_cleaned, _ = clean_2d(frag, reset_isotope=True, remove_H=True)
1032
- rdDepictor.Compute2DCoords(frag_cleaned)
1033
- # to serialize the molecule
1034
- data[tk]['frag'] = Chem.MolToMolBlock(frag_cleaned)
1035
- data[tk]['frag_indices'] = frag_ijkl
1036
-
1037
- else:
1038
- # mol.confs will be populated with torsion conformers.
1039
- # It is designed for a batch optimization in the future.
1040
- mol = self.copy()
1041
- mol.confs = []
1042
- for tk, indices in torsion_atoms_indices.items():
1043
- data[tk] = {'indices': indices, 'angle':[], 'init':[], 'last':[], 'Converged':[]}
1044
- for angle in np.arange(-180.0, 180.0, interval):
1045
- # Iterated numpy.ndarray does not contain the last 180: -180., ..., (180).
1046
- x = ref_conf.copy()
1047
- x.props.update({'torsion_key': tk, 'angle': float(angle)})
1048
- x.set_torsion(*indices, angle) # atoms bonded to `l` move.
1049
- mol.confs.append(x)
1050
-
1051
- # Calculate relaxation energies
1052
- for conf in mol.confs:
1053
- conf = conf.optimize(calculator, fmax, **kwargs)
1054
- # conf.optimize() updates coordinates and conf.props:
1055
- # `angle`, `E_tot_init(kcal/mol)`, `E_tot(kcal/mol)`, `Converged`.
1056
- tk = conf.props['torsion_key']
1057
- data[tk]['angle'].append(conf.props['angle'])
1058
- data[tk]['init'].append(conf.props['E_tot_init(kcal/mol)'])
1059
- data[tk]['last'].append(conf.props['E_tot(kcal/mol)'])
1060
- data[tk]['Converged'].append(conf.props['Converged'])
1061
-
1062
- # Post-processing
1063
- torsion_energy_profiles = {}
1064
- for tk, dictdata in data.items():
1065
- if use_converged_only:
1066
- dictdata['angle'] = list(itertools.compress(dictdata['angle'], dictdata['Converged']))
1067
- dictdata['init'] = list(itertools.compress(dictdata['init'], dictdata['Converged']))
1068
- dictdata['last'] = list(itertools.compress(dictdata['last'], dictdata['Converged']))
1069
- relax = np.array(dictdata['init']) - np.median(dictdata['last'])
1070
- E_rel = relax - np.min(relax)
1071
- torsion_energy_profiles[tk] = {
1072
- 'indices' : dictdata['indices'],
1073
- 'angle' : np.round(np.array(dictdata['angle']), 1).tolist(), # np.ndarray -> list for serialization
1074
- 'E_rel(kcal/mol)': np.round(E_rel, 2).tolist(), # np.ndarray -> list for serialization
1075
- 'frag' : dictdata.get('frag', None),
1076
- 'frag_indices' : dictdata.get('frag_indices', None),
1077
- }
1078
-
1079
- self.props['torsion'] = torsion_energy_profiles
1080
- self.props['torsion_calculator'] = str(calculator)
1001
+ ref_conf = ref_conf.torsion_energies(calculator,
1002
+ torsion_key,
1003
+ simplify,
1004
+ fmax,
1005
+ interval,
1006
+ use_converged_only,
1007
+ **kwargs)
1008
+ for k in ['torsion', 'torsion_calculator']:
1009
+ self.props[k] = ref_conf.props[k]
1081
1010
 
1082
1011
  return self
1083
1012
 
@@ -1629,7 +1558,15 @@ class Mol:
1629
1558
  return json.dumps(props)
1630
1559
 
1631
1560
 
1632
- def serialize(self, decimals: int = 2) -> str:
1561
+ def serialize(self, decimals: int = 2) -> str:
1562
+ """Serialize information necessary to rebuild a Mol object.
1563
+
1564
+ Args:
1565
+ decimals (int, optional): number of decimal places for float data type. Defaults to 2.
1566
+
1567
+ Returns:
1568
+ str: serialized string for json.loads()
1569
+ """
1633
1570
  serialized = json.dumps({
1634
1571
  'name' : self.name,
1635
1572
  'smiles': self.smiles,
@@ -1641,10 +1578,14 @@ class Mol:
1641
1578
 
1642
1579
 
1643
1580
  def deserialize(self, serialized: str) -> Self:
1644
- """Updates self with the serialized string input.
1581
+ """De-serialize the information and build a new Mol object.
1582
+
1583
+ Example:
1584
+ serialized = mol1.serialize()
1585
+ mol2 = Mol().deserialize(serialized)
1645
1586
 
1646
1587
  Args:
1647
- serialized (str): input
1588
+ serialized (str): serialized string.
1648
1589
 
1649
1590
  Returns:
1650
1591
  Self: modified self.
@@ -180,4 +180,6 @@ def clean_2d(rdmol: Chem.Mol,
180
180
  if remove_H:
181
181
  mol = Chem.RemoveHs(mol)
182
182
 
183
+ rdDepictor.Compute2DCoords(mol)
184
+
183
185
  return (mol, conformers)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rdworks
3
- Version: 0.36.4
3
+ Version: 0.37.1
4
4
  Summary: Frequently used 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>
@@ -481,6 +481,9 @@ def test_torsion_fragment():
481
481
  # {0: (5, 4, 3, 1)}
482
482
  assert len(ta2) == 1
483
483
  frag, frag_ijkl = create_torsion_fragment(mol2.confs[0].rdmol, ta2[0])
484
+ # expects no fragmentation
485
+ assert frag == mol2.confs[0].rdmol
486
+ assert frag_ijkl == ta2[0]
484
487
 
485
488
 
486
489
  def test_torsion_energies():
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes