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
synkit/IO/data_io.py ADDED
@@ -0,0 +1,269 @@
1
+ import os
2
+ import json
3
+ import pickle
4
+ import numpy as np
5
+ from numpy import ndarray
6
+ from joblib import dump, load
7
+ from typing import List, Dict, Any, Generator, Optional
8
+ from synkit.IO.debug import setup_logging
9
+
10
+ logger = setup_logging()
11
+
12
+
13
+ def save_database(database: List[Dict], pathname: str = "./Data/database.json") -> None:
14
+ """Save a database (a list of dictionaries) to a JSON file.
15
+
16
+ :param database: The database to be saved.
17
+ :type database: list[dict]
18
+ :param pathname: The path where the database will be saved. Defaults
19
+ to './Data/database.json'.
20
+ :type pathname: str
21
+ :raises TypeError: If the database is not a list of dictionaries.
22
+ :raises ValueError: If there is an error writing the file.
23
+ """
24
+ if not all(isinstance(item, dict) for item in database):
25
+ raise TypeError("Database should be a list of dictionaries.")
26
+ try:
27
+ with open(pathname, "w") as f:
28
+ json.dump(database, f)
29
+ except IOError as e:
30
+ raise ValueError(f"Error writing to file {pathname}: {e}")
31
+
32
+
33
+ def load_database(pathname: str = "./Data/database.json") -> List[Dict]:
34
+ """Load a database (a list of dictionaries) from a JSON file.
35
+
36
+ :param pathname: The path from where the database will be loaded.
37
+ Defaults to './Data/database.json'.
38
+ :type pathname: str
39
+ :return: The loaded database.
40
+ :rtype: list[dict]
41
+ :raises ValueError: If there is an error reading the file.
42
+ """
43
+ try:
44
+ with open(pathname, "r") as f:
45
+ database = json.load(f)
46
+ return database
47
+ except IOError as e:
48
+ raise ValueError(f"Error reading file {pathname}: {e}")
49
+
50
+
51
+ def save_to_pickle(data: List[Dict[str, Any]], filename: str) -> None:
52
+ """Save a list of dictionaries to a pickle file.
53
+
54
+ :param data: A list of dictionaries to be saved.
55
+ :type data: list[dict]
56
+ :param filename: The name of the file where the data will be saved.
57
+ :type filename: str
58
+ """
59
+ with open(filename, "wb") as file:
60
+ pickle.dump(data, file)
61
+
62
+
63
+ def load_from_pickle(filename: str) -> List[Any]:
64
+ """Load data from a pickle file.
65
+
66
+ :param filename: The name of the pickle file to load data from.
67
+ :type filename: str
68
+ :return: The data loaded from the pickle file.
69
+ :rtype: list
70
+ """
71
+ with open(filename, "rb") as file:
72
+ return pickle.load(file)
73
+
74
+
75
+ def load_gml_as_text(gml_file_path: str) -> Optional[str]:
76
+ """Load the contents of a GML file as a text string.
77
+
78
+ :param gml_file_path: The file path to the GML file.
79
+ :type gml_file_path: str
80
+ :return: The text content of the GML file, or None if the file does
81
+ not exist or an error occurs.
82
+ :rtype: str or None
83
+ """
84
+ try:
85
+ with open(gml_file_path, "r") as file:
86
+ return file.read()
87
+ except FileNotFoundError:
88
+ logger.error(f"File not found: {gml_file_path}")
89
+ return None
90
+ except Exception as e:
91
+ logger.error(f"An error occurred while reading {gml_file_path}: {e}")
92
+ return None
93
+
94
+
95
+ def save_text_as_gml(gml_text: str, file_path: str) -> bool:
96
+ """Save a GML text string to a file.
97
+
98
+ :param gml_text: The GML content as a text string.
99
+ :type gml_text: str
100
+ :param file_path: The file path where the GML text will be saved.
101
+ :type file_path: str
102
+ :return: True if saving was successful, False otherwise.
103
+ :rtype: bool
104
+ """
105
+ try:
106
+ with open(file_path, "w") as file:
107
+ file.write(gml_text)
108
+ logger.info(f"GML text successfully saved to {file_path}")
109
+ return True
110
+ except Exception as e:
111
+ logger.error(f"An error occurred while saving the GML text: {e}")
112
+ return False
113
+
114
+
115
+ def save_compressed(array: ndarray, filename: str) -> None:
116
+ """Saves a NumPy array in a compressed format using .npz extension.
117
+
118
+ :param array: The NumPy array to be saved.
119
+ :type array: numpy.ndarray
120
+ :param filename: The file path or name to save the array to, with a
121
+ '.npz' extension.
122
+ :type filename: str
123
+ """
124
+ np.savez_compressed(filename, array=array)
125
+
126
+
127
+ def load_compressed(filename: str) -> ndarray:
128
+ """Loads a NumPy array from a compressed .npz file.
129
+
130
+ :param filename: The path of the .npz file to load.
131
+ :type filename: str
132
+ :return: The loaded NumPy array.
133
+ :rtype: numpy.ndarray
134
+ :raises KeyError: If the .npz file does not contain an array with
135
+ the key 'array'.
136
+ """
137
+ with np.load(filename) as data:
138
+ if "array" in data:
139
+ return data["array"]
140
+ else:
141
+ raise KeyError(
142
+ "The .npz file does not contain an array with the key 'array'."
143
+ )
144
+
145
+
146
+ def save_model(model: Any, filename: str) -> None:
147
+ """Save a machine learning model to a file using joblib.
148
+
149
+ :param model: The machine learning model to save.
150
+ :type model: object
151
+ :param filename: The path to the file where the model will be saved.
152
+ :type filename: str
153
+ """
154
+ dump(model, filename)
155
+ logger.info(f"Model saved successfully to {filename}")
156
+
157
+
158
+ def load_model(filename: str) -> Any:
159
+ """Load a machine learning model from a file using joblib.
160
+
161
+ :param filename: The path to the file from which the model will be
162
+ loaded.
163
+ :type filename: str
164
+ :return: The loaded machine learning model.
165
+ :rtype: object
166
+ """
167
+ model = load(filename)
168
+ logger.info(f"Model loaded successfully from {filename}")
169
+ return model
170
+
171
+
172
+ def save_dict_to_json(data: dict, file_path: str) -> None:
173
+ """Save a dictionary to a JSON file.
174
+
175
+ :param data: The dictionary to be saved.
176
+ :type data: dict
177
+ :param file_path: The path to the file where the dictionary should
178
+ be saved.
179
+ :type file_path: str
180
+ """
181
+ with open(file_path, "w") as json_file:
182
+ json.dump(data, json_file, indent=4)
183
+ logger.info(f"Dictionary successfully saved to {file_path}")
184
+
185
+
186
+ def load_dict_from_json(file_path: str) -> Optional[dict]:
187
+ """Load a dictionary from a JSON file.
188
+
189
+ :param file_path: The path to the JSON file from which to load the
190
+ dictionary.
191
+ :type file_path: str
192
+ :return: The dictionary loaded from the JSON file, or None if an
193
+ error occurs.
194
+ :rtype: dict or None
195
+ """
196
+ try:
197
+ with open(file_path, "r") as json_file:
198
+ data = json.load(json_file)
199
+ logger.info(f"Dictionary successfully loaded from {file_path}")
200
+ return data
201
+ except Exception as e:
202
+ logger.error(e)
203
+ return None
204
+
205
+
206
+ def load_from_pickle_generator(file_path: str) -> Generator[Any, None, None]:
207
+ """A generator that yields items from a pickle file where each pickle load
208
+ returns a list of dictionaries.
209
+
210
+ :param file_path: The path to the pickle file to load.
211
+ :type file_path: str
212
+ :yield: A single item from the list of dictionaries stored in the
213
+ pickle file.
214
+ :rtype: Any
215
+ """
216
+ with open(file_path, "rb") as file:
217
+ while True:
218
+ try:
219
+ batch_items = pickle.load(file)
220
+ for item in batch_items:
221
+ yield item
222
+ except EOFError:
223
+ break
224
+
225
+
226
+ def collect_data(num_batches: int, temp_dir: str, file_template: str) -> List[Any]:
227
+ """Collects and aggregates data from multiple pickle files into a single
228
+ list.
229
+
230
+ :param num_batches: The number of batch files to process.
231
+ :type num_batches: int
232
+ :param temp_dir: The directory where the batch files are stored.
233
+ :type temp_dir: str
234
+ :param file_template: The template string for batch file names,
235
+ expecting an integer formatter.
236
+ :type file_template: str
237
+ :return: A list of aggregated data items from all batch files.
238
+ :rtype: list
239
+ """
240
+ collected_data: List[Any] = []
241
+ for i in range(num_batches):
242
+ file_path = os.path.join(temp_dir, file_template.format(i))
243
+ for item in load_from_pickle_generator(file_path):
244
+ collected_data.append(item)
245
+ return collected_data
246
+
247
+
248
+ def save_list_to_file(data_list: list, file_path: str) -> None:
249
+ """Save a list to a file in JSON format.
250
+
251
+ :param data_list: The list to save.
252
+ :type data_list: list
253
+ :param file_path: The path to the file where the list will be saved.
254
+ :type file_path: str
255
+ """
256
+ with open(file_path, "w") as file:
257
+ json.dump(data_list, file)
258
+
259
+
260
+ def load_list_from_file(file_path: str) -> list:
261
+ """Load a list from a JSON-formatted file.
262
+
263
+ :param file_path: The path to the file to read the list from.
264
+ :type file_path: str
265
+ :return: The list loaded from the file.
266
+ :rtype: list
267
+ """
268
+ with open(file_path, "r") as file:
269
+ return json.load(file)
@@ -0,0 +1,143 @@
1
+ from typing import List, Dict, Any, Optional
2
+ import joblib
3
+ from tqdm import tqdm as _tqdm_type
4
+
5
+
6
+ class TqdmJoblib:
7
+ """
8
+ Context manager to integrate a tqdm progress bar with joblib's Parallel.
9
+
10
+ Usage:
11
+ with TqdmJoblib(tqdm(total=100)) as t:
12
+ Parallel(...)(delayed(...)(...) for ...)
13
+
14
+ :param tqdm_obj: an instantiated tqdm progress bar object (e.g. `tqdm(total=...)`).
15
+ :type tqdm_obj: tqdm.tqdm
16
+ :param max_batch_size: maximum sensible batch size to accept from joblib's
17
+ callback; anything larger will be treated as 1 to avoid
18
+ corrupting the bar.
19
+ :type max_batch_size: int, optional
20
+ :param allow_overshoot: if False (default) cap updates so the bar never
21
+ exceeds `tqdm_obj.total`. If True, allow normal updates.
22
+ :type allow_overshoot: bool, optional
23
+ :param silent_close_errors: swallow exceptions raised when closing the tqdm
24
+ object on exit (default True).
25
+ :type silent_close_errors: bool, optional
26
+ :raises AttributeError: if joblib has no `parallel.BatchCompletionCallBack`.
27
+ """
28
+
29
+ def __init__(
30
+ self,
31
+ tqdm_obj: _tqdm_type,
32
+ max_batch_size: int = 10**6,
33
+ allow_overshoot: bool = False,
34
+ silent_close_errors: bool = True,
35
+ ) -> None:
36
+ self.tqdm_obj = tqdm_obj
37
+ self.max_batch_size = int(max_batch_size)
38
+ self.allow_overshoot = bool(allow_overshoot)
39
+ self.silent_close_errors = bool(silent_close_errors)
40
+
41
+ self._orig: Optional[Any] = None
42
+ self._patched = False
43
+
44
+ def __enter__(self):
45
+ orig_cb = getattr(joblib.parallel, "BatchCompletionCallBack", None)
46
+ if orig_cb is None:
47
+ raise AttributeError("joblib.parallel.BatchCompletionCallBack not found")
48
+
49
+ self._orig = orig_cb
50
+
51
+ def _callback(*args, **kwargs):
52
+ try:
53
+ n = int(args[0])
54
+ if n <= 0 or n > self.max_batch_size:
55
+ raise ValueError
56
+ except Exception:
57
+ n = 1
58
+
59
+ if not self.allow_overshoot:
60
+ remaining = max(0, (self.tqdm_obj.total or 0) - (self.tqdm_obj.n or 0))
61
+ inc = n if n <= remaining else remaining
62
+ else:
63
+ inc = n
64
+
65
+ if inc > 0:
66
+ try:
67
+ self.tqdm_obj.update(inc)
68
+ except Exception:
69
+ # If tqdm object's update fails for any reason, fallback to +1
70
+ try:
71
+ self.tqdm_obj.update(1)
72
+ except Exception:
73
+ pass
74
+
75
+ return self._orig(*args, **kwargs)
76
+
77
+ joblib.parallel.BatchCompletionCallBack = _callback
78
+ self._patched = True
79
+ return self
80
+
81
+ def __exit__(self, exc_type, exc_val, exc_tb):
82
+ if self._patched and self._orig is not None:
83
+ try:
84
+ joblib.parallel.BatchCompletionCallBack = self._orig
85
+ except Exception:
86
+ # best-effort restore; ignore to avoid masking user exceptions
87
+ pass
88
+
89
+ try:
90
+ if self.tqdm_obj is not None:
91
+ self.tqdm_obj.close()
92
+ except Exception:
93
+ if not self.silent_close_errors:
94
+ raise
95
+
96
+
97
+ def merge_dicts(
98
+ list1: List[Dict[str, Any]],
99
+ list2: List[Dict[str, Any]],
100
+ key: str,
101
+ intersection: bool = True,
102
+ ) -> List[Dict[str, Any]]:
103
+ """Merges two lists of dictionaries based on a specified key, with an
104
+ option to either merge only dictionaries with matching key values
105
+ (intersection) or all dictionaries (union).
106
+
107
+ :param list1: The first list of dictionaries.
108
+ :type list1: List[Dict[str, Any]]
109
+ :param list2: The second list of dictionaries.
110
+ :type list2: List[Dict[str, Any]]
111
+ :param key: The key used to match and merge dictionaries from both lists.
112
+ :type key: str
113
+ :param intersection: If True, only merge dictionaries with matching key values;
114
+ if False, merge all dictionaries, combining those with matching key values.
115
+ :type intersection: bool
116
+
117
+ :return: Dictionaries merged according to the selected strategy.
118
+ :rtype: List[Dict[str, Any]]
119
+ """
120
+ dict1 = {item[key]: item for item in list1}
121
+ dict2 = {item[key]: item for item in list2}
122
+
123
+ if intersection:
124
+ # Intersection of keys: only keys present in both dictionaries are merged
125
+ merged_list = []
126
+ for item1 in list1:
127
+ r_id = item1.get(key)
128
+ if r_id in dict2:
129
+ merged_item = {**item1, **dict2[r_id]}
130
+ merged_list.append(merged_item)
131
+ return merged_list
132
+ else:
133
+ # Union of keys: all keys from both dictionaries are merged
134
+ merged_dict = {}
135
+ all_keys = set(dict1) | set(dict2)
136
+ for k in all_keys:
137
+ if k in dict1 and k in dict2:
138
+ merged_dict[k] = {**dict1[k], **dict2[k]}
139
+ elif k in dict1:
140
+ merged_dict[k] = dict1[k]
141
+ else:
142
+ merged_dict[k] = dict2[k]
143
+ return list(merged_dict.values())
synkit/IO/debug.py ADDED
@@ -0,0 +1,73 @@
1
+ import os
2
+ import logging
3
+ import warnings
4
+ from rdkit import rdBase, RDLogger
5
+
6
+
7
+ def setup_logging(
8
+ log_level: str = "INFO", log_filename: str = None, task_type: str = None
9
+ ) -> logging.Logger:
10
+ """Configures logging to either the console or a file, based on provided
11
+ parameters.
12
+
13
+ :param log_level: Logging level to set. Defaults to 'INFO'.
14
+ Options: 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'.
15
+ :type log_level: str
16
+ :param log_filename: If provided, logs are written to this file. Defaults to None (logs to console).
17
+ :type log_filename: str or None
18
+ :param task_type: Logger name/namespace. Useful for distinguishing loggers in multi-task settings.
19
+ Defaults to None.
20
+ :type task_type: str or None
21
+
22
+ :return: Configured logger instance.
23
+ :rtype: logging.Logger
24
+
25
+ :raises ValueError: If an invalid log level is provided.
26
+ """
27
+ log_format = "%(asctime)s - %(levelname)s - %(message)s"
28
+ numeric_level = getattr(logging, log_level.upper(), None)
29
+
30
+ if not isinstance(numeric_level, int):
31
+ raise ValueError(f"Invalid log level: {log_level}")
32
+
33
+ logger = logging.getLogger(task_type)
34
+ logger.handlers.clear() # Efficiently remove all existing handlers
35
+
36
+ if log_filename:
37
+ os.makedirs(os.path.dirname(log_filename), exist_ok=True)
38
+ logging.basicConfig(
39
+ level=numeric_level, format=log_format, filename=log_filename, filemode="a"
40
+ )
41
+ else:
42
+ logging.basicConfig(level=numeric_level, format=log_format)
43
+
44
+ return logger
45
+
46
+
47
+ def configure_warnings_and_logs(
48
+ ignore_warnings: bool = False, disable_rdkit_logs: bool = False
49
+ ) -> None:
50
+ """Configures Python warnings and RDKit log behavior based on input flags.
51
+
52
+ :param ignore_warnings: Whether to suppress all Python warnings.
53
+ Default is False.
54
+ :type ignore_warnings: bool
55
+ :param disable_rdkit_logs: Whether to disable RDKit error and
56
+ warning logs. Default is False.
57
+ :type disable_rdkit_logs: bool
58
+ :return: None :usage: Use this function to control verbosity (e.g.
59
+ in production or testing), but use with caution during
60
+ development to avoid missing critical issues.
61
+ """
62
+ if ignore_warnings:
63
+ warnings.filterwarnings("ignore")
64
+ else:
65
+ warnings.resetwarnings()
66
+
67
+ if disable_rdkit_logs:
68
+ rdBase.DisableLog("rdApp.error")
69
+ rdBase.DisableLog("rdApp.warning")
70
+ RDLogger.DisableLog("rdApp.warning")
71
+ else:
72
+ rdBase.EnableLog("rdApp.error")
73
+ rdBase.EnableLog("rdApp.warning")
synkit/IO/gml_to_nx.py ADDED
@@ -0,0 +1,150 @@
1
+ import re
2
+ import networkx as nx
3
+ from typing import Tuple
4
+ from synkit.Graph.ITS.its_construction import ITSConstruction
5
+
6
+
7
+ class GMLToNX:
8
+ """Parses GML-like text and transforms it into three NetworkX graphs
9
+ representing the left, right, and context graphs of a chemical reaction
10
+ step.
11
+
12
+ :param gml_text: The GML-like text to parse.
13
+ :type gml_text: str
14
+ :ivar graphs: A dictionary containing 'left', 'right', and 'context'
15
+ NetworkX graphs.
16
+ :vartype graphs: dict[str, nx.Graph]
17
+ """
18
+
19
+ def __init__(self, gml_text: str):
20
+ """Initializes a GMLToNX object that can parse GML-like text into
21
+ separate NetworkX graphs representing different stages or components of
22
+ a chemical reaction.
23
+
24
+ :param gml_text: The GML-like text to be parsed.
25
+ :type gml_text: str
26
+ """
27
+ self.gml_text = gml_text
28
+ self.graphs = {"left": nx.Graph(), "context": nx.Graph(), "right": nx.Graph()}
29
+
30
+ def _parse_element(self, line: str, current_section: str):
31
+ """Parses a line of GML-like text to extract node or edge data and adds
32
+ it to the current section's graph.
33
+
34
+ :param line: A single line of GML-like text.
35
+ :type line: str
36
+ :param current_section: Which section ('left', 'right',
37
+ 'context') to add the node/edge to.
38
+ :type current_section: str
39
+ """
40
+ label_to_order = {"-": 1, ":": 1.5, "=": 2, "#": 3}
41
+ tokens = line.split()
42
+
43
+ if "node" in line:
44
+ node_id = int(tokens[tokens.index("id") + 1])
45
+ label = tokens[tokens.index("label") + 1].strip('"')
46
+ element, charge = self._extract_element_and_charge(label)
47
+ node_attributes = {
48
+ "element": element,
49
+ "charge": charge,
50
+ "atom_map": node_id,
51
+ "hcount": 0,
52
+ }
53
+ self.graphs[current_section].add_node(node_id, **node_attributes)
54
+
55
+ elif "edge" in line:
56
+ source = int(tokens[tokens.index("source") + 1])
57
+ target = int(tokens[tokens.index("target") + 1])
58
+ label = tokens[tokens.index("label") + 1].strip('"')
59
+ order = label_to_order.get(label, 0)
60
+ self.graphs[current_section].add_edge(source, target, order=order)
61
+
62
+ def _extract_element_and_charge(self, label: str) -> Tuple[str, int]:
63
+ """Extracts the chemical element and its charge from a node label.
64
+
65
+ :param label: The label string from a GML node (e.g., 'N+',
66
+ 'O2-', etc.).
67
+ :type label: str
68
+ :return: A tuple of (element symbol, formal charge).
69
+ :rtype: tuple[str, int]
70
+ """
71
+ match = re.match(r"([A-Za-z*]+)(\d+)?([+-])?$", label)
72
+ if not match:
73
+ return ("X", 0)
74
+ element = match.group(1)
75
+ num = match.group(2)
76
+ sign = match.group(3)
77
+ charge = 0
78
+ if sign:
79
+ charge_val = int(num) if num else 1
80
+ charge = charge_val if sign == "+" else -charge_val
81
+ return element, charge
82
+
83
+ def _synchronize_nodes_and_edges(self):
84
+ """Ensures that all nodes and edges in 'context' appear in both 'left'
85
+ and 'right'. We do not remove edges from left or right if they are not
86
+ in context. We only add missing context nodes and edges to left and
87
+ right.
88
+
89
+ :return: None
90
+ """
91
+ # Add missing context nodes to left and right
92
+ for node, ndata in self.graphs["context"].nodes(data=True):
93
+ if node not in self.graphs["left"]:
94
+ self.graphs["left"].add_node(node, **ndata)
95
+ else:
96
+ # Merge attributes if node already exists in left
97
+ for k, v in ndata.items():
98
+ self.graphs["left"].nodes[node][k] = v
99
+
100
+ if node not in self.graphs["right"]:
101
+ self.graphs["right"].add_node(node, **ndata)
102
+ else:
103
+ # Merge attributes if node already exists in right
104
+ for k, v in ndata.items():
105
+ self.graphs["right"].nodes[node][k] = v
106
+
107
+ # Add missing context edges to left and right
108
+ for s, t, edata in self.graphs["context"].edges(data=True):
109
+ if not self.graphs["left"].has_edge(s, t):
110
+ self.graphs["left"].add_edge(s, t, **edata)
111
+ if not self.graphs["right"].has_edge(s, t):
112
+ self.graphs["right"].add_edge(s, t, **edata)
113
+
114
+ def transform(self) -> Tuple[nx.Graph, nx.Graph, nx.Graph]:
115
+ """Transforms the GML-like text into three NetworkX graphs: left, right, and context.
116
+
117
+ :return: A tuple of (left_graph, right_graph, context_graph), each a NetworkX graph.
118
+ :rtype: tuple[nx.Graph, nx.Graph, nx.Graph]
119
+ """
120
+ current_section = None
121
+ lines = self.gml_text.split("\n")
122
+ for line in lines:
123
+ line = line.strip()
124
+ if line.startswith("rule") or line == "]":
125
+ continue
126
+ if any(section in line for section in ["left", "context", "right"]):
127
+ current_section = line.split("[")[0].strip()
128
+ continue
129
+ if line.startswith("node") or line.startswith("edge"):
130
+ self._parse_element(line, current_section)
131
+
132
+ # Synchronize after parsing
133
+ self._synchronize_nodes_and_edges()
134
+
135
+ # Create the ITS graph
136
+ its_graph = ITSConstruction().ITSGraph(
137
+ self.graphs["left"], self.graphs["right"]
138
+ )
139
+
140
+ # Restore node attributes in ITS graph from left (or right)
141
+ for n in its_graph.nodes():
142
+ if n in self.graphs["left"].nodes:
143
+ for k, v in self.graphs["left"].nodes[n].items():
144
+ its_graph.nodes[n][k] = v
145
+
146
+ self.graphs["context"] = ITSConstruction().ITSGraph(
147
+ self.graphs["left"], self.graphs["right"]
148
+ )
149
+
150
+ return self.graphs["left"], self.graphs["right"], self.graphs["context"]