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,713 @@
|
|
|
1
|
+
"""Conversion between a bipartite CRN digraph and the :class:`SynCRN` tables.
|
|
2
|
+
|
|
3
|
+
One direction collects species and reaction nodes out of a NetworkX digraph and
|
|
4
|
+
builds the canonical tables; the other rebuilds a digraph from those tables,
|
|
5
|
+
preserving the original node ids, node kinds and edge attributes so that a
|
|
6
|
+
round-trip is lossless.
|
|
7
|
+
|
|
8
|
+
Node ordering uses a natural (digit-aware) sort, so ``r_2`` precedes ``r_10``
|
|
9
|
+
and a graph round-trip does not permute a network's reactions.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from collections import Counter
|
|
15
|
+
from typing import Any, Dict, Hashable, List, Optional, Tuple
|
|
16
|
+
import re
|
|
17
|
+
|
|
18
|
+
import networkx as nx
|
|
19
|
+
|
|
20
|
+
from .reaction import RXNSide, Reaction
|
|
21
|
+
from .rule import Rule
|
|
22
|
+
from .species import Species
|
|
23
|
+
from ._parse import ID_STYLES
|
|
24
|
+
|
|
25
|
+
_DIGIT_RUN_RE = re.compile(r"(\d+)")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _natural_chunks(text: str) -> Tuple[Tuple[int, int, str], ...]:
|
|
29
|
+
"""Split a string into comparable alternating text and integer chunks.
|
|
30
|
+
|
|
31
|
+
Each chunk is normalized to a 3-tuple so that chunks of different kinds stay
|
|
32
|
+
comparable: digit runs become ``(0, value, "")`` and text runs become
|
|
33
|
+
``(1, 0, text)``.
|
|
34
|
+
|
|
35
|
+
:param text:
|
|
36
|
+
String to split.
|
|
37
|
+
:type text: str
|
|
38
|
+
|
|
39
|
+
:return:
|
|
40
|
+
Tuple of comparable chunks.
|
|
41
|
+
:rtype: Tuple[Tuple[int, int, str], ...]
|
|
42
|
+
"""
|
|
43
|
+
return tuple(
|
|
44
|
+
(0, int(part), "") if part.isdigit() else (1, 0, part)
|
|
45
|
+
for part in _DIGIT_RUN_RE.split(text)
|
|
46
|
+
if part != ""
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _stable_sort_key(x: Any) -> Tuple[str, Tuple[Tuple[int, int, str], ...]]:
|
|
51
|
+
"""Return a stable, natural sort key for mixed node-id types.
|
|
52
|
+
|
|
53
|
+
Ordering is by type name first, so heterogeneous node ids never compare
|
|
54
|
+
across types, and then by a natural (digit-aware) reading of ``repr``. The
|
|
55
|
+
digit awareness is what keeps ``r_2`` before ``r_10``; a plain lexicographic
|
|
56
|
+
key would reorder a network's reactions on every graph round-trip.
|
|
57
|
+
|
|
58
|
+
:param x:
|
|
59
|
+
Any object that can be represented with ``repr``.
|
|
60
|
+
:type x: Any
|
|
61
|
+
|
|
62
|
+
:return:
|
|
63
|
+
Tuple of type name and natural chunks of ``repr(x)``.
|
|
64
|
+
:rtype: Tuple[str, Tuple[Tuple[int, int, str], ...]]
|
|
65
|
+
|
|
66
|
+
.. rubric:: Example
|
|
67
|
+
|
|
68
|
+
.. code-block:: python
|
|
69
|
+
|
|
70
|
+
sorted(["r_10", "r_2"], key=_stable_sort_key)
|
|
71
|
+
# ['r_2', 'r_10']
|
|
72
|
+
"""
|
|
73
|
+
return (type(x).__name__, _natural_chunks(repr(x)))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _edge_side(is_incoming: bool, role: Optional[str]) -> str:
|
|
77
|
+
"""Resolve the side of a reaction incidence edge.
|
|
78
|
+
|
|
79
|
+
Explicit edge role takes priority. If no role is provided, graph direction
|
|
80
|
+
is used:
|
|
81
|
+
|
|
82
|
+
- ``species -> reaction`` means ``lhs``
|
|
83
|
+
- ``reaction -> species`` means ``rhs``
|
|
84
|
+
|
|
85
|
+
:param is_incoming:
|
|
86
|
+
Whether the edge is incoming to the reaction node.
|
|
87
|
+
:type is_incoming: bool
|
|
88
|
+
|
|
89
|
+
:param role:
|
|
90
|
+
Optional edge role, usually ``"reactant"`` or ``"product"``.
|
|
91
|
+
:type role: Optional[str]
|
|
92
|
+
|
|
93
|
+
:return:
|
|
94
|
+
Either ``"lhs"`` or ``"rhs"``.
|
|
95
|
+
:rtype: str
|
|
96
|
+
|
|
97
|
+
.. rubric:: Example
|
|
98
|
+
|
|
99
|
+
.. code-block:: python
|
|
100
|
+
|
|
101
|
+
_edge_side(True, "reactant")
|
|
102
|
+
# "lhs"
|
|
103
|
+
"""
|
|
104
|
+
if role == "reactant":
|
|
105
|
+
return "lhs"
|
|
106
|
+
if role == "product":
|
|
107
|
+
return "rhs"
|
|
108
|
+
return "lhs" if is_incoming else "rhs"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _collect_bipartite_nodes(
|
|
112
|
+
crn: nx.DiGraph,
|
|
113
|
+
*,
|
|
114
|
+
species_kind: str,
|
|
115
|
+
reaction_kinds: Tuple[str, ...],
|
|
116
|
+
) -> Tuple[List[Hashable], List[Hashable]]:
|
|
117
|
+
"""Collect species and reaction-like nodes from a bipartite CRN graph.
|
|
118
|
+
|
|
119
|
+
:param crn:
|
|
120
|
+
Directed bipartite CRN graph.
|
|
121
|
+
:type crn: nx.DiGraph
|
|
122
|
+
|
|
123
|
+
:param species_kind:
|
|
124
|
+
Node-kind value identifying species nodes.
|
|
125
|
+
:type species_kind: str
|
|
126
|
+
|
|
127
|
+
:param reaction_kinds:
|
|
128
|
+
Node-kind values identifying reaction or rule nodes.
|
|
129
|
+
:type reaction_kinds: Tuple[str, ...]
|
|
130
|
+
|
|
131
|
+
:return:
|
|
132
|
+
Pair ``(species_nodes, reaction_nodes)`` in deterministic order.
|
|
133
|
+
:rtype: Tuple[List[Hashable], List[Hashable]]
|
|
134
|
+
|
|
135
|
+
.. rubric:: Example
|
|
136
|
+
|
|
137
|
+
.. code-block:: python
|
|
138
|
+
|
|
139
|
+
species_nodes, reaction_nodes = _collect_bipartite_nodes(
|
|
140
|
+
crn,
|
|
141
|
+
species_kind="species",
|
|
142
|
+
reaction_kinds=("reaction", "rule"),
|
|
143
|
+
)
|
|
144
|
+
"""
|
|
145
|
+
reaction_kind_set = set(reaction_kinds)
|
|
146
|
+
|
|
147
|
+
species_nodes: List[Hashable] = []
|
|
148
|
+
reaction_nodes: List[Hashable] = []
|
|
149
|
+
|
|
150
|
+
for node, attrs in crn.nodes(data=True):
|
|
151
|
+
kind = attrs.get("kind")
|
|
152
|
+
if kind == species_kind:
|
|
153
|
+
species_nodes.append(node)
|
|
154
|
+
elif kind in reaction_kind_set:
|
|
155
|
+
reaction_nodes.append(node)
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
sorted(species_nodes, key=_stable_sort_key),
|
|
159
|
+
sorted(reaction_nodes, key=_stable_sort_key),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _validate_bipartite_node_sets(
|
|
164
|
+
*,
|
|
165
|
+
species_nodes: List[Hashable],
|
|
166
|
+
reaction_nodes: List[Hashable],
|
|
167
|
+
strict: bool,
|
|
168
|
+
) -> None:
|
|
169
|
+
"""Validate that a bipartite CRN graph contains required node classes.
|
|
170
|
+
|
|
171
|
+
:param species_nodes:
|
|
172
|
+
Collected species nodes.
|
|
173
|
+
:type species_nodes: List[Hashable]
|
|
174
|
+
|
|
175
|
+
:param reaction_nodes:
|
|
176
|
+
Collected reaction-like nodes.
|
|
177
|
+
:type reaction_nodes: List[Hashable]
|
|
178
|
+
|
|
179
|
+
:param strict:
|
|
180
|
+
Whether missing classes should raise an error.
|
|
181
|
+
:type strict: bool
|
|
182
|
+
|
|
183
|
+
:return:
|
|
184
|
+
None.
|
|
185
|
+
:rtype: None
|
|
186
|
+
"""
|
|
187
|
+
if strict and not species_nodes:
|
|
188
|
+
raise ValueError("No species nodes found in graph")
|
|
189
|
+
if strict and not reaction_nodes:
|
|
190
|
+
raise ValueError("No reaction/rule nodes found in graph")
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _make_internal_id_maps(
|
|
194
|
+
*,
|
|
195
|
+
species_nodes: List[Hashable],
|
|
196
|
+
reaction_nodes: List[Hashable],
|
|
197
|
+
species_prefix: str,
|
|
198
|
+
reaction_prefix: str,
|
|
199
|
+
id_style: str = "prefixed",
|
|
200
|
+
) -> Tuple[Dict[Hashable, str], Dict[Hashable, str]]:
|
|
201
|
+
"""Build internal id maps for species and reaction nodes.
|
|
202
|
+
|
|
203
|
+
:param species_nodes:
|
|
204
|
+
Ordered species nodes.
|
|
205
|
+
:type species_nodes: List[Hashable]
|
|
206
|
+
|
|
207
|
+
:param reaction_nodes:
|
|
208
|
+
Ordered reaction-like nodes.
|
|
209
|
+
:type reaction_nodes: List[Hashable]
|
|
210
|
+
|
|
211
|
+
:param species_prefix:
|
|
212
|
+
Prefix for generated species ids.
|
|
213
|
+
:type species_prefix: str
|
|
214
|
+
|
|
215
|
+
:param reaction_prefix:
|
|
216
|
+
Prefix for generated reaction ids.
|
|
217
|
+
:type reaction_prefix: str
|
|
218
|
+
|
|
219
|
+
:param id_style:
|
|
220
|
+
Either ``"prefixed"`` or the legacy shared-namespace ``"numeric"``.
|
|
221
|
+
:type id_style: str
|
|
222
|
+
|
|
223
|
+
:return:
|
|
224
|
+
Pair ``(species_node_to_id, reaction_node_to_id)``.
|
|
225
|
+
:rtype: Tuple[Dict[Hashable, str], Dict[Hashable, str]]
|
|
226
|
+
|
|
227
|
+
:raises ValueError:
|
|
228
|
+
If ``id_style`` is not a recognised policy.
|
|
229
|
+
"""
|
|
230
|
+
if id_style not in ID_STYLES:
|
|
231
|
+
raise ValueError(
|
|
232
|
+
f"id_style must be one of {sorted(ID_STYLES)}, got {id_style!r}"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
if id_style == "numeric":
|
|
236
|
+
offset = len(species_nodes)
|
|
237
|
+
species_node_to_id = {
|
|
238
|
+
node: str(i) for i, node in enumerate(species_nodes, start=1)
|
|
239
|
+
}
|
|
240
|
+
reaction_node_to_id = {
|
|
241
|
+
node: str(offset + i) for i, node in enumerate(reaction_nodes, start=1)
|
|
242
|
+
}
|
|
243
|
+
return species_node_to_id, reaction_node_to_id
|
|
244
|
+
|
|
245
|
+
species_node_to_id = {
|
|
246
|
+
node: f"{species_prefix}{i}" for i, node in enumerate(species_nodes, start=1)
|
|
247
|
+
}
|
|
248
|
+
reaction_node_to_id = {
|
|
249
|
+
node: f"{reaction_prefix}{i}" for i, node in enumerate(reaction_nodes, start=1)
|
|
250
|
+
}
|
|
251
|
+
return species_node_to_id, reaction_node_to_id
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _build_species_table_from_graph(
|
|
255
|
+
crn: nx.DiGraph,
|
|
256
|
+
*,
|
|
257
|
+
species_nodes: List[Hashable],
|
|
258
|
+
species_node_to_id: Dict[Hashable, str],
|
|
259
|
+
) -> Dict[str, Species]:
|
|
260
|
+
"""Build the canonical species table from graph species nodes.
|
|
261
|
+
|
|
262
|
+
:param crn:
|
|
263
|
+
Source CRN graph.
|
|
264
|
+
:type crn: nx.DiGraph
|
|
265
|
+
|
|
266
|
+
:param species_nodes:
|
|
267
|
+
Ordered species nodes.
|
|
268
|
+
:type species_nodes: List[Hashable]
|
|
269
|
+
|
|
270
|
+
:param species_node_to_id:
|
|
271
|
+
Mapping from source node id to internal species id.
|
|
272
|
+
:type species_node_to_id: Dict[Hashable, str]
|
|
273
|
+
|
|
274
|
+
:return:
|
|
275
|
+
Species table keyed by internal species id.
|
|
276
|
+
:rtype: Dict[str, Species]
|
|
277
|
+
"""
|
|
278
|
+
species: Dict[str, Species] = {}
|
|
279
|
+
for node in species_nodes:
|
|
280
|
+
attrs = dict(crn.nodes[node])
|
|
281
|
+
sid = species_node_to_id[node]
|
|
282
|
+
species[sid] = Species(
|
|
283
|
+
id=sid,
|
|
284
|
+
source_node_id=attrs.get("source_node_id", node),
|
|
285
|
+
label=str(attrs.get("label", sid)),
|
|
286
|
+
smiles=attrs.get("smiles"),
|
|
287
|
+
source_attrs=dict(attrs),
|
|
288
|
+
metadata={},
|
|
289
|
+
)
|
|
290
|
+
return species
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _collect_reaction_sides_from_graph(
|
|
294
|
+
crn: nx.DiGraph,
|
|
295
|
+
*,
|
|
296
|
+
rnode: Hashable,
|
|
297
|
+
species_node_to_id: Dict[Hashable, str],
|
|
298
|
+
strict: bool,
|
|
299
|
+
) -> Tuple[RXNSide, RXNSide, Dict[str, Dict[str, Any]], Dict[str, Dict[str, Any]]]:
|
|
300
|
+
"""Collect reactant and product sides for one reaction node.
|
|
301
|
+
|
|
302
|
+
:param crn:
|
|
303
|
+
Source CRN graph.
|
|
304
|
+
:type crn: nx.DiGraph
|
|
305
|
+
|
|
306
|
+
:param rnode:
|
|
307
|
+
Reaction node in the source graph.
|
|
308
|
+
:type rnode: Hashable
|
|
309
|
+
|
|
310
|
+
:param species_node_to_id:
|
|
311
|
+
Mapping from source species node id to canonical species id.
|
|
312
|
+
:type species_node_to_id: Dict[Hashable, str]
|
|
313
|
+
|
|
314
|
+
:param strict:
|
|
315
|
+
Whether malformed structure should raise an error.
|
|
316
|
+
:type strict: bool
|
|
317
|
+
|
|
318
|
+
:return:
|
|
319
|
+
Tuple ``(lhs, rhs, reactant_edge_attrs, product_edge_attrs)``.
|
|
320
|
+
:rtype: Tuple[RXNSide, RXNSide, Dict[str, Dict[str, Any]], Dict[str, Dict[str, Any]]]
|
|
321
|
+
"""
|
|
322
|
+
lhs_counter: Counter[str] = Counter()
|
|
323
|
+
rhs_counter: Counter[str] = Counter()
|
|
324
|
+
reactant_edge_attrs: Dict[str, Dict[str, Any]] = {}
|
|
325
|
+
product_edge_attrs: Dict[str, Dict[str, Any]] = {}
|
|
326
|
+
|
|
327
|
+
for u, _, eattrs in crn.in_edges(rnode, data=True):
|
|
328
|
+
if u not in species_node_to_id:
|
|
329
|
+
if strict:
|
|
330
|
+
raise ValueError(
|
|
331
|
+
f"Incoming edge into reaction node {rnode!r} must come from "
|
|
332
|
+
f"a species node, got {u!r}"
|
|
333
|
+
)
|
|
334
|
+
continue
|
|
335
|
+
|
|
336
|
+
sid = species_node_to_id[u]
|
|
337
|
+
attrs = dict(eattrs)
|
|
338
|
+
raw_stoich = attrs.get("stoich", 1)
|
|
339
|
+
if not float(raw_stoich).is_integer():
|
|
340
|
+
raise ValueError(
|
|
341
|
+
"Discrete CRN coefficients must be integral; normalize rational stoichiometry explicitly"
|
|
342
|
+
)
|
|
343
|
+
stoich = int(raw_stoich)
|
|
344
|
+
if stoich <= 0:
|
|
345
|
+
raise ValueError(f"Invalid stoich={stoich} on edge ({u!r}, {rnode!r})")
|
|
346
|
+
|
|
347
|
+
side = _edge_side(True, attrs.get("role"))
|
|
348
|
+
if side == "lhs":
|
|
349
|
+
lhs_counter[sid] += stoich
|
|
350
|
+
reactant_edge_attrs[sid] = attrs
|
|
351
|
+
else:
|
|
352
|
+
rhs_counter[sid] += stoich
|
|
353
|
+
product_edge_attrs[sid] = attrs
|
|
354
|
+
|
|
355
|
+
for _, v, eattrs in crn.out_edges(rnode, data=True):
|
|
356
|
+
if v not in species_node_to_id:
|
|
357
|
+
if strict:
|
|
358
|
+
raise ValueError(
|
|
359
|
+
f"Outgoing edge from reaction node {rnode!r} must go to "
|
|
360
|
+
f"a species node, got {v!r}"
|
|
361
|
+
)
|
|
362
|
+
continue
|
|
363
|
+
|
|
364
|
+
sid = species_node_to_id[v]
|
|
365
|
+
attrs = dict(eattrs)
|
|
366
|
+
raw_stoich = attrs.get("stoich", 1)
|
|
367
|
+
if not float(raw_stoich).is_integer():
|
|
368
|
+
raise ValueError(
|
|
369
|
+
"Discrete CRN coefficients must be integral; normalize rational stoichiometry explicitly"
|
|
370
|
+
)
|
|
371
|
+
stoich = int(raw_stoich)
|
|
372
|
+
if stoich <= 0:
|
|
373
|
+
raise ValueError(f"Invalid stoich={stoich} on edge ({rnode!r}, {v!r})")
|
|
374
|
+
|
|
375
|
+
side = _edge_side(False, attrs.get("role"))
|
|
376
|
+
if side == "lhs":
|
|
377
|
+
lhs_counter[sid] += stoich
|
|
378
|
+
reactant_edge_attrs[sid] = attrs
|
|
379
|
+
else:
|
|
380
|
+
rhs_counter[sid] += stoich
|
|
381
|
+
product_edge_attrs[sid] = attrs
|
|
382
|
+
|
|
383
|
+
lhs = RXNSide(dict(lhs_counter))
|
|
384
|
+
rhs = RXNSide(dict(rhs_counter))
|
|
385
|
+
return lhs, rhs, reactant_edge_attrs, product_edge_attrs
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def _validate_nonempty_reaction_sides(
|
|
389
|
+
*,
|
|
390
|
+
rnode: Hashable,
|
|
391
|
+
lhs: RXNSide,
|
|
392
|
+
rhs: RXNSide,
|
|
393
|
+
strict: bool,
|
|
394
|
+
) -> None:
|
|
395
|
+
"""Validate that a reaction has non-empty lhs and rhs sides when strict mode is enabled.
|
|
396
|
+
|
|
397
|
+
:param rnode:
|
|
398
|
+
Source reaction node id.
|
|
399
|
+
:type rnode: Hashable
|
|
400
|
+
|
|
401
|
+
:param lhs:
|
|
402
|
+
Reactant side.
|
|
403
|
+
:type lhs: RXNSide
|
|
404
|
+
|
|
405
|
+
:param rhs:
|
|
406
|
+
Product side.
|
|
407
|
+
:type rhs: RXNSide
|
|
408
|
+
|
|
409
|
+
:param strict:
|
|
410
|
+
Whether empty sides should raise an error.
|
|
411
|
+
:type strict: bool
|
|
412
|
+
|
|
413
|
+
:return:
|
|
414
|
+
None.
|
|
415
|
+
:rtype: None
|
|
416
|
+
"""
|
|
417
|
+
if strict and not lhs:
|
|
418
|
+
raise ValueError(f"Reaction node {rnode!r} has empty reactant side")
|
|
419
|
+
if strict and not rhs:
|
|
420
|
+
raise ValueError(f"Reaction node {rnode!r} has empty product side")
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def _get_or_create_rule_from_attrs(
|
|
424
|
+
*,
|
|
425
|
+
rattrs: Dict[str, Any],
|
|
426
|
+
rules: Dict[str, Rule],
|
|
427
|
+
rule_key_to_id: Dict[Tuple[Optional[int], Optional[str]], str],
|
|
428
|
+
rule_prefix: str,
|
|
429
|
+
) -> Optional[str]:
|
|
430
|
+
"""Get or create a canonical rule entry from reaction-node attributes.
|
|
431
|
+
|
|
432
|
+
:param rattrs:
|
|
433
|
+
Reaction-node attribute dictionary.
|
|
434
|
+
:type rattrs: Dict[str, Any]
|
|
435
|
+
|
|
436
|
+
:param rules:
|
|
437
|
+
Mutable rule table.
|
|
438
|
+
:type rules: Dict[str, Rule]
|
|
439
|
+
|
|
440
|
+
:param rule_key_to_id:
|
|
441
|
+
Mapping from abstract rule key to canonical rule id.
|
|
442
|
+
:type rule_key_to_id: Dict[Tuple[Optional[int], Optional[str]], str]
|
|
443
|
+
|
|
444
|
+
:param rule_prefix:
|
|
445
|
+
Prefix used when creating new rule ids.
|
|
446
|
+
:type rule_prefix: str
|
|
447
|
+
|
|
448
|
+
:return:
|
|
449
|
+
Canonical rule id if a rule is defined, else ``None``.
|
|
450
|
+
:rtype: Optional[str]
|
|
451
|
+
"""
|
|
452
|
+
rule_key = (rattrs.get("rule_index"), rattrs.get("rule_repr"))
|
|
453
|
+
if rule_key == (None, None):
|
|
454
|
+
return None
|
|
455
|
+
|
|
456
|
+
if rule_key not in rule_key_to_id:
|
|
457
|
+
rule_id = f"{rule_prefix}{len(rule_key_to_id) + 1}"
|
|
458
|
+
rule_key_to_id[rule_key] = rule_id
|
|
459
|
+
rules[rule_id] = Rule(
|
|
460
|
+
id=rule_id,
|
|
461
|
+
rule_index=rattrs.get("rule_index"),
|
|
462
|
+
rule_repr=rattrs.get("rule_repr"),
|
|
463
|
+
label=(
|
|
464
|
+
f"rule[{rattrs.get('rule_index')}]"
|
|
465
|
+
if rattrs.get("rule_index") is not None
|
|
466
|
+
else None
|
|
467
|
+
),
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
return rule_key_to_id[rule_key]
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def _build_reaction_from_graph_node(
|
|
474
|
+
crn: nx.DiGraph,
|
|
475
|
+
*,
|
|
476
|
+
rnode: Hashable,
|
|
477
|
+
rid: str,
|
|
478
|
+
species_node_to_id: Dict[Hashable, str],
|
|
479
|
+
rules: Dict[str, Rule],
|
|
480
|
+
rule_key_to_id: Dict[Tuple[Optional[int], Optional[str]], str],
|
|
481
|
+
rule_prefix: str,
|
|
482
|
+
strict: bool,
|
|
483
|
+
) -> Reaction:
|
|
484
|
+
"""Build one canonical Reaction object from a graph reaction node.
|
|
485
|
+
|
|
486
|
+
:param crn:
|
|
487
|
+
Source CRN graph.
|
|
488
|
+
:type crn: nx.DiGraph
|
|
489
|
+
|
|
490
|
+
:param rnode:
|
|
491
|
+
Reaction node id in the source graph.
|
|
492
|
+
:type rnode: Hashable
|
|
493
|
+
|
|
494
|
+
:param rid:
|
|
495
|
+
Canonical reaction id.
|
|
496
|
+
:type rid: str
|
|
497
|
+
|
|
498
|
+
:param species_node_to_id:
|
|
499
|
+
Mapping from source species node ids to canonical species ids.
|
|
500
|
+
:type species_node_to_id: Dict[Hashable, str]
|
|
501
|
+
|
|
502
|
+
:param rules:
|
|
503
|
+
Mutable rule table.
|
|
504
|
+
:type rules: Dict[str, Rule]
|
|
505
|
+
|
|
506
|
+
:param rule_key_to_id:
|
|
507
|
+
Mapping from abstract rule key to canonical rule id.
|
|
508
|
+
:type rule_key_to_id: Dict[Tuple[Optional[int], Optional[str]], str]
|
|
509
|
+
|
|
510
|
+
:param rule_prefix:
|
|
511
|
+
Prefix for rule ids.
|
|
512
|
+
:type rule_prefix: str
|
|
513
|
+
|
|
514
|
+
:param strict:
|
|
515
|
+
Whether malformed structure should raise an error.
|
|
516
|
+
:type strict: bool
|
|
517
|
+
|
|
518
|
+
:return:
|
|
519
|
+
Canonical reaction object.
|
|
520
|
+
:rtype: Reaction
|
|
521
|
+
"""
|
|
522
|
+
rattrs = dict(crn.nodes[rnode])
|
|
523
|
+
|
|
524
|
+
lhs, rhs, reactant_edge_attrs, product_edge_attrs = (
|
|
525
|
+
_collect_reaction_sides_from_graph(
|
|
526
|
+
crn,
|
|
527
|
+
rnode=rnode,
|
|
528
|
+
species_node_to_id=species_node_to_id,
|
|
529
|
+
strict=strict,
|
|
530
|
+
)
|
|
531
|
+
)
|
|
532
|
+
_validate_nonempty_reaction_sides(rnode=rnode, lhs=lhs, rhs=rhs, strict=strict)
|
|
533
|
+
|
|
534
|
+
rule_id = _get_or_create_rule_from_attrs(
|
|
535
|
+
rattrs=rattrs,
|
|
536
|
+
rules=rules,
|
|
537
|
+
rule_key_to_id=rule_key_to_id,
|
|
538
|
+
rule_prefix=rule_prefix,
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
return Reaction(
|
|
542
|
+
id=rid,
|
|
543
|
+
source_node_id=rattrs.get("source_node_id", rnode),
|
|
544
|
+
source_kind=str(rattrs.get("source_kind", rattrs.get("kind", "reaction"))),
|
|
545
|
+
lhs=lhs,
|
|
546
|
+
rhs=rhs,
|
|
547
|
+
label=rattrs.get("label", rid),
|
|
548
|
+
step=rattrs.get("step"),
|
|
549
|
+
rule_index=rattrs.get("rule_index"),
|
|
550
|
+
app_index=rattrs.get("app_index"),
|
|
551
|
+
rule_repr=rattrs.get("rule_repr"),
|
|
552
|
+
rule_id=rule_id,
|
|
553
|
+
source_attrs=dict(rattrs),
|
|
554
|
+
metadata={},
|
|
555
|
+
reactant_edge_attrs=reactant_edge_attrs,
|
|
556
|
+
product_edge_attrs=product_edge_attrs,
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
def _resolve_species_node_id(sp: Species, *, node_ids: str) -> Hashable:
|
|
561
|
+
"""Resolve the node id for one species during graph reconstruction.
|
|
562
|
+
|
|
563
|
+
:param sp:
|
|
564
|
+
Species record.
|
|
565
|
+
:type sp: Species
|
|
566
|
+
|
|
567
|
+
:param node_ids:
|
|
568
|
+
Either ``"source"`` or ``"internal"``.
|
|
569
|
+
:type node_ids: str
|
|
570
|
+
|
|
571
|
+
:return:
|
|
572
|
+
Reconstructed graph node id.
|
|
573
|
+
:rtype: Hashable
|
|
574
|
+
"""
|
|
575
|
+
return sp.source_node_id if node_ids == "source" else sp.id
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
def _resolve_reaction_node_id(rxn: Reaction, *, node_ids: str) -> Hashable:
|
|
579
|
+
"""Resolve the node id for one reaction during graph reconstruction.
|
|
580
|
+
|
|
581
|
+
:param rxn:
|
|
582
|
+
Reaction record.
|
|
583
|
+
:type rxn: Reaction
|
|
584
|
+
|
|
585
|
+
:param node_ids:
|
|
586
|
+
Either ``"source"`` or ``"internal"``.
|
|
587
|
+
:type node_ids: str
|
|
588
|
+
|
|
589
|
+
:return:
|
|
590
|
+
Reconstructed graph node id.
|
|
591
|
+
:rtype: Hashable
|
|
592
|
+
"""
|
|
593
|
+
return rxn.source_node_id if node_ids == "source" else rxn.id
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
def _species_node_attrs(
|
|
597
|
+
sp: Species,
|
|
598
|
+
*,
|
|
599
|
+
include_internal_ids: bool,
|
|
600
|
+
) -> Dict[str, Any]:
|
|
601
|
+
"""Build species-node attributes for graph reconstruction.
|
|
602
|
+
|
|
603
|
+
:param sp:
|
|
604
|
+
Species record.
|
|
605
|
+
:type sp: Species
|
|
606
|
+
|
|
607
|
+
:param include_internal_ids:
|
|
608
|
+
Whether canonical ids should be attached as attributes.
|
|
609
|
+
:type include_internal_ids: bool
|
|
610
|
+
|
|
611
|
+
:return:
|
|
612
|
+
Node-attribute dictionary.
|
|
613
|
+
:rtype: Dict[str, Any]
|
|
614
|
+
"""
|
|
615
|
+
attrs = dict(sp.source_attrs)
|
|
616
|
+
attrs["kind"] = "species"
|
|
617
|
+
attrs["label"] = sp.label
|
|
618
|
+
attrs["smiles"] = sp.smiles
|
|
619
|
+
if include_internal_ids:
|
|
620
|
+
attrs["syncrn_id"] = sp.id
|
|
621
|
+
attrs["source_node_id"] = sp.source_node_id
|
|
622
|
+
return attrs
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
def _reaction_node_attrs(
|
|
626
|
+
rxn: Reaction,
|
|
627
|
+
*,
|
|
628
|
+
reaction_kind: Optional[str],
|
|
629
|
+
include_internal_ids: bool,
|
|
630
|
+
) -> Dict[str, Any]:
|
|
631
|
+
"""Build reaction-node attributes for graph reconstruction.
|
|
632
|
+
|
|
633
|
+
:param rxn:
|
|
634
|
+
Reaction record.
|
|
635
|
+
:type rxn: Reaction
|
|
636
|
+
|
|
637
|
+
:param reaction_kind:
|
|
638
|
+
Optional override for reconstructed reaction kind.
|
|
639
|
+
:type reaction_kind: Optional[str]
|
|
640
|
+
|
|
641
|
+
:param include_internal_ids:
|
|
642
|
+
Whether canonical ids should be attached as attributes.
|
|
643
|
+
:type include_internal_ids: bool
|
|
644
|
+
|
|
645
|
+
:return:
|
|
646
|
+
Node-attribute dictionary.
|
|
647
|
+
:rtype: Dict[str, Any]
|
|
648
|
+
"""
|
|
649
|
+
attrs = dict(rxn.source_attrs)
|
|
650
|
+
attrs["kind"] = reaction_kind or rxn.source_kind
|
|
651
|
+
attrs["label"] = rxn.label
|
|
652
|
+
attrs["step"] = rxn.step
|
|
653
|
+
attrs["rule_index"] = rxn.rule_index
|
|
654
|
+
attrs["app_index"] = rxn.app_index
|
|
655
|
+
attrs["rule_repr"] = rxn.rule_repr
|
|
656
|
+
if rxn.rule_id is not None:
|
|
657
|
+
attrs.setdefault("rule_id", rxn.rule_id)
|
|
658
|
+
if include_internal_ids:
|
|
659
|
+
attrs["syncrn_id"] = rxn.id
|
|
660
|
+
attrs["source_node_id"] = rxn.source_node_id
|
|
661
|
+
return attrs
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
def _add_reaction_edges_to_graph(
|
|
665
|
+
g: nx.DiGraph,
|
|
666
|
+
*,
|
|
667
|
+
rxn: Reaction,
|
|
668
|
+
reaction_node: Hashable,
|
|
669
|
+
species_node_map: Dict[str, Hashable],
|
|
670
|
+
) -> None:
|
|
671
|
+
"""Add reactant and product incidence edges for one reaction.
|
|
672
|
+
|
|
673
|
+
:param g:
|
|
674
|
+
Graph under construction.
|
|
675
|
+
:type g: nx.DiGraph
|
|
676
|
+
|
|
677
|
+
:param rxn:
|
|
678
|
+
Reaction record.
|
|
679
|
+
:type rxn: Reaction
|
|
680
|
+
|
|
681
|
+
:param reaction_node:
|
|
682
|
+
Graph node id of the reconstructed reaction node.
|
|
683
|
+
:type reaction_node: Hashable
|
|
684
|
+
|
|
685
|
+
:param species_node_map:
|
|
686
|
+
Mapping from canonical species ids to graph node ids.
|
|
687
|
+
:type species_node_map: Dict[str, Hashable]
|
|
688
|
+
|
|
689
|
+
:return:
|
|
690
|
+
None.
|
|
691
|
+
:rtype: None
|
|
692
|
+
"""
|
|
693
|
+
for sid, coeff in rxn.lhs.items():
|
|
694
|
+
snode = species_node_map[sid]
|
|
695
|
+
attrs = dict(rxn.reactant_edge_attrs.get(sid, {}))
|
|
696
|
+
attrs["role"] = "reactant"
|
|
697
|
+
attrs["stoich"] = coeff
|
|
698
|
+
if rxn.step is not None:
|
|
699
|
+
attrs.setdefault("step", rxn.step)
|
|
700
|
+
if rxn.rule_index is not None:
|
|
701
|
+
attrs.setdefault("rule_index", rxn.rule_index)
|
|
702
|
+
g.add_edge(snode, reaction_node, **attrs)
|
|
703
|
+
|
|
704
|
+
for sid, coeff in rxn.rhs.items():
|
|
705
|
+
snode = species_node_map[sid]
|
|
706
|
+
attrs = dict(rxn.product_edge_attrs.get(sid, {}))
|
|
707
|
+
attrs["role"] = "product"
|
|
708
|
+
attrs["stoich"] = coeff
|
|
709
|
+
if rxn.step is not None:
|
|
710
|
+
attrs.setdefault("step", rxn.step)
|
|
711
|
+
if rxn.rule_index is not None:
|
|
712
|
+
attrs.setdefault("rule_index", rxn.rule_index)
|
|
713
|
+
g.add_edge(reaction_node, snode, **attrs)
|