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.
- {synkit-1.4.0 → synkit-1.4.2b1}/.gitignore +3 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/PKG-INFO +1 -1
- {synkit-1.4.0 → synkit-1.4.2b1}/pyproject.toml +1 -1
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/__init__.py +70 -0
- {synkit-1.4.0/synkit/Chem/Reaction → synkit-1.4.2b1/synkit/Chem/Reaction/Mapper}/aam_validator.py +145 -13
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/chem/__init__.py +46 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/chem/aam.py +439 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/chem/its.py +319 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/chem/smiles.py +524 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/__init__.py +58 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/branching.py +521 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/certificate.py +136 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/enumerate.py +1079 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/exhaustive.py +209 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/kernel.py +268 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/exact/milp.py +193 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/__init__.py +60 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/automorphism.py +113 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/blockcut.py +104 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/labeled_graph.py +104 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/refine.py +186 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/graph/synkit_adapter.py +110 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/io/__init__.py +13 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/io/idxmapstr.py +87 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/slap/__init__.py +22 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/slap/lap.py +185 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/Mapper/slap/sequential.py +691 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/__init__.py +6 -0
- synkit-1.4.2b1/synkit/Chem/Reaction/aam_validator.py +5 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/tautomerize.py +4 -1
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Hyrogen/_misc.py +22 -10
- synkit-1.4.2b1/synkit/Graph/Hyrogen/hcomplete.py +1014 -0
- synkit-1.4.2b1/synkit/Graph/Hyrogen/hextend.py +305 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_construction.py +2 -2
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_expand.py +55 -48
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/approx_mcs.py +95 -1075
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/mcs_matcher.py +72 -1
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/subgraph_matcher.py +4 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/wl_sel.py +1 -1
- synkit-1.4.2b1/synkit/Graph/Mech/__init__.py +26 -0
- synkit-1.4.2b1/synkit/Graph/Mech/electron_accounting.py +309 -0
- synkit-1.4.2b1/synkit/Graph/Mech/lwg_editor.py +403 -0
- synkit-1.4.2b1/synkit/Graph/Mech/lwg_ops.py +313 -0
- synkit-1.4.2b1/synkit/Graph/Wildcard/its_merge.py +869 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/chem_converter.py +21 -13
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/rbl_engine.py +876 -234
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/syn_reactor.py +23 -4
- synkit-1.4.2b1/synkit/Vis/__init__.py +89 -0
- synkit-1.4.2b1/synkit/Vis/crn/__init__.py +5 -0
- synkit-1.4.0/synkit/Vis/crn_vis.py → synkit-1.4.2b1/synkit/Vis/crn/visualizer.py +8 -2
- synkit-1.4.2b1/synkit/Vis/epd/__init__.py +20 -0
- synkit-1.4.2b1/synkit/Vis/epd/arrows.py +425 -0
- synkit-1.4.2b1/synkit/Vis/epd/chem.py +197 -0
- synkit-1.4.2b1/synkit/Vis/epd/constants.py +83 -0
- synkit-1.4.2b1/synkit/Vis/epd/layout.py +283 -0
- synkit-1.4.2b1/synkit/Vis/epd/mapping.py +51 -0
- synkit-1.4.2b1/synkit/Vis/epd/models.py +107 -0
- synkit-1.4.2b1/synkit/Vis/epd/render.py +528 -0
- synkit-1.4.2b1/synkit/Vis/epd/utils.py +108 -0
- synkit-1.4.2b1/synkit/Vis/epd/visualizer.py +826 -0
- synkit-1.4.2b1/synkit/Vis/its/__init__.py +19 -0
- synkit-1.4.0/synkit/Vis/its_drawer.py → synkit-1.4.2b1/synkit/Vis/its/drawer.py +3 -3
- synkit-1.4.2b1/synkit/Vis/molecule/__init__.py +31 -0
- synkit-1.4.0/synkit/Vis/reaction_drawer.py → synkit-1.4.2b1/synkit/Vis/molecule/reaction.py +1 -1
- synkit-1.4.2b1/synkit/Vis/mtg/__init__.py +17 -0
- synkit-1.4.0/synkit/Vis/mtg_drawer.py → synkit-1.4.2b1/synkit/Vis/mtg/drawer.py +1 -1
- synkit-1.4.2b1/synkit/Vis/reaction/__init__.py +19 -0
- synkit-1.4.0/synkit/Vis/rxn_vis.py → synkit-1.4.2b1/synkit/Vis/reaction/rxn.py +1 -1
- synkit-1.4.2b1/synkit/Vis/space/__init__.py +17 -0
- synkit-1.4.0/synkit/Vis/chemical_space.py → synkit-1.4.2b1/synkit/Vis/space/chemical.py +0 -3
- synkit-1.4.0/synkit/Chem/Reaction/Mapper/__init__.py +0 -8
- synkit-1.4.0/synkit/Chem/Reaction/Mapper/wl_mapper.py +0 -2345
- synkit-1.4.0/synkit/Chem/Reaction/__init__.py +0 -9
- synkit-1.4.0/synkit/Graph/Hyrogen/hcomplete.py +0 -353
- synkit-1.4.0/synkit/Graph/Hyrogen/hextend.py +0 -166
- synkit-1.4.0/synkit/Graph/Mech/electron_accounting.py +0 -64
- synkit-1.4.0/synkit/Graph/Wildcard/its_merge.py +0 -540
- synkit-1.4.0/synkit/Utils/__init__.py +0 -0
- synkit-1.4.0/synkit/Vis/__init__.py +0 -50
- synkit-1.4.0/synkit/Vis/vis_synedu/Vis/__init__.py +0 -7
- synkit-1.4.0/synkit/Vis/vis_synedu/Vis/dpo.py +0 -862
- synkit-1.4.0/synkit/Vis/vis_synedu/rxn_vis.py +0 -382
- synkit-1.4.0/synkit/Vis/vis_synedu/vis.py +0 -501
- {synkit-1.4.0 → synkit-1.4.2b1}/LICENSE +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/README.md +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/DAG/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/DAG/crn.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/DAG/mod_crn.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/DAG/syncrn.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/abstract.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/arity.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/builder.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/derivation.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/flattener.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/keys.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/mixtures.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/smiles.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/state.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/strategy.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Construct/worker.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/_adapter.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/pathfinder.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/reachability.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Pathway/realizability.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/analyzer.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/net.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/persistence.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/semiflows.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Petrinet/structure.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/dynamics.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/helper.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/stoich.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Props/thermo.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/kegg_api.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/kegg_extract.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/kegg_impute.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Query/kegg_parse.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/reaction.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/rule.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/species.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Structure/syncrn.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/_common.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/_ir.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/automorphism.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/canon.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/isomorphism.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/symmetry.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Symmetry/wl_canon.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/crn_vis.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/labels.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/layout.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/palette.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/validation.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/Visualize/vis.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/backend.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/conversion.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/hyperedge.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/hypergraph.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Structure/rxn.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Symmetry/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Symmetry/automorphism.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Symmetry/canon.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/Symmetry/wl_canon.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/configs/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/configs/loader.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/configs/models.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/constants.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/crn_formula.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/deficiency.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/enumerator.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/exceptions.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/explorer.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/helpers.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/injectivity.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/motif.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/network.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/pathway.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/properties.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/reaction.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/utils.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/CRN/dev_crn/viz.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Cluster/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Cluster/butina.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Fingerprint/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/atom_features.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/descriptors.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/formula.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/graph_annotator.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/standardize.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Molecule/valence.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/balance_check.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/canon_rsmi.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/cleaning.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/deionize.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/fix_aam.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/neutralize.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/radical_wildcard.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/Reaction/standardize.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Chem/utils.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Data/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Data/gen_partial_aam.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Canon/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Canon/canon_algs.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Canon/canon_graph.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Canon/nauty.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Context/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Context/hier_context.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Context/radius_expand.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/api.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/audit.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/catalog.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/detector.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/model.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/FG/ring_system.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/Descriptors/topology.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/graph_descriptors.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/graph_fps.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/graph_signature.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/hash_fps.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/morgan_fps.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/path_fps.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Feature/wl_hash.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Hyrogen/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_builder.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_decompose.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_destruction.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_relabel.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/its_reverter.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/normalize_aam.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/partial_its.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/ITS/rc_extractor.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/mcs_matcher.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/mtg.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/mtg_explore.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/MTG/utils.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/auto_est.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/automorphism.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/batch_cluster.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/dedup_matches.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/graph_cluster.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/graph_matcher.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/graph_morphism.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/multi_turbo_iso.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/orbit.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/partial_matcher.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/sing.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Matcher/turbo_iso.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Mech/conversion.py +0 -0
- {synkit-1.4.0/synkit/Graph/Mech → synkit-1.4.2b1/synkit/Graph/Wildcard}/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/fuse_graph.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/graph_wc.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/radwc.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/wc_matcher.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/Wildcard/wildcard.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/canon_graph.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/syn_graph.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Graph/utils.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/gml_to_graph.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/graph_to_gml.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/graph_to_smarts.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/smarts_expander.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/smarts_generalizer.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/combinatorial/smarts_to_graph.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/data_io.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/data_process.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/debug.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/dg_to_gml.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/gml_to_nx.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/graph_to_mol.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/mol_to_graph.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/nx_to_gml.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/IO/smiles_to_id.py +0 -0
- {synkit-1.4.0/synkit/Graph/Wildcard → synkit-1.4.2b1/synkit/Rule/Apply}/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Apply/reactor_rule.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Apply/retro_reactor.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Apply/rule_matcher.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Apply/rule_rbl.py +0 -0
- {synkit-1.4.0/synkit/Rule/Apply → synkit-1.4.2b1/synkit/Rule/Compose}/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/compose_rule.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/rule_compose.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/rule_mapping.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/seq_comp.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Compose/valence_constrain.py +0 -0
- {synkit-1.4.0/synkit/Rule/Compose → synkit-1.4.2b1/synkit/Rule/Modify}/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/implict_rule.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/longest_path.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/molecule_rule.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/prune_templates.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/rule_utils.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/Modify/strip_rule.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Rule/syn_rule.py +0 -0
- {synkit-1.4.0/synkit/Rule/Modify → synkit-1.4.2b1/synkit/Synthesis/MSR}/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/MSR/multi_steps.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/MSR/path_finder.py +0 -0
- {synkit-1.4.0/synkit/Synthesis/MSR → synkit-1.4.2b1/synkit/Synthesis/Metrics}/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Metrics/_base.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Metrics/_plot.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Metrics/_ranking.py +0 -0
- {synkit-1.4.0/synkit/Synthesis/Metrics → synkit-1.4.2b1/synkit/Synthesis/Reactor}/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/batch_reactor.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/benchmark.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/imba_engine.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/mod_aam.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/mod_reactor.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/partial_engine.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/post_syn.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/rule_filter.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/single_predictor.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/Reactor/strategy.py +0 -0
- {synkit-1.4.0/synkit/Synthesis/Reactor → synkit-1.4.2b1/synkit/Synthesis}/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Synthesis/reactor_utils.py +0 -0
- {synkit-1.4.0/synkit/Synthesis → synkit-1.4.2b1/synkit/Utils}/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Utils/utils.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Vis/graph_visualizer.py +0 -0
- /synkit-1.4.0/synkit/Vis/molecule_drawer.py → /synkit-1.4.2b1/synkit/Vis/molecule/drawer.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Vis/pdf_writer.py +0 -0
- /synkit-1.4.0/synkit/Vis/rule_vis.py → /synkit-1.4.2b1/synkit/Vis/reaction/rule.py +0 -0
- {synkit-1.4.0/synkit/Vis → synkit-1.4.2b1/synkit/Vis/space}/embedding.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Vis/visual_drawer.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/Vis/visual_model.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/__init__.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/examples.py +0 -0
- {synkit-1.4.0 → synkit-1.4.2b1}/synkit/version.py +0 -0
|
@@ -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
|
+
]
|
{synkit-1.4.0/synkit/Chem/Reaction → synkit-1.4.2b1/synkit/Chem/Reaction/Mapper}/aam_validator.py
RENAMED
|
@@ -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
|
-
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
|
|
142
|
-
mapped_smile,
|
|
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
|
-
@
|
|
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
|
|
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
|
|
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
|
-
@
|
|
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(
|
|
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
|
+
]
|