synkit 1.6.5__py3-none-win_amd64.whl
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/CRN/Benchmark/__init__.py +53 -0
- synkit/CRN/Benchmark/crosschecks.py +13 -0
- synkit/CRN/Benchmark/kegg.py +12 -0
- synkit/CRN/Benchmark/networks.py +13 -0
- synkit/CRN/Benchmark/scaling.py +13 -0
- synkit/CRN/Benchmark/validate.py +13 -0
- synkit/CRN/Construct/__init__.py +16 -0
- synkit/CRN/Construct/abstract.py +668 -0
- synkit/CRN/Construct/arity.py +36 -0
- synkit/CRN/Construct/builder.py +619 -0
- synkit/CRN/Construct/derivation.py +63 -0
- synkit/CRN/Construct/flattener.py +100 -0
- synkit/CRN/Construct/keys.py +14 -0
- synkit/CRN/Construct/mixtures.py +117 -0
- synkit/CRN/Construct/rdkit_worker.py +69 -0
- synkit/CRN/Construct/smiles.py +99 -0
- synkit/CRN/Construct/state.py +31 -0
- synkit/CRN/Construct/strategy.py +75 -0
- synkit/CRN/Construct/worker.py +42 -0
- synkit/CRN/IO/__init__.py +36 -0
- synkit/CRN/IO/sbml.py +925 -0
- synkit/CRN/Pathway/__init__.py +72 -0
- synkit/CRN/Pathway/_adapter.py +333 -0
- synkit/CRN/Pathway/pathfinder.py +500 -0
- synkit/CRN/Pathway/reachability.py +796 -0
- synkit/CRN/Pathway/realizability.py +1322 -0
- synkit/CRN/Petrinet/__init__.py +93 -0
- synkit/CRN/Petrinet/analyzer.py +486 -0
- synkit/CRN/Petrinet/minimal_semiflows.py +436 -0
- synkit/CRN/Petrinet/net.py +1041 -0
- synkit/CRN/Petrinet/persistence.py +97 -0
- synkit/CRN/Petrinet/semiflows.py +483 -0
- synkit/CRN/Petrinet/siphon_search.py +402 -0
- synkit/CRN/Petrinet/structure.py +286 -0
- synkit/CRN/Props/__init__.py +130 -0
- synkit/CRN/Props/_rank.py +29 -0
- synkit/CRN/Props/deficiency.py +953 -0
- synkit/CRN/Props/dynamics.py +832 -0
- synkit/CRN/Props/helper.py +151 -0
- synkit/CRN/Props/stoich.py +751 -0
- synkit/CRN/Props/thermo.py +584 -0
- synkit/CRN/Query/__init__.py +66 -0
- synkit/CRN/Query/cache.py +41 -0
- synkit/CRN/Query/kegg_api.py +99 -0
- synkit/CRN/Query/kegg_extract.py +714 -0
- synkit/CRN/Query/kegg_impute.py +707 -0
- synkit/CRN/Query/kegg_parse.py +480 -0
- synkit/CRN/Query/to_syncrn.py +290 -0
- synkit/CRN/README.md +234 -0
- synkit/CRN/Structure/__init__.py +12 -0
- synkit/CRN/Structure/_graph_io.py +713 -0
- synkit/CRN/Structure/_matrices.py +88 -0
- synkit/CRN/Structure/_parse.py +544 -0
- synkit/CRN/Structure/reaction.py +237 -0
- synkit/CRN/Structure/rule.py +55 -0
- synkit/CRN/Structure/species.py +46 -0
- synkit/CRN/Structure/syncrn.py +929 -0
- synkit/CRN/Symmetry/__init__.py +20 -0
- synkit/CRN/Symmetry/_common.py +1059 -0
- synkit/CRN/Symmetry/_ir.py +940 -0
- synkit/CRN/Symmetry/automorphism.py +472 -0
- synkit/CRN/Symmetry/canon.py +441 -0
- synkit/CRN/Symmetry/isomorphism.py +412 -0
- synkit/CRN/Symmetry/symmetry.py +61 -0
- synkit/CRN/Symmetry/wl_canon.py +967 -0
- synkit/CRN/Visualize/__init__.py +11 -0
- synkit/CRN/Visualize/labels.py +113 -0
- synkit/CRN/Visualize/layout.py +708 -0
- synkit/CRN/Visualize/palette.py +292 -0
- synkit/CRN/Visualize/validation.py +122 -0
- synkit/CRN/Visualize/vis.py +1152 -0
- synkit/CRN/__init__.py +233 -0
- synkit/CRN/_build.py +50 -0
- synkit/CRN/_native_build.py +175 -0
- synkit/CRN/analysis.py +629 -0
- synkit/CRN/backend.py +74 -0
- synkit/CRN/cpp/CMakeLists.txt +58 -0
- synkit/CRN/cpp/algebra.cpp +46 -0
- synkit/CRN/cpp/closure.cpp +29 -0
- synkit/CRN/cpp/exact.h +55 -0
- synkit/CRN/cpp/pathway.cpp +46 -0
- synkit/CRN/cpp/semiflows.cpp +209 -0
- synkit/CRN/cpp/structural.cpp +240 -0
- synkit/CRN/cpp/symmetry.cpp +45 -0
- synkit/CRN/cpp/write_manifest.cmake +28 -0
- synkit/CRN/kinds.py +137 -0
- synkit/CRN/lib/synkit_crn.dll +0 -0
- synkit/CRN/lib/synkit_crn.json +33 -0
- synkit/CRN/native.py +388 -0
- synkit/CRN/native_analysis.py +459 -0
- synkit/Chem/Cluster/__init__.py +0 -0
- synkit/Chem/Cluster/butina.py +140 -0
- synkit/Chem/Fingerprint/__init__.py +0 -0
- synkit/Chem/Fingerprint/fp_calculator.py +155 -0
- synkit/Chem/Fingerprint/smiles_featurizer.py +258 -0
- synkit/Chem/Fingerprint/transformation_fp.py +139 -0
- synkit/Chem/Mapper/README.rst +43 -0
- synkit/Chem/Mapper/__init__.py +255 -0
- synkit/Chem/Mapper/_compat.py +130 -0
- synkit/Chem/Mapper/adapters/__init__.py +1 -0
- synkit/Chem/Mapper/adapters/prediction.py +126 -0
- synkit/Chem/Mapper/adapters/template.py +412 -0
- synkit/Chem/Mapper/chem/__init__.py +52 -0
- synkit/Chem/Mapper/chem/aam.py +673 -0
- synkit/Chem/Mapper/chem/blind.py +160 -0
- synkit/Chem/Mapper/chem/its.py +309 -0
- synkit/Chem/Mapper/chem/smiles.py +564 -0
- synkit/Chem/Mapper/graph/__init__.py +66 -0
- synkit/Chem/Mapper/graph/automorphism.py +395 -0
- synkit/Chem/Mapper/graph/blockcut.py +98 -0
- synkit/Chem/Mapper/graph/labeled_graph.py +104 -0
- synkit/Chem/Mapper/graph/refine.py +176 -0
- synkit/Chem/Mapper/graph/synkit_adapter.py +110 -0
- synkit/Chem/Mapper/io/__init__.py +13 -0
- synkit/Chem/Mapper/io/idxmapstr.py +82 -0
- synkit/Chem/Mapper/mapper.py +685 -0
- synkit/Chem/Mapper/reaction_search.py +554 -0
- synkit/Chem/Mapper/reporting/__init__.py +1 -0
- synkit/Chem/Mapper/reporting/alternatives.py +451 -0
- synkit/Chem/Mapper/reporting/analysis.py +681 -0
- synkit/Chem/Mapper/reporting/native_analysis.py +485 -0
- synkit/Chem/Mapper/reporting/spectrum.py +642 -0
- synkit/Chem/Mapper/solvers/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/__init__.py +141 -0
- synkit/Chem/Mapper/solvers/exact/assignment/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/assignment/assignment_certificate.py +113 -0
- synkit/Chem/Mapper/solvers/exact/assignment/assignment_domains.py +162 -0
- synkit/Chem/Mapper/solvers/exact/assignment/assignment_verification.py +58 -0
- synkit/Chem/Mapper/solvers/exact/assignment/incremental_assignment.py +247 -0
- synkit/Chem/Mapper/solvers/exact/certificate.py +128 -0
- synkit/Chem/Mapper/solvers/exact/core.py +183 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/bounds.py +319 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/exhaustive.py +179 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/inputs.py +283 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/records.py +242 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/search.py +1025 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/verify.py +378 -0
- synkit/Chem/Mapper/solvers/exact/edit_support.py +375 -0
- synkit/Chem/Mapper/solvers/exact/hybrid.py +224 -0
- synkit/Chem/Mapper/solvers/exact/hydrogen.py +264 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/branching.py +499 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumerate.py +1050 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumeration_result.py +30 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/kernel.py +256 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/milp.py +194 -0
- synkit/Chem/Mapper/solvers/exact/native/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/native/build.py +154 -0
- synkit/Chem/Mapper/solvers/exact/native/candidates.py +593 -0
- synkit/Chem/Mapper/solvers/exact/native/canonical.py +396 -0
- synkit/Chem/Mapper/solvers/exact/native/disk_frontier.py +415 -0
- synkit/Chem/Mapper/solvers/exact/native/frontier.py +390 -0
- synkit/Chem/Mapper/solvers/exact/native/hydrogen_quotient.py +213 -0
- synkit/Chem/Mapper/solvers/exact/native/its.py +528 -0
- synkit/Chem/Mapper/solvers/exact/native/native_distance.cpp +2803 -0
- synkit/Chem/Mapper/solvers/exact/native/orbit_aggregation.py +328 -0
- synkit/Chem/Mapper/solvers/exact/native/parallel.py +205 -0
- synkit/Chem/Mapper/solvers/exact/native/pmcd.py +203 -0
- synkit/Chem/Mapper/solvers/exact/native/runtime.py +40 -0
- synkit/Chem/Mapper/solvers/exact/native/search.py +294 -0
- synkit/Chem/Mapper/solvers/exact/native/separator.py +224 -0
- synkit/Chem/Mapper/solvers/exact/native_build.py +12 -0
- synkit/Chem/Mapper/solvers/exact/pabs/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/pabs/cost_lattice.py +43 -0
- synkit/Chem/Mapper/solvers/exact/pabs/factor_spectrum.py +110 -0
- synkit/Chem/Mapper/solvers/exact/pabs/multi_shell.py +368 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation.py +679 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation_bounds.py +436 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation_limits.py +13 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation_search.py +856 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation_symmetry.py +66 -0
- synkit/Chem/Mapper/solvers/exact/pabs/residual_typed_bonds.py +136 -0
- synkit/Chem/Mapper/solvers/exact/pabs/reward_frontier.py +201 -0
- synkit/Chem/Mapper/solvers/exact/pabs/separator_bound.py +258 -0
- synkit/Chem/Mapper/solvers/exact/pabs/separator_spectrum.py +308 -0
- synkit/Chem/Mapper/solvers/exact/pabs/sparse_reward_bound.py +207 -0
- synkit/Chem/Mapper/solvers/exact/pabs/suffix_spectrum.py +299 -0
- synkit/Chem/Mapper/solvers/exact/search.py +55 -0
- synkit/Chem/Mapper/solvers/exact/seeds/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/seeds/seed.py +104 -0
- synkit/Chem/Mapper/solvers/exact/seeds/seed_fragments.py +148 -0
- synkit/Chem/Mapper/solvers/exact/seeds/seed_relaxation.py +181 -0
- synkit/Chem/Mapper/solvers/exact/symmetry.py +223 -0
- synkit/Chem/Mapper/solvers/native/__init__.py +4 -0
- synkit/Chem/Mapper/solvers/native/assignment.py +99 -0
- synkit/Chem/Mapper/solvers/native/astar.py +22 -0
- synkit/Chem/Mapper/solvers/native/build.py +385 -0
- synkit/Chem/Mapper/solvers/native/classification.py +641 -0
- synkit/Chem/Mapper/solvers/native/core.py +378 -0
- synkit/Chem/Mapper/solvers/native/cpp/CMakeLists.txt +120 -0
- synkit/Chem/Mapper/solvers/native/cpp/examples/map_reaction.cpp +29 -0
- synkit/Chem/Mapper/solvers/native/cpp/examples/slap_graph.cpp +63 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/assignment/assignment.h +18 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/astar.h +18 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/bound.h +33 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/pmcd_witness.h +16 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/runtime.h +130 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/hydrogen/hydrogen.h +73 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mapper.h +175 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mces/mces.h +9 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/pabs/seed.h +34 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/reaction/reaction.h +30 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/sepdp/sepdp.h +21 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/slap.h +72 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/solvers/solvers.h +16 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/classification.h +140 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/cpabs.h +33 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/assignment/abb.cpp +302 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/CMakeLists.txt +12 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/README.md +47 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar.cpp +228 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar_graph.cpp +37 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/bound.cpp +212 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/core/dispatch.cpp +272 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/core/pmcd_witness.cpp +36 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/hydrogen/hydrogen.cpp +380 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/mces/README.md +57 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/mces/mces.cpp +287 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/bridge.cpp +334 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/chemical_floor.inc +181 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/endpoint_symmetry.inc +104 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/exact_helpers.h +20 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_assignment_certificate.h +165 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_certificate.h +125 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_model.h +365 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_provider.inc +319 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_rounding.inc +170 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_test_hooks.h +342 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/objective_reduction.inc +137 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/overlap_dual.inc +351 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/profile_seed.inc +214 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/seed_heuristics.inc +640 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_embedding.cpp +430 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_root_lp.h +176 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/test_hooks.inc +262 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/reaction/reaction.cpp +611 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/README.md +61 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/sepdp.cpp +253 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/slap.cpp +810 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/formulation.h +138 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/maxsat.cpp +526 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/ortools.cpp +475 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/seed.h +80 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/weighted_cnf.h +256 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/supporting/README.md +43 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/supporting/dfs.cpp +123 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/supporting/edit_support.cpp +224 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification.cpp +553 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_pipeline.cpp +124 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_stream.h +13 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/cpabs.cpp +455 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/edge_deck.cpp +743 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naugraph.c +732 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.c +94 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.h +49 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.c +1771 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.h +133 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nautil.c +750 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naututil.h +355 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.c +1256 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.h +1544 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.c +1131 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.h +70 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/sorttemplates.c +580 -0
- synkit/Chem/Mapper/solvers/native/hydrogen.py +711 -0
- synkit/Chem/Mapper/solvers/native/implicit.py +506 -0
- synkit/Chem/Mapper/solvers/native/implicit_certificate.py +187 -0
- synkit/Chem/Mapper/solvers/native/implicit_preparation.py +309 -0
- synkit/Chem/Mapper/solvers/native/lib/synkit_mapper.dll +0 -0
- synkit/Chem/Mapper/solvers/native/mces.py +16 -0
- synkit/Chem/Mapper/solvers/native/reaction.py +179 -0
- synkit/Chem/Mapper/solvers/native/reaction_build.py +277 -0
- synkit/Chem/Mapper/solvers/native/reaction_text.py +26 -0
- synkit/Chem/Mapper/solvers/native/runtime.py +242 -0
- synkit/Chem/Mapper/solvers/native/sepdp.py +47 -0
- synkit/Chem/Mapper/solvers/native/slap.py +266 -0
- synkit/Chem/Mapper/solvers/native/solvers.py +67 -0
- synkit/Chem/Mapper/solvers/native/stereo.py +86 -0
- synkit/Chem/Mapper/solvers/native/supporting.py +34 -0
- synkit/Chem/Mapper/solvers/native/symmetry.py +91 -0
- synkit/Chem/Mapper/solvers/slap/__init__.py +29 -0
- synkit/Chem/Mapper/solvers/slap/lap.py +174 -0
- synkit/Chem/Mapper/solvers/slap/sequential.py +696 -0
- synkit/Chem/Mapper/validation/__init__.py +1 -0
- synkit/Chem/Mapper/validation/aam_validator.py +442 -0
- synkit/Chem/Mapper/validation/annotations.py +274 -0
- synkit/Chem/Mapper/validation/bonds.py +124 -0
- synkit/Chem/Mapper/validation/cohorts.py +72 -0
- synkit/Chem/Mapper/validation/identifiability.py +150 -0
- synkit/Chem/Mapper/validation/numerical_scope.py +36 -0
- synkit/Chem/Mapper/validation/orbits.py +137 -0
- synkit/Chem/Molecule/__init__.py +0 -0
- synkit/Chem/Molecule/_chirality_loci.py +165 -0
- synkit/Chem/Molecule/_chirality_types.py +231 -0
- synkit/Chem/Molecule/_helical_loci.py +167 -0
- synkit/Chem/Molecule/_stereo_axis_evidence.py +202 -0
- synkit/Chem/Molecule/_stereo_element_detection.py +193 -0
- synkit/Chem/Molecule/_stereo_orientation_constraints.py +511 -0
- synkit/Chem/Molecule/_tetrahedral_carriers.py +63 -0
- synkit/Chem/Molecule/atom_features.py +379 -0
- synkit/Chem/Molecule/chirality.py +1041 -0
- synkit/Chem/Molecule/cip_assignment.py +569 -0
- synkit/Chem/Molecule/cip_ranking.py +843 -0
- synkit/Chem/Molecule/coordinate_stereo.py +503 -0
- synkit/Chem/Molecule/derived_stereo_naming.py +165 -0
- synkit/Chem/Molecule/descriptors.py +452 -0
- synkit/Chem/Molecule/formula.py +249 -0
- synkit/Chem/Molecule/global_stereo.py +175 -0
- synkit/Chem/Molecule/graph_annotator.py +300 -0
- synkit/Chem/Molecule/standardize.py +817 -0
- synkit/Chem/Molecule/stereo_evidence.py +179 -0
- synkit/Chem/Molecule/stereo_perception.py +1032 -0
- synkit/Chem/Molecule/valence.py +123 -0
- synkit/Chem/Reaction/Mapper/__init__.py +44 -0
- synkit/Chem/Reaction/__init__.py +20 -0
- synkit/Chem/Reaction/aam_validator.py +5 -0
- synkit/Chem/Reaction/balance_check.py +138 -0
- synkit/Chem/Reaction/canon_rsmi.py +249 -0
- synkit/Chem/Reaction/cleaning.py +58 -0
- synkit/Chem/Reaction/deionize.py +199 -0
- synkit/Chem/Reaction/explicit_h_audit.py +232 -0
- synkit/Chem/Reaction/fix_aam.py +64 -0
- synkit/Chem/Reaction/neutralize.py +207 -0
- synkit/Chem/Reaction/radical_wildcard.py +224 -0
- synkit/Chem/Reaction/standardize.py +203 -0
- synkit/Chem/Reaction/tautomerize.py +205 -0
- synkit/Chem/__init__.py +1 -0
- synkit/Chem/utils.py +315 -0
- synkit/Data/__init__.py +0 -0
- synkit/Data/aldol.json.gz +1 -0
- synkit/Data/gen_partial_aam.py +147 -0
- synkit/Data/paracetamol.json.gz +1 -0
- synkit/Graph/Canon/__init__.py +16 -0
- synkit/Graph/Canon/_native/__init__.py +13 -0
- synkit/Graph/Canon/_native/build.py +93 -0
- synkit/Graph/Canon/_native/lib/synkit_canon.dll +0 -0
- synkit/Graph/Canon/_native/prepare.py +49 -0
- synkit/Graph/Canon/_native/runtime.py +140 -0
- synkit/Graph/Canon/_native/search.py +137 -0
- synkit/Graph/Canon/canon_algs.py +228 -0
- synkit/Graph/Canon/canon_graph.py +531 -0
- synkit/Graph/Canon/cpp/CMakeLists.txt +42 -0
- synkit/Graph/Canon/cpp/README.md +123 -0
- synkit/Graph/Canon/cpp/examples/canonical_graph.cpp +16 -0
- synkit/Graph/Canon/cpp/include/synkit_canon/canon.h +85 -0
- synkit/Graph/Canon/cpp/src/canonical.cpp +391 -0
- synkit/Graph/Canon/cpp/src/symmetry.h +83 -0
- synkit/Graph/Canon/cpp/tests/symmetry.cpp +93 -0
- synkit/Graph/Canon/exact.py +1020 -0
- synkit/Graph/Canon/exact_refinement.py +368 -0
- synkit/Graph/Canon/nauty.py +143 -0
- synkit/Graph/Context/__init__.py +0 -0
- synkit/Graph/Context/hier_context.py +244 -0
- synkit/Graph/Context/radius_expand.py +252 -0
- synkit/Graph/FG/__init__.py +19 -0
- synkit/Graph/FG/api.py +39 -0
- synkit/Graph/FG/audit.py +155 -0
- synkit/Graph/FG/catalog.py +919 -0
- synkit/Graph/FG/detector.py +288 -0
- synkit/Graph/FG/model.py +97 -0
- synkit/Graph/FG/recognizers.py +274 -0
- synkit/Graph/FG/ring_system.py +154 -0
- synkit/Graph/Feature/Descriptors/topology.py +857 -0
- synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
- synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +222 -0
- synkit/Graph/Feature/__init__.py +5 -0
- synkit/Graph/Feature/graph_descriptors.py +323 -0
- synkit/Graph/Feature/graph_fps.py +96 -0
- synkit/Graph/Feature/graph_signature.py +239 -0
- synkit/Graph/Feature/hash_fps.py +133 -0
- synkit/Graph/Feature/morgan_fps.py +88 -0
- synkit/Graph/Feature/path_fps.py +81 -0
- synkit/Graph/Feature/wl_hash.py +134 -0
- synkit/Graph/Fusion/__init__.py +85 -0
- synkit/Graph/Fusion/candidate.py +559 -0
- synkit/Graph/Fusion/constructor.py +877 -0
- synkit/Graph/Fusion/identity.py +184 -0
- synkit/Graph/Fusion/interface.py +700 -0
- synkit/Graph/Fusion/search.py +241 -0
- synkit/Graph/Hyrogen/__init__.py +6 -0
- synkit/Graph/Hyrogen/_misc.py +591 -0
- synkit/Graph/Hyrogen/hcomplete.py +995 -0
- synkit/Graph/Hyrogen/hcomplete_legacy.py +368 -0
- synkit/Graph/Hyrogen/hcompletion_algorithms.py +713 -0
- synkit/Graph/Hyrogen/hextend.py +570 -0
- synkit/Graph/Hyrogen/hextend_legacy.py +215 -0
- synkit/Graph/ITS/__init__.py +4 -0
- synkit/Graph/ITS/its_builder.py +120 -0
- synkit/Graph/ITS/its_construction.py +719 -0
- synkit/Graph/ITS/its_decompose.py +572 -0
- synkit/Graph/ITS/its_destruction.py +331 -0
- synkit/Graph/ITS/its_expand.py +1251 -0
- synkit/Graph/ITS/its_relabel.py +187 -0
- synkit/Graph/ITS/its_reverter.py +356 -0
- synkit/Graph/ITS/normalize_aam.py +145 -0
- synkit/Graph/ITS/partial_its.py +238 -0
- synkit/Graph/ITS/rc_extractor.py +656 -0
- synkit/Graph/ITS/stereo.py +74 -0
- synkit/Graph/MTG/__init__.py +107 -0
- synkit/Graph/MTG/gluing.py +451 -0
- synkit/Graph/MTG/history.py +928 -0
- synkit/Graph/MTG/inventory.py +118 -0
- synkit/Graph/MTG/local.py +447 -0
- synkit/Graph/MTG/mcs_matcher.py +246 -0
- synkit/Graph/MTG/mtg.py +611 -0
- synkit/Graph/MTG/mtg_explore.py +74 -0
- synkit/Graph/MTG/observation.py +209 -0
- synkit/Graph/MTG/process.py +577 -0
- synkit/Graph/MTG/queries.py +66 -0
- synkit/Graph/MTG/realization.py +95 -0
- synkit/Graph/MTG/series_parallel.py +107 -0
- synkit/Graph/MTG/utils.py +424 -0
- synkit/Graph/Matcher/__init__.py +10 -0
- synkit/Graph/Matcher/approx_mcs.py +1264 -0
- synkit/Graph/Matcher/auto_est.py +736 -0
- synkit/Graph/Matcher/automorphism.py +314 -0
- synkit/Graph/Matcher/batch_cluster.py +224 -0
- synkit/Graph/Matcher/dedup_matches.py +247 -0
- synkit/Graph/Matcher/graph_cluster.py +191 -0
- synkit/Graph/Matcher/graph_matcher.py +312 -0
- synkit/Graph/Matcher/graph_morphism.py +421 -0
- synkit/Graph/Matcher/mcs_matcher.py +804 -0
- synkit/Graph/Matcher/multi_turbo_iso.py +186 -0
- synkit/Graph/Matcher/orbit.py +284 -0
- synkit/Graph/Matcher/partial_matcher.py +694 -0
- synkit/Graph/Matcher/sing.py +544 -0
- synkit/Graph/Matcher/subgraph_matcher.py +812 -0
- synkit/Graph/Matcher/turbo_iso.py +272 -0
- synkit/Graph/Matcher/wl_sel.py +537 -0
- synkit/Graph/Mech/__init__.py +26 -0
- synkit/Graph/Mech/conversion.py +1466 -0
- synkit/Graph/Mech/conversion_debug.py +237 -0
- synkit/Graph/Mech/electron_accounting.py +200 -0
- synkit/Graph/Mech/lwg_editor.py +406 -0
- synkit/Graph/Mech/lwg_ops.py +313 -0
- synkit/Graph/Morphism/__init__.py +99 -0
- synkit/Graph/Morphism/constraints.py +460 -0
- synkit/Graph/Morphism/llg.py +999 -0
- synkit/Graph/Morphism/morphism.py +349 -0
- synkit/Graph/Morphism/stereo.py +258 -0
- synkit/Graph/Morphism/stereo_morphism.py +383 -0
- synkit/Graph/Morphism/stereo_morphism_helpers.py +957 -0
- synkit/Graph/Morphism/stereo_morphism_types.py +117 -0
- synkit/Graph/Stereo/__init__.py +376 -0
- synkit/Graph/Stereo/_descriptor_core.py +207 -0
- synkit/Graph/Stereo/_descriptor_serialization.py +138 -0
- synkit/Graph/Stereo/canonical.py +648 -0
- synkit/Graph/Stereo/changes.py +964 -0
- synkit/Graph/Stereo/composition.py +391 -0
- synkit/Graph/Stereo/configured.py +946 -0
- synkit/Graph/Stereo/couplings.py +245 -0
- synkit/Graph/Stereo/descriptors.py +1030 -0
- synkit/Graph/Stereo/enumeration.py +597 -0
- synkit/Graph/Stereo/extended_descriptors.py +406 -0
- synkit/Graph/Stereo/global_configured.py +152 -0
- synkit/Graph/Stereo/global_stereo.py +304 -0
- synkit/Graph/Stereo/identity.py +648 -0
- synkit/Graph/Stereo/interchange.py +496 -0
- synkit/Graph/Stereo/legacy.py +460 -0
- synkit/Graph/Stereo/matching.py +899 -0
- synkit/Graph/Stereo/native.py +154 -0
- synkit/Graph/Stereo/orbits.py +668 -0
- synkit/Graph/Stereo/outcomes.py +99 -0
- synkit/Graph/Stereo/pairwise.py +350 -0
- synkit/Graph/Stereo/rdkit_adapter.py +662 -0
- synkit/Graph/Stereo/rdkit_identity.py +118 -0
- synkit/Graph/Stereo/rdkit_resonance.py +140 -0
- synkit/Graph/Stereo/reaction_interchange.py +266 -0
- synkit/Graph/Stereo/semantics.py +296 -0
- synkit/Graph/Stereo/supports.py +257 -0
- synkit/Graph/Stereo/wire.py +339 -0
- synkit/Graph/Wildcard/__init__.py +0 -0
- synkit/Graph/Wildcard/fuse_graph.py +156 -0
- synkit/Graph/Wildcard/graph_wc.py +303 -0
- synkit/Graph/Wildcard/its_merge.py +857 -0
- synkit/Graph/Wildcard/radwc.py +114 -0
- synkit/Graph/Wildcard/wc_matcher.py +576 -0
- synkit/Graph/Wildcard/wildcard.py +225 -0
- synkit/Graph/__init__.py +17 -0
- synkit/Graph/canon_graph.py +14 -0
- synkit/Graph/syn_graph.py +199 -0
- synkit/Graph/utils.py +324 -0
- synkit/IO/__init__.py +4 -0
- synkit/IO/chem_converter.py +1059 -0
- synkit/IO/combinatorial/__init__.py +8 -0
- synkit/IO/combinatorial/gml_to_graph.py +223 -0
- synkit/IO/combinatorial/graph_to_gml.py +280 -0
- synkit/IO/combinatorial/graph_to_smarts.py +186 -0
- synkit/IO/combinatorial/smarts_expander.py +147 -0
- synkit/IO/combinatorial/smarts_generalizer.py +133 -0
- synkit/IO/combinatorial/smarts_to_graph.py +179 -0
- synkit/IO/conversion.py +42 -0
- synkit/IO/data_io.py +269 -0
- synkit/IO/data_process.py +143 -0
- synkit/IO/debug.py +73 -0
- synkit/IO/gml_to_nx.py +150 -0
- synkit/IO/graph_to_mol.py +199 -0
- synkit/IO/mol_to_graph.py +1105 -0
- synkit/IO/mol_to_graph_chemistry.py +545 -0
- synkit/IO/nx_to_gml.py +209 -0
- synkit/IO/smiles_to_id.py +123 -0
- synkit/Mechanism/__init__.py +151 -0
- synkit/Mechanism/adapters.py +136 -0
- synkit/Mechanism/audit.py +323 -0
- synkit/Mechanism/benchmark.py +638 -0
- synkit/Mechanism/compatibility.py +13 -0
- synkit/Mechanism/drawing.py +85 -0
- synkit/Mechanism/electron_models.py +725 -0
- synkit/Mechanism/equivalence.py +521 -0
- synkit/Mechanism/evidence.py +262 -0
- synkit/Mechanism/interchange.py +141 -0
- synkit/Mechanism/model.py +918 -0
- synkit/Mechanism/neighbor_stereo.py +312 -0
- synkit/Mechanism/radical_data.py +740 -0
- synkit/Mechanism/replay.py +986 -0
- synkit/Mechanism/schema.py +264 -0
- synkit/Mechanism/stereo_state.py +416 -0
- synkit/Mechanism/symbols.py +91 -0
- synkit/Rule/Apply/__init__.py +35 -0
- synkit/Rule/Apply/conditions.py +45 -0
- synkit/Rule/Apply/dpo.py +998 -0
- synkit/Rule/Apply/rule_matcher.py +218 -0
- synkit/Rule/Apply/validation.py +354 -0
- synkit/Rule/Compose/__init__.py +106 -0
- synkit/Rule/Compose/_identity.py +43 -0
- synkit/Rule/Compose/composition.py +976 -0
- synkit/Rule/Compose/laws.py +439 -0
- synkit/Rule/Compose/search.py +771 -0
- synkit/Rule/Compose/synrule.py +170 -0
- synkit/Rule/Modify/__init__.py +0 -0
- synkit/Rule/Modify/implict_rule.py +56 -0
- synkit/Rule/Modify/longest_path.py +92 -0
- synkit/Rule/Modify/molecule_rule.py +115 -0
- synkit/Rule/Modify/prune_templates.py +78 -0
- synkit/Rule/Modify/rule_utils.py +194 -0
- synkit/Rule/Modify/strip_rule.py +97 -0
- synkit/Rule/__init__.py +28 -0
- synkit/Rule/generic_stereo.py +884 -0
- synkit/Rule/stereo_identity.py +271 -0
- synkit/Rule/syn_rule.py +1090 -0
- synkit/Synthesis/MSR/__init__.py +0 -0
- synkit/Synthesis/MSR/path_finder.py +239 -0
- synkit/Synthesis/Metrics/__init__.py +0 -0
- synkit/Synthesis/Metrics/_base.py +52 -0
- synkit/Synthesis/Metrics/_plot.py +129 -0
- synkit/Synthesis/Metrics/_ranking.py +179 -0
- synkit/Synthesis/RBL/__init__.py +80 -0
- synkit/Synthesis/RBL/engine.py +1249 -0
- synkit/Synthesis/RBL/matching.py +652 -0
- synkit/Synthesis/RBL/overlap.py +336 -0
- synkit/Synthesis/RBL/pipeline.py +376 -0
- synkit/Synthesis/RBL/policy.py +139 -0
- synkit/Synthesis/RBL/proof.py +370 -0
- synkit/Synthesis/RBL/reaction.py +506 -0
- synkit/Synthesis/RBL/state.py +169 -0
- synkit/Synthesis/RBL/validation.py +1060 -0
- synkit/Synthesis/Reactor/__init__.py +60 -0
- synkit/Synthesis/Reactor/core/__init__.py +1 -0
- synkit/Synthesis/Reactor/core/engine.py +967 -0
- synkit/Synthesis/Reactor/core/product.py +621 -0
- synkit/Synthesis/Reactor/core/rewrite.py +561 -0
- synkit/Synthesis/Reactor/core/strategy.py +44 -0
- synkit/Synthesis/Reactor/matching/__init__.py +1 -0
- synkit/Synthesis/Reactor/matching/mixin.py +920 -0
- synkit/Synthesis/Reactor/matching/policy.py +345 -0
- synkit/Synthesis/Reactor/matching/symmetry.py +309 -0
- synkit/Synthesis/Reactor/output/__init__.py +1 -0
- synkit/Synthesis/Reactor/output/deduplication.py +703 -0
- synkit/Synthesis/Reactor/output/policy.py +16 -0
- synkit/Synthesis/Reactor/output/serialization.py +485 -0
- synkit/Synthesis/Reactor/output/structural.py +893 -0
- synkit/Synthesis/Reactor/stereo/__init__.py +1 -0
- synkit/Synthesis/Reactor/stereo/assignment.py +35 -0
- synkit/Synthesis/Reactor/stereo/mixin.py +780 -0
- synkit/Synthesis/Reactor/variants/__init__.py +1 -0
- synkit/Synthesis/Reactor/variants/imbalanced.py +180 -0
- synkit/Synthesis/Reactor/variants/partial.py +84 -0
- synkit/Synthesis/Reactor/workflow/__init__.py +1 -0
- synkit/Synthesis/Reactor/workflow/batch.py +550 -0
- synkit/Synthesis/Reactor/workflow/benchmark.py +143 -0
- synkit/Synthesis/Reactor/workflow/postprocess.py +267 -0
- synkit/Synthesis/Reactor/workflow/rule_filter.py +210 -0
- synkit/Synthesis/__init__.py +0 -0
- synkit/Synthesis/reactor_utils.py +316 -0
- synkit/Utils/__init__.py +0 -0
- synkit/Utils/utils.py +172 -0
- synkit/Vis/__init__.py +91 -0
- synkit/Vis/crn/__init__.py +40 -0
- synkit/Vis/epd/__init__.py +20 -0
- synkit/Vis/epd/arrows.py +425 -0
- synkit/Vis/epd/chem.py +197 -0
- synkit/Vis/epd/constants.py +83 -0
- synkit/Vis/epd/layout.py +283 -0
- synkit/Vis/epd/mapping.py +51 -0
- synkit/Vis/epd/models.py +136 -0
- synkit/Vis/epd/render.py +543 -0
- synkit/Vis/epd/utils.py +108 -0
- synkit/Vis/epd/visualizer.py +811 -0
- synkit/Vis/graph_visualizer.py +375 -0
- synkit/Vis/its/__init__.py +19 -0
- synkit/Vis/its/drawer.py +615 -0
- synkit/Vis/its_drawer.py +35 -0
- synkit/Vis/molecule/__init__.py +31 -0
- synkit/Vis/molecule/drawer.py +563 -0
- synkit/Vis/molecule/reaction.py +285 -0
- synkit/Vis/molecule_drawer.py +33 -0
- synkit/Vis/mtg/__init__.py +17 -0
- synkit/Vis/mtg/drawer.py +769 -0
- synkit/Vis/mtg_drawer.py +34 -0
- synkit/Vis/pdf_writer.py +146 -0
- synkit/Vis/reaction/__init__.py +19 -0
- synkit/Vis/reaction/rule.py +141 -0
- synkit/Vis/reaction/rxn.py +532 -0
- synkit/Vis/reaction_drawer.py +41 -0
- synkit/Vis/space/__init__.py +17 -0
- synkit/Vis/space/chemical.py +80 -0
- synkit/Vis/space/embedding.py +87 -0
- synkit/Vis/vis_synedu/Vis/__init__.py +7 -0
- synkit/Vis/vis_synedu/Vis/dpo.py +862 -0
- synkit/Vis/vis_synedu/rxn_vis.py +377 -0
- synkit/Vis/vis_synedu/vis.py +501 -0
- synkit/Vis/visual_drawer.py +215 -0
- synkit/Vis/visual_model.py +520 -0
- synkit/__init__.py +3 -0
- synkit/_native.py +91 -0
- synkit/examples.py +50 -0
- synkit/version.py +23 -0
- synkit-1.6.5.dist-info/METADATA +156 -0
- synkit-1.6.5.dist-info/RECORD +636 -0
- synkit-1.6.5.dist-info/WHEEL +4 -0
- synkit-1.6.5.dist-info/licenses/LICENSE +21 -0
- synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
- synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
from typing import List, Any, Dict, Tuple, Callable
|
|
4
|
+
|
|
5
|
+
from synkit.IO.debug import setup_logging
|
|
6
|
+
from synkit.Graph.Feature.wl_hash import WLHash
|
|
7
|
+
from synkit.Graph.Context.radius_expand import RadiusExpand
|
|
8
|
+
from synkit.Graph.Matcher.batch_cluster import BatchCluster
|
|
9
|
+
|
|
10
|
+
logger = setup_logging()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class HierContext(RadiusExpand):
|
|
14
|
+
"""Hierarchical clustering class for reaction context graphs.
|
|
15
|
+
|
|
16
|
+
Extends RadiusExpand to build multi-level graph representations and
|
|
17
|
+
clusters them based on structural features such as Weisfeiler-Lehman
|
|
18
|
+
hashing.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
node_label_names: List[str] = ["element", "charge"],
|
|
24
|
+
node_label_default: List[Any] = ["*", 0],
|
|
25
|
+
edge_attribute: str = "order",
|
|
26
|
+
max_radius: int = 3,
|
|
27
|
+
) -> None:
|
|
28
|
+
"""Initializes the HierContext class for hierarchical clustering of
|
|
29
|
+
reaction context graphs.
|
|
30
|
+
|
|
31
|
+
:param node_label_names: A list of node attribute names used for matching.
|
|
32
|
+
:type node_label_names: List[str]
|
|
33
|
+
:param node_label_default: A list of default values for node attributes.
|
|
34
|
+
:type node_label_default: List[Any]
|
|
35
|
+
:param edge_attribute: The edge attribute used in matching.
|
|
36
|
+
:type edge_attribute: str
|
|
37
|
+
:param max_radius: The maximum hierarchical level (radius) to be considered.
|
|
38
|
+
:type max_radius: int
|
|
39
|
+
"""
|
|
40
|
+
super().__init__()
|
|
41
|
+
self.radius: List[int] = list(range(max_radius + 1))
|
|
42
|
+
self.node_label_names: List[str] = node_label_names
|
|
43
|
+
self.node_label_default: List[Any] = node_label_default
|
|
44
|
+
self.edge_attribute: str = edge_attribute
|
|
45
|
+
self.cluster: BatchCluster = BatchCluster(
|
|
46
|
+
self.node_label_names, self.node_label_default, self.edge_attribute
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def _group_class(
|
|
51
|
+
data: List[Dict[str, Any]], key: str
|
|
52
|
+
) -> Dict[Any, List[Dict[str, Any]]]:
|
|
53
|
+
"""Groups a list of dictionaries into subgroups based on the specified
|
|
54
|
+
key.
|
|
55
|
+
|
|
56
|
+
:param data: A list of dictionaries to be grouped.
|
|
57
|
+
:type data: List[Dict[str, Any]]
|
|
58
|
+
:param key: The key used for grouping items.
|
|
59
|
+
:type key: str
|
|
60
|
+
|
|
61
|
+
:return: Dictionary grouping entries by the selected key value.
|
|
62
|
+
:rtype: Dict[Any, List[Dict[str, Any]]]
|
|
63
|
+
"""
|
|
64
|
+
grouped_data: Dict[Any, List[Dict[str, Any]]] = defaultdict(list)
|
|
65
|
+
for item in data:
|
|
66
|
+
grouped_data[item.get(key)].append(item)
|
|
67
|
+
return dict(grouped_data)
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def _update_child_idx(
|
|
71
|
+
data: List[List[Dict[str, Any]]], cls_id: str = "class"
|
|
72
|
+
) -> List[List[Dict[str, Any]]]:
|
|
73
|
+
"""Updates hierarchical templates by assigning child IDs based on
|
|
74
|
+
parent–cluster relationships.
|
|
75
|
+
|
|
76
|
+
:param data: A list of layers, where each layer is a list of dictionaries
|
|
77
|
+
containing node data.
|
|
78
|
+
:type data: List[List[Dict[str, Any]]]
|
|
79
|
+
:param cls_id: The key used to identify the node's class or cluster ID (default is "class").
|
|
80
|
+
:type cls_id: str
|
|
81
|
+
|
|
82
|
+
:return: Hierarchical data whose nodes list their child class IDs.
|
|
83
|
+
:rtype: List[List[Dict[str, Any]]]
|
|
84
|
+
"""
|
|
85
|
+
node_dict: Dict[str, Dict[str, Any]] = {}
|
|
86
|
+
|
|
87
|
+
# Initialize the "Child" list for each node and build a mapping based on layer index and class ID.
|
|
88
|
+
for layer_idx, layer in enumerate(data):
|
|
89
|
+
for node in layer:
|
|
90
|
+
node["Child"] = []
|
|
91
|
+
node_dict[f"{layer_idx}-{node[cls_id]}"] = node
|
|
92
|
+
|
|
93
|
+
# Update parent's "Child" list by linking child nodes to their respective parent(s).
|
|
94
|
+
for layer_idx, layer in enumerate(data[1:], 1):
|
|
95
|
+
for node in layer:
|
|
96
|
+
parents = node.get("Parent", [])
|
|
97
|
+
if isinstance(parents, (int, str)):
|
|
98
|
+
parents = [parents]
|
|
99
|
+
for parent_id in parents:
|
|
100
|
+
parent_key = f"{layer_idx - 1}-{parent_id}"
|
|
101
|
+
if parent_key in node_dict:
|
|
102
|
+
node_dict[parent_key]["Child"].append(node[cls_id])
|
|
103
|
+
return data
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def _process(
|
|
107
|
+
data: List[Dict[str, Any]],
|
|
108
|
+
k: int,
|
|
109
|
+
its_key: str,
|
|
110
|
+
context_key: str,
|
|
111
|
+
cls_func: Callable,
|
|
112
|
+
) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
|
|
113
|
+
"""Processes a list of graph data entries by extracting context
|
|
114
|
+
subgraphs and computing their hashes, then classifies the data using
|
|
115
|
+
the provided clustering function.
|
|
116
|
+
|
|
117
|
+
:param data: A list of dictionaries, each representing a graph or data entry.
|
|
118
|
+
:type data: List[Dict[str, Any]]
|
|
119
|
+
:param k: The number of nearest neighbors to include during context extraction.
|
|
120
|
+
:type k: int
|
|
121
|
+
:param its_key: The key corresponding to the ITS graph in each data entry.
|
|
122
|
+
:type its_key: str
|
|
123
|
+
:param context_key: The key under which the extracted context subgraph will be stored.
|
|
124
|
+
:type context_key: str
|
|
125
|
+
:param cls_func: The clustering function instance to be used for clustering.
|
|
126
|
+
:type cls_func: Callable
|
|
127
|
+
|
|
128
|
+
:return: A tuple containing:
|
|
129
|
+
The list of clustered data entries with updated cluster identifiers.
|
|
130
|
+
The list of processed template dictionaries.
|
|
131
|
+
:rtype: Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]
|
|
132
|
+
"""
|
|
133
|
+
for item in data:
|
|
134
|
+
context = RadiusExpand.extract_k(item[its_key], n_knn=k)
|
|
135
|
+
item[context_key] = context
|
|
136
|
+
item["WLHash"] = WLHash().weisfeiler_lehman_graph_hash(context)
|
|
137
|
+
|
|
138
|
+
cluster_results, templates = cls_func.cluster(data, [], context_key, "WLHash")
|
|
139
|
+
|
|
140
|
+
for result in cluster_results:
|
|
141
|
+
result[f"R_{k}"] = result.pop("class")
|
|
142
|
+
|
|
143
|
+
templates_processed = [
|
|
144
|
+
{"R-id": tpl["R-id"], context_key: tpl[context_key], "class": tpl["class"]}
|
|
145
|
+
for tpl in templates
|
|
146
|
+
]
|
|
147
|
+
|
|
148
|
+
return cluster_results, templates_processed
|
|
149
|
+
|
|
150
|
+
def _process_level(
|
|
151
|
+
self,
|
|
152
|
+
data: List[Dict[str, Any]],
|
|
153
|
+
its_key: str,
|
|
154
|
+
context_key: str,
|
|
155
|
+
cls_func: Callable,
|
|
156
|
+
radius: int = 1,
|
|
157
|
+
) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
|
|
158
|
+
"""Processes a specific hierarchical level by grouping data based on
|
|
159
|
+
parent cluster IDs, extracting context for child levels, and clustering
|
|
160
|
+
the data.
|
|
161
|
+
|
|
162
|
+
:param data: A list of dictionaries representing graph data entries.
|
|
163
|
+
:type data: List[Dict[str, Any]]
|
|
164
|
+
:param its_key: The key corresponding to the ITS graph in each entry.
|
|
165
|
+
:type its_key: str
|
|
166
|
+
:param context_key: The key under which the extracted context subgraph is stored.
|
|
167
|
+
:type context_key: str
|
|
168
|
+
:param cls_func: The clustering function instance to be used.
|
|
169
|
+
:type cls_func: Callable
|
|
170
|
+
:param radius: The current hierarchical level (radius) being processed (default is 1).
|
|
171
|
+
:type radius: int, optional
|
|
172
|
+
|
|
173
|
+
:return: A tuple containing:
|
|
174
|
+
The updated list of data entries with new cluster indices for this level.
|
|
175
|
+
The list of newly generated template dictionaries for this level.
|
|
176
|
+
:rtype: Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]
|
|
177
|
+
"""
|
|
178
|
+
grouped_data: Dict[Any, List[Dict[str, Any]]] = self._group_class(
|
|
179
|
+
data, f"R_{radius - 1}"
|
|
180
|
+
)
|
|
181
|
+
templates: List[Dict[str, Any]] = []
|
|
182
|
+
cluster_indices_all: List[Dict[str, Any]] = []
|
|
183
|
+
template_offset: int = 0
|
|
184
|
+
|
|
185
|
+
for parent_class, group in grouped_data.items():
|
|
186
|
+
cluster_indices, new_templates = self._process(
|
|
187
|
+
group, radius, its_key, context_key, cls_func
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
for ci in cluster_indices:
|
|
191
|
+
ci[f"R_{radius}"] += template_offset
|
|
192
|
+
|
|
193
|
+
for tpl in new_templates:
|
|
194
|
+
tpl["class"] += template_offset
|
|
195
|
+
tpl["Parent"] = parent_class
|
|
196
|
+
|
|
197
|
+
cluster_indices_all.extend(cluster_indices)
|
|
198
|
+
templates.extend(new_templates)
|
|
199
|
+
template_offset = len(templates)
|
|
200
|
+
|
|
201
|
+
return cluster_indices_all, templates
|
|
202
|
+
|
|
203
|
+
def fit(
|
|
204
|
+
self,
|
|
205
|
+
original_data: List[Dict[str, Any]],
|
|
206
|
+
its_key: str = "ITS",
|
|
207
|
+
context_key: str = "K",
|
|
208
|
+
) -> Tuple[List[Dict[str, Any]], List[List[Dict[str, Any]]]]:
|
|
209
|
+
"""Processes a list of graph data entries, classifying each based on
|
|
210
|
+
hierarchical clustering. The method extracts context subgraphs,
|
|
211
|
+
computes graph hashes, and clusters the data at multiple hierarchical
|
|
212
|
+
levels. Finally, child node indices are updated based on parent–cluster
|
|
213
|
+
relationships.
|
|
214
|
+
|
|
215
|
+
:param original_data: A list of dictionaries, each representing a graph data entry
|
|
216
|
+
with an ITS graph.
|
|
217
|
+
:type original_data: List[Dict[str, Any]]
|
|
218
|
+
:param its_key: The key in each dictionary corresponding to the ITS graph (default is "ITS").
|
|
219
|
+
:type its_key: str
|
|
220
|
+
:param context_key: The key under which the extracted context subgraph is stored (default is "K").
|
|
221
|
+
:type context_key: str
|
|
222
|
+
|
|
223
|
+
:return: A tuple containing:
|
|
224
|
+
The updated list of graph data entries with hierarchical cluster indices.
|
|
225
|
+
A list (per hierarchical level) of template dictionaries that have been updated with child indices.
|
|
226
|
+
:rtype: Tuple[List[Dict[str, Any]], List[List[Dict[str, Any]]]]
|
|
227
|
+
"""
|
|
228
|
+
data: List[Dict[str, Any]] = copy.deepcopy(original_data)
|
|
229
|
+
|
|
230
|
+
logger.info("Processing parent level (radius 0)")
|
|
231
|
+
cluster_indices, templates = self._process(
|
|
232
|
+
data, 0, its_key, context_key, self.cluster
|
|
233
|
+
)
|
|
234
|
+
templates_all: List[List[Dict[str, Any]]] = [templates]
|
|
235
|
+
|
|
236
|
+
for radius in self.radius[1:]:
|
|
237
|
+
logger.info(f"Processing child level with radius {radius}")
|
|
238
|
+
cluster_indices, templates_radius = self._process_level(
|
|
239
|
+
data, its_key, context_key, self.cluster, radius
|
|
240
|
+
)
|
|
241
|
+
templates_all.append(templates_radius)
|
|
242
|
+
|
|
243
|
+
templates_all = self._update_child_idx(templates_all)
|
|
244
|
+
return cluster_indices, templates_all
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import networkx as nx
|
|
3
|
+
from itertools import chain
|
|
4
|
+
from joblib import Parallel, delayed
|
|
5
|
+
from typing import List, Set, Dict, Any, Tuple
|
|
6
|
+
|
|
7
|
+
from synkit.Graph.ITS.its_decompose import get_rc
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RadiusExpand:
|
|
11
|
+
"""A utility class for extracting and expanding reaction contexts from
|
|
12
|
+
chemical reaction graphs.
|
|
13
|
+
|
|
14
|
+
This class provides methods to:
|
|
15
|
+
- Identify reaction center nodes based on unequal edge orders.
|
|
16
|
+
- Expand reaction centers by including n-level nearest neighbors.
|
|
17
|
+
- Extract subgraphs from larger graphs.
|
|
18
|
+
- Construct a reaction context subgraph (K graph) from an ITS graph.
|
|
19
|
+
- Retrieve the longest unique extension path from reaction centers using DFS.
|
|
20
|
+
- Perform parallel extraction of reaction contexts from multiple reaction dictionaries.
|
|
21
|
+
- Remove edges based on specified edge attribute values.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self) -> None:
|
|
25
|
+
"""Initializes an instance of the RadiusExpand class.
|
|
26
|
+
|
|
27
|
+
This class does not maintain any instance-specific state and
|
|
28
|
+
uses only static and class methods.
|
|
29
|
+
"""
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def find_unequal_order_edges(G: nx.Graph) -> List[int]:
|
|
34
|
+
"""Identifies reaction center nodes in a graph based on the presence of
|
|
35
|
+
unequal order edges.
|
|
36
|
+
|
|
37
|
+
:param G: Graph to analyze for reaction centers.
|
|
38
|
+
:type G: nx.Graph
|
|
39
|
+
|
|
40
|
+
:return: A list of node indices identified as reaction centers based on unequal order edges.
|
|
41
|
+
:rtype: List[int]
|
|
42
|
+
"""
|
|
43
|
+
reaction_center_nodes: Set[int] = set()
|
|
44
|
+
for u, v, data in G.edges(data=True):
|
|
45
|
+
order = data.get("order", (1, 1))
|
|
46
|
+
if (
|
|
47
|
+
isinstance(order, tuple)
|
|
48
|
+
and order[0] != order[1]
|
|
49
|
+
and data.get("standard_order", 1) != 0
|
|
50
|
+
):
|
|
51
|
+
reaction_center_nodes.update([u, v])
|
|
52
|
+
return list(reaction_center_nodes)
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def find_nearest_neighbors(
|
|
56
|
+
G: nx.Graph, center_nodes: List[int], n_knn: int = 1
|
|
57
|
+
) -> Set[int]:
|
|
58
|
+
"""Finds the n-level nearest neighbors around the specified center
|
|
59
|
+
nodes in a graph.
|
|
60
|
+
|
|
61
|
+
:param G: The graph in which to search for neighboring nodes.
|
|
62
|
+
:type G: nx.Graph
|
|
63
|
+
:param center_nodes: Initial center node indices.
|
|
64
|
+
:type center_nodes: List[int]
|
|
65
|
+
:param n_knn: The number of neighbor levels to include (default is 1).
|
|
66
|
+
:type n_knn: int, optional
|
|
67
|
+
|
|
68
|
+
:return: A set of node indices including the original center nodes and their nearest neighbors.
|
|
69
|
+
:rtype: Set[int]
|
|
70
|
+
"""
|
|
71
|
+
extended_nodes: Set[int] = set(center_nodes)
|
|
72
|
+
for _ in range(n_knn):
|
|
73
|
+
neighbors = set(
|
|
74
|
+
chain.from_iterable(G.neighbors(node) for node in extended_nodes)
|
|
75
|
+
)
|
|
76
|
+
extended_nodes.update(neighbors)
|
|
77
|
+
return extended_nodes
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def extract_subgraph(G: nx.Graph, node_indices: List[int]) -> nx.Graph:
|
|
81
|
+
"""Extracts a subgraph from the original graph containing the specified
|
|
82
|
+
node indices.
|
|
83
|
+
|
|
84
|
+
:param G: The original graph.
|
|
85
|
+
:type G: nx.Graph
|
|
86
|
+
:param node_indices: A list of node indices to include in the subgraph.
|
|
87
|
+
:type node_indices: List[int]
|
|
88
|
+
|
|
89
|
+
:return: A new graph that is a copy of the subgraph containing only the specified nodes.
|
|
90
|
+
:rtype: nx.Graph
|
|
91
|
+
"""
|
|
92
|
+
return G.subgraph(node_indices).copy()
|
|
93
|
+
|
|
94
|
+
@staticmethod
|
|
95
|
+
def extract_k(its: nx.Graph, n_knn: int = 0) -> Tuple[nx.Graph, Any]:
|
|
96
|
+
"""Constructs the context subgraph (K graph) from an ITS graph based on
|
|
97
|
+
reaction centers, and computes the longest extension path from these
|
|
98
|
+
centers constrained by 'standard_order' edges.
|
|
99
|
+
|
|
100
|
+
:param its: The ITS graph representing the reaction network.
|
|
101
|
+
:type its: nx.Graph
|
|
102
|
+
:param n_knn: The number of neighbor levels to include in the context subgraph.
|
|
103
|
+
Default is 0.
|
|
104
|
+
:type n_knn: int, optional
|
|
105
|
+
|
|
106
|
+
:return: Extracted context graph. A zero radius returns the reaction
|
|
107
|
+
center; ``-1`` uses the maximum radius.
|
|
108
|
+
:rtype: Tuple[nx.Graph, Any]
|
|
109
|
+
"""
|
|
110
|
+
rc = get_rc(its)
|
|
111
|
+
rc_nodes = list(rc.nodes())
|
|
112
|
+
if n_knn == 0:
|
|
113
|
+
return rc
|
|
114
|
+
elif n_knn == -1:
|
|
115
|
+
paths = RadiusExpand.longest_radius_extension(its, rc_nodes)
|
|
116
|
+
n_knn = len(paths)
|
|
117
|
+
|
|
118
|
+
expanded_nodes = RadiusExpand.find_nearest_neighbors(its, rc_nodes, n_knn)
|
|
119
|
+
context = RadiusExpand.extract_subgraph(its, list(expanded_nodes))
|
|
120
|
+
return context
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def context_extraction(
|
|
124
|
+
data: Dict[str, Any],
|
|
125
|
+
its_key: str = "ITS",
|
|
126
|
+
context_key: str = "K",
|
|
127
|
+
n_knn: int = 0,
|
|
128
|
+
) -> Dict[str, Any]:
|
|
129
|
+
"""Extracts the reaction context for a single reaction dictionary by
|
|
130
|
+
computing both the context subgraph and the longest extension path.
|
|
131
|
+
|
|
132
|
+
:param data: Reaction data containing at least an ITS graph.
|
|
133
|
+
:type data: Dict[str, Any]
|
|
134
|
+
:param its_key: Key in the dictionary for retrieving the ITS graph.
|
|
135
|
+
Default is ITS.
|
|
136
|
+
:type its_key: str, optional
|
|
137
|
+
:param context_key: Key under which to store the extracted context subgraph.
|
|
138
|
+
Default is K.
|
|
139
|
+
:type context_key: str, optional
|
|
140
|
+
:param n_knn: Number of neighbor levels to include for context extraction.
|
|
141
|
+
Default is 0.
|
|
142
|
+
:type n_knn: int, optional
|
|
143
|
+
|
|
144
|
+
:return: Reaction data containing the extracted context graph.
|
|
145
|
+
:rtype: Dict[str, Any]
|
|
146
|
+
"""
|
|
147
|
+
context_data: Dict[str, Any] = copy.copy(data)
|
|
148
|
+
its = context_data[its_key]
|
|
149
|
+
context = RadiusExpand.extract_k(its, n_knn)
|
|
150
|
+
context_data[context_key] = context
|
|
151
|
+
return context_data
|
|
152
|
+
|
|
153
|
+
@classmethod
|
|
154
|
+
def paralle_context_extraction(
|
|
155
|
+
cls,
|
|
156
|
+
data: List[Dict[str, Any]],
|
|
157
|
+
its_key: str = "ITS",
|
|
158
|
+
context_key: str = "K",
|
|
159
|
+
n_jobs: int = 1,
|
|
160
|
+
verbose: int = 0,
|
|
161
|
+
n_knn: int = 0,
|
|
162
|
+
) -> List[Dict[str, Any]]:
|
|
163
|
+
"""Performs parallel extraction of reaction contexts for multiple
|
|
164
|
+
reaction dictionaries.
|
|
165
|
+
|
|
166
|
+
:param data: A list of reaction data dictionaries, each containing an ITS graph.
|
|
167
|
+
:type data: List[Dict[str, Any]]
|
|
168
|
+
:param its_key: Key in the dictionary for retrieving the ITS graph.
|
|
169
|
+
Default is ITS.
|
|
170
|
+
:type its_key: str, optional
|
|
171
|
+
:param context_key: Key under which to store the extracted context subgraph.
|
|
172
|
+
Default is K.
|
|
173
|
+
:type context_key: str, optional
|
|
174
|
+
:param n_jobs: Number of parallel jobs to use. Default is 1.
|
|
175
|
+
:type n_jobs: int, optional
|
|
176
|
+
:param verbose: Verbosity level for the parallel processing. Default is 0.
|
|
177
|
+
:type verbose: int, optional
|
|
178
|
+
:param n_knn: Number of neighbor levels to include for context extraction.
|
|
179
|
+
Default is 0.
|
|
180
|
+
:type n_knn: int, optional
|
|
181
|
+
|
|
182
|
+
:return: Reaction records augmented with their context graphs and
|
|
183
|
+
longest extension paths.
|
|
184
|
+
:rtype: List[Dict[str, Any]]
|
|
185
|
+
"""
|
|
186
|
+
return Parallel(n_jobs=n_jobs, verbose=verbose)(
|
|
187
|
+
delayed(cls.context_extraction)(reaction, its_key, context_key, n_knn)
|
|
188
|
+
for reaction in data
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
@staticmethod
|
|
192
|
+
def remove_normal_edges(graph: nx.Graph, property_key: str) -> nx.Graph:
|
|
193
|
+
"""Removes edges from a graph where the specified edge attribute has a
|
|
194
|
+
value of 0.
|
|
195
|
+
|
|
196
|
+
:param graph: The input graph to modify.
|
|
197
|
+
:type graph: nx.Graph
|
|
198
|
+
:param property_key: The key of the edge attribute to check for removal;
|
|
199
|
+
edges with a value of 0 will be removed.
|
|
200
|
+
:type property_key: str
|
|
201
|
+
|
|
202
|
+
:return: A copy of the input graph with the specified edges removed.
|
|
203
|
+
:rtype: nx.Graph
|
|
204
|
+
"""
|
|
205
|
+
filtered_graph = graph.copy()
|
|
206
|
+
edges_to_remove = [
|
|
207
|
+
(u, v)
|
|
208
|
+
for u, v, attrs in filtered_graph.edges(data=True)
|
|
209
|
+
if attrs.get(property_key, 1) == 0
|
|
210
|
+
]
|
|
211
|
+
filtered_graph.remove_edges_from(edges_to_remove)
|
|
212
|
+
return filtered_graph
|
|
213
|
+
|
|
214
|
+
@staticmethod
|
|
215
|
+
def longest_radius_extension(G: nx.Graph, rc_nodes: List[int]) -> List[int]:
|
|
216
|
+
"""Computes the longest unique extension path in the graph starting
|
|
217
|
+
from the given reaction center nodes, constrained by traversing only
|
|
218
|
+
those edges where the 'standard_order' attribute equals 0.
|
|
219
|
+
|
|
220
|
+
This method uses a depth-first search (DFS) strategy to explore all possible
|
|
221
|
+
unique paths and returns the longest one.
|
|
222
|
+
|
|
223
|
+
:param G: The graph to search for extension paths.
|
|
224
|
+
:type G: nx.Graph
|
|
225
|
+
:param rc_nodes: A list of reaction center node indices to serve as starting points for the search.
|
|
226
|
+
:type rc_nodes: List[int]
|
|
227
|
+
|
|
228
|
+
:return: A list of node indices representing the longest unique extension path found.
|
|
229
|
+
:rtype: List[int]
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
def dfs(node: int, visited: Set[int], path: List[int]) -> List[int]:
|
|
233
|
+
visited.add(node)
|
|
234
|
+
longest_path = path.copy()
|
|
235
|
+
for neighbor in G.neighbors(node):
|
|
236
|
+
edge_data = G.get_edge_data(node, neighbor)
|
|
237
|
+
if edge_data.get("standard_order", 1) == 0 and neighbor not in visited:
|
|
238
|
+
current_path = dfs(neighbor, visited.copy(), path + [neighbor])
|
|
239
|
+
if len(current_path) > len(longest_path):
|
|
240
|
+
longest_path = current_path
|
|
241
|
+
return longest_path
|
|
242
|
+
|
|
243
|
+
longest_extension: List[int] = []
|
|
244
|
+
visited_overall: Set[int] = set()
|
|
245
|
+
|
|
246
|
+
for rc_node in rc_nodes:
|
|
247
|
+
if rc_node not in visited_overall:
|
|
248
|
+
path = dfs(rc_node, visited_overall.copy(), [rc_node])
|
|
249
|
+
visited_overall.update(path)
|
|
250
|
+
if len(path) > len(longest_extension):
|
|
251
|
+
longest_extension = path
|
|
252
|
+
return longest_extension
|
|
@@ -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
|
+
]
|
synkit/Graph/FG/api.py
ADDED
|
@@ -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)
|