synkit 1.2.2__tar.gz → 1.3__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 (266) hide show
  1. {synkit-1.2.2 → synkit-1.3}/.gitignore +2 -1
  2. {synkit-1.2.2 → synkit-1.3}/PKG-INFO +1 -1
  3. {synkit-1.2.2 → synkit-1.3}/pyproject.toml +1 -1
  4. synkit-1.3/synkit/Graph/ITS/its_construction.py +660 -0
  5. synkit-1.3/synkit/Graph/ITS/its_reverter.py +330 -0
  6. synkit-1.3/synkit/Graph/ITS/rc_extractor.py +615 -0
  7. synkit-1.3/synkit/IO/chem_converter.py +892 -0
  8. synkit-1.3/synkit/IO/mol_to_graph.py +1117 -0
  9. synkit-1.2.2/synkit/Graph/ITS/its_construction.py +0 -316
  10. synkit-1.2.2/synkit/IO/chem_converter.py +0 -621
  11. synkit-1.2.2/synkit/IO/mol_to_graph.py +0 -480
  12. {synkit-1.2.2 → synkit-1.3}/LICENSE +0 -0
  13. {synkit-1.2.2 → synkit-1.3}/README.md +0 -0
  14. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/DAG/__init__.py +0 -0
  15. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/DAG/crn.py +0 -0
  16. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/DAG/mod_crn.py +0 -0
  17. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/DAG/syncrn.py +0 -0
  18. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/__init__.py +0 -0
  19. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/abstract.py +0 -0
  20. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/arity.py +0 -0
  21. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/builder.py +0 -0
  22. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/derivation.py +0 -0
  23. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/flattener.py +0 -0
  24. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/keys.py +0 -0
  25. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/mixtures.py +0 -0
  26. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/smiles.py +0 -0
  27. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/state.py +0 -0
  28. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/strategy.py +0 -0
  29. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Construct/worker.py +0 -0
  30. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Pathway/__init__.py +0 -0
  31. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Pathway/_adapter.py +0 -0
  32. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Pathway/pathfinder.py +0 -0
  33. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Pathway/reachability.py +0 -0
  34. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Pathway/realizability.py +0 -0
  35. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Petrinet/__init__.py +0 -0
  36. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Petrinet/analyzer.py +0 -0
  37. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Petrinet/net.py +0 -0
  38. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Petrinet/persistence.py +0 -0
  39. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Petrinet/semiflows.py +0 -0
  40. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Petrinet/structure.py +0 -0
  41. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Props/__init__.py +0 -0
  42. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Props/dynamics.py +0 -0
  43. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Props/helper.py +0 -0
  44. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Props/stoich.py +0 -0
  45. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Props/thermo.py +0 -0
  46. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Query/__init__.py +0 -0
  47. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Query/kegg_api.py +0 -0
  48. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Query/kegg_extract.py +0 -0
  49. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Query/kegg_impute.py +0 -0
  50. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Query/kegg_parse.py +0 -0
  51. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Structure/__init__.py +0 -0
  52. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Structure/reaction.py +0 -0
  53. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Structure/rule.py +0 -0
  54. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Structure/species.py +0 -0
  55. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Structure/syncrn.py +0 -0
  56. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Symmetry/__init__.py +0 -0
  57. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Symmetry/_common.py +0 -0
  58. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Symmetry/_ir.py +0 -0
  59. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Symmetry/automorphism.py +0 -0
  60. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Symmetry/canon.py +0 -0
  61. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Symmetry/isomorphism.py +0 -0
  62. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Symmetry/symmetry.py +0 -0
  63. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Symmetry/wl_canon.py +0 -0
  64. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Visualize/__init__.py +0 -0
  65. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Visualize/crn_vis.py +0 -0
  66. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Visualize/labels.py +0 -0
  67. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Visualize/layout.py +0 -0
  68. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Visualize/palette.py +0 -0
  69. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Visualize/validation.py +0 -0
  70. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/Visualize/vis.py +0 -0
  71. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/__init__.py +0 -0
  72. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Structure/__init__.py +0 -0
  73. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Structure/backend.py +0 -0
  74. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Structure/conversion.py +0 -0
  75. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Structure/hyperedge.py +0 -0
  76. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Structure/hypergraph.py +0 -0
  77. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Structure/rxn.py +0 -0
  78. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Symmetry/__init__.py +0 -0
  79. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Symmetry/automorphism.py +0 -0
  80. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Symmetry/canon.py +0 -0
  81. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/Symmetry/wl_canon.py +0 -0
  82. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/__init__.py +0 -0
  83. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/configs/__init__.py +0 -0
  84. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/configs/loader.py +0 -0
  85. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/configs/models.py +0 -0
  86. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/constants.py +0 -0
  87. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/crn_formula.py +0 -0
  88. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/deficiency.py +0 -0
  89. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/enumerator.py +0 -0
  90. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/exceptions.py +0 -0
  91. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/explorer.py +0 -0
  92. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/helpers.py +0 -0
  93. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/injectivity.py +0 -0
  94. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/motif.py +0 -0
  95. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/network.py +0 -0
  96. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/pathway.py +0 -0
  97. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/properties.py +0 -0
  98. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/reaction.py +0 -0
  99. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/utils.py +0 -0
  100. {synkit-1.2.2 → synkit-1.3}/synkit/CRN/dev_crn/viz.py +0 -0
  101. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Cluster/__init__.py +0 -0
  102. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Cluster/butina.py +0 -0
  103. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Fingerprint/__init__.py +0 -0
  104. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
  105. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
  106. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
  107. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Molecule/__init__.py +0 -0
  108. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Molecule/atom_features.py +0 -0
  109. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Molecule/descriptors.py +0 -0
  110. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Molecule/formula.py +0 -0
  111. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Molecule/graph_annotator.py +0 -0
  112. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Molecule/standardize.py +0 -0
  113. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Molecule/valence.py +0 -0
  114. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/Mapper/__init__.py +0 -0
  115. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/Mapper/wl_mapper.py +0 -0
  116. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/__init__.py +0 -0
  117. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/aam_validator.py +0 -0
  118. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/balance_check.py +0 -0
  119. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/canon_rsmi.py +0 -0
  120. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/cleaning.py +0 -0
  121. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/deionize.py +0 -0
  122. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/fix_aam.py +0 -0
  123. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/neutralize.py +0 -0
  124. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/radical_wildcard.py +0 -0
  125. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/standardize.py +0 -0
  126. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/Reaction/tautomerize.py +0 -0
  127. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/__init__.py +0 -0
  128. {synkit-1.2.2 → synkit-1.3}/synkit/Chem/utils.py +0 -0
  129. {synkit-1.2.2 → synkit-1.3}/synkit/Data/__init__.py +0 -0
  130. {synkit-1.2.2 → synkit-1.3}/synkit/Data/gen_partial_aam.py +0 -0
  131. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Canon/__init__.py +0 -0
  132. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Canon/canon_algs.py +0 -0
  133. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Canon/canon_graph.py +0 -0
  134. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Canon/nauty.py +0 -0
  135. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Context/__init__.py +0 -0
  136. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Context/hier_context.py +0 -0
  137. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Context/radius_expand.py +0 -0
  138. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/Descriptors/topology.py +0 -0
  139. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
  140. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +0 -0
  141. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/__init__.py +0 -0
  142. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/graph_descriptors.py +0 -0
  143. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/graph_fps.py +0 -0
  144. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/graph_signature.py +0 -0
  145. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/hash_fps.py +0 -0
  146. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/morgan_fps.py +0 -0
  147. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/path_fps.py +0 -0
  148. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Feature/wl_hash.py +0 -0
  149. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Hyrogen/__init__.py +0 -0
  150. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Hyrogen/_misc.py +0 -0
  151. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Hyrogen/hcomplete.py +0 -0
  152. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Hyrogen/hextend.py +0 -0
  153. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/ITS/__init__.py +0 -0
  154. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/ITS/its_builder.py +0 -0
  155. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/ITS/its_decompose.py +0 -0
  156. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/ITS/its_destruction.py +0 -0
  157. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/ITS/its_expand.py +0 -0
  158. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/ITS/its_relabel.py +0 -0
  159. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/ITS/normalize_aam.py +0 -0
  160. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/ITS/partial_its.py +0 -0
  161. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/MTG/__init__.py +0 -0
  162. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/MTG/group_comp.py +0 -0
  163. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/MTG/groupoid.py +0 -0
  164. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/MTG/mcs_matcher.py +0 -0
  165. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/MTG/mtg.py +0 -0
  166. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/MTG/mtg_explore.py +0 -0
  167. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/MTG/utils.py +0 -0
  168. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/__init__.py +0 -0
  169. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/approx_mcs.py +0 -0
  170. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/auto_est.py +0 -0
  171. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/automorphism.py +0 -0
  172. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/batch_cluster.py +0 -0
  173. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/dedup_matches.py +0 -0
  174. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/graph_cluster.py +0 -0
  175. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/graph_matcher.py +0 -0
  176. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/graph_morphism.py +0 -0
  177. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/mcs_matcher.py +0 -0
  178. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/multi_turbo_iso.py +0 -0
  179. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/orbit.py +0 -0
  180. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/partial_matcher.py +0 -0
  181. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/sing.py +0 -0
  182. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/subgraph_matcher.py +0 -0
  183. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/turbo_iso.py +0 -0
  184. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Matcher/wl_sel.py +0 -0
  185. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Wildcard/__init__.py +0 -0
  186. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Wildcard/fuse_graph.py +0 -0
  187. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Wildcard/graph_wc.py +0 -0
  188. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Wildcard/its_merge.py +0 -0
  189. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Wildcard/radwc.py +0 -0
  190. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Wildcard/wc_matcher.py +0 -0
  191. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/Wildcard/wildcard.py +0 -0
  192. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/__init__.py +0 -0
  193. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/canon_graph.py +0 -0
  194. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/syn_graph.py +0 -0
  195. {synkit-1.2.2 → synkit-1.3}/synkit/Graph/utils.py +0 -0
  196. {synkit-1.2.2 → synkit-1.3}/synkit/IO/__init__.py +0 -0
  197. {synkit-1.2.2 → synkit-1.3}/synkit/IO/combinatorial/__init__.py +0 -0
  198. {synkit-1.2.2 → synkit-1.3}/synkit/IO/combinatorial/gml_to_graph.py +0 -0
  199. {synkit-1.2.2 → synkit-1.3}/synkit/IO/combinatorial/graph_to_gml.py +0 -0
  200. {synkit-1.2.2 → synkit-1.3}/synkit/IO/combinatorial/graph_to_smarts.py +0 -0
  201. {synkit-1.2.2 → synkit-1.3}/synkit/IO/combinatorial/smarts_expander.py +0 -0
  202. {synkit-1.2.2 → synkit-1.3}/synkit/IO/combinatorial/smarts_generalizer.py +0 -0
  203. {synkit-1.2.2 → synkit-1.3}/synkit/IO/combinatorial/smarts_to_graph.py +0 -0
  204. {synkit-1.2.2 → synkit-1.3}/synkit/IO/data_io.py +0 -0
  205. {synkit-1.2.2 → synkit-1.3}/synkit/IO/data_process.py +0 -0
  206. {synkit-1.2.2 → synkit-1.3}/synkit/IO/debug.py +0 -0
  207. {synkit-1.2.2 → synkit-1.3}/synkit/IO/dg_to_gml.py +0 -0
  208. {synkit-1.2.2 → synkit-1.3}/synkit/IO/gml_to_nx.py +0 -0
  209. {synkit-1.2.2 → synkit-1.3}/synkit/IO/graph_to_mol.py +0 -0
  210. {synkit-1.2.2 → synkit-1.3}/synkit/IO/nx_to_gml.py +0 -0
  211. {synkit-1.2.2 → synkit-1.3}/synkit/IO/smiles_to_id.py +0 -0
  212. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Apply/__init__.py +0 -0
  213. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Apply/reactor_rule.py +0 -0
  214. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Apply/retro_reactor.py +0 -0
  215. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Apply/rule_matcher.py +0 -0
  216. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Apply/rule_rbl.py +0 -0
  217. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Compose/__init__.py +0 -0
  218. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Compose/compose_rule.py +0 -0
  219. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Compose/rule_compose.py +0 -0
  220. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Compose/rule_mapping.py +0 -0
  221. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Compose/seq_comp.py +0 -0
  222. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Compose/valence_constrain.py +0 -0
  223. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Modify/__init__.py +0 -0
  224. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Modify/implict_rule.py +0 -0
  225. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Modify/longest_path.py +0 -0
  226. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Modify/molecule_rule.py +0 -0
  227. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Modify/prune_templates.py +0 -0
  228. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Modify/rule_utils.py +0 -0
  229. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/Modify/strip_rule.py +0 -0
  230. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/__init__.py +0 -0
  231. {synkit-1.2.2 → synkit-1.3}/synkit/Rule/syn_rule.py +0 -0
  232. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/MSR/__init__.py +0 -0
  233. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/MSR/multi_steps.py +0 -0
  234. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/MSR/path_finder.py +0 -0
  235. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Metrics/__init__.py +0 -0
  236. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Metrics/_base.py +0 -0
  237. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Metrics/_plot.py +0 -0
  238. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Metrics/_ranking.py +0 -0
  239. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/__init__.py +0 -0
  240. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/batch_reactor.py +0 -0
  241. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/benchmark.py +0 -0
  242. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/imba_engine.py +0 -0
  243. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/mod_aam.py +0 -0
  244. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/mod_reactor.py +0 -0
  245. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/partial_engine.py +0 -0
  246. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/post_syn.py +0 -0
  247. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/rbl_engine.py +0 -0
  248. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/rule_filter.py +0 -0
  249. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/single_predictor.py +0 -0
  250. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/strategy.py +0 -0
  251. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/Reactor/syn_reactor.py +0 -0
  252. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/__init__.py +0 -0
  253. {synkit-1.2.2 → synkit-1.3}/synkit/Synthesis/reactor_utils.py +0 -0
  254. {synkit-1.2.2 → synkit-1.3}/synkit/Utils/__init__.py +0 -0
  255. {synkit-1.2.2 → synkit-1.3}/synkit/Utils/utils.py +0 -0
  256. {synkit-1.2.2 → synkit-1.3}/synkit/Vis/__init__.py +0 -0
  257. {synkit-1.2.2 → synkit-1.3}/synkit/Vis/chemical_space.py +0 -0
  258. {synkit-1.2.2 → synkit-1.3}/synkit/Vis/crn_vis.py +0 -0
  259. {synkit-1.2.2 → synkit-1.3}/synkit/Vis/embedding.py +0 -0
  260. {synkit-1.2.2 → synkit-1.3}/synkit/Vis/graph_visualizer.py +0 -0
  261. {synkit-1.2.2 → synkit-1.3}/synkit/Vis/pdf_writer.py +0 -0
  262. {synkit-1.2.2 → synkit-1.3}/synkit/Vis/rule_vis.py +0 -0
  263. {synkit-1.2.2 → synkit-1.3}/synkit/Vis/rxn_vis.py +0 -0
  264. {synkit-1.2.2 → synkit-1.3}/synkit/__init__.py +0 -0
  265. {synkit-1.2.2 → synkit-1.3}/synkit/examples.py +0 -0
  266. {synkit-1.2.2 → synkit-1.3}/synkit/version.py +0 -0
