synkit 0.0.8__tar.gz → 0.0.10__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 (271) hide show
  1. {synkit-0.0.8 → synkit-0.0.10}/.gitignore +2 -1
  2. synkit-0.0.10/.readthedocs.yml +24 -0
  3. {synkit-0.0.8 → synkit-0.0.10}/PKG-INFO +5 -1
  4. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_canon_rsmi.py +5 -1
  5. synkit-0.0.10/Test/Chem/Reaction/test_radical_wildcard.py +51 -0
  6. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/ITS/test_its_expand.py +9 -1
  7. synkit-0.0.10/Test/Graph/ITS/test_its_relabel.py +61 -0
  8. synkit-0.0.10/Test/Rule/Apply/test_rule_matcher.py +94 -0
  9. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Modify/test_molecule_rule.py +1 -1
  10. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Modify/test_rule_utils.py +2 -1
  11. synkit-0.0.10/Test/Synthesis/Reactor/test_partial_engine.py +48 -0
  12. synkit-0.0.10/Test/Synthesis/Reactor/test_rbl_reactor.py +52 -0
  13. {synkit-0.0.8 → synkit-0.0.10}/doc/api.rst +6 -0
  14. synkit-0.0.10/doc/conf.py +49 -0
  15. synkit-0.0.10/doc/figures/context.png +0 -0
  16. {synkit-0.0.8 → synkit-0.0.10}/doc/getting_started.rst +1 -1
  17. {synkit-0.0.8 → synkit-0.0.10}/doc/graph.rst +44 -0
  18. {synkit-0.0.8 → synkit-0.0.10}/doc/index.rst +1 -0
  19. synkit-0.0.10/doc/requirements.txt +3 -0
  20. {synkit-0.0.8 → synkit-0.0.10}/pyproject.toml +6 -2
  21. synkit-0.0.10/synkit/Chem/Reaction/radical_wildcard.py +165 -0
  22. synkit-0.0.10/synkit/Data/gen_partial_aam.py +148 -0
  23. synkit-0.0.10/synkit/Graph/Canon/__init__.py +3 -0
  24. {synkit-0.0.8/synkit/Graph → synkit-0.0.10/synkit/Graph/Canon}/canon_graph.py +11 -2
  25. synkit-0.0.10/synkit/Graph/Canon/nauty.py +320 -0
  26. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Hyrogen/_misc.py +19 -2
  27. synkit-0.0.10/synkit/Graph/ITS/its_builder.py +114 -0
  28. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/ITS/its_construction.py +80 -71
  29. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/ITS/its_decompose.py +53 -20
  30. synkit-0.0.10/synkit/Graph/ITS/its_expand.py +84 -0
  31. synkit-0.0.10/synkit/Graph/ITS/its_relabel.py +191 -0
  32. synkit-0.0.10/synkit/Graph/Matcher/__init__.py +10 -0
  33. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Matcher/graph_morphism.py +100 -2
  34. synkit-0.0.10/synkit/Graph/Matcher/mcs_matcher.py +202 -0
  35. synkit-0.0.10/synkit/Graph/Matcher/multi_turbo_iso.py +178 -0
  36. synkit-0.0.10/synkit/Graph/Matcher/partial_matcher.py +214 -0
  37. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Matcher/turbo_iso.py +8 -5
  38. synkit-0.0.10/synkit/Graph/Wildcard/fuse_graph.py +158 -0
  39. synkit-0.0.10/synkit/Graph/__init__.py +16 -0
  40. synkit-0.0.10/synkit/Graph/canon_graph.py +538 -0
  41. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/chem_converter.py +23 -17
  42. synkit-0.0.10/synkit/Rule/Apply/rule_matcher.py +191 -0
  43. synkit-0.0.10/synkit/Synthesis/Reactor/batch_reactor.py +231 -0
  44. synkit-0.0.10/synkit/Synthesis/Reactor/partial_engine.py +71 -0
  45. synkit-0.0.10/synkit/Synthesis/Reactor/rbl_engine.py +123 -0
  46. synkit-0.0.10/synkit/Synthesis/Reactor/rule_filter.py +201 -0
  47. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/Reactor/strategy.py +2 -0
  48. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/Reactor/syn_reactor.py +63 -45
  49. synkit-0.0.10/synkit/Utils/__init__.py +0 -0
  50. synkit-0.0.10/synkit/__init__.py +0 -0
  51. synkit-0.0.8/doc/conf.py +0 -31
  52. synkit-0.0.8/synkit/Graph/ITS/its_builder.py +0 -94
  53. synkit-0.0.8/synkit/Graph/ITS/its_expand.py +0 -88
  54. synkit-0.0.8/synkit/Graph/Matcher/__init__.py +0 -10
  55. synkit-0.0.8/synkit/Graph/Matcher/mcs_matcher.py +0 -202
  56. synkit-0.0.8/synkit/Graph/__init__.py +0 -6
  57. synkit-0.0.8/synkit/Synthesis/Reactor/old_syn_reactor.py +0 -443
  58. {synkit-0.0.8 → synkit-0.0.10}/.github/workflows/build-doc.yml +0 -0
  59. {synkit-0.0.8 → synkit-0.0.10}/.github/workflows/publish-package.yml +0 -0
  60. {synkit-0.0.8 → synkit-0.0.10}/.github/workflows/test-and-lint.yml +0 -0
  61. {synkit-0.0.8 → synkit-0.0.10}/Data/Figure/synkit.png +0 -0
  62. {synkit-0.0.8 → synkit-0.0.10}/Data/Testcase/Compose/ComposeRule/data.txt +0 -0
  63. {synkit-0.0.8 → synkit-0.0.10}/Data/Testcase/Compose/SingleRule/R0/0.gml +0 -0
  64. {synkit-0.0.8 → synkit-0.0.10}/Data/Testcase/Compose/SingleRule/R0/1.gml +0 -0
  65. {synkit-0.0.8 → synkit-0.0.10}/Data/Testcase/Compose/SingleRule/R0/2.gml +0 -0
  66. {synkit-0.0.8 → synkit-0.0.10}/LICENSE +0 -0
  67. {synkit-0.0.8 → synkit-0.0.10}/Makefile +0 -0
  68. {synkit-0.0.8 → synkit-0.0.10}/README.md +0 -0
  69. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Fingerprint/__init__.py +0 -0
  70. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Fingerprint/test_fp_calculator.py +0 -0
  71. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Fingerprint/test_smiles_featurizer.py +0 -0
  72. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Fingerprint/test_transformation_fp.py +0 -0
  73. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Molecule/__init__.py +0 -0
  74. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Molecule/test_standardize.py +0 -0
  75. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/__init__.py +0 -0
  76. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_aam_utils.py +0 -0
  77. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_aam_validator.py +0 -0
  78. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_balance_checker.py +0 -0
  79. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_cleanning.py +0 -0
  80. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_deionize.py +0 -0
  81. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_fix_aam.py +0 -0
  82. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_neutralize.py +0 -0
  83. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_rsmi_utils.py +0 -0
  84. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_standardize.py +0 -0
  85. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/Reaction/test_tautomerize.py +0 -0
  86. {synkit-0.0.8 → synkit-0.0.10}/Test/Chem/__init__.py +0 -0
  87. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Context/__init__.py +0 -0
  88. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Context/test_hier_context.py +0 -0
  89. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Context/test_radius_expand.py +0 -0
  90. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Feature/__init__.py +0 -0
  91. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Feature/test_graph_descriptors.py +0 -0
  92. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Feature/test_graph_fps.py +0 -0
  93. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Feature/test_graph_signature.py +0 -0
  94. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Feature/test_hash_fps.py +0 -0
  95. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Feature/test_morgan_fps.py +0 -0
  96. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Feature/test_path_fps.py +0 -0
  97. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Hydrogen/__init__.py +0 -0
  98. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Hydrogen/test_graph_hydrogen.py +0 -0
  99. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Hydrogen/test_hcomplete.py +0 -0
  100. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Hydrogen/test_misc.py +0 -0
  101. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/ITS/__init__.py +0 -0
  102. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/ITS/test_its_construction.py +0 -0
  103. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/ITS/test_normalize_aam.py +0 -0
  104. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/MTG/__init__.py +0 -0
  105. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/MTG/test_group_comp.py +0 -0
  106. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/MTG/test_groupoid.py +0 -0
  107. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/MTG/test_mtg.py +0 -0
  108. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Matcher/__init__.py +0 -0
  109. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Matcher/test_batch_cluster.py +0 -0
  110. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Matcher/test_graph_cluster.py +0 -0
  111. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Matcher/test_graph_matcher.py +0 -0
  112. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Matcher/test_graph_morphism.py +0 -0
  113. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/Matcher/test_subgraph_matcher.py +0 -0
  114. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/__init__.py +0 -0
  115. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/test_canon_graph.py +0 -0
  116. {synkit-0.0.8 → synkit-0.0.10}/Test/Graph/test_syn_graph.py +0 -0
  117. {synkit-0.0.8 → synkit-0.0.10}/Test/IO/__init__.py +0 -0
  118. {synkit-0.0.8 → synkit-0.0.10}/Test/IO/test_chemical_converter.py +0 -0
  119. {synkit-0.0.8 → synkit-0.0.10}/Test/IO/test_dg_to_gml.py +0 -0
  120. {synkit-0.0.8 → synkit-0.0.10}/Test/IO/test_gml_to_nx.py +0 -0
  121. {synkit-0.0.8 → synkit-0.0.10}/Test/IO/test_graph_to_mol.py +0 -0
  122. {synkit-0.0.8 → synkit-0.0.10}/Test/IO/test_mol_to_graph.py +0 -0
  123. {synkit-0.0.8 → synkit-0.0.10}/Test/IO/test_nx_to_gml.py +0 -0
  124. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Apply/__init__.py +0 -0
  125. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Apply/test_reactor_rule.py +0 -0
  126. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Apply/test_retro_reactor.py +0 -0
  127. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Apply/test_rule_rbl.py +0 -0
  128. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Compose/__init__.py +0 -0
  129. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Compose/test_rule_compose.py +0 -0
  130. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Compose/test_valance_constrain.py +0 -0
  131. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/Modify/__init__.py +0 -0
  132. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/__init__.py +0 -0
  133. {synkit-0.0.8 → synkit-0.0.10}/Test/Rule/test_syn_rule.py +0 -0
  134. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/CRN/__init__.py +0 -0
  135. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/CRN/test_crn.py +0 -0
  136. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/CRN/test_mod_crn.py +0 -0
  137. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/MSR/__init__.py +0 -0
  138. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/MSR/test_multi_steps.py +0 -0
  139. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/MSR/test_path_finder.py +0 -0
  140. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/Reactor/__init__.py +0 -0
  141. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/Reactor/test_core_engine.py +0 -0
  142. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/Reactor/test_mod_aam.py +0 -0
  143. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/Reactor/test_mod_reactor.py +0 -0
  144. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/Reactor/test_strategy.py +0 -0
  145. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/__init__.py +0 -0
  146. {synkit-0.0.8 → synkit-0.0.10}/Test/Synthesis/test_reactor_utils.py +0 -0
  147. {synkit-0.0.8 → synkit-0.0.10}/Test/Vis/__init__.py +0 -0
  148. {synkit-0.0.8 → synkit-0.0.10}/Test/Vis/test_embedding.py +0 -0
  149. {synkit-0.0.8 → synkit-0.0.10}/Test/__init__.py +0 -0
  150. {synkit-0.0.8 → synkit-0.0.10}/build-doc.sh +0 -0
  151. {synkit-0.0.8 → synkit-0.0.10}/doc/changelog.rst +0 -0
  152. {synkit-0.0.8 → synkit-0.0.10}/doc/chem.rst +0 -0
  153. {synkit-0.0.8 → synkit-0.0.10}/doc/figures/aldol.png +0 -0
  154. {synkit-0.0.8 → synkit-0.0.10}/doc/figures/aldol_its.png +0 -0
  155. {synkit-0.0.8 → synkit-0.0.10}/doc/figures/mtg.png +0 -0
  156. {synkit-0.0.8 → synkit-0.0.10}/doc/io.rst +0 -0
  157. {synkit-0.0.8 → synkit-0.0.10}/doc/reference.rst +0 -0
  158. {synkit-0.0.8 → synkit-0.0.10}/doc/refs.bib +0 -0
  159. {synkit-0.0.8 → synkit-0.0.10}/doc/rule.rst +0 -0
  160. {synkit-0.0.8 → synkit-0.0.10}/doc/synthesis.rst +0 -0
  161. {synkit-0.0.8 → synkit-0.0.10}/environment.yml +0 -0
  162. {synkit-0.0.8 → synkit-0.0.10}/lint.sh +0 -0
  163. {synkit-0.0.8 → synkit-0.0.10}/make.bat +0 -0
  164. {synkit-0.0.8 → synkit-0.0.10}/pytest.sh +0 -0
  165. {synkit-0.0.8 → synkit-0.0.10}/requirements.txt +0 -0
  166. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Fingerprint/__init__.py +0 -0
  167. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
  168. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
  169. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
  170. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Molecule/__init__.py +0 -0
  171. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Molecule/standardize.py +0 -0
  172. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/__init__.py +0 -0
  173. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/aam_utils.py +0 -0
  174. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/aam_validator.py +0 -0
  175. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/balance_check.py +0 -0
  176. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/canon_rsmi.py +0 -0
  177. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/cleanning.py +0 -0
  178. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/deionize.py +0 -0
  179. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/fix_aam.py +0 -0
  180. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/neutralize.py +0 -0
  181. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/rsmi_utils.py +0 -0
  182. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/standardize.py +0 -0
  183. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/Reaction/tautomerize.py +0 -0
  184. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/__init__.py +0 -0
  185. {synkit-0.0.8 → synkit-0.0.10}/synkit/Chem/utils.py +0 -0
  186. {synkit-0.0.8/synkit/Graph/Context → synkit-0.0.10/synkit/Data}/__init__.py +0 -0
  187. {synkit-0.0.8/synkit/Graph → synkit-0.0.10/synkit/Graph/Canon}/canon_algs.py +0 -0
  188. {synkit-0.0.8/synkit/Graph/Hyrogen → synkit-0.0.10/synkit/Graph/Context}/__init__.py +0 -0
  189. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Context/hier_context.py +0 -0
  190. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Context/radius_expand.py +0 -0
  191. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Feature/__init__.py +0 -0
  192. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Feature/graph_descriptors.py +0 -0
  193. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Feature/graph_fps.py +0 -0
  194. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Feature/graph_signature.py +0 -0
  195. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Feature/hash_fps.py +0 -0
  196. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Feature/morgan_fps.py +0 -0
  197. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Feature/path_fps.py +0 -0
  198. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Feature/wl_hash.py +0 -0
  199. {synkit-0.0.8/synkit/Graph/MTG → synkit-0.0.10/synkit/Graph/Hyrogen}/__init__.py +0 -0
  200. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Hyrogen/hcomplete.py +0 -0
  201. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Hyrogen/hextend.py +0 -0
  202. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/ITS/__init__.py +0 -0
  203. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/ITS/normalize_aam.py +0 -0
  204. {synkit-0.0.8/synkit/Rule/Apply → synkit-0.0.10/synkit/Graph/MTG}/__init__.py +0 -0
  205. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/MTG/group_comp.py +0 -0
  206. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/MTG/groupoid.py +0 -0
  207. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/MTG/mcs_matcher.py +0 -0
  208. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/MTG/mtg.py +0 -0
  209. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Matcher/batch_cluster.py +0 -0
  210. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Matcher/graph_cluster.py +0 -0
  211. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Matcher/graph_matcher.py +0 -0
  212. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Matcher/sing.py +0 -0
  213. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/Matcher/subgraph_matcher.py +0 -0
  214. {synkit-0.0.8/synkit/Rule/Compose → synkit-0.0.10/synkit/Graph/Wildcard}/__init__.py +0 -0
  215. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/syn_graph.py +0 -0
  216. {synkit-0.0.8 → synkit-0.0.10}/synkit/Graph/utils.py +0 -0
  217. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/__init__.py +0 -0
  218. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/data_io.py +0 -0
  219. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/data_process.py +0 -0
  220. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/debug.py +0 -0
  221. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/dg_to_gml.py +0 -0
  222. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/gml_to_nx.py +0 -0
  223. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/graph_to_mol.py +0 -0
  224. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/mol_to_graph.py +0 -0
  225. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/nx_to_gml.py +0 -0
  226. {synkit-0.0.8 → synkit-0.0.10}/synkit/IO/smiles_to_id.py +0 -0
  227. {synkit-0.0.8/synkit/Rule/Modify → synkit-0.0.10/synkit/Rule/Apply}/__init__.py +0 -0
  228. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Apply/reactor_rule.py +0 -0
  229. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Apply/retro_reactor.py +0 -0
  230. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Apply/rule_rbl.py +0 -0
  231. {synkit-0.0.8/synkit/Synthesis/CRN → synkit-0.0.10/synkit/Rule/Compose}/__init__.py +0 -0
  232. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Compose/compose_rule.py +0 -0
  233. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Compose/rule_compose.py +0 -0
  234. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Compose/rule_mapping.py +0 -0
  235. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Compose/seq_comp.py +0 -0
  236. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Compose/valence_constrain.py +0 -0
  237. {synkit-0.0.8/synkit/Synthesis/MSR → synkit-0.0.10/synkit/Rule/Modify}/__init__.py +0 -0
  238. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Modify/implict_rule.py +0 -0
  239. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Modify/longest_path.py +0 -0
  240. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Modify/molecule_rule.py +0 -0
  241. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Modify/prune_templates.py +0 -0
  242. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Modify/rule_utils.py +0 -0
  243. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/Modify/strip_rule.py +0 -0
  244. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/__init__.py +0 -0
  245. {synkit-0.0.8 → synkit-0.0.10}/synkit/Rule/syn_rule.py +0 -0
  246. {synkit-0.0.8/synkit/Synthesis/Metrics → synkit-0.0.10/synkit/Synthesis/CRN}/__init__.py +0 -0
  247. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/CRN/crn.py +0 -0
  248. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/CRN/dcrn.py +0 -0
  249. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/CRN/mod_crn.py +0 -0
  250. {synkit-0.0.8/synkit/Synthesis/Reactor → synkit-0.0.10/synkit/Synthesis/MSR}/__init__.py +0 -0
  251. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/MSR/multi_steps.py +0 -0
  252. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/MSR/path_finder.py +0 -0
  253. {synkit-0.0.8/synkit/Synthesis → synkit-0.0.10/synkit/Synthesis/Metrics}/__init__.py +0 -0
  254. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/Metrics/_base.py +0 -0
  255. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/Metrics/_plot.py +0 -0
  256. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/Metrics/_ranking.py +0 -0
  257. {synkit-0.0.8/synkit/Utils → synkit-0.0.10/synkit/Synthesis/Reactor}/__init__.py +0 -0
  258. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/Reactor/core_engine.py +0 -0
  259. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/Reactor/mod_aam.py +0 -0
  260. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/Reactor/mod_reactor.py +0 -0
  261. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/Reactor/single_predictor.py +0 -0
  262. {synkit-0.0.8/synkit → synkit-0.0.10/synkit/Synthesis}/__init__.py +0 -0
  263. {synkit-0.0.8 → synkit-0.0.10}/synkit/Synthesis/reactor_utils.py +0 -0
  264. {synkit-0.0.8 → synkit-0.0.10}/synkit/Utils/utils.py +0 -0
  265. {synkit-0.0.8 → synkit-0.0.10}/synkit/Vis/__init__.py +0 -0
  266. {synkit-0.0.8 → synkit-0.0.10}/synkit/Vis/chemical_space.py +0 -0
  267. {synkit-0.0.8 → synkit-0.0.10}/synkit/Vis/embedding.py +0 -0
  268. {synkit-0.0.8 → synkit-0.0.10}/synkit/Vis/graph_visualizer.py +0 -0
  269. {synkit-0.0.8 → synkit-0.0.10}/synkit/Vis/pdf_writer.py +0 -0
  270. {synkit-0.0.8 → synkit-0.0.10}/synkit/Vis/rule_vis.py +0 -0
  271. {synkit-0.0.8 → synkit-0.0.10}/synkit/Vis/rxn_vis.py +0 -0
