synkit 0.0.6__tar.gz → 0.0.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. {synkit-0.0.6 → synkit-0.0.8}/.github/workflows/build-doc.yml +1 -0
  2. synkit-0.0.8/.github/workflows/test-and-lint.yml +68 -0
  3. {synkit-0.0.6 → synkit-0.0.8}/.gitignore +6 -6
  4. synkit-0.0.8/Data/Figure/synkit.png +0 -0
  5. {synkit-0.0.6 → synkit-0.0.8}/PKG-INFO +2 -2
  6. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Molecule/test_standardize.py +1 -1
  7. synkit-0.0.8/Test/Chem/Reaction/test_aam_utils.py +52 -0
  8. {synkit-0.0.6/Test/Graph/ITS → synkit-0.0.8/Test/Chem/Reaction}/test_aam_validator.py +1 -1
  9. synkit-0.0.8/Test/Chem/Reaction/test_canon_rsmi.py +52 -0
  10. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Reaction/test_deionize.py +1 -1
  11. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Context/test_radius_expand.py +1 -1
  12. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Feature/test_graph_descriptors.py +1 -1
  13. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Hydrogen/test_graph_hydrogen.py +4 -4
  14. synkit-0.0.8/Test/Graph/Hydrogen/test_misc.py +92 -0
  15. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/ITS/test_its_construction.py +4 -4
  16. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/ITS/test_its_expand.py +2 -1
  17. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/ITS/test_normalize_aam.py +1 -1
  18. synkit-0.0.8/Test/Graph/MTG/test_group_comp.py +52 -0
  19. synkit-0.0.8/Test/Graph/MTG/test_groupoid.py +181 -0
  20. synkit-0.0.8/Test/Graph/MTG/test_mtg.py +39 -0
  21. {synkit-0.0.6/Test/Graph/Cluster → synkit-0.0.8/Test/Graph/Matcher}/test_batch_cluster.py +1 -1
  22. {synkit-0.0.6/Test/Graph/Cluster → synkit-0.0.8/Test/Graph/Matcher}/test_graph_cluster.py +6 -3
  23. synkit-0.0.8/Test/Graph/Matcher/test_graph_matcher.py +158 -0
  24. {synkit-0.0.6/Test/Graph/Cluster → synkit-0.0.8/Test/Graph/Matcher}/test_graph_morphism.py +1 -1
  25. synkit-0.0.8/Test/Graph/Matcher/test_subgraph_matcher.py +136 -0
  26. synkit-0.0.8/Test/Graph/test_canon_graph.py +90 -0
  27. synkit-0.0.8/Test/Graph/test_syn_graph.py +69 -0
  28. {synkit-0.0.6 → synkit-0.0.8}/Test/IO/test_chemical_converter.py +130 -25
  29. {synkit-0.0.6 → synkit-0.0.8}/Test/IO/test_dg_to_gml.py +22 -15
  30. {synkit-0.0.6 → synkit-0.0.8}/Test/IO/test_gml_to_nx.py +1 -1
  31. {synkit-0.0.6/Test/Rule → synkit-0.0.8/Test/Rule/Apply}/test_reactor_rule.py +7 -2
  32. {synkit-0.0.6/Test/Rule → synkit-0.0.8/Test/Rule/Apply}/test_retro_reactor.py +5 -1
  33. {synkit-0.0.6/Test/Rule → synkit-0.0.8/Test/Rule/Apply}/test_rule_rbl.py +5 -1
  34. {synkit-0.0.6/Test/Rule → synkit-0.0.8/Test/Rule/Compose}/test_rule_compose.py +12 -6
  35. {synkit-0.0.6/Test/Rule → synkit-0.0.8/Test/Rule/Compose}/test_valance_constrain.py +12 -2
  36. {synkit-0.0.6/Test/Rule → synkit-0.0.8/Test/Rule/Modify}/test_molecule_rule.py +13 -4
  37. {synkit-0.0.6/Test/Rule → synkit-0.0.8/Test/Rule/Modify}/test_rule_utils.py +19 -5
  38. synkit-0.0.8/Test/Rule/test_syn_rule.py +99 -0
  39. synkit-0.0.8/Test/Synthesis/CRN/test_crn.py +54 -0
  40. synkit-0.0.8/Test/Synthesis/CRN/test_mod_crn.py +50 -0
  41. {synkit-0.0.6/Test/Reactor → synkit-0.0.8/Test/Synthesis/MSR}/test_multi_steps.py +6 -3
  42. {synkit-0.0.6/Test/Reactor → synkit-0.0.8/Test/Synthesis/MSR}/test_path_finder.py +7 -4
  43. synkit-0.0.8/Test/Synthesis/Reactor/test_core_engine.py +112 -0
  44. synkit-0.0.6/Test/Reactor/test_reactor_engine.py → synkit-0.0.8/Test/Synthesis/Reactor/test_mod_aam.py +45 -88
  45. synkit-0.0.8/Test/Synthesis/Reactor/test_mod_reactor.py +153 -0
  46. synkit-0.0.8/Test/Synthesis/Reactor/test_strategy.py +42 -0
  47. {synkit-0.0.6/Test/Reactor → synkit-0.0.8/Test/Synthesis}/test_reactor_utils.py +7 -2
  48. synkit-0.0.8/build-doc.sh +31 -0
  49. synkit-0.0.8/doc/api.rst +235 -0
  50. synkit-0.0.8/doc/changelog.rst +76 -0
  51. synkit-0.0.8/doc/chem.rst +69 -0
  52. {synkit-0.0.6 → synkit-0.0.8}/doc/conf.py +3 -2
  53. synkit-0.0.8/doc/figures/aldol.png +0 -0
  54. synkit-0.0.8/doc/figures/aldol_its.png +0 -0
  55. synkit-0.0.8/doc/figures/mtg.png +0 -0
  56. synkit-0.0.8/doc/getting_started.rst +84 -0
  57. synkit-0.0.8/doc/graph.rst +264 -0
  58. synkit-0.0.8/doc/index.rst +15 -0
  59. synkit-0.0.8/doc/io.rst +163 -0
  60. synkit-0.0.8/doc/reference.rst +6 -0
  61. synkit-0.0.8/doc/refs.bib +29 -0
  62. synkit-0.0.8/doc/rule.rst +2 -0
  63. synkit-0.0.8/doc/synthesis.rst +195 -0
  64. synkit-0.0.8/environment.yml +9 -0
  65. synkit-0.0.8/lint.sh +30 -0
  66. {synkit-0.0.6 → synkit-0.0.8}/pyproject.toml +2 -2
  67. {synkit-0.0.6 → synkit-0.0.8}/requirements.txt +1 -1
  68. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Molecule/standardize.py +24 -0
  69. synkit-0.0.8/synkit/Chem/Reaction/__init__.py +4 -0
  70. synkit-0.0.8/synkit/Chem/Reaction/aam_validator.py +253 -0
  71. synkit-0.0.8/synkit/Chem/Reaction/canon_rsmi.py +255 -0
  72. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Reaction/rsmi_utils.py +26 -0
  73. synkit-0.0.8/synkit/Chem/Reaction/standardize.py +151 -0
  74. synkit-0.0.8/synkit/Chem/__init__.py +1 -0
  75. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Context/hier_context.py +1 -1
  76. synkit-0.0.8/synkit/Graph/Feature/__init__.py +5 -0
  77. synkit-0.0.8/synkit/Graph/Feature/wl_hash.py +142 -0
  78. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Hyrogen/_misc.py +232 -90
  79. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Hyrogen/hcomplete.py +1 -1
  80. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Hyrogen/hextend.py +1 -1
  81. synkit-0.0.8/synkit/Graph/ITS/__init__.py +4 -0
  82. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/ITS/its_construction.py +105 -1
  83. synkit-0.0.8/synkit/Graph/ITS/its_decompose.py +486 -0
  84. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/ITS/its_expand.py +1 -2
  85. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/ITS/normalize_aam.py +0 -1
  86. synkit-0.0.8/synkit/Graph/MTG/group_comp.py +158 -0
  87. synkit-0.0.8/synkit/Graph/MTG/groupoid.py +357 -0
  88. synkit-0.0.8/synkit/Graph/MTG/mcs_matcher.py +205 -0
  89. synkit-0.0.8/synkit/Graph/MTG/mtg.py +207 -0
  90. synkit-0.0.8/synkit/Graph/Matcher/__init__.py +10 -0
  91. {synkit-0.0.6/synkit/Graph/Cluster → synkit-0.0.8/synkit/Graph/Matcher}/batch_cluster.py +33 -12
  92. {synkit-0.0.6/synkit/Graph/Cluster → synkit-0.0.8/synkit/Graph/Matcher}/graph_cluster.py +46 -12
  93. synkit-0.0.8/synkit/Graph/Matcher/graph_matcher.py +320 -0
  94. synkit-0.0.8/synkit/Graph/Matcher/mcs_matcher.py +202 -0
  95. synkit-0.0.8/synkit/Graph/Matcher/sing.py +212 -0
  96. synkit-0.0.8/synkit/Graph/Matcher/subgraph_matcher.py +556 -0
  97. synkit-0.0.8/synkit/Graph/Matcher/turbo_iso.py +204 -0
  98. synkit-0.0.8/synkit/Graph/__init__.py +6 -0
  99. synkit-0.0.8/synkit/Graph/canon_algs.py +257 -0
  100. synkit-0.0.8/synkit/Graph/canon_graph.py +529 -0
  101. synkit-0.0.8/synkit/Graph/syn_graph.py +166 -0
  102. synkit-0.0.8/synkit/Graph/utils.py +159 -0
  103. synkit-0.0.8/synkit/IO/__init__.py +3 -0
  104. synkit-0.0.8/synkit/IO/chem_converter.py +456 -0
  105. synkit-0.0.8/synkit/IO/data_io.py +335 -0
  106. synkit-0.0.8/synkit/IO/debug.py +75 -0
  107. {synkit-0.0.6 → synkit-0.0.8}/synkit/IO/dg_to_gml.py +9 -1
  108. {synkit-0.0.6 → synkit-0.0.8}/synkit/IO/gml_to_nx.py +34 -2
  109. {synkit-0.0.6 → synkit-0.0.8}/synkit/IO/graph_to_mol.py +36 -19
  110. synkit-0.0.8/synkit/IO/mol_to_graph.py +353 -0
  111. {synkit-0.0.6 → synkit-0.0.8}/synkit/IO/nx_to_gml.py +80 -74
  112. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Apply}/reactor_rule.py +13 -6
  113. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Apply}/retro_reactor.py +11 -3
  114. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Apply}/rule_rbl.py +11 -5
  115. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Compose}/compose_rule.py +25 -7
  116. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Compose}/rule_compose.py +10 -2
  117. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Compose}/seq_comp.py +3 -3
  118. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Compose}/valence_constrain.py +8 -2
  119. synkit-0.0.8/synkit/Rule/Modify/implict_rule.py +66 -0
  120. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Modify}/molecule_rule.py +1 -1
  121. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Modify}/prune_templates.py +1 -1
  122. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Modify}/strip_rule.py +1 -1
  123. synkit-0.0.8/synkit/Rule/__init__.py +1 -0
  124. synkit-0.0.8/synkit/Rule/syn_rule.py +280 -0
  125. synkit-0.0.8/synkit/Synthesis/CRN/__init__.py +0 -0
  126. synkit-0.0.8/synkit/Synthesis/CRN/crn.py +207 -0
  127. {synkit-0.0.6/synkit/Reactor → synkit-0.0.8/synkit/Synthesis/CRN}/dcrn.py +2 -2
  128. synkit-0.0.8/synkit/Synthesis/CRN/mod_crn.py +169 -0
  129. synkit-0.0.8/synkit/Synthesis/MSR/__init__.py +0 -0
  130. {synkit-0.0.6/synkit/Reactor → synkit-0.0.8/synkit/Synthesis/MSR}/multi_steps.py +13 -9
  131. synkit-0.0.8/synkit/Synthesis/Metrics/__init__.py +0 -0
  132. {synkit-0.0.6/synkit → synkit-0.0.8/synkit/Synthesis}/Metrics/_base.py +1 -1
  133. synkit-0.0.8/synkit/Synthesis/Reactor/__init__.py +0 -0
  134. synkit-0.0.8/synkit/Synthesis/Reactor/core_engine.py +212 -0
  135. synkit-0.0.8/synkit/Synthesis/Reactor/mod_aam.py +283 -0
  136. synkit-0.0.8/synkit/Synthesis/Reactor/mod_reactor.py +446 -0
  137. synkit-0.0.8/synkit/Synthesis/Reactor/old_syn_reactor.py +443 -0
  138. {synkit-0.0.6/synkit → synkit-0.0.8/synkit/Synthesis}/Reactor/single_predictor.py +14 -14
  139. synkit-0.0.8/synkit/Synthesis/Reactor/strategy.py +51 -0
  140. synkit-0.0.8/synkit/Synthesis/Reactor/syn_reactor.py +561 -0
  141. synkit-0.0.8/synkit/Synthesis/__init__.py +0 -0
  142. {synkit-0.0.6/synkit/Reactor → synkit-0.0.8/synkit/Synthesis}/reactor_utils.py +2 -2
  143. synkit-0.0.8/synkit/Utils/__init__.py +0 -0
  144. synkit-0.0.8/synkit/Vis/__init__.py +5 -0
  145. synkit-0.0.8/synkit/Vis/graph_visualizer.py +376 -0
  146. synkit-0.0.8/synkit/Vis/rule_vis.py +185 -0
  147. synkit-0.0.8/synkit/Vis/rxn_vis.py +163 -0
  148. synkit-0.0.8/synkit/__init__.py +0 -0
  149. synkit-0.0.6/.github/workflows/test-and-lint.yml +0 -55
  150. synkit-0.0.6/CHANGELOG.md +0 -89
  151. synkit-0.0.6/Data/Benchmark/conversion_time.json.gz +0 -240767
  152. synkit-0.0.6/Data/Figure/synkit.png +0 -0
  153. synkit-0.0.6/Data/Testcase/mech.json.gz +0 -1
  154. synkit-0.0.6/Data/Testcase/para_rule.json.gz +0 -1
  155. synkit-0.0.6/Data/Testcase/para_rule_retro.json.gz +0 -1
  156. synkit-0.0.6/Data/smart.json.gz +0 -1
  157. synkit-0.0.6/Test/Graph/Cluster/test_rule_morphism.py +0 -103
  158. synkit-0.0.6/Test/Reactor/test_core_engine.py +0 -112
  159. synkit-0.0.6/Test/Reactor/test_crn.py +0 -58
  160. synkit-0.0.6/Test/Vis/test_dpo_vis.py +0 -75
  161. synkit-0.0.6/doc/getting_started.rst +0 -66
  162. synkit-0.0.6/doc/index.rst +0 -23
  163. synkit-0.0.6/doc/references.rst +0 -113
  164. synkit-0.0.6/lint.sh +0 -7
  165. synkit-0.0.6/synkit/Chem/Reaction/standardize.py +0 -159
  166. synkit-0.0.6/synkit/Graph/Cluster/rule_morphism.py +0 -102
  167. synkit-0.0.6/synkit/Graph/Feature/wl_hash.py +0 -120
  168. synkit-0.0.6/synkit/Graph/ITS/aam_validator.py +0 -255
  169. synkit-0.0.6/synkit/Graph/ITS/its_decompose.py +0 -243
  170. synkit-0.0.6/synkit/IO/chem_converter.py +0 -386
  171. synkit-0.0.6/synkit/IO/data_io.py +0 -301
  172. synkit-0.0.6/synkit/IO/debug.py +0 -79
  173. synkit-0.0.6/synkit/IO/mol_to_graph.py +0 -282
  174. synkit-0.0.6/synkit/Reactor/core_engine.py +0 -213
  175. synkit-0.0.6/synkit/Reactor/crn.py +0 -118
  176. synkit-0.0.6/synkit/Reactor/reactor_engine.py +0 -228
  177. synkit-0.0.6/synkit/Rule/MaxValence.json.gz +0 -1
  178. synkit-0.0.6/synkit/Vis/chemical_graph_visualizer.py +0 -378
  179. synkit-0.0.6/synkit/Vis/chemical_reaction_visualizer.py +0 -133
  180. synkit-0.0.6/synkit/Vis/dpo_vis.py +0 -103
  181. synkit-0.0.6/synkit/Vis/graph_visualizer.py +0 -287
  182. synkit-0.0.6/synkit/Vis/rsmi_to_fig.py +0 -169
  183. {synkit-0.0.6 → synkit-0.0.8}/.github/workflows/publish-package.yml +0 -0
  184. {synkit-0.0.6 → synkit-0.0.8}/Data/Testcase/Compose/ComposeRule/data.txt +0 -0
  185. {synkit-0.0.6 → synkit-0.0.8}/Data/Testcase/Compose/SingleRule/R0/0.gml +0 -0
  186. {synkit-0.0.6 → synkit-0.0.8}/Data/Testcase/Compose/SingleRule/R0/1.gml +0 -0
  187. {synkit-0.0.6 → synkit-0.0.8}/Data/Testcase/Compose/SingleRule/R0/2.gml +0 -0
  188. {synkit-0.0.6 → synkit-0.0.8}/LICENSE +0 -0
  189. {synkit-0.0.6 → synkit-0.0.8}/Makefile +0 -0
  190. {synkit-0.0.6 → synkit-0.0.8}/README.md +0 -0
  191. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Fingerprint/__init__.py +0 -0
  192. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Fingerprint/test_fp_calculator.py +0 -0
  193. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Fingerprint/test_smiles_featurizer.py +0 -0
  194. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Fingerprint/test_transformation_fp.py +0 -0
  195. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Molecule/__init__.py +0 -0
  196. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Reaction/__init__.py +0 -0
  197. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Reaction/test_balance_checker.py +0 -0
  198. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Reaction/test_cleanning.py +0 -0
  199. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Reaction/test_fix_aam.py +0 -0
  200. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Reaction/test_neutralize.py +0 -0
  201. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Reaction/test_rsmi_utils.py +0 -0
  202. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Reaction/test_standardize.py +0 -0
  203. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/Reaction/test_tautomerize.py +0 -0
  204. {synkit-0.0.6 → synkit-0.0.8}/Test/Chem/__init__.py +0 -0
  205. {synkit-0.0.6/Test/Graph/Cluster → synkit-0.0.8/Test/Graph/Context}/__init__.py +0 -0
  206. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Context/test_hier_context.py +0 -0
  207. {synkit-0.0.6/Test/Graph/Context → synkit-0.0.8/Test/Graph/Feature}/__init__.py +0 -0
  208. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Feature/test_graph_fps.py +0 -0
  209. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Feature/test_graph_signature.py +0 -0
  210. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Feature/test_hash_fps.py +0 -0
  211. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Feature/test_morgan_fps.py +0 -0
  212. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Feature/test_path_fps.py +0 -0
  213. {synkit-0.0.6/Test/Graph/Feature → synkit-0.0.8/Test/Graph/Hydrogen}/__init__.py +0 -0
  214. {synkit-0.0.6 → synkit-0.0.8}/Test/Graph/Hydrogen/test_hcomplete.py +0 -0
  215. {synkit-0.0.6/Test/Graph/Hydrogen → synkit-0.0.8/Test/Graph/ITS}/__init__.py +0 -0
  216. {synkit-0.0.6/Test/Graph/ITS → synkit-0.0.8/Test/Graph/MTG}/__init__.py +0 -0
  217. {synkit-0.0.6/Test/Graph → synkit-0.0.8/Test/Graph/Matcher}/__init__.py +0 -0
  218. {synkit-0.0.6/Test/IO → synkit-0.0.8/Test/Graph}/__init__.py +0 -0
  219. {synkit-0.0.6/Test/Reactor → synkit-0.0.8/Test/IO}/__init__.py +0 -0
  220. {synkit-0.0.6 → synkit-0.0.8}/Test/IO/test_graph_to_mol.py +0 -0
  221. {synkit-0.0.6 → synkit-0.0.8}/Test/IO/test_mol_to_graph.py +0 -0
  222. {synkit-0.0.6 → synkit-0.0.8}/Test/IO/test_nx_to_gml.py +0 -0
  223. {synkit-0.0.6/Test/Rule → synkit-0.0.8/Test/Rule/Apply}/__init__.py +0 -0
  224. {synkit-0.0.6/Test/Vis → synkit-0.0.8/Test/Rule/Compose}/__init__.py +0 -0
  225. {synkit-0.0.6/Test → synkit-0.0.8/Test/Rule/Modify}/__init__.py +0 -0
  226. {synkit-0.0.6/synkit/Chem/Fingerprint → synkit-0.0.8/Test/Rule}/__init__.py +0 -0
  227. {synkit-0.0.6/synkit/Chem/Molecule → synkit-0.0.8/Test/Synthesis/CRN}/__init__.py +0 -0
  228. {synkit-0.0.6/synkit/Chem/Reaction → synkit-0.0.8/Test/Synthesis/MSR}/__init__.py +0 -0
  229. {synkit-0.0.6/synkit/Graph/Cluster → synkit-0.0.8/Test/Synthesis/Reactor}/__init__.py +0 -0
  230. {synkit-0.0.6/synkit/Graph/Context → synkit-0.0.8/Test/Synthesis}/__init__.py +0 -0
  231. {synkit-0.0.6/synkit/Graph/Feature → synkit-0.0.8/Test/Vis}/__init__.py +0 -0
  232. {synkit-0.0.6 → synkit-0.0.8}/Test/Vis/test_embedding.py +0 -0
  233. {synkit-0.0.6/synkit/Graph/Hyrogen → synkit-0.0.8/Test}/__init__.py +0 -0
  234. {synkit-0.0.6 → synkit-0.0.8}/make.bat +0 -0
  235. {synkit-0.0.6 → synkit-0.0.8}/pytest.sh +0 -0
  236. {synkit-0.0.6/synkit/IO → synkit-0.0.8/synkit/Chem/Fingerprint}/__init__.py +0 -0
  237. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
  238. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
  239. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
  240. {synkit-0.0.6/synkit/Metrics → synkit-0.0.8/synkit/Chem/Molecule}/__init__.py +0 -0
  241. {synkit-0.0.6/synkit/Graph/ITS → synkit-0.0.8/synkit/Chem/Reaction}/aam_utils.py +0 -0
  242. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Reaction/balance_check.py +0 -0
  243. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Reaction/cleanning.py +0 -0
  244. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Reaction/deionize.py +0 -0
  245. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Reaction/fix_aam.py +0 -0
  246. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Reaction/neutralize.py +0 -0
  247. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/Reaction/tautomerize.py +0 -0
  248. {synkit-0.0.6 → synkit-0.0.8}/synkit/Chem/utils.py +0 -0
  249. {synkit-0.0.6/synkit/Reactor → synkit-0.0.8/synkit/Graph/Context}/__init__.py +0 -0
  250. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Context/radius_expand.py +0 -0
  251. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Feature/graph_descriptors.py +0 -0
  252. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Feature/graph_fps.py +0 -0
  253. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Feature/graph_signature.py +0 -0
  254. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Feature/hash_fps.py +0 -0
  255. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Feature/morgan_fps.py +0 -0
  256. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/Feature/path_fps.py +0 -0
  257. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Graph/Hyrogen}/__init__.py +0 -0
  258. {synkit-0.0.6 → synkit-0.0.8}/synkit/Graph/ITS/its_builder.py +0 -0
  259. {synkit-0.0.6/synkit/Utils → synkit-0.0.8/synkit/Graph/MTG}/__init__.py +0 -0
  260. {synkit-0.0.6/synkit/Graph/Cluster → synkit-0.0.8/synkit/Graph/Matcher}/graph_morphism.py +0 -0
  261. {synkit-0.0.6 → synkit-0.0.8}/synkit/IO/data_process.py +0 -0
  262. {synkit-0.0.6 → synkit-0.0.8}/synkit/IO/smiles_to_id.py +0 -0
  263. {synkit-0.0.6/synkit/Vis → synkit-0.0.8/synkit/Rule/Apply}/__init__.py +0 -0
  264. {synkit-0.0.6/synkit → synkit-0.0.8/synkit/Rule/Compose}/__init__.py +0 -0
  265. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Compose}/rule_mapping.py +0 -0
  266. /synkit-0.0.6/synkit/Graph/__init.py → /synkit-0.0.8/synkit/Rule/Modify/__init__.py +0 -0
  267. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Modify}/longest_path.py +0 -0
  268. {synkit-0.0.6/synkit/Rule → synkit-0.0.8/synkit/Rule/Modify}/rule_utils.py +0 -0
  269. {synkit-0.0.6/synkit/Reactor → synkit-0.0.8/synkit/Synthesis/MSR}/path_finder.py +0 -0
  270. {synkit-0.0.6/synkit → synkit-0.0.8/synkit/Synthesis}/Metrics/_plot.py +0 -0
  271. {synkit-0.0.6/synkit → synkit-0.0.8/synkit/Synthesis}/Metrics/_ranking.py +0 -0
  272. {synkit-0.0.6 → synkit-0.0.8}/synkit/Utils/utils.py +0 -0
  273. {synkit-0.0.6 → synkit-0.0.8}/synkit/Vis/chemical_space.py +0 -0
  274. {synkit-0.0.6 → synkit-0.0.8}/synkit/Vis/embedding.py +0 -0
  275. {synkit-0.0.6 → synkit-0.0.8}/synkit/Vis/pdf_writer.py +0 -0