@@ -26,4 +26,5 @@ Data/USPTO/*
26
26
  crn/*
27
27
  test_run.py
28
28
  Data/Study/CRN/case_formose/*
29
- Data/Study/CRN/case_glycolysis/*
29
+ Data/Study/CRN/case_glycolysis/*
30
+ synkit/Graph/dev/*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synkit
3
- Version: 1.2.2
3
+ Version: 1.3
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.2.2"
7
+ version = "1.3"
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,660 @@
1
+ import networkx as nx
2
+ from typing import Tuple, Dict, Any, Optional, List, Hashable
3
+ from copy import deepcopy
4
+
5
+
6
+ class ITSConstruction:
7
+ """
8
+ Utility class for constructing an ITS graph from two input graphs.
9
+
10
+ Nodes store paired state information through the ``typesGH`` attribute.
11
+ Edges store direct paired attributes such as ``order=(g, h)`` without
12
+ an edge-level ``typesGH``.
13
+
14
+ The main public entry point is :meth:`construct`.
15
+ """
16
+
17
+ CORE_NODE_DEFAULTS: Dict[str, Any] = {
18
+ "element": "*",
19
+ "charge": 0,
20
+ "atom_map": 0,
21
+ "hcount": 0,
22
+ "aromatic": False,
23
+ "neighbors": lambda: ["", ""],
24
+ "partial_charge": 0,
25
+ "hybridization": "",
26
+ "lone_pairs": 0,
27
+ "valence_electrons": 0,
28
+ }
29
+
30
+ CORE_EDGE_DEFAULTS: Dict[str, Any] = {
31
+ "order": 0.0,
32
+ "ez_isomer": "",
33
+ "bond_type": "",
34
+ "conjugated": False,
35
+ "in_ring": False,
36
+ }
37
+
38
+ @staticmethod
39
+ def _resolve_defaults(
40
+ user_defaults: Optional[Dict[str, Any]], core_defaults: Dict[str, Any]
41
+ ) -> Dict[str, Any]:
42
+ """
43
+ Merge user-provided defaults with built-in defaults.
44
+
45
+ :param user_defaults:
46
+ Optional mapping of user overrides.
47
+ :type user_defaults: Optional[Dict[str, Any]]
48
+ :param core_defaults:
49
+ Built-in defaults. Callable values are treated as factories.
50
+ :type core_defaults: Dict[str, Any]
51
+
52
+ :returns:
53
+ Resolved defaults with fresh copies for mutable values.
54
+ :rtype: Dict[str, Any]
55
+ """
56
+ resolved: Dict[str, Any] = {}
57
+ user_defaults = user_defaults or {}
58
+
59
+ for key, core_val in core_defaults.items():
60
+ if key in user_defaults:
61
+ resolved[key] = deepcopy(user_defaults[key])
62
+ elif callable(core_val):
63
+ resolved[key] = core_val()
64
+ else:
65
+ resolved[key] = deepcopy(core_val)
66
+
67
+ return resolved
68
+
69
+ @staticmethod
70
+ def _compute_standard_order(
71
+ its: nx.Graph, ignore_aromaticity: bool = False
72
+ ) -> None:
73
+ """
74
+ Compute ``standard_order`` for each edge from ``order=(g, h)``.
75
+
76
+ :param its:
77
+ ITS graph whose edges contain an ``order`` tuple.
78
+ :type its: nx.Graph
79
+ :param ignore_aromaticity:
80
+ If ``True``, absolute differences smaller than ``1`` are set to ``0``.
81
+ :type ignore_aromaticity: bool
82
+ """
83
+ for u, v, data in its.edges(data=True):
84
+ order_tuple = data.get("order", (0.0, 0.0))
85
+ try:
86
+ o_g, o_h = order_tuple
87
+ except Exception:
88
+ o_g, o_h = 0.0, 0.0
89
+
90
+ standard_order = o_g - o_h
91
+ if ignore_aromaticity and abs(standard_order) < 1:
92
+ standard_order = 0
93
+
94
+ its[u][v]["standard_order"] = standard_order
95
+
96
+ @staticmethod
97
+ def _select_base_graph(G: nx.Graph, H: nx.Graph, balance_its: bool) -> nx.Graph:
98
+ """
99
+ Select the base graph used to initialize the ITS graph.
100
+
101
+ :param G:
102
+ First input graph.
103
+ :type G: nx.Graph
104
+ :param H:
105
+ Second input graph.
106
+ :type H: nx.Graph
107
+ :param balance_its:
108
+ If ``True``, prefer the smaller graph; otherwise prefer the larger.
109
+ :type balance_its: bool
110
+
111
+ :returns:
112
+ Selected base graph.
113
+ :rtype: nx.Graph
114
+ """
115
+ if (balance_its and len(G.nodes) <= len(H.nodes)) or (
116
+ not balance_its and len(G.nodes) >= len(H.nodes)
117
+ ):
118
+ return G
119
+ return H
120
+
121
+ @staticmethod
122
+ def _initialize_its(base: nx.Graph) -> nx.Graph:
123
+ """
124
+ Deep-copy the base graph and remove all edges.
125
+
126
+ :param base:
127
+ Graph chosen as ITS initialization template.
128
+ :type base: nx.Graph
129
+
130
+ :returns:
131
+ Edge-free copy of the base graph.
132
+ :rtype: nx.Graph
133
+ """
134
+ its = deepcopy(base)
135
+ its.remove_edges_from(list(its.edges()))
136
+ return its
137
+
138
+ @staticmethod
139
+ def _ensure_union_nodes(its: nx.Graph, G: nx.Graph, H: nx.Graph) -> None:
140
+ """
141
+ Ensure the ITS graph contains the union of nodes from both input graphs.
142
+
143
+ :param its:
144
+ ITS graph to update in place.
145
+ :type its: nx.Graph
146
+ :param G:
147
+ First input graph.
148
+ :type G: nx.Graph
149
+ :param H:
150
+ Second input graph.
151
+ :type H: nx.Graph
152
+ """
153
+ all_nodes = set(G.nodes()) | set(H.nodes())
154
+ for n in all_nodes:
155
+ if n in its:
156
+ continue
157
+
158
+ source_attrs: Dict[str, Any] = {}
159
+ if n in G:
160
+ source_attrs = deepcopy(G.nodes[n])
161
+ elif n in H:
162
+ source_attrs = deepcopy(H.nodes[n])
163
+
164
+ its.add_node(n, **source_attrs)
165
+
166
+ @staticmethod
167
+ def _build_node_side_tuple(
168
+ graph: nx.Graph,
169
+ node: Hashable,
170
+ attrs: List[str],
171
+ defaults: Dict[str, Any],
172
+ ) -> Tuple[Any, ...]:
173
+ """
174
+ Build one side of a node tuple for ``typesGH``.
175
+
176
+ :param graph:
177
+ Source graph.
178
+ :type graph: nx.Graph
179
+ :param node:
180
+ Node identifier.
181
+ :type node: Hashable
182
+ :param attrs:
183
+ Ordered node attributes.
184
+ :type attrs: List[str]
185
+ :param defaults:
186
+ Default values for missing attributes.
187
+ :type defaults: Dict[str, Any]
188
+
189
+ :returns:
190
+ Attribute tuple for the requested node.
191
+ :rtype: Tuple[Any, ...]
192
+ """
193
+ if node not in graph:
194
+ return tuple(defaults.get(attr) for attr in attrs)
195
+ return tuple(graph.nodes[node].get(attr, defaults.get(attr)) for attr in attrs)
196
+
197
+ @staticmethod
198
+ def _populate_node_attributes(
199
+ its: nx.Graph,
200
+ G: nx.Graph,
201
+ H: nx.Graph,
202
+ node_attrs: List[str],
203
+ node_defaults: Dict[str, Any],
204
+ store: bool,
205
+ ) -> None:
206
+ """
207
+ Populate node-level ``typesGH`` and per-attribute node storage.
208
+
209
+ :param its:
210
+ ITS graph to update in place.
211
+ :type its: nx.Graph
212
+ :param G:
213
+ First input graph.
214
+ :type G: nx.Graph
215
+ :param H:
216
+ Second input graph.
217
+ :type H: nx.Graph
218
+ :param node_attrs:
219
+ Ordered node attributes included in ``typesGH``.
220
+ :type node_attrs: List[str]
221
+ :param node_defaults:
222
+ Default values for missing node attributes.
223
+ :type node_defaults: Dict[str, Any]
224
+ :param store:
225
+ If ``True``, store per-attribute ``(G, H)`` tuples. Otherwise store
226
+ only the ``G``-side value.
227
+ :type store: bool
228
+ """
229
+ for n in its.nodes():
230
+ g_tuple = ITSConstruction._build_node_side_tuple(
231
+ G, n, node_attrs, node_defaults
232
+ )
233
+ h_tuple = ITSConstruction._build_node_side_tuple(
234
+ H, n, node_attrs, node_defaults
235
+ )
236
+
237
+ its.nodes[n]["typesGH"] = (g_tuple, h_tuple)
238
+
239
+ for i, attr in enumerate(node_attrs):
240
+ its.nodes[n][attr] = (g_tuple[i], h_tuple[i]) if store else g_tuple[i]
241
+
242
+ @staticmethod
243
+ def _edge_keys(G: nx.Graph, H: nx.Graph) -> List[Tuple[Hashable, Hashable]]:
244
+ """
245
+ Compute the union of undirected edges from ``G`` and ``H``.
246
+
247
+ :param G:
248
+ First input graph.
249
+ :type G: nx.Graph
250
+ :param H:
251
+ Second input graph.
252
+ :type H: nx.Graph
253
+
254
+ :returns:
255
+ List of unique edge pairs.
256
+ :rtype: List[Tuple[Hashable, Hashable]]
257
+ """
258
+ edge_keys = {frozenset((u, v)) for u, v in G.edges()} | {
259
+ frozenset((u, v)) for u, v in H.edges()
260
+ }
261
+ return [tuple(fs) for fs in edge_keys]
262
+
263
+ @staticmethod
264
+ def _build_edge_pair_data(
265
+ G: nx.Graph,
266
+ H: nx.Graph,
267
+ u: Hashable,
268
+ v: Hashable,
269
+ edge_attrs: List[str],
270
+ edge_defaults: Dict[str, Any],
271
+ ) -> Dict[str, Any]:
272
+ """
273
+ Build direct paired edge attributes for one ITS edge.
274
+
275
+ Each requested edge attribute is stored as ``(G_value, H_value)``.
276
+ The ``order`` attribute is always guaranteed to exist.
277
+
278
+ :param G:
279
+ First input graph.
280
+ :type G: nx.Graph
281
+ :param H:
282
+ Second input graph.
283
+ :type H: nx.Graph
284
+ :param u:
285
+ First edge endpoint.
286
+ :type u: Hashable
287
+ :param v:
288
+ Second edge endpoint.
289
+ :type v: Hashable
290
+ :param edge_attrs:
291
+ Edge attributes to store as paired tuples.
292
+ :type edge_attrs: List[str]
293
+ :param edge_defaults:
294
+ Default values for missing edge attributes.
295
+ :type edge_defaults: Dict[str, Any]
296
+
297
+ :returns:
298
+ Edge attribute mapping for ITS storage.
299
+ :rtype: Dict[str, Any]
300
+ """
301
+ g_edge = G[u][v] if G.has_edge(u, v) else {}
302
+ h_edge = H[u][v] if H.has_edge(u, v) else {}
303
+
304
+ edge_data: Dict[str, Any] = {}
305
+ for attr in edge_attrs:
306
+ default = edge_defaults.get(attr)
307
+ g_val = g_edge.get(attr, default)
308
+ h_val = h_edge.get(attr, default)
309
+ edge_data[attr] = (g_val, h_val)
310
+
311
+ if "order" not in edge_data:
312
+ g_order = g_edge.get("order", edge_defaults.get("order", 0.0))
313
+ h_order = h_edge.get("order", edge_defaults.get("order", 0.0))
314
+ edge_data["order"] = (g_order, h_order)
315
+
316
+ if "kekule_order" in edge_data:
317
+ g_order = g_edge.get("kekule_order", edge_defaults.get("order", 0.0))
318
+ h_order = h_edge.get("kekule_order", edge_defaults.get("order", 0.0))
319
+ edge_data["kekule_order"] = (g_order, h_order)
320
+
321
+ return edge_data
322
+
323
+ @staticmethod
324
+ def _populate_edge_attributes(
325
+ its: nx.Graph,
326
+ G: nx.Graph,
327
+ H: nx.Graph,
328
+ edge_attrs: List[str],
329
+ edge_defaults: Dict[str, Any],
330
+ ) -> None:
331
+ """
332
+ Populate ITS edges with direct paired edge attributes.
333
+
334
+ :param its:
335
+ ITS graph to update in place.
336
+ :type its: nx.Graph
337
+ :param G:
338
+ First input graph.
339
+ :type G: nx.Graph
340
+ :param H:
341
+ Second input graph.
342
+ :type H: nx.Graph
343
+ :param edge_attrs:
344
+ Edge attributes to store as ``(G, H)`` tuples.
345
+ :type edge_attrs: List[str]
346
+ :param edge_defaults:
347
+ Default values for missing edge attributes.
348
+ :type edge_defaults: Dict[str, Any]
349
+ """
350
+ for u, v in ITSConstruction._edge_keys(G, H):
351
+ edge_data = ITSConstruction._build_edge_pair_data(
352
+ G, H, u, v, edge_attrs, edge_defaults
353
+ )
354
+ its.add_edge(u, v, **edge_data)
355
+
356
+ @staticmethod
357
+ def construct(
358
+ G: nx.Graph,
359
+ H: nx.Graph,
360
+ *,
361
+ ignore_aromaticity: bool = False,
362
+ balance_its: bool = True,
363
+ store: bool = True,
364
+ node_attrs: Optional[List[str]] = None,
365
+ edge_attrs: Optional[List[str]] = None,
366
+ attributes_defaults: Optional[Dict[str, Any]] = None,
367
+ ) -> nx.Graph:
368
+ """
369
+ Construct an ITS graph from two input graphs.
370
+
371
+ Nodes store ``typesGH`` as paired tuples over ``node_attrs``.
372
+ Requested edge attributes are stored directly as paired values such as
373
+ ``order=(g, h)`` and ``bond_type=(g, h)``. No edge-level ``typesGH`` is created.
374
+
375
+ :param G:
376
+ First input graph, typically the reactant-side graph.
377
+ :type G: nx.Graph
378
+ :param H:
379
+ Second input graph, typically the product-side graph.
380
+ :type H: nx.Graph
381
+ :param ignore_aromaticity:
382
+ If ``True``, bond-order differences with absolute value smaller than
383
+ ``1`` are treated as zero when computing ``standard_order``.
384
+ :type ignore_aromaticity: bool
385
+ :param balance_its:
386
+ If ``True``, initialize from the smaller graph; otherwise from the larger.
387
+ :type balance_its: bool
388
+ :param store:
389
+ Controls node attribute storage only. If ``True``, node attributes are
390
+ stored as ``(G, H)`` tuples. If ``False``, only the ``G``-side value
391
+ is stored. Edge attributes are always stored as paired tuples.
392
+ :type store: bool
393
+ :param node_attrs:
394
+ Ordered list of node attributes included in node-level ``typesGH``.
395
+ :type node_attrs: Optional[List[str]]
396
+ :param edge_attrs:
397
+ Ordered list of edge attributes stored directly as ``(G, H)`` tuples.
398
+ :type edge_attrs: Optional[List[str]]
399
+ :param attributes_defaults:
400
+ Optional overrides for node attribute defaults.
401
+ :type attributes_defaults: Optional[Dict[str, Any]]
402
+
403
+ :returns:
404
+ ITS graph with merged nodes, paired node/edge annotations, and
405
+ derived ``standard_order``.
406
+ :rtype: nx.Graph
407
+
408
+ Example
409
+ -------
410
+ .. code-block:: python
411
+
412
+ node_attrs = [
413
+ "element",
414
+ "aromatic",
415
+ "hcount",
416
+ "charge",
417
+ "neighbors",
418
+ "hybridization",
419
+ "atom_map",
420
+ "lone_pairs",
421
+ ]
422
+
423
+ edge_attrs = [
424
+ "kekule_order",
425
+ "order",
426
+ "bond_type",
427
+ "conjugated",
428
+ "in_ring",
429
+ ]
430
+
431
+ its = ITSConstruction.construct(
432
+ r_graph,
433
+ p_graph,
434
+ node_attrs=node_attrs,
435
+ edge_attrs=edge_attrs,
436
+ store=True,
437
+ )
438
+
439
+ print(its.edges[12, 30]["order"])
440
+ print(its.edges[12, 30]["bond_type"])
441
+ print(its.edges[12, 30]["standard_order"])
442
+ """
443
+ node_attrs = node_attrs or [
444
+ "element",
445
+ "aromatic",
446
+ "hcount",
447
+ "charge",
448
+ "neighbors",
449
+ ]
450
+ edge_attrs = edge_attrs or ["order"]
451
+
452
+ node_defaults = ITSConstruction._resolve_defaults(
453
+ attributes_defaults, ITSConstruction.CORE_NODE_DEFAULTS
454
+ )
455
+ edge_defaults = ITSConstruction._resolve_defaults(
456
+ None, ITSConstruction.CORE_EDGE_DEFAULTS
457
+ )
458
+
459
+ base = ITSConstruction._select_base_graph(G, H, balance_its)
460
+ its = ITSConstruction._initialize_its(base)
461
+
462
+ ITSConstruction._ensure_union_nodes(its, G, H)
463
+ ITSConstruction._populate_node_attributes(
464
+ its, G, H, node_attrs, node_defaults, store
465
+ )
466
+ ITSConstruction._populate_edge_attributes(its, G, H, edge_attrs, edge_defaults)
467
+ ITSConstruction._compute_standard_order(
468
+ its, ignore_aromaticity=ignore_aromaticity
469
+ )
470
+
471
+ return its
472
+
473
+ @staticmethod
474
+ def ITSGraph(
475
+ G: nx.Graph,
476
+ H: nx.Graph,
477
+ ignore_aromaticity: bool = False,
478
+ attributes_defaults: Optional[Dict[str, Any]] = None,
479
+ balance_its: bool = False,
480
+ store: bool = False,
481
+ ) -> nx.Graph:
482
+ """
483
+ Backward-compatible wrapper around :meth:`construct`.
484
+
485
+ :param G:
486
+ First input graph.
487
+ :type G: nx.Graph
488
+ :param H:
489
+ Second input graph.
490
+ :type H: nx.Graph
491
+ :param ignore_aromaticity:
492
+ If ``True``, small bond-order differences are ignored.
493
+ :type ignore_aromaticity: bool
494
+ :param attributes_defaults:
495
+ Optional node defaults for missing values.
496
+ :type attributes_defaults: Optional[Dict[str, Any]]
497
+ :param balance_its:
498
+ If ``True``, prefer the smaller graph as base.
499
+ :type balance_its: bool
500
+ :param store:
501
+ If ``True``, node attributes are stored as paired tuples.
502
+ :type store: bool
503
+
504
+ :returns:
505
+ Constructed ITS graph using legacy node and edge attribute defaults.
506
+ :rtype: nx.Graph
507
+ """
508
+ return ITSConstruction.construct(
509
+ G,
510
+ H,
511
+ ignore_aromaticity=ignore_aromaticity,
512
+ balance_its=balance_its,
513
+ store=store,
514
+ node_attrs=["element", "aromatic", "hcount", "charge", "neighbors"],
515
+ edge_attrs=["order"],
516
+ attributes_defaults=attributes_defaults,
517
+ )
518
+
519
+ @staticmethod
520
+ def typesGH_info(
521
+ node_attrs: Optional[List[str]] = None, edge_attrs: Optional[List[str]] = None
522
+ ) -> Dict[str, Dict[str, Tuple[type, Any]]]:
523
+ """
524
+ Provide expected types and defaults for node and edge attributes.
525
+
526
+ :param node_attrs:
527
+ Node attributes expected in node-level ``typesGH``.
528
+ :type node_attrs: Optional[List[str]]
529
+ :param edge_attrs:
530
+ Edge attributes expected as direct paired edge tuples.
531
+ :type edge_attrs: Optional[List[str]]
532
+
533
+ :returns:
534
+ Nested mapping describing ``(type, default)`` for each selected attribute.
535
+ :rtype: Dict[str, Dict[str, Tuple[type, Any]]]
536
+ """
537
+ node_attrs = node_attrs or [
538
+ "element",
539
+ "aromatic",
540
+ "hcount",
541
+ "charge",
542
+ "neighbors",
543
+ ]
544
+ edge_attrs = edge_attrs or ["order"]
545
+
546
+ node_prop_types: Dict[str, type] = {
547
+ "element": str,
548
+ "aromatic": bool,
549
+ "hcount": int,
550
+ "charge": int,
551
+ "neighbors": list,
552
+ }
553
+ edge_prop_types: Dict[str, type] = {
554
+ "order": float,
555
+ "ez_isomer": str,
556
+ "bond_type": str,
557
+ "conjugated": bool,
558
+ "in_ring": bool,
559
+ }
560
+
561
+ node_defaults = {
562
+ attr: (
563
+ node_prop_types.get(attr, object),
564
+ (
565
+ ITSConstruction.CORE_NODE_DEFAULTS.get(attr)()
566
+ if callable(ITSConstruction.CORE_NODE_DEFAULTS.get(attr))
567
+ else ITSConstruction.CORE_NODE_DEFAULTS.get(attr)
568
+ ),
569
+ )
570
+ for attr in node_attrs
571
+ }
572
+ edge_defaults = {
573
+ attr: (
574
+ edge_prop_types.get(attr, object),
575
+ ITSConstruction.CORE_EDGE_DEFAULTS.get(attr),
576
+ )
577
+ for attr in edge_attrs
578
+ }
579
+
580
+ return {"node": node_defaults, "edge": edge_defaults}
581
+
582
+ @staticmethod
583
+ def get_node_attribute(
584
+ graph: nx.Graph, node: Hashable, attribute: str, default: Any
585
+ ) -> Any:
586
+ """
587
+ Retrieve a node attribute or return a default if missing.
588
+
589
+ :param graph:
590
+ Input graph.
591
+ :type graph: nx.Graph
592
+ :param node:
593
+ Node identifier.
594
+ :type node: Hashable
595
+ :param attribute:
596
+ Attribute name.
597
+ :type attribute: str
598
+ :param default:
599
+ Fallback value.
600
+ :type default: Any
601
+
602
+ :returns:
603
+ Stored node attribute or fallback default.
604
+ :rtype: Any
605
+ """
606
+ try:
607
+ return graph.nodes[node][attribute]
608
+ except KeyError:
609
+ return default
610
+
611
+ @staticmethod
612
+ def get_node_attributes_with_defaults(
613
+ graph: nx.Graph, node: Hashable, attributes_defaults: Dict[str, Any] = None
614
+ ) -> Tuple:
615
+ """
616
+ Retrieve multiple node attributes using provided defaults.
617
+
618
+ :param graph:
619
+ Input graph.
620
+ :type graph: nx.Graph
621
+ :param node:
622
+ Node identifier.
623
+ :type node: Hashable
624
+ :param attributes_defaults:
625
+ Mapping from attribute names to fallback values.
626
+ :type attributes_defaults: Optional[Dict[str, Any]]
627
+
628
+ :returns:
629
+ Tuple of node attributes in mapping order.
630
+ :rtype: Tuple
631
+
632
+ Example
633
+ -------
634
+ .. code-block:: python
635
+
636
+ attrs = ITSConstruction.get_node_attributes_with_defaults(
637
+ graph=G,
638
+ node=1,
639
+ attributes_defaults={
640
+ "element": "*",
641
+ "aromatic": False,
642
+ "hcount": 0,
643
+ "charge": 0,
644
+ "neighbors": ["", ""],
645
+ },
646
+ )
647
+ """
648
+ if attributes_defaults is None:
649
+ attributes_defaults = {
650
+ "element": "*",
651
+ "aromatic": False,
652
+ "hcount": 0,
653
+ "charge": 0,
654
+ "neighbors": ["", ""],
655
+ }
656
+
657
+ return tuple(
658
+ ITSConstruction.get_node_attribute(graph, node, attr, default)
659
+ for attr, default in attributes_defaults.items()
660
+ )