synkit 1.3.2__tar.gz → 1.4.0__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 (286) hide show
  1. {synkit-1.3.2 → synkit-1.4.0}/.gitignore +5 -0
  2. {synkit-1.3.2 → synkit-1.4.0}/PKG-INFO +1 -1
  3. {synkit-1.3.2 → synkit-1.4.0}/pyproject.toml +1 -1
  4. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/tautomerize.py +50 -7
  5. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Canon/canon_graph.py +2 -2
  6. synkit-1.4.0/synkit/Graph/FG/__init__.py +19 -0
  7. synkit-1.4.0/synkit/Graph/FG/api.py +39 -0
  8. synkit-1.4.0/synkit/Graph/FG/audit.py +155 -0
  9. synkit-1.4.0/synkit/Graph/FG/catalog.py +1168 -0
  10. synkit-1.4.0/synkit/Graph/FG/detector.py +288 -0
  11. synkit-1.4.0/synkit/Graph/FG/model.py +97 -0
  12. synkit-1.4.0/synkit/Graph/FG/ring_system.py +154 -0
  13. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Hyrogen/_misc.py +78 -7
  14. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/its_construction.py +14 -1
  15. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/its_destruction.py +25 -3
  16. synkit-1.4.0/synkit/Graph/ITS/its_expand.py +444 -0
  17. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/its_reverter.py +7 -0
  18. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/rc_extractor.py +24 -2
  19. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/MTG/mtg.py +388 -41
  20. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/graph_matcher.py +34 -15
  21. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/subgraph_matcher.py +127 -11
  22. synkit-1.4.0/synkit/Graph/Mech/conversion.py +1305 -0
  23. synkit-1.4.0/synkit/Graph/Mech/electron_accounting.py +64 -0
  24. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/canon_graph.py +12 -3
  25. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/utils.py +31 -1
  26. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/chem_converter.py +85 -10
  27. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/graph_to_mol.py +2 -0
  28. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/mol_to_graph.py +28 -7
  29. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Apply/rule_matcher.py +26 -3
  30. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/syn_rule.py +135 -28
  31. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/imba_engine.py +10 -0
  32. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/partial_engine.py +15 -1
  33. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/rbl_engine.py +21 -0
  34. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/rule_filter.py +11 -1
  35. synkit-1.4.0/synkit/Synthesis/Reactor/syn_reactor.py +1429 -0
  36. synkit-1.4.0/synkit/Utils/__init__.py +0 -0
  37. synkit-1.4.0/synkit/Vis/__init__.py +50 -0
  38. {synkit-1.3.2 → synkit-1.4.0}/synkit/Vis/graph_visualizer.py +1 -1
  39. synkit-1.4.0/synkit/Vis/its_drawer.py +615 -0
  40. synkit-1.4.0/synkit/Vis/molecule_drawer.py +565 -0
  41. synkit-1.4.0/synkit/Vis/mtg_drawer.py +769 -0
  42. synkit-1.4.0/synkit/Vis/reaction_drawer.py +285 -0
  43. synkit-1.4.0/synkit/Vis/vis_synedu/Vis/__init__.py +7 -0
  44. synkit-1.4.0/synkit/Vis/vis_synedu/Vis/dpo.py +862 -0
  45. synkit-1.4.0/synkit/Vis/vis_synedu/rxn_vis.py +382 -0
  46. synkit-1.4.0/synkit/Vis/vis_synedu/vis.py +501 -0
  47. synkit-1.4.0/synkit/Vis/visual_drawer.py +215 -0
  48. synkit-1.4.0/synkit/Vis/visual_model.py +520 -0
  49. synkit-1.3.2/synkit/Graph/ITS/its_expand.py +0 -86
  50. synkit-1.3.2/synkit/Graph/MTG/group_comp.py +0 -157
  51. synkit-1.3.2/synkit/Graph/MTG/groupoid.py +0 -358
  52. synkit-1.3.2/synkit/Synthesis/Reactor/syn_reactor.py +0 -638
  53. synkit-1.3.2/synkit/Vis/__init__.py +0 -5
  54. {synkit-1.3.2 → synkit-1.4.0}/LICENSE +0 -0
  55. {synkit-1.3.2 → synkit-1.4.0}/README.md +0 -0
  56. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/DAG/__init__.py +0 -0
  57. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/DAG/crn.py +0 -0
  58. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/DAG/mod_crn.py +0 -0
  59. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/DAG/syncrn.py +0 -0
  60. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/__init__.py +0 -0
  61. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/abstract.py +0 -0
  62. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/arity.py +0 -0
  63. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/builder.py +0 -0
  64. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/derivation.py +0 -0
  65. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/flattener.py +0 -0
  66. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/keys.py +0 -0
  67. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/mixtures.py +0 -0
  68. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/smiles.py +0 -0
  69. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/state.py +0 -0
  70. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/strategy.py +0 -0
  71. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Construct/worker.py +0 -0
  72. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Pathway/__init__.py +0 -0
  73. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Pathway/_adapter.py +0 -0
  74. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Pathway/pathfinder.py +0 -0
  75. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Pathway/reachability.py +0 -0
  76. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Pathway/realizability.py +0 -0
  77. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Petrinet/__init__.py +0 -0
  78. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Petrinet/analyzer.py +0 -0
  79. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Petrinet/net.py +0 -0
  80. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Petrinet/persistence.py +0 -0
  81. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Petrinet/semiflows.py +0 -0
  82. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Petrinet/structure.py +0 -0
  83. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Props/__init__.py +0 -0
  84. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Props/dynamics.py +0 -0
  85. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Props/helper.py +0 -0
  86. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Props/stoich.py +0 -0
  87. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Props/thermo.py +0 -0
  88. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Query/__init__.py +0 -0
  89. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Query/kegg_api.py +0 -0
  90. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Query/kegg_extract.py +0 -0
  91. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Query/kegg_impute.py +0 -0
  92. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Query/kegg_parse.py +0 -0
  93. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Structure/__init__.py +0 -0
  94. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Structure/reaction.py +0 -0
  95. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Structure/rule.py +0 -0
  96. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Structure/species.py +0 -0
  97. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Structure/syncrn.py +0 -0
  98. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Symmetry/__init__.py +0 -0
  99. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Symmetry/_common.py +0 -0
  100. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Symmetry/_ir.py +0 -0
  101. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Symmetry/automorphism.py +0 -0
  102. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Symmetry/canon.py +0 -0
  103. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Symmetry/isomorphism.py +0 -0
  104. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Symmetry/symmetry.py +0 -0
  105. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Symmetry/wl_canon.py +0 -0
  106. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Visualize/__init__.py +0 -0
  107. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Visualize/crn_vis.py +0 -0
  108. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Visualize/labels.py +0 -0
  109. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Visualize/layout.py +0 -0
  110. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Visualize/palette.py +0 -0
  111. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Visualize/validation.py +0 -0
  112. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/Visualize/vis.py +0 -0
  113. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/__init__.py +0 -0
  114. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Structure/__init__.py +0 -0
  115. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Structure/backend.py +0 -0
  116. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Structure/conversion.py +0 -0
  117. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Structure/hyperedge.py +0 -0
  118. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Structure/hypergraph.py +0 -0
  119. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Structure/rxn.py +0 -0
  120. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Symmetry/__init__.py +0 -0
  121. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Symmetry/automorphism.py +0 -0
  122. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Symmetry/canon.py +0 -0
  123. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/Symmetry/wl_canon.py +0 -0
  124. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/__init__.py +0 -0
  125. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/configs/__init__.py +0 -0
  126. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/configs/loader.py +0 -0
  127. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/configs/models.py +0 -0
  128. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/constants.py +0 -0
  129. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/crn_formula.py +0 -0
  130. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/deficiency.py +0 -0
  131. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/enumerator.py +0 -0
  132. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/exceptions.py +0 -0
  133. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/explorer.py +0 -0
  134. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/helpers.py +0 -0
  135. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/injectivity.py +0 -0
  136. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/motif.py +0 -0
  137. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/network.py +0 -0
  138. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/pathway.py +0 -0
  139. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/properties.py +0 -0
  140. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/reaction.py +0 -0
  141. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/utils.py +0 -0
  142. {synkit-1.3.2 → synkit-1.4.0}/synkit/CRN/dev_crn/viz.py +0 -0
  143. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Cluster/__init__.py +0 -0
  144. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Cluster/butina.py +0 -0
  145. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Fingerprint/__init__.py +0 -0
  146. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
  147. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
  148. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
  149. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Molecule/__init__.py +0 -0
  150. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Molecule/atom_features.py +0 -0
  151. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Molecule/descriptors.py +0 -0
  152. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Molecule/formula.py +0 -0
  153. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Molecule/graph_annotator.py +0 -0
  154. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Molecule/standardize.py +0 -0
  155. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Molecule/valence.py +0 -0
  156. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/Mapper/__init__.py +0 -0
  157. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/Mapper/wl_mapper.py +0 -0
  158. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/__init__.py +0 -0
  159. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/aam_validator.py +0 -0
  160. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/balance_check.py +0 -0
  161. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/canon_rsmi.py +0 -0
  162. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/cleaning.py +0 -0
  163. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/deionize.py +0 -0
  164. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/fix_aam.py +0 -0
  165. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/neutralize.py +0 -0
  166. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/radical_wildcard.py +0 -0
  167. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/Reaction/standardize.py +0 -0
  168. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/__init__.py +0 -0
  169. {synkit-1.3.2 → synkit-1.4.0}/synkit/Chem/utils.py +0 -0
  170. {synkit-1.3.2 → synkit-1.4.0}/synkit/Data/__init__.py +0 -0
  171. {synkit-1.3.2 → synkit-1.4.0}/synkit/Data/gen_partial_aam.py +0 -0
  172. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Canon/__init__.py +0 -0
  173. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Canon/canon_algs.py +0 -0
  174. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Canon/nauty.py +0 -0
  175. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Context/__init__.py +0 -0
  176. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Context/hier_context.py +0 -0
  177. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Context/radius_expand.py +0 -0
  178. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/Descriptors/topology.py +0 -0
  179. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
  180. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +0 -0
  181. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/__init__.py +0 -0
  182. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/graph_descriptors.py +0 -0
  183. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/graph_fps.py +0 -0
  184. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/graph_signature.py +0 -0
  185. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/hash_fps.py +0 -0
  186. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/morgan_fps.py +0 -0
  187. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/path_fps.py +0 -0
  188. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Feature/wl_hash.py +0 -0
  189. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Hyrogen/__init__.py +0 -0
  190. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Hyrogen/hcomplete.py +0 -0
  191. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Hyrogen/hextend.py +0 -0
  192. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/__init__.py +0 -0
  193. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/its_builder.py +0 -0
  194. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/its_decompose.py +0 -0
  195. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/its_relabel.py +0 -0
  196. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/normalize_aam.py +0 -0
  197. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/ITS/partial_its.py +0 -0
  198. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/MTG/__init__.py +0 -0
  199. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/MTG/mcs_matcher.py +0 -0
  200. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/MTG/mtg_explore.py +0 -0
  201. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/MTG/utils.py +0 -0
  202. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/__init__.py +0 -0
  203. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/approx_mcs.py +0 -0
  204. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/auto_est.py +0 -0
  205. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/automorphism.py +0 -0
  206. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/batch_cluster.py +0 -0
  207. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/dedup_matches.py +0 -0
  208. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/graph_cluster.py +0 -0
  209. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/graph_morphism.py +0 -0
  210. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/mcs_matcher.py +0 -0
  211. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/multi_turbo_iso.py +0 -0
  212. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/orbit.py +0 -0
  213. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/partial_matcher.py +0 -0
  214. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/sing.py +0 -0
  215. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/turbo_iso.py +0 -0
  216. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Matcher/wl_sel.py +0 -0
  217. {synkit-1.3.2/synkit/Graph/Wildcard → synkit-1.4.0/synkit/Graph/Mech}/__init__.py +0 -0
  218. {synkit-1.3.2/synkit/Rule/Apply → synkit-1.4.0/synkit/Graph/Wildcard}/__init__.py +0 -0
  219. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Wildcard/fuse_graph.py +0 -0
  220. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Wildcard/graph_wc.py +0 -0
  221. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Wildcard/its_merge.py +0 -0
  222. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Wildcard/radwc.py +0 -0
  223. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Wildcard/wc_matcher.py +0 -0
  224. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/Wildcard/wildcard.py +0 -0
  225. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/__init__.py +0 -0
  226. {synkit-1.3.2 → synkit-1.4.0}/synkit/Graph/syn_graph.py +0 -0
  227. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/__init__.py +0 -0
  228. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/combinatorial/__init__.py +0 -0
  229. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/combinatorial/gml_to_graph.py +0 -0
  230. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/combinatorial/graph_to_gml.py +0 -0
  231. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/combinatorial/graph_to_smarts.py +0 -0
  232. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/combinatorial/smarts_expander.py +0 -0
  233. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/combinatorial/smarts_generalizer.py +0 -0
  234. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/combinatorial/smarts_to_graph.py +0 -0
  235. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/data_io.py +0 -0
  236. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/data_process.py +0 -0
  237. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/debug.py +0 -0
  238. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/dg_to_gml.py +0 -0
  239. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/gml_to_nx.py +0 -0
  240. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/nx_to_gml.py +0 -0
  241. {synkit-1.3.2 → synkit-1.4.0}/synkit/IO/smiles_to_id.py +0 -0
  242. {synkit-1.3.2/synkit/Rule/Compose → synkit-1.4.0/synkit/Rule/Apply}/__init__.py +0 -0
  243. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Apply/reactor_rule.py +0 -0
  244. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Apply/retro_reactor.py +0 -0
  245. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Apply/rule_rbl.py +0 -0
  246. {synkit-1.3.2/synkit/Rule/Modify → synkit-1.4.0/synkit/Rule/Compose}/__init__.py +0 -0
  247. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Compose/compose_rule.py +0 -0
  248. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Compose/rule_compose.py +0 -0
  249. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Compose/rule_mapping.py +0 -0
  250. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Compose/seq_comp.py +0 -0
  251. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Compose/valence_constrain.py +0 -0
  252. {synkit-1.3.2/synkit/Synthesis/MSR → synkit-1.4.0/synkit/Rule/Modify}/__init__.py +0 -0
  253. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Modify/implict_rule.py +0 -0
  254. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Modify/longest_path.py +0 -0
  255. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Modify/molecule_rule.py +0 -0
  256. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Modify/prune_templates.py +0 -0
  257. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Modify/rule_utils.py +0 -0
  258. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/Modify/strip_rule.py +0 -0
  259. {synkit-1.3.2 → synkit-1.4.0}/synkit/Rule/__init__.py +0 -0
  260. {synkit-1.3.2/synkit/Synthesis/Metrics → synkit-1.4.0/synkit/Synthesis/MSR}/__init__.py +0 -0
  261. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/MSR/multi_steps.py +0 -0
  262. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/MSR/path_finder.py +0 -0
  263. {synkit-1.3.2/synkit/Synthesis/Reactor → synkit-1.4.0/synkit/Synthesis/Metrics}/__init__.py +0 -0
  264. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Metrics/_base.py +0 -0
  265. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Metrics/_plot.py +0 -0
  266. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Metrics/_ranking.py +0 -0
  267. {synkit-1.3.2/synkit/Synthesis → synkit-1.4.0/synkit/Synthesis/Reactor}/__init__.py +0 -0
  268. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/batch_reactor.py +0 -0
  269. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/benchmark.py +0 -0
  270. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/mod_aam.py +0 -0
  271. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/mod_reactor.py +0 -0
  272. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/post_syn.py +0 -0
  273. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/single_predictor.py +0 -0
  274. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/Reactor/strategy.py +0 -0
  275. {synkit-1.3.2/synkit/Utils → synkit-1.4.0/synkit/Synthesis}/__init__.py +0 -0
  276. {synkit-1.3.2 → synkit-1.4.0}/synkit/Synthesis/reactor_utils.py +0 -0
  277. {synkit-1.3.2 → synkit-1.4.0}/synkit/Utils/utils.py +0 -0
  278. {synkit-1.3.2 → synkit-1.4.0}/synkit/Vis/chemical_space.py +0 -0
  279. {synkit-1.3.2 → synkit-1.4.0}/synkit/Vis/crn_vis.py +0 -0
  280. {synkit-1.3.2 → synkit-1.4.0}/synkit/Vis/embedding.py +0 -0
  281. {synkit-1.3.2 → synkit-1.4.0}/synkit/Vis/pdf_writer.py +0 -0
  282. {synkit-1.3.2 → synkit-1.4.0}/synkit/Vis/rule_vis.py +0 -0
  283. {synkit-1.3.2 → synkit-1.4.0}/synkit/Vis/rxn_vis.py +0 -0
  284. {synkit-1.3.2 → synkit-1.4.0}/synkit/__init__.py +0 -0
  285. {synkit-1.3.2 → synkit-1.4.0}/synkit/examples.py +0 -0
  286. {synkit-1.3.2 → synkit-1.4.0}/synkit/version.py +0 -0
