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,648 @@
|
|
|
1
|
+
"""Exact canonicalization of configured permutation-labelled stereographs.
|
|
2
|
+
|
|
3
|
+
The public entry points in this module cover SynKit's complete configured
|
|
4
|
+
stereo catalogue. The tetrahedral-specific functions are retained as narrow
|
|
5
|
+
compatibility helpers, not as a separate stereograph model.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from collections.abc import Callable, Iterable, Mapping, Sequence
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from typing import Any, Hashable, Literal
|
|
14
|
+
|
|
15
|
+
import networkx as nx
|
|
16
|
+
|
|
17
|
+
from synkit.Graph.Canon.exact import (
|
|
18
|
+
AutomorphismWitness,
|
|
19
|
+
ExactCanonicalResult,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from .descriptors import (
|
|
23
|
+
Reference,
|
|
24
|
+
StereoValue,
|
|
25
|
+
TetrahedralStereo,
|
|
26
|
+
)
|
|
27
|
+
from .orbits import SHAPE_DEFINITIONS
|
|
28
|
+
|
|
29
|
+
# ``/2`` is the persisted wire-schema revision of the complete configured
|
|
30
|
+
# certificate. It is deliberately not exposed as a second scientific model.
|
|
31
|
+
STEREOGRAPH_SCHEMA = "synkit.canonical-stereograph/2"
|
|
32
|
+
|
|
33
|
+
_DEFAULT_ATOM_COLOR_KEYS = (
|
|
34
|
+
"element",
|
|
35
|
+
"isotope",
|
|
36
|
+
"charge",
|
|
37
|
+
"formal_charge",
|
|
38
|
+
"radical",
|
|
39
|
+
"radical_electrons",
|
|
40
|
+
"aromatic",
|
|
41
|
+
"hcount",
|
|
42
|
+
"lone_pairs",
|
|
43
|
+
)
|
|
44
|
+
_DEFAULT_BOND_COLOR_KEYS = (
|
|
45
|
+
"order",
|
|
46
|
+
"standard_order",
|
|
47
|
+
"bond_type",
|
|
48
|
+
"aromatic",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
AttributeSelector = str | Sequence[str] | Callable[[Mapping[str, Any]], Any]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass(frozen=True)
|
|
55
|
+
class AtomVertex:
|
|
56
|
+
"""Auxiliary-graph handle for one base-graph atom."""
|
|
57
|
+
|
|
58
|
+
reference: Hashable
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class BondVertex:
|
|
63
|
+
"""Auxiliary-graph handle for one base-graph bond/resource."""
|
|
64
|
+
|
|
65
|
+
index: int
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass(frozen=True)
|
|
69
|
+
class StereoLocusVertex:
|
|
70
|
+
"""Auxiliary-graph handle for one configured stereo locus."""
|
|
71
|
+
|
|
72
|
+
index: int
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass(frozen=True)
|
|
76
|
+
class StereoPortVertex:
|
|
77
|
+
"""One owner-specific ligand incidence at a stereo locus."""
|
|
78
|
+
|
|
79
|
+
locus: int
|
|
80
|
+
position: int
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass(frozen=True)
|
|
84
|
+
class StereoTupleVertex:
|
|
85
|
+
"""One allowed ordered tuple in a local configuration orbit."""
|
|
86
|
+
|
|
87
|
+
locus: int
|
|
88
|
+
index: int
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass(frozen=True)
|
|
92
|
+
class StereoSlotVertex:
|
|
93
|
+
"""Position-coloured connection between a tuple and one port."""
|
|
94
|
+
|
|
95
|
+
locus: int
|
|
96
|
+
tuple_index: int
|
|
97
|
+
position: int
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass(frozen=True)
|
|
101
|
+
class VirtualResourceVertex:
|
|
102
|
+
"""Owner-scoped hidden hydrogen or lone-pair resource."""
|
|
103
|
+
|
|
104
|
+
locus: int
|
|
105
|
+
position: int
|
|
106
|
+
kind: str
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@dataclass(frozen=True)
|
|
110
|
+
class CanonicalStereographResult:
|
|
111
|
+
"""Complete configured-stereograph identity and projected witnesses.
|
|
112
|
+
|
|
113
|
+
``canonical_code`` is the deterministic, versioned exact certificate.
|
|
114
|
+
Atom/bond orders and projected automorphisms retain input handles and are
|
|
115
|
+
witnesses modulo configured-stereograph automorphism, not unique choices
|
|
116
|
+
among constitutionally symmetric atoms or ports.
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
schema: str
|
|
120
|
+
canonical_code: str
|
|
121
|
+
canonical_digest: str
|
|
122
|
+
atom_order: tuple[Hashable, ...]
|
|
123
|
+
bond_order: tuple[tuple[Hashable, Hashable], ...]
|
|
124
|
+
locus_order: tuple[int, ...]
|
|
125
|
+
port_order: tuple[StereoPortVertex, ...]
|
|
126
|
+
atom_automorphisms: tuple[AutomorphismWitness, ...]
|
|
127
|
+
locus_automorphisms: tuple[AutomorphismWitness, ...]
|
|
128
|
+
port_automorphisms: tuple[AutomorphismWitness, ...]
|
|
129
|
+
auxiliary: ExactCanonicalResult
|
|
130
|
+
identity_profile: str = "attributed_graph"
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def complete(self) -> bool:
|
|
134
|
+
return self.auxiliary.complete
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def exact(self) -> bool:
|
|
138
|
+
return self.auxiliary.exact
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def canonical_certificate(self) -> str:
|
|
142
|
+
"""Return the exact, versioned stereograph serialization."""
|
|
143
|
+
return self.canonical_code
|
|
144
|
+
|
|
145
|
+
def same_stereograph(self, other: object) -> bool:
|
|
146
|
+
"""Compare exact versioned certificates, not finite digests."""
|
|
147
|
+
return (
|
|
148
|
+
isinstance(other, CanonicalStereographResult)
|
|
149
|
+
and self.schema == other.schema
|
|
150
|
+
and self.identity_profile == other.identity_profile
|
|
151
|
+
and self.auxiliary.same_canonical_graph(other.auxiliary)
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class StereographMirrorStatus(str, Enum):
|
|
156
|
+
"""Exact mirror-comparison outcome for a configured stereograph."""
|
|
157
|
+
|
|
158
|
+
ACHIRAL = "achiral"
|
|
159
|
+
CHIRAL = "chiral"
|
|
160
|
+
INCOMPLETE = "incomplete"
|
|
161
|
+
UNSUPPORTED = "unsupported"
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@dataclass(frozen=True)
|
|
165
|
+
class StereographMirrorResult:
|
|
166
|
+
"""Evidence for exact comparison with a geometry-specific mirror.
|
|
167
|
+
|
|
168
|
+
Definitive results retain both complete exact certificates. Incomplete
|
|
169
|
+
or unsupported inputs deliberately return no plausible partial identity.
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
status: StereographMirrorStatus
|
|
173
|
+
descriptor_count: int
|
|
174
|
+
original: CanonicalStereographResult | None = None
|
|
175
|
+
mirror: CanonicalStereographResult | None = None
|
|
176
|
+
mirrored_descriptors: tuple[StereoValue, ...] = ()
|
|
177
|
+
atom_mirror_isomorphism: tuple[tuple[Hashable, Hashable], ...] | None = None
|
|
178
|
+
incomplete_loci: tuple[str, ...] = ()
|
|
179
|
+
unsupported_loci: tuple[str, ...] = ()
|
|
180
|
+
unsupported_families: tuple[str, ...] = ()
|
|
181
|
+
method: str = "exact_canonical_stereograph_mirror_comparison"
|
|
182
|
+
identity_profile: str = "attributed_graph"
|
|
183
|
+
original_identity: Any | None = None
|
|
184
|
+
mirror_identity: Any | None = None
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def is_definitive(self) -> bool:
|
|
188
|
+
return self.status in {
|
|
189
|
+
StereographMirrorStatus.ACHIRAL,
|
|
190
|
+
StereographMirrorStatus.CHIRAL,
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def is_chiral(self) -> bool | None:
|
|
195
|
+
if not self.is_definitive:
|
|
196
|
+
return None
|
|
197
|
+
return self.status is StereographMirrorStatus.CHIRAL
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@dataclass(frozen=True)
|
|
201
|
+
class _Expansion:
|
|
202
|
+
graph: nx.Graph
|
|
203
|
+
bond_endpoints: tuple[tuple[Hashable, Hashable], ...]
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _selected(
|
|
207
|
+
attributes: Mapping[str, Any],
|
|
208
|
+
selector: AttributeSelector,
|
|
209
|
+
) -> Any:
|
|
210
|
+
if isinstance(selector, str):
|
|
211
|
+
return attributes.get(selector)
|
|
212
|
+
if callable(selector):
|
|
213
|
+
return selector(attributes)
|
|
214
|
+
return tuple(attributes.get(key) for key in selector)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _add_coloured_node(
|
|
218
|
+
graph: nx.Graph,
|
|
219
|
+
node: Hashable,
|
|
220
|
+
color: tuple[Any, ...],
|
|
221
|
+
) -> None:
|
|
222
|
+
graph.add_node(node, color=color)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _validate_base_graph(graph: nx.Graph) -> None:
|
|
226
|
+
if not isinstance(graph, nx.Graph) or graph.is_directed():
|
|
227
|
+
raise TypeError(
|
|
228
|
+
"Configured molecular stereographs currently require an "
|
|
229
|
+
"undirected NetworkX Graph."
|
|
230
|
+
)
|
|
231
|
+
if graph.is_multigraph():
|
|
232
|
+
raise TypeError(
|
|
233
|
+
"Parallel resources must already be represented as typed "
|
|
234
|
+
"incidence vertices."
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def _material_port_resource(
|
|
239
|
+
base: nx.Graph,
|
|
240
|
+
bonds: Mapping[tuple[Hashable, Hashable], BondVertex],
|
|
241
|
+
owner: Hashable,
|
|
242
|
+
reference: Reference,
|
|
243
|
+
*,
|
|
244
|
+
geometry: str,
|
|
245
|
+
) -> BondVertex:
|
|
246
|
+
if reference not in base:
|
|
247
|
+
raise ValueError(f"{geometry} ligand reference {reference!r} is absent.")
|
|
248
|
+
if not base.has_edge(owner, reference):
|
|
249
|
+
raise ValueError(
|
|
250
|
+
f"{geometry} ligand {reference!r} is not bonded to owner {owner!r}."
|
|
251
|
+
)
|
|
252
|
+
return bonds[(owner, reference)]
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _add_configuration_orbit(
|
|
256
|
+
auxiliary: nx.Graph,
|
|
257
|
+
locus: StereoLocusVertex,
|
|
258
|
+
descriptor: StereoValue,
|
|
259
|
+
locus_index: int,
|
|
260
|
+
targets: Mapping[Reference, Hashable],
|
|
261
|
+
frame_positions: Sequence[int],
|
|
262
|
+
) -> None:
|
|
263
|
+
definition = SHAPE_DEFINITIONS[descriptor.descriptor_class]
|
|
264
|
+
orbit = definition.preserving_group.orbit(descriptor.configuration.frame)
|
|
265
|
+
for tuple_index, frame in enumerate(orbit):
|
|
266
|
+
relation = StereoTupleVertex(locus_index, tuple_index)
|
|
267
|
+
_add_coloured_node(
|
|
268
|
+
auxiliary,
|
|
269
|
+
relation,
|
|
270
|
+
("stereo_tuple", descriptor.descriptor_class),
|
|
271
|
+
)
|
|
272
|
+
auxiliary.add_edge(locus, relation)
|
|
273
|
+
for slot_position, frame_position in enumerate(frame_positions):
|
|
274
|
+
reference = frame[frame_position]
|
|
275
|
+
slot = StereoSlotVertex(locus_index, tuple_index, slot_position)
|
|
276
|
+
_add_coloured_node(
|
|
277
|
+
auxiliary,
|
|
278
|
+
slot,
|
|
279
|
+
(
|
|
280
|
+
"stereo_slot",
|
|
281
|
+
descriptor.descriptor_class,
|
|
282
|
+
slot_position,
|
|
283
|
+
),
|
|
284
|
+
)
|
|
285
|
+
auxiliary.add_edge(relation, slot)
|
|
286
|
+
auxiliary.add_edge(slot, targets[reference])
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def expand_tetrahedral_stereograph(
|
|
290
|
+
base_graph: nx.Graph,
|
|
291
|
+
descriptors: Iterable[TetrahedralStereo],
|
|
292
|
+
*,
|
|
293
|
+
atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
|
|
294
|
+
bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
|
|
295
|
+
) -> nx.Graph:
|
|
296
|
+
"""Expand tetrahedral stereo through the unified stereograph engine."""
|
|
297
|
+
fixed = _require_tetrahedral(tuple(descriptors))
|
|
298
|
+
return expand_stereograph(
|
|
299
|
+
base_graph,
|
|
300
|
+
fixed,
|
|
301
|
+
atom_color=atom_color,
|
|
302
|
+
bond_color=bond_color,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def expand_stereograph(
|
|
307
|
+
base_graph: nx.Graph,
|
|
308
|
+
descriptors: Iterable[StereoValue],
|
|
309
|
+
*,
|
|
310
|
+
atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
|
|
311
|
+
bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
|
|
312
|
+
) -> nx.Graph:
|
|
313
|
+
"""Expand a complete configured stereograph."""
|
|
314
|
+
from .configured import expand_configured_stereograph
|
|
315
|
+
|
|
316
|
+
return expand_configured_stereograph(
|
|
317
|
+
base_graph,
|
|
318
|
+
tuple(descriptors),
|
|
319
|
+
atom_color=atom_color,
|
|
320
|
+
bond_color=bond_color,
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def _require_tetrahedral(
|
|
325
|
+
descriptors: tuple[StereoValue, ...],
|
|
326
|
+
) -> tuple[TetrahedralStereo, ...]:
|
|
327
|
+
if any(not isinstance(item, TetrahedralStereo) for item in descriptors):
|
|
328
|
+
raise TypeError(
|
|
329
|
+
"This tetrahedral compatibility API accepts only "
|
|
330
|
+
"TetrahedralStereo descriptors."
|
|
331
|
+
)
|
|
332
|
+
return descriptors # type: ignore[return-value]
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def _expand_base_graph(
|
|
336
|
+
base_graph: nx.Graph,
|
|
337
|
+
*,
|
|
338
|
+
atom_color: AttributeSelector,
|
|
339
|
+
bond_color: AttributeSelector,
|
|
340
|
+
) -> _Expansion:
|
|
341
|
+
_validate_base_graph(base_graph)
|
|
342
|
+
base = base_graph.copy()
|
|
343
|
+
auxiliary = nx.Graph()
|
|
344
|
+
atom_vertices = {reference: AtomVertex(reference) for reference in base}
|
|
345
|
+
for reference, vertex in atom_vertices.items():
|
|
346
|
+
_add_coloured_node(
|
|
347
|
+
auxiliary,
|
|
348
|
+
vertex,
|
|
349
|
+
("atom", _selected(base.nodes[reference], atom_color)),
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
endpoints = []
|
|
353
|
+
for index, (left, right, attributes) in enumerate(base.edges(data=True)):
|
|
354
|
+
vertex = BondVertex(index)
|
|
355
|
+
endpoints.append((left, right))
|
|
356
|
+
_add_coloured_node(
|
|
357
|
+
auxiliary,
|
|
358
|
+
vertex,
|
|
359
|
+
("bond_resource", _selected(attributes, bond_color)),
|
|
360
|
+
)
|
|
361
|
+
auxiliary.add_edge(atom_vertices[left], vertex)
|
|
362
|
+
auxiliary.add_edge(vertex, atom_vertices[right])
|
|
363
|
+
return _Expansion(auxiliary, tuple(endpoints))
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def _project_witnesses(
|
|
367
|
+
result: ExactCanonicalResult,
|
|
368
|
+
vertex_type: type[AtomVertex] | type[StereoLocusVertex] | type[StereoPortVertex],
|
|
369
|
+
) -> tuple[AutomorphismWitness, ...]:
|
|
370
|
+
projected = []
|
|
371
|
+
for witness in result.automorphisms:
|
|
372
|
+
mapping = witness.as_dict()
|
|
373
|
+
pairs = []
|
|
374
|
+
for source, target in mapping.items():
|
|
375
|
+
if not isinstance(source, vertex_type):
|
|
376
|
+
continue
|
|
377
|
+
if not isinstance(target, vertex_type):
|
|
378
|
+
raise RuntimeError(
|
|
379
|
+
"Auxiliary automorphism changed a semantic vertex role."
|
|
380
|
+
)
|
|
381
|
+
if isinstance(source, AtomVertex):
|
|
382
|
+
pairs.append((source.reference, target.reference))
|
|
383
|
+
elif isinstance(source, StereoLocusVertex):
|
|
384
|
+
pairs.append((source.index, target.index))
|
|
385
|
+
else:
|
|
386
|
+
pairs.append((source, target))
|
|
387
|
+
projected.append(AutomorphismWitness(tuple(pairs)))
|
|
388
|
+
return tuple(projected)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def canonicalize_tetrahedral_stereograph(
|
|
392
|
+
base_graph: nx.Graph,
|
|
393
|
+
descriptors: Iterable[TetrahedralStereo],
|
|
394
|
+
*,
|
|
395
|
+
atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
|
|
396
|
+
bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
|
|
397
|
+
) -> CanonicalStereographResult:
|
|
398
|
+
"""Return exact stereograph identity for configured tetrahedral stereo."""
|
|
399
|
+
fixed = _require_tetrahedral(tuple(descriptors))
|
|
400
|
+
return canonicalize_stereograph(
|
|
401
|
+
base_graph,
|
|
402
|
+
fixed,
|
|
403
|
+
atom_color=atom_color,
|
|
404
|
+
bond_color=bond_color,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def canonicalize_stereograph(
|
|
409
|
+
base_graph: nx.Graph,
|
|
410
|
+
descriptors: Iterable[StereoValue],
|
|
411
|
+
*,
|
|
412
|
+
atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
|
|
413
|
+
bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
|
|
414
|
+
enumerate_automorphism_group: bool = True,
|
|
415
|
+
) -> CanonicalStereographResult:
|
|
416
|
+
"""Return exact identity for a complete configured stereograph."""
|
|
417
|
+
from .configured import canonicalize_configured_stereograph
|
|
418
|
+
|
|
419
|
+
return canonicalize_configured_stereograph(
|
|
420
|
+
base_graph,
|
|
421
|
+
tuple(descriptors),
|
|
422
|
+
atom_color=atom_color,
|
|
423
|
+
bond_color=bond_color,
|
|
424
|
+
enumerate_automorphism_group=enumerate_automorphism_group,
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def canonicalize_tetrahedral_registry(
|
|
429
|
+
base_graph: nx.Graph,
|
|
430
|
+
registry: Mapping[str, StereoValue],
|
|
431
|
+
*,
|
|
432
|
+
atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
|
|
433
|
+
bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
|
|
434
|
+
) -> CanonicalStereographResult:
|
|
435
|
+
"""Canonicalize a registry only when every entry is tetrahedral.
|
|
436
|
+
|
|
437
|
+
Rejecting other configured families is deliberate: silently omitting an
|
|
438
|
+
E/Z, axial, or coordination descriptor would produce an incomplete
|
|
439
|
+
stereochemical identity.
|
|
440
|
+
"""
|
|
441
|
+
descriptors = tuple(registry.values())
|
|
442
|
+
unsupported = tuple(
|
|
443
|
+
descriptor.descriptor_class
|
|
444
|
+
for descriptor in descriptors
|
|
445
|
+
if not isinstance(descriptor, TetrahedralStereo)
|
|
446
|
+
)
|
|
447
|
+
if unsupported:
|
|
448
|
+
families = ", ".join(sorted(set(unsupported)))
|
|
449
|
+
raise TypeError(
|
|
450
|
+
"Tetrahedral canonicalization cannot omit configured stereo "
|
|
451
|
+
f"families: {families}."
|
|
452
|
+
)
|
|
453
|
+
return canonicalize_tetrahedral_stereograph(
|
|
454
|
+
base_graph,
|
|
455
|
+
descriptors,
|
|
456
|
+
atom_color=atom_color,
|
|
457
|
+
bond_color=bond_color,
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def canonicalize_stereo_registry(
|
|
462
|
+
base_graph: nx.Graph,
|
|
463
|
+
registry: Mapping[str, StereoValue],
|
|
464
|
+
*,
|
|
465
|
+
atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
|
|
466
|
+
bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
|
|
467
|
+
enumerate_automorphism_group: bool = True,
|
|
468
|
+
) -> CanonicalStereographResult:
|
|
469
|
+
"""Canonicalize a registry across the complete configured catalogue."""
|
|
470
|
+
from .configured import canonicalize_configured_registry
|
|
471
|
+
|
|
472
|
+
return canonicalize_configured_registry(
|
|
473
|
+
base_graph,
|
|
474
|
+
registry,
|
|
475
|
+
atom_color=atom_color,
|
|
476
|
+
bond_color=bond_color,
|
|
477
|
+
enumerate_automorphism_group=enumerate_automorphism_group,
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def mirror_stereo_descriptor(
|
|
482
|
+
descriptor: StereoValue,
|
|
483
|
+
) -> StereoValue:
|
|
484
|
+
"""Apply the geometry-specific spatial-reflection action."""
|
|
485
|
+
from .configured import mirror_configured_descriptor
|
|
486
|
+
|
|
487
|
+
return mirror_configured_descriptor(descriptor) # type: ignore[arg-type]
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def mirror_stereo_registry(
|
|
491
|
+
registry: Mapping[str, StereoValue],
|
|
492
|
+
) -> dict[str, StereoValue]:
|
|
493
|
+
"""Return the geometry-specific mirror without changing loci."""
|
|
494
|
+
return {
|
|
495
|
+
identifier: mirror_stereo_descriptor(descriptor)
|
|
496
|
+
for identifier, descriptor in registry.items()
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def classify_stereograph_mirror(
|
|
501
|
+
base_graph: nx.Graph,
|
|
502
|
+
registry: Mapping[str, StereoValue],
|
|
503
|
+
*,
|
|
504
|
+
incomplete_loci: Iterable[str] = (),
|
|
505
|
+
unsupported_loci: Iterable[str] = (),
|
|
506
|
+
atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
|
|
507
|
+
bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
|
|
508
|
+
) -> StereographMirrorResult:
|
|
509
|
+
"""Compare a complete configured stereograph with its exact mirror.
|
|
510
|
+
|
|
511
|
+
``incomplete_loci`` and ``unsupported_loci`` let a perception boundary
|
|
512
|
+
declare missing configured information without inventing descriptors.
|
|
513
|
+
Unsupported evidence takes precedence over incomplete evidence.
|
|
514
|
+
"""
|
|
515
|
+
from .configured import classify_configured_stereograph_mirror
|
|
516
|
+
|
|
517
|
+
return classify_configured_stereograph_mirror(
|
|
518
|
+
base_graph,
|
|
519
|
+
registry,
|
|
520
|
+
incomplete_loci=incomplete_loci,
|
|
521
|
+
unsupported_loci=unsupported_loci,
|
|
522
|
+
atom_color=atom_color,
|
|
523
|
+
bond_color=bond_color,
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def _rdkit_graph(molecule: Any) -> nx.Graph:
|
|
528
|
+
"""Return a defensive attributed graph in the RDKit atom namespace."""
|
|
529
|
+
from rdkit import Chem
|
|
530
|
+
|
|
531
|
+
from synkit.IO.mol_to_graph import MolToGraph
|
|
532
|
+
|
|
533
|
+
if not isinstance(molecule, Chem.Mol):
|
|
534
|
+
raise TypeError("RDKit stereograph canonicalization requires Chem.Mol.")
|
|
535
|
+
working = Chem.Mol(molecule)
|
|
536
|
+
atom_maps = tuple(int(atom.GetAtomMapNum()) for atom in working.GetAtoms())
|
|
537
|
+
fully_mapped = all(value > 0 for value in atom_maps) and len(set(atom_maps)) == len(
|
|
538
|
+
atom_maps
|
|
539
|
+
)
|
|
540
|
+
return MolToGraph(include_stereo_descriptors=False).transform(
|
|
541
|
+
working,
|
|
542
|
+
use_index_as_atom_map=fully_mapped,
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def _rdkit_graph_and_registry(
|
|
547
|
+
molecule: Any,
|
|
548
|
+
) -> tuple[nx.Graph, Mapping[str, StereoValue]]:
|
|
549
|
+
"""Return one RDKit graph/descriptor identifier namespace."""
|
|
550
|
+
from rdkit import Chem
|
|
551
|
+
|
|
552
|
+
from .rdkit_adapter import descriptors_from_rdkit
|
|
553
|
+
|
|
554
|
+
graph = _rdkit_graph(molecule)
|
|
555
|
+
working = Chem.Mol(molecule)
|
|
556
|
+
atom_maps = tuple(int(atom.GetAtomMapNum()) for atom in working.GetAtoms())
|
|
557
|
+
fully_mapped = all(value > 0 for value in atom_maps) and len(set(atom_maps)) == len(
|
|
558
|
+
atom_maps
|
|
559
|
+
)
|
|
560
|
+
registry = descriptors_from_rdkit(
|
|
561
|
+
working,
|
|
562
|
+
require_atom_maps=fully_mapped,
|
|
563
|
+
)
|
|
564
|
+
return graph, registry
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def canonicalize_rdkit_tetrahedral_stereograph(
|
|
568
|
+
molecule: Any,
|
|
569
|
+
) -> CanonicalStereographResult:
|
|
570
|
+
"""Canonicalize RDKit constitution plus its configured tetrahedral stereo.
|
|
571
|
+
|
|
572
|
+
A defensive molecule copy is converted with atom-map node IDs only when
|
|
573
|
+
every atom has a unique positive map. Otherwise both the molecular graph
|
|
574
|
+
and descriptors use one-based RDKit-index IDs. Atom maps, CIP labels,
|
|
575
|
+
coordinates, and RDKit local chiral tags do not enter semantic colours.
|
|
576
|
+
"""
|
|
577
|
+
graph, registry = _rdkit_graph_and_registry(molecule)
|
|
578
|
+
return canonicalize_tetrahedral_registry(graph, registry)
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
def canonicalize_rdkit_stereograph(
|
|
582
|
+
molecule: Any,
|
|
583
|
+
*,
|
|
584
|
+
identity_profile: Literal["chemical", "lewis_state", "acs_topology"] = "lewis_state",
|
|
585
|
+
):
|
|
586
|
+
"""Canonicalize configured RDKit stereo under an explicit identity profile.
|
|
587
|
+
|
|
588
|
+
The compatibility default is the supplied Lewis drawing. Chemical
|
|
589
|
+
identity returns a versioned resonance-family certificate; it is not a
|
|
590
|
+
single drawing's certificate. Mirror classification defaults to chemical
|
|
591
|
+
identity, so select the same profile when comparing the operations.
|
|
592
|
+
"""
|
|
593
|
+
from .configured import canonicalize_rdkit_configured_stereograph
|
|
594
|
+
|
|
595
|
+
return canonicalize_rdkit_configured_stereograph(molecule, identity_profile=identity_profile)
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
def classify_rdkit_stereograph_mirror(
|
|
599
|
+
molecule: Any,
|
|
600
|
+
*,
|
|
601
|
+
require_complete: bool = True,
|
|
602
|
+
identity_profile: Literal[
|
|
603
|
+
"chemical",
|
|
604
|
+
"lewis_state",
|
|
605
|
+
"acs_topology",
|
|
606
|
+
] = "chemical",
|
|
607
|
+
) -> StereographMirrorResult:
|
|
608
|
+
"""Classify configured RDKit input through exact molecular mirror identity.
|
|
609
|
+
|
|
610
|
+
The chemical default compares the exact resonance family while preserving
|
|
611
|
+
genuine bond-order distinctions. ``lewis_state`` audits one supplied
|
|
612
|
+
Lewis drawing; ``acs_topology`` is connectivity-only benchmark
|
|
613
|
+
compatibility.
|
|
614
|
+
"""
|
|
615
|
+
from .configured import classify_rdkit_configured_stereograph_mirror
|
|
616
|
+
|
|
617
|
+
return classify_rdkit_configured_stereograph_mirror(
|
|
618
|
+
molecule,
|
|
619
|
+
require_complete=require_complete,
|
|
620
|
+
identity_profile=identity_profile,
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
__all__ = [
|
|
625
|
+
"AtomVertex",
|
|
626
|
+
"BondVertex",
|
|
627
|
+
"CanonicalStereographResult",
|
|
628
|
+
"STEREOGRAPH_SCHEMA",
|
|
629
|
+
"StereographMirrorResult",
|
|
630
|
+
"StereographMirrorStatus",
|
|
631
|
+
"StereoLocusVertex",
|
|
632
|
+
"StereoPortVertex",
|
|
633
|
+
"StereoSlotVertex",
|
|
634
|
+
"StereoTupleVertex",
|
|
635
|
+
"VirtualResourceVertex",
|
|
636
|
+
"classify_rdkit_stereograph_mirror",
|
|
637
|
+
"classify_stereograph_mirror",
|
|
638
|
+
"canonicalize_rdkit_stereograph",
|
|
639
|
+
"canonicalize_rdkit_tetrahedral_stereograph",
|
|
640
|
+
"canonicalize_stereo_registry",
|
|
641
|
+
"canonicalize_stereograph",
|
|
642
|
+
"canonicalize_tetrahedral_registry",
|
|
643
|
+
"canonicalize_tetrahedral_stereograph",
|
|
644
|
+
"expand_stereograph",
|
|
645
|
+
"expand_tetrahedral_stereograph",
|
|
646
|
+
"mirror_stereo_descriptor",
|
|
647
|
+
"mirror_stereo_registry",
|
|
648
|
+
]
|