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,442 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import networkx as nx
|
|
3
|
+
from operator import eq
|
|
4
|
+
from itertools import combinations
|
|
5
|
+
from functools import wraps
|
|
6
|
+
from joblib import Parallel, delayed
|
|
7
|
+
from typing import Dict, List, Tuple, Union, Optional
|
|
8
|
+
from networkx.algorithms.isomorphism import generic_node_match, generic_edge_match
|
|
9
|
+
|
|
10
|
+
from synkit.IO.chem_converter import rsmi_to_graph
|
|
11
|
+
from synkit.Graph.ITS.its_decompose import get_rc
|
|
12
|
+
from synkit.Graph.ITS.its_construction import ITSConstruction
|
|
13
|
+
from synkit.Chem.utils import enumerate_tautomers, mapping_success_rate
|
|
14
|
+
|
|
15
|
+
CONSTITUTIONAL_NODE_ATTRS = (
|
|
16
|
+
"element",
|
|
17
|
+
"aromatic",
|
|
18
|
+
"hcount",
|
|
19
|
+
"charge",
|
|
20
|
+
"neighbors",
|
|
21
|
+
"atom_map",
|
|
22
|
+
)
|
|
23
|
+
CONSTITUTIONAL_EDGE_ATTRS = ("order",)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class _DualMethod:
|
|
27
|
+
"""Bind a method to either an instance or the class."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, func):
|
|
30
|
+
self.func = func
|
|
31
|
+
wraps(func)(self)
|
|
32
|
+
|
|
33
|
+
def __get__(self, obj, cls=None):
|
|
34
|
+
@wraps(self.func)
|
|
35
|
+
def wrapper(*args, **kwargs):
|
|
36
|
+
return self.func(obj, cls, *args, **kwargs)
|
|
37
|
+
|
|
38
|
+
return wrapper
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AAMValidator:
|
|
42
|
+
"""A utility class for validating atom‐atom mappings (AAM) in reaction
|
|
43
|
+
SMILES.
|
|
44
|
+
|
|
45
|
+
Provides methods to compare mapped SMILES against ground truth by
|
|
46
|
+
using reaction‐center (RC) or ITS‐graph isomorphism checks, including
|
|
47
|
+
tautomer enumeration support and batch validation over tabular data.
|
|
48
|
+
|
|
49
|
+
Quick start
|
|
50
|
+
-----------
|
|
51
|
+
>>> from synkit.Chem.Mapper import AAMValidator
|
|
52
|
+
>>> validator = AAMValidator()
|
|
53
|
+
>>> rsmi_1 = (
|
|
54
|
+
'[CH3:1][C:2](=[O:3])[OH:4].[CH3:5][OH:6]'
|
|
55
|
+
'>>'
|
|
56
|
+
'[CH3:1][C:2](=[O:3])[O:6][CH3:5].[OH2:4]')
|
|
57
|
+
>>> rsmi_2 = (
|
|
58
|
+
'[CH3:5][C:1](=[O:2])[OH:3].[CH3:6][OH:4]'
|
|
59
|
+
'>>'
|
|
60
|
+
'[CH3:5][C:1](=[O:2])[O:4][CH3:6].[OH2:3]')
|
|
61
|
+
>>> is_eq = validator.smiles_check(rsmi_1, rsmi_2, check_method='ITS')
|
|
62
|
+
>>> print(is_eq)
|
|
63
|
+
>>> True
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(self, strip_unbalanced_maps: bool = True) -> None:
|
|
67
|
+
"""Initialize the AAMValidator.
|
|
68
|
+
|
|
69
|
+
:param strip_unbalanced_maps: If True, remove atoms whose atom-map
|
|
70
|
+
labels are present on only one side before building ITS/RC graphs.
|
|
71
|
+
This reproduces the more permissive SynRXN benchmark behavior.
|
|
72
|
+
:type strip_unbalanced_maps: bool
|
|
73
|
+
"""
|
|
74
|
+
self.strip_unbalanced_maps = strip_unbalanced_maps
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def _resolve_strip_unbalanced_maps(
|
|
78
|
+
instance: Optional["AAMValidator"],
|
|
79
|
+
strip_unbalanced_maps: Optional[bool],
|
|
80
|
+
) -> bool:
|
|
81
|
+
"""Resolve call-level override against the instance default."""
|
|
82
|
+
if strip_unbalanced_maps is not None:
|
|
83
|
+
return strip_unbalanced_maps
|
|
84
|
+
if instance is not None:
|
|
85
|
+
return instance.strip_unbalanced_maps
|
|
86
|
+
return True
|
|
87
|
+
|
|
88
|
+
@staticmethod
|
|
89
|
+
def _node_atom_map(graph: nx.Graph, node: object) -> Optional[int]:
|
|
90
|
+
"""Return a node's atom-map label when available."""
|
|
91
|
+
value = graph.nodes[node].get("atom_map", node)
|
|
92
|
+
try:
|
|
93
|
+
return int(value)
|
|
94
|
+
except (TypeError, ValueError):
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def _strip_unbalanced_map_nodes(
|
|
99
|
+
reactant_graph: nx.Graph,
|
|
100
|
+
product_graph: nx.Graph,
|
|
101
|
+
) -> Tuple[nx.Graph, nx.Graph]:
|
|
102
|
+
"""Remove nodes whose atom maps are not present on both sides."""
|
|
103
|
+
reactant_maps = {
|
|
104
|
+
atom_map
|
|
105
|
+
for node in reactant_graph.nodes
|
|
106
|
+
if (atom_map := AAMValidator._node_atom_map(reactant_graph, node))
|
|
107
|
+
is not None
|
|
108
|
+
}
|
|
109
|
+
product_maps = {
|
|
110
|
+
atom_map
|
|
111
|
+
for node in product_graph.nodes
|
|
112
|
+
if (atom_map := AAMValidator._node_atom_map(product_graph, node))
|
|
113
|
+
is not None
|
|
114
|
+
}
|
|
115
|
+
common_maps = reactant_maps & product_maps
|
|
116
|
+
|
|
117
|
+
stripped_reactant = reactant_graph.copy()
|
|
118
|
+
stripped_product = product_graph.copy()
|
|
119
|
+
stripped_reactant.remove_nodes_from(
|
|
120
|
+
[
|
|
121
|
+
node
|
|
122
|
+
for node in stripped_reactant.nodes
|
|
123
|
+
if AAMValidator._node_atom_map(stripped_reactant, node)
|
|
124
|
+
not in common_maps
|
|
125
|
+
]
|
|
126
|
+
)
|
|
127
|
+
stripped_product.remove_nodes_from(
|
|
128
|
+
[
|
|
129
|
+
node
|
|
130
|
+
for node in stripped_product.nodes
|
|
131
|
+
if AAMValidator._node_atom_map(stripped_product, node)
|
|
132
|
+
not in common_maps
|
|
133
|
+
]
|
|
134
|
+
)
|
|
135
|
+
return stripped_reactant, stripped_product
|
|
136
|
+
|
|
137
|
+
@staticmethod
|
|
138
|
+
def check_equivariant_graph(
|
|
139
|
+
its_graphs: List[nx.Graph],
|
|
140
|
+
) -> Tuple[List[Tuple[int, int]], int]:
|
|
141
|
+
"""Identify all pairs of isomorphic ITS graphs.
|
|
142
|
+
|
|
143
|
+
:param its_graphs: A list of ITS graphs to compare.
|
|
144
|
+
:type its_graphs: list of networkx.Graph
|
|
145
|
+
:return:
|
|
146
|
+
- A list of index‐pairs `(i, j)` where `its_graphs[i]` is isomorphic to `its_graphs[j]`.
|
|
147
|
+
- The total count of such isomorphic pairs.
|
|
148
|
+
:rtype: tuple (list of tuple of int, int, int)
|
|
149
|
+
"""
|
|
150
|
+
# typesGH is one paired state attribute; compare its complete value.
|
|
151
|
+
node_match = generic_node_match("typesGH", "*", eq)
|
|
152
|
+
edge_match = generic_edge_match("order", 1, eq)
|
|
153
|
+
|
|
154
|
+
classified = []
|
|
155
|
+
for i, j in combinations(range(len(its_graphs)), 2):
|
|
156
|
+
if nx.is_isomorphic(
|
|
157
|
+
its_graphs[i],
|
|
158
|
+
its_graphs[j],
|
|
159
|
+
node_match=node_match,
|
|
160
|
+
edge_match=edge_match,
|
|
161
|
+
):
|
|
162
|
+
classified.append((i, j))
|
|
163
|
+
|
|
164
|
+
return classified, len(classified)
|
|
165
|
+
|
|
166
|
+
@_DualMethod
|
|
167
|
+
def smiles_checks(
|
|
168
|
+
self,
|
|
169
|
+
cls,
|
|
170
|
+
mapped_smile: str,
|
|
171
|
+
ground_truth: str,
|
|
172
|
+
ignore_aromaticity: bool = False,
|
|
173
|
+
strip_unbalanced_maps: Optional[bool] = None,
|
|
174
|
+
constitutional_only: bool = False,
|
|
175
|
+
) -> Dict[str, bool]:
|
|
176
|
+
"""Return ITS and reaction-centre verdicts from one graph construction.
|
|
177
|
+
|
|
178
|
+
:param mapped_smile: The mapped SMILES to validate.
|
|
179
|
+
:type mapped_smile: str
|
|
180
|
+
:param ground_truth: The reference SMILES string.
|
|
181
|
+
:type ground_truth: str
|
|
182
|
+
:param ignore_aromaticity: If True, ignore aromaticity
|
|
183
|
+
differences in ITS construction.
|
|
184
|
+
:type ignore_aromaticity: bool
|
|
185
|
+
:param strip_unbalanced_maps: If True, remove atom-map labels present
|
|
186
|
+
on only one side before graph comparison. If None, use the
|
|
187
|
+
instance default or False for class-level calls.
|
|
188
|
+
:type strip_unbalanced_maps: bool or None
|
|
189
|
+
:param constitutional_only: Convert only attributes used by the
|
|
190
|
+
ITS/RC isomorphism test and omit graph-level stereo descriptors.
|
|
191
|
+
:type constitutional_only: bool
|
|
192
|
+
:return: Dictionary with Boolean ``"ITS"`` and ``"RC"`` verdicts.
|
|
193
|
+
:rtype: Dict[str, bool]
|
|
194
|
+
"""
|
|
195
|
+
its_graphs, rc_graphs = [], []
|
|
196
|
+
strip_unbalanced_maps = cls._resolve_strip_unbalanced_maps(
|
|
197
|
+
self, strip_unbalanced_maps
|
|
198
|
+
)
|
|
199
|
+
try:
|
|
200
|
+
for rsmi in (mapped_smile, ground_truth):
|
|
201
|
+
G, H = rsmi_to_graph(
|
|
202
|
+
rsmi=rsmi,
|
|
203
|
+
sanitize=True,
|
|
204
|
+
drop_non_aam=True,
|
|
205
|
+
node_attrs=(
|
|
206
|
+
CONSTITUTIONAL_NODE_ATTRS if constitutional_only else None
|
|
207
|
+
),
|
|
208
|
+
edge_attrs=(
|
|
209
|
+
CONSTITUTIONAL_EDGE_ATTRS if constitutional_only else None
|
|
210
|
+
),
|
|
211
|
+
include_stereo_descriptors=not constitutional_only,
|
|
212
|
+
)
|
|
213
|
+
if strip_unbalanced_maps:
|
|
214
|
+
G, H = cls._strip_unbalanced_map_nodes(G, H)
|
|
215
|
+
its = ITSConstruction().ITSGraph(
|
|
216
|
+
G, H, ignore_aromaticity=ignore_aromaticity
|
|
217
|
+
)
|
|
218
|
+
its_graphs.append(its)
|
|
219
|
+
rc_graphs.append(get_rc(its))
|
|
220
|
+
|
|
221
|
+
_, its_count = AAMValidator.check_equivariant_graph(its_graphs)
|
|
222
|
+
_, rc_count = AAMValidator.check_equivariant_graph(rc_graphs)
|
|
223
|
+
return {"ITS": its_count == 1, "RC": rc_count == 1}
|
|
224
|
+
except Exception:
|
|
225
|
+
return {"ITS": False, "RC": False}
|
|
226
|
+
|
|
227
|
+
@_DualMethod
|
|
228
|
+
def smiles_check(
|
|
229
|
+
self,
|
|
230
|
+
cls,
|
|
231
|
+
mapped_smile: str,
|
|
232
|
+
ground_truth: str,
|
|
233
|
+
check_method: str = "RC",
|
|
234
|
+
ignore_aromaticity: bool = False,
|
|
235
|
+
strip_unbalanced_maps: Optional[bool] = None,
|
|
236
|
+
constitutional_only: bool = False,
|
|
237
|
+
) -> bool:
|
|
238
|
+
"""Validate one mapped SMILES against ground truth.
|
|
239
|
+
|
|
240
|
+
This compatibility wrapper selects one result from
|
|
241
|
+
:meth:`smiles_checks`. Use ``smiles_checks`` when both ITS and RC
|
|
242
|
+
verdicts are required so the endpoint and ITS graphs are built once.
|
|
243
|
+
"""
|
|
244
|
+
verdicts = cls.smiles_checks(
|
|
245
|
+
mapped_smile,
|
|
246
|
+
ground_truth,
|
|
247
|
+
ignore_aromaticity=ignore_aromaticity,
|
|
248
|
+
strip_unbalanced_maps=cls._resolve_strip_unbalanced_maps(
|
|
249
|
+
self, strip_unbalanced_maps
|
|
250
|
+
),
|
|
251
|
+
constitutional_only=constitutional_only,
|
|
252
|
+
)
|
|
253
|
+
key = "RC" if check_method.upper() == "RC" else "ITS"
|
|
254
|
+
return verdicts[key]
|
|
255
|
+
|
|
256
|
+
@_DualMethod
|
|
257
|
+
def smiles_check_tautomer(
|
|
258
|
+
self,
|
|
259
|
+
cls,
|
|
260
|
+
mapped_smile: str,
|
|
261
|
+
ground_truth: str,
|
|
262
|
+
check_method: str = "RC",
|
|
263
|
+
ignore_aromaticity: bool = False,
|
|
264
|
+
strip_unbalanced_maps: Optional[bool] = None,
|
|
265
|
+
) -> Optional[bool]:
|
|
266
|
+
"""Validate against all tautomers of a ground truth SMILES.
|
|
267
|
+
|
|
268
|
+
:param mapped_smile: The mapped SMILES to test.
|
|
269
|
+
:type mapped_smile: str
|
|
270
|
+
:param ground_truth: The reference SMILES for generating tautomers.
|
|
271
|
+
:type ground_truth: str
|
|
272
|
+
:param check_method: `"RC"` or `"ITS"` as in `smiles_check`.
|
|
273
|
+
:type check_method: str
|
|
274
|
+
:param ignore_aromaticity: If True, ignore aromaticity in ITS construction.
|
|
275
|
+
:type ignore_aromaticity: bool
|
|
276
|
+
:param strip_unbalanced_maps: If True, remove atom-map labels present
|
|
277
|
+
on only one side before graph comparison. If None, use the
|
|
278
|
+
instance default or False for class-level calls.
|
|
279
|
+
:type strip_unbalanced_maps: bool or None
|
|
280
|
+
:return:
|
|
281
|
+
- `True` if any tautomer matches.
|
|
282
|
+
- `False` if none match.
|
|
283
|
+
- `None` if an error occurs.
|
|
284
|
+
:rtype: bool or None
|
|
285
|
+
"""
|
|
286
|
+
strip_unbalanced_maps = cls._resolve_strip_unbalanced_maps(
|
|
287
|
+
self, strip_unbalanced_maps
|
|
288
|
+
)
|
|
289
|
+
try:
|
|
290
|
+
tautomers = enumerate_tautomers(ground_truth)
|
|
291
|
+
return any(
|
|
292
|
+
cls.smiles_check(
|
|
293
|
+
mapped_smile,
|
|
294
|
+
taut,
|
|
295
|
+
check_method,
|
|
296
|
+
ignore_aromaticity,
|
|
297
|
+
strip_unbalanced_maps,
|
|
298
|
+
)
|
|
299
|
+
for taut in tautomers
|
|
300
|
+
)
|
|
301
|
+
except Exception:
|
|
302
|
+
return None
|
|
303
|
+
|
|
304
|
+
@_DualMethod
|
|
305
|
+
def check_pair(
|
|
306
|
+
self,
|
|
307
|
+
cls,
|
|
308
|
+
mapping: Dict[str, str],
|
|
309
|
+
mapped_col: str,
|
|
310
|
+
ground_truth_col: str,
|
|
311
|
+
check_method: str = "RC",
|
|
312
|
+
ignore_aromaticity: bool = False,
|
|
313
|
+
ignore_tautomers: bool = True,
|
|
314
|
+
strip_unbalanced_maps: Optional[bool] = None,
|
|
315
|
+
) -> bool:
|
|
316
|
+
"""Validate a single record (dict) entry for equivalence.
|
|
317
|
+
|
|
318
|
+
:param mapping: A record containing both mapped and ground‐truth SMILES.
|
|
319
|
+
:type mapping: dict of str→str
|
|
320
|
+
:param mapped_col: Key for the mapped SMILES in `mapping`.
|
|
321
|
+
:type mapped_col: str
|
|
322
|
+
:param ground_truth_col: Key for the ground-truth SMILES in `mapping`.
|
|
323
|
+
:type ground_truth_col: str
|
|
324
|
+
:param check_method: `"RC"` or `"ITS"`.
|
|
325
|
+
:type check_method: str
|
|
326
|
+
:param ignore_aromaticity: If True, ignore aromaticity in ITS construction.
|
|
327
|
+
:type ignore_aromaticity: bool
|
|
328
|
+
:param ignore_tautomers: If True, skip tautomer enumeration.
|
|
329
|
+
:type ignore_tautomers: bool
|
|
330
|
+
:param strip_unbalanced_maps: If True, remove atom-map labels present
|
|
331
|
+
on only one side before graph comparison. If None, use the
|
|
332
|
+
instance default or False for class-level calls.
|
|
333
|
+
:type strip_unbalanced_maps: bool or None
|
|
334
|
+
:return: Validation result for this single pair.
|
|
335
|
+
:rtype: bool
|
|
336
|
+
"""
|
|
337
|
+
strip_unbalanced_maps = cls._resolve_strip_unbalanced_maps(
|
|
338
|
+
self, strip_unbalanced_maps
|
|
339
|
+
)
|
|
340
|
+
if ignore_tautomers:
|
|
341
|
+
return cls.smiles_check(
|
|
342
|
+
mapping[mapped_col],
|
|
343
|
+
mapping[ground_truth_col],
|
|
344
|
+
check_method,
|
|
345
|
+
ignore_aromaticity,
|
|
346
|
+
strip_unbalanced_maps,
|
|
347
|
+
)
|
|
348
|
+
else:
|
|
349
|
+
return cls.smiles_check_tautomer(
|
|
350
|
+
mapping[mapped_col],
|
|
351
|
+
mapping[ground_truth_col],
|
|
352
|
+
check_method,
|
|
353
|
+
ignore_aromaticity,
|
|
354
|
+
strip_unbalanced_maps,
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
@_DualMethod
|
|
358
|
+
def validate_smiles(
|
|
359
|
+
self,
|
|
360
|
+
cls,
|
|
361
|
+
data: Union[pd.DataFrame, List[Dict[str, str]]],
|
|
362
|
+
ground_truth_col: str = "ground_truth",
|
|
363
|
+
mapped_cols: List[str] = ["rxn_mapper", "graphormer", "local_mapper"],
|
|
364
|
+
check_method: str = "RC",
|
|
365
|
+
ignore_aromaticity: bool = False,
|
|
366
|
+
n_jobs: int = 1,
|
|
367
|
+
verbose: int = 0,
|
|
368
|
+
ignore_tautomers: bool = True,
|
|
369
|
+
strip_unbalanced_maps: Optional[bool] = None,
|
|
370
|
+
) -> List[Dict[str, Union[str, float, List[bool]]]]:
|
|
371
|
+
"""Batch-validate mapped SMILES in tabular or list-of-dicts form.
|
|
372
|
+
|
|
373
|
+
:param data: A pandas DataFrame or list of dicts, each row containing at least
|
|
374
|
+
`ground_truth_col` and each entry in `mapped_cols`.
|
|
375
|
+
:type data: pandas.DataFrame or list of dict
|
|
376
|
+
:param ground_truth_col: Column/key name for the ground-truth SMILES.
|
|
377
|
+
:type ground_truth_col: str
|
|
378
|
+
:param mapped_cols: List of column/key names for mapped SMILES to validate.
|
|
379
|
+
:type mapped_cols: list of str
|
|
380
|
+
:param check_method: `"RC"` or `"ITS"` validation method.
|
|
381
|
+
:type check_method: str
|
|
382
|
+
:param ignore_aromaticity: If True, ignore aromaticity in ITS construction.
|
|
383
|
+
:type ignore_aromaticity: bool
|
|
384
|
+
:param n_jobs: Number of parallel jobs to use (joblib).
|
|
385
|
+
:type n_jobs: int
|
|
386
|
+
:param verbose: Verbosity level for parallel execution.
|
|
387
|
+
:type verbose: int
|
|
388
|
+
:param ignore_tautomers: If True, use simple pairwise check; otherwise enumerate tautomers.
|
|
389
|
+
:type ignore_tautomers: bool
|
|
390
|
+
:param strip_unbalanced_maps: If True, remove atom-map labels present
|
|
391
|
+
on only one side before graph comparison. If None, use the
|
|
392
|
+
instance default or False for class-level calls.
|
|
393
|
+
:type strip_unbalanced_maps: bool or None
|
|
394
|
+
:return: A list of dicts, one per mapper, with keys:
|
|
395
|
+
- `"mapper"`: the mapper name
|
|
396
|
+
- `"accuracy"`: percentage correct (float)
|
|
397
|
+
- `"results"`: list of individual bool results
|
|
398
|
+
- `"success_rate"`: mapping success rate metric
|
|
399
|
+
:rtype: list of dict
|
|
400
|
+
:raises ValueError: If `data` is not a DataFrame or list of dicts.
|
|
401
|
+
"""
|
|
402
|
+
validation_results = []
|
|
403
|
+
|
|
404
|
+
# Normalize to list-of-dicts
|
|
405
|
+
if isinstance(data, pd.DataFrame):
|
|
406
|
+
mappings = data.to_dict("records")
|
|
407
|
+
elif isinstance(data, list):
|
|
408
|
+
mappings = data
|
|
409
|
+
else:
|
|
410
|
+
raise ValueError(
|
|
411
|
+
"Data must be either a pandas DataFrame or a list of dictionaries."
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
strip_unbalanced_maps = cls._resolve_strip_unbalanced_maps(
|
|
415
|
+
self, strip_unbalanced_maps
|
|
416
|
+
)
|
|
417
|
+
for mapped_col in mapped_cols:
|
|
418
|
+
results = Parallel(n_jobs=n_jobs, verbose=verbose)(
|
|
419
|
+
delayed(cls.check_pair)(
|
|
420
|
+
mapping,
|
|
421
|
+
mapped_col,
|
|
422
|
+
ground_truth_col,
|
|
423
|
+
check_method,
|
|
424
|
+
ignore_aromaticity,
|
|
425
|
+
ignore_tautomers,
|
|
426
|
+
strip_unbalanced_maps,
|
|
427
|
+
)
|
|
428
|
+
for mapping in mappings
|
|
429
|
+
)
|
|
430
|
+
accuracy = sum(results) / len(mappings) if mappings else 0.0
|
|
431
|
+
validation_results.append(
|
|
432
|
+
{
|
|
433
|
+
"mapper": mapped_col,
|
|
434
|
+
"accuracy": round(100 * accuracy, 2),
|
|
435
|
+
"results": results,
|
|
436
|
+
"success_rate": mapping_success_rate(
|
|
437
|
+
[m[mapped_col] for m in mappings]
|
|
438
|
+
),
|
|
439
|
+
}
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
return validation_results
|