synkit 1.3.2__tar.gz → 1.3.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.3.2 → synkit-1.3.2b1}/.gitignore +5 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/PKG-INFO +1 -1
- {synkit-1.3.2 → synkit-1.3.2b1}/pyproject.toml +1 -1
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/tautomerize.py +50 -7
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Canon/canon_graph.py +2 -2
- synkit-1.3.2b1/synkit/Graph/FG/__init__.py +19 -0
- synkit-1.3.2b1/synkit/Graph/FG/api.py +39 -0
- synkit-1.3.2b1/synkit/Graph/FG/audit.py +155 -0
- synkit-1.3.2b1/synkit/Graph/FG/catalog.py +1168 -0
- synkit-1.3.2b1/synkit/Graph/FG/detector.py +288 -0
- synkit-1.3.2b1/synkit/Graph/FG/model.py +97 -0
- synkit-1.3.2b1/synkit/Graph/FG/ring_system.py +154 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Hyrogen/_misc.py +78 -7
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/its_construction.py +14 -1
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/its_destruction.py +25 -3
- synkit-1.3.2b1/synkit/Graph/ITS/its_expand.py +444 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/its_reverter.py +7 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/rc_extractor.py +24 -2
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/MTG/mtg.py +377 -39
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/graph_matcher.py +34 -15
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/subgraph_matcher.py +127 -11
- synkit-1.3.2b1/synkit/Graph/Mech/conversion.py +1305 -0
- synkit-1.3.2b1/synkit/Graph/Mech/electron_accounting.py +64 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/canon_graph.py +12 -3
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/utils.py +31 -1
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/chem_converter.py +85 -10
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/graph_to_mol.py +2 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/mol_to_graph.py +28 -7
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Apply/rule_matcher.py +26 -3
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/syn_rule.py +135 -28
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/imba_engine.py +10 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/partial_engine.py +15 -1
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/rbl_engine.py +21 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/rule_filter.py +11 -1
- synkit-1.3.2b1/synkit/Synthesis/Reactor/syn_reactor.py +1429 -0
- synkit-1.3.2b1/synkit/Utils/__init__.py +0 -0
- synkit-1.3.2b1/synkit/Vis/__init__.py +47 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Vis/graph_visualizer.py +1 -1
- synkit-1.3.2b1/synkit/Vis/its_drawer.py +615 -0
- synkit-1.3.2b1/synkit/Vis/molecule_drawer.py +565 -0
- synkit-1.3.2b1/synkit/Vis/reaction_drawer.py +285 -0
- synkit-1.3.2b1/synkit/Vis/vis_synedu/Vis/__init__.py +7 -0
- synkit-1.3.2b1/synkit/Vis/vis_synedu/Vis/dpo.py +862 -0
- synkit-1.3.2b1/synkit/Vis/vis_synedu/rxn_vis.py +382 -0
- synkit-1.3.2b1/synkit/Vis/vis_synedu/vis.py +501 -0
- synkit-1.3.2b1/synkit/Vis/visual_drawer.py +215 -0
- synkit-1.3.2b1/synkit/Vis/visual_model.py +520 -0
- synkit-1.3.2/synkit/Graph/ITS/its_expand.py +0 -86
- synkit-1.3.2/synkit/Graph/MTG/group_comp.py +0 -157
- synkit-1.3.2/synkit/Graph/MTG/groupoid.py +0 -358
- synkit-1.3.2/synkit/Synthesis/Reactor/syn_reactor.py +0 -638
- synkit-1.3.2/synkit/Vis/__init__.py +0 -5
- {synkit-1.3.2 → synkit-1.3.2b1}/LICENSE +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/README.md +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/DAG/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/DAG/crn.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/DAG/mod_crn.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/DAG/syncrn.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/abstract.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/arity.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/builder.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/derivation.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/flattener.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/keys.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/mixtures.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/smiles.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/state.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/strategy.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Construct/worker.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Pathway/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Pathway/_adapter.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Pathway/pathfinder.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Pathway/reachability.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Pathway/realizability.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Petrinet/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Petrinet/analyzer.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Petrinet/net.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Petrinet/persistence.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Petrinet/semiflows.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Petrinet/structure.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Props/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Props/dynamics.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Props/helper.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Props/stoich.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Props/thermo.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Query/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Query/kegg_api.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Query/kegg_extract.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Query/kegg_impute.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Query/kegg_parse.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Structure/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Structure/reaction.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Structure/rule.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Structure/species.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Structure/syncrn.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Symmetry/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Symmetry/_common.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Symmetry/_ir.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Symmetry/automorphism.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Symmetry/canon.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Symmetry/isomorphism.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Symmetry/symmetry.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Symmetry/wl_canon.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Visualize/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Visualize/crn_vis.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Visualize/labels.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Visualize/layout.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Visualize/palette.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Visualize/validation.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/Visualize/vis.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Structure/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Structure/backend.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Structure/conversion.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Structure/hyperedge.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Structure/hypergraph.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Structure/rxn.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Symmetry/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Symmetry/automorphism.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Symmetry/canon.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/Symmetry/wl_canon.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/configs/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/configs/loader.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/configs/models.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/constants.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/crn_formula.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/deficiency.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/enumerator.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/exceptions.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/explorer.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/helpers.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/injectivity.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/motif.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/network.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/pathway.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/properties.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/reaction.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/utils.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/CRN/dev_crn/viz.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Cluster/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Cluster/butina.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Fingerprint/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Molecule/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Molecule/atom_features.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Molecule/descriptors.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Molecule/formula.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Molecule/graph_annotator.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Molecule/standardize.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Molecule/valence.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/Mapper/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/Mapper/wl_mapper.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/aam_validator.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/balance_check.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/canon_rsmi.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/cleaning.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/deionize.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/fix_aam.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/neutralize.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/radical_wildcard.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/Reaction/standardize.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Chem/utils.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Data/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Data/gen_partial_aam.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Canon/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Canon/canon_algs.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Canon/nauty.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Context/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Context/hier_context.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Context/radius_expand.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/Descriptors/topology.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/graph_descriptors.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/graph_fps.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/graph_signature.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/hash_fps.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/morgan_fps.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/path_fps.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Feature/wl_hash.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Hyrogen/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Hyrogen/hcomplete.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Hyrogen/hextend.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/its_builder.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/its_decompose.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/its_relabel.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/normalize_aam.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/ITS/partial_its.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/MTG/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/MTG/mcs_matcher.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/MTG/mtg_explore.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/MTG/utils.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/approx_mcs.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/auto_est.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/automorphism.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/batch_cluster.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/dedup_matches.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/graph_cluster.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/graph_morphism.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/mcs_matcher.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/multi_turbo_iso.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/orbit.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/partial_matcher.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/sing.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/turbo_iso.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Matcher/wl_sel.py +0 -0
- {synkit-1.3.2/synkit/Graph/Wildcard → synkit-1.3.2b1/synkit/Graph/Mech}/__init__.py +0 -0
- {synkit-1.3.2/synkit/Rule/Apply → synkit-1.3.2b1/synkit/Graph/Wildcard}/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Wildcard/fuse_graph.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Wildcard/graph_wc.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Wildcard/its_merge.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Wildcard/radwc.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Wildcard/wc_matcher.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/Wildcard/wildcard.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Graph/syn_graph.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/combinatorial/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/combinatorial/gml_to_graph.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/combinatorial/graph_to_gml.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/combinatorial/graph_to_smarts.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/combinatorial/smarts_expander.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/combinatorial/smarts_generalizer.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/combinatorial/smarts_to_graph.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/data_io.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/data_process.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/debug.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/dg_to_gml.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/gml_to_nx.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/nx_to_gml.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/IO/smiles_to_id.py +0 -0
- {synkit-1.3.2/synkit/Rule/Compose → synkit-1.3.2b1/synkit/Rule/Apply}/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Apply/reactor_rule.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Apply/retro_reactor.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Apply/rule_rbl.py +0 -0
- {synkit-1.3.2/synkit/Rule/Modify → synkit-1.3.2b1/synkit/Rule/Compose}/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Compose/compose_rule.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Compose/rule_compose.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Compose/rule_mapping.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Compose/seq_comp.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Compose/valence_constrain.py +0 -0
- {synkit-1.3.2/synkit/Synthesis/MSR → synkit-1.3.2b1/synkit/Rule/Modify}/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Modify/implict_rule.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Modify/longest_path.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Modify/molecule_rule.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Modify/prune_templates.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Modify/rule_utils.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/Modify/strip_rule.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Rule/__init__.py +0 -0
- {synkit-1.3.2/synkit/Synthesis/Metrics → synkit-1.3.2b1/synkit/Synthesis/MSR}/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/MSR/multi_steps.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/MSR/path_finder.py +0 -0
- {synkit-1.3.2/synkit/Synthesis/Reactor → synkit-1.3.2b1/synkit/Synthesis/Metrics}/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Metrics/_base.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Metrics/_plot.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Metrics/_ranking.py +0 -0
- {synkit-1.3.2/synkit/Synthesis → synkit-1.3.2b1/synkit/Synthesis/Reactor}/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/batch_reactor.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/benchmark.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/mod_aam.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/mod_reactor.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/post_syn.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/single_predictor.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/Reactor/strategy.py +0 -0
- {synkit-1.3.2/synkit/Utils → synkit-1.3.2b1/synkit/Synthesis}/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Synthesis/reactor_utils.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Utils/utils.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Vis/chemical_space.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Vis/crn_vis.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Vis/embedding.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Vis/pdf_writer.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Vis/rule_vis.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/Vis/rxn_vis.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/__init__.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/examples.py +0 -0
- {synkit-1.3.2 → synkit-1.3.2b1}/synkit/version.py +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from typing import List, Dict, Optional
|
|
2
2
|
from rdkit import Chem
|
|
3
|
-
from fgutils import FGQuery
|
|
4
3
|
from joblib import Parallel, delayed
|
|
5
4
|
|
|
5
|
+
from synkit.Graph.FG import smiles_to_graph_and_functional_groups
|
|
6
|
+
|
|
6
7
|
|
|
7
8
|
class Tautomerize:
|
|
8
9
|
"""Standardize molecules by converting enol and hemiketal tautomers into
|
|
@@ -103,18 +104,60 @@ class Tautomerize:
|
|
|
103
104
|
:returns: Canonical SMILES of the standardized molecule.
|
|
104
105
|
:rtype: str
|
|
105
106
|
"""
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
while True:
|
|
108
|
+
targets = Tautomerize._tautomer_targets(smiles)
|
|
109
|
+
if not targets:
|
|
110
|
+
break
|
|
111
|
+
label, indices = targets[0]
|
|
110
112
|
if label == "hemiketal":
|
|
111
113
|
smiles = Tautomerize.standardize_hemiketal(smiles, indices)
|
|
112
|
-
fg = query.get(smiles)
|
|
113
114
|
elif label == "enol":
|
|
114
115
|
smiles = Tautomerize.standardize_enol(smiles, indices)
|
|
115
|
-
fg = query.get(smiles)
|
|
116
116
|
return Chem.CanonSmiles(smiles)
|
|
117
117
|
|
|
118
|
+
@staticmethod
|
|
119
|
+
def _tautomer_targets(smiles: str) -> list[tuple[str, List[int]]]:
|
|
120
|
+
"""Return RDKit-index targets used by the tautomer repair helpers."""
|
|
121
|
+
mol = Chem.MolFromSmiles(smiles)
|
|
122
|
+
if mol is None:
|
|
123
|
+
return []
|
|
124
|
+
graph, groups = smiles_to_graph_and_functional_groups(smiles)
|
|
125
|
+
node_to_idx = {
|
|
126
|
+
(
|
|
127
|
+
atom.GetAtomMapNum() if atom.GetAtomMapNum() else atom.GetIdx() + 1
|
|
128
|
+
): atom.GetIdx()
|
|
129
|
+
for atom in mol.GetAtoms()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
targets = [
|
|
133
|
+
(label, [node_to_idx[node] for node in nodes])
|
|
134
|
+
for label, nodes in groups
|
|
135
|
+
if label in {"hemiketal", "enol"}
|
|
136
|
+
]
|
|
137
|
+
targets.extend(
|
|
138
|
+
("hemiketal", [node_to_idx[node] for node in nodes])
|
|
139
|
+
for nodes in Tautomerize._geminal_diol_nodes(graph)
|
|
140
|
+
)
|
|
141
|
+
return targets
|
|
142
|
+
|
|
143
|
+
@staticmethod
|
|
144
|
+
def _geminal_diol_nodes(graph) -> list[tuple[int, ...]]:
|
|
145
|
+
"""Legacy tautomerization compatibility for hydrated carbonyls."""
|
|
146
|
+
targets: list[tuple[int, ...]] = []
|
|
147
|
+
for carbon, data in graph.nodes(data=True):
|
|
148
|
+
if data.get("element") != "C":
|
|
149
|
+
continue
|
|
150
|
+
hydroxyls = [
|
|
151
|
+
neighbor
|
|
152
|
+
for neighbor in graph.neighbors(carbon)
|
|
153
|
+
if graph.nodes[neighbor].get("element") == "O"
|
|
154
|
+
and graph.nodes[neighbor].get("hcount", 0) >= 1
|
|
155
|
+
and graph.edges[carbon, neighbor].get("order") == 1.0
|
|
156
|
+
]
|
|
157
|
+
if len(hydroxyls) >= 2:
|
|
158
|
+
targets.append((carbon, hydroxyls[0], hydroxyls[1]))
|
|
159
|
+
return targets
|
|
160
|
+
|
|
118
161
|
@staticmethod
|
|
119
162
|
def fix_dict(data: Dict[str, str], reaction_column: str) -> Dict[str, str]:
|
|
120
163
|
"""Standardize the reactant and product SMILES in a reaction
|
|
@@ -316,8 +316,8 @@ class GraphCanonicaliser:
|
|
|
316
316
|
nodes = sorted(g.nodes(data=True), key=lambda x: self._node_key(*x))
|
|
317
317
|
edges = sorted(g.edges(data=True), key=lambda x: self._edge_key(*x))
|
|
318
318
|
|
|
319
|
-
node_str = ";".join(f"{n}:{self._node_key(n,d)}" for n, d in nodes)
|
|
320
|
-
edge_str = ";".join(f"{(u,v)}:{self._edge_key(u,v,d)}" for u, v, d in edges)
|
|
319
|
+
node_str = ";".join(f"{n}:{self._node_key(n, d)}" for n, d in nodes)
|
|
320
|
+
edge_str = ";".join(f"{(u, v)}:{self._edge_key(u, v, d)}" for u, v, d in edges)
|
|
321
321
|
return f"N[{node_str}]|E[{edge_str}]"
|
|
322
322
|
|
|
323
323
|
# ------------------------------------------------------------------ #
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Functional-group detection on SynKit molecular graphs."""
|
|
2
|
+
|
|
3
|
+
from .catalog import default_registry
|
|
4
|
+
from .audit import FunctionalGroupAudit, audit_reaction_smiles
|
|
5
|
+
from .api import FunctionalGroupLabels, smiles_to_graph_and_functional_groups
|
|
6
|
+
from .detector import FunctionalGroupDetector
|
|
7
|
+
from .model import FunctionalGroupMatch, FunctionalGroupPattern, FunctionalGroupRegistry
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"FunctionalGroupDetector",
|
|
11
|
+
"FunctionalGroupLabels",
|
|
12
|
+
"FunctionalGroupAudit",
|
|
13
|
+
"FunctionalGroupMatch",
|
|
14
|
+
"FunctionalGroupPattern",
|
|
15
|
+
"FunctionalGroupRegistry",
|
|
16
|
+
"default_registry",
|
|
17
|
+
"audit_reaction_smiles",
|
|
18
|
+
"smiles_to_graph_and_functional_groups",
|
|
19
|
+
]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import networkx as nx
|
|
4
|
+
|
|
5
|
+
from synkit.IO.chem_converter import smiles_to_graph
|
|
6
|
+
|
|
7
|
+
from .detector import FunctionalGroupDetector
|
|
8
|
+
|
|
9
|
+
FunctionalGroupLabels = list[tuple[str, tuple[int, ...]]]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def smiles_to_graph_and_functional_groups(
|
|
13
|
+
smiles: str,
|
|
14
|
+
*,
|
|
15
|
+
sanitize: bool = True,
|
|
16
|
+
) -> tuple[nx.Graph, FunctionalGroupLabels]:
|
|
17
|
+
"""Convert SMILES to a molecular graph and detect functional groups.
|
|
18
|
+
|
|
19
|
+
Atom-mapped SMILES keep their non-zero atom-map numbers as graph node IDs.
|
|
20
|
+
Unmapped atoms use their 1-based atom order as node IDs, so both mapped and
|
|
21
|
+
unmapped SMILES can be passed to the same API.
|
|
22
|
+
|
|
23
|
+
:param smiles: Input SMILES, with or without atom-map labels.
|
|
24
|
+
:type smiles: str
|
|
25
|
+
:param sanitize: If ``True``, sanitize the RDKit molecule during conversion.
|
|
26
|
+
:type sanitize: bool
|
|
27
|
+
:return: Molecular graph and detected ``(name, node_ids)`` FG labels.
|
|
28
|
+
:rtype: tuple[nx.Graph, list[tuple[str, tuple[int, ...]]]]
|
|
29
|
+
:raises ValueError: If the SMILES cannot be converted to a molecular graph.
|
|
30
|
+
"""
|
|
31
|
+
graph = smiles_to_graph(
|
|
32
|
+
smiles,
|
|
33
|
+
drop_non_aam=False,
|
|
34
|
+
sanitize=sanitize,
|
|
35
|
+
use_index_as_atom_map=True,
|
|
36
|
+
)
|
|
37
|
+
if graph is None:
|
|
38
|
+
raise ValueError(f"Could not convert SMILES to molecular graph: {smiles!r}")
|
|
39
|
+
return graph, FunctionalGroupDetector().detect(graph)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections import Counter
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from time import perf_counter
|
|
6
|
+
from typing import Iterable
|
|
7
|
+
|
|
8
|
+
import networkx as nx
|
|
9
|
+
|
|
10
|
+
from synkit.Chem.Reaction.standardize import Standardize
|
|
11
|
+
from synkit.IO.chem_converter import smiles_to_graph
|
|
12
|
+
|
|
13
|
+
from .detector import FunctionalGroupDetector
|
|
14
|
+
from .ring_system import AromaticRingSystemDetector
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class FunctionalGroupAudit:
|
|
19
|
+
"""Aggregated detector coverage over a reaction-SMILES corpus."""
|
|
20
|
+
|
|
21
|
+
reactions: int
|
|
22
|
+
molecules: int
|
|
23
|
+
parse_failures: int
|
|
24
|
+
elapsed_seconds: float
|
|
25
|
+
label_counts: Counter[str]
|
|
26
|
+
heteroaromatic_systems: int
|
|
27
|
+
named_heteroaromatic_systems: int
|
|
28
|
+
unnamed_heteroaromatic_systems: Counter[tuple]
|
|
29
|
+
uncovered_atom_signatures: Counter[tuple]
|
|
30
|
+
uncovered_edge_signatures: Counter[tuple]
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def unnamed_heteroaromatic_count(self) -> int:
|
|
34
|
+
return self.heteroaromatic_systems - self.named_heteroaromatic_systems
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def audit_reaction_smiles(
|
|
38
|
+
reactions: Iterable[str],
|
|
39
|
+
*,
|
|
40
|
+
standardizer: Standardize | None = None,
|
|
41
|
+
) -> FunctionalGroupAudit:
|
|
42
|
+
"""Audit FG coverage for an iterable of reaction SMILES strings."""
|
|
43
|
+
std = Standardize() if standardizer is None else standardizer
|
|
44
|
+
detector = FunctionalGroupDetector()
|
|
45
|
+
|
|
46
|
+
reaction_count = 0
|
|
47
|
+
molecule_count = 0
|
|
48
|
+
parse_failures = 0
|
|
49
|
+
heteroaromatic_systems = 0
|
|
50
|
+
named_heteroaromatic_systems = 0
|
|
51
|
+
label_counts: Counter[str] = Counter()
|
|
52
|
+
unnamed_systems: Counter[tuple] = Counter()
|
|
53
|
+
uncovered_atoms: Counter[tuple] = Counter()
|
|
54
|
+
uncovered_edges: Counter[tuple] = Counter()
|
|
55
|
+
|
|
56
|
+
started = perf_counter()
|
|
57
|
+
for reaction in reactions:
|
|
58
|
+
reaction_count += 1
|
|
59
|
+
standardized = std.fit(reaction, remove_aam=True)
|
|
60
|
+
for side in standardized.split(">>"):
|
|
61
|
+
for smiles in side.split("."):
|
|
62
|
+
graph = smiles_to_graph(
|
|
63
|
+
smiles,
|
|
64
|
+
drop_non_aam=False,
|
|
65
|
+
use_index_as_atom_map=True,
|
|
66
|
+
)
|
|
67
|
+
if graph is None:
|
|
68
|
+
parse_failures += 1
|
|
69
|
+
continue
|
|
70
|
+
molecule_count += 1
|
|
71
|
+
matches = detector.matches(graph)
|
|
72
|
+
label_counts.update(match.name for match in matches)
|
|
73
|
+
covered = {node for match in matches for node in match.group_nodes}
|
|
74
|
+
_count_uncovered_signatures(
|
|
75
|
+
graph,
|
|
76
|
+
covered,
|
|
77
|
+
uncovered_atoms,
|
|
78
|
+
uncovered_edges,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
named_ring_nodes = {
|
|
82
|
+
match.group_nodes
|
|
83
|
+
for match in matches
|
|
84
|
+
if match.name != "heteroaromatic_ring"
|
|
85
|
+
and match.pattern.priority == 70
|
|
86
|
+
}
|
|
87
|
+
for system in AromaticRingSystemDetector.detect(graph):
|
|
88
|
+
if not system.hetero_nodes:
|
|
89
|
+
continue
|
|
90
|
+
heteroaromatic_systems += 1
|
|
91
|
+
has_named_subring = any(
|
|
92
|
+
set(nodes).issubset(system.nodes) for nodes in named_ring_nodes
|
|
93
|
+
)
|
|
94
|
+
if has_named_subring:
|
|
95
|
+
named_heteroaromatic_systems += 1
|
|
96
|
+
continue
|
|
97
|
+
unnamed_systems[
|
|
98
|
+
(
|
|
99
|
+
system.hetero_pattern,
|
|
100
|
+
system.is_fused,
|
|
101
|
+
system.ring_sizes,
|
|
102
|
+
tuple(sorted(system.element_counts.items())),
|
|
103
|
+
)
|
|
104
|
+
] += 1
|
|
105
|
+
|
|
106
|
+
return FunctionalGroupAudit(
|
|
107
|
+
reactions=reaction_count,
|
|
108
|
+
molecules=molecule_count,
|
|
109
|
+
parse_failures=parse_failures,
|
|
110
|
+
elapsed_seconds=perf_counter() - started,
|
|
111
|
+
label_counts=label_counts,
|
|
112
|
+
heteroaromatic_systems=heteroaromatic_systems,
|
|
113
|
+
named_heteroaromatic_systems=named_heteroaromatic_systems,
|
|
114
|
+
unnamed_heteroaromatic_systems=unnamed_systems,
|
|
115
|
+
uncovered_atom_signatures=uncovered_atoms,
|
|
116
|
+
uncovered_edge_signatures=uncovered_edges,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _count_uncovered_signatures(
|
|
121
|
+
graph: nx.Graph,
|
|
122
|
+
covered: set[int],
|
|
123
|
+
atom_counts: Counter[tuple],
|
|
124
|
+
edge_counts: Counter[tuple],
|
|
125
|
+
) -> None:
|
|
126
|
+
for node, data in graph.nodes(data=True):
|
|
127
|
+
if data.get("element") == "H" or node in covered:
|
|
128
|
+
continue
|
|
129
|
+
neighbors = tuple(
|
|
130
|
+
sorted(
|
|
131
|
+
graph.nodes[neighbor].get("element")
|
|
132
|
+
for neighbor in graph.neighbors(node)
|
|
133
|
+
if graph.nodes[neighbor].get("element") != "H"
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
atom_counts[
|
|
137
|
+
(
|
|
138
|
+
data.get("element"),
|
|
139
|
+
data.get("aromatic", False),
|
|
140
|
+
data.get("hcount", 0),
|
|
141
|
+
neighbors,
|
|
142
|
+
)
|
|
143
|
+
] += 1
|
|
144
|
+
|
|
145
|
+
for left, right, data in graph.edges(data=True):
|
|
146
|
+
if left in covered or right in covered:
|
|
147
|
+
continue
|
|
148
|
+
left_element = graph.nodes[left].get("element")
|
|
149
|
+
right_element = graph.nodes[right].get("element")
|
|
150
|
+
if "H" in {left_element, right_element}:
|
|
151
|
+
continue
|
|
152
|
+
edge_counts[
|
|
153
|
+
tuple(sorted((left_element, right_element)))
|
|
154
|
+
+ (data.get("order"), data.get("aromatic", False))
|
|
155
|
+
] += 1
|