synkit 1.6.5__py3-none-win_amd64.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.
Files changed (636) hide show
  1. synkit/CRN/Benchmark/__init__.py +53 -0
  2. synkit/CRN/Benchmark/crosschecks.py +13 -0
  3. synkit/CRN/Benchmark/kegg.py +12 -0
  4. synkit/CRN/Benchmark/networks.py +13 -0
  5. synkit/CRN/Benchmark/scaling.py +13 -0
  6. synkit/CRN/Benchmark/validate.py +13 -0
  7. synkit/CRN/Construct/__init__.py +16 -0
  8. synkit/CRN/Construct/abstract.py +668 -0
  9. synkit/CRN/Construct/arity.py +36 -0
  10. synkit/CRN/Construct/builder.py +619 -0
  11. synkit/CRN/Construct/derivation.py +63 -0
  12. synkit/CRN/Construct/flattener.py +100 -0
  13. synkit/CRN/Construct/keys.py +14 -0
  14. synkit/CRN/Construct/mixtures.py +117 -0
  15. synkit/CRN/Construct/rdkit_worker.py +69 -0
  16. synkit/CRN/Construct/smiles.py +99 -0
  17. synkit/CRN/Construct/state.py +31 -0
  18. synkit/CRN/Construct/strategy.py +75 -0
  19. synkit/CRN/Construct/worker.py +42 -0
  20. synkit/CRN/IO/__init__.py +36 -0
  21. synkit/CRN/IO/sbml.py +925 -0
  22. synkit/CRN/Pathway/__init__.py +72 -0
  23. synkit/CRN/Pathway/_adapter.py +333 -0
  24. synkit/CRN/Pathway/pathfinder.py +500 -0
  25. synkit/CRN/Pathway/reachability.py +796 -0
  26. synkit/CRN/Pathway/realizability.py +1322 -0
  27. synkit/CRN/Petrinet/__init__.py +93 -0
  28. synkit/CRN/Petrinet/analyzer.py +486 -0
  29. synkit/CRN/Petrinet/minimal_semiflows.py +436 -0
  30. synkit/CRN/Petrinet/net.py +1041 -0
  31. synkit/CRN/Petrinet/persistence.py +97 -0
  32. synkit/CRN/Petrinet/semiflows.py +483 -0
  33. synkit/CRN/Petrinet/siphon_search.py +402 -0
  34. synkit/CRN/Petrinet/structure.py +286 -0
  35. synkit/CRN/Props/__init__.py +130 -0
  36. synkit/CRN/Props/_rank.py +29 -0
  37. synkit/CRN/Props/deficiency.py +953 -0
  38. synkit/CRN/Props/dynamics.py +832 -0
  39. synkit/CRN/Props/helper.py +151 -0
  40. synkit/CRN/Props/stoich.py +751 -0
  41. synkit/CRN/Props/thermo.py +584 -0
  42. synkit/CRN/Query/__init__.py +66 -0
  43. synkit/CRN/Query/cache.py +41 -0
  44. synkit/CRN/Query/kegg_api.py +99 -0
  45. synkit/CRN/Query/kegg_extract.py +714 -0
  46. synkit/CRN/Query/kegg_impute.py +707 -0
  47. synkit/CRN/Query/kegg_parse.py +480 -0
  48. synkit/CRN/Query/to_syncrn.py +290 -0
  49. synkit/CRN/README.md +234 -0
  50. synkit/CRN/Structure/__init__.py +12 -0
  51. synkit/CRN/Structure/_graph_io.py +713 -0
  52. synkit/CRN/Structure/_matrices.py +88 -0
  53. synkit/CRN/Structure/_parse.py +544 -0
  54. synkit/CRN/Structure/reaction.py +237 -0
  55. synkit/CRN/Structure/rule.py +55 -0
  56. synkit/CRN/Structure/species.py +46 -0
  57. synkit/CRN/Structure/syncrn.py +929 -0
  58. synkit/CRN/Symmetry/__init__.py +20 -0
  59. synkit/CRN/Symmetry/_common.py +1059 -0
  60. synkit/CRN/Symmetry/_ir.py +940 -0
  61. synkit/CRN/Symmetry/automorphism.py +472 -0
  62. synkit/CRN/Symmetry/canon.py +441 -0
  63. synkit/CRN/Symmetry/isomorphism.py +412 -0
  64. synkit/CRN/Symmetry/symmetry.py +61 -0
  65. synkit/CRN/Symmetry/wl_canon.py +967 -0
  66. synkit/CRN/Visualize/__init__.py +11 -0
  67. synkit/CRN/Visualize/labels.py +113 -0
  68. synkit/CRN/Visualize/layout.py +708 -0
  69. synkit/CRN/Visualize/palette.py +292 -0
  70. synkit/CRN/Visualize/validation.py +122 -0
  71. synkit/CRN/Visualize/vis.py +1152 -0
  72. synkit/CRN/__init__.py +233 -0
  73. synkit/CRN/_build.py +50 -0
  74. synkit/CRN/_native_build.py +175 -0
  75. synkit/CRN/analysis.py +629 -0
  76. synkit/CRN/backend.py +74 -0
  77. synkit/CRN/cpp/CMakeLists.txt +58 -0
  78. synkit/CRN/cpp/algebra.cpp +46 -0
  79. synkit/CRN/cpp/closure.cpp +29 -0
  80. synkit/CRN/cpp/exact.h +55 -0
  81. synkit/CRN/cpp/pathway.cpp +46 -0
  82. synkit/CRN/cpp/semiflows.cpp +209 -0
  83. synkit/CRN/cpp/structural.cpp +240 -0
  84. synkit/CRN/cpp/symmetry.cpp +45 -0
  85. synkit/CRN/cpp/write_manifest.cmake +28 -0
  86. synkit/CRN/kinds.py +137 -0
  87. synkit/CRN/lib/synkit_crn.dll +0 -0
  88. synkit/CRN/lib/synkit_crn.json +33 -0
  89. synkit/CRN/native.py +388 -0
  90. synkit/CRN/native_analysis.py +459 -0
  91. synkit/Chem/Cluster/__init__.py +0 -0
  92. synkit/Chem/Cluster/butina.py +140 -0
  93. synkit/Chem/Fingerprint/__init__.py +0 -0
  94. synkit/Chem/Fingerprint/fp_calculator.py +155 -0
  95. synkit/Chem/Fingerprint/smiles_featurizer.py +258 -0
  96. synkit/Chem/Fingerprint/transformation_fp.py +139 -0
  97. synkit/Chem/Mapper/README.rst +43 -0
  98. synkit/Chem/Mapper/__init__.py +255 -0
  99. synkit/Chem/Mapper/_compat.py +130 -0
  100. synkit/Chem/Mapper/adapters/__init__.py +1 -0
  101. synkit/Chem/Mapper/adapters/prediction.py +126 -0
  102. synkit/Chem/Mapper/adapters/template.py +412 -0
  103. synkit/Chem/Mapper/chem/__init__.py +52 -0
  104. synkit/Chem/Mapper/chem/aam.py +673 -0
  105. synkit/Chem/Mapper/chem/blind.py +160 -0
  106. synkit/Chem/Mapper/chem/its.py +309 -0
  107. synkit/Chem/Mapper/chem/smiles.py +564 -0
  108. synkit/Chem/Mapper/graph/__init__.py +66 -0
  109. synkit/Chem/Mapper/graph/automorphism.py +395 -0
  110. synkit/Chem/Mapper/graph/blockcut.py +98 -0
  111. synkit/Chem/Mapper/graph/labeled_graph.py +104 -0
  112. synkit/Chem/Mapper/graph/refine.py +176 -0
  113. synkit/Chem/Mapper/graph/synkit_adapter.py +110 -0
  114. synkit/Chem/Mapper/io/__init__.py +13 -0
  115. synkit/Chem/Mapper/io/idxmapstr.py +82 -0
  116. synkit/Chem/Mapper/mapper.py +685 -0
  117. synkit/Chem/Mapper/reaction_search.py +554 -0
  118. synkit/Chem/Mapper/reporting/__init__.py +1 -0
  119. synkit/Chem/Mapper/reporting/alternatives.py +451 -0
  120. synkit/Chem/Mapper/reporting/analysis.py +681 -0
  121. synkit/Chem/Mapper/reporting/native_analysis.py +485 -0
  122. synkit/Chem/Mapper/reporting/spectrum.py +642 -0
  123. synkit/Chem/Mapper/solvers/__init__.py +1 -0
  124. synkit/Chem/Mapper/solvers/exact/__init__.py +141 -0
  125. synkit/Chem/Mapper/solvers/exact/assignment/__init__.py +1 -0
  126. synkit/Chem/Mapper/solvers/exact/assignment/assignment_certificate.py +113 -0
  127. synkit/Chem/Mapper/solvers/exact/assignment/assignment_domains.py +162 -0
  128. synkit/Chem/Mapper/solvers/exact/assignment/assignment_verification.py +58 -0
  129. synkit/Chem/Mapper/solvers/exact/assignment/incremental_assignment.py +247 -0
  130. synkit/Chem/Mapper/solvers/exact/certificate.py +128 -0
  131. synkit/Chem/Mapper/solvers/exact/core.py +183 -0
  132. synkit/Chem/Mapper/solvers/exact/distance_search/__init__.py +1 -0
  133. synkit/Chem/Mapper/solvers/exact/distance_search/bounds.py +319 -0
  134. synkit/Chem/Mapper/solvers/exact/distance_search/exhaustive.py +179 -0
  135. synkit/Chem/Mapper/solvers/exact/distance_search/inputs.py +283 -0
  136. synkit/Chem/Mapper/solvers/exact/distance_search/records.py +242 -0
  137. synkit/Chem/Mapper/solvers/exact/distance_search/search.py +1025 -0
  138. synkit/Chem/Mapper/solvers/exact/distance_search/verify.py +378 -0
  139. synkit/Chem/Mapper/solvers/exact/edit_support.py +375 -0
  140. synkit/Chem/Mapper/solvers/exact/hybrid.py +224 -0
  141. synkit/Chem/Mapper/solvers/exact/hydrogen.py +264 -0
  142. synkit/Chem/Mapper/solvers/exact/kernel_solvers/__init__.py +1 -0
  143. synkit/Chem/Mapper/solvers/exact/kernel_solvers/branching.py +499 -0
  144. synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumerate.py +1050 -0
  145. synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumeration_result.py +30 -0
  146. synkit/Chem/Mapper/solvers/exact/kernel_solvers/kernel.py +256 -0
  147. synkit/Chem/Mapper/solvers/exact/kernel_solvers/milp.py +194 -0
  148. synkit/Chem/Mapper/solvers/exact/native/__init__.py +1 -0
  149. synkit/Chem/Mapper/solvers/exact/native/build.py +154 -0
  150. synkit/Chem/Mapper/solvers/exact/native/candidates.py +593 -0
  151. synkit/Chem/Mapper/solvers/exact/native/canonical.py +396 -0
  152. synkit/Chem/Mapper/solvers/exact/native/disk_frontier.py +415 -0
  153. synkit/Chem/Mapper/solvers/exact/native/frontier.py +390 -0
  154. synkit/Chem/Mapper/solvers/exact/native/hydrogen_quotient.py +213 -0
  155. synkit/Chem/Mapper/solvers/exact/native/its.py +528 -0
  156. synkit/Chem/Mapper/solvers/exact/native/native_distance.cpp +2803 -0
  157. synkit/Chem/Mapper/solvers/exact/native/orbit_aggregation.py +328 -0
  158. synkit/Chem/Mapper/solvers/exact/native/parallel.py +205 -0
  159. synkit/Chem/Mapper/solvers/exact/native/pmcd.py +203 -0
  160. synkit/Chem/Mapper/solvers/exact/native/runtime.py +40 -0
  161. synkit/Chem/Mapper/solvers/exact/native/search.py +294 -0
  162. synkit/Chem/Mapper/solvers/exact/native/separator.py +224 -0
  163. synkit/Chem/Mapper/solvers/exact/native_build.py +12 -0
  164. synkit/Chem/Mapper/solvers/exact/pabs/__init__.py +1 -0
  165. synkit/Chem/Mapper/solvers/exact/pabs/cost_lattice.py +43 -0
  166. synkit/Chem/Mapper/solvers/exact/pabs/factor_spectrum.py +110 -0
  167. synkit/Chem/Mapper/solvers/exact/pabs/multi_shell.py +368 -0
  168. synkit/Chem/Mapper/solvers/exact/pabs/propagation.py +679 -0
  169. synkit/Chem/Mapper/solvers/exact/pabs/propagation_bounds.py +436 -0
  170. synkit/Chem/Mapper/solvers/exact/pabs/propagation_limits.py +13 -0
  171. synkit/Chem/Mapper/solvers/exact/pabs/propagation_search.py +856 -0
  172. synkit/Chem/Mapper/solvers/exact/pabs/propagation_symmetry.py +66 -0
  173. synkit/Chem/Mapper/solvers/exact/pabs/residual_typed_bonds.py +136 -0
  174. synkit/Chem/Mapper/solvers/exact/pabs/reward_frontier.py +201 -0
  175. synkit/Chem/Mapper/solvers/exact/pabs/separator_bound.py +258 -0
  176. synkit/Chem/Mapper/solvers/exact/pabs/separator_spectrum.py +308 -0
  177. synkit/Chem/Mapper/solvers/exact/pabs/sparse_reward_bound.py +207 -0
  178. synkit/Chem/Mapper/solvers/exact/pabs/suffix_spectrum.py +299 -0
  179. synkit/Chem/Mapper/solvers/exact/search.py +55 -0
  180. synkit/Chem/Mapper/solvers/exact/seeds/__init__.py +1 -0
  181. synkit/Chem/Mapper/solvers/exact/seeds/seed.py +104 -0
  182. synkit/Chem/Mapper/solvers/exact/seeds/seed_fragments.py +148 -0
  183. synkit/Chem/Mapper/solvers/exact/seeds/seed_relaxation.py +181 -0
  184. synkit/Chem/Mapper/solvers/exact/symmetry.py +223 -0
  185. synkit/Chem/Mapper/solvers/native/__init__.py +4 -0
  186. synkit/Chem/Mapper/solvers/native/assignment.py +99 -0
  187. synkit/Chem/Mapper/solvers/native/astar.py +22 -0
  188. synkit/Chem/Mapper/solvers/native/build.py +385 -0
  189. synkit/Chem/Mapper/solvers/native/classification.py +641 -0
  190. synkit/Chem/Mapper/solvers/native/core.py +378 -0
  191. synkit/Chem/Mapper/solvers/native/cpp/CMakeLists.txt +120 -0
  192. synkit/Chem/Mapper/solvers/native/cpp/examples/map_reaction.cpp +29 -0
  193. synkit/Chem/Mapper/solvers/native/cpp/examples/slap_graph.cpp +63 -0
  194. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/assignment/assignment.h +18 -0
  195. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/astar.h +18 -0
  196. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/bound.h +33 -0
  197. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/pmcd_witness.h +16 -0
  198. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/runtime.h +130 -0
  199. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/hydrogen/hydrogen.h +73 -0
  200. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mapper.h +175 -0
  201. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mces/mces.h +9 -0
  202. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/pabs/seed.h +34 -0
  203. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/reaction/reaction.h +30 -0
  204. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/sepdp/sepdp.h +21 -0
  205. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/slap.h +72 -0
  206. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/solvers/solvers.h +16 -0
  207. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/classification.h +140 -0
  208. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/cpabs.h +33 -0
  209. synkit/Chem/Mapper/solvers/native/cpp/src/assignment/abb.cpp +302 -0
  210. synkit/Chem/Mapper/solvers/native/cpp/src/astar/CMakeLists.txt +12 -0
  211. synkit/Chem/Mapper/solvers/native/cpp/src/astar/README.md +47 -0
  212. synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar.cpp +228 -0
  213. synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar_graph.cpp +37 -0
  214. synkit/Chem/Mapper/solvers/native/cpp/src/astar/bound.cpp +212 -0
  215. synkit/Chem/Mapper/solvers/native/cpp/src/core/dispatch.cpp +272 -0
  216. synkit/Chem/Mapper/solvers/native/cpp/src/core/pmcd_witness.cpp +36 -0
  217. synkit/Chem/Mapper/solvers/native/cpp/src/hydrogen/hydrogen.cpp +380 -0
  218. synkit/Chem/Mapper/solvers/native/cpp/src/mces/README.md +57 -0
  219. synkit/Chem/Mapper/solvers/native/cpp/src/mces/mces.cpp +287 -0
  220. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/bridge.cpp +334 -0
  221. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/chemical_floor.inc +181 -0
  222. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/endpoint_symmetry.inc +104 -0
  223. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/exact_helpers.h +20 -0
  224. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_assignment_certificate.h +165 -0
  225. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_certificate.h +125 -0
  226. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_model.h +365 -0
  227. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_provider.inc +319 -0
  228. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_rounding.inc +170 -0
  229. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_test_hooks.h +342 -0
  230. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/objective_reduction.inc +137 -0
  231. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/overlap_dual.inc +351 -0
  232. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/profile_seed.inc +214 -0
  233. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/seed_heuristics.inc +640 -0
  234. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_embedding.cpp +430 -0
  235. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_root_lp.h +176 -0
  236. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/test_hooks.inc +262 -0
  237. synkit/Chem/Mapper/solvers/native/cpp/src/reaction/reaction.cpp +611 -0
  238. synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/README.md +61 -0
  239. synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/sepdp.cpp +253 -0
  240. synkit/Chem/Mapper/solvers/native/cpp/src/slap.cpp +810 -0
  241. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/formulation.h +138 -0
  242. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/maxsat.cpp +526 -0
  243. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/ortools.cpp +475 -0
  244. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/seed.h +80 -0
  245. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/weighted_cnf.h +256 -0
  246. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/README.md +43 -0
  247. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/dfs.cpp +123 -0
  248. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/edit_support.cpp +224 -0
  249. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification.cpp +553 -0
  250. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_pipeline.cpp +124 -0
  251. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_stream.h +13 -0
  252. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/cpabs.cpp +455 -0
  253. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/edge_deck.cpp +743 -0
  254. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
  255. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
  256. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naugraph.c +732 -0
  257. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.c +94 -0
  258. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.h +49 -0
  259. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.c +1771 -0
  260. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.h +133 -0
  261. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nautil.c +750 -0
  262. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naututil.h +355 -0
  263. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.c +1256 -0
  264. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.h +1544 -0
  265. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.c +1131 -0
  266. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.h +70 -0
  267. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/sorttemplates.c +580 -0
  268. synkit/Chem/Mapper/solvers/native/hydrogen.py +711 -0
  269. synkit/Chem/Mapper/solvers/native/implicit.py +506 -0
  270. synkit/Chem/Mapper/solvers/native/implicit_certificate.py +187 -0
  271. synkit/Chem/Mapper/solvers/native/implicit_preparation.py +309 -0
  272. synkit/Chem/Mapper/solvers/native/lib/synkit_mapper.dll +0 -0
  273. synkit/Chem/Mapper/solvers/native/mces.py +16 -0
  274. synkit/Chem/Mapper/solvers/native/reaction.py +179 -0
  275. synkit/Chem/Mapper/solvers/native/reaction_build.py +277 -0
  276. synkit/Chem/Mapper/solvers/native/reaction_text.py +26 -0
  277. synkit/Chem/Mapper/solvers/native/runtime.py +242 -0
  278. synkit/Chem/Mapper/solvers/native/sepdp.py +47 -0
  279. synkit/Chem/Mapper/solvers/native/slap.py +266 -0
  280. synkit/Chem/Mapper/solvers/native/solvers.py +67 -0
  281. synkit/Chem/Mapper/solvers/native/stereo.py +86 -0
  282. synkit/Chem/Mapper/solvers/native/supporting.py +34 -0
  283. synkit/Chem/Mapper/solvers/native/symmetry.py +91 -0
  284. synkit/Chem/Mapper/solvers/slap/__init__.py +29 -0
  285. synkit/Chem/Mapper/solvers/slap/lap.py +174 -0
  286. synkit/Chem/Mapper/solvers/slap/sequential.py +696 -0
  287. synkit/Chem/Mapper/validation/__init__.py +1 -0
  288. synkit/Chem/Mapper/validation/aam_validator.py +442 -0
  289. synkit/Chem/Mapper/validation/annotations.py +274 -0
  290. synkit/Chem/Mapper/validation/bonds.py +124 -0
  291. synkit/Chem/Mapper/validation/cohorts.py +72 -0
  292. synkit/Chem/Mapper/validation/identifiability.py +150 -0
  293. synkit/Chem/Mapper/validation/numerical_scope.py +36 -0
  294. synkit/Chem/Mapper/validation/orbits.py +137 -0
  295. synkit/Chem/Molecule/__init__.py +0 -0
  296. synkit/Chem/Molecule/_chirality_loci.py +165 -0
  297. synkit/Chem/Molecule/_chirality_types.py +231 -0
  298. synkit/Chem/Molecule/_helical_loci.py +167 -0
  299. synkit/Chem/Molecule/_stereo_axis_evidence.py +202 -0
  300. synkit/Chem/Molecule/_stereo_element_detection.py +193 -0
  301. synkit/Chem/Molecule/_stereo_orientation_constraints.py +511 -0
  302. synkit/Chem/Molecule/_tetrahedral_carriers.py +63 -0
  303. synkit/Chem/Molecule/atom_features.py +379 -0
  304. synkit/Chem/Molecule/chirality.py +1041 -0
  305. synkit/Chem/Molecule/cip_assignment.py +569 -0
  306. synkit/Chem/Molecule/cip_ranking.py +843 -0
  307. synkit/Chem/Molecule/coordinate_stereo.py +503 -0
  308. synkit/Chem/Molecule/derived_stereo_naming.py +165 -0
  309. synkit/Chem/Molecule/descriptors.py +452 -0
  310. synkit/Chem/Molecule/formula.py +249 -0
  311. synkit/Chem/Molecule/global_stereo.py +175 -0
  312. synkit/Chem/Molecule/graph_annotator.py +300 -0
  313. synkit/Chem/Molecule/standardize.py +817 -0
  314. synkit/Chem/Molecule/stereo_evidence.py +179 -0
  315. synkit/Chem/Molecule/stereo_perception.py +1032 -0
  316. synkit/Chem/Molecule/valence.py +123 -0
  317. synkit/Chem/Reaction/Mapper/__init__.py +44 -0
  318. synkit/Chem/Reaction/__init__.py +20 -0
  319. synkit/Chem/Reaction/aam_validator.py +5 -0
  320. synkit/Chem/Reaction/balance_check.py +138 -0
  321. synkit/Chem/Reaction/canon_rsmi.py +249 -0
  322. synkit/Chem/Reaction/cleaning.py +58 -0
  323. synkit/Chem/Reaction/deionize.py +199 -0
  324. synkit/Chem/Reaction/explicit_h_audit.py +232 -0
  325. synkit/Chem/Reaction/fix_aam.py +64 -0
  326. synkit/Chem/Reaction/neutralize.py +207 -0
  327. synkit/Chem/Reaction/radical_wildcard.py +224 -0
  328. synkit/Chem/Reaction/standardize.py +203 -0
  329. synkit/Chem/Reaction/tautomerize.py +205 -0
  330. synkit/Chem/__init__.py +1 -0
  331. synkit/Chem/utils.py +315 -0
  332. synkit/Data/__init__.py +0 -0
  333. synkit/Data/aldol.json.gz +1 -0
  334. synkit/Data/gen_partial_aam.py +147 -0
  335. synkit/Data/paracetamol.json.gz +1 -0
  336. synkit/Graph/Canon/__init__.py +16 -0
  337. synkit/Graph/Canon/_native/__init__.py +13 -0
  338. synkit/Graph/Canon/_native/build.py +93 -0
  339. synkit/Graph/Canon/_native/lib/synkit_canon.dll +0 -0
  340. synkit/Graph/Canon/_native/prepare.py +49 -0
  341. synkit/Graph/Canon/_native/runtime.py +140 -0
  342. synkit/Graph/Canon/_native/search.py +137 -0
  343. synkit/Graph/Canon/canon_algs.py +228 -0
  344. synkit/Graph/Canon/canon_graph.py +531 -0
  345. synkit/Graph/Canon/cpp/CMakeLists.txt +42 -0
  346. synkit/Graph/Canon/cpp/README.md +123 -0
  347. synkit/Graph/Canon/cpp/examples/canonical_graph.cpp +16 -0
  348. synkit/Graph/Canon/cpp/include/synkit_canon/canon.h +85 -0
  349. synkit/Graph/Canon/cpp/src/canonical.cpp +391 -0
  350. synkit/Graph/Canon/cpp/src/symmetry.h +83 -0
  351. synkit/Graph/Canon/cpp/tests/symmetry.cpp +93 -0
  352. synkit/Graph/Canon/exact.py +1020 -0
  353. synkit/Graph/Canon/exact_refinement.py +368 -0
  354. synkit/Graph/Canon/nauty.py +143 -0
  355. synkit/Graph/Context/__init__.py +0 -0
  356. synkit/Graph/Context/hier_context.py +244 -0
  357. synkit/Graph/Context/radius_expand.py +252 -0
  358. synkit/Graph/FG/__init__.py +19 -0
  359. synkit/Graph/FG/api.py +39 -0
  360. synkit/Graph/FG/audit.py +155 -0
  361. synkit/Graph/FG/catalog.py +919 -0
  362. synkit/Graph/FG/detector.py +288 -0
  363. synkit/Graph/FG/model.py +97 -0
  364. synkit/Graph/FG/recognizers.py +274 -0
  365. synkit/Graph/FG/ring_system.py +154 -0
  366. synkit/Graph/Feature/Descriptors/topology.py +857 -0
  367. synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
  368. synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +222 -0
  369. synkit/Graph/Feature/__init__.py +5 -0
  370. synkit/Graph/Feature/graph_descriptors.py +323 -0
  371. synkit/Graph/Feature/graph_fps.py +96 -0
  372. synkit/Graph/Feature/graph_signature.py +239 -0
  373. synkit/Graph/Feature/hash_fps.py +133 -0
  374. synkit/Graph/Feature/morgan_fps.py +88 -0
  375. synkit/Graph/Feature/path_fps.py +81 -0
  376. synkit/Graph/Feature/wl_hash.py +134 -0
  377. synkit/Graph/Fusion/__init__.py +85 -0
  378. synkit/Graph/Fusion/candidate.py +559 -0
  379. synkit/Graph/Fusion/constructor.py +877 -0
  380. synkit/Graph/Fusion/identity.py +184 -0
  381. synkit/Graph/Fusion/interface.py +700 -0
  382. synkit/Graph/Fusion/search.py +241 -0
  383. synkit/Graph/Hyrogen/__init__.py +6 -0
  384. synkit/Graph/Hyrogen/_misc.py +591 -0
  385. synkit/Graph/Hyrogen/hcomplete.py +995 -0
  386. synkit/Graph/Hyrogen/hcomplete_legacy.py +368 -0
  387. synkit/Graph/Hyrogen/hcompletion_algorithms.py +713 -0
  388. synkit/Graph/Hyrogen/hextend.py +570 -0
  389. synkit/Graph/Hyrogen/hextend_legacy.py +215 -0
  390. synkit/Graph/ITS/__init__.py +4 -0
  391. synkit/Graph/ITS/its_builder.py +120 -0
  392. synkit/Graph/ITS/its_construction.py +719 -0
  393. synkit/Graph/ITS/its_decompose.py +572 -0
  394. synkit/Graph/ITS/its_destruction.py +331 -0
  395. synkit/Graph/ITS/its_expand.py +1251 -0
  396. synkit/Graph/ITS/its_relabel.py +187 -0
  397. synkit/Graph/ITS/its_reverter.py +356 -0
  398. synkit/Graph/ITS/normalize_aam.py +145 -0
  399. synkit/Graph/ITS/partial_its.py +238 -0
  400. synkit/Graph/ITS/rc_extractor.py +656 -0
  401. synkit/Graph/ITS/stereo.py +74 -0
  402. synkit/Graph/MTG/__init__.py +107 -0
  403. synkit/Graph/MTG/gluing.py +451 -0
  404. synkit/Graph/MTG/history.py +928 -0
  405. synkit/Graph/MTG/inventory.py +118 -0
  406. synkit/Graph/MTG/local.py +447 -0
  407. synkit/Graph/MTG/mcs_matcher.py +246 -0
  408. synkit/Graph/MTG/mtg.py +611 -0
  409. synkit/Graph/MTG/mtg_explore.py +74 -0
  410. synkit/Graph/MTG/observation.py +209 -0
  411. synkit/Graph/MTG/process.py +577 -0
  412. synkit/Graph/MTG/queries.py +66 -0
  413. synkit/Graph/MTG/realization.py +95 -0
  414. synkit/Graph/MTG/series_parallel.py +107 -0
  415. synkit/Graph/MTG/utils.py +424 -0
  416. synkit/Graph/Matcher/__init__.py +10 -0
  417. synkit/Graph/Matcher/approx_mcs.py +1264 -0
  418. synkit/Graph/Matcher/auto_est.py +736 -0
  419. synkit/Graph/Matcher/automorphism.py +314 -0
  420. synkit/Graph/Matcher/batch_cluster.py +224 -0
  421. synkit/Graph/Matcher/dedup_matches.py +247 -0
  422. synkit/Graph/Matcher/graph_cluster.py +191 -0
  423. synkit/Graph/Matcher/graph_matcher.py +312 -0
  424. synkit/Graph/Matcher/graph_morphism.py +421 -0
  425. synkit/Graph/Matcher/mcs_matcher.py +804 -0
  426. synkit/Graph/Matcher/multi_turbo_iso.py +186 -0
  427. synkit/Graph/Matcher/orbit.py +284 -0
  428. synkit/Graph/Matcher/partial_matcher.py +694 -0
  429. synkit/Graph/Matcher/sing.py +544 -0
  430. synkit/Graph/Matcher/subgraph_matcher.py +812 -0
  431. synkit/Graph/Matcher/turbo_iso.py +272 -0
  432. synkit/Graph/Matcher/wl_sel.py +537 -0
  433. synkit/Graph/Mech/__init__.py +26 -0
  434. synkit/Graph/Mech/conversion.py +1466 -0
  435. synkit/Graph/Mech/conversion_debug.py +237 -0
  436. synkit/Graph/Mech/electron_accounting.py +200 -0
  437. synkit/Graph/Mech/lwg_editor.py +406 -0
  438. synkit/Graph/Mech/lwg_ops.py +313 -0
  439. synkit/Graph/Morphism/__init__.py +99 -0
  440. synkit/Graph/Morphism/constraints.py +460 -0
  441. synkit/Graph/Morphism/llg.py +999 -0
  442. synkit/Graph/Morphism/morphism.py +349 -0
  443. synkit/Graph/Morphism/stereo.py +258 -0
  444. synkit/Graph/Morphism/stereo_morphism.py +383 -0
  445. synkit/Graph/Morphism/stereo_morphism_helpers.py +957 -0
  446. synkit/Graph/Morphism/stereo_morphism_types.py +117 -0
  447. synkit/Graph/Stereo/__init__.py +376 -0
  448. synkit/Graph/Stereo/_descriptor_core.py +207 -0
  449. synkit/Graph/Stereo/_descriptor_serialization.py +138 -0
  450. synkit/Graph/Stereo/canonical.py +648 -0
  451. synkit/Graph/Stereo/changes.py +964 -0
  452. synkit/Graph/Stereo/composition.py +391 -0
  453. synkit/Graph/Stereo/configured.py +946 -0
  454. synkit/Graph/Stereo/couplings.py +245 -0
  455. synkit/Graph/Stereo/descriptors.py +1030 -0
  456. synkit/Graph/Stereo/enumeration.py +597 -0
  457. synkit/Graph/Stereo/extended_descriptors.py +406 -0
  458. synkit/Graph/Stereo/global_configured.py +152 -0
  459. synkit/Graph/Stereo/global_stereo.py +304 -0
  460. synkit/Graph/Stereo/identity.py +648 -0
  461. synkit/Graph/Stereo/interchange.py +496 -0
  462. synkit/Graph/Stereo/legacy.py +460 -0
  463. synkit/Graph/Stereo/matching.py +899 -0
  464. synkit/Graph/Stereo/native.py +154 -0
  465. synkit/Graph/Stereo/orbits.py +668 -0
  466. synkit/Graph/Stereo/outcomes.py +99 -0
  467. synkit/Graph/Stereo/pairwise.py +350 -0
  468. synkit/Graph/Stereo/rdkit_adapter.py +662 -0
  469. synkit/Graph/Stereo/rdkit_identity.py +118 -0
  470. synkit/Graph/Stereo/rdkit_resonance.py +140 -0
  471. synkit/Graph/Stereo/reaction_interchange.py +266 -0
  472. synkit/Graph/Stereo/semantics.py +296 -0
  473. synkit/Graph/Stereo/supports.py +257 -0
  474. synkit/Graph/Stereo/wire.py +339 -0
  475. synkit/Graph/Wildcard/__init__.py +0 -0
  476. synkit/Graph/Wildcard/fuse_graph.py +156 -0
  477. synkit/Graph/Wildcard/graph_wc.py +303 -0
  478. synkit/Graph/Wildcard/its_merge.py +857 -0
  479. synkit/Graph/Wildcard/radwc.py +114 -0
  480. synkit/Graph/Wildcard/wc_matcher.py +576 -0
  481. synkit/Graph/Wildcard/wildcard.py +225 -0
  482. synkit/Graph/__init__.py +17 -0
  483. synkit/Graph/canon_graph.py +14 -0
  484. synkit/Graph/syn_graph.py +199 -0
  485. synkit/Graph/utils.py +324 -0
  486. synkit/IO/__init__.py +4 -0
  487. synkit/IO/chem_converter.py +1059 -0
  488. synkit/IO/combinatorial/__init__.py +8 -0
  489. synkit/IO/combinatorial/gml_to_graph.py +223 -0
  490. synkit/IO/combinatorial/graph_to_gml.py +280 -0
  491. synkit/IO/combinatorial/graph_to_smarts.py +186 -0
  492. synkit/IO/combinatorial/smarts_expander.py +147 -0
  493. synkit/IO/combinatorial/smarts_generalizer.py +133 -0
  494. synkit/IO/combinatorial/smarts_to_graph.py +179 -0
  495. synkit/IO/conversion.py +42 -0
  496. synkit/IO/data_io.py +269 -0
  497. synkit/IO/data_process.py +143 -0
  498. synkit/IO/debug.py +73 -0
  499. synkit/IO/gml_to_nx.py +150 -0
  500. synkit/IO/graph_to_mol.py +199 -0
  501. synkit/IO/mol_to_graph.py +1105 -0
  502. synkit/IO/mol_to_graph_chemistry.py +545 -0
  503. synkit/IO/nx_to_gml.py +209 -0
  504. synkit/IO/smiles_to_id.py +123 -0
  505. synkit/Mechanism/__init__.py +151 -0
  506. synkit/Mechanism/adapters.py +136 -0
  507. synkit/Mechanism/audit.py +323 -0
  508. synkit/Mechanism/benchmark.py +638 -0
  509. synkit/Mechanism/compatibility.py +13 -0
  510. synkit/Mechanism/drawing.py +85 -0
  511. synkit/Mechanism/electron_models.py +725 -0
  512. synkit/Mechanism/equivalence.py +521 -0
  513. synkit/Mechanism/evidence.py +262 -0
  514. synkit/Mechanism/interchange.py +141 -0
  515. synkit/Mechanism/model.py +918 -0
  516. synkit/Mechanism/neighbor_stereo.py +312 -0
  517. synkit/Mechanism/radical_data.py +740 -0
  518. synkit/Mechanism/replay.py +986 -0
  519. synkit/Mechanism/schema.py +264 -0
  520. synkit/Mechanism/stereo_state.py +416 -0
  521. synkit/Mechanism/symbols.py +91 -0
  522. synkit/Rule/Apply/__init__.py +35 -0
  523. synkit/Rule/Apply/conditions.py +45 -0
  524. synkit/Rule/Apply/dpo.py +998 -0
  525. synkit/Rule/Apply/rule_matcher.py +218 -0
  526. synkit/Rule/Apply/validation.py +354 -0
  527. synkit/Rule/Compose/__init__.py +106 -0
  528. synkit/Rule/Compose/_identity.py +43 -0
  529. synkit/Rule/Compose/composition.py +976 -0
  530. synkit/Rule/Compose/laws.py +439 -0
  531. synkit/Rule/Compose/search.py +771 -0
  532. synkit/Rule/Compose/synrule.py +170 -0
  533. synkit/Rule/Modify/__init__.py +0 -0
  534. synkit/Rule/Modify/implict_rule.py +56 -0
  535. synkit/Rule/Modify/longest_path.py +92 -0
  536. synkit/Rule/Modify/molecule_rule.py +115 -0
  537. synkit/Rule/Modify/prune_templates.py +78 -0
  538. synkit/Rule/Modify/rule_utils.py +194 -0
  539. synkit/Rule/Modify/strip_rule.py +97 -0
  540. synkit/Rule/__init__.py +28 -0
  541. synkit/Rule/generic_stereo.py +884 -0
  542. synkit/Rule/stereo_identity.py +271 -0
  543. synkit/Rule/syn_rule.py +1090 -0
  544. synkit/Synthesis/MSR/__init__.py +0 -0
  545. synkit/Synthesis/MSR/path_finder.py +239 -0
  546. synkit/Synthesis/Metrics/__init__.py +0 -0
  547. synkit/Synthesis/Metrics/_base.py +52 -0
  548. synkit/Synthesis/Metrics/_plot.py +129 -0
  549. synkit/Synthesis/Metrics/_ranking.py +179 -0
  550. synkit/Synthesis/RBL/__init__.py +80 -0
  551. synkit/Synthesis/RBL/engine.py +1249 -0
  552. synkit/Synthesis/RBL/matching.py +652 -0
  553. synkit/Synthesis/RBL/overlap.py +336 -0
  554. synkit/Synthesis/RBL/pipeline.py +376 -0
  555. synkit/Synthesis/RBL/policy.py +139 -0
  556. synkit/Synthesis/RBL/proof.py +370 -0
  557. synkit/Synthesis/RBL/reaction.py +506 -0
  558. synkit/Synthesis/RBL/state.py +169 -0
  559. synkit/Synthesis/RBL/validation.py +1060 -0
  560. synkit/Synthesis/Reactor/__init__.py +60 -0
  561. synkit/Synthesis/Reactor/core/__init__.py +1 -0
  562. synkit/Synthesis/Reactor/core/engine.py +967 -0
  563. synkit/Synthesis/Reactor/core/product.py +621 -0
  564. synkit/Synthesis/Reactor/core/rewrite.py +561 -0
  565. synkit/Synthesis/Reactor/core/strategy.py +44 -0
  566. synkit/Synthesis/Reactor/matching/__init__.py +1 -0
  567. synkit/Synthesis/Reactor/matching/mixin.py +920 -0
  568. synkit/Synthesis/Reactor/matching/policy.py +345 -0
  569. synkit/Synthesis/Reactor/matching/symmetry.py +309 -0
  570. synkit/Synthesis/Reactor/output/__init__.py +1 -0
  571. synkit/Synthesis/Reactor/output/deduplication.py +703 -0
  572. synkit/Synthesis/Reactor/output/policy.py +16 -0
  573. synkit/Synthesis/Reactor/output/serialization.py +485 -0
  574. synkit/Synthesis/Reactor/output/structural.py +893 -0
  575. synkit/Synthesis/Reactor/stereo/__init__.py +1 -0
  576. synkit/Synthesis/Reactor/stereo/assignment.py +35 -0
  577. synkit/Synthesis/Reactor/stereo/mixin.py +780 -0
  578. synkit/Synthesis/Reactor/variants/__init__.py +1 -0
  579. synkit/Synthesis/Reactor/variants/imbalanced.py +180 -0
  580. synkit/Synthesis/Reactor/variants/partial.py +84 -0
  581. synkit/Synthesis/Reactor/workflow/__init__.py +1 -0
  582. synkit/Synthesis/Reactor/workflow/batch.py +550 -0
  583. synkit/Synthesis/Reactor/workflow/benchmark.py +143 -0
  584. synkit/Synthesis/Reactor/workflow/postprocess.py +267 -0
  585. synkit/Synthesis/Reactor/workflow/rule_filter.py +210 -0
  586. synkit/Synthesis/__init__.py +0 -0
  587. synkit/Synthesis/reactor_utils.py +316 -0
  588. synkit/Utils/__init__.py +0 -0
  589. synkit/Utils/utils.py +172 -0
  590. synkit/Vis/__init__.py +91 -0
  591. synkit/Vis/crn/__init__.py +40 -0
  592. synkit/Vis/epd/__init__.py +20 -0
  593. synkit/Vis/epd/arrows.py +425 -0
  594. synkit/Vis/epd/chem.py +197 -0
  595. synkit/Vis/epd/constants.py +83 -0
  596. synkit/Vis/epd/layout.py +283 -0
  597. synkit/Vis/epd/mapping.py +51 -0
  598. synkit/Vis/epd/models.py +136 -0
  599. synkit/Vis/epd/render.py +543 -0
  600. synkit/Vis/epd/utils.py +108 -0
  601. synkit/Vis/epd/visualizer.py +811 -0
  602. synkit/Vis/graph_visualizer.py +375 -0
  603. synkit/Vis/its/__init__.py +19 -0
  604. synkit/Vis/its/drawer.py +615 -0
  605. synkit/Vis/its_drawer.py +35 -0
  606. synkit/Vis/molecule/__init__.py +31 -0
  607. synkit/Vis/molecule/drawer.py +563 -0
  608. synkit/Vis/molecule/reaction.py +285 -0
  609. synkit/Vis/molecule_drawer.py +33 -0
  610. synkit/Vis/mtg/__init__.py +17 -0
  611. synkit/Vis/mtg/drawer.py +769 -0
  612. synkit/Vis/mtg_drawer.py +34 -0
  613. synkit/Vis/pdf_writer.py +146 -0
  614. synkit/Vis/reaction/__init__.py +19 -0
  615. synkit/Vis/reaction/rule.py +141 -0
  616. synkit/Vis/reaction/rxn.py +532 -0
  617. synkit/Vis/reaction_drawer.py +41 -0
  618. synkit/Vis/space/__init__.py +17 -0
  619. synkit/Vis/space/chemical.py +80 -0
  620. synkit/Vis/space/embedding.py +87 -0
  621. synkit/Vis/vis_synedu/Vis/__init__.py +7 -0
  622. synkit/Vis/vis_synedu/Vis/dpo.py +862 -0
  623. synkit/Vis/vis_synedu/rxn_vis.py +377 -0
  624. synkit/Vis/vis_synedu/vis.py +501 -0
  625. synkit/Vis/visual_drawer.py +215 -0
  626. synkit/Vis/visual_model.py +520 -0
  627. synkit/__init__.py +3 -0
  628. synkit/_native.py +91 -0
  629. synkit/examples.py +50 -0
  630. synkit/version.py +23 -0
  631. synkit-1.6.5.dist-info/METADATA +156 -0
  632. synkit-1.6.5.dist-info/RECORD +636 -0
  633. synkit-1.6.5.dist-info/WHEEL +4 -0
  634. synkit-1.6.5.dist-info/licenses/LICENSE +21 -0
  635. synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
  636. synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