@@ -23,6 +23,7 @@ jobs:
23
23
  cache: 'pip' # caching pip dependencies
24
24
  - run: pip install -r requirements.txt
25
25
  - run: pip install sphinx sphinx-rtd-theme
26
+ - run: pip install sphinxcontrib-bibtex
26
27
  - run: python3 -m sphinx ./doc docs
27
28
  - name: publish doc
28
29
  shell: bash
@@ -0,0 +1,68 @@
1
+ name: Test & Lint
2
+
3
+ on:
4
+ push:
5
+ branches: [ "main", "dev", "maintain", "refractor" ]
6
+ pull_request:
7
+ branches: [ "main" ]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test-lint:
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ os: [ubuntu-latest, macos-latest, windows-latest]
18
+
19
+ runs-on: ${{ matrix.os }}
20
+
21
+ steps:
22
+ # 0) Check out the code
23
+ - uses: actions/checkout@v3
24
+
25
+ # 1) Install Miniconda (downloaded — the “bundled” version was removed)
26
+ - name: Set up Miniconda
27
+ uses: conda-incubator/setup-miniconda@v2
28
+ with:
29
+ miniconda-version: "latest" # <<–‑‑ mandatory or the action fails
30
+ python-version: "3.11"
31
+ auto-update-conda: true
32
+ environment-file: environment.yml
33
+ activate-environment: synkit-env
34
+ use-mamba: true # optional, just faster
35
+
36
+ # 2) Extra Linux‑only dependency: mod ≥ 0.17
37
+ - name: Install mod (Linux only)
38
+ if: matrix.os == 'ubuntu-latest'
39
+ run: conda run -n synkit-env conda install -c jakobandersen -c conda-forge "mod>=0.17" -y
40
+
41
+ # 3) Optional extra project deps via pip (requirements.txt)
42
+ - name: Install project requirements
43
+ if: hashFiles('requirements.txt') != ''
44
+ run: conda run -n synkit-env pip install -r requirements.txt
45
+
46
+ # 4a) Lint on Linux/macOS
47
+ - name: Lint (Unix)
48
+ if: matrix.os != 'windows-latest'
49
+ shell: bash -l {0}
50
+ run: |
51
+ conda activate synkit-env
52
+ bash lint.sh
53
+
54
+ # 4b) Lint on Windows
55
+ - name: Lint (Windows)
56
+ if: matrix.os == 'windows-latest'
57
+ shell: bash -l {0}
58
+ run: |
59
+ conda activate synkit-env
60
+ bash lint.sh
61
+
62
+
63
+ # 5) Test
64
+ - name: Test
65
+ shell: bash -l {0}
66
+ run: |
67
+ conda activate synkit-env
68
+ bash pytest.sh
@@ -4,19 +4,19 @@
4
4
  */catboost_info/*
5
5
  *.ipynb
6
6
  *.json
7
- test_mod.py
8
- test_format.py
9
- *dev_zone
10
7
  *.pkl.gz
11
- dev_scripts/*
12
8
  *.pdf
13
9
  out
14
10
  summary
15
- Data/Benchmark/its.json.gz
16
- Data/Benchmark/rc.json.gz
17
11
  *.log
18
12
  .coverage
19
13
  dev/*
20
14
  *.rdf
21
15
  Data/Testcase/hydro/aam.json.gz
22
16
  synkit/Chem/FG/*
17
+ test_syn_reactor.py
18
+ Data/Benchmark/*
19
+ # *.png
20
+ *.json.gz
21
+ run.sh
22
+ docs/*
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synkit
3
- Version: 0.0.6
3
+ Version: 0.0.8
4
4
  Summary: Utility for reaction modeling using graph grammar
5
5
  Project-URL: homepage, https://github.com/TieuLongPhan/SynKit
6
6
  Project-URL: source, https://github.com/TieuLongPhan/SynKit
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3
14
14
  Requires-Python: >=3.11
15
15
  Requires-Dist: networkx>=3.3
16
16
  Requires-Dist: pandas>=1.5.3
17
- Requires-Dist: rdkit>=2024.3.3
17
+ Requires-Dist: rdkit>=2025.3.1
18
18
  Requires-Dist: regex>=2024.11.6
19
19
  Requires-Dist: requests>=2.32.3
20
20
  Requires-Dist: scikit-learn>=1.4.0
@@ -17,7 +17,7 @@ class TestMoleculeFunctions(unittest.TestCase):
17
17
 
18
18
  def test_normalize_molecule(self):
19
19
  smi = "[Na]OC(=O)c1ccc(C[S+2]([O-])([O-]))cc1"
20
- expect = "O=C(O[Na])c1ccc(C[S](=O)=O)cc1"
20
+ expect = "O=C([O][Na])c1ccc(C[S](=O)=O)cc1"
21
21
  mol = Chem.MolFromSmiles(smi)
22
22
  normalized_mol = normalize_molecule(mol)
23
23
  self.assertIsInstance(normalized_mol, Chem.Mol)
@@ -0,0 +1,52 @@
1
+ import unittest
2
+ from rdkit import Chem
3
+ from synkit.Chem.Reaction.aam_utils import enumerate_tautomers, mapping_success_rate
4
+
5
+
6
+ class TestChemUtils(unittest.TestCase):
7
+ def test_enumerate_tautomers_simple(self):
8
+ # A simple keto-enol tautomerism: acetylacetone (CC(=O)CC=O) -> same product
9
+ reaction = "CC(=O)CC=O>>O"
10
+ tautomers = enumerate_tautomers(reaction)
11
+ # Should return a list with at least the original reaction
12
+ self.assertIsInstance(tautomers, list)
13
+ self.assertIn(reaction, tautomers)
14
+ # Each entry should be a valid reaction SMILES
15
+ for rsmi in tautomers:
16
+ self.assertIsInstance(rsmi, str)
17
+ parts = rsmi.split(">>")
18
+ self.assertEqual(len(parts), 2)
19
+ # Reactant and product part parseable by RDKit
20
+ self.assertIsNotNone(Chem.MolFromSmiles(parts[0]))
21
+ self.assertIsNotNone(Chem.MolFromSmiles(parts[1]))
22
+
23
+ def test_enumerate_tautomers_invalid(self):
24
+ # Invalid SMILES input
25
+ bad = "INVALID>>SMILES"
26
+ result = enumerate_tautomers(bad)
27
+ # Should return list with original
28
+ self.assertEqual(result, [bad])
29
+
30
+ def test_mapping_success_rate_normal(self):
31
+ data = ["C:1CC", "CCC", "O:3=O", ":5", "N"]
32
+ rate = mapping_success_rate(data)
33
+ # Entries with mapping: 'C:1CC', 'O:3=O', ':5' => 3/5 = 60.0%
34
+ self.assertEqual(rate, 60.0)
35
+
36
+ def test_mapping_success_rate_empty(self):
37
+ with self.assertRaises(ValueError):
38
+ mapping_success_rate([])
39
+
40
+ def test_mapping_success_rate_all(self):
41
+ data = [":1C", ":2", "N:3"]
42
+ rate = mapping_success_rate(data)
43
+ self.assertEqual(rate, 100.0)
44
+
45
+ def test_mapping_success_rate_none(self):
46
+ data = ["C", "O", "N"]
47
+ rate = mapping_success_rate(data)
48
+ self.assertEqual(rate, 0.0)
49
+
50
+
51
+ if __name__ == "__main__":
52
+ unittest.main()
@@ -1,5 +1,5 @@
1
1
  import unittest
2
- from synkit.Graph.ITS.aam_validator import AAMValidator
2
+ from synkit.Chem.Reaction.aam_validator import AAMValidator
3
3
 
4
4
 
5
5
  class TestAMMValidator(unittest.TestCase):
@@ -0,0 +1,52 @@
1
+ import unittest
2
+ import networkx as nx
3
+ from synkit.Chem.Reaction.canon_rsmi import CanonRSMI
4
+ from synkit.IO.chem_converter import rsmi_to_graph
5
+
6
+
7
+ class TestCanonRSMI(unittest.TestCase):
8
+ def setUp(self):
9
+ # Use generic backend for deterministic behavior
10
+ self.canon = CanonRSMI(backend="wl", wl_iterations=5)
11
+ # Example reaction SMILES with atom-map labels
12
+ self.input_rsmi = "[CH3:3][CH2:5][OH:10]>>[CH2:3]=[CH2:5].[OH2:10]"
13
+ # After expand_aam and canonicalisation, since backend is generic,
14
+ # we expect the SMILES to remain unchanged (identity)
15
+ self.expected_canonical = "[CH2:1]([CH3:2])[OH:3]>>[CH2:1]=[CH2:2].[OH2:3]"
16
+
17
+ def test_raw_and_canonical_rsmi(self):
18
+ result = self.canon.canonicalise(self.input_rsmi)
19
+ self.assertEqual(result.raw_rsmi, self.input_rsmi)
20
+ self.assertEqual(result.canonical_rsmi, self.expected_canonical)
21
+
22
+ def test_mapping_pairs(self):
23
+ result = self.canon(self.input_rsmi)
24
+ # Mapping pairs should preserve identity mapping
25
+ # mapping_pairs will be matching (map_new, map_old)
26
+ self.assertEqual(sorted(result.mapping_pairs), [(1, 5), (2, 3), (3, 10)])
27
+
28
+ def test_graphs_and_hashes(self):
29
+ result = self.canon(self.input_rsmi)
30
+ # raw graphs should parse correctly
31
+ r_raw, p_raw = rsmi_to_graph(self.input_rsmi)
32
+ self.assertIsInstance(result.raw_reactant_graph, nx.Graph)
33
+ self.assertIsInstance(result.raw_product_graph, nx.Graph)
34
+ # canonical graphs should also be Graph
35
+ self.assertIsInstance(result.canonical_reactant_graph, nx.Graph)
36
+ self.assertIsInstance(result.canonical_product_graph, nx.Graph)
37
+ # reactant_hash and product_hash should match underlying canonicaliser
38
+ h_reac = self.canon._canon.canonical_signature(result.canonical_reactant_graph)
39
+ h_prod = self.canon._canon.canonical_signature(result.canonical_product_graph)
40
+ # canonical_hash is combined
41
+ self.assertEqual(result.canonical_hash, f"{h_reac}>>{h_prod}")
42
+
43
+ def test_idempotence(self):
44
+ # Applying canonicalise twice yields same result
45
+ result1 = self.canon(self.input_rsmi)
46
+ result2 = self.canon(result1.canonical_rsmi)
47
+ self.assertEqual(result1.canonical_rsmi, result2.canonical_rsmi)
48
+ self.assertEqual(result1.mapping_pairs, result2.mapping_pairs)
49
+
50
+
51
+ if __name__ == "__main__":
52
+ unittest.main()
@@ -34,7 +34,7 @@ class TestDeionize(unittest.TestCase):
34
34
  def test_uncharge_smiles(self):
35
35
  charge_smiles = "[Na+].[OH-]"
36
36
  uncharged_smiles = Deionize.uncharge_smiles(charge_smiles)
37
- self.assertEqual(uncharged_smiles, "O[Na]") # can not uncharge amonium
37
+ self.assertEqual(uncharged_smiles, "[OH][Na]")
38
38
 
39
39
  def test_apply_uncharge_smiles_to_reactions(self):
40
40
  reactions = [{"reactants": "[NH4+].[OH-]", "products": "N.O"}]
@@ -3,7 +3,7 @@ import networkx as nx
3
3
  from synkit.IO.data_io import load_from_pickle
4
4
  from synkit.Graph.ITS.its_decompose import get_rc
5
5
  from synkit.Graph.Context.radius_expand import RadiusExpand
6
- from synkit.Graph.Cluster.graph_morphism import graph_isomorphism, subgraph_isomorphism
6
+ from synkit.Graph.Matcher.graph_morphism import graph_isomorphism, subgraph_isomorphism
7
7
 
8
8
 
9
9
  class TestRadiusExpand(unittest.TestCase):
@@ -183,7 +183,7 @@ class TestGraphDescriptor(unittest.TestCase):
183
183
 
184
184
  # Run the descriptor function
185
185
  results = GraphDescriptor.process_entries_in_parallel(
186
- self.data_parallel, "GraphRules", "ITSGraph", n_jobs=4
186
+ self.data_parallel, "GraphRules", "ITSGraph", n_jobs=1
187
187
  )
188
188
  self.assertEqual(results[0]["topo"], expected_output["topo"])
189
189
  self.assertEqual(results[0]["cycle"], expected_output["cycle"])
@@ -1,8 +1,8 @@
1
1
  import unittest
2
- from synkit.Graph.ITS.aam_validator import AAMValidator
3
- from synkit.Graph.Cluster.graph_morphism import graph_isomorphism
2
+ from synkit.Chem.Reaction.aam_validator import AAMValidator
3
+ from synkit.Graph.Matcher.graph_morphism import graph_isomorphism
4
4
  from synkit.IO.chem_converter import rsmi_to_graph, graph_to_rsmi
5
- from synkit.Graph.Hyrogen._misc import implicit_hydrogen, explicit_hydrogen
5
+ from synkit.Graph.Hyrogen._misc import implicit_hydrogen, h_to_explicit
6
6
 
7
7
 
8
8
  class TestGraphH(unittest.TestCase):
@@ -53,7 +53,7 @@ class TestGraphH(unittest.TestCase):
53
53
 
54
54
  def test_explicit_hydrogen(self):
55
55
  r_imp, p_imp = rsmi_to_graph(self.implicit_rsmi)
56
- r_ex, p_ex = explicit_hydrogen(r_imp), explicit_hydrogen(p_imp)
56
+ r_ex, p_ex = h_to_explicit(r_imp), h_to_explicit(p_imp)
57
57
  r, p = rsmi_to_graph(self.rsmi)
58
58
  self.assertTrue(graph_isomorphism(r, r_ex))
59
59
  self.assertTrue(graph_isomorphism(p, p_ex))
@@ -0,0 +1,92 @@
1
+ import unittest
2
+
3
+ from synkit.Graph.Hyrogen._misc import (
4
+ has_XH,
5
+ h_to_implicit,
6
+ h_to_explicit,
7
+ check_explicit_hydrogen,
8
+ check_hcount_change,
9
+ )
10
+ from synkit.IO.chem_converter import rsmi_to_its
11
+ from synkit.Graph.ITS.its_decompose import its_decompose
12
+
13
+
14
+ class TestHydrogenUtilities(unittest.TestCase):
15
+
16
+ def setUp(self):
17
+ # Explicit hydrogen example
18
+ self.rsmi_explicit = "[C:1]=[C:2].[H:3][H:4]>>[C:1]([H:3])[C:2][H:4]"
19
+ self.its_explicit = rsmi_to_its(self.rsmi_explicit)
20
+ self.rc_explicit = self.its_explicit
21
+ self.r_explicit, self.p_explicit = its_decompose(self.rc_explicit)
22
+
23
+ # Implicit hydrogen example
24
+ self.rsmi_implicit = "[C:1]=[C:2].[H:3][H:4]>>[CH:1][CH:2]"
25
+ self.its_implicit = rsmi_to_its(self.rsmi_implicit)
26
+ self.rc_implicit = self.its_implicit
27
+ self.r_implicit, self.p_implicit = its_decompose(self.rc_implicit)
28
+
29
+ def test_has_XH_explicit(self):
30
+ self.assertTrue(
31
+ has_XH(self.rc_explicit), "Explicit hydrogen bonds should be detected."
32
+ )
33
+
34
+ def test_has_XH_implicit(self):
35
+ self.assertFalse(
36
+ has_XH(self.rc_implicit),
37
+ "Implicit hydrogen representation should have no explicit X-H bonds.",
38
+ )
39
+
40
+ def test_h_to_implicit_removes_H_nodes(self):
41
+ G = self.rc_explicit
42
+ heavy_atoms = [n for n, d in G.nodes(data=True) if d.get("element") != "H"]
43
+ G_implicit = h_to_implicit(G)
44
+ h_nodes = [n for n, d in G_implicit.nodes(data=True) if d.get("element") == "H"]
45
+ self.assertEqual(len(h_nodes), 0, "All hydrogen nodes should be removed.")
46
+ for n in heavy_atoms:
47
+ self.assertGreaterEqual(
48
+ G_implicit.nodes[n].get("hcount", 0),
49
+ 1,
50
+ "Heavy atoms should have hcount ≥ 1.",
51
+ )
52
+
53
+ def test_h_to_explicit_adds_H_nodes(self):
54
+ G = self.rc_explicit
55
+ G_implicit = h_to_implicit(G)
56
+ heavy_atoms = [
57
+ n for n, d in G_implicit.nodes(data=True) if d.get("element") != "H"
58
+ ]
59
+ G_expanded = h_to_explicit(G_implicit, heavy_atoms)
60
+ h_nodes = [n for n, d in G_expanded.nodes(data=True) if d.get("element") == "H"]
61
+ self.assertGreaterEqual(len(h_nodes), 2, "Hydrogen nodes should be added back.")
62
+
63
+ def test_roundtrip_hydrogen_conversion(self):
64
+ G = self.rc_explicit
65
+ heavy_atoms = [n for n, d in G.nodes(data=True) if d.get("element") != "H"]
66
+ G1 = h_to_implicit(G)
67
+ G2 = h_to_explicit(G1, heavy_atoms)
68
+ h_nodes = [n for n, d in G2.nodes(data=True) if d.get("element") == "H"]
69
+ self.assertGreaterEqual(
70
+ len(h_nodes),
71
+ 2,
72
+ "Hydrogens should be recoverable after roundtrip conversion.",
73
+ )
74
+
75
+ def test_check_explicit_hydrogen(self):
76
+ count, ids = check_explicit_hydrogen(self.rc_explicit)
77
+ self.assertEqual(count, 2, "Should detect 2 explicit hydrogens.")
78
+ self.assertEqual(len(ids), 2)
79
+ for node_id in ids:
80
+ self.assertEqual(self.rc_explicit.nodes[node_id]["element"], "H")
81
+
82
+ def test_check_hcount_change_explicit(self):
83
+ delta = check_hcount_change(self.r_explicit, self.p_explicit)
84
+ self.assertEqual(delta, 2, "Expected hydrogen movement in explicit graph.")
85
+
86
+ def test_check_hcount_change_implicit(self):
87
+ delta = check_hcount_change(self.r_implicit, self.p_implicit)
88
+ self.assertEqual(delta, 2, "Expected hydrogen movement in implicit graph.")
89
+
90
+
91
+ if __name__ == "__main__":
92
+ unittest.main()
@@ -21,21 +21,21 @@ class TestITSConstruction(unittest.TestCase):
21
21
  self.H.add_edge(1, 2, order=1) # Different order
22
22
 
23
23
  def test_ITSGraph(self):
24
- ITS = ITSConstruction.ITSGraph(self.G, self.H)
24
+ ITS = ITSConstruction().ITSGraph(self.G, self.H)
25
25
  self.assertTrue(isinstance(ITS, nx.Graph))
26
26
  self.assertEqual(len(ITS.nodes()), 2)
27
27
  self.assertEqual(len(ITS.edges()), 1)
28
28
  self.assertEqual(ITS[1][2]["order"], (2, 1))
29
29
 
30
30
  def test_get_node_attributes_with_defaults(self):
31
- attributes = ITSConstruction.get_node_attributes_with_defaults(self.G, 1)
31
+ attributes = ITSConstruction().get_node_attributes_with_defaults(self.G, 1)
32
32
  self.assertEqual(attributes, ("C", False, 2, 0, ["", ""]))
33
33
 
34
34
  def test_add_edges_to_ITS(self):
35
35
  ITS = nx.Graph()
36
36
  ITS.add_node(1, element="C", aromatic=False, hcount=3, charge=0)
37
37
  ITS.add_node(2, element="C", aromatic=False, hcount=3, charge=0)
38
- new_ITS = ITSConstruction.add_edges_to_ITS(ITS, self.G, self.H)
38
+ new_ITS = ITSConstruction().add_edges_to_ITS(ITS, self.G, self.H)
39
39
  self.assertTrue(isinstance(new_ITS, nx.Graph))
40
40
  self.assertEqual(len(new_ITS.edges()), 1)
41
41
  self.assertEqual(new_ITS[1][2]["order"], (2, 1))
@@ -43,7 +43,7 @@ class TestITSConstruction(unittest.TestCase):
43
43
  def test_add_standard_order_attribute(self):
44
44
  graph = nx.Graph()
45
45
  graph.add_edge(1, 2, order=(1, 2))
46
- updated_graph = ITSConstruction.add_standard_order_attribute(graph)
46
+ updated_graph = ITSConstruction().add_standard_order_attribute(graph)
47
47
  self.assertEqual(updated_graph[1][2]["standard_order"], -1)
48
48
 
49
49
 
@@ -1,5 +1,5 @@
1
1
  import unittest
2
- from synkit.Graph.ITS.aam_validator import AAMValidator
2
+ from synkit.Chem.Reaction.aam_validator import AAMValidator
3
3
  from synkit.Graph.ITS.its_expand import ITSExpand
4
4
 
5
5
 
@@ -12,6 +12,7 @@ class TestPartialExpand(unittest.TestCase):
12
12
  "[CH3:1][CH2:2][CH2:3][Cl:4].[NH2:5][H:6]"
13
13
  + ">>[CH3:1][CH2:2][CH2:3][NH2:5].[Cl:4][H:6]"
14
14
  )
15
+ print(output_rsmi)
15
16
  self.assertTrue(AAMValidator.smiles_check(output_rsmi, expected_rsmi, "ITS"))
16
17
 
17
18
 
@@ -1,7 +1,7 @@
1
1
  import unittest
2
2
  import networkx as nx
3
3
  from synkit.Graph.ITS.normalize_aam import NormalizeAAM
4
- from synkit.Graph.ITS.aam_validator import AAMValidator
4
+ from synkit.Chem.Reaction.aam_validator import AAMValidator
5
5
 
6
6
 
7
7
  class TestNormalizeAAM(unittest.TestCase):
@@ -0,0 +1,52 @@
1
+ import unittest
2
+ from synkit.IO.chem_converter import rsmi_to_its
3
+ from synkit.Graph.MTG.groupoid import node_constraint
4
+ from synkit.Graph.MTG.group_comp import GroupComp
5
+
6
+
7
+ class TestGroupComp(unittest.TestCase):
8
+
9
+ def setUp(self) -> None:
10
+ test_1 = [
11
+ "[CH:4]([H:7])([H:8])[CH:5]=[O:6]>>[CH:4]([H:8])=[CH:5][O:6]([H:7])",
12
+ "[CH3:1][CH:2]=[O:3].[CH:4]([H:8])=[CH:5][O:6]([H:7])>>[CH3:1][CH:2]([O:3][H:7])[CH:4]([H:8])[CH:5]=[O:6]",
13
+ ]
14
+ self.test_graph_1 = [rsmi_to_its(var) for var in test_1]
15
+ test_2 = [
16
+ "[CH2:1]=[CH:2]-[CH2+:3]>>[CH2+:1]-[CH:2]=[CH2:3]",
17
+ "[H:1]-[CH2:2]-[CH2+:3]>>[CH2:2]=[CH2:3].[H+:1]",
18
+ ]
19
+ self.test_graph_2 = [rsmi_to_its(var) for var in test_2]
20
+
21
+ def test_get_mapping(self):
22
+ g = GroupComp(self.test_graph_1[0], self.test_graph_1[1])
23
+ m = g.get_mapping(include_singleton=False)
24
+ self.assertEqual(len(m), 4)
25
+
26
+ def test_get_mapping_singleton(self):
27
+ g = GroupComp(self.test_graph_1[0], self.test_graph_1[1])
28
+ m = g.get_mapping(include_singleton=True)
29
+ self.assertEqual(len(m), 10)
30
+
31
+ def test_get_mapping_from_nodes(self):
32
+ m0 = node_constraint(
33
+ self.test_graph_2[0].nodes(data=True), self.test_graph_2[1].nodes(data=True)
34
+ )
35
+ g = GroupComp(self.test_graph_2[0], self.test_graph_2[1])
36
+ m = g.get_mapping_from_nodes(
37
+ m0,
38
+ self.test_graph_2[0].edges(data=True),
39
+ self.test_graph_2[1].edges(data=True),
40
+ )
41
+ self.assertEqual(len(m), 1)
42
+
43
+ def test_get_mapping_fallback(self):
44
+ g = GroupComp(self.test_graph_2[0], self.test_graph_2[1])
45
+ m = g.get_mapping(
46
+ include_singleton=False
47
+ ) # even False if cannot find candidate will fall back
48
+ self.assertEqual(len(m), 1)
49
+
50
+
51
+ if __name__ == "__main__":
52
+ unittest.main()