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,929 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any, Callable, Dict, Hashable, List, Optional, Tuple
|
|
5
|
+
|
|
6
|
+
import networkx as nx
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from .reaction import Reaction
|
|
10
|
+
from .rule import Rule
|
|
11
|
+
from .species import Species
|
|
12
|
+
from ._graph_io import (
|
|
13
|
+
_add_reaction_edges_to_graph,
|
|
14
|
+
_build_reaction_from_graph_node,
|
|
15
|
+
_build_species_table_from_graph,
|
|
16
|
+
_collect_bipartite_nodes,
|
|
17
|
+
_make_internal_id_maps,
|
|
18
|
+
_reaction_node_attrs,
|
|
19
|
+
_resolve_reaction_node_id,
|
|
20
|
+
_resolve_species_node_id,
|
|
21
|
+
_species_node_attrs,
|
|
22
|
+
_validate_bipartite_node_sets,
|
|
23
|
+
)
|
|
24
|
+
from ._matrices import _dense_from_entries, _sparse_from_entries
|
|
25
|
+
from ._parse import (
|
|
26
|
+
ID_STYLES,
|
|
27
|
+
_build_reactions_from_parsed_strings,
|
|
28
|
+
_build_rules_table_from_reaction_strings,
|
|
29
|
+
_build_species_table_from_labels,
|
|
30
|
+
_default_parse_side_text,
|
|
31
|
+
_mint_reaction_string_ids,
|
|
32
|
+
_parse_reaction_string_entry,
|
|
33
|
+
_species_order_from_parsed_reactions,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
__all__ = ["ID_STYLES", "SynCRN"]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class SynCRN:
|
|
41
|
+
"""Canonical reaction-system object for SynKit-CRN.
|
|
42
|
+
|
|
43
|
+
Official representations exposed by this object
|
|
44
|
+
------------------------------------------------
|
|
45
|
+
- ``SynCRN``: master reaction-system object
|
|
46
|
+
- ``SynCRN.to_digraph()``: species--reaction bipartite graph view
|
|
47
|
+
- ``SynCRN.to_stoichiometric_matrices()``: matrix view for stoichiometric analysis
|
|
48
|
+
- ``SynCRN.to_petrinet()``: pre/post incidence view for pathways
|
|
49
|
+
- ``SynCRN.to_equations()``: human-readable reaction list
|
|
50
|
+
|
|
51
|
+
Design notes
|
|
52
|
+
------------
|
|
53
|
+
Input digraph nodes with ``kind="rule"`` are preserved exactly on round-trip
|
|
54
|
+
via ``Reaction.source_kind`` and ``Reaction.source_attrs``. They are also
|
|
55
|
+
normalized as concrete reaction instances for downstream computation.
|
|
56
|
+
|
|
57
|
+
:param species:
|
|
58
|
+
Mapping from internal species ids to Species records.
|
|
59
|
+
:type species: Dict[str, Species]
|
|
60
|
+
|
|
61
|
+
:param reactions:
|
|
62
|
+
Mapping from internal reaction ids to Reaction records.
|
|
63
|
+
:type reactions: Dict[str, Reaction]
|
|
64
|
+
|
|
65
|
+
:param rules:
|
|
66
|
+
Mapping from internal rule ids to Rule records.
|
|
67
|
+
:type rules: Dict[str, Rule]
|
|
68
|
+
|
|
69
|
+
:param graph_attrs:
|
|
70
|
+
Original graph-level attributes from the input digraph.
|
|
71
|
+
:type graph_attrs: Dict[str, Any]
|
|
72
|
+
|
|
73
|
+
:param metadata:
|
|
74
|
+
Additional canonical metadata for the SynCRN object.
|
|
75
|
+
:type metadata: Dict[str, Any]
|
|
76
|
+
|
|
77
|
+
.. rubric:: Example
|
|
78
|
+
|
|
79
|
+
.. code-block:: python
|
|
80
|
+
|
|
81
|
+
syn = SynCRN.from_reaction_strings(["A>>B", "B>>C"])
|
|
82
|
+
print(syn.n_species)
|
|
83
|
+
print(syn.to_equations())
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
species: Dict[str, Species] = field(default_factory=dict)
|
|
87
|
+
reactions: Dict[str, Reaction] = field(default_factory=dict)
|
|
88
|
+
rules: Dict[str, Rule] = field(default_factory=dict)
|
|
89
|
+
graph_attrs: Dict[str, Any] = field(default_factory=dict)
|
|
90
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def from_digraph(
|
|
94
|
+
cls,
|
|
95
|
+
crn: nx.DiGraph,
|
|
96
|
+
*,
|
|
97
|
+
species_kind: str = "species",
|
|
98
|
+
reaction_kinds: Tuple[str, ...] = ("reaction", "rule"),
|
|
99
|
+
species_prefix: str = "s_",
|
|
100
|
+
reaction_prefix: str = "r_",
|
|
101
|
+
rule_prefix: str = "rule_",
|
|
102
|
+
strict: bool = True,
|
|
103
|
+
id_style: str = "prefixed",
|
|
104
|
+
) -> "SynCRN":
|
|
105
|
+
"""Build a canonical SynCRN object from a species--reaction bipartite digraph.
|
|
106
|
+
|
|
107
|
+
The current SynKit-CRN graph frequently stores concrete reaction-instance
|
|
108
|
+
nodes with ``kind="rule"``. This constructor preserves that original kind
|
|
109
|
+
in ``Reaction.source_kind`` while also converting such nodes into concrete
|
|
110
|
+
reaction instances for downstream computation.
|
|
111
|
+
|
|
112
|
+
Internal ids follow the same policy as
|
|
113
|
+
:meth:`from_reaction_strings`: ``id_style="prefixed"`` mints ``s_1`` /
|
|
114
|
+
``r_1`` / ``rule_1``, while ``id_style="numeric"`` mints ``1..n`` for
|
|
115
|
+
species and ``n+1..n+m`` for reactions.
|
|
116
|
+
|
|
117
|
+
:param crn:
|
|
118
|
+
Directed bipartite graph with species and reaction-like nodes.
|
|
119
|
+
:type crn: nx.DiGraph
|
|
120
|
+
|
|
121
|
+
:param species_kind:
|
|
122
|
+
Node-kind value used for species nodes.
|
|
123
|
+
:type species_kind: str
|
|
124
|
+
|
|
125
|
+
:param reaction_kinds:
|
|
126
|
+
Node-kind values used for reaction-instance nodes.
|
|
127
|
+
:type reaction_kinds: Tuple[str, ...]
|
|
128
|
+
|
|
129
|
+
:param species_prefix:
|
|
130
|
+
Prefix for generated internal species ids.
|
|
131
|
+
:type species_prefix: str
|
|
132
|
+
|
|
133
|
+
:param reaction_prefix:
|
|
134
|
+
Prefix for generated internal reaction ids.
|
|
135
|
+
:type reaction_prefix: str
|
|
136
|
+
|
|
137
|
+
:param rule_prefix:
|
|
138
|
+
Prefix for generated internal rule ids.
|
|
139
|
+
:type rule_prefix: str
|
|
140
|
+
|
|
141
|
+
:param strict:
|
|
142
|
+
Whether malformed graph structure should raise an error.
|
|
143
|
+
:type strict: bool
|
|
144
|
+
|
|
145
|
+
:param id_style:
|
|
146
|
+
Internal-id policy, either ``"prefixed"`` (default) or ``"numeric"``.
|
|
147
|
+
:type id_style: str
|
|
148
|
+
|
|
149
|
+
:return:
|
|
150
|
+
Canonical SynCRN object.
|
|
151
|
+
:rtype: SynCRN
|
|
152
|
+
|
|
153
|
+
:raises TypeError:
|
|
154
|
+
If ``crn`` is not an ``nx.DiGraph``.
|
|
155
|
+
|
|
156
|
+
:raises ValueError:
|
|
157
|
+
If ``id_style`` is not a recognised policy.
|
|
158
|
+
|
|
159
|
+
.. rubric:: Example
|
|
160
|
+
|
|
161
|
+
.. code-block:: python
|
|
162
|
+
|
|
163
|
+
syn = SynCRN.from_digraph(crn)
|
|
164
|
+
print(syn.to_equations())
|
|
165
|
+
"""
|
|
166
|
+
if not isinstance(crn, nx.DiGraph):
|
|
167
|
+
raise TypeError(f"crn must be nx.DiGraph, got {type(crn).__name__}")
|
|
168
|
+
|
|
169
|
+
species_nodes, reaction_nodes = _collect_bipartite_nodes(
|
|
170
|
+
crn,
|
|
171
|
+
species_kind=species_kind,
|
|
172
|
+
reaction_kinds=reaction_kinds,
|
|
173
|
+
)
|
|
174
|
+
_validate_bipartite_node_sets(
|
|
175
|
+
species_nodes=species_nodes,
|
|
176
|
+
reaction_nodes=reaction_nodes,
|
|
177
|
+
strict=strict,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
species_node_to_id, reaction_node_to_id = _make_internal_id_maps(
|
|
181
|
+
species_nodes=species_nodes,
|
|
182
|
+
reaction_nodes=reaction_nodes,
|
|
183
|
+
species_prefix=species_prefix,
|
|
184
|
+
reaction_prefix=reaction_prefix,
|
|
185
|
+
id_style=id_style,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
species = _build_species_table_from_graph(
|
|
189
|
+
crn,
|
|
190
|
+
species_nodes=species_nodes,
|
|
191
|
+
species_node_to_id=species_node_to_id,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
rules: Dict[str, Rule] = {}
|
|
195
|
+
rule_key_to_id: Dict[Tuple[Optional[int], Optional[str]], str] = {}
|
|
196
|
+
reactions: Dict[str, Reaction] = {}
|
|
197
|
+
|
|
198
|
+
for rnode in reaction_nodes:
|
|
199
|
+
rid = reaction_node_to_id[rnode]
|
|
200
|
+
reactions[rid] = _build_reaction_from_graph_node(
|
|
201
|
+
crn,
|
|
202
|
+
rnode=rnode,
|
|
203
|
+
rid=rid,
|
|
204
|
+
species_node_to_id=species_node_to_id,
|
|
205
|
+
rules=rules,
|
|
206
|
+
rule_key_to_id=rule_key_to_id,
|
|
207
|
+
rule_prefix=rule_prefix,
|
|
208
|
+
strict=strict,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
return cls(
|
|
212
|
+
species=species,
|
|
213
|
+
reactions=reactions,
|
|
214
|
+
rules=rules,
|
|
215
|
+
graph_attrs=dict(crn.graph),
|
|
216
|
+
metadata={
|
|
217
|
+
"source_graph_type": type(crn).__name__,
|
|
218
|
+
"id_style": id_style,
|
|
219
|
+
},
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def species_ids(self) -> List[str]:
|
|
224
|
+
"""Return the internal species order.
|
|
225
|
+
|
|
226
|
+
:return:
|
|
227
|
+
Ordered list of species ids.
|
|
228
|
+
:rtype: List[str]
|
|
229
|
+
|
|
230
|
+
.. rubric:: Example
|
|
231
|
+
|
|
232
|
+
.. code-block:: python
|
|
233
|
+
|
|
234
|
+
print(syn.species_ids)
|
|
235
|
+
"""
|
|
236
|
+
return list(self.species.keys())
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def reaction_ids(self) -> List[str]:
|
|
240
|
+
"""Return the internal reaction order.
|
|
241
|
+
|
|
242
|
+
:return:
|
|
243
|
+
Ordered list of reaction ids.
|
|
244
|
+
:rtype: List[str]
|
|
245
|
+
|
|
246
|
+
.. rubric:: Example
|
|
247
|
+
|
|
248
|
+
.. code-block:: python
|
|
249
|
+
|
|
250
|
+
print(syn.reaction_ids)
|
|
251
|
+
"""
|
|
252
|
+
return list(self.reactions.keys())
|
|
253
|
+
|
|
254
|
+
@property
|
|
255
|
+
def rule_ids(self) -> List[str]:
|
|
256
|
+
"""Return the internal rule order.
|
|
257
|
+
|
|
258
|
+
:return:
|
|
259
|
+
Ordered list of rule ids.
|
|
260
|
+
:rtype: List[str]
|
|
261
|
+
|
|
262
|
+
.. rubric:: Example
|
|
263
|
+
|
|
264
|
+
.. code-block:: python
|
|
265
|
+
|
|
266
|
+
print(syn.rule_ids)
|
|
267
|
+
"""
|
|
268
|
+
return list(self.rules.keys())
|
|
269
|
+
|
|
270
|
+
@property
|
|
271
|
+
def n_species(self) -> int:
|
|
272
|
+
"""Return the number of species.
|
|
273
|
+
|
|
274
|
+
:return:
|
|
275
|
+
Number of species.
|
|
276
|
+
:rtype: int
|
|
277
|
+
"""
|
|
278
|
+
return len(self.species)
|
|
279
|
+
|
|
280
|
+
@property
|
|
281
|
+
def n_reactions(self) -> int:
|
|
282
|
+
"""Return the number of reactions.
|
|
283
|
+
|
|
284
|
+
:return:
|
|
285
|
+
Number of reactions.
|
|
286
|
+
:rtype: int
|
|
287
|
+
"""
|
|
288
|
+
return len(self.reactions)
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def n_rules(self) -> int:
|
|
292
|
+
"""Return the number of unique abstract rules.
|
|
293
|
+
|
|
294
|
+
:return:
|
|
295
|
+
Number of rules.
|
|
296
|
+
:rtype: int
|
|
297
|
+
"""
|
|
298
|
+
return len(self.rules)
|
|
299
|
+
|
|
300
|
+
def __repr__(self) -> str:
|
|
301
|
+
"""Return a compact developer-facing representation.
|
|
302
|
+
|
|
303
|
+
:return:
|
|
304
|
+
Summary representation string.
|
|
305
|
+
:rtype: str
|
|
306
|
+
"""
|
|
307
|
+
return (
|
|
308
|
+
f"SynCRN(n_species={self.n_species}, "
|
|
309
|
+
f"n_reactions={self.n_reactions}, n_rules={self.n_rules})"
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
def __str__(self) -> str:
|
|
313
|
+
"""Return a human-readable text summary.
|
|
314
|
+
|
|
315
|
+
:return:
|
|
316
|
+
Multiline description string.
|
|
317
|
+
:rtype: str
|
|
318
|
+
"""
|
|
319
|
+
return self.describe(include_species=True, species="label")
|
|
320
|
+
|
|
321
|
+
def _species_token(self, species_id: str, mode: str = "label") -> str:
|
|
322
|
+
"""Resolve how a species should be displayed.
|
|
323
|
+
|
|
324
|
+
Supported modes are ``"id"``, ``"label"``, ``"smiles"``, and ``"source"``.
|
|
325
|
+
|
|
326
|
+
:param species_id:
|
|
327
|
+
Internal species id.
|
|
328
|
+
:type species_id: str
|
|
329
|
+
|
|
330
|
+
:param mode:
|
|
331
|
+
Species display mode.
|
|
332
|
+
:type mode: str
|
|
333
|
+
|
|
334
|
+
:return:
|
|
335
|
+
Display token for the species.
|
|
336
|
+
:rtype: str
|
|
337
|
+
|
|
338
|
+
:raises ValueError:
|
|
339
|
+
If the display mode is unsupported.
|
|
340
|
+
|
|
341
|
+
.. rubric:: Example
|
|
342
|
+
|
|
343
|
+
.. code-block:: python
|
|
344
|
+
|
|
345
|
+
syn._species_token("1", mode="label")
|
|
346
|
+
"""
|
|
347
|
+
sp = self.species[species_id]
|
|
348
|
+
if mode == "id":
|
|
349
|
+
return sp.id
|
|
350
|
+
if mode == "label":
|
|
351
|
+
return sp.label
|
|
352
|
+
if mode == "smiles":
|
|
353
|
+
return sp.smiles or sp.label
|
|
354
|
+
if mode == "source":
|
|
355
|
+
return str(sp.source_node_id)
|
|
356
|
+
raise ValueError("species mode must be one of: id, label, smiles, source")
|
|
357
|
+
|
|
358
|
+
def format_reaction(
|
|
359
|
+
self,
|
|
360
|
+
reaction_id: str,
|
|
361
|
+
*,
|
|
362
|
+
species: str = "label",
|
|
363
|
+
include_id: bool = True,
|
|
364
|
+
include_rule: bool = False,
|
|
365
|
+
include_step: bool = False,
|
|
366
|
+
arrow: str = ">>",
|
|
367
|
+
) -> str:
|
|
368
|
+
"""Format one reaction as text.
|
|
369
|
+
|
|
370
|
+
:param reaction_id:
|
|
371
|
+
Internal reaction id.
|
|
372
|
+
:type reaction_id: str
|
|
373
|
+
|
|
374
|
+
:param species:
|
|
375
|
+
Species display mode.
|
|
376
|
+
:type species: str
|
|
377
|
+
|
|
378
|
+
:param include_id:
|
|
379
|
+
Whether to include the internal reaction id.
|
|
380
|
+
:type include_id: bool
|
|
381
|
+
|
|
382
|
+
:param include_rule:
|
|
383
|
+
Whether to include rule provenance.
|
|
384
|
+
:type include_rule: bool
|
|
385
|
+
|
|
386
|
+
:param include_step:
|
|
387
|
+
Whether to include step provenance.
|
|
388
|
+
:type include_step: bool
|
|
389
|
+
|
|
390
|
+
:param arrow:
|
|
391
|
+
Arrow string between lhs and rhs.
|
|
392
|
+
:type arrow: str
|
|
393
|
+
|
|
394
|
+
:return:
|
|
395
|
+
Human-readable reaction string.
|
|
396
|
+
:rtype: str
|
|
397
|
+
|
|
398
|
+
.. rubric:: Example
|
|
399
|
+
|
|
400
|
+
.. code-block:: python
|
|
401
|
+
|
|
402
|
+
syn.format_reaction("r_1", species="label", include_rule=True)
|
|
403
|
+
"""
|
|
404
|
+
rxn = self.reactions[reaction_id]
|
|
405
|
+
return rxn.format(
|
|
406
|
+
lambda sid: self._species_token(sid, species),
|
|
407
|
+
include_id=include_id,
|
|
408
|
+
include_rule=include_rule,
|
|
409
|
+
include_step=include_step,
|
|
410
|
+
arrow=arrow,
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
def to_equations(
|
|
414
|
+
self,
|
|
415
|
+
*,
|
|
416
|
+
species: str = "label",
|
|
417
|
+
include_id: bool = True,
|
|
418
|
+
include_rule: bool = False,
|
|
419
|
+
include_step: bool = False,
|
|
420
|
+
arrow: str = ">>",
|
|
421
|
+
) -> List[str]:
|
|
422
|
+
"""Return the network as a list of formatted reaction equations.
|
|
423
|
+
|
|
424
|
+
:param species:
|
|
425
|
+
Species display mode.
|
|
426
|
+
:type species: str
|
|
427
|
+
|
|
428
|
+
:param include_id:
|
|
429
|
+
Whether to include internal reaction ids.
|
|
430
|
+
:type include_id: bool
|
|
431
|
+
|
|
432
|
+
:param include_rule:
|
|
433
|
+
Whether to include rule provenance.
|
|
434
|
+
:type include_rule: bool
|
|
435
|
+
|
|
436
|
+
:param include_step:
|
|
437
|
+
Whether to include step provenance.
|
|
438
|
+
:type include_step: bool
|
|
439
|
+
|
|
440
|
+
:param arrow:
|
|
441
|
+
Arrow string between lhs and rhs.
|
|
442
|
+
:type arrow: str
|
|
443
|
+
|
|
444
|
+
:return:
|
|
445
|
+
List of formatted reaction equations.
|
|
446
|
+
:rtype: List[str]
|
|
447
|
+
|
|
448
|
+
.. rubric:: Example
|
|
449
|
+
|
|
450
|
+
.. code-block:: python
|
|
451
|
+
|
|
452
|
+
eqs = syn.to_equations(species="smiles", include_rule=True)
|
|
453
|
+
print("\\n".join(eqs))
|
|
454
|
+
"""
|
|
455
|
+
return [
|
|
456
|
+
self.format_reaction(
|
|
457
|
+
rid,
|
|
458
|
+
species=species,
|
|
459
|
+
include_id=include_id,
|
|
460
|
+
include_rule=include_rule,
|
|
461
|
+
include_step=include_step,
|
|
462
|
+
arrow=arrow,
|
|
463
|
+
)
|
|
464
|
+
for rid in self.reaction_ids
|
|
465
|
+
]
|
|
466
|
+
|
|
467
|
+
def describe(
|
|
468
|
+
self,
|
|
469
|
+
*,
|
|
470
|
+
include_species: bool = False,
|
|
471
|
+
species: str = "label",
|
|
472
|
+
) -> str:
|
|
473
|
+
"""Return a human-readable multiline description of the network.
|
|
474
|
+
|
|
475
|
+
:param include_species:
|
|
476
|
+
Whether to append a final line listing species names.
|
|
477
|
+
:type include_species: bool
|
|
478
|
+
|
|
479
|
+
:param species:
|
|
480
|
+
Species display mode used in the text summary.
|
|
481
|
+
:type species: str
|
|
482
|
+
|
|
483
|
+
:return:
|
|
484
|
+
Multiline text description.
|
|
485
|
+
:rtype: str
|
|
486
|
+
|
|
487
|
+
.. rubric:: Example
|
|
488
|
+
|
|
489
|
+
.. code-block:: python
|
|
490
|
+
|
|
491
|
+
print(syn.describe(include_species=True, species="label"))
|
|
492
|
+
"""
|
|
493
|
+
lines = [f"SynCRN: {self.n_species} species, {self.n_reactions} reactions"]
|
|
494
|
+
|
|
495
|
+
for rid in self.reaction_ids:
|
|
496
|
+
rxn = self.reactions[rid]
|
|
497
|
+
lhs = rxn.format_side(
|
|
498
|
+
rxn.lhs, lambda sid: self._species_token(sid, species)
|
|
499
|
+
)
|
|
500
|
+
rhs = rxn.format_side(
|
|
501
|
+
rxn.rhs, lambda sid: self._species_token(sid, species)
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
line = f" {rxn.id}: {lhs} >> {rhs}"
|
|
505
|
+
if rxn.rule_index is not None:
|
|
506
|
+
line += f" rule {rxn.rule_index}"
|
|
507
|
+
|
|
508
|
+
lines.append(line)
|
|
509
|
+
|
|
510
|
+
if include_species:
|
|
511
|
+
names = [self._species_token(sid, species) for sid in self.species_ids]
|
|
512
|
+
lines.append("Species: " + ", ".join(names))
|
|
513
|
+
|
|
514
|
+
return "\n".join(lines)
|
|
515
|
+
|
|
516
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
517
|
+
"""Return a nested JSON-like dictionary representation.
|
|
518
|
+
|
|
519
|
+
:return:
|
|
520
|
+
Full SynCRN object as a dictionary.
|
|
521
|
+
:rtype: Dict[str, Any]
|
|
522
|
+
|
|
523
|
+
.. rubric:: Example
|
|
524
|
+
|
|
525
|
+
.. code-block:: python
|
|
526
|
+
|
|
527
|
+
data = syn.to_dict()
|
|
528
|
+
print(data["species"].keys())
|
|
529
|
+
"""
|
|
530
|
+
return {
|
|
531
|
+
"graph_attrs": dict(self.graph_attrs),
|
|
532
|
+
"metadata": dict(self.metadata),
|
|
533
|
+
"species": {sid: sp.to_dict() for sid, sp in self.species.items()},
|
|
534
|
+
"rules": {rid: rule.to_dict() for rid, rule in self.rules.items()},
|
|
535
|
+
"reactions": {rid: rxn.to_dict() for rid, rxn in self.reactions.items()},
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
def to_stoichiometric_matrices(
|
|
539
|
+
self,
|
|
540
|
+
*,
|
|
541
|
+
sparse: bool = False,
|
|
542
|
+
dtype: Any = None,
|
|
543
|
+
) -> Dict[str, Any]:
|
|
544
|
+
"""Construct stoichiometric matrices in canonical species and reaction order.
|
|
545
|
+
|
|
546
|
+
The returned dictionary contains:
|
|
547
|
+
|
|
548
|
+
- ``species_order``
|
|
549
|
+
- ``reaction_order``
|
|
550
|
+
- ``S_minus``: reactant-incidence matrix
|
|
551
|
+
- ``S_plus``: product-incidence matrix
|
|
552
|
+
- ``S``: net stoichiometric matrix
|
|
553
|
+
|
|
554
|
+
Matrices are ``numpy.ndarray`` of shape ``(n_species, n_reactions)``, so
|
|
555
|
+
they can be handed straight to :mod:`numpy.linalg` and to
|
|
556
|
+
:mod:`synkit.CRN.Props`. Reaction networks are sparse — a species takes
|
|
557
|
+
part in a handful of reactions regardless of network size — so pass
|
|
558
|
+
``sparse=True`` for large networks to get ``scipy.sparse.csr_array``
|
|
559
|
+
matrices built from the nonzeros only, without ever allocating
|
|
560
|
+
``n_species x n_reactions`` cells.
|
|
561
|
+
|
|
562
|
+
:param sparse:
|
|
563
|
+
Whether to return ``scipy.sparse.csr_array`` instead of dense
|
|
564
|
+
``numpy.ndarray`` matrices.
|
|
565
|
+
:type sparse: bool
|
|
566
|
+
|
|
567
|
+
:param dtype:
|
|
568
|
+
Element dtype. Defaults to ``numpy.int64`` when every coefficient is
|
|
569
|
+
integral and ``numpy.float64`` otherwise.
|
|
570
|
+
:type dtype: Any
|
|
571
|
+
|
|
572
|
+
:return:
|
|
573
|
+
Stoichiometric matrix view of the network.
|
|
574
|
+
:rtype: Dict[str, Any]
|
|
575
|
+
|
|
576
|
+
.. rubric:: Example
|
|
577
|
+
|
|
578
|
+
.. code-block:: python
|
|
579
|
+
|
|
580
|
+
mats = syn.to_stoichiometric_matrices()
|
|
581
|
+
print(mats["species_order"])
|
|
582
|
+
print(mats["reaction_order"])
|
|
583
|
+
print(mats["S"])
|
|
584
|
+
|
|
585
|
+
big = syn.to_stoichiometric_matrices(sparse=True)
|
|
586
|
+
print(big["S"].nnz)
|
|
587
|
+
"""
|
|
588
|
+
species_order = self.species_ids
|
|
589
|
+
reaction_order = self.reaction_ids
|
|
590
|
+
|
|
591
|
+
n = len(species_order)
|
|
592
|
+
m = len(reaction_order)
|
|
593
|
+
|
|
594
|
+
sidx = {sid: i for i, sid in enumerate(species_order)}
|
|
595
|
+
ridx = {rid: j for j, rid in enumerate(reaction_order)}
|
|
596
|
+
|
|
597
|
+
minus_entries: List[Tuple[int, int, Any]] = []
|
|
598
|
+
plus_entries: List[Tuple[int, int, Any]] = []
|
|
599
|
+
|
|
600
|
+
for rid, rxn in self.reactions.items():
|
|
601
|
+
j = ridx[rid]
|
|
602
|
+
for sid, coeff in rxn.lhs.items():
|
|
603
|
+
minus_entries.append((sidx[sid], j, coeff))
|
|
604
|
+
for sid, coeff in rxn.rhs.items():
|
|
605
|
+
plus_entries.append((sidx[sid], j, coeff))
|
|
606
|
+
|
|
607
|
+
if dtype is None:
|
|
608
|
+
values = [v for _, _, v in minus_entries] + [v for _, _, v in plus_entries]
|
|
609
|
+
integral = all(
|
|
610
|
+
isinstance(v, (int, np.integer)) or float(v).is_integer()
|
|
611
|
+
for v in values
|
|
612
|
+
)
|
|
613
|
+
dtype = np.int64 if integral else np.float64
|
|
614
|
+
|
|
615
|
+
if sparse:
|
|
616
|
+
s_minus = _sparse_from_entries(minus_entries, shape=(n, m), dtype=dtype)
|
|
617
|
+
s_plus = _sparse_from_entries(plus_entries, shape=(n, m), dtype=dtype)
|
|
618
|
+
else:
|
|
619
|
+
s_minus = _dense_from_entries(minus_entries, shape=(n, m), dtype=dtype)
|
|
620
|
+
s_plus = _dense_from_entries(plus_entries, shape=(n, m), dtype=dtype)
|
|
621
|
+
|
|
622
|
+
return {
|
|
623
|
+
"species_order": species_order,
|
|
624
|
+
"reaction_order": reaction_order,
|
|
625
|
+
"S_minus": s_minus,
|
|
626
|
+
"S_plus": s_plus,
|
|
627
|
+
"S": s_plus - s_minus,
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
def to_petrinet(self) -> Dict[str, Any]:
|
|
631
|
+
"""Return a Petri-net style pre/post incidence view.
|
|
632
|
+
|
|
633
|
+
The returned dictionary contains:
|
|
634
|
+
|
|
635
|
+
- ``places``: species ids
|
|
636
|
+
- ``transitions``: reaction ids
|
|
637
|
+
- ``pre``: input incidence map
|
|
638
|
+
- ``post``: output incidence map
|
|
639
|
+
|
|
640
|
+
:return:
|
|
641
|
+
Petri-net incidence representation.
|
|
642
|
+
:rtype: Dict[str, Any]
|
|
643
|
+
|
|
644
|
+
.. rubric:: Example
|
|
645
|
+
|
|
646
|
+
.. code-block:: python
|
|
647
|
+
|
|
648
|
+
pn = syn.to_petrinet()
|
|
649
|
+
print(pn["pre"])
|
|
650
|
+
print(pn["post"])
|
|
651
|
+
"""
|
|
652
|
+
pre: Dict[str, Dict[str, int]] = {sid: {} for sid in self.species_ids}
|
|
653
|
+
post: Dict[str, Dict[str, int]] = {sid: {} for sid in self.species_ids}
|
|
654
|
+
|
|
655
|
+
for rid, rxn in self.reactions.items():
|
|
656
|
+
for sid, coeff in rxn.lhs.items():
|
|
657
|
+
pre[sid][rid] = coeff
|
|
658
|
+
for sid, coeff in rxn.rhs.items():
|
|
659
|
+
post[sid][rid] = coeff
|
|
660
|
+
|
|
661
|
+
return {
|
|
662
|
+
"places": list(self.species_ids),
|
|
663
|
+
"transitions": list(self.reaction_ids),
|
|
664
|
+
"pre": pre,
|
|
665
|
+
"post": post,
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
def to_digraph(
|
|
669
|
+
self,
|
|
670
|
+
*,
|
|
671
|
+
node_ids: str = "source",
|
|
672
|
+
reaction_kind: Optional[str] = None,
|
|
673
|
+
include_internal_ids: bool = True,
|
|
674
|
+
) -> nx.DiGraph:
|
|
675
|
+
"""Reconstruct a species--reaction bipartite digraph.
|
|
676
|
+
|
|
677
|
+
By default, this method preserves original node ids and original
|
|
678
|
+
reaction-node kinds. This means that input reaction nodes with
|
|
679
|
+
``kind="rule"`` will still appear as ``kind="rule"`` after round-trip.
|
|
680
|
+
|
|
681
|
+
:param node_ids:
|
|
682
|
+
``"source"`` preserves original node ids, while ``"internal"``
|
|
683
|
+
uses canonical ids such as ``s_1`` and ``r_1``.
|
|
684
|
+
:type node_ids: str
|
|
685
|
+
|
|
686
|
+
:param reaction_kind:
|
|
687
|
+
Optional override for reconstructed reaction-node kind.
|
|
688
|
+
:type reaction_kind: Optional[str]
|
|
689
|
+
|
|
690
|
+
:param include_internal_ids:
|
|
691
|
+
Whether to attach ``syncrn_id`` and ``source_node_id`` as node attributes.
|
|
692
|
+
:type include_internal_ids: bool
|
|
693
|
+
|
|
694
|
+
:return:
|
|
695
|
+
Reconstructed bipartite digraph.
|
|
696
|
+
:rtype: nx.DiGraph
|
|
697
|
+
|
|
698
|
+
:raises ValueError:
|
|
699
|
+
If ``node_ids`` is not ``"source"`` or ``"internal"``.
|
|
700
|
+
|
|
701
|
+
.. rubric:: Example
|
|
702
|
+
|
|
703
|
+
.. code-block:: python
|
|
704
|
+
|
|
705
|
+
g2 = syn.to_digraph()
|
|
706
|
+
g3 = syn.to_digraph(node_ids="internal", reaction_kind="reaction")
|
|
707
|
+
"""
|
|
708
|
+
if node_ids not in {"source", "internal"}:
|
|
709
|
+
raise ValueError("node_ids must be 'source' or 'internal'")
|
|
710
|
+
|
|
711
|
+
g = nx.DiGraph()
|
|
712
|
+
g.graph.update(self.graph_attrs)
|
|
713
|
+
g.graph.update(self.metadata)
|
|
714
|
+
|
|
715
|
+
species_node_map: Dict[str, Hashable] = {}
|
|
716
|
+
reaction_node_map: Dict[str, Hashable] = {}
|
|
717
|
+
|
|
718
|
+
for sid, sp in self.species.items():
|
|
719
|
+
nid = _resolve_species_node_id(sp, node_ids=node_ids)
|
|
720
|
+
g.add_node(
|
|
721
|
+
nid,
|
|
722
|
+
**_species_node_attrs(sp, include_internal_ids=include_internal_ids),
|
|
723
|
+
)
|
|
724
|
+
species_node_map[sid] = nid
|
|
725
|
+
|
|
726
|
+
for rid, rxn in self.reactions.items():
|
|
727
|
+
nid = _resolve_reaction_node_id(rxn, node_ids=node_ids)
|
|
728
|
+
g.add_node(
|
|
729
|
+
nid,
|
|
730
|
+
**_reaction_node_attrs(
|
|
731
|
+
rxn,
|
|
732
|
+
reaction_kind=reaction_kind,
|
|
733
|
+
include_internal_ids=include_internal_ids,
|
|
734
|
+
),
|
|
735
|
+
)
|
|
736
|
+
reaction_node_map[rid] = nid
|
|
737
|
+
|
|
738
|
+
for rid, rxn in self.reactions.items():
|
|
739
|
+
_add_reaction_edges_to_graph(
|
|
740
|
+
g,
|
|
741
|
+
rxn=rxn,
|
|
742
|
+
reaction_node=reaction_node_map[rid],
|
|
743
|
+
species_node_map=species_node_map,
|
|
744
|
+
)
|
|
745
|
+
|
|
746
|
+
return g
|
|
747
|
+
|
|
748
|
+
@classmethod
|
|
749
|
+
def from_reaction_strings(
|
|
750
|
+
cls,
|
|
751
|
+
rxns: List[str],
|
|
752
|
+
rules: Optional[List[Optional[str]]] = None,
|
|
753
|
+
*,
|
|
754
|
+
parser: Optional[Callable[[str], Any]] = None,
|
|
755
|
+
strict: bool = True,
|
|
756
|
+
id_style: str = "prefixed",
|
|
757
|
+
species_prefix: str = "s_",
|
|
758
|
+
reaction_prefix: str = "r_",
|
|
759
|
+
rule_prefix: str = "rule_",
|
|
760
|
+
) -> "SynCRN":
|
|
761
|
+
"""Build a SynCRN object directly from reaction strings.
|
|
762
|
+
|
|
763
|
+
Reactions and rules are interpreted pairwise, so ``rxns[i]`` corresponds
|
|
764
|
+
to ``rules[i]``.
|
|
765
|
+
|
|
766
|
+
ID policy
|
|
767
|
+
---------
|
|
768
|
+
By default this constructor mints the same prefixed ids as
|
|
769
|
+
:meth:`from_digraph`, so code written against one constructor works
|
|
770
|
+
against the other:
|
|
771
|
+
|
|
772
|
+
- Species ids: ``"s_1"``, ``"s_2"``, ...
|
|
773
|
+
- Reaction ids: ``"r_1"``, ``"r_2"``, ...
|
|
774
|
+
- Rule ids: ``"rule_1"``, ``"rule_2"``, ...
|
|
775
|
+
|
|
776
|
+
Passing ``id_style="numeric"`` restores the legacy single-namespace
|
|
777
|
+
scheme, where species are ``"1".."n"`` and reaction ids continue at
|
|
778
|
+
``"n+1"``. That scheme is ambiguous — a species label can coincide with
|
|
779
|
+
a reaction id — and is kept only for backwards compatibility.
|
|
780
|
+
|
|
781
|
+
Species are indexed by first appearance in the input reactions.
|
|
782
|
+
|
|
783
|
+
:param rxns:
|
|
784
|
+
List of reaction strings such as ``"2A>>B+3C"``.
|
|
785
|
+
:type rxns: List[str]
|
|
786
|
+
|
|
787
|
+
:param rules:
|
|
788
|
+
Optional list of rule strings pairwise aligned with ``rxns``.
|
|
789
|
+
:type rules: Optional[List[Optional[str]]]
|
|
790
|
+
|
|
791
|
+
:param parser:
|
|
792
|
+
Optional side parser. It should accept one side string such as
|
|
793
|
+
``"2A+B"`` and return either a mapping, an object with
|
|
794
|
+
``to_dict()``, or an object with ``items()``.
|
|
795
|
+
:type parser: Optional[Callable[[str], Any]]
|
|
796
|
+
|
|
797
|
+
:param strict:
|
|
798
|
+
Whether malformed reaction strings or empty sides should raise an error.
|
|
799
|
+
:type strict: bool
|
|
800
|
+
|
|
801
|
+
:param id_style:
|
|
802
|
+
Internal-id policy, either ``"prefixed"`` (default) or ``"numeric"``.
|
|
803
|
+
:type id_style: str
|
|
804
|
+
|
|
805
|
+
:param species_prefix:
|
|
806
|
+
Prefix for generated species ids under ``id_style="prefixed"``.
|
|
807
|
+
:type species_prefix: str
|
|
808
|
+
|
|
809
|
+
:param reaction_prefix:
|
|
810
|
+
Prefix for generated reaction ids under ``id_style="prefixed"``.
|
|
811
|
+
:type reaction_prefix: str
|
|
812
|
+
|
|
813
|
+
:param rule_prefix:
|
|
814
|
+
Prefix for generated rule ids under ``id_style="prefixed"``.
|
|
815
|
+
:type rule_prefix: str
|
|
816
|
+
|
|
817
|
+
:return:
|
|
818
|
+
Canonical SynCRN object.
|
|
819
|
+
:rtype: SynCRN
|
|
820
|
+
|
|
821
|
+
:raises TypeError:
|
|
822
|
+
If ``rxns`` or ``rules`` have invalid types.
|
|
823
|
+
|
|
824
|
+
:raises ValueError:
|
|
825
|
+
If reaction strings are malformed, rules are not pairwise aligned,
|
|
826
|
+
or ``id_style`` is unknown.
|
|
827
|
+
|
|
828
|
+
.. rubric:: Example
|
|
829
|
+
|
|
830
|
+
.. code-block:: python
|
|
831
|
+
|
|
832
|
+
syn = SynCRN.from_reaction_strings(["2A>>B+3C"])
|
|
833
|
+
print(syn.species_ids) # ['s_1', 's_2', 's_3']
|
|
834
|
+
print(syn.reaction_ids) # ['r_1']
|
|
835
|
+
|
|
836
|
+
legacy = SynCRN.from_reaction_strings(["2A>>B+3C"], id_style="numeric")
|
|
837
|
+
print(legacy.species_ids) # ['1', '2', '3']
|
|
838
|
+
"""
|
|
839
|
+
if id_style not in ID_STYLES:
|
|
840
|
+
raise ValueError(
|
|
841
|
+
f"id_style must be one of {sorted(ID_STYLES)}, got {id_style!r}"
|
|
842
|
+
)
|
|
843
|
+
if not isinstance(rxns, (list, tuple)) or not all(
|
|
844
|
+
isinstance(x, str) for x in rxns
|
|
845
|
+
):
|
|
846
|
+
raise TypeError("rxns must be a list or tuple of reaction strings")
|
|
847
|
+
|
|
848
|
+
if len(rxns) == 0:
|
|
849
|
+
return cls(
|
|
850
|
+
species={},
|
|
851
|
+
reactions={},
|
|
852
|
+
rules={},
|
|
853
|
+
graph_attrs={},
|
|
854
|
+
metadata={
|
|
855
|
+
"source": "reaction_strings",
|
|
856
|
+
"n_input_reactions": 0,
|
|
857
|
+
"has_pairwise_rules": False,
|
|
858
|
+
"id_style": id_style,
|
|
859
|
+
},
|
|
860
|
+
)
|
|
861
|
+
|
|
862
|
+
has_rules = rules is not None and len(rules) > 0
|
|
863
|
+
if has_rules:
|
|
864
|
+
if not isinstance(rules, (list, tuple)):
|
|
865
|
+
raise TypeError("rules must be a list or tuple when provided")
|
|
866
|
+
if len(rules) != len(rxns):
|
|
867
|
+
raise ValueError(
|
|
868
|
+
f"rules must be pairwise with rxns: got {len(rxns)} reactions and "
|
|
869
|
+
f"{len(rules)} rules"
|
|
870
|
+
)
|
|
871
|
+
if not all(r is None or isinstance(r, str) for r in rules):
|
|
872
|
+
raise TypeError("rules entries must be strings or None")
|
|
873
|
+
|
|
874
|
+
parse_side = parser if parser is not None else _default_parse_side_text
|
|
875
|
+
|
|
876
|
+
parsed_rxns = [
|
|
877
|
+
_parse_reaction_string_entry(
|
|
878
|
+
rxn_text=rxn_text,
|
|
879
|
+
rxn_index=i,
|
|
880
|
+
rule_repr=rules[i] if has_rules else None,
|
|
881
|
+
has_rules=has_rules,
|
|
882
|
+
parse_side=parse_side,
|
|
883
|
+
strict=strict,
|
|
884
|
+
)
|
|
885
|
+
for i, rxn_text in enumerate(rxns)
|
|
886
|
+
]
|
|
887
|
+
|
|
888
|
+
species_order = _species_order_from_parsed_reactions(parsed_rxns)
|
|
889
|
+
minted = _mint_reaction_string_ids(
|
|
890
|
+
n_species=len(species_order),
|
|
891
|
+
n_reactions=len(parsed_rxns),
|
|
892
|
+
id_style=id_style,
|
|
893
|
+
species_prefix=species_prefix,
|
|
894
|
+
reaction_prefix=reaction_prefix,
|
|
895
|
+
rule_prefix=rule_prefix,
|
|
896
|
+
)
|
|
897
|
+
label_to_sid = dict(zip(species_order, minted["species_ids"]))
|
|
898
|
+
|
|
899
|
+
species = _build_species_table_from_labels(
|
|
900
|
+
species_order,
|
|
901
|
+
species_ids=minted["species_ids"],
|
|
902
|
+
species_source_ids=minted["species_source_ids"],
|
|
903
|
+
)
|
|
904
|
+
rules_table = _build_rules_table_from_reaction_strings(
|
|
905
|
+
parsed_rxns,
|
|
906
|
+
rule_ids=minted["rule_ids"],
|
|
907
|
+
has_rules=has_rules,
|
|
908
|
+
)
|
|
909
|
+
reactions = _build_reactions_from_parsed_strings(
|
|
910
|
+
parsed_rxns,
|
|
911
|
+
label_to_sid=label_to_sid,
|
|
912
|
+
reaction_ids=minted["reaction_ids"],
|
|
913
|
+
reaction_source_ids=minted["reaction_source_ids"],
|
|
914
|
+
rule_ids=minted["rule_ids"],
|
|
915
|
+
has_rules=has_rules,
|
|
916
|
+
)
|
|
917
|
+
|
|
918
|
+
return cls(
|
|
919
|
+
species=species,
|
|
920
|
+
reactions=reactions,
|
|
921
|
+
rules=rules_table,
|
|
922
|
+
graph_attrs={},
|
|
923
|
+
metadata={
|
|
924
|
+
"source": "reaction_strings",
|
|
925
|
+
"n_input_reactions": len(rxns),
|
|
926
|
+
"has_pairwise_rules": has_rules,
|
|
927
|
+
"id_style": id_style,
|
|
928
|
+
},
|
|
929
|
+
)
|