@@ -0,0 +1,187 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Dict, Iterable, List, Tuple
3
+ from rdkit import Chem
4
+
5
+ from synkit.Graph.syn_graph import SynGraph
6
+ from synkit.IO import setup_logging
7
+ from synkit.IO.graph_to_mol import GraphToMol
8
+ from synkit.IO.chem_converter import smiles_to_graph
9
+ from synkit.Graph.Matcher.graph_morphism import find_graph_isomorphism
10
+
11
+ logger = setup_logging("INFO")
12
+
13
+
14
+ class ITSRelabel:
15
+ """Extend reaction SMILES through atom-map alignment between reactant and
16
+ product SynGraphs.
17
+
18
+ :cvar logger: Logger instance for debug and info messages.
19
+ :type logger: logging.Logger
20
+ :ivar graph_to_mol: Converter from SynGraph to RDKit Mol.
21
+ :type graph_to_mol: GraphToMol
22
+ """
23
+
24
+ def __init__(self) -> None:
25
+ """Initialize ITSRelabel with default GraphToMol converter."""
26
+ self.graph_to_mol = GraphToMol()
27
+
28
+ @staticmethod
29
+ def _get_nodes_with_atom_map(graph: SynGraph) -> List[Any]:
30
+ """Extract node IDs with a non-zero atom_map attribute from a SynGraph.
31
+
32
+ :param graph: Input SynGraph with 'atom_map' on nodes.
33
+ :type graph: SynGraph
34
+ :return: List of node identifiers where 'atom_map' != 0.
35
+ :rtype: List[Any]
36
+ """
37
+ return [
38
+ n
39
+ for n, attrs in graph.raw.nodes(data=True)
40
+ if attrs.get("atom_map", 0) != 0
41
+ ]
42
+
43
+ @staticmethod
44
+ def _remove_internal_edges(graph: SynGraph, nodes: List[Any]) -> SynGraph:
45
+ """Remove edges connecting nodes in the given list from a SynGraph.
46
+
47
+ :param graph: Input SynGraph to prune.
48
+ :type graph: SynGraph
49
+ :param nodes: Node IDs whose connecting edges will be removed.
50
+ :type nodes: List[Any]
51
+ :return: A new SynGraph with specified edges removed.
52
+ :rtype: SynGraph
53
+ """
54
+ G_copy = SynGraph(graph.raw.copy())
55
+ node_set = set(nodes)
56
+ edges_to_remove = [
57
+ (u, v) for u, v in G_copy.raw.edges() if u in node_set and v in node_set
58
+ ]
59
+ G_copy.raw.remove_edges_from(edges_to_remove)
60
+ return G_copy
61
+
62
+ @staticmethod
63
+ def _dict_to_tuple_list(
64
+ mapping: Dict[Any, Any], sort_by_key: bool = False, sort_by_value: bool = False
65
+ ) -> List[Tuple[Any, Any]]:
66
+ """Convert a mapping dict into a sorted list of tuples.
67
+
68
+ :param mapping: Dictionary to convert.
69
+ :type mapping: Dict[Any, Any]
70
+ :param sort_by_key: Sort tuples by key if True.
71
+ :type sort_by_key: bool
72
+ :param sort_by_value: Sort tuples by value if True.
73
+ :type sort_by_value: bool
74
+ :return: List of (key, value) tuples.
75
+ :rtype: List[Tuple[Any, Any]]
76
+ """
77
+ items = list(mapping.items())
78
+ if sort_by_key:
79
+ items.sort(key=lambda x: x[0])
80
+ elif sort_by_value:
81
+ items.sort(key=lambda x: x[1])
82
+ return items
83
+
84
+ def _update_mapping(
85
+ self,
86
+ G: SynGraph,
87
+ H: SynGraph,
88
+ mapping: Iterable[Tuple[Any, Any]],
89
+ aam_key: str = "atom_map",
90
+ ) -> Tuple[SynGraph, SynGraph]:
91
+ """Update node attributes in two SynGraphs based on a sequential
92
+ mapping.
93
+
94
+ This method resets the specified atom-map attribute for all
95
+ nodes in both graphs to 0, then assigns a new atom-map value
96
+ (i+1) for each mapped pair: G.nodes[g_node][aam_key] = i + 1
97
+ H.nodes[h_node][aam_key] = i + 1
98
+
99
+ :param G: First SynGraph to update (reactant).
100
+ :type G: SynGraph
101
+ :param H: Second SynGraph to update (product).
102
+ :type H: SynGraph
103
+ :param mapping: Iterable of (g_node, h_node) tuples defining
104
+ node correspondence.
105
+ :type mapping: Iterable[Tuple[Any, Any]]
106
+ :param aam_key: Name of the atom-map attribute on each node.
107
+ :type aam_key: str
108
+ :return: Tuple of updated SynGraphs (G_updated, H_updated).
109
+ :rtype: Tuple[SynGraph, SynGraph]
110
+ """
111
+ # Create deep copies of raw graphs
112
+ G_copy = SynGraph(G.raw.copy())
113
+ H_copy = SynGraph(H.raw.copy())
114
+
115
+ # Reset atom-map to zero for all nodes
116
+ for node in G_copy.raw.nodes():
117
+ G_copy.raw.nodes[node][aam_key] = 0
118
+ for node in H_copy.raw.nodes():
119
+ H_copy.raw.nodes[node][aam_key] = 0
120
+
121
+ # Assign new sequential mapping values
122
+ for i, (g_node, h_node) in enumerate(mapping):
123
+ value = i + 1
124
+ if g_node in G_copy.raw:
125
+ G_copy.raw.nodes[g_node][aam_key] = value
126
+ else:
127
+ logger.warning(f"Node {g_node} not found in reactant graph")
128
+ if h_node in H_copy.raw:
129
+ H_copy.raw.nodes[h_node][aam_key] = value
130
+ else:
131
+ logger.warning(f"Node {h_node} not found in product graph")
132
+
133
+ return G_copy, H_copy
134
+
135
+ def fit(self, rsmi: str) -> str:
136
+ """Generate an extended reaction SMILES by aligning atom maps of
137
+ reactant and product.
138
+
139
+ :param rsmi: Reaction SMILES string formatted as 'reactant>>product'.
140
+ :type rsmi: str
141
+ :return: Extended reaction SMILES after remapping.
142
+ :rtype: str
143
+ :raises ValueError: If input format is invalid or graphs are not isomorphic.
144
+
145
+ .. rubric:: Examples
146
+
147
+ >>> its = ITSRelabel()
148
+ >>> its.fit('CCO:1>>CC=O:1')
149
+ 'CCO>>CC=O'
150
+ """
151
+ # Parse reaction SMILES
152
+ try:
153
+ react_smiles, prod_smiles = rsmi.split(">>")
154
+ except ValueError as e:
155
+ raise ValueError("Expected 'reactant>>product' format") from e
156
+
157
+ # Convert to SynGraphs
158
+ G = SynGraph(
159
+ smiles_to_graph(
160
+ react_smiles, drop_non_aam=False, use_index_as_atom_map=False
161
+ )
162
+ )
163
+ H = SynGraph(
164
+ smiles_to_graph(
165
+ prod_smiles, drop_non_aam=False, use_index_as_atom_map=False
166
+ )
167
+ )
168
+
169
+ # Identify and prune mapped nodes
170
+ R_nodes = self._get_nodes_with_atom_map(G)
171
+ P_nodes = self._get_nodes_with_atom_map(H)
172
+ Gp = self._remove_internal_edges(G, R_nodes)
173
+ Hp = self._remove_internal_edges(H, P_nodes)
174
+
175
+ # Find isomorphism mapping
176
+ mapping = find_graph_isomorphism(Gp.raw, Hp.raw, use_defaults=True)
177
+ if not mapping:
178
+ raise ValueError("No isomorphism found between pruned graphs")
179
+
180
+ # Update atom_map attributes
181
+ mapped_pairs = self._dict_to_tuple_list(mapping, sort_by_key=True)
182
+ G_new, H_new = self._update_mapping(G, H, mapped_pairs, aam_key="atom_map")
183
+
184
+ # Convert back to molecules and SMILES
185
+ mol_G = self.graph_to_mol.graph_to_mol(G_new.raw, use_h_count=True)
186
+ mol_H = self.graph_to_mol.graph_to_mol(H_new.raw, use_h_count=True)
187
+ return f"{Chem.MolToSmiles(mol_G)}>>{Chem.MolToSmiles(mol_H)}"
@@ -0,0 +1,356 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Literal, Optional
4
+ import networkx as nx
5
+
6
+ Side = Literal["reactant", "product", "r", "p", 0, 1]
7
+
8
+
9
+ class ITSReverter:
10
+ """Reconstruct reactant/product molecular graphs from an ITS-style graph.
11
+
12
+ Expected ITS format
13
+ -------------------
14
+ Nodes store paired attributes such as::
15
+
16
+ element=('C', 'C')
17
+ charge=(0, 0)
18
+ hcount=(3, 3)
19
+
20
+ Edges store paired attributes such as::
21
+
22
+ order=(1.0, 0.0)
23
+ bond_type=('SINGLE', '')
24
+ conjugated=(False, False)
25
+
26
+ where index 0 = reactant side and index 1 = product side.
27
+
28
+ .. rubric:: Notes
29
+
30
+ - ``typesGH`` is not required for reconstruction.
31
+ - ``standard_order`` is a reaction-delta attribute and is not used to rebuild
32
+ a side-specific molecular graph.
33
+ - By default, isolated atoms are kept. This is important for cases where a
34
+ mapped atom becomes disconnected on one side.
35
+
36
+ .. rubric:: Example
37
+
38
+ .. code-block:: python
39
+
40
+ reverter = ITSReverter(its)
41
+
42
+ g_reactant = reverter.to_reactant_graph()
43
+ g_product = reverter.to_product_graph()
44
+
45
+ print(g_reactant.nodes(data=True))
46
+ print(g_product.edges(data=True))
47
+ """
48
+
49
+ #: node attributes commonly stored in ITS and worth restoring
50
+ DEFAULT_NODE_ATTRS = (
51
+ "element",
52
+ "aromatic",
53
+ "hcount",
54
+ "charge",
55
+ "hybridization",
56
+ "neighbors",
57
+ "atom_map",
58
+ "lone_pairs",
59
+ "radical",
60
+ "valence_electrons",
61
+ "h_pairs",
62
+ "h_pairs_left",
63
+ "h_pairs_right",
64
+ "h_pair_atom_maps",
65
+ )
66
+
67
+ #: edge attributes commonly stored in ITS and worth restoring
68
+ DEFAULT_EDGE_ATTRS = (
69
+ "kekule_order",
70
+ "sigma_order",
71
+ "pi_order",
72
+ "order",
73
+ "bond_type",
74
+ "conjugated",
75
+ "in_ring",
76
+ )
77
+
78
+ def __init__(self, its_graph: nx.Graph):
79
+ """
80
+ :param its_graph: ITS graph with paired node/edge attributes.
81
+ :type its_graph: nx.Graph
82
+ """
83
+ self.its_graph = its_graph
84
+
85
+ @staticmethod
86
+ def _side_to_index(side: Side) -> int:
87
+ """Convert side identifier to tuple index.
88
+
89
+ :param side: Side specifier.
90
+ :type side: Side
91
+ :return: 0 for reactant, 1 for product.
92
+ :rtype: int
93
+ :raises ValueError: If the side is invalid.
94
+ """
95
+ if side in ("reactant", "r", 0):
96
+ return 0
97
+ if side in ("product", "p", 1):
98
+ return 1
99
+ raise ValueError(f"Unsupported side: {side!r}")
100
+
101
+ @staticmethod
102
+ def _pick_side_value(value: Any, idx: int) -> Any:
103
+ """Pick one side from a paired ITS attribute.
104
+
105
+ If ``value`` is a 2-tuple, return the selected side.
106
+ Otherwise return the value unchanged.
107
+
108
+ :param value: Attribute value.
109
+ :type value: Any
110
+ :param idx: Side index.
111
+ :type idx: int
112
+ :return: Side-specific value.
113
+ :rtype: Any
114
+ """
115
+ if isinstance(value, tuple) and len(value) == 2:
116
+ return value[idx]
117
+ return value
118
+
119
+ @classmethod
120
+ def _node_exists_on_side(cls, attrs: dict[str, Any], idx: int) -> bool:
121
+ """Decide whether a node exists on a given side.
122
+
123
+ A node is treated as present if its side-specific ``element`` is not empty.
124
+
125
+ :param attrs: ITS node attributes.
126
+ :type attrs: dict[str, Any]
127
+ :param idx: Side index.
128
+ :type idx: int
129
+ :return: Whether the node exists on that side.
130
+ :rtype: bool
131
+ """
132
+ present = attrs.get("present")
133
+ if isinstance(present, tuple) and len(present) == 2:
134
+ return bool(present[idx])
135
+
136
+ element = cls._pick_side_value(attrs.get("element"), idx)
137
+ return element not in (None, "")
138
+
139
+ @classmethod
140
+ def _edge_exists_on_side(cls, attrs: dict[str, Any], idx: int) -> bool:
141
+ """Decide whether an edge exists on a given side.
142
+
143
+ Priority:
144
+ 1. ``order``
145
+ 2. ``kekule_order``
146
+ 3. ``bond_type``
147
+
148
+ :param attrs: ITS edge attributes.
149
+ :type attrs: dict[str, Any]
150
+ :param idx: Side index.
151
+ :type idx: int
152
+ :return: Whether the bond exists on that side.
153
+ :rtype: bool
154
+ """
155
+ order = cls._pick_side_value(attrs.get("order"), idx)
156
+ if order not in (None, "", 0, 0.0):
157
+ return True
158
+
159
+ kekule_order = cls._pick_side_value(attrs.get("kekule_order"), idx)
160
+ if kekule_order not in (None, "", 0, 0.0):
161
+ return True
162
+
163
+ bond_type = cls._pick_side_value(attrs.get("bond_type"), idx)
164
+ if bond_type not in (None, ""):
165
+ return True
166
+
167
+ return False
168
+
169
+ @classmethod
170
+ def _extract_side_attrs(
171
+ cls,
172
+ attrs: dict[str, Any],
173
+ idx: int,
174
+ keep_keys: Optional[tuple[str, ...]] = None,
175
+ exclude_keys: Optional[set[str]] = None,
176
+ ) -> dict[str, Any]:
177
+ """Extract side-specific attributes from a paired ITS attribute dict.
178
+
179
+ :param attrs: ITS attribute dictionary.
180
+ :type attrs: dict[str, Any]
181
+ :param idx: Side index.
182
+ :type idx: int
183
+ :param keep_keys: Optional whitelist of keys to keep.
184
+ :type keep_keys: Optional[tuple[str, ...]]
185
+ :param exclude_keys: Optional set of keys to exclude.
186
+ :type exclude_keys: Optional[set[str]]
187
+ :return: Flattened side-specific attribute dictionary.
188
+ :rtype: dict[str, Any]
189
+ """
190
+ out: dict[str, Any] = {}
191
+ exclude_keys = exclude_keys or set()
192
+
193
+ for key, value in attrs.items():
194
+ if keep_keys is not None and key not in keep_keys:
195
+ continue
196
+ if key in exclude_keys:
197
+ continue
198
+ out[key] = cls._pick_side_value(value, idx)
199
+
200
+ return out
201
+
202
+ @staticmethod
203
+ def _recompute_neighbors(graph: nx.Graph) -> None:
204
+ """
205
+ Recompute ``neighbors`` attribute from graph connectivity.
206
+
207
+ The value is stored as a sorted list of neighboring element symbols.
208
+
209
+ :param graph: Molecular graph.
210
+ :type graph: nx.Graph
211
+ """
212
+ for node in graph.nodes:
213
+ neighbor_elements = []
214
+ for nb in graph.neighbors(node):
215
+ elem = graph.nodes[nb].get("element")
216
+ neighbor_elements.append(elem)
217
+ graph.nodes[node]["neighbors"] = sorted(neighbor_elements)
218
+
219
+ def to_graph(
220
+ self,
221
+ side: Side,
222
+ node_attrs: Optional[tuple[str, ...]] = None,
223
+ edge_attrs: Optional[tuple[str, ...]] = None,
224
+ recompute_neighbors: bool = False,
225
+ drop_isolated: bool = False,
226
+ ) -> nx.Graph:
227
+ """Reconstruct one side-specific molecular graph.
228
+
229
+ :param side:
230
+ Which side to reconstruct.
231
+ Accepted values: ``"reactant"``, ``"product"``, ``"r"``, ``"p"``, ``0``, ``1``.
232
+ :type side: Side
233
+ :param node_attrs:
234
+ Node attribute keys to keep. If ``None``, uses ``DEFAULT_NODE_ATTRS``.
235
+ :type node_attrs: Optional[tuple[str, ...]]
236
+ :param edge_attrs:
237
+ Edge attribute keys to keep. If ``None``, uses ``DEFAULT_EDGE_ATTRS``.
238
+ :type edge_attrs: Optional[tuple[str, ...]]
239
+ :param recompute_neighbors:
240
+ If ``True``, overwrite the stored ``neighbors`` attribute using the
241
+ reconstructed graph connectivity.
242
+ :type recompute_neighbors: bool
243
+ :param drop_isolated:
244
+ If ``True``, remove nodes with degree 0 after reconstruction.
245
+ Default is ``False`` so disconnected mapped atoms are preserved.
246
+ :type drop_isolated: bool
247
+ :return:
248
+ Side-specific molecular graph.
249
+ :rtype: nx.Graph
250
+ """
251
+ idx = self._side_to_index(side)
252
+ node_attrs = node_attrs or self.DEFAULT_NODE_ATTRS
253
+ edge_attrs = edge_attrs or self.DEFAULT_EDGE_ATTRS
254
+
255
+ g = nx.Graph()
256
+
257
+ # nodes
258
+ for node, attrs in self.its_graph.nodes(data=True):
259
+ if not self._node_exists_on_side(attrs, idx):
260
+ continue
261
+
262
+ flat_node_attrs = self._extract_side_attrs(
263
+ attrs=attrs,
264
+ idx=idx,
265
+ keep_keys=node_attrs,
266
+ exclude_keys={"typesGH"},
267
+ )
268
+ g.add_node(node, **flat_node_attrs)
269
+
270
+ # edges
271
+ for u, v, attrs in self.its_graph.edges(data=True):
272
+ if u not in g or v not in g:
273
+ continue
274
+ if not self._edge_exists_on_side(attrs, idx):
275
+ continue
276
+
277
+ flat_edge_attrs = self._extract_side_attrs(
278
+ attrs=attrs,
279
+ idx=idx,
280
+ keep_keys=edge_attrs,
281
+ exclude_keys={"standard_order"},
282
+ )
283
+ g.add_edge(u, v, **flat_edge_attrs)
284
+
285
+ if recompute_neighbors:
286
+ self._recompute_neighbors(g)
287
+
288
+ if drop_isolated:
289
+ isolates = list(nx.isolates(g))
290
+ g.remove_nodes_from(isolates)
291
+
292
+ stereo = self.its_graph.graph.get("stereo_descriptors", {})
293
+ if isinstance(stereo, dict) and ("reactant" in stereo or "product" in stereo):
294
+ side_name = "reactant" if idx == 0 else "product"
295
+ g.graph["stereo_descriptors"] = dict(stereo.get(side_name, {}))
296
+ g.graph["stereo_projection"] = side_name
297
+ elif isinstance(stereo, dict):
298
+ g.graph["stereo_descriptors"] = dict(stereo)
299
+
300
+ return g
301
+
302
+ def to_reactant_graph(
303
+ self,
304
+ recompute_neighbors: bool = False,
305
+ drop_isolated: bool = False,
306
+ ) -> nx.Graph:
307
+ """Reconstruct the reactant-side graph.
308
+
309
+ :param recompute_neighbors: Whether to recompute ``neighbors``.
310
+ :type recompute_neighbors: bool
311
+ :param drop_isolated: Whether to remove isolated nodes.
312
+ :type drop_isolated: bool
313
+ :return: Reactant molecular graph.
314
+ :rtype: nx.Graph
315
+ """
316
+ return self.to_graph(
317
+ side="reactant",
318
+ recompute_neighbors=recompute_neighbors,
319
+ drop_isolated=drop_isolated,
320
+ )
321
+
322
+ def to_product_graph(
323
+ self,
324
+ recompute_neighbors: bool = False,
325
+ drop_isolated: bool = False,
326
+ ) -> nx.Graph:
327
+ """Reconstruct the product-side graph.
328
+
329
+ :param recompute_neighbors: Whether to recompute ``neighbors``.
330
+ :type recompute_neighbors: bool
331
+ :param drop_isolated: Whether to remove isolated nodes.
332
+ :type drop_isolated: bool
333
+ :return: Product molecular graph.
334
+ :rtype: nx.Graph
335
+ """
336
+ return self.to_graph(
337
+ side="product",
338
+ recompute_neighbors=recompute_neighbors,
339
+ drop_isolated=drop_isolated,
340
+ )
341
+
342
+ def to_transition_state_graph(self) -> nx.Graph:
343
+ """Return an ITS projection carrying only transition-state stereo.
344
+
345
+ Structural node and edge attributes remain paired because the ITS is
346
+ SynKit's transition-state representation. The stereo registry is
347
+ flattened to the optional ``transition`` descriptors so ordinary
348
+ registry consumers can inspect fleeting stereo without confusing it
349
+ with either stable endpoint.
350
+ """
351
+ graph = self.its_graph.copy()
352
+ stereo = self.its_graph.graph.get("stereo_descriptors", {})
353
+ transition = stereo.get("transition", {}) if isinstance(stereo, dict) else {}
354
+ graph.graph["stereo_descriptors"] = dict(transition)
355
+ graph.graph["stereo_projection"] = "transition"
356
+ return graph
@@ -0,0 +1,145 @@
1
+ import networkx as nx
2
+ from rdkit import Chem
3
+ from typing import List
4
+
5
+ from synkit.IO.chem_converter import rsmi_to_graph
6
+ from synkit.IO.graph_to_mol import GraphToMol
7
+ from synkit.Chem.Reaction.fix_aam import FixAAM
8
+ from synkit.Graph.Hyrogen._misc import implicit_hydrogen
9
+ from synkit.Graph.ITS.its_construction import ITSConstruction
10
+ from synkit.Graph.ITS.its_decompose import get_rc
11
+
12
+
13
+ class NormalizeAAM:
14
+ """Provides functionalities to normalize atom mappings in SMILES
15
+ representations, extract and process reaction centers from ITS graphs, and
16
+ convert between graph representations and molecular models."""
17
+
18
+ def __init__(self) -> None:
19
+ """Initializes the NormalizeAAM class."""
20
+ pass
21
+
22
+ @staticmethod
23
+ def fix_rsmi_kekulize(rsmi: str) -> str:
24
+ """Filters the reactants and products of a reaction SMILES string.
25
+
26
+ :param rsmi: A string representing the reaction SMILES in the form of "reactants >> products".
27
+ :type rsmi: str
28
+
29
+ :return: A filtered reaction SMILES string where invalid reactants/products are removed.
30
+ :rtype: str
31
+ """
32
+ # Split the reaction into reactants and products
33
+ reactants, products = rsmi.split(">>")
34
+
35
+ # Filter valid reactants and products
36
+ filtered_reactants = NormalizeAAM.fix_kekulize(reactants)
37
+ filtered_products = NormalizeAAM.fix_kekulize(products)
38
+
39
+ # Return the filtered reaction SMILES
40
+ return f"{filtered_reactants}>>{filtered_products}"
41
+
42
+ @staticmethod
43
+ def fix_kekulize(smiles: str) -> str:
44
+ """Filters and returns valid SMILES strings from a string of SMILES,
45
+ joined by '.'.
46
+
47
+ This function processes a string of SMILES separated by periods (e.g., "CCO.CC=O"),
48
+ filters out invalid SMILES, and returns a string of valid SMILES joined by periods.
49
+
50
+ :param smiles: A string containing SMILES strings separated by periods ('.').
51
+ :type smiles: str
52
+
53
+ :return: A string of valid SMILES, joined by periods ('.').
54
+ :rtype: str
55
+ """
56
+ smiles_list = smiles.split(".") # Split SMILES by period
57
+ valid_smiles = [] # List to store valid SMILES strings
58
+
59
+ for smile in smiles_list:
60
+ mol = Chem.MolFromSmiles(smile, sanitize=False)
61
+ if mol: # Check if molecule is valid
62
+ valid_smiles.append(
63
+ Chem.MolToSmiles(
64
+ mol, canonical=True, kekuleSmiles=True, allHsExplicit=True
65
+ )
66
+ )
67
+ return ".".join(valid_smiles) # Return valid SMILES joined by '.'
68
+
69
+ @staticmethod
70
+ def extract_subgraph(graph: nx.Graph, indices: List[int]) -> nx.Graph:
71
+ """Extracts a subgraph from a given graph based on a list of node
72
+ indices.
73
+
74
+ :param graph: The original graph from which to extract the subgraph.
75
+ :type graph: nx.Graph
76
+ :param indices: A list of node indices that define the subgraph.
77
+ :type indices: List[int]
78
+
79
+ :return: The extracted subgraph.
80
+ :rtype: nx.Graph
81
+ """
82
+ return graph.subgraph(indices).copy()
83
+
84
+ def reset_indices_and_atom_map(
85
+ self, subgraph: nx.Graph, aam_key: str = "atom_map"
86
+ ) -> nx.Graph:
87
+ """Resets the node indices and the atom_map of the subgraph to be
88
+ continuous from 1 onwards.
89
+
90
+ :param subgraph: The subgraph with possibly non-continuous indices.
91
+ :type subgraph: nx.Graph
92
+ :param aam_key: The attribute key for atom mapping. Defaults to 'atom_map'.
93
+ :type aam_key: str
94
+
95
+ :return: A new subgraph with continuous indices and adjusted atom_map.
96
+ :rtype: nx.Graph
97
+ """
98
+ new_graph = nx.Graph()
99
+ node_id_mapping = {
100
+ old_id: new_id for new_id, old_id in enumerate(subgraph.nodes(), 1)
101
+ }
102
+ for old_id, new_id in node_id_mapping.items():
103
+ node_data = subgraph.nodes[old_id].copy()
104
+ node_data[aam_key] = new_id
105
+ new_graph.add_node(new_id, **node_data)
106
+ for u, v, data in subgraph.edges(data=True):
107
+ new_graph.add_edge(node_id_mapping[u], node_id_mapping[v], **data)
108
+ return new_graph
109
+
110
+ def fit(self, rsmi: str, fix_aam_indice: bool = True) -> str:
111
+ """Processes a reaction SMILES (RSMI) to adjust atom mappings, extract
112
+ reaction centers, decompose into separate reactant and product graphs,
113
+ and generate the corresponding SMILES.
114
+
115
+ :param rsmi: The reaction SMILES string to be processed.
116
+ :type rsmi: str
117
+ :param fix_aam_indice: Whether to fix the atom mapping numbers.
118
+ Defaults to True.
119
+ :type fix_aam_indice: bool
120
+
121
+ :return: The resulting reaction SMILES string with updated atom mappings.
122
+ :rtype: str
123
+ """
124
+ rsmi = self.fix_rsmi_kekulize(rsmi)
125
+ if fix_aam_indice:
126
+ rsmi = FixAAM().fix_aam_rsmi(rsmi)
127
+ r_graph, p_graph = rsmi_to_graph(
128
+ rsmi,
129
+ sanitize=True,
130
+ use_index_as_atom_map=True,
131
+ drop_non_aam=True,
132
+ )
133
+ its = ITSConstruction().ITSGraph(r_graph, p_graph)
134
+ rc = get_rc(its)
135
+ list_hydrogen = []
136
+ for _, value in rc.nodes(data=True):
137
+ if value["element"] == "H":
138
+ list_hydrogen.append(value["atom_map"])
139
+ r_graph = implicit_hydrogen(r_graph, list_hydrogen)
140
+ p_graph = implicit_hydrogen(p_graph, list_hydrogen)
141
+
142
+ r_mol, p_mol = GraphToMol().graph_to_mol(
143
+ r_graph, sanitize=True, use_h_count=True
144
+ ), GraphToMol().graph_to_mol(p_graph, sanitize=True, use_h_count=True)
145
+ return f"{Chem.MolToSmiles(r_mol)}>>{Chem.MolToSmiles(p_mol)}"