synkit 1.4.0__tar.gz → 1.4.2b1__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 (330) hide show
  1. {synkit-1.4.0 → synkit-1.4.2b1}/.gitignore +3 -0
  2. {synkit-1.4.0 → synkit-1.4.2b1}/PKG-INFO +1 -1
  3. {synkit-1.4.0 → synkit-1.4.2b1}/pyproject.toml +1 -1
  4. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/__init__.py +70 -0
  5. {synkit-1.4.0/synkit/Chem/Reaction → synkit-1.4.2b1/synkit/Chem/Reaction/Mapper}/aam_validator.py +145 -13
  6. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/chem/__init__.py +46 -0
  7. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/chem/aam.py +439 -0
  8. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/chem/its.py +319 -0
  9. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/chem/smiles.py +524 -0
  10. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/__init__.py +58 -0
  11. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/branching.py +521 -0
  12. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/certificate.py +136 -0
  13. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/enumerate.py +1079 -0
  14. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/exhaustive.py +209 -0
  15. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/kernel.py +268 -0
  16. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/milp.py +193 -0
  17. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/__init__.py +60 -0
  18. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/automorphism.py +113 -0
  19. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/blockcut.py +104 -0
  20. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/labeled_graph.py +104 -0
  21. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/refine.py +186 -0
  22. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/synkit_adapter.py +110 -0
  23. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/io/__init__.py +13 -0
  24. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/io/idxmapstr.py +87 -0
  25. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/slap/__init__.py +22 -0
  26. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/slap/lap.py +185 -0
  27. synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/slap/sequential.py +691 -0
  28. synkit-1.4.2b1/synkit/Chem/Reaction/__init__.py +6 -0
  29. synkit-1.4.2b1/synkit/Chem/Reaction/aam_validator.py +5 -0
  30. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/tautomerize.py +4 -1
  31. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Hyrogen/_misc.py +22 -10
  32. synkit-1.4.2b1/synkit/Graph/Hyrogen/hcomplete.py +1014 -0
  33. synkit-1.4.2b1/synkit/Graph/Hyrogen/hextend.py +305 -0
  34. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_construction.py +2 -2
  35. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_expand.py +55 -48
  36. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/approx_mcs.py +95 -1075
  37. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/mcs_matcher.py +72 -1
  38. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/subgraph_matcher.py +4 -0
  39. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/wl_sel.py +1 -1
  40. synkit-1.4.2b1/synkit/Graph/Mech/__init__.py +26 -0
  41. synkit-1.4.2b1/synkit/Graph/Mech/electron_accounting.py +309 -0
  42. synkit-1.4.2b1/synkit/Graph/Mech/lwg_editor.py +403 -0
  43. synkit-1.4.2b1/synkit/Graph/Mech/lwg_ops.py +313 -0
  44. synkit-1.4.2b1/synkit/Graph/Wildcard/its_merge.py +869 -0
  45. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/chem_converter.py +21 -13
  46. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/rbl_engine.py +876 -234
  47. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/syn_reactor.py +23 -4
  48. synkit-1.4.2b1/synkit/Vis/__init__.py +89 -0
  49. synkit-1.4.2b1/synkit/Vis/crn/__init__.py +5 -0
  50. synkit-1.4.0/synkit/Vis/crn_vis.py → synkit-1.4.2b1/synkit/Vis/crn/visualizer.py +8 -2
  51. synkit-1.4.2b1/synkit/Vis/epd/__init__.py +20 -0
  52. synkit-1.4.2b1/synkit/Vis/epd/arrows.py +425 -0
  53. synkit-1.4.2b1/synkit/Vis/epd/chem.py +197 -0
  54. synkit-1.4.2b1/synkit/Vis/epd/constants.py +83 -0
  55. synkit-1.4.2b1/synkit/Vis/epd/layout.py +283 -0
  56. synkit-1.4.2b1/synkit/Vis/epd/mapping.py +51 -0
  57. synkit-1.4.2b1/synkit/Vis/epd/models.py +107 -0
  58. synkit-1.4.2b1/synkit/Vis/epd/render.py +528 -0
  59. synkit-1.4.2b1/synkit/Vis/epd/utils.py +108 -0
  60. synkit-1.4.2b1/synkit/Vis/epd/visualizer.py +826 -0
  61. synkit-1.4.2b1/synkit/Vis/its/__init__.py +19 -0
  62. synkit-1.4.0/synkit/Vis/its_drawer.py → synkit-1.4.2b1/synkit/Vis/its/drawer.py +3 -3
  63. synkit-1.4.2b1/synkit/Vis/molecule/__init__.py +31 -0
  64. synkit-1.4.0/synkit/Vis/reaction_drawer.py → synkit-1.4.2b1/synkit/Vis/molecule/reaction.py +1 -1
  65. synkit-1.4.2b1/synkit/Vis/mtg/__init__.py +17 -0
  66. synkit-1.4.0/synkit/Vis/mtg_drawer.py → synkit-1.4.2b1/synkit/Vis/mtg/drawer.py +1 -1
  67. synkit-1.4.2b1/synkit/Vis/reaction/__init__.py +19 -0
  68. synkit-1.4.0/synkit/Vis/rxn_vis.py → synkit-1.4.2b1/synkit/Vis/reaction/rxn.py +1 -1
  69. synkit-1.4.2b1/synkit/Vis/space/__init__.py +17 -0
  70. synkit-1.4.0/synkit/Vis/chemical_space.py → synkit-1.4.2b1/synkit/Vis/space/chemical.py +0 -3
  71. synkit-1.4.0/synkit/Chem/Reaction/Mapper/__init__.py +0 -8
  72. synkit-1.4.0/synkit/Chem/Reaction/Mapper/wl_mapper.py +0 -2345
  73. synkit-1.4.0/synkit/Chem/Reaction/__init__.py +0 -9
  74. synkit-1.4.0/synkit/Graph/Hyrogen/hcomplete.py +0 -353
  75. synkit-1.4.0/synkit/Graph/Hyrogen/hextend.py +0 -166
  76. synkit-1.4.0/synkit/Graph/Mech/electron_accounting.py +0 -64
  77. synkit-1.4.0/synkit/Graph/Wildcard/its_merge.py +0 -540
  78. synkit-1.4.0/synkit/Utils/__init__.py +0 -0
  79. synkit-1.4.0/synkit/Vis/__init__.py +0 -50
  80. synkit-1.4.0/synkit/Vis/vis_synedu/Vis/__init__.py +0 -7
  81. synkit-1.4.0/synkit/Vis/vis_synedu/Vis/dpo.py +0 -862
  82. synkit-1.4.0/synkit/Vis/vis_synedu/rxn_vis.py +0 -382
  83. synkit-1.4.0/synkit/Vis/vis_synedu/vis.py +0 -501
  84. {synkit-1.4.0 → synkit-1.4.2b1}/LICENSE +0 -0
  85. {synkit-1.4.0 → synkit-1.4.2b1}/README.md +0 -0
  86. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/DAG/__init__.py +0 -0
  87. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/DAG/crn.py +0 -0
  88. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/DAG/mod_crn.py +0 -0
  89. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/DAG/syncrn.py +0 -0
  90. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/__init__.py +0 -0
  91. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/abstract.py +0 -0
  92. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/arity.py +0 -0
  93. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/builder.py +0 -0
  94. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/derivation.py +0 -0
  95. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/flattener.py +0 -0
  96. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/keys.py +0 -0
  97. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/mixtures.py +0 -0
  98. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/smiles.py +0 -0
  99. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/state.py +0 -0
  100. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/strategy.py +0 -0
  101. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/worker.py +0 -0
  102. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/__init__.py +0 -0
  103. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/_adapter.py +0 -0
  104. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/pathfinder.py +0 -0
  105. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/reachability.py +0 -0
  106. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/realizability.py +0 -0
  107. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/__init__.py +0 -0
  108. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/analyzer.py +0 -0
  109. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/net.py +0 -0
  110. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/persistence.py +0 -0
  111. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/semiflows.py +0 -0
  112. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/structure.py +0 -0
  113. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/__init__.py +0 -0
  114. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/dynamics.py +0 -0
  115. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/helper.py +0 -0
  116. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/stoich.py +0 -0
  117. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/thermo.py +0 -0
  118. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/__init__.py +0 -0
  119. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/kegg_api.py +0 -0
  120. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/kegg_extract.py +0 -0
  121. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/kegg_impute.py +0 -0
  122. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/kegg_parse.py +0 -0
  123. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/__init__.py +0 -0
  124. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/reaction.py +0 -0
  125. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/rule.py +0 -0
  126. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/species.py +0 -0
  127. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/syncrn.py +0 -0
  128. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/__init__.py +0 -0
  129. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/_common.py +0 -0
  130. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/_ir.py +0 -0
  131. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/automorphism.py +0 -0
  132. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/canon.py +0 -0
  133. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/isomorphism.py +0 -0
  134. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/symmetry.py +0 -0
  135. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/wl_canon.py +0 -0
  136. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/__init__.py +0 -0
  137. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/crn_vis.py +0 -0
  138. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/labels.py +0 -0
  139. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/layout.py +0 -0
  140. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/palette.py +0 -0
  141. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/validation.py +0 -0
  142. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/vis.py +0 -0
  143. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/__init__.py +0 -0
  144. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/__init__.py +0 -0
  145. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/backend.py +0 -0
  146. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/conversion.py +0 -0
  147. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/hyperedge.py +0 -0
  148. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/hypergraph.py +0 -0
  149. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/rxn.py +0 -0
  150. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Symmetry/__init__.py +0 -0
  151. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Symmetry/automorphism.py +0 -0
  152. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Symmetry/canon.py +0 -0
  153. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Symmetry/wl_canon.py +0 -0
  154. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/__init__.py +0 -0
  155. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/configs/__init__.py +0 -0
  156. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/configs/loader.py +0 -0
  157. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/configs/models.py +0 -0
  158. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/constants.py +0 -0
  159. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/crn_formula.py +0 -0
  160. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/deficiency.py +0 -0
  161. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/enumerator.py +0 -0
  162. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/exceptions.py +0 -0
  163. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/explorer.py +0 -0
  164. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/helpers.py +0 -0
  165. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/injectivity.py +0 -0
  166. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/motif.py +0 -0
  167. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/network.py +0 -0
  168. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/pathway.py +0 -0
  169. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/properties.py +0 -0
  170. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/reaction.py +0 -0
  171. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/utils.py +0 -0
  172. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/viz.py +0 -0
  173. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Cluster/__init__.py +0 -0
  174. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Cluster/butina.py +0 -0
  175. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Fingerprint/__init__.py +0 -0
  176. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
  177. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
  178. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
  179. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/__init__.py +0 -0
  180. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/atom_features.py +0 -0
  181. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/descriptors.py +0 -0
  182. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/formula.py +0 -0
  183. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/graph_annotator.py +0 -0
  184. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/standardize.py +0 -0
  185. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/valence.py +0 -0
  186. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/balance_check.py +0 -0
  187. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/canon_rsmi.py +0 -0
  188. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/cleaning.py +0 -0
  189. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/deionize.py +0 -0
  190. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/fix_aam.py +0 -0
  191. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/neutralize.py +0 -0
  192. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/radical_wildcard.py +0 -0
  193. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/standardize.py +0 -0
  194. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/__init__.py +0 -0
  195. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/utils.py +0 -0
  196. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Data/__init__.py +0 -0
  197. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Data/gen_partial_aam.py +0 -0
  198. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Canon/__init__.py +0 -0
  199. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Canon/canon_algs.py +0 -0
  200. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Canon/canon_graph.py +0 -0
  201. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Canon/nauty.py +0 -0
  202. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Context/__init__.py +0 -0
  203. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Context/hier_context.py +0 -0
  204. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Context/radius_expand.py +0 -0
  205. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/__init__.py +0 -0
  206. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/api.py +0 -0
  207. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/audit.py +0 -0
  208. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/catalog.py +0 -0
  209. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/detector.py +0 -0
  210. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/model.py +0 -0
  211. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/ring_system.py +0 -0
  212. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/Descriptors/topology.py +0 -0
  213. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
  214. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +0 -0
  215. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/__init__.py +0 -0
  216. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/graph_descriptors.py +0 -0
  217. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/graph_fps.py +0 -0
  218. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/graph_signature.py +0 -0
  219. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/hash_fps.py +0 -0
  220. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/morgan_fps.py +0 -0
  221. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/path_fps.py +0 -0
  222. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/wl_hash.py +0 -0
  223. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Hyrogen/__init__.py +0 -0
  224. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/__init__.py +0 -0
  225. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_builder.py +0 -0
  226. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_decompose.py +0 -0
  227. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_destruction.py +0 -0
  228. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_relabel.py +0 -0
  229. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_reverter.py +0 -0
  230. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/normalize_aam.py +0 -0
  231. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/partial_its.py +0 -0
  232. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/rc_extractor.py +0 -0
  233. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/__init__.py +0 -0
  234. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/mcs_matcher.py +0 -0
  235. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/mtg.py +0 -0
  236. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/mtg_explore.py +0 -0
  237. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/utils.py +0 -0
  238. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/__init__.py +0 -0
  239. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/auto_est.py +0 -0
  240. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/automorphism.py +0 -0
  241. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/batch_cluster.py +0 -0
  242. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/dedup_matches.py +0 -0
  243. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/graph_cluster.py +0 -0
  244. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/graph_matcher.py +0 -0
  245. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/graph_morphism.py +0 -0
  246. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/multi_turbo_iso.py +0 -0
  247. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/orbit.py +0 -0
  248. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/partial_matcher.py +0 -0
  249. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/sing.py +0 -0
  250. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/turbo_iso.py +0 -0
  251. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Mech/conversion.py +0 -0
  252. {synkit-1.4.0/synkit/Graph/Mech → synkit-1.4.2b1/synkit/Graph/Wildcard}/__init__.py +0 -0
  253. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/fuse_graph.py +0 -0
  254. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/graph_wc.py +0 -0
  255. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/radwc.py +0 -0
  256. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/wc_matcher.py +0 -0
  257. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/wildcard.py +0 -0
  258. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/__init__.py +0 -0
  259. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/canon_graph.py +0 -0
  260. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/syn_graph.py +0 -0
  261. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/utils.py +0 -0
  262. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/__init__.py +0 -0
  263. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/__init__.py +0 -0
  264. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/gml_to_graph.py +0 -0
  265. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/graph_to_gml.py +0 -0
  266. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/graph_to_smarts.py +0 -0
  267. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/smarts_expander.py +0 -0
  268. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/smarts_generalizer.py +0 -0
  269. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/smarts_to_graph.py +0 -0
  270. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/data_io.py +0 -0
  271. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/data_process.py +0 -0
  272. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/debug.py +0 -0
  273. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/dg_to_gml.py +0 -0
  274. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/gml_to_nx.py +0 -0
  275. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/graph_to_mol.py +0 -0
  276. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/mol_to_graph.py +0 -0
  277. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/nx_to_gml.py +0 -0
  278. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/smiles_to_id.py +0 -0
  279. {synkit-1.4.0/synkit/Graph/Wildcard → synkit-1.4.2b1/synkit/Rule/Apply}/__init__.py +0 -0
  280. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Apply/reactor_rule.py +0 -0
  281. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Apply/retro_reactor.py +0 -0
  282. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Apply/rule_matcher.py +0 -0
  283. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Apply/rule_rbl.py +0 -0
  284. {synkit-1.4.0/synkit/Rule/Apply → synkit-1.4.2b1/synkit/Rule/Compose}/__init__.py +0 -0
  285. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/compose_rule.py +0 -0
  286. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/rule_compose.py +0 -0
  287. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/rule_mapping.py +0 -0
  288. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/seq_comp.py +0 -0
  289. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/valence_constrain.py +0 -0
  290. {synkit-1.4.0/synkit/Rule/Compose → synkit-1.4.2b1/synkit/Rule/Modify}/__init__.py +0 -0
  291. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/implict_rule.py +0 -0
  292. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/longest_path.py +0 -0
  293. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/molecule_rule.py +0 -0
  294. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/prune_templates.py +0 -0
  295. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/rule_utils.py +0 -0
  296. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/strip_rule.py +0 -0
  297. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/__init__.py +0 -0
  298. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/syn_rule.py +0 -0
  299. {synkit-1.4.0/synkit/Rule/Modify → synkit-1.4.2b1/synkit/Synthesis/MSR}/__init__.py +0 -0
  300. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/MSR/multi_steps.py +0 -0
  301. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/MSR/path_finder.py +0 -0
  302. {synkit-1.4.0/synkit/Synthesis/MSR → synkit-1.4.2b1/synkit/Synthesis/Metrics}/__init__.py +0 -0
  303. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Metrics/_base.py +0 -0
  304. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Metrics/_plot.py +0 -0
  305. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Metrics/_ranking.py +0 -0
  306. {synkit-1.4.0/synkit/Synthesis/Metrics → synkit-1.4.2b1/synkit/Synthesis/Reactor}/__init__.py +0 -0
  307. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/batch_reactor.py +0 -0
  308. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/benchmark.py +0 -0
  309. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/imba_engine.py +0 -0
  310. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/mod_aam.py +0 -0
  311. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/mod_reactor.py +0 -0
  312. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/partial_engine.py +0 -0
  313. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/post_syn.py +0 -0
  314. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/rule_filter.py +0 -0
  315. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/single_predictor.py +0 -0
  316. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/strategy.py +0 -0
  317. {synkit-1.4.0/synkit/Synthesis/Reactor → synkit-1.4.2b1/synkit/Synthesis}/__init__.py +0 -0
  318. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/reactor_utils.py +0 -0
  319. {synkit-1.4.0/synkit/Synthesis → synkit-1.4.2b1/synkit/Utils}/__init__.py +0 -0
  320. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Utils/utils.py +0 -0
  321. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Vis/graph_visualizer.py +0 -0
  322. /synkit-1.4.0/synkit/Vis/molecule_drawer.py → /synkit-1.4.2b1/synkit/Vis/molecule/drawer.py +0 -0
  323. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Vis/pdf_writer.py +0 -0
  324. /synkit-1.4.0/synkit/Vis/rule_vis.py → /synkit-1.4.2b1/synkit/Vis/reaction/rule.py +0 -0
  325. {synkit-1.4.0/synkit/Vis → synkit-1.4.2b1/synkit/Vis/space}/embedding.py +0 -0
  326. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Vis/visual_drawer.py +0 -0
  327. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Vis/visual_model.py +0 -0
  328. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/__init__.py +0 -0
  329. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/examples.py +0 -0
  330. {synkit-1.4.0 → synkit-1.4.2b1}/synkit/version.py +0 -0
