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