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,496 @@
|
|
|
1
|
+
"""Loss-accounted descriptor interchange with StereoMolGraph.
|
|
2
|
+
|
|
3
|
+
StereoMolGraph uses ``None`` for any ligand absent from its molecular graph.
|
|
4
|
+
SynKit requires the chemical identity of that virtual ligand because hydrogen
|
|
5
|
+
and a lone pair produce different stereo dependencies. This module therefore
|
|
6
|
+
allows ``None`` only at the transport boundary and requires either an exact
|
|
7
|
+
slot sidecar or chemical resolution from the source molecule/Lewis graph.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from collections.abc import Callable, Mapping
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from types import MappingProxyType
|
|
15
|
+
from typing import Any, Literal
|
|
16
|
+
|
|
17
|
+
from rdkit import Chem
|
|
18
|
+
|
|
19
|
+
from .descriptors import (
|
|
20
|
+
AtropBondStereo,
|
|
21
|
+
OctahedralStereo,
|
|
22
|
+
PlanarBondStereo,
|
|
23
|
+
SquarePlanarStereo,
|
|
24
|
+
StereoValue,
|
|
25
|
+
TetrahedralStereo,
|
|
26
|
+
TrigonalBipyramidalStereo,
|
|
27
|
+
descriptor_id,
|
|
28
|
+
parse_virtual_reference,
|
|
29
|
+
virtual_reference,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
StereoProjection = Literal["all", "rdkit_2d"]
|
|
33
|
+
VirtualReferenceResolver = Callable[[int, int], str | None]
|
|
34
|
+
|
|
35
|
+
_SYNKIT_TYPES = {
|
|
36
|
+
"tetrahedral": TetrahedralStereo,
|
|
37
|
+
"square_planar": SquarePlanarStereo,
|
|
38
|
+
"trigonal_bipyramidal": TrigonalBipyramidalStereo,
|
|
39
|
+
"octahedral": OctahedralStereo,
|
|
40
|
+
"planar_bond": PlanarBondStereo,
|
|
41
|
+
"atrop_bond": AtropBondStereo,
|
|
42
|
+
}
|
|
43
|
+
_EXTERNAL_CLASS_NAMES = {
|
|
44
|
+
"Tetrahedral": "tetrahedral",
|
|
45
|
+
"SquarePlanar": "square_planar",
|
|
46
|
+
"TrigonalBipyramidal": "trigonal_bipyramidal",
|
|
47
|
+
"Octahedral": "octahedral",
|
|
48
|
+
"PlanarBond": "planar_bond",
|
|
49
|
+
"AtropBond": "atrop_bond",
|
|
50
|
+
}
|
|
51
|
+
_ATOM_CLASSES = frozenset(
|
|
52
|
+
{"tetrahedral", "square_planar", "trigonal_bipyramidal", "octahedral"}
|
|
53
|
+
)
|
|
54
|
+
_EXPECTED_LENGTHS = {
|
|
55
|
+
"tetrahedral": 5,
|
|
56
|
+
"square_planar": 5,
|
|
57
|
+
"trigonal_bipyramidal": 6,
|
|
58
|
+
"octahedral": 7,
|
|
59
|
+
"planar_bond": 6,
|
|
60
|
+
"atrop_bond": 6,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class StereoInterchangeError(ValueError):
|
|
65
|
+
"""Raised when descriptor interchange would require a silent guess."""
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass(frozen=True)
|
|
69
|
+
class VirtualReferenceSidecar:
|
|
70
|
+
"""Exact typed identities for StereoMolGraph ``None`` transport slots."""
|
|
71
|
+
|
|
72
|
+
descriptor_class: str
|
|
73
|
+
locus: str
|
|
74
|
+
references: tuple[tuple[int, str], ...] = ()
|
|
75
|
+
|
|
76
|
+
def __post_init__(self) -> None:
|
|
77
|
+
if self.descriptor_class not in _SYNKIT_TYPES:
|
|
78
|
+
raise StereoInterchangeError(
|
|
79
|
+
f"Unsupported sidecar descriptor class: {self.descriptor_class!r}."
|
|
80
|
+
)
|
|
81
|
+
slots = [slot for slot, _reference in self.references]
|
|
82
|
+
if len(slots) != len(set(slots)):
|
|
83
|
+
raise StereoInterchangeError(
|
|
84
|
+
"Virtual-reference sidecar slots must be unique."
|
|
85
|
+
)
|
|
86
|
+
for slot, reference in self.references:
|
|
87
|
+
if slot < 0 or parse_virtual_reference(reference) is None:
|
|
88
|
+
raise StereoInterchangeError(
|
|
89
|
+
f"Invalid virtual-reference sidecar entry: {(slot, reference)!r}."
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def by_slot(self) -> Mapping[int, str]:
|
|
93
|
+
return MappingProxyType(dict(self.references))
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@dataclass(frozen=True)
|
|
97
|
+
class StereoInterchangeIssue:
|
|
98
|
+
"""One explicit exclusion or information loss at the bridge boundary."""
|
|
99
|
+
|
|
100
|
+
code: str
|
|
101
|
+
locus: str
|
|
102
|
+
detail: str
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@dataclass(frozen=True)
|
|
106
|
+
class StereoInterchangeReport:
|
|
107
|
+
"""Normalized registry plus an auditable projection/loss ledger."""
|
|
108
|
+
|
|
109
|
+
descriptors: Mapping[str, StereoValue]
|
|
110
|
+
exclusions: tuple[StereoInterchangeIssue, ...] = ()
|
|
111
|
+
losses: tuple[StereoInterchangeIssue, ...] = ()
|
|
112
|
+
|
|
113
|
+
def __post_init__(self) -> None:
|
|
114
|
+
object.__setattr__(
|
|
115
|
+
self, "descriptors", MappingProxyType(dict(self.descriptors))
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def lossless(self) -> bool:
|
|
120
|
+
"""Whether every descriptor inside the selected projection was resolved."""
|
|
121
|
+
return not self.losses
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _stereomolgraph_descriptor_types() -> Mapping[str, type[Any]]:
|
|
125
|
+
try:
|
|
126
|
+
from stereomolgraph.stereodescriptors import (
|
|
127
|
+
AtropBond,
|
|
128
|
+
Octahedral,
|
|
129
|
+
PlanarBond,
|
|
130
|
+
SquarePlanar,
|
|
131
|
+
Tetrahedral,
|
|
132
|
+
TrigonalBipyramidal,
|
|
133
|
+
)
|
|
134
|
+
except ImportError as error:
|
|
135
|
+
raise StereoInterchangeError(
|
|
136
|
+
"StereoMolGraph is not installed; pass descriptor_types explicitly."
|
|
137
|
+
) from error
|
|
138
|
+
return {
|
|
139
|
+
"tetrahedral": Tetrahedral,
|
|
140
|
+
"square_planar": SquarePlanar,
|
|
141
|
+
"trigonal_bipyramidal": TrigonalBipyramidal,
|
|
142
|
+
"octahedral": Octahedral,
|
|
143
|
+
"planar_bond": PlanarBond,
|
|
144
|
+
"atrop_bond": AtropBond,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _external_descriptor_class(descriptor: Any) -> str:
|
|
149
|
+
external_name = type(descriptor).__name__
|
|
150
|
+
try:
|
|
151
|
+
return _EXTERNAL_CLASS_NAMES[external_name]
|
|
152
|
+
except KeyError as error:
|
|
153
|
+
raise StereoInterchangeError(
|
|
154
|
+
f"Unsupported StereoMolGraph descriptor class: {external_name!r}."
|
|
155
|
+
) from error
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _locus_from_atoms(descriptor_class: str, atoms: tuple[Any, ...]) -> str:
|
|
159
|
+
if descriptor_class in _ATOM_CLASSES:
|
|
160
|
+
if not atoms or type(atoms[0]) is not int:
|
|
161
|
+
raise StereoInterchangeError(
|
|
162
|
+
"Atom-centered descriptor transport requires an integer center."
|
|
163
|
+
)
|
|
164
|
+
return f"atom:{atoms[0]}"
|
|
165
|
+
if len(atoms) < 4 or type(atoms[2]) is not int or type(atoms[3]) is not int:
|
|
166
|
+
raise StereoInterchangeError(
|
|
167
|
+
"Bond-centered descriptor transport requires integer central atoms."
|
|
168
|
+
)
|
|
169
|
+
left, right = sorted((atoms[2], atoms[3]))
|
|
170
|
+
return f"bond:{left}-{right}"
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _slot_owner(descriptor_class: str, atoms: tuple[Any, ...], slot: int) -> int:
|
|
174
|
+
if descriptor_class in _ATOM_CLASSES:
|
|
175
|
+
if slot == 0 or type(atoms[0]) is not int:
|
|
176
|
+
raise StereoInterchangeError(
|
|
177
|
+
"A virtual reference cannot replace an atom stereocenter."
|
|
178
|
+
)
|
|
179
|
+
return atoms[0]
|
|
180
|
+
if slot in {0, 1} and type(atoms[2]) is int:
|
|
181
|
+
return atoms[2]
|
|
182
|
+
if slot in {4, 5} and type(atoms[3]) is int:
|
|
183
|
+
return atoms[3]
|
|
184
|
+
raise StereoInterchangeError(
|
|
185
|
+
"A virtual reference cannot replace a central bond atom."
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _external_transport_state(
|
|
190
|
+
descriptor: Any,
|
|
191
|
+
descriptor_class: str,
|
|
192
|
+
) -> tuple[tuple[Any, ...], Any]:
|
|
193
|
+
try:
|
|
194
|
+
atoms = tuple(descriptor.atoms)
|
|
195
|
+
parity = descriptor.parity
|
|
196
|
+
except (AttributeError, TypeError) as error:
|
|
197
|
+
raise StereoInterchangeError(
|
|
198
|
+
"StereoMolGraph descriptor transport requires atoms and parity."
|
|
199
|
+
) from error
|
|
200
|
+
expected_length = _EXPECTED_LENGTHS[descriptor_class]
|
|
201
|
+
if len(atoms) != expected_length:
|
|
202
|
+
raise StereoInterchangeError(
|
|
203
|
+
f"{descriptor_class} transport requires {expected_length} references; "
|
|
204
|
+
f"observed {len(atoms)}."
|
|
205
|
+
)
|
|
206
|
+
return atoms, parity
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def synkit_descriptor_to_stereomolgraph(
|
|
210
|
+
descriptor: StereoValue,
|
|
211
|
+
*,
|
|
212
|
+
descriptor_types: Mapping[str, type[Any]] | None = None,
|
|
213
|
+
) -> tuple[Any, VirtualReferenceSidecar]:
|
|
214
|
+
"""Convert one descriptor and preserve typed virtual slots in a sidecar."""
|
|
215
|
+
external_types = descriptor_types or _stereomolgraph_descriptor_types()
|
|
216
|
+
try:
|
|
217
|
+
external_type = external_types[descriptor.descriptor_class]
|
|
218
|
+
except KeyError as error:
|
|
219
|
+
raise StereoInterchangeError(
|
|
220
|
+
f"No StereoMolGraph type for {descriptor.descriptor_class!r}."
|
|
221
|
+
) from error
|
|
222
|
+
|
|
223
|
+
transported: list[int | None] = []
|
|
224
|
+
references: list[tuple[int, str]] = []
|
|
225
|
+
for slot, value in enumerate(descriptor.atoms):
|
|
226
|
+
if type(value) is int:
|
|
227
|
+
transported.append(value)
|
|
228
|
+
continue
|
|
229
|
+
virtual = parse_virtual_reference(value)
|
|
230
|
+
if virtual is None:
|
|
231
|
+
raise StereoInterchangeError(f"Invalid SynKit stereo reference: {value!r}.")
|
|
232
|
+
transported.append(None)
|
|
233
|
+
references.append((slot, str(virtual)))
|
|
234
|
+
|
|
235
|
+
sidecar = VirtualReferenceSidecar(
|
|
236
|
+
descriptor.descriptor_class,
|
|
237
|
+
descriptor_id(descriptor),
|
|
238
|
+
tuple(references),
|
|
239
|
+
)
|
|
240
|
+
return external_type(tuple(transported), descriptor.parity), sidecar
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def stereomolgraph_descriptor_to_synkit(
|
|
244
|
+
descriptor: Any,
|
|
245
|
+
*,
|
|
246
|
+
virtual_references: VirtualReferenceSidecar | None = None,
|
|
247
|
+
reference_resolver: VirtualReferenceResolver | None = None,
|
|
248
|
+
provenance: str | None = "stereomolgraph",
|
|
249
|
+
) -> StereoValue:
|
|
250
|
+
"""Convert one descriptor, rejecting every unresolved ``None`` slot."""
|
|
251
|
+
descriptor_class = _external_descriptor_class(descriptor)
|
|
252
|
+
atoms, parity = _external_transport_state(descriptor, descriptor_class)
|
|
253
|
+
locus = _locus_from_atoms(descriptor_class, atoms)
|
|
254
|
+
supplied: Mapping[int, str] = {}
|
|
255
|
+
if virtual_references is not None:
|
|
256
|
+
if (
|
|
257
|
+
virtual_references.descriptor_class != descriptor_class
|
|
258
|
+
or virtual_references.locus != locus
|
|
259
|
+
):
|
|
260
|
+
raise StereoInterchangeError(
|
|
261
|
+
"Virtual-reference sidecar does not belong to this descriptor."
|
|
262
|
+
)
|
|
263
|
+
supplied = virtual_references.by_slot()
|
|
264
|
+
|
|
265
|
+
used_slots: set[int] = set()
|
|
266
|
+
resolved: list[int | str] = []
|
|
267
|
+
for slot, value in enumerate(atoms):
|
|
268
|
+
if type(value) is int:
|
|
269
|
+
resolved.append(value)
|
|
270
|
+
continue
|
|
271
|
+
if value is not None:
|
|
272
|
+
raise StereoInterchangeError(
|
|
273
|
+
f"StereoMolGraph references must be integers or None, got {value!r}."
|
|
274
|
+
)
|
|
275
|
+
owner = _slot_owner(descriptor_class, atoms, slot)
|
|
276
|
+
reference = supplied.get(slot)
|
|
277
|
+
if reference is None and reference_resolver is not None:
|
|
278
|
+
reference = reference_resolver(owner, slot)
|
|
279
|
+
virtual = parse_virtual_reference(reference)
|
|
280
|
+
if virtual is None or virtual.center != owner:
|
|
281
|
+
raise StereoInterchangeError(
|
|
282
|
+
f"Unresolved virtual reference at {locus} slot {slot}; "
|
|
283
|
+
"an owner-matched @H or @LP identity is required."
|
|
284
|
+
)
|
|
285
|
+
resolved.append(str(virtual))
|
|
286
|
+
used_slots.add(slot)
|
|
287
|
+
|
|
288
|
+
unused_slots = set(supplied) - used_slots
|
|
289
|
+
if unused_slots:
|
|
290
|
+
raise StereoInterchangeError(
|
|
291
|
+
f"Sidecar contains non-virtual slots for {locus}: {sorted(unused_slots)}."
|
|
292
|
+
)
|
|
293
|
+
descriptor_type = _SYNKIT_TYPES[descriptor_class]
|
|
294
|
+
try:
|
|
295
|
+
return descriptor_type( # type: ignore[call-arg,return-value]
|
|
296
|
+
tuple(resolved),
|
|
297
|
+
parity,
|
|
298
|
+
provenance,
|
|
299
|
+
)
|
|
300
|
+
except (TypeError, ValueError) as error:
|
|
301
|
+
raise StereoInterchangeError(
|
|
302
|
+
f"Invalid {descriptor_class} descriptor at {locus}: {error}"
|
|
303
|
+
) from error
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def _source_atoms_by_id(molecule: Chem.Mol) -> dict[int, Chem.Atom]:
|
|
307
|
+
values: dict[int, Chem.Atom] = {}
|
|
308
|
+
for atom in molecule.GetAtoms():
|
|
309
|
+
atom_id = int(atom.GetAtomMapNum())
|
|
310
|
+
if atom_id <= 0:
|
|
311
|
+
raise StereoInterchangeError(
|
|
312
|
+
"Direct StereoMolGraph interchange requires non-zero atom maps."
|
|
313
|
+
)
|
|
314
|
+
if atom_id in values:
|
|
315
|
+
raise StereoInterchangeError(
|
|
316
|
+
"Direct StereoMolGraph interchange requires unique atom maps."
|
|
317
|
+
)
|
|
318
|
+
values[atom_id] = atom
|
|
319
|
+
return values
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _lewis_lone_pairs_by_id(lewis_graph: Any | None) -> dict[int, int]:
|
|
323
|
+
if lewis_graph is None:
|
|
324
|
+
return {}
|
|
325
|
+
values: dict[int, int] = {}
|
|
326
|
+
for node, attributes in lewis_graph.nodes(data=True):
|
|
327
|
+
atom_id = attributes.get("atom_map") or node
|
|
328
|
+
if type(atom_id) is int:
|
|
329
|
+
values[atom_id] = int(
|
|
330
|
+
attributes.get("estimated_lone_pairs", attributes.get("lone_pairs", 0))
|
|
331
|
+
)
|
|
332
|
+
return values
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def _chemical_reference_resolver(
|
|
336
|
+
atoms_by_id: Mapping[int, Chem.Atom],
|
|
337
|
+
lone_pairs_by_id: Mapping[int, int],
|
|
338
|
+
*,
|
|
339
|
+
use_rdkit_lone_pair_fallback: bool,
|
|
340
|
+
) -> VirtualReferenceResolver:
|
|
341
|
+
def resolve(owner: int, _slot: int) -> str | None:
|
|
342
|
+
atom = atoms_by_id.get(owner)
|
|
343
|
+
if atom is None:
|
|
344
|
+
return None
|
|
345
|
+
hidden_hydrogens = int(atom.GetNumExplicitHs()) + int(atom.GetNumImplicitHs())
|
|
346
|
+
if hidden_hydrogens > 0:
|
|
347
|
+
return virtual_reference("H", owner)
|
|
348
|
+
if lone_pairs_by_id.get(owner, 0) > 0:
|
|
349
|
+
return virtual_reference("LP", owner)
|
|
350
|
+
if use_rdkit_lone_pair_fallback:
|
|
351
|
+
from synkit.IO.mol_to_graph import MolToGraph
|
|
352
|
+
|
|
353
|
+
if MolToGraph.estimate_lone_pairs(atom) > 0:
|
|
354
|
+
return virtual_reference("LP", owner)
|
|
355
|
+
return None
|
|
356
|
+
|
|
357
|
+
return resolve
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def _rdkit_2d_projection_exclusion(
|
|
361
|
+
descriptor_class: str,
|
|
362
|
+
atoms: tuple[Any, ...],
|
|
363
|
+
locus: str,
|
|
364
|
+
*,
|
|
365
|
+
tetrahedral_loci: set[int],
|
|
366
|
+
ez_loci: set[frozenset[int]],
|
|
367
|
+
) -> StereoInterchangeIssue | None:
|
|
368
|
+
if descriptor_class in _ATOM_CLASSES:
|
|
369
|
+
if descriptor_class != "tetrahedral":
|
|
370
|
+
return StereoInterchangeIssue(
|
|
371
|
+
"CLASS_OUTSIDE_RDKIT_2D_PROJECTION",
|
|
372
|
+
locus,
|
|
373
|
+
"Atom descriptor class is outside SynKit's RDKit 2D subset.",
|
|
374
|
+
)
|
|
375
|
+
if atoms[0] not in tetrahedral_loci:
|
|
376
|
+
return StereoInterchangeIssue(
|
|
377
|
+
"UNSPECIFIED_ATOM_STEREO_EXCLUDED",
|
|
378
|
+
locus,
|
|
379
|
+
"Tetrahedral topology was not stereospecified by RDKit.",
|
|
380
|
+
)
|
|
381
|
+
return None
|
|
382
|
+
if descriptor_class != "planar_bond":
|
|
383
|
+
return StereoInterchangeIssue(
|
|
384
|
+
"CLASS_OUTSIDE_RDKIT_2D_PROJECTION",
|
|
385
|
+
locus,
|
|
386
|
+
"Bond descriptor class is outside SynKit's RDKit 2D subset.",
|
|
387
|
+
)
|
|
388
|
+
if frozenset(atoms[2:4]) in ez_loci:
|
|
389
|
+
return None
|
|
390
|
+
return StereoInterchangeIssue(
|
|
391
|
+
"TOPOLOGY_OR_UNSPECIFIED_BOND_STEREO_EXCLUDED",
|
|
392
|
+
locus,
|
|
393
|
+
"Planar-bond topology was not stereospecified as E/Z by RDKit.",
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def stereomolgraph_registry_to_synkit(
|
|
398
|
+
stereo_mol_graph: Any,
|
|
399
|
+
*,
|
|
400
|
+
source_molecule: Chem.Mol,
|
|
401
|
+
lewis_graph: Any | None = None,
|
|
402
|
+
projection: StereoProjection = "rdkit_2d",
|
|
403
|
+
) -> StereoInterchangeReport:
|
|
404
|
+
"""Import a normalized registry directly, without regenerating bond orders.
|
|
405
|
+
|
|
406
|
+
``projection='rdkit_2d'`` selects the shared RDKit-authored tetrahedral and
|
|
407
|
+
E/Z boundary. StereoMolGraph's topology-inferred, unspecified, and richer
|
|
408
|
+
descriptor loci are reported as exclusions rather than false mismatches.
|
|
409
|
+
"""
|
|
410
|
+
if projection not in {"all", "rdkit_2d"}:
|
|
411
|
+
raise ValueError("projection must be 'all' or 'rdkit_2d'.")
|
|
412
|
+
|
|
413
|
+
molecule = Chem.Mol(source_molecule)
|
|
414
|
+
Chem.AssignStereochemistry(molecule, cleanIt=False, force=True)
|
|
415
|
+
atoms_by_id = _source_atoms_by_id(molecule)
|
|
416
|
+
lone_pairs_by_id = _lewis_lone_pairs_by_id(lewis_graph)
|
|
417
|
+
tetrahedral_tags = {
|
|
418
|
+
Chem.ChiralType.CHI_TETRAHEDRAL_CW,
|
|
419
|
+
Chem.ChiralType.CHI_TETRAHEDRAL_CCW,
|
|
420
|
+
}
|
|
421
|
+
tetrahedral_loci = {
|
|
422
|
+
atom_id
|
|
423
|
+
for atom_id, atom in atoms_by_id.items()
|
|
424
|
+
if atom.GetChiralTag() in tetrahedral_tags
|
|
425
|
+
}
|
|
426
|
+
ez_loci = {
|
|
427
|
+
frozenset(
|
|
428
|
+
{
|
|
429
|
+
int(bond.GetBeginAtom().GetAtomMapNum()),
|
|
430
|
+
int(bond.GetEndAtom().GetAtomMapNum()),
|
|
431
|
+
}
|
|
432
|
+
)
|
|
433
|
+
for bond in molecule.GetBonds()
|
|
434
|
+
if bond.GetStereo() in {Chem.BondStereo.STEREOE, Chem.BondStereo.STEREOZ}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
resolve_reference = _chemical_reference_resolver(
|
|
438
|
+
atoms_by_id,
|
|
439
|
+
lone_pairs_by_id,
|
|
440
|
+
use_rdkit_lone_pair_fallback=lewis_graph is None,
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
external_descriptors = tuple(stereo_mol_graph.atom_stereo.values()) + tuple(
|
|
444
|
+
stereo_mol_graph.bond_stereo.values()
|
|
445
|
+
)
|
|
446
|
+
imported: dict[str, StereoValue] = {}
|
|
447
|
+
exclusions: list[StereoInterchangeIssue] = []
|
|
448
|
+
losses: list[StereoInterchangeIssue] = []
|
|
449
|
+
for external in external_descriptors:
|
|
450
|
+
try:
|
|
451
|
+
descriptor_class = _external_descriptor_class(external)
|
|
452
|
+
atoms = tuple(external.atoms)
|
|
453
|
+
locus = _locus_from_atoms(descriptor_class, atoms)
|
|
454
|
+
except StereoInterchangeError as error:
|
|
455
|
+
losses.append(
|
|
456
|
+
StereoInterchangeIssue("UNSUPPORTED_DESCRIPTOR", "unknown", str(error))
|
|
457
|
+
)
|
|
458
|
+
continue
|
|
459
|
+
|
|
460
|
+
if projection == "rdkit_2d":
|
|
461
|
+
exclusion = _rdkit_2d_projection_exclusion(
|
|
462
|
+
descriptor_class,
|
|
463
|
+
atoms,
|
|
464
|
+
locus,
|
|
465
|
+
tetrahedral_loci=tetrahedral_loci,
|
|
466
|
+
ez_loci=ez_loci,
|
|
467
|
+
)
|
|
468
|
+
if exclusion is not None:
|
|
469
|
+
exclusions.append(exclusion)
|
|
470
|
+
continue
|
|
471
|
+
|
|
472
|
+
try:
|
|
473
|
+
converted = stereomolgraph_descriptor_to_synkit(
|
|
474
|
+
external,
|
|
475
|
+
reference_resolver=resolve_reference,
|
|
476
|
+
provenance="stereomolgraph:direct",
|
|
477
|
+
)
|
|
478
|
+
except StereoInterchangeError as error:
|
|
479
|
+
losses.append(
|
|
480
|
+
StereoInterchangeIssue("UNRESOLVED_REFERENCE", locus, str(error))
|
|
481
|
+
)
|
|
482
|
+
continue
|
|
483
|
+
key = descriptor_id(converted)
|
|
484
|
+
previous = imported.get(key)
|
|
485
|
+
if previous is not None and previous != converted:
|
|
486
|
+
losses.append(
|
|
487
|
+
StereoInterchangeIssue(
|
|
488
|
+
"LOCUS_COLLISION",
|
|
489
|
+
key,
|
|
490
|
+
"Two non-equivalent descriptors project onto the same SynKit locus.",
|
|
491
|
+
)
|
|
492
|
+
)
|
|
493
|
+
continue
|
|
494
|
+
imported[key] = converted
|
|
495
|
+
|
|
496
|
+
return StereoInterchangeReport(imported, tuple(exclusions), tuple(losses))
|