@@ -37,3 +37,6 @@ test_syn.py
37
37
  .gitignore
38
38
  measure_candidate_stages.py
39
39
  run_valid_bug_cases.py
40
+ debug/*
41
+ diag_postproc.py
42
+ diag_nofused.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synkit
3
- Version: 1.4.0
3
+ Version: 1.4.2b1
4
4
  Summary: Utility for reaction modeling using graph grammar
5
5
  Project-URL: homepage, https://github.com/TieuLongPhan/SynKit
6
6
  Project-URL: source, https://github.com/TieuLongPhan/SynKit
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "synkit"
7
- version = "1.4.0"
7
+ version = "1.4.2b1"
8
8
  description = "Utility for reaction modeling using graph grammar"
9
9
  readme = "README.md"
10
10
  long-description = { file = "CHANGELOG.md" }
@@ -0,0 +1,70 @@
1
+ """
2
+ synkit.Chem.Reaction.Mapper
3
+ ===========================
4
+
5
+ An atom-to-atom mapping (AAM) toolkit built on Weisfeiler-Lehman label
6
+ refinement coupled with sequential linear assignment problems (SLAP). The
7
+ approximate SLAP result can be refined into a *certified* optimum on the
8
+ ambiguous reaction-center kernel using the
9
+ :mod:`synkit.Chem.Reaction.Mapper.exact` solvers.
10
+
11
+ Research basis
12
+ --------------
13
+ This enhanced mapper develops the SLAP mapping idea from:
14
+ Shin-ichi Koda and Shinji Saito, "General and scalable atom-to-atom mapping
15
+ via Weisfeiler-Lehman-like approximate graph matching", ChemRxiv (2025).
16
+ DOI: 10.26434/chemrxiv-2025-hthwn
17
+
18
+ Quick start
19
+ -----------
20
+ >>> from synkit.Chem.Reaction.Mapper import AAMapper, AAMValidator
21
+ >>> m = AAMapper(binary=True)
22
+ >>> m.map_smiles("CC(=O)O.OC>>CC(=O)OC")
23
+ >>> print(m.results[0]["smiles"])
24
+ >>> validator = AAMValidator()
25
+
26
+ Package layout
27
+ --------------
28
+ :mod:`synkit.Chem.Reaction.Mapper.graph`
29
+ Labeled-graph data structure, WL/2-WL refinement, automorphisms,
30
+ block-cut-tree decomposition.
31
+ :mod:`synkit.Chem.Reaction.Mapper.slap`
32
+ Sequential-LAP engine (:class:`GraphMatcher`) and LAP utilities
33
+ (chemical distance, Gilmore-Lawler lower bound).
34
+ :mod:`synkit.Chem.Reaction.Mapper.exact`
35
+ Kernelization, MILP/QAP solver, orbital-branching solver, exhaustive
36
+ DFS mapper, symmetry-distinct enumeration, and optimality certificates.
37
+ :mod:`synkit.Chem.Reaction.Mapper.chem`
38
+ RDKit SMILES I/O and ITS-based deduplication / electron-balance checks.
39
+ :mod:`synkit.Chem.Reaction.Mapper.io`
40
+ Index-mapping-string helpers.
41
+ :mod:`synkit.Chem.Reaction.Mapper.aam_validator`
42
+ AAM validation against ground-truth mapped reaction SMILES.
43
+
44
+ Public API
45
+ ----------
46
+ """
47
+
48
+ from .graph.labeled_graph import LabeledGraph
49
+ from .slap.sequential import GraphMatcher
50
+ from .chem.aam import AAMapper
51
+ from .aam_validator import AAMValidator
52
+
53
+ RESEARCH_BASIS_TITLE = (
54
+ "General and scalable atom-to-atom mapping via "
55
+ "Weisfeiler-Lehman-like approximate graph matching"
56
+ )
57
+ RESEARCH_BASIS_DOI = "10.26434/chemrxiv-2025-hthwn"
58
+ RESEARCH_BASIS_URL = f"https://doi.org/{RESEARCH_BASIS_DOI}"
59
+ RESEARCH_BASIS_AUTHORS = "Shin-ichi Koda and Shinji Saito"
60
+
61
+ __all__ = [
62
+ "LabeledGraph",
63
+ "GraphMatcher",
64
+ "AAMapper",
65
+ "AAMValidator",
66
+ "RESEARCH_BASIS_TITLE",
67
+ "RESEARCH_BASIS_DOI",
68
+ "RESEARCH_BASIS_URL",
69
+ "RESEARCH_BASIS_AUTHORS",
70
+ ]
@@ -2,6 +2,7 @@ import pandas as pd
2
2
  import networkx as nx
3
3
  from operator import eq
4
4
  from itertools import combinations
5
+ from functools import wraps
5
6
  from joblib import Parallel, delayed
6
7
  from typing import Dict, List, Tuple, Union, Optional
7
8
  from networkx.algorithms.isomorphism import generic_node_match, generic_edge_match
@@ -12,6 +13,21 @@ from synkit.Graph.ITS.its_construction import ITSConstruction
12
13
  from synkit.Chem.utils import enumerate_tautomers, mapping_success_rate
13
14
 
14
15
 
16
+ class _DualMethod:
17
+ """Bind a method to either an instance or the class."""
18
+
19
+ def __init__(self, func):
20
+ self.func = func
21
+ wraps(func)(self)
22
+
23
+ def __get__(self, obj, cls=None):
24
+ @wraps(self.func)
25
+ def wrapper(*args, **kwargs):
26
+ return self.func(obj, cls, *args, **kwargs)
27
+
28
+ return wrapper
29
+
30
+
15
31
  class AAMValidator:
16
32
  """A utility class for validating atom‐atom mappings (AAM) in reaction
17
33
  SMILES.
@@ -22,7 +38,7 @@ class AAMValidator:
22
38
 
23
39
  Quick start
24
40
  -----------
25
- >>> from synkit.Chem.Reaction import AAMValidator
41
+ >>> from synkit.Chem.Reaction.Mapper import AAMValidator
26
42
  >>> validator = AAMValidator()
27
43
  >>> rsmi_1 = (
28
44
  '[CH3:1][C:2](=[O:3])[OH:4].[CH3:5][OH:6]'
@@ -37,9 +53,76 @@ class AAMValidator:
37
53
  >>> True
38
54
  """
39
55
 
40
- def __init__(self) -> None:
41
- """Initialize the AAMValidator."""
42
- pass
56
+ def __init__(self, strip_unbalanced_maps: bool = True) -> None:
57
+ """Initialize the AAMValidator.
58
+
59
+ :param strip_unbalanced_maps: If True, remove atoms whose atom-map
60
+ labels are present on only one side before building ITS/RC graphs.
61
+ This reproduces the more permissive SynRXN benchmark behavior.
62
+ :type strip_unbalanced_maps: bool
63
+ """
64
+ self.strip_unbalanced_maps = strip_unbalanced_maps
65
+
66
+ @staticmethod
67
+ def _resolve_strip_unbalanced_maps(
68
+ instance: Optional["AAMValidator"],
69
+ strip_unbalanced_maps: Optional[bool],
70
+ ) -> bool:
71
+ """Resolve call-level override against the instance default."""
72
+ if strip_unbalanced_maps is not None:
73
+ return strip_unbalanced_maps
74
+ if instance is not None:
75
+ return instance.strip_unbalanced_maps
76
+ return True
77
+
78
+ @staticmethod
79
+ def _node_atom_map(graph: nx.Graph, node: object) -> Optional[int]:
80
+ """Return a node's atom-map label when available."""
81
+ value = graph.nodes[node].get("atom_map", node)
82
+ try:
83
+ return int(value)
84
+ except (TypeError, ValueError):
85
+ return None
86
+
87
+ @staticmethod
88
+ def _strip_unbalanced_map_nodes(
89
+ reactant_graph: nx.Graph,
90
+ product_graph: nx.Graph,
91
+ ) -> Tuple[nx.Graph, nx.Graph]:
92
+ """Remove nodes whose atom maps are not present on both sides."""
93
+ reactant_maps = {
94
+ atom_map
95
+ for node in reactant_graph.nodes
96
+ if (atom_map := AAMValidator._node_atom_map(reactant_graph, node))
97
+ is not None
98
+ }
99
+ product_maps = {
100
+ atom_map
101
+ for node in product_graph.nodes
102
+ if (atom_map := AAMValidator._node_atom_map(product_graph, node))
103
+ is not None
104
+ }
105
+ common_maps = reactant_maps & product_maps
106
+
107
+ stripped_reactant = reactant_graph.copy()
108
+ stripped_product = product_graph.copy()
109
+ stripped_reactant.remove_nodes_from(
110
+ [
111
+ node
112
+ for node in stripped_reactant.nodes
113
+ if AAMValidator._node_atom_map(stripped_reactant, node)
114
+ not in common_maps
115
+ ]
116
+ )
117
+ stripped_product.remove_nodes_from(
118
+ [
119
+ node
120
+ for node in stripped_product.nodes
121
+ if AAMValidator._node_atom_map(stripped_product, node)
122
+ not in common_maps
123
+ ]
124
+ )
125
+ return stripped_reactant, stripped_product
43
126
 
44
127
  @staticmethod
45
128
  def check_equivariant_graph(
@@ -72,12 +155,15 @@ class AAMValidator:
72
155
 
73
156
  return classified, len(classified)
74
157
 
75
- @staticmethod
158
+ @_DualMethod
76
159
  def smiles_check(
160
+ self,
161
+ cls,
77
162
  mapped_smile: str,
78
163
  ground_truth: str,
79
164
  check_method: str = "RC",
80
165
  ignore_aromaticity: bool = False,
166
+ strip_unbalanced_maps: Optional[bool] = None,
81
167
  ) -> bool:
82
168
  """Validate a single mapped SMILES string against ground truth.
83
169
 
@@ -92,14 +178,23 @@ class AAMValidator:
92
178
  :param ignore_aromaticity: If True, ignore aromaticity
93
179
  differences in ITS construction.
94
180
  :type ignore_aromaticity: bool
181
+ :param strip_unbalanced_maps: If True, remove atom-map labels present
182
+ on only one side before graph comparison. If None, use the
183
+ instance default or False for class-level calls.
184
+ :type strip_unbalanced_maps: bool or None
95
185
  :returns: True if exactly one isomorphic match is found; False
96
186
  otherwise.
97
187
  :rtype: bool
98
188
  """
99
189
  its_graphs, rc_graphs = [], []
190
+ strip_unbalanced_maps = cls._resolve_strip_unbalanced_maps(
191
+ self, strip_unbalanced_maps
192
+ )
100
193
  try:
101
194
  for rsmi in (mapped_smile, ground_truth):
102
195
  G, H = rsmi_to_graph(rsmi=rsmi, sanitize=True, drop_non_aam=True)
196
+ if strip_unbalanced_maps:
197
+ G, H = cls._strip_unbalanced_map_nodes(G, H)
103
198
  its = ITSConstruction().ITSGraph(
104
199
  G, H, ignore_aromaticity=ignore_aromaticity
105
200
  )
@@ -112,12 +207,15 @@ class AAMValidator:
112
207
  except Exception:
113
208
  return False
114
209
 
115
- @staticmethod
210
+ @_DualMethod
116
211
  def smiles_check_tautomer(
212
+ self,
213
+ cls,
117
214
  mapped_smile: str,
118
215
  ground_truth: str,
119
216
  check_method: str = "RC",
120
217
  ignore_aromaticity: bool = False,
218
+ strip_unbalanced_maps: Optional[bool] = None,
121
219
  ) -> Optional[bool]:
122
220
  """Validate against all tautomers of a ground truth SMILES.
123
221
 
@@ -129,31 +227,45 @@ class AAMValidator:
129
227
  :type check_method: str
130
228
  :param ignore_aromaticity: If True, ignore aromaticity in ITS construction.
131
229
  :type ignore_aromaticity: bool
230
+ :param strip_unbalanced_maps: If True, remove atom-map labels present
231
+ on only one side before graph comparison. If None, use the
232
+ instance default or False for class-level calls.
233
+ :type strip_unbalanced_maps: bool or None
132
234
  :returns:
133
235
  - `True` if any tautomer matches.
134
236
  - `False` if none match.
135
237
  - `None` if an error occurs.
136
238
  :rtype: bool or None
137
239
  """
240
+ strip_unbalanced_maps = cls._resolve_strip_unbalanced_maps(
241
+ self, strip_unbalanced_maps
242
+ )
138
243
  try:
139
244
  tautomers = enumerate_tautomers(ground_truth)
140
245
  return any(
141
- AAMValidator.smiles_check(
142
- mapped_smile, taut, check_method, ignore_aromaticity
246
+ cls.smiles_check(
247
+ mapped_smile,
248
+ taut,
249
+ check_method,
250
+ ignore_aromaticity,
251
+ strip_unbalanced_maps,
143
252
  )
144
253
  for taut in tautomers
145
254
  )
146
255
  except Exception:
147
256
  return None
148
257
 
149
- @staticmethod
258
+ @_DualMethod
150
259
  def check_pair(
260
+ self,
261
+ cls,
151
262
  mapping: Dict[str, str],
152
263
  mapped_col: str,
153
264
  ground_truth_col: str,
154
265
  check_method: str = "RC",
155
266
  ignore_aromaticity: bool = False,
156
267
  ignore_tautomers: bool = True,
268
+ strip_unbalanced_maps: Optional[bool] = None,
157
269
  ) -> bool:
158
270
  """Validate a single record (dict) entry for equivalence.
159
271
 
@@ -169,26 +281,37 @@ class AAMValidator:
169
281
  :type ignore_aromaticity: bool
170
282
  :param ignore_tautomers: If True, skip tautomer enumeration.
171
283
  :type ignore_tautomers: bool
284
+ :param strip_unbalanced_maps: If True, remove atom-map labels present
285
+ on only one side before graph comparison. If None, use the
286
+ instance default or False for class-level calls.
287
+ :type strip_unbalanced_maps: bool or None
172
288
  :returns: Validation result for this single pair.
173
289
  :rtype: bool
174
290
  """
291
+ strip_unbalanced_maps = cls._resolve_strip_unbalanced_maps(
292
+ self, strip_unbalanced_maps
293
+ )
175
294
  if ignore_tautomers:
176
- return AAMValidator.smiles_check(
295
+ return cls.smiles_check(
177
296
  mapping[mapped_col],
178
297
  mapping[ground_truth_col],
179
298
  check_method,
180
299
  ignore_aromaticity,
300
+ strip_unbalanced_maps,
181
301
  )
182
302
  else:
183
- return AAMValidator.smiles_check_tautomer(
303
+ return cls.smiles_check_tautomer(
184
304
  mapping[mapped_col],
185
305
  mapping[ground_truth_col],
186
306
  check_method,
187
307
  ignore_aromaticity,
308
+ strip_unbalanced_maps,
188
309
  )
189
310
 
190
- @staticmethod
311
+ @_DualMethod
191
312
  def validate_smiles(
313
+ self,
314
+ cls,
192
315
  data: Union[pd.DataFrame, List[Dict[str, str]]],
193
316
  ground_truth_col: str = "ground_truth",
194
317
  mapped_cols: List[str] = ["rxn_mapper", "graphormer", "local_mapper"],
@@ -197,6 +320,7 @@ class AAMValidator:
197
320
  n_jobs: int = 1,
198
321
  verbose: int = 0,
199
322
  ignore_tautomers: bool = True,
323
+ strip_unbalanced_maps: Optional[bool] = None,
200
324
  ) -> List[Dict[str, Union[str, float, List[bool]]]]:
201
325
  """Batch-validate mapped SMILES in tabular or list-of-dicts form.
202
326
 
@@ -217,6 +341,10 @@ class AAMValidator:
217
341
  :type verbose: int
218
342
  :param ignore_tautomers: If True, use simple pairwise check; otherwise enumerate tautomers.
219
343
  :type ignore_tautomers: bool
344
+ :param strip_unbalanced_maps: If True, remove atom-map labels present
345
+ on only one side before graph comparison. If None, use the
346
+ instance default or False for class-level calls.
347
+ :type strip_unbalanced_maps: bool or None
220
348
  :returns: A list of dicts, one per mapper, with keys:
221
349
  - `"mapper"`: the mapper name
222
350
  - `"accuracy"`: percentage correct (float)
@@ -237,15 +365,19 @@ class AAMValidator:
237
365
  "Data must be either a pandas DataFrame or a list of dictionaries."
238
366
  )
239
367
 
368
+ strip_unbalanced_maps = cls._resolve_strip_unbalanced_maps(
369
+ self, strip_unbalanced_maps
370
+ )
240
371
  for mapped_col in mapped_cols:
241
372
  results = Parallel(n_jobs=n_jobs, verbose=verbose)(
242
- delayed(AAMValidator.check_pair)(
373
+ delayed(cls.check_pair)(
243
374
  mapping,
244
375
  mapped_col,
245
376
  ground_truth_col,
246
377
  check_method,
247
378
  ignore_aromaticity,
248
379
  ignore_tautomers,
380
+ strip_unbalanced_maps,
249
381
  )
250
382
  for mapping in mappings
251
383
  )
@@ -0,0 +1,46 @@
1
+ """
2
+ mapper.chem — chemistry front-end (RDKit SMILES, ITS analysis).
3
+
4
+ Submodules
5
+ ----------
6
+ aam
7
+ :class:`AAMapper`: high-level reaction-SMILES atom-to-atom mapper.
8
+ smiles
9
+ SMILES ↔ LabeledGraph conversion and reaction-SMILES annotation utilities.
10
+ its
11
+ ITS graph hashing, electron-balance checks, and symmetry-distinct
12
+ deduplication via synkit.
13
+ """
14
+
15
+ from .aam import AAMapper
16
+ from .its import (
17
+ its_canonical_hash,
18
+ dedup_mapped_rxns,
19
+ mapped_rxn_is_electron_balanced,
20
+ is_electron_balanced,
21
+ electron_balance_status,
22
+ )
23
+ from .smiles import (
24
+ HAS_RDKIT,
25
+ smiles2lgp,
26
+ get_numbered_rxn_smiles,
27
+ canonicalize_rxn_smiles,
28
+ expand_reaction_center_hydrogens,
29
+ )
30
+
31
+ __all__ = [
32
+ # aam
33
+ "AAMapper",
34
+ # its
35
+ "its_canonical_hash",
36
+ "dedup_mapped_rxns",
37
+ "mapped_rxn_is_electron_balanced",
38
+ "is_electron_balanced",
39
+ "electron_balance_status",
40
+ # smiles
41
+ "HAS_RDKIT",
42
+ "smiles2lgp",
43
+ "get_numbered_rxn_smiles",
44
+ "canonicalize_rxn_smiles",
45
+ "expand_reaction_center_hydrogens",
46
+ ]