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
synkit/IO/nx_to_gml.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import networkx as nx
|
|
2
|
+
from typing import Tuple, List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class NXToGML:
|
|
6
|
+
"""Converts NetworkX graph representations of chemical reactions to GML
|
|
7
|
+
(Graph Modelling Language) strings. Useful for exporting reaction rules in
|
|
8
|
+
a standard graph format.
|
|
9
|
+
|
|
10
|
+
This class provides static methods for converting individual graphs,
|
|
11
|
+
sets of reaction graphs, and managing charge/attribute changes in
|
|
12
|
+
the export process.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self) -> None:
|
|
16
|
+
"""Initializes an NXToGML object."""
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def _charge_to_string(charge: int) -> str:
|
|
21
|
+
"""Converts an integer charge into a string representation.
|
|
22
|
+
|
|
23
|
+
:param charge: The charge value, which can be positive,
|
|
24
|
+
negative, or zero.
|
|
25
|
+
:type charge: int
|
|
26
|
+
:return: The string representation of the charge (e.g. '+',
|
|
27
|
+
'2+', '-', '3-', '').
|
|
28
|
+
:rtype: str
|
|
29
|
+
"""
|
|
30
|
+
if charge > 0:
|
|
31
|
+
return "+" if charge == 1 else f"{charge}+"
|
|
32
|
+
elif charge < 0:
|
|
33
|
+
return "-" if charge == -1 else f"{-charge}-"
|
|
34
|
+
else:
|
|
35
|
+
return ""
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def _find_changed_nodes(
|
|
39
|
+
graph1: nx.Graph, graph2: nx.Graph, attributes: List[str] = ["charge"]
|
|
40
|
+
) -> List[int]:
|
|
41
|
+
"""Identifies nodes with changes in specified attributes between two
|
|
42
|
+
NetworkX graphs.
|
|
43
|
+
|
|
44
|
+
:param graph1: The first NetworkX graph.
|
|
45
|
+
:type graph1: nx.Graph
|
|
46
|
+
:param graph2: The second NetworkX graph.
|
|
47
|
+
:type graph2: nx.Graph
|
|
48
|
+
:param attributes: List of attribute names to check for changes.
|
|
49
|
+
:type attributes: list[str]
|
|
50
|
+
:return: Node identifiers that have changes in the specified
|
|
51
|
+
attributes.
|
|
52
|
+
:rtype: list[int]
|
|
53
|
+
"""
|
|
54
|
+
changed_nodes = []
|
|
55
|
+
for node in graph1.nodes():
|
|
56
|
+
if node in graph2:
|
|
57
|
+
for attr in attributes:
|
|
58
|
+
value1 = graph1.nodes[node].get(attr, None)
|
|
59
|
+
value2 = graph2.nodes[node].get(attr, None)
|
|
60
|
+
if value1 != value2:
|
|
61
|
+
changed_nodes.append(node)
|
|
62
|
+
break
|
|
63
|
+
return changed_nodes
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def _convert_graph_to_gml(
|
|
67
|
+
graph: nx.Graph,
|
|
68
|
+
section: str,
|
|
69
|
+
changed_node_ids: List[int],
|
|
70
|
+
explicit_hydrogen: bool = False,
|
|
71
|
+
) -> str:
|
|
72
|
+
"""Converts a NetworkX graph to a GML string for a specific reaction
|
|
73
|
+
section.
|
|
74
|
+
|
|
75
|
+
:param graph: The NetworkX graph to be converted.
|
|
76
|
+
:type graph: nx.Graph
|
|
77
|
+
:param section: The section name in the GML output ('left',
|
|
78
|
+
'right', or 'context').
|
|
79
|
+
:type section: str
|
|
80
|
+
:param changed_node_ids: List of nodes with changed attributes.
|
|
81
|
+
:type changed_node_ids: list[int]
|
|
82
|
+
:param explicit_hydrogen: Whether to explicitly include hydrogen
|
|
83
|
+
atoms in the output.
|
|
84
|
+
:type explicit_hydrogen: bool
|
|
85
|
+
:return: The GML string representation of the graph for the
|
|
86
|
+
specified section.
|
|
87
|
+
:rtype: str
|
|
88
|
+
"""
|
|
89
|
+
order_to_label = {1: "-", 1.5: ":", 2: "=", 3: "#"}
|
|
90
|
+
gml_str = f" {section} [\n"
|
|
91
|
+
|
|
92
|
+
if section == "context":
|
|
93
|
+
for node in graph.nodes(data=True):
|
|
94
|
+
if node[0] not in changed_node_ids:
|
|
95
|
+
element = node[1].get("element", "X")
|
|
96
|
+
charge = node[1].get("charge", 0)
|
|
97
|
+
charge_str = NXToGML._charge_to_string(charge)
|
|
98
|
+
gml_str += (
|
|
99
|
+
f' node [ id {node[0]} label "{element}{charge_str}" ]\n'
|
|
100
|
+
)
|
|
101
|
+
if explicit_hydrogen:
|
|
102
|
+
for edge in graph.edges(data=True):
|
|
103
|
+
order = edge[2].get("order", (1.0, 1.0))
|
|
104
|
+
standard_order = edge[2].get("standard_order", (0))
|
|
105
|
+
if standard_order == 0:
|
|
106
|
+
label = order_to_label.get(order, "-")
|
|
107
|
+
gml_str += (
|
|
108
|
+
f" edge [ source {edge[0]} target {edge[1]}"
|
|
109
|
+
+ f' label "{label}" ]\n'
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
if section != "context":
|
|
113
|
+
for edge in graph.edges(data=True):
|
|
114
|
+
label = order_to_label.get(edge[2].get("order", 1), "-")
|
|
115
|
+
gml_str += f' edge [ source {edge[0]} target {edge[1]} label "{label}" ]\n'
|
|
116
|
+
for node in graph.nodes(data=True):
|
|
117
|
+
if node[0] in changed_node_ids:
|
|
118
|
+
element = node[1].get("element", "X")
|
|
119
|
+
charge = node[1].get("charge", 0)
|
|
120
|
+
charge_str = NXToGML._charge_to_string(charge)
|
|
121
|
+
gml_str += (
|
|
122
|
+
f' node [ id {node[0]} label "{element}{charge_str}" ]\n'
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
gml_str += " ]\n"
|
|
126
|
+
return gml_str
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def _rule_grammar(
|
|
130
|
+
L: nx.Graph,
|
|
131
|
+
R: nx.Graph,
|
|
132
|
+
K: nx.Graph,
|
|
133
|
+
rule_name: str,
|
|
134
|
+
changed_node_ids: List[int],
|
|
135
|
+
explicit_hydrogen: bool,
|
|
136
|
+
) -> str:
|
|
137
|
+
"""Generates a GML string for a chemical rule, including left, context,
|
|
138
|
+
and right graphs.
|
|
139
|
+
|
|
140
|
+
:param L: The left graph.
|
|
141
|
+
:type L: nx.Graph
|
|
142
|
+
:param R: The right graph.
|
|
143
|
+
:type R: nx.Graph
|
|
144
|
+
:param K: The context graph.
|
|
145
|
+
:type K: nx.Graph
|
|
146
|
+
:param rule_name: The name of the rule.
|
|
147
|
+
:type rule_name: str
|
|
148
|
+
:param changed_node_ids: List of nodes with changed attributes.
|
|
149
|
+
:type changed_node_ids: list[int]
|
|
150
|
+
:param explicit_hydrogen: Whether to explicitly include hydrogen
|
|
151
|
+
atoms in the output.
|
|
152
|
+
:type explicit_hydrogen: bool
|
|
153
|
+
:return: The GML string representation of the rule.
|
|
154
|
+
:rtype: str
|
|
155
|
+
"""
|
|
156
|
+
gml_str = "rule [\n"
|
|
157
|
+
gml_str += f' ruleID "{rule_name}"\n'
|
|
158
|
+
gml_str += NXToGML._convert_graph_to_gml(L, "left", changed_node_ids)
|
|
159
|
+
gml_str += NXToGML._convert_graph_to_gml(
|
|
160
|
+
K, "context", changed_node_ids, explicit_hydrogen
|
|
161
|
+
)
|
|
162
|
+
gml_str += NXToGML._convert_graph_to_gml(R, "right", changed_node_ids)
|
|
163
|
+
gml_str += "]"
|
|
164
|
+
return gml_str
|
|
165
|
+
|
|
166
|
+
@staticmethod
|
|
167
|
+
def transform(
|
|
168
|
+
graph_rules: Tuple[nx.Graph, nx.Graph, nx.Graph],
|
|
169
|
+
rule_name: str = "Test",
|
|
170
|
+
reindex: bool = False,
|
|
171
|
+
attributes: List[str] = ["charge"],
|
|
172
|
+
explicit_hydrogen: bool = False,
|
|
173
|
+
) -> str:
|
|
174
|
+
"""Processes a triple of reaction graphs to generate a GML string rule,
|
|
175
|
+
with options for node reindexing and explicit hydrogen expansion.
|
|
176
|
+
|
|
177
|
+
:param graph_rules: Tuple containing (L, R, K) reaction graphs.
|
|
178
|
+
:type graph_rules: tuple[nx.Graph, nx.Graph, nx.Graph]
|
|
179
|
+
:param rule_name: The rule name to use in the output.
|
|
180
|
+
:type rule_name: str
|
|
181
|
+
:param reindex: Whether to reindex node IDs based on the L graph
|
|
182
|
+
sequence.
|
|
183
|
+
:type reindex: bool
|
|
184
|
+
:param attributes: List of attribute names to check for node
|
|
185
|
+
changes.
|
|
186
|
+
:type attributes: list[str]
|
|
187
|
+
:param explicit_hydrogen: Whether to explicitly include hydrogen
|
|
188
|
+
atoms in the output.
|
|
189
|
+
:type explicit_hydrogen: bool
|
|
190
|
+
:return: The GML string representing the chemical rule.
|
|
191
|
+
:rtype: str
|
|
192
|
+
"""
|
|
193
|
+
L, R, K = graph_rules
|
|
194
|
+
if explicit_hydrogen:
|
|
195
|
+
from synkit.Graph.Hyrogen._misc import h_to_explicit
|
|
196
|
+
|
|
197
|
+
K = h_to_explicit(K, nodes=None)
|
|
198
|
+
if reindex:
|
|
199
|
+
index_mapping = {
|
|
200
|
+
old_id: new_id for new_id, old_id in enumerate(L.nodes(), 1)
|
|
201
|
+
}
|
|
202
|
+
L = nx.relabel_nodes(L, index_mapping)
|
|
203
|
+
R = nx.relabel_nodes(R, index_mapping)
|
|
204
|
+
K = nx.relabel_nodes(K, index_mapping)
|
|
205
|
+
changed_node_ids = NXToGML._find_changed_nodes(L, R, attributes)
|
|
206
|
+
rule_grammar = NXToGML._rule_grammar(
|
|
207
|
+
L, R, K, rule_name, changed_node_ids, explicit_hydrogen
|
|
208
|
+
)
|
|
209
|
+
return rule_grammar
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import requests
|
|
3
|
+
import urllib.parse
|
|
4
|
+
from typing import List
|
|
5
|
+
from joblib import Parallel, delayed
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def smiles_to_iupac(smiles_string: str, timeout: int = 1):
|
|
9
|
+
"""Converts a SMILES string to its corresponding IUPAC name(s) using the
|
|
10
|
+
PubChem PUG REST API.
|
|
11
|
+
|
|
12
|
+
:param smiles_string: The SMILES string of the compound (e.g., "C=O" for formaldehyde).
|
|
13
|
+
:type smiles_string: str
|
|
14
|
+
:param timeout: The timeout in seconds for the request. Default is 1 second.
|
|
15
|
+
:type timeout: int, optional
|
|
16
|
+
|
|
17
|
+
:return: A list of IUPAC names associated with the SMILES string. Returns an empty list if none found.
|
|
18
|
+
:rtype: list
|
|
19
|
+
"""
|
|
20
|
+
# URL encode the SMILES string to handle special characters
|
|
21
|
+
encoded_smiles = urllib.parse.quote(smiles_string)
|
|
22
|
+
|
|
23
|
+
# PubChem PUG REST API endpoint to retrieve properties
|
|
24
|
+
url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/smiles/{encoded_smiles}/property/IUPACName/JSON"
|
|
25
|
+
|
|
26
|
+
retries = 3 # Number of retries in case of failure
|
|
27
|
+
delay = 2 # Delay between retries (in seconds)
|
|
28
|
+
|
|
29
|
+
for attempt in range(retries):
|
|
30
|
+
try:
|
|
31
|
+
response = requests.get(url, timeout=timeout) # Adjust timeout for speed
|
|
32
|
+
response.raise_for_status() # Raise an HTTPError for bad responses
|
|
33
|
+
|
|
34
|
+
data = response.json()
|
|
35
|
+
|
|
36
|
+
# Extract the IUPAC name(s) from the response
|
|
37
|
+
properties = data.get("PropertyTable", {}).get("Properties", [])
|
|
38
|
+
|
|
39
|
+
if not properties:
|
|
40
|
+
print(f"No properties found for SMILES: {smiles_string}")
|
|
41
|
+
return []
|
|
42
|
+
|
|
43
|
+
iupac_names = [
|
|
44
|
+
prop.get("IUPACName") for prop in properties if prop.get("IUPACName")
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
if iupac_names:
|
|
48
|
+
return iupac_names
|
|
49
|
+
else:
|
|
50
|
+
print(f"No IUPAC name found for SMILES: {smiles_string}")
|
|
51
|
+
return []
|
|
52
|
+
|
|
53
|
+
except (requests.exceptions.RequestException, ValueError, KeyError) as e:
|
|
54
|
+
# If an error occurs, retry a few times
|
|
55
|
+
print(
|
|
56
|
+
f"Attempt {attempt + 1} failed for SMILES: {smiles_string}, Error: {e}"
|
|
57
|
+
)
|
|
58
|
+
if attempt < retries - 1:
|
|
59
|
+
time.sleep(delay) # Wait before retrying
|
|
60
|
+
else:
|
|
61
|
+
print(f"Final failure for SMILES: {smiles_string}")
|
|
62
|
+
return []
|
|
63
|
+
|
|
64
|
+
return []
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def batch_process_smiles(smiles_batch: List[str], timeout=1):
|
|
68
|
+
"""Processes a batch of SMILES strings to get IUPAC names.
|
|
69
|
+
|
|
70
|
+
:param smiles_batch: A list of SMILES strings to process.
|
|
71
|
+
:type smiles_batch: list
|
|
72
|
+
:param timeout: Timeout for requests (in seconds).
|
|
73
|
+
:type timeout: int
|
|
74
|
+
|
|
75
|
+
:return: A list of IUPAC name results for each SMILES in the batch.
|
|
76
|
+
:rtype: list
|
|
77
|
+
"""
|
|
78
|
+
return [smiles_to_iupac(smiles, timeout) for smiles in smiles_batch]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def get_iupac_for_smiles_list(
|
|
82
|
+
smiles_list: List[str], batch_size=10, n_jobs=4, timeout=1
|
|
83
|
+
):
|
|
84
|
+
"""Convert a list of SMILES strings to their corresponding IUPAC names
|
|
85
|
+
using the PubChem API with batch processing.
|
|
86
|
+
|
|
87
|
+
:param smiles_list: A list of SMILES strings to be converted to IUPAC names.
|
|
88
|
+
:type smiles_list: list
|
|
89
|
+
:param batch_size: Number of SMILES strings to process in each batch.
|
|
90
|
+
:type batch_size: int
|
|
91
|
+
:param n_jobs: Number of parallel jobs to run for batch processing.
|
|
92
|
+
:type n_jobs: int
|
|
93
|
+
:param timeout: Timeout for requests (in seconds).
|
|
94
|
+
:type timeout: int
|
|
95
|
+
|
|
96
|
+
:return: A dictionary with SMILES as keys and lists of IUPAC names as values.
|
|
97
|
+
:rtype: dict
|
|
98
|
+
"""
|
|
99
|
+
# Split the list into smaller batches
|
|
100
|
+
# fmt: off
|
|
101
|
+
batches = [
|
|
102
|
+
smiles_list[i: i + batch_size] for i in range(0, len(smiles_list), batch_size)
|
|
103
|
+
]
|
|
104
|
+
# fmt: on
|
|
105
|
+
|
|
106
|
+
# Use joblib's Parallel and delayed to process batches in parallel
|
|
107
|
+
batch_results = Parallel(n_jobs=n_jobs)(
|
|
108
|
+
delayed(batch_process_smiles)(batch, timeout) for batch in batches
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Flatten the list of results and map to SMILES
|
|
112
|
+
flattened_results = [item for sublist in batch_results for item in sublist]
|
|
113
|
+
iupac_dict = dict(zip(smiles_list, flattened_results))
|
|
114
|
+
|
|
115
|
+
return iupac_dict
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# Example of usage
|
|
119
|
+
smiles_list = ["CCO", "C=O", "CC(=O)O", "C1=CC=CC=C1", "C2H6O", "C4H10", "C5H12"]
|
|
120
|
+
iupac_results = get_iupac_for_smiles_list(smiles_list, batch_size=3, n_jobs=2)
|
|
121
|
+
|
|
122
|
+
for smiles, iupac_names in iupac_results.items():
|
|
123
|
+
print(f"SMILES: {smiles} => IUPAC Names: {iupac_names}")
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Public v2 models for representing supplied reaction mechanisms."""
|
|
2
|
+
|
|
3
|
+
from .adapters import (
|
|
4
|
+
electron_move_from_legacy_epd,
|
|
5
|
+
group_from_legacy_epd,
|
|
6
|
+
legacy_epd_from_group,
|
|
7
|
+
mechanism_from_ef_smirks,
|
|
8
|
+
mechanism_from_legacy_epd,
|
|
9
|
+
)
|
|
10
|
+
from .audit import (
|
|
11
|
+
LocalElectronStateAudit,
|
|
12
|
+
RadicalStateAudit,
|
|
13
|
+
audit_local_electron_state,
|
|
14
|
+
radical_counts_by_atom_map,
|
|
15
|
+
radical_match,
|
|
16
|
+
)
|
|
17
|
+
from .compatibility import (
|
|
18
|
+
COMPATIBLE_LEWIS_GRAPH_ACRONYMS,
|
|
19
|
+
LEGACY_LEWIS_GRAPH_ACRONYM,
|
|
20
|
+
PREVIOUS_PUBLIC_LEWIS_GRAPH_ACRONYM,
|
|
21
|
+
PUBLIC_LEWIS_GRAPH_ACRONYM,
|
|
22
|
+
PUBLIC_LEWIS_GRAPH_NAME,
|
|
23
|
+
)
|
|
24
|
+
from .model import (
|
|
25
|
+
SCHEMA_VERSION,
|
|
26
|
+
ElectronLocus,
|
|
27
|
+
ElectronMove,
|
|
28
|
+
ElectronMoveGroup,
|
|
29
|
+
ElectrocyclicStereoMotion,
|
|
30
|
+
MechanismModelError,
|
|
31
|
+
MechanismRecord,
|
|
32
|
+
MechanisticStep,
|
|
33
|
+
StereoDescriptor,
|
|
34
|
+
StereoEffect,
|
|
35
|
+
VerificationCertificate,
|
|
36
|
+
VerificationIssue,
|
|
37
|
+
)
|
|
38
|
+
from .neighbor_stereo import RelativeNeighborChange
|
|
39
|
+
from .schema import mechanism_record_schema
|
|
40
|
+
from .equivalence import mechanism_equivalent
|
|
41
|
+
from .interchange import (
|
|
42
|
+
ConversionLossReport,
|
|
43
|
+
project_record,
|
|
44
|
+
project_stereo_graph,
|
|
45
|
+
stereo_graph_from_gml,
|
|
46
|
+
stereo_graph_to_gml,
|
|
47
|
+
)
|
|
48
|
+
from .stereo_state import (
|
|
49
|
+
StereoStateTimeline,
|
|
50
|
+
apply_stereo_effects,
|
|
51
|
+
stereo_timeline,
|
|
52
|
+
)
|
|
53
|
+
from .benchmark import (
|
|
54
|
+
BenchmarkCase,
|
|
55
|
+
CorruptedAnnotation,
|
|
56
|
+
benchmark_release_issues,
|
|
57
|
+
corrupt_record,
|
|
58
|
+
radical_candidates,
|
|
59
|
+
write_candidate_manifest,
|
|
60
|
+
)
|
|
61
|
+
from .radical_data import (
|
|
62
|
+
RADICAL_CLASS_TO_MACRO,
|
|
63
|
+
RadicalAAMCompletionResult,
|
|
64
|
+
RadicalDatasetRecord,
|
|
65
|
+
RadicalNormalizationReport,
|
|
66
|
+
complete_radical_aam,
|
|
67
|
+
iter_radical_csv,
|
|
68
|
+
normalize_radical_row,
|
|
69
|
+
radical_dataset_summary,
|
|
70
|
+
)
|
|
71
|
+
from .replay import (
|
|
72
|
+
GroupReplayReport,
|
|
73
|
+
MechanismReplayer,
|
|
74
|
+
MechanismReplayResult,
|
|
75
|
+
)
|
|
76
|
+
from .symbols import (
|
|
77
|
+
LONE_PAIR,
|
|
78
|
+
PI,
|
|
79
|
+
RADICAL,
|
|
80
|
+
SIGMA,
|
|
81
|
+
external_locus_symbol,
|
|
82
|
+
internal_action_label,
|
|
83
|
+
legacy_action_label,
|
|
84
|
+
normalize_locus_symbol,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
__all__ = [
|
|
88
|
+
"SCHEMA_VERSION",
|
|
89
|
+
"ElectronLocus",
|
|
90
|
+
"ElectronMove",
|
|
91
|
+
"ElectronMoveGroup",
|
|
92
|
+
"ElectrocyclicStereoMotion",
|
|
93
|
+
"MechanismModelError",
|
|
94
|
+
"MechanismRecord",
|
|
95
|
+
"MechanisticStep",
|
|
96
|
+
"StereoDescriptor",
|
|
97
|
+
"StereoEffect",
|
|
98
|
+
"VerificationCertificate",
|
|
99
|
+
"VerificationIssue",
|
|
100
|
+
"RelativeNeighborChange",
|
|
101
|
+
"RadicalStateAudit",
|
|
102
|
+
"LocalElectronStateAudit",
|
|
103
|
+
"audit_local_electron_state",
|
|
104
|
+
"PUBLIC_LEWIS_GRAPH_NAME",
|
|
105
|
+
"PUBLIC_LEWIS_GRAPH_ACRONYM",
|
|
106
|
+
"PREVIOUS_PUBLIC_LEWIS_GRAPH_ACRONYM",
|
|
107
|
+
"LEGACY_LEWIS_GRAPH_ACRONYM",
|
|
108
|
+
"COMPATIBLE_LEWIS_GRAPH_ACRONYMS",
|
|
109
|
+
"radical_counts_by_atom_map",
|
|
110
|
+
"radical_match",
|
|
111
|
+
"electron_move_from_legacy_epd",
|
|
112
|
+
"group_from_legacy_epd",
|
|
113
|
+
"legacy_epd_from_group",
|
|
114
|
+
"mechanism_from_ef_smirks",
|
|
115
|
+
"mechanism_from_legacy_epd",
|
|
116
|
+
"mechanism_record_schema",
|
|
117
|
+
"LONE_PAIR",
|
|
118
|
+
"SIGMA",
|
|
119
|
+
"PI",
|
|
120
|
+
"RADICAL",
|
|
121
|
+
"normalize_locus_symbol",
|
|
122
|
+
"external_locus_symbol",
|
|
123
|
+
"internal_action_label",
|
|
124
|
+
"legacy_action_label",
|
|
125
|
+
"RADICAL_CLASS_TO_MACRO",
|
|
126
|
+
"RadicalAAMCompletionResult",
|
|
127
|
+
"RadicalDatasetRecord",
|
|
128
|
+
"RadicalNormalizationReport",
|
|
129
|
+
"complete_radical_aam",
|
|
130
|
+
"normalize_radical_row",
|
|
131
|
+
"iter_radical_csv",
|
|
132
|
+
"radical_dataset_summary",
|
|
133
|
+
"GroupReplayReport",
|
|
134
|
+
"MechanismReplayer",
|
|
135
|
+
"MechanismReplayResult",
|
|
136
|
+
"mechanism_equivalent",
|
|
137
|
+
"ConversionLossReport",
|
|
138
|
+
"project_record",
|
|
139
|
+
"project_stereo_graph",
|
|
140
|
+
"stereo_graph_from_gml",
|
|
141
|
+
"stereo_graph_to_gml",
|
|
142
|
+
"apply_stereo_effects",
|
|
143
|
+
"stereo_timeline",
|
|
144
|
+
"StereoStateTimeline",
|
|
145
|
+
"BenchmarkCase",
|
|
146
|
+
"CorruptedAnnotation",
|
|
147
|
+
"benchmark_release_issues",
|
|
148
|
+
"corrupt_record",
|
|
149
|
+
"radical_candidates",
|
|
150
|
+
"write_candidate_manifest",
|
|
151
|
+
]
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""Compatibility adapters between v1 EPD/EF-SMIRKS and v2 models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Iterable, Sequence
|
|
6
|
+
|
|
7
|
+
from .model import (
|
|
8
|
+
ElectronLocus,
|
|
9
|
+
ElectronMove,
|
|
10
|
+
ElectronMoveGroup,
|
|
11
|
+
MechanismModelError,
|
|
12
|
+
MechanismRecord,
|
|
13
|
+
MechanisticStep,
|
|
14
|
+
)
|
|
15
|
+
from .symbols import legacy_action_label, normalize_locus_symbol
|
|
16
|
+
|
|
17
|
+
_ACTION_LOCI = {
|
|
18
|
+
"LP": "lp",
|
|
19
|
+
"RAD": "∙",
|
|
20
|
+
"SIGMA": "σ",
|
|
21
|
+
"PI": "π",
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _locus(token: str, atom_maps: Sequence[int]) -> ElectronLocus:
|
|
26
|
+
kind = _ACTION_LOCI.get(token.strip().upper())
|
|
27
|
+
if kind is None:
|
|
28
|
+
if token.strip().upper() == "B":
|
|
29
|
+
raise MechanismModelError(
|
|
30
|
+
"Generic legacy 'B' does not identify σ versus π; use typed "
|
|
31
|
+
"EPD or an ITS-aware adapter."
|
|
32
|
+
)
|
|
33
|
+
try:
|
|
34
|
+
kind = normalize_locus_symbol(token)
|
|
35
|
+
except (TypeError, ValueError) as exc:
|
|
36
|
+
raise MechanismModelError(
|
|
37
|
+
f"Unsupported legacy EPD locus: {token!r}"
|
|
38
|
+
) from exc
|
|
39
|
+
return ElectronLocus(kind=kind, atom_maps=tuple(int(value) for value in atom_maps))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def electron_move_from_legacy_epd(
|
|
43
|
+
row: Sequence[Any], *, group_id: str = "g1", event_id: str | None = None
|
|
44
|
+
) -> ElectronMove:
|
|
45
|
+
"""Losslessly adapt one polar v1 ``[action, source, target]`` row."""
|
|
46
|
+
if len(row) < 3:
|
|
47
|
+
raise MechanismModelError(f"Invalid legacy EPD row: {row!r}")
|
|
48
|
+
action, source, target = row[:3]
|
|
49
|
+
try:
|
|
50
|
+
source_token, target_token = str(action).split("-/", 1)
|
|
51
|
+
target_token = target_token.removesuffix("+")
|
|
52
|
+
except ValueError as exc:
|
|
53
|
+
raise MechanismModelError(f"Invalid legacy EPD action: {action!r}") from exc
|
|
54
|
+
return ElectronMove(
|
|
55
|
+
event_id=event_id,
|
|
56
|
+
source=_locus(source_token, source),
|
|
57
|
+
target=_locus(target_token, target),
|
|
58
|
+
electron_count=2,
|
|
59
|
+
arrow_type="curved",
|
|
60
|
+
group_id=group_id,
|
|
61
|
+
metadata={"legacy_action": str(action)},
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def group_from_legacy_epd(
|
|
66
|
+
epd: Iterable[Sequence[Any]], *, group_id: str = "g1"
|
|
67
|
+
) -> ElectronMoveGroup:
|
|
68
|
+
moves = tuple(
|
|
69
|
+
electron_move_from_legacy_epd(row, group_id=group_id, event_id=f"e{index}")
|
|
70
|
+
for index, row in enumerate(epd, start=1)
|
|
71
|
+
)
|
|
72
|
+
return ElectronMoveGroup(group_id=group_id, moves=moves)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def mechanism_from_legacy_epd(
|
|
76
|
+
mapped_reaction: str,
|
|
77
|
+
epd: Iterable[Sequence[Any]],
|
|
78
|
+
*,
|
|
79
|
+
provenance: dict[str, Any] | None = None,
|
|
80
|
+
) -> MechanismRecord:
|
|
81
|
+
# Legacy EPD is an ordered list of local edits. Preserve that ordering by
|
|
82
|
+
# giving every row its own step/group; callers can explicitly coalesce
|
|
83
|
+
# events when they have simultaneous-event provenance.
|
|
84
|
+
steps = tuple(
|
|
85
|
+
MechanisticStep(
|
|
86
|
+
step_id=f"s{index}",
|
|
87
|
+
groups=(
|
|
88
|
+
ElectronMoveGroup(
|
|
89
|
+
group_id=f"g{index}",
|
|
90
|
+
moves=(
|
|
91
|
+
electron_move_from_legacy_epd(
|
|
92
|
+
row, group_id=f"g{index}", event_id=f"e{index}"
|
|
93
|
+
),
|
|
94
|
+
),
|
|
95
|
+
),
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
for index, row in enumerate(epd, start=1)
|
|
99
|
+
)
|
|
100
|
+
return MechanismRecord(
|
|
101
|
+
mapped_reaction=mapped_reaction,
|
|
102
|
+
steps=steps,
|
|
103
|
+
provenance={"format": "legacy_epd", **(provenance or {})},
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def mechanism_from_ef_smirks(text: str, **kwargs: Any) -> MechanismRecord:
|
|
108
|
+
"""Create a v2 record from existing EF-SMIRKS conversion support.
|
|
109
|
+
|
|
110
|
+
EF-SMIRKS currently encodes legacy two-electron arrow geometry only;
|
|
111
|
+
fishhook metadata is represented directly by :class:`ElectronMove`.
|
|
112
|
+
"""
|
|
113
|
+
from synkit.Graph.Mech.conversion import ef_smirks_to_epd
|
|
114
|
+
|
|
115
|
+
converted = ef_smirks_to_epd(text, **kwargs)
|
|
116
|
+
return mechanism_from_legacy_epd(
|
|
117
|
+
converted["complete_aam"],
|
|
118
|
+
converted["epd_lw"],
|
|
119
|
+
provenance={"format": "ef_smirks", "ef_smirks": text},
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def legacy_epd_from_group(group: ElectronMoveGroup) -> list[list[Any]]:
|
|
124
|
+
"""Return v1 rows when all moves are representable polar curved arrows."""
|
|
125
|
+
rows: list[list[Any]] = []
|
|
126
|
+
for move in group.moves:
|
|
127
|
+
if move.electron_count != 2:
|
|
128
|
+
raise MechanismModelError("Fishhooks cannot be represented by legacy EPD.")
|
|
129
|
+
rows.append(
|
|
130
|
+
[
|
|
131
|
+
legacy_action_label(move.source.kind, move.target.kind),
|
|
132
|
+
list(move.source.atom_maps),
|
|
133
|
+
list(move.target.atom_maps),
|
|
134
|
+
]
|
|
135
|
+
)
|
|
136
|
+
return rows
|