@@ -32,3 +32,8 @@ synkit/Graph/dev/*
32
32
  *.json
33
33
  *.txt
34
34
  *.log
35
+ sprint/
36
+ test_syn.py
37
+ .gitignore
38
+ measure_candidate_stages.py
39
+ run_valid_bug_cases.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synkit
3
- Version: 1.3.2
3
+ Version: 1.4.0
4
4
  Summary: Utility for reaction modeling using graph grammar
5
5
  Project-URL: homepage, https://github.com/TieuLongPhan/SynKit
6
6
  Project-URL: source, https://github.com/TieuLongPhan/SynKit
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "synkit"
7
- version = "1.3.2"
7
+ version = "1.4.0"
8
8
  description = "Utility for reaction modeling using graph grammar"
9
9
  readme = "README.md"
10
10
  long-description = { file = "CHANGELOG.md" }
@@ -1,8 +1,9 @@
1
1
  from typing import List, Dict, Optional
2
2
  from rdkit import Chem
3
- from fgutils import FGQuery
4
3
  from joblib import Parallel, delayed
5
4
 
5
+ from synkit.Graph.FG import smiles_to_graph_and_functional_groups
6
+
6
7
 
7
8
  class Tautomerize:
8
9
  """Standardize molecules by converting enol and hemiketal tautomers into
@@ -103,18 +104,60 @@ class Tautomerize:
103
104
  :returns: Canonical SMILES of the standardized molecule.
104
105
  :rtype: str
105
106
  """
106
- query = FGQuery()
107
- fg = query.get(smiles)
108
- for item in fg:
109
- label, indices = item
107
+ while True:
108
+ targets = Tautomerize._tautomer_targets(smiles)
109
+ if not targets:
110
+ break
111
+ label, indices = targets[0]
110
112
  if label == "hemiketal":
111
113
  smiles = Tautomerize.standardize_hemiketal(smiles, indices)
112
- fg = query.get(smiles)
113
114
  elif label == "enol":
114
115
  smiles = Tautomerize.standardize_enol(smiles, indices)
115
- fg = query.get(smiles)
116
116
  return Chem.CanonSmiles(smiles)
117
117
 
118
+ @staticmethod
119
+ def _tautomer_targets(smiles: str) -> list[tuple[str, List[int]]]:
120
+ """Return RDKit-index targets used by the tautomer repair helpers."""
121
+ mol = Chem.MolFromSmiles(smiles)
122
+ if mol is None:
123
+ return []
124
+ graph, groups = smiles_to_graph_and_functional_groups(smiles)
125
+ node_to_idx = {
126
+ (
127
+ atom.GetAtomMapNum() if atom.GetAtomMapNum() else atom.GetIdx() + 1
128
+ ): atom.GetIdx()
129
+ for atom in mol.GetAtoms()
130
+ }
131
+
132
+ targets = [
133
+ (label, [node_to_idx[node] for node in nodes])
134
+ for label, nodes in groups
135
+ if label in {"hemiketal", "enol"}
136
+ ]
137
+ targets.extend(
138
+ ("hemiketal", [node_to_idx[node] for node in nodes])
139
+ for nodes in Tautomerize._geminal_diol_nodes(graph)
140
+ )
141
+ return targets
142
+
143
+ @staticmethod
144
+ def _geminal_diol_nodes(graph) -> list[tuple[int, ...]]:
145
+ """Legacy tautomerization compatibility for hydrated carbonyls."""
146
+ targets: list[tuple[int, ...]] = []
147
+ for carbon, data in graph.nodes(data=True):
148
+ if data.get("element") != "C":
149
+ continue
150
+ hydroxyls = [
151
+ neighbor
152
+ for neighbor in graph.neighbors(carbon)
153
+ if graph.nodes[neighbor].get("element") == "O"
154
+ and graph.nodes[neighbor].get("hcount", 0) >= 1
155
+ and graph.edges[carbon, neighbor].get("order") == 1.0
156
+ ]
157
+ if len(hydroxyls) >= 2:
158
+ targets.append((carbon, hydroxyls[0], hydroxyls[1]))
159
+ return targets
160
+
118
161
  @staticmethod
119
162
  def fix_dict(data: Dict[str, str], reaction_column: str) -> Dict[str, str]:
120
163
  """Standardize the reactant and product SMILES in a reaction
@@ -316,8 +316,8 @@ class GraphCanonicaliser:
316
316
  nodes = sorted(g.nodes(data=True), key=lambda x: self._node_key(*x))
317
317
  edges = sorted(g.edges(data=True), key=lambda x: self._edge_key(*x))
318
318
 
319
- node_str = ";".join(f"{n}:{self._node_key(n,d)}" for n, d in nodes)
320
- edge_str = ";".join(f"{(u,v)}:{self._edge_key(u,v,d)}" for u, v, d in edges)
319
+ node_str = ";".join(f"{n}:{self._node_key(n, d)}" for n, d in nodes)
320
+ edge_str = ";".join(f"{(u, v)}:{self._edge_key(u, v, d)}" for u, v, d in edges)
321
321
  return f"N[{node_str}]|E[{edge_str}]"
322
322
 
323
323
  # ------------------------------------------------------------------ #
@@ -0,0 +1,19 @@
1
+ """Functional-group detection on SynKit molecular graphs."""
2
+
3
+ from .catalog import default_registry
4
+ from .audit import FunctionalGroupAudit, audit_reaction_smiles
5
+ from .api import FunctionalGroupLabels, smiles_to_graph_and_functional_groups
6
+ from .detector import FunctionalGroupDetector
7
+ from .model import FunctionalGroupMatch, FunctionalGroupPattern, FunctionalGroupRegistry
8
+
9
+ __all__ = [
10
+ "FunctionalGroupDetector",
11
+ "FunctionalGroupLabels",
12
+ "FunctionalGroupAudit",
13
+ "FunctionalGroupMatch",
14
+ "FunctionalGroupPattern",
15
+ "FunctionalGroupRegistry",
16
+ "default_registry",
17
+ "audit_reaction_smiles",
18
+ "smiles_to_graph_and_functional_groups",
19
+ ]
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ import networkx as nx
4
+
5
+ from synkit.IO.chem_converter import smiles_to_graph
6
+
7
+ from .detector import FunctionalGroupDetector
8
+
9
+ FunctionalGroupLabels = list[tuple[str, tuple[int, ...]]]
10
+
11
+
12
+ def smiles_to_graph_and_functional_groups(
13
+ smiles: str,
14
+ *,
15
+ sanitize: bool = True,
16
+ ) -> tuple[nx.Graph, FunctionalGroupLabels]:
17
+ """Convert SMILES to a molecular graph and detect functional groups.
18
+
19
+ Atom-mapped SMILES keep their non-zero atom-map numbers as graph node IDs.
20
+ Unmapped atoms use their 1-based atom order as node IDs, so both mapped and
21
+ unmapped SMILES can be passed to the same API.
22
+
23
+ :param smiles: Input SMILES, with or without atom-map labels.
24
+ :type smiles: str
25
+ :param sanitize: If ``True``, sanitize the RDKit molecule during conversion.
26
+ :type sanitize: bool
27
+ :return: Molecular graph and detected ``(name, node_ids)`` FG labels.
28
+ :rtype: tuple[nx.Graph, list[tuple[str, tuple[int, ...]]]]
29
+ :raises ValueError: If the SMILES cannot be converted to a molecular graph.
30
+ """
31
+ graph = smiles_to_graph(
32
+ smiles,
33
+ drop_non_aam=False,
34
+ sanitize=sanitize,
35
+ use_index_as_atom_map=True,
36
+ )
37
+ if graph is None:
38
+ raise ValueError(f"Could not convert SMILES to molecular graph: {smiles!r}")
39
+ return graph, FunctionalGroupDetector().detect(graph)
@@ -0,0 +1,155 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import Counter
4
+ from dataclasses import dataclass
5
+ from time import perf_counter
6
+ from typing import Iterable
7
+
8
+ import networkx as nx
9
+
10
+ from synkit.Chem.Reaction.standardize import Standardize
11
+ from synkit.IO.chem_converter import smiles_to_graph
12
+
13
+ from .detector import FunctionalGroupDetector
14
+ from .ring_system import AromaticRingSystemDetector
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class FunctionalGroupAudit:
19
+ """Aggregated detector coverage over a reaction-SMILES corpus."""
20
+
21
+ reactions: int
22
+ molecules: int
23
+ parse_failures: int
24
+ elapsed_seconds: float
25
+ label_counts: Counter[str]
26
+ heteroaromatic_systems: int
27
+ named_heteroaromatic_systems: int
28
+ unnamed_heteroaromatic_systems: Counter[tuple]
29
+ uncovered_atom_signatures: Counter[tuple]
30
+ uncovered_edge_signatures: Counter[tuple]
31
+
32
+ @property
33
+ def unnamed_heteroaromatic_count(self) -> int:
34
+ return self.heteroaromatic_systems - self.named_heteroaromatic_systems
35
+
36
+
37
+ def audit_reaction_smiles(
38
+ reactions: Iterable[str],
39
+ *,
40
+ standardizer: Standardize | None = None,
41
+ ) -> FunctionalGroupAudit:
42
+ """Audit FG coverage for an iterable of reaction SMILES strings."""
43
+ std = Standardize() if standardizer is None else standardizer
44
+ detector = FunctionalGroupDetector()
45
+
46
+ reaction_count = 0
47
+ molecule_count = 0
48
+ parse_failures = 0
49
+ heteroaromatic_systems = 0
50
+ named_heteroaromatic_systems = 0
51
+ label_counts: Counter[str] = Counter()
52
+ unnamed_systems: Counter[tuple] = Counter()
53
+ uncovered_atoms: Counter[tuple] = Counter()
54
+ uncovered_edges: Counter[tuple] = Counter()
55
+
56
+ started = perf_counter()
57
+ for reaction in reactions:
58
+ reaction_count += 1
59
+ standardized = std.fit(reaction, remove_aam=True)
60
+ for side in standardized.split(">>"):
61
+ for smiles in side.split("."):
62
+ graph = smiles_to_graph(
63
+ smiles,
64
+ drop_non_aam=False,
65
+ use_index_as_atom_map=True,
66
+ )
67
+ if graph is None:
68
+ parse_failures += 1
69
+ continue
70
+ molecule_count += 1
71
+ matches = detector.matches(graph)
72
+ label_counts.update(match.name for match in matches)
73
+ covered = {node for match in matches for node in match.group_nodes}
74
+ _count_uncovered_signatures(
75
+ graph,
76
+ covered,
77
+ uncovered_atoms,
78
+ uncovered_edges,
79
+ )
80
+
81
+ named_ring_nodes = {
82
+ match.group_nodes
83
+ for match in matches
84
+ if match.name != "heteroaromatic_ring"
85
+ and match.pattern.priority == 70
86
+ }
87
+ for system in AromaticRingSystemDetector.detect(graph):
88
+ if not system.hetero_nodes:
89
+ continue
90
+ heteroaromatic_systems += 1
91
+ has_named_subring = any(
92
+ set(nodes).issubset(system.nodes) for nodes in named_ring_nodes
93
+ )
94
+ if has_named_subring:
95
+ named_heteroaromatic_systems += 1
96
+ continue
97
+ unnamed_systems[
98
+ (
99
+ system.hetero_pattern,
100
+ system.is_fused,
101
+ system.ring_sizes,
102
+ tuple(sorted(system.element_counts.items())),
103
+ )
104
+ ] += 1
105
+
106
+ return FunctionalGroupAudit(
107
+ reactions=reaction_count,
108
+ molecules=molecule_count,
109
+ parse_failures=parse_failures,
110
+ elapsed_seconds=perf_counter() - started,
111
+ label_counts=label_counts,
112
+ heteroaromatic_systems=heteroaromatic_systems,
113
+ named_heteroaromatic_systems=named_heteroaromatic_systems,
114
+ unnamed_heteroaromatic_systems=unnamed_systems,
115
+ uncovered_atom_signatures=uncovered_atoms,
116
+ uncovered_edge_signatures=uncovered_edges,
117
+ )
118
+
119
+
120
+ def _count_uncovered_signatures(
121
+ graph: nx.Graph,
122
+ covered: set[int],
123
+ atom_counts: Counter[tuple],
124
+ edge_counts: Counter[tuple],
125
+ ) -> None:
126
+ for node, data in graph.nodes(data=True):
127
+ if data.get("element") == "H" or node in covered:
128
+ continue
129
+ neighbors = tuple(
130
+ sorted(
131
+ graph.nodes[neighbor].get("element")
132
+ for neighbor in graph.neighbors(node)
133
+ if graph.nodes[neighbor].get("element") != "H"
134
+ )
135
+ )
136
+ atom_counts[
137
+ (
138
+ data.get("element"),
139
+ data.get("aromatic", False),
140
+ data.get("hcount", 0),
141
+ neighbors,
142
+ )
143
+ ] += 1
144
+
145
+ for left, right, data in graph.edges(data=True):
146
+ if left in covered or right in covered:
147
+ continue
148
+ left_element = graph.nodes[left].get("element")
149
+ right_element = graph.nodes[right].get("element")
150
+ if "H" in {left_element, right_element}:
151
+ continue
152
+ edge_counts[
153
+ tuple(sorted((left_element, right_element)))
154
+ + (data.get("order"), data.get("aromatic", False))
155
+ ] += 1