@@ -19,4 +19,5 @@ Data/Benchmark/*
19
19
  # *.png
20
20
  *.json.gz
21
21
  run.sh
22
- docs/*
22
+ docs/*
23
+ run_rdcanon.py
@@ -0,0 +1,24 @@
1
+ # Read the Docs configuration file
2
+ # https://docs.readthedocs.io/en/stable/config-file/v2.html
3
+
4
+ # 1) Tell RTD this is v2 of the schema
5
+ version: 2
6
+
7
+ # 2) Pick your build image and interpreter
8
+ build:
9
+ os: ubuntu-22.04
10
+ tools:
11
+ python: "3.11"
12
+
13
+ # 3) Install your package + any doc-only extras
14
+ python:
15
+ install:
16
+ - method: pip
17
+ path: .
18
+ extra_requirements:
19
+ - docs
20
+
21
+ # 4) Point Sphinx at your conf.py and choose HTML
22
+ sphinx:
23
+ configuration: doc/conf.py
24
+ builder: html
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synkit
3
- Version: 0.0.8
3
+ Version: 0.0.10
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
@@ -22,6 +22,10 @@ Requires-Dist: seaborn>=0.13.2
22
22
  Provides-Extra: all
23
23
  Requires-Dist: numpy>=2.2.0; extra == 'all'
24
24
  Requires-Dist: torch>=2.2.0; extra == 'all'
25
+ Provides-Extra: docs
26
+ Requires-Dist: sphinx-rtd-theme; extra == 'docs'
27
+ Requires-Dist: sphinx>=6.0; extra == 'docs'
28
+ Requires-Dist: sphinxcontrib-bibtex; extra == 'docs'
25
29
  Description-Content-Type: text/markdown
26
30
 
27
31
  # SynKit
@@ -7,7 +7,11 @@ from synkit.IO.chem_converter import rsmi_to_graph
7
7
  class TestCanonRSMI(unittest.TestCase):
8
8
  def setUp(self):
9
9
  # Use generic backend for deterministic behavior
10
- self.canon = CanonRSMI(backend="wl", wl_iterations=5)
10
+ self.canon = CanonRSMI(
11
+ backend="wl",
12
+ wl_iterations=5,
13
+ node_attrs=["element", "aromatic", "charge", "hcount", "neighbors"],
14
+ )
11
15
  # Example reaction SMILES with atom-map labels
12
16
  self.input_rsmi = "[CH3:3][CH2:5][OH:10]>>[CH2:3]=[CH2:5].[OH2:10]"
13
17
  # After expand_aam and canonicalisation, since backend is generic,
@@ -0,0 +1,51 @@
1
+ import unittest
2
+ from synkit.Chem.Reaction.radical_wildcard import RadicalWildcardAdder
3
+
4
+
5
+ class TestRadicalWildcardAdder(unittest.TestCase):
6
+ """
7
+ Unit tests for RadicalWildcardAdder using unittest.
8
+ """
9
+
10
+ def test_transform_given_rxn(self):
11
+ """
12
+ Ensure that transform() applies the wildcard_map correctly and preserves explicit H.
13
+ """
14
+ rxn_in = (
15
+ "[CH3:1][CH2:2][C:3](=[O:4])[OH:5]."
16
+ "[O:6][H:7]>>"
17
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:6]."
18
+ "[OH:5][H:7]"
19
+ )
20
+ adder = RadicalWildcardAdder()
21
+ result = adder.transform(rxn_in)
22
+
23
+ expected = (
24
+ "[CH3:1][CH2:2][C:3](=[O:4])[OH:5]."
25
+ "[O:6]([H:7])[*:8]>>"
26
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:6][*:8]."
27
+ "[OH:5][H:7]"
28
+ )
29
+ self.assertEqual(result, expected)
30
+
31
+ def test_auto_map_selection_and_repr_str(self):
32
+ """
33
+ Check that wildcard_map is auto-selected and repr/str methods report correctly.
34
+ """
35
+ rxn = (
36
+ "[CH3:1][CH2:2][C:3](=[O:4])[OH:5]."
37
+ "[O:6][H:7]>>"
38
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:6]."
39
+ "[OH:5][H:7]"
40
+ )
41
+ adder = RadicalWildcardAdder()
42
+ out = adder.transform(rxn)
43
+
44
+ # The output should contain exactly one [*:8] in reactants and one in products
45
+ reactants, products = out.split(">>")
46
+ self.assertEqual(reactants.count("[*:8]"), 1)
47
+ self.assertEqual(products.count("[*:8]"), 1)
48
+
49
+
50
+ if __name__ == "__main__":
51
+ unittest.main()
@@ -12,7 +12,15 @@ 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
+ self.assertTrue(AAMValidator.smiles_check(output_rsmi, expected_rsmi, "ITS"))
16
+
17
+ def test_expand_with_relabel(self):
18
+ input_rsmi = "CC[CH2:3][Cl:1].[NH2:2][H:4]>>CC[CH2:3][NH2:2].[Cl:1][H:4]"
19
+ output_rsmi = ITSExpand.expand_aam_with_its(input_rsmi, relabel=True)
20
+ expected_rsmi = (
21
+ "[CH3:1][CH2:2][CH2:3][Cl:4].[NH2:5][H:6]"
22
+ + ">>[CH3:1][CH2:2][CH2:3][NH2:5].[Cl:4][H:6]"
23
+ )
16
24
  self.assertTrue(AAMValidator.smiles_check(output_rsmi, expected_rsmi, "ITS"))
17
25
 
18
26
 
@@ -0,0 +1,61 @@
1
+ import unittest
2
+ from rdkit import Chem
3
+ from synkit.Graph.ITS.its_relabel import ITSRelabel
4
+ from synkit.Graph.syn_graph import SynGraph
5
+ from synkit.IO.chem_converter import smiles_to_graph
6
+
7
+
8
+ class TestITSRelabel(unittest.TestCase):
9
+ def setUp(self):
10
+ self.its = ITSRelabel()
11
+
12
+ def test_get_nodes_with_atom_map(self):
13
+ # Build a graph from SMILES with explicit atom mapping
14
+ raw = smiles_to_graph(
15
+ "[CH3:1][CH2:2][OH:3]", use_index_as_atom_map=True, drop_non_aam=False
16
+ )
17
+ sg = SynGraph(raw)
18
+ nodes = ITSRelabel._get_nodes_with_atom_map(sg)
19
+ # Every atom should have a non-zero atom_map
20
+ self.assertCountEqual(nodes, list(sg.raw.nodes()))
21
+
22
+ def test_remove_internal_edges(self):
23
+ # Linear 3‑carbon chain; after removing internal edges none remain
24
+ raw = smiles_to_graph("CCC", use_index_as_atom_map=True, drop_non_aam=False)
25
+ sg = SynGraph(raw)
26
+ all_nodes = list(sg.raw.nodes())
27
+ pruned = ITSRelabel._remove_internal_edges(sg, all_nodes)
28
+ self.assertEqual(pruned.raw.number_of_edges(), 0)
29
+
30
+ def test_dict_to_tuple_list_sorting(self):
31
+ mapping = {3: 1, 2: 2, 1: 3}
32
+ # Sort by key
33
+ by_key = ITSRelabel._dict_to_tuple_list(mapping, sort_by_key=True)
34
+ self.assertEqual(by_key, [(1, 3), (2, 2), (3, 1)])
35
+ # Sort by value
36
+ by_val = ITSRelabel._dict_to_tuple_list(mapping, sort_by_value=True)
37
+ self.assertEqual(by_val, [(3, 1), (2, 2), (1, 3)])
38
+ # No sorting
39
+ no_sort = ITSRelabel._dict_to_tuple_list(mapping)
40
+ self.assertCountEqual(no_sort, [(1, 3), (2, 2), (3, 1)])
41
+
42
+ def test_fit_simple_reaction(self):
43
+ # CCO to CC=O, mapping preserved
44
+ input_rsmi = "CC[CH2:3][Cl:1].[N:2]>>CC[CH2:3][N:2].[Cl:1]"
45
+ out = self.its.fit(input_rsmi)
46
+ react, prod = out.split(">>")
47
+ self.assertIsNotNone(Chem.MolFromSmiles(react))
48
+ self.assertIsNotNone(Chem.MolFromSmiles(prod))
49
+
50
+ def test_fit_invalid_format_raises(self):
51
+ with self.assertRaises(ValueError):
52
+ self.its.fit("invalid_format")
53
+
54
+ def test_fit_non_isomorphic_raises(self):
55
+ # Wrong reaction format
56
+ with self.assertRaises(ValueError):
57
+ self.its.fit("C:1>CC:1")
58
+
59
+
60
+ if __name__ == "__main__":
61
+ unittest.main()
@@ -0,0 +1,94 @@
1
+ import io
2
+ import unittest
3
+ from contextlib import redirect_stdout
4
+
5
+ import networkx as nx
6
+
7
+ from synkit.IO.chem_converter import rsmi_to_its
8
+ from synkit.Rule.Apply.rule_matcher import RuleMatcher
9
+ from synkit.Chem.Reaction.standardize import Standardize
10
+ from synkit.Chem.Reaction.aam_validator import AAMValidator
11
+ from synkit.Chem.Reaction.balance_check import BalanceReactionCheck
12
+
13
+
14
+ class TestRuleMatcher(unittest.TestCase):
15
+
16
+ def test_rule_match_balance(self):
17
+ """Balanced reaction should match directly and produce correct SMARTS."""
18
+ input_rsmi = "CC[CH2:3][Cl:1].[NH2:2][H:4]>>CC[CH2:3][NH2:2].[Cl:1][H:4]"
19
+ rule = rsmi_to_its(input_rsmi, core=True)
20
+ rsmi_std = Standardize().fit(input_rsmi)
21
+ expected_rsmi = (
22
+ "[CH3:1][CH2:2][CH2:3][Cl:4].[NH2:5][H:6]"
23
+ ">>[CH3:1][CH2:2][CH2:3][NH2:5].[Cl:4][H:6]"
24
+ )
25
+
26
+ matcher = RuleMatcher(rsmi_std, rule)
27
+ smarts, returned_rule = matcher.get_result()
28
+
29
+ # The returned SMARTS should regenerate the expected RSMI via AAMValidator
30
+ self.assertTrue(AAMValidator.smiles_check(smarts, expected_rsmi, "ITS"))
31
+ # The returned rule graph should be isomorphic to the input rule
32
+ self.assertTrue(nx.is_isomorphic(returned_rule, rule))
33
+
34
+ def test_rbl_missing_product(self):
35
+ """Partial (RBL) match when product fragments are missing in rule."""
36
+ rsmi = "CC(Br)C.CB(O)O>>CC(C)C"
37
+ template = "[CH3:1][Br:2].[BH2:3][CH3:4]>>[CH3:1][CH3:4].[BH2:3][Br:2]"
38
+ matcher = RuleMatcher(rsmi, template)
39
+ smarts, _ = matcher.get_result()
40
+ expect = "CB(O)O.CC(C)Br>>CC(C)C.OB(O)Br"
41
+ self.assertEqual(Standardize().fit(smarts), expect)
42
+
43
+ def test_rbl_missing_reactant(self):
44
+ """Partial (RBL) match when reactant fragments are missing in rule."""
45
+ rsmi = "CCC(=O)(O)>>CCC(=O)OC.O"
46
+ template = (
47
+ "[CH3:1][C:2](=[O:3])[OH:4].[CH3:5][O:6][H:7]"
48
+ ">>[CH3:1][C:2](=[O:3])[O:6][CH3:5].[H:7][OH:4]"
49
+ )
50
+ matcher = RuleMatcher(rsmi, template)
51
+ smarts, _ = matcher.get_result()
52
+ expect = "CCC(=O)O.CO>>CCC(=O)OC.O"
53
+ self.assertEqual(Standardize().fit(smarts), expect)
54
+
55
+ def test_no_match_raises(self):
56
+ """If no SMARTS reproduces the RSMI under the rule, a ValueError is raised."""
57
+ rsmi = "CCO>>CC=O"
58
+ # Use a completely unrelated template
59
+ bad_template = "[CH3:1][OH:2]>>[CH2:1]=O"
60
+ with self.assertRaises(ValueError):
61
+ RuleMatcher(rsmi, bad_template)
62
+
63
+ def test_str_and_repr(self):
64
+ """__str__ and __repr__ reflect the RSMI, balance status, and rule size."""
65
+ input_rsmi = "CC[CH2:3][Cl:1].[NH2:2][H:4]>>CC[CH2:3][NH2:2].[Cl:1][H:4]"
66
+ template = rsmi_to_its(input_rsmi, core=True)
67
+ rsmi = Standardize().fit(input_rsmi)
68
+ matcher = RuleMatcher(rsmi, template)
69
+ # str should mention balanced/unbalanced correctly
70
+ if BalanceReactionCheck(n_jobs=1).rsmi_balance_check(matcher.rsmi):
71
+ self.assertIn("(balanced)", str(matcher))
72
+ else:
73
+ self.assertIn("(unbalanced)", str(matcher))
74
+ # repr should include node/edge counts of the rule
75
+ rep = repr(matcher)
76
+ self.assertIn("RuleMatcher(rsmi=", rep)
77
+ self.assertIn("balanced=", rep)
78
+
79
+ def test_help_output(self):
80
+ """help() should print internal state and list candidate SMARTS patterns."""
81
+ input_rsmi = "CC[CH2:3][Cl:1].[NH2:2][H:4]>>CC[CH2:3][NH2:2].[Cl:1][H:4]"
82
+ template = rsmi_to_its(input_rsmi, core=True)
83
+ rsmi = Standardize().fit(input_rsmi)
84
+ matcher = RuleMatcher(rsmi, template)
85
+ buf = io.StringIO()
86
+ with redirect_stdout(buf):
87
+ matcher.help()
88
+ out = buf.getvalue()
89
+ self.assertIn("RuleMatcher for RSMI", out)
90
+ self.assertIn("Candidate SMARTS patterns:", out)
91
+
92
+
93
+ if __name__ == "__main__":
94
+ unittest.main()
@@ -1,6 +1,6 @@
1
1
  import unittest
2
2
  from synkit.Rule.Modify.molecule_rule import MoleculeRule
3
- from synkit.Graph.Matcher import GraphMatcherEngine
3
+ from synkit.Graph.Matcher.graph_matcher import GraphMatcherEngine
4
4
  import importlib
5
5
 
6
6
  MOD_AVAILABLE = importlib.util.find_spec("mod") is not None
@@ -7,7 +7,8 @@ from synkit.Rule.Modify.rule_utils import (
7
7
  strip_context,
8
8
  _increment_gml_ids,
9
9
  )
10
- from synkit.Graph.Matcher import GraphMatcherEngine, SubgraphMatch
10
+ from synkit.Graph.Matcher.graph_matcher import GraphMatcherEngine
11
+ from synkit.Graph.Matcher.subgraph_matcher import SubgraphMatch
11
12
  import importlib
12
13
 
13
14
  MOD_AVAILABLE = importlib.util.find_spec("mod") is not None
@@ -0,0 +1,48 @@
1
+ import unittest
2
+ from synkit.Synthesis.Reactor.partial_engine import PartialEngine
3
+
4
+
5
+ class TestPartialEngine(unittest.TestCase):
6
+ def test_forward_direction_example(self):
7
+ """
8
+ Example 1:
9
+ PartialEngine(smi='CCC(=O)OC',
10
+ template='[C:1][O:2].[O:3][H:4]>>[C:1][O:3].[O:2][H:4]')
11
+ .fit(invert=False)
12
+ should return the two forward wildcarded SMARTS.
13
+ """
14
+ smi = "CCC(=O)OC"
15
+ template = "[C:1][O:2].[O:3][H:4]>>[C:1][O:3].[O:2][H:4]"
16
+ engine = PartialEngine(smi, template)
17
+ result = engine.fit(invert=False)
18
+ expected = [
19
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:5][CH3:6].[OH:7][*:8]>>"
20
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:7][*:8].[OH:5][CH3:6]",
21
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:5][CH3:6].[OH:7][*:8]>>"
22
+ "[CH3:1][CH2:2][C:3](=[O:4])[OH:5].[CH3:6][O:7][*:8]",
23
+ ]
24
+ self.assertEqual(result, expected)
25
+
26
+ def test_backward_direction_example(self):
27
+ """
28
+ Example 2:
29
+ PartialEngine(smi='CCC(=O)OCC',
30
+ template='[C:1][O:2].[O:3][H:4]>>[C:1][O:3].[O:2][H:4]')
31
+ .fit(invert=True)
32
+ should return the two backward wildcarded SMARTS.
33
+ """
34
+ smi = "CCC(=O)OCC"
35
+ template = "[C:1][O:2].[O:3][H:4]>>[C:1][O:3].[O:2][H:4]"
36
+ engine = PartialEngine(smi, template)
37
+ result = engine.fit(invert=True)
38
+ expected = [
39
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:8][*:9].[OH:5][CH2:6][CH3:7]>>"
40
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:5][CH2:6][CH3:7].[OH:8][*:9]",
41
+ "[CH2:6]([CH3:7])[O:8][*:9].[CH3:1][CH2:2][C:3](=[O:4])[OH:5]>>"
42
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:5][CH2:6][CH3:7].[OH:8][*:9]",
43
+ ]
44
+ self.assertEqual(result, expected)
45
+
46
+
47
+ if __name__ == "__main__":
48
+ unittest.main()
@@ -0,0 +1,52 @@
1
+ import unittest
2
+ from synkit.IO import its_to_rsmi, rsmi_to_its
3
+ from synkit.Synthesis.Reactor.rbl_engine import RBLEngine
4
+
5
+
6
+ class TestRBLEngine(unittest.TestCase):
7
+ def test_example1(self):
8
+ # Example 1
9
+ rsmi = "CCC(=O)(O)>>CCC(=O)OC"
10
+ raw_template = (
11
+ "[CH3:1][C:2](=[O:3])[OH:4]."
12
+ "[CH3:5][O:6][H:7]>>"
13
+ "[CH3:1][C:2](=[O:3])[O:6][CH3:5]."
14
+ "[H:7][OH:4]"
15
+ )
16
+ its = rsmi_to_its(raw_template, core=True)
17
+ template = its_to_rsmi(its)
18
+
19
+ engine = RBLEngine(rsmi, template)
20
+ result = engine.fit()
21
+
22
+ expected = [
23
+ (
24
+ "[CH3:1][CH2:2][C:3](=[O:4])[OH:7]."
25
+ "[OH:5][CH3:6]>>"
26
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:5][CH3:6]."
27
+ "[OH2:7]"
28
+ )
29
+ ]
30
+ self.assertEqual(result, expected)
31
+
32
+ def test_example2(self):
33
+ # Example 2
34
+ rsmi = "CCC(=O)OC>>CCC(=O)OCC"
35
+ template = "[C:1][O:2].[O:3][H:4]>>[C:1][O:3].[O:2][H:4]"
36
+
37
+ engine = RBLEngine(rsmi, template)
38
+ result = engine.fit()
39
+
40
+ expected = [
41
+ (
42
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:8][CH3:9]."
43
+ "[OH:5][CH2:6][CH3:7]>>"
44
+ "[CH3:1][CH2:2][C:3](=[O:4])[O:5][CH2:6][CH3:7]."
45
+ "[OH:8][CH3:9]"
46
+ )
47
+ ]
48
+ self.assertEqual(result, expected)
49
+
50
+
51
+ if __name__ == "__main__":
52
+ unittest.main()
@@ -48,6 +48,7 @@ The `ITS` submodule provides tools for constructing, decomposing, and validating
48
48
 
49
49
  - **its_construction**: Functions for constructing an ITS graph.
50
50
  - **its_decompose**: Functions for decomposing an ITS graph and extracting reaction center.
51
+ - **its_expand**: Functions for expanding partial ITS graphs into full ITS graphs.
51
52
 
52
53
  .. automodule:: synkit.Graph.ITS.its_construction
53
54
  :members:
@@ -55,6 +56,11 @@ The `ITS` submodule provides tools for constructing, decomposing, and validating
55
56
  :show-inheritance:
56
57
 
57
58
  .. automodule:: synkit.Graph.ITS.its_decompose
59
+ :members: get_rc, its_decompose
60
+ :undoc-members:
61
+ :show-inheritance:
62
+
63
+ .. automodule:: synkit.Graph.ITS.its_expand
58
64
  :members:
59
65
  :undoc-members:
60
66
  :show-inheritance:
@@ -0,0 +1,49 @@
1
+ import os
2
+ import sys
3
+ from importlib.metadata import version as _get_version, PackageNotFoundError
4
+
5
+ # -- Path setup --------------------------------------------------------------
6
+ # Add project root to sys.path to import the package
7
+ sys.path.insert(0, os.path.abspath(".."))
8
+
9
+ # -- Project information -----------------------------------------------------
10
+ project = "synkit"
11
+ author = "Tieu-Long Phan"
12
+
13
+
14
+ try:
15
+ release = _get_version("synkit")
16
+ except PackageNotFoundError:
17
+ try:
18
+ import synkit
19
+
20
+ release = synkit.__version__
21
+ except (ImportError, AttributeError):
22
+ # Fallback default
23
+ release = "0.0.10"
24
+ # Use only major.minor for short version
25
+ version = ".".join(release.split(".")[:2])
26
+
27
+ # -- General configuration ---------------------------------------------------
28
+ extensions = [
29
+ "sphinx.ext.autodoc",
30
+ "sphinx.ext.autosectionlabel",
31
+ "sphinx.ext.githubpages",
32
+ "sphinxcontrib.bibtex",
33
+ # "sphinx.ext.napoleon", # un-comment if using Google/NumPy docstrings
34
+ ]
35
+
36
+ bibtex_bibfiles = ["refs.bib"]
37
+ templates_path = ["_templates"]
38
+ exclude_patterns = []
39
+ autosectionlabel_prefix_document = True
40
+
41
+ autodoc_default_options = {
42
+ "members": True,
43
+ "undoc-members": True,
44
+ "show-inheritance": True,
45
+ }
46
+
47
+ # -- Options for HTML output -------------------------------------------------
48
+ html_theme = "sphinx_rtd_theme"
49
+ html_static_path = ["_static"]
Binary file
@@ -66,7 +66,7 @@ After installation, verify that **synkit** is available and check its version:
66
66
 
67
67
  .. code-block:: bash
68
68
 
69
- python -c "import synkit; print(synkit.__version__)"
69
+ python -c "import importlib.metadata as m; print(m.version('synkit'))"
70
70
  # Should print the installed synkit version
71
71
 
72
72
  Further Resources
@@ -254,6 +254,50 @@ This example builds two reaction-center ITS graphs, computes their MCS mapping,
254
254
  (C) Composite ITS graph "gluing" both transformations
255
255
  (D) Mechanistic Transition Graph (MTG) showing step-wise mechanism
256
256
 
257
+ Context graph
258
+ -------------
259
+
260
+ The ``synkit.Graph.Context`` submodule provides tools for expanding reaction center graphs to include nearest neighbors, enabling context‑aware analysis of reaction networks.
261
+
262
+ .. code-block:: python
263
+ :caption: Context graph expansion example
264
+ :linenos:
265
+
266
+ from synkit.IO import rsmi_to_its
267
+ from synkit.Graph.Context.radius_expand import RadiusExpand
268
+ from synkit.Vis.graph_visualizer import GraphVisualizer
269
+
270
+ smart = (
271
+ '[CH3:1][O:2][C:3](=[O:4])[CH:5]([CH2:6][CH2:7][CH2:8][CH2:9]'
272
+ '[NH:10][C:11](=[O:12])[O:13][CH2:14][c:15]1[cH:16][cH:17]'
273
+ '[cH:18][cH:19][cH:20]1)[NH:21][C:22](=[O:23])[NH:24][c:25]1'
274
+ '[cH:26][c:27]([O:28][CH3:29])[cH:30][c:31]([C:32]([CH3:33])'
275
+ '([CH3:34])[CH3:35])[c:36]1[OH:37].[OH:38][H:39]>>'
276
+ '[C:11](=[O:12])([O:13][CH2:14][c:15]1[cH:16][cH:17][cH:18]'
277
+ '[cH:19][cH:20]1)[OH:38].[CH3:1][O:2][C:3](=[O:4])[CH:5]'
278
+ '([CH2:6][CH2:7][CH2:8][CH2:9][NH:10][H:39])[NH:21][C:22]'
279
+ '(=[O:23])[NH:24][c:25]1[cH:26][c:27]([O:28][CH3:29])[cH:30]'
280
+ '[c:31]([C:32]([CH3:33])([CH3:34])[CH3:35])[c:36]1[OH:37]'
281
+ )
282
+ its = rsmi_to_its(smart)
283
+ rc = rsmi_to_its(smart, core=True)
284
+ exp = RadiusExpand()
285
+ k1 = exp.extract_k(its, n_knn=1)
286
+
287
+ gv = GraphVisualizer()
288
+ gv.visualize_its_grid([rc, k1])
289
+
290
+ .. container:: figure
291
+
292
+ .. image:: ./figures/context.png
293
+ :alt: Context graph expansion example
294
+ :align: center
295
+ :width: 1000px
296
+
297
+ *Figure:*
298
+ (A) Minimal reaction center subgraph obtained by contracting all atoms that participate directly in bond‑order changes.
299
+ Nodes are colour‑coded by element; edges in **red** indicate bonds being broken, while edges in **blue** mark bonds being formed.
300
+ (B) First shell ($k=1$) context expansion: every reaction center atom is augmented with all of its immediate neighbours.
257
301
 
258
302
 
259
303
  See Also
@@ -1,5 +1,6 @@
1
1
  Welcome to synkit documentation!
2
2
  ================================
3
+ This is documentation for synkit version |version| (release |release|).
3
4
 
4
5
  .. toctree::
5
6
  :caption: Contents
@@ -0,0 +1,3 @@
1
+ sphinx
2
+ sphinx-rtd-theme
3
+ sphinxcontrib-bibtex
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "synkit"
7
- version = "0.0.8"
7
+ version = "0.0.10"
8
8
  authors = [
9
9
  {name="Tieu Long Phan", email="tieu@bioinf.uni-leipzig.de"}
10
10
  ]
@@ -30,7 +30,11 @@ dependencies = [
30
30
 
31
31
  [project.optional-dependencies]
32
32
  all = ["numpy>=2.2.0", "torch>=2.2.0"]
33
-
33
+ docs = [
34
+ "sphinx>=6.0",
35
+ "sphinx-rtd-theme",
36
+ "sphinxcontrib-bibtex",
37
+ ]
34
38
  [project.urls]
35
39
  homepage = "https://github.com/TieuLongPhan/SynKit"
36
40
  source = "https://github.com/TieuLongPhan/SynKit"