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,118 @@
|
|
|
1
|
+
"""Versioned RDKit identity profiles and complete resonance-family keys."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Mapping
|
|
6
|
+
from dataclasses import dataclass, replace
|
|
7
|
+
from functools import cached_property
|
|
8
|
+
import hashlib
|
|
9
|
+
import json
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from .canonical import CanonicalStereographResult, _rdkit_graph_and_registry
|
|
13
|
+
from .configured import (
|
|
14
|
+
MirrorIdentityProfile,
|
|
15
|
+
_mirror_profile_options,
|
|
16
|
+
_resonance_graphs,
|
|
17
|
+
canonicalize_configured_registry,
|
|
18
|
+
)
|
|
19
|
+
from .descriptors import StereoValue
|
|
20
|
+
|
|
21
|
+
RDKIT_IDENTITY_SCHEMA = "synkit.rdkit-stereograph/1"
|
|
22
|
+
RESONANCE_FAMILY_SCHEMA = "synkit.resonance-family-stereograph/1"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def profile_certificate(result: CanonicalStereographResult, profile: str):
|
|
26
|
+
"""Namespace a single drawing's full key without changing its witnesses."""
|
|
27
|
+
code = f"{RDKIT_IDENTITY_SCHEMA}\n{profile}\n{result.canonical_code}"
|
|
28
|
+
return replace(
|
|
29
|
+
result, schema=RDKIT_IDENTITY_SCHEMA, canonical_code=code,
|
|
30
|
+
canonical_digest=hashlib.sha256(code.encode("utf-8")).hexdigest(),
|
|
31
|
+
identity_profile=profile,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class ResonanceFamilyCanonicalResult:
|
|
37
|
+
"""Identity of an entire declared resonance family.
|
|
38
|
+
|
|
39
|
+
``members`` retain one witness per distinct canonical drawing. An atom
|
|
40
|
+
order or automorphism of one member must not be interpreted as a unique
|
|
41
|
+
atom order or the full automorphism group of the family. Equality uses
|
|
42
|
+
the complete sorted family, never a finite digest or a selected member.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
members: tuple[CanonicalStereographResult, ...]
|
|
46
|
+
schema: str = RESONANCE_FAMILY_SCHEMA
|
|
47
|
+
identity_profile: str = "chemical"
|
|
48
|
+
|
|
49
|
+
def __post_init__(self):
|
|
50
|
+
if not self.members or any(not member.complete or not member.exact for member in self.members):
|
|
51
|
+
raise ValueError("A family certificate requires complete exact members.")
|
|
52
|
+
codes = tuple(member.canonical_code for member in self.members)
|
|
53
|
+
if codes != tuple(sorted(set(codes))):
|
|
54
|
+
raise ValueError("Family members must have sorted distinct full certificates.")
|
|
55
|
+
|
|
56
|
+
@cached_property
|
|
57
|
+
def canonical_code(self) -> str:
|
|
58
|
+
return f"{self.schema}\n" + json.dumps(
|
|
59
|
+
[self.identity_profile, [member.canonical_code for member in self.members]],
|
|
60
|
+
ensure_ascii=True, separators=(",", ":"),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
@cached_property
|
|
64
|
+
def canonical_digest(self) -> str:
|
|
65
|
+
return hashlib.sha256(self.canonical_code.encode("utf-8")).hexdigest()
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def canonical_certificate(self) -> str:
|
|
69
|
+
return self.canonical_code
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def complete(self) -> bool:
|
|
73
|
+
return True
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def exact(self) -> bool:
|
|
77
|
+
return True
|
|
78
|
+
|
|
79
|
+
def same_stereograph(self, other: object) -> bool:
|
|
80
|
+
return (
|
|
81
|
+
isinstance(other, ResonanceFamilyCanonicalResult)
|
|
82
|
+
and self.schema == other.schema
|
|
83
|
+
and self.identity_profile == other.identity_profile
|
|
84
|
+
and self.canonical_code == other.canonical_code
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
RDKitIdentityResult = CanonicalStereographResult | ResonanceFamilyCanonicalResult
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def canonicalize_rdkit_registry(
|
|
92
|
+
molecule: Any,
|
|
93
|
+
registry: Mapping[str, StereoValue],
|
|
94
|
+
*,
|
|
95
|
+
identity_profile: MirrorIdentityProfile,
|
|
96
|
+
) -> RDKitIdentityResult:
|
|
97
|
+
"""Canonize a registry in the molecule's shared atom-handle namespace."""
|
|
98
|
+
options = _mirror_profile_options(identity_profile)
|
|
99
|
+
if identity_profile != "chemical":
|
|
100
|
+
graph, _source = _rdkit_graph_and_registry(molecule)
|
|
101
|
+
return profile_certificate(
|
|
102
|
+
canonicalize_configured_registry(graph, registry, **options), identity_profile,
|
|
103
|
+
)
|
|
104
|
+
members = {}
|
|
105
|
+
for graph in _resonance_graphs(molecule):
|
|
106
|
+
result = profile_certificate(canonicalize_configured_registry(graph, registry), "lewis_state")
|
|
107
|
+
members.setdefault(result.canonical_code, result)
|
|
108
|
+
return ResonanceFamilyCanonicalResult(tuple(members[code] for code in sorted(members)))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def canonicalize_rdkit_identity(
|
|
112
|
+
molecule: Any,
|
|
113
|
+
*,
|
|
114
|
+
identity_profile: MirrorIdentityProfile = "lewis_state",
|
|
115
|
+
) -> RDKitIdentityResult:
|
|
116
|
+
"""Produce a full source-declared configured identity in one profile."""
|
|
117
|
+
_graph, registry = _rdkit_graph_and_registry(molecule)
|
|
118
|
+
return canonicalize_rdkit_registry(molecule, registry, identity_profile=identity_profile)
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""Declared RDKit resonance closure and profile-aware phosphate equivalence."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Literal
|
|
6
|
+
|
|
7
|
+
import networkx as nx
|
|
8
|
+
|
|
9
|
+
from .canonical import _rdkit_graph
|
|
10
|
+
|
|
11
|
+
MirrorIdentityProfile = Literal["chemical", "lewis_state", "acs_topology"]
|
|
12
|
+
_MAX_RESONANCE_FORMS = 4096
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _resonance_graphs(molecule: Any) -> tuple[nx.Graph, ...]:
|
|
16
|
+
"""Return RDKit resonance forms closed under the declared phosphate move.
|
|
17
|
+
|
|
18
|
+
This is an explicit computational identity convention, not a guarantee
|
|
19
|
+
of exhaustive enumeration of every chemically possible resonance form.
|
|
20
|
+
The terminal phosphate move is needed because RDKit's supplier does not
|
|
21
|
+
supply those charge/bond-order exchanges itself.
|
|
22
|
+
"""
|
|
23
|
+
from rdkit import Chem
|
|
24
|
+
|
|
25
|
+
supplier = Chem.ResonanceMolSupplier(
|
|
26
|
+
molecule,
|
|
27
|
+
flags=(Chem.ResonanceFlags.ALLOW_CHARGE_SEPARATION | Chem.ResonanceFlags.KEKULE_ALL),
|
|
28
|
+
maxStructs=_MAX_RESONANCE_FORMS,
|
|
29
|
+
)
|
|
30
|
+
forms = tuple(supplier)
|
|
31
|
+
if len(forms) >= _MAX_RESONANCE_FORMS:
|
|
32
|
+
raise RuntimeError(
|
|
33
|
+
"Exact resonance-family enumeration reached the "
|
|
34
|
+
f"{_MAX_RESONANCE_FORMS}-form safety limit."
|
|
35
|
+
)
|
|
36
|
+
if not forms:
|
|
37
|
+
forms = (Chem.Mol(molecule),)
|
|
38
|
+
pending = list(forms)
|
|
39
|
+
seen = set()
|
|
40
|
+
graphs = []
|
|
41
|
+
while pending:
|
|
42
|
+
form = pending.pop()
|
|
43
|
+
drawing = (
|
|
44
|
+
tuple(atom.GetFormalCharge() for atom in form.GetAtoms()),
|
|
45
|
+
tuple(str(bond.GetBondType()) for bond in form.GetBonds()),
|
|
46
|
+
)
|
|
47
|
+
if drawing in seen:
|
|
48
|
+
continue
|
|
49
|
+
seen.add(drawing)
|
|
50
|
+
if len(seen) >= _MAX_RESONANCE_FORMS:
|
|
51
|
+
raise RuntimeError(
|
|
52
|
+
"Exact resonance-family closure reached the "
|
|
53
|
+
f"{_MAX_RESONANCE_FORMS}-form safety limit."
|
|
54
|
+
)
|
|
55
|
+
normalized = Chem.Mol(form)
|
|
56
|
+
Chem.SetAromaticity(normalized)
|
|
57
|
+
graphs.append(_rdkit_graph(normalized))
|
|
58
|
+
for center, left, right in _terminal_phosphate_pairs(form):
|
|
59
|
+
alternate = Chem.RWMol(form)
|
|
60
|
+
alternate.GetAtomWithIdx(left).SetFormalCharge(-1)
|
|
61
|
+
alternate.GetAtomWithIdx(right).SetFormalCharge(0)
|
|
62
|
+
alternate.GetBondBetweenAtoms(center, left).SetBondType(Chem.BondType.SINGLE)
|
|
63
|
+
alternate.GetBondBetweenAtoms(center, right).SetBondType(Chem.BondType.DOUBLE)
|
|
64
|
+
alternate = alternate.GetMol()
|
|
65
|
+
Chem.SanitizeMol(alternate)
|
|
66
|
+
pending.append(alternate)
|
|
67
|
+
return tuple(graphs)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _terminal_phosphate_pairs(molecule: Any) -> tuple[tuple[int, int, int], ...]:
|
|
71
|
+
"""Locate the narrowly declared terminal phosphate resonance move.
|
|
72
|
+
|
|
73
|
+
Only neutral, nonradical, four-coordinate P with a terminal neutral O
|
|
74
|
+
double bond and a terminal anionic O single bond is included. Both O
|
|
75
|
+
atoms have no hydrogens or radicals. The move exchanges charge and bond
|
|
76
|
+
order while preserving atom identity, isotope and total charge/valence.
|
|
77
|
+
"""
|
|
78
|
+
from rdkit import Chem
|
|
79
|
+
|
|
80
|
+
pairs = []
|
|
81
|
+
for atom in molecule.GetAtoms():
|
|
82
|
+
if (
|
|
83
|
+
atom.GetAtomicNum() != 15
|
|
84
|
+
or atom.GetFormalCharge() != 0
|
|
85
|
+
or atom.GetDegree() != 4
|
|
86
|
+
or atom.GetTotalValence() != 5
|
|
87
|
+
or atom.GetNumRadicalElectrons() != 0
|
|
88
|
+
or atom.GetTotalNumHs() != 0
|
|
89
|
+
):
|
|
90
|
+
continue
|
|
91
|
+
double = []
|
|
92
|
+
single = []
|
|
93
|
+
for oxygen in atom.GetNeighbors():
|
|
94
|
+
if (
|
|
95
|
+
oxygen.GetAtomicNum() != 8
|
|
96
|
+
or oxygen.GetDegree() != 1
|
|
97
|
+
or oxygen.GetTotalNumHs() != 0
|
|
98
|
+
or oxygen.GetNumRadicalElectrons() != 0
|
|
99
|
+
or oxygen.GetIsAromatic()
|
|
100
|
+
):
|
|
101
|
+
continue
|
|
102
|
+
bond = molecule.GetBondBetweenAtoms(atom.GetIdx(), oxygen.GetIdx())
|
|
103
|
+
if oxygen.GetFormalCharge() == 0 and bond.GetBondType() == Chem.BondType.DOUBLE:
|
|
104
|
+
double.append(oxygen.GetIdx())
|
|
105
|
+
if oxygen.GetFormalCharge() == -1 and bond.GetBondType() == Chem.BondType.SINGLE:
|
|
106
|
+
single.append(oxygen.GetIdx())
|
|
107
|
+
pairs.extend((atom.GetIdx(), left, right) for left in double for right in single)
|
|
108
|
+
return tuple(pairs)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _is_terminal_phosphate_resonance_locus(
|
|
112
|
+
molecule: Any,
|
|
113
|
+
element: Any,
|
|
114
|
+
*,
|
|
115
|
+
identity_profile: MirrorIdentityProfile,
|
|
116
|
+
) -> bool:
|
|
117
|
+
"""Return whether an apparent P center differs only by localized resonance.
|
|
118
|
+
|
|
119
|
+
A neutral tetra-coordinate phosphorus with terminal ``P=O`` and
|
|
120
|
+
``P-[O-]`` ligands contains two drawings of the same delocalized phosphate
|
|
121
|
+
oxygen environment. Treating bond order and formal charge as ligand
|
|
122
|
+
identity makes this look tetrahedral even though exchanging those terminal
|
|
123
|
+
oxygens is resonance-equivalent in the molecular-identity task.
|
|
124
|
+
"""
|
|
125
|
+
if identity_profile == "lewis_state":
|
|
126
|
+
return False
|
|
127
|
+
support = element.support
|
|
128
|
+
if not hasattr(support, "center"):
|
|
129
|
+
return False
|
|
130
|
+
# Degree-one ligands have no remaining environment. Their transposition
|
|
131
|
+
# fixes every other atom, and the declared move supplies exactly the
|
|
132
|
+
# exchanged charge/bond-order drawing in the chemical profile. The ACS
|
|
133
|
+
# profile omits those attributes outright. Isotope remains identity in
|
|
134
|
+
# both profiles; atom-map labels remain transport handles only.
|
|
135
|
+
return any(
|
|
136
|
+
center == support.center
|
|
137
|
+
and molecule.GetAtomWithIdx(left).GetIsotope()
|
|
138
|
+
== molecule.GetAtomWithIdx(right).GetIsotope()
|
|
139
|
+
for center, left, right in _terminal_phosphate_pairs(molecule)
|
|
140
|
+
)
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"""Loss-accounted interchange for complete reaction-stereo values.
|
|
2
|
+
|
|
3
|
+
Molecule and reaction line notations do not have fields for executable rule
|
|
4
|
+
guards, stereo changes, branch populations, coupled outcomes, or typed
|
|
5
|
+
refusals. This module therefore distinguishes lossless sidecar-capable
|
|
6
|
+
formats from endpoint-only carriers and makes every omitted semantic axis a
|
|
7
|
+
stable machine-readable issue.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from hashlib import sha256
|
|
14
|
+
from typing import Any, Mapping
|
|
15
|
+
|
|
16
|
+
import networkx as nx
|
|
17
|
+
|
|
18
|
+
from .wire import StereoReactionValue
|
|
19
|
+
|
|
20
|
+
REACTION_STEREO_INTERCHANGE_SCHEMA = "synkit.reaction-stereo-interchange/1"
|
|
21
|
+
REACTION_STEREO_SIDECAR_KEY = "reaction_stereo_json"
|
|
22
|
+
REACTION_STEREO_DIGEST_KEY = "reaction_stereo_sha256"
|
|
23
|
+
|
|
24
|
+
_SIDECAR_FORMATS = frozenset({"internal_graph", "gml"})
|
|
25
|
+
_WIRE_FORMATS = frozenset({"canonical_dict", "canonical_json"})
|
|
26
|
+
_ENDPOINT_FORMATS = frozenset({"reaction_smiles", "cxsmiles", "mol_v3000"})
|
|
27
|
+
SUPPORTED_REACTION_STEREO_FORMATS = _SIDECAR_FORMATS | _WIRE_FORMATS | _ENDPOINT_FORMATS
|
|
28
|
+
_AXES = (
|
|
29
|
+
"guards",
|
|
30
|
+
"effects",
|
|
31
|
+
"outcomes",
|
|
32
|
+
"couplings",
|
|
33
|
+
"assertions",
|
|
34
|
+
"refusals",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ReactionStereoInterchangeError(ValueError):
|
|
39
|
+
"""Raised when strict projection would discard reaction semantics."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, report: "ReactionStereoInterchangeReport") -> None:
|
|
42
|
+
self.report = report
|
|
43
|
+
super().__init__(
|
|
44
|
+
f"{report.target_format} cannot losslessly encode "
|
|
45
|
+
f"{', '.join(issue.axis for issue in report.issues)}"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True)
|
|
50
|
+
class ReactionStereoInterchangeIssue:
|
|
51
|
+
"""One semantic axis not representable in the target carrier."""
|
|
52
|
+
|
|
53
|
+
code: str
|
|
54
|
+
axis: str
|
|
55
|
+
targets: tuple[str, ...]
|
|
56
|
+
severity: str = "ERROR"
|
|
57
|
+
detail: str = ""
|
|
58
|
+
|
|
59
|
+
def to_dict(self) -> dict[str, Any]:
|
|
60
|
+
return {
|
|
61
|
+
"code": self.code,
|
|
62
|
+
"axis": self.axis,
|
|
63
|
+
"targets": list(self.targets),
|
|
64
|
+
"severity": self.severity,
|
|
65
|
+
"detail": self.detail,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass(frozen=True)
|
|
70
|
+
class ReactionStereoInterchangeReport:
|
|
71
|
+
"""Stable loss/refusal ledger for one projection."""
|
|
72
|
+
|
|
73
|
+
target_format: str
|
|
74
|
+
issues: tuple[ReactionStereoInterchangeIssue, ...] = ()
|
|
75
|
+
sidecar_available: bool = False
|
|
76
|
+
schema: str = REACTION_STEREO_INTERCHANGE_SCHEMA
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def lossless(self) -> bool:
|
|
80
|
+
return not self.issues
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def status(self) -> str:
|
|
84
|
+
return "PRESERVED" if self.lossless else "REFUSED"
|
|
85
|
+
|
|
86
|
+
def to_dict(self) -> dict[str, Any]:
|
|
87
|
+
return {
|
|
88
|
+
"schema": self.schema,
|
|
89
|
+
"target_format": self.target_format,
|
|
90
|
+
"status": self.status,
|
|
91
|
+
"lossless": self.lossless,
|
|
92
|
+
"sidecar_available": self.sidecar_available,
|
|
93
|
+
"issues": [issue.to_dict() for issue in self.issues],
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _axis_targets(
|
|
98
|
+
value: StereoReactionValue,
|
|
99
|
+
) -> tuple[tuple[str, tuple[str, ...]], ...]:
|
|
100
|
+
return (
|
|
101
|
+
("guards", tuple(value.guards)),
|
|
102
|
+
("effects", tuple(value.effects)),
|
|
103
|
+
("outcomes", tuple(value.outcomes)),
|
|
104
|
+
("couplings", tuple(value.couplings)),
|
|
105
|
+
("assertions", tuple(value.assertions)),
|
|
106
|
+
(
|
|
107
|
+
"refusals",
|
|
108
|
+
tuple(
|
|
109
|
+
target
|
|
110
|
+
for refusal in value.refusals
|
|
111
|
+
for target in (refusal.targets or ("reaction",))
|
|
112
|
+
),
|
|
113
|
+
),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _endpoint_report(
|
|
118
|
+
value: StereoReactionValue,
|
|
119
|
+
target_format: str,
|
|
120
|
+
) -> ReactionStereoInterchangeReport:
|
|
121
|
+
issues = tuple(
|
|
122
|
+
ReactionStereoInterchangeIssue(
|
|
123
|
+
"REACTION_AXIS_NOT_REPRESENTABLE",
|
|
124
|
+
axis,
|
|
125
|
+
tuple(sorted(set(targets))),
|
|
126
|
+
detail=(
|
|
127
|
+
f"{target_format} is an endpoint carrier and has no normative "
|
|
128
|
+
f"field for reaction-stereo {axis}."
|
|
129
|
+
),
|
|
130
|
+
)
|
|
131
|
+
for axis, targets in _axis_targets(value)
|
|
132
|
+
if targets
|
|
133
|
+
)
|
|
134
|
+
return ReactionStereoInterchangeReport(
|
|
135
|
+
target_format,
|
|
136
|
+
issues,
|
|
137
|
+
sidecar_available=True,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def project_reaction_stereo(
|
|
142
|
+
value: StereoReactionValue,
|
|
143
|
+
target_format: str,
|
|
144
|
+
*,
|
|
145
|
+
carrier: Any | None = None,
|
|
146
|
+
strict: bool = True,
|
|
147
|
+
) -> tuple[Any, ReactionStereoInterchangeReport]:
|
|
148
|
+
"""Project a complete value, preserving it or reporting every lost axis.
|
|
149
|
+
|
|
150
|
+
``carrier`` is the endpoint text/value supplied by the caller for
|
|
151
|
+
reaction SMILES, CXSMILES, or MOL V3000. SynKit never claims that such a
|
|
152
|
+
carrier contains rule semantics merely because the endpoints retain local
|
|
153
|
+
stereochemical labels.
|
|
154
|
+
"""
|
|
155
|
+
target_format = target_format.lower()
|
|
156
|
+
if target_format not in SUPPORTED_REACTION_STEREO_FORMATS:
|
|
157
|
+
raise ValueError(f"Unsupported reaction-stereo format: {target_format!r}.")
|
|
158
|
+
if target_format == "canonical_dict":
|
|
159
|
+
return value.to_dict(), ReactionStereoInterchangeReport(target_format)
|
|
160
|
+
if target_format == "canonical_json":
|
|
161
|
+
return (
|
|
162
|
+
value.normalized_json(),
|
|
163
|
+
ReactionStereoInterchangeReport(target_format),
|
|
164
|
+
)
|
|
165
|
+
if target_format == "internal_graph":
|
|
166
|
+
if carrier is not None and not isinstance(carrier, nx.Graph):
|
|
167
|
+
raise TypeError("internal_graph carrier must be a NetworkX graph.")
|
|
168
|
+
graph = nx.Graph() if carrier is None else nx.Graph(carrier)
|
|
169
|
+
_attach_sidecar(graph, value)
|
|
170
|
+
return graph, ReactionStereoInterchangeReport(
|
|
171
|
+
target_format,
|
|
172
|
+
sidecar_available=True,
|
|
173
|
+
)
|
|
174
|
+
if target_format == "gml":
|
|
175
|
+
if carrier is not None and not isinstance(carrier, nx.Graph):
|
|
176
|
+
raise TypeError("gml carrier must be a NetworkX graph.")
|
|
177
|
+
graph = nx.Graph() if carrier is None else nx.Graph(carrier)
|
|
178
|
+
_attach_sidecar(graph, value)
|
|
179
|
+
text = "\n".join(nx.generate_gml(graph))
|
|
180
|
+
return text, ReactionStereoInterchangeReport(
|
|
181
|
+
target_format,
|
|
182
|
+
sidecar_available=True,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
report = _endpoint_report(value, target_format)
|
|
186
|
+
if strict and not report.lossless:
|
|
187
|
+
raise ReactionStereoInterchangeError(report)
|
|
188
|
+
return carrier, report
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _attach_sidecar(graph: nx.Graph, value: StereoReactionValue) -> None:
|
|
192
|
+
payload = value.normalized_json()
|
|
193
|
+
graph.graph[REACTION_STEREO_SIDECAR_KEY] = payload
|
|
194
|
+
graph.graph[REACTION_STEREO_DIGEST_KEY] = sha256(
|
|
195
|
+
payload.encode("utf-8")
|
|
196
|
+
).hexdigest()
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _value_from_sidecar(
|
|
200
|
+
attributes: Mapping[str, Any],
|
|
201
|
+
) -> StereoReactionValue:
|
|
202
|
+
try:
|
|
203
|
+
payload = str(attributes[REACTION_STEREO_SIDECAR_KEY])
|
|
204
|
+
observed = str(attributes[REACTION_STEREO_DIGEST_KEY])
|
|
205
|
+
except KeyError as error:
|
|
206
|
+
raise ValueError("Reaction-stereo sidecar or digest is missing.") from error
|
|
207
|
+
expected = sha256(payload.encode("utf-8")).hexdigest()
|
|
208
|
+
if observed != expected:
|
|
209
|
+
raise ValueError("Reaction-stereo sidecar digest mismatch.")
|
|
210
|
+
return StereoReactionValue.from_json(payload)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def reaction_stereo_from_graph(
|
|
214
|
+
graph: nx.Graph,
|
|
215
|
+
) -> StereoReactionValue:
|
|
216
|
+
"""Read and authenticate a reaction-stereo internal-graph sidecar."""
|
|
217
|
+
return _value_from_sidecar(graph.graph)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def reaction_stereo_from_gml(
|
|
221
|
+
text: str,
|
|
222
|
+
) -> tuple[nx.Graph, StereoReactionValue]:
|
|
223
|
+
"""Read GML and authenticate its complete reaction-stereo sidecar."""
|
|
224
|
+
graph = nx.parse_gml(text.splitlines())
|
|
225
|
+
return graph, _value_from_sidecar(graph.graph)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def reaction_stereo_interchange_schema() -> dict[str, Any]:
|
|
229
|
+
"""Return the dependency-free schema for the loss ledger."""
|
|
230
|
+
return {
|
|
231
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
232
|
+
"$id": REACTION_STEREO_INTERCHANGE_SCHEMA,
|
|
233
|
+
"type": "object",
|
|
234
|
+
"additionalProperties": False,
|
|
235
|
+
"required": [
|
|
236
|
+
"schema",
|
|
237
|
+
"target_format",
|
|
238
|
+
"status",
|
|
239
|
+
"lossless",
|
|
240
|
+
"sidecar_available",
|
|
241
|
+
"issues",
|
|
242
|
+
],
|
|
243
|
+
"properties": {
|
|
244
|
+
"schema": {"const": REACTION_STEREO_INTERCHANGE_SCHEMA},
|
|
245
|
+
"target_format": {"enum": sorted(SUPPORTED_REACTION_STEREO_FORMATS)},
|
|
246
|
+
"status": {"enum": ["PRESERVED", "REFUSED"]},
|
|
247
|
+
"lossless": {"type": "boolean"},
|
|
248
|
+
"sidecar_available": {"type": "boolean"},
|
|
249
|
+
"issues": {"type": "array"},
|
|
250
|
+
},
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
__all__ = [
|
|
255
|
+
"REACTION_STEREO_DIGEST_KEY",
|
|
256
|
+
"REACTION_STEREO_INTERCHANGE_SCHEMA",
|
|
257
|
+
"REACTION_STEREO_SIDECAR_KEY",
|
|
258
|
+
"SUPPORTED_REACTION_STEREO_FORMATS",
|
|
259
|
+
"ReactionStereoInterchangeError",
|
|
260
|
+
"ReactionStereoInterchangeIssue",
|
|
261
|
+
"ReactionStereoInterchangeReport",
|
|
262
|
+
"project_reaction_stereo",
|
|
263
|
+
"reaction_stereo_from_gml",
|
|
264
|
+
"reaction_stereo_from_graph",
|
|
265
|
+
"reaction_stereo_interchange_schema",
|
|
266
|
+
]
|