synkit 0.0.4__tar.gz → 0.0.5__tar.gz
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-0.0.5/.github/workflows/build-doc.yml +34 -0
- {synkit-0.0.4 → synkit-0.0.5}/.gitignore +4 -0
- synkit-0.0.5/Data/Figure/synkit.png +0 -0
- synkit-0.0.5/Makefile +20 -0
- {synkit-0.0.4 → synkit-0.0.5}/PKG-INFO +2 -2
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Fingerprint/test_fp_calculator.py +9 -14
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Cluster/test_graph_morphism.py +21 -1
- synkit-0.0.5/Test/Graph/Context/test_hier_context.py +173 -0
- synkit-0.0.5/Test/Graph/Context/test_radius_expand.py +108 -0
- {synkit-0.0.4/Test/Graph → synkit-0.0.5/Test/Graph/Hydrogen}/test_graph_hydrogen.py +1 -1
- synkit-0.0.5/Test/Graph/Hydrogen/test_hcomplete.py +77 -0
- synkit-0.0.5/doc/conf.py +30 -0
- synkit-0.0.5/doc/getting_started.rst +66 -0
- synkit-0.0.5/doc/index.rst +23 -0
- synkit-0.0.5/doc/references.rst +113 -0
- synkit-0.0.5/make.bat +35 -0
- {synkit-0.0.4 → synkit-0.0.5}/pyproject.toml +2 -3
- {synkit-0.0.4 → synkit-0.0.5}/requirements.txt +2 -3
- synkit-0.0.5/synkit/Chem/Fingerprint/fp_calculator.py +158 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Fingerprint/smiles_featurizer.py +3 -3
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Cluster/batch_cluster.py +2 -2
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Cluster/graph_cluster.py +1 -1
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Cluster/graph_morphism.py +131 -0
- synkit-0.0.5/synkit/Graph/Context/hier_context.py +229 -0
- synkit-0.0.5/synkit/Graph/Context/radius_expand.py +246 -0
- synkit-0.0.4/synkit/Graph/hydrogen.py → synkit-0.0.5/synkit/Graph/Hyrogen/_misc.py +167 -3
- synkit-0.0.5/synkit/Graph/Hyrogen/hcomplete.py +357 -0
- synkit-0.0.5/synkit/Graph/Hyrogen/hextend.py +170 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/ITS/normalize_aam.py +1 -1
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/chem_converter.py +1 -1
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/debug.py +2 -1
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/nx_to_gml.py +1 -1
- synkit-0.0.5/synkit/Rule/__init__.py +0 -0
- synkit-0.0.5/synkit/Rule/longest_path.py +95 -0
- synkit-0.0.5/synkit/Rule/prune_templates.py +77 -0
- synkit-0.0.5/synkit/Utils/__init__.py +0 -0
- synkit-0.0.5/synkit/Vis/__init__.py +0 -0
- synkit-0.0.5/synkit/__init__.py +0 -0
- synkit-0.0.4/synkit/Chem/Fingerprint/fp_calculator.py +0 -108
- synkit-0.0.4/synkit/_misc.py +0 -181
- {synkit-0.0.4 → synkit-0.0.5}/.github/workflows/publish-package.yml +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/.github/workflows/test-and-lint.yml +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/CHANGELOG.md +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Data/Benchmark/conversion_time.json.gz +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Data/Testcase/Compose/ComposeRule/data.txt +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Data/Testcase/Compose/SingleRule/R0/0.gml +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Data/Testcase/Compose/SingleRule/R0/1.gml +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Data/Testcase/Compose/SingleRule/R0/2.gml +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Data/Testcase/mech.json.gz +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Data/Testcase/para_rule.json.gz +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Data/Testcase/para_rule_retro.json.gz +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Data/smart.json.gz +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/LICENSE +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/README.md +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Fingerprint/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Fingerprint/test_smiles_featurizer.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Fingerprint/test_transformation_fp.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Molecule/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Molecule/test_standardize.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Reaction/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Reaction/test_balance_checker.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Reaction/test_cleanning.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Reaction/test_deionize.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Reaction/test_fix_aam.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Reaction/test_neutralize.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Reaction/test_rsmi_utils.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Reaction/test_standardize.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/Reaction/test_tautomerize.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Chem/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Cluster/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Cluster/test_batch_cluster.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Cluster/test_graph_cluster.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Cluster/test_rule_morphism.py +0 -0
- {synkit-0.0.4/Test/Graph/Feature → synkit-0.0.5/Test/Graph/Context}/__init__.py +0 -0
- {synkit-0.0.4/Test/Graph/ITS → synkit-0.0.5/Test/Graph/Feature}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Feature/test_graph_descriptors.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Feature/test_graph_fps.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Feature/test_graph_signature.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Feature/test_hash_fps.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Feature/test_morgan_fps.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/Feature/test_path_fps.py +0 -0
- {synkit-0.0.4/Test/Graph → synkit-0.0.5/Test/Graph/Hydrogen}/__init__.py +0 -0
- {synkit-0.0.4/Test/IO → synkit-0.0.5/Test/Graph/ITS}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/ITS/test_aam_validator.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/ITS/test_its_construction.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/ITS/test_its_expand.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Graph/ITS/test_normalize_aam.py +0 -0
- {synkit-0.0.4/Test/Reactor → synkit-0.0.5/Test/Graph}/__init__.py +0 -0
- {synkit-0.0.4/Test/Rule → synkit-0.0.5/Test/IO}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/IO/test_chemical_converter.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/IO/test_dg_to_gml.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/IO/test_gml_to_nx.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/IO/test_graph_to_mol.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/IO/test_mol_to_graph.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/IO/test_nx_to_gml.py +0 -0
- {synkit-0.0.4/Test/Vis → synkit-0.0.5/Test/Reactor}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Reactor/test_core_engine.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Reactor/test_crn.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Reactor/test_multi_steps.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Reactor/test_path_finder.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Reactor/test_reactor_engine.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Reactor/test_reactor_utils.py +0 -0
- {synkit-0.0.4/Test → synkit-0.0.5/Test/Rule}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Rule/test_molecule_rule.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Rule/test_reactor_rule.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Rule/test_retro_reactor.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Rule/test_rule_compose.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Rule/test_rule_rbl.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Rule/test_rule_utils.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Rule/test_valance_constrain.py +0 -0
- {synkit-0.0.4/synkit/Chem/Fingerprint → synkit-0.0.5/Test/Vis}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Vis/test_dpo_vis.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/Test/Vis/test_embedding.py +0 -0
- {synkit-0.0.4/synkit/Chem/Molecule → synkit-0.0.5/Test}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/lint.sh +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/pytest.sh +0 -0
- {synkit-0.0.4/synkit/Chem/Reaction → synkit-0.0.5/synkit/Chem/Fingerprint}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
- {synkit-0.0.4/synkit/Graph/Cluster → synkit-0.0.5/synkit/Chem/Molecule}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Molecule/standardize.py +0 -0
- {synkit-0.0.4/synkit/Graph/Feature → synkit-0.0.5/synkit/Chem/Reaction}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Reaction/balance_check.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Reaction/cleanning.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Reaction/deionize.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Reaction/fix_aam.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Reaction/neutralize.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Reaction/rsmi_utils.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Reaction/standardize.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/Reaction/tautomerize.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Chem/utils.py +0 -0
- {synkit-0.0.4/synkit/IO → synkit-0.0.5/synkit/Graph/Cluster}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Cluster/rule_morphism.py +0 -0
- {synkit-0.0.4/synkit/Metrics → synkit-0.0.5/synkit/Graph/Context}/__init__.py +0 -0
- {synkit-0.0.4/synkit/Reactor → synkit-0.0.5/synkit/Graph/Feature}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Feature/graph_descriptors.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Feature/graph_fps.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Feature/graph_signature.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Feature/hash_fps.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Feature/morgan_fps.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Feature/path_fps.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/Feature/wl_hash.py +0 -0
- {synkit-0.0.4/synkit/Rule → synkit-0.0.5/synkit/Graph/Hyrogen}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/ITS/aam_utils.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/ITS/aam_validator.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/ITS/its_builder.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/ITS/its_construction.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/ITS/its_decompose.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/ITS/its_expand.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Graph/__init.py +0 -0
- {synkit-0.0.4/synkit/Utils → synkit-0.0.5/synkit/IO}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/data_io.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/data_process.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/dg_to_gml.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/gml_to_nx.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/graph_to_mol.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/mol_to_graph.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/IO/smiles_to_id.py +0 -0
- {synkit-0.0.4/synkit/Vis → synkit-0.0.5/synkit/Metrics}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Metrics/_base.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Metrics/_plot.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Metrics/_ranking.py +0 -0
- {synkit-0.0.4/synkit → synkit-0.0.5/synkit/Reactor}/__init__.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Reactor/core_engine.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Reactor/crn.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Reactor/dcrn.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Reactor/multi_steps.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Reactor/path_finder.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Reactor/reactor_engine.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Reactor/reactor_utils.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Reactor/single_predictor.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Rule/MaxValence.json.gz +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Rule/molecule_rule.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Rule/reactor_rule.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Rule/retro_reactor.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Rule/rule_compose.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Rule/rule_rbl.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Rule/rule_utils.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Rule/strip_rule.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Rule/valence_constrain.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Utils/utils.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Vis/chemical_graph_visualizer.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Vis/chemical_reaction_visualizer.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Vis/chemical_space.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Vis/dpo_vis.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Vis/embedding.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Vis/graph_visualizer.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Vis/pdf_writer.py +0 -0
- {synkit-0.0.4 → synkit-0.0.5}/synkit/Vis/rsmi_to_fig.py +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Build documentation for GitHub Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
workflow_dispatch: # Enable manual action trigger
|
|
9
|
+
|
|
10
|
+
env:
|
|
11
|
+
PYTHONPATH: .
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build_documentation_for_github_pages:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v3
|
|
18
|
+
with:
|
|
19
|
+
fetch-depth: 0
|
|
20
|
+
- uses: actions/setup-python@v4
|
|
21
|
+
with:
|
|
22
|
+
python-version: '3.11'
|
|
23
|
+
cache: 'pip' # caching pip dependencies
|
|
24
|
+
- run: pip install -r requirements.txt
|
|
25
|
+
- run: pip install sphinx sphinx-rtd-theme
|
|
26
|
+
- run: python3 -m sphinx ./doc docs
|
|
27
|
+
- name: publish doc
|
|
28
|
+
shell: bash
|
|
29
|
+
run: |
|
|
30
|
+
git config user.name "GitHub Action"
|
|
31
|
+
git config user.email "no@mail.tmp"
|
|
32
|
+
git add -f docs/
|
|
33
|
+
git commit -m "Doc build"
|
|
34
|
+
git push --force "https://github.com/TieuLongPhan/SynKit.git" `git subtree split --prefix docs/ main`:gh-pages
|
|
Binary file
|
synkit-0.0.5/Makefile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Minimal makefile for Sphinx documentation
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
# You can set these variables from the command line, and also
|
|
5
|
+
# from the environment for the first two.
|
|
6
|
+
SPHINXOPTS ?=
|
|
7
|
+
SPHINXBUILD ?= sphinx-build
|
|
8
|
+
SOURCEDIR = source
|
|
9
|
+
BUILDDIR = build
|
|
10
|
+
|
|
11
|
+
# Put it first so that "make" without argument is like "make help".
|
|
12
|
+
help:
|
|
13
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
14
|
+
|
|
15
|
+
.PHONY: help Makefile
|
|
16
|
+
|
|
17
|
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
18
|
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
19
|
+
%: Makefile
|
|
20
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: synkit
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: Utility for reaction modeling using graph grammar
|
|
5
5
|
Project-URL: homepage, https://github.com/TieuLongPhan/SynKit
|
|
6
6
|
Project-URL: source, https://github.com/TieuLongPhan/SynKit
|
|
@@ -19,9 +19,9 @@ Requires-Dist: regex>=2024.11.6
|
|
|
19
19
|
Requires-Dist: requests>=2.32.3
|
|
20
20
|
Requires-Dist: scikit-learn>=1.4.0
|
|
21
21
|
Requires-Dist: seaborn>=0.13.2
|
|
22
|
-
Requires-Dist: torch>=2.2.0
|
|
23
22
|
Provides-Extra: all
|
|
24
23
|
Requires-Dist: numpy>=2.2.0; extra == 'all'
|
|
24
|
+
Requires-Dist: torch>=2.2.0; extra == 'all'
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
|
|
27
27
|
# SynKit
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import unittest
|
|
2
|
-
import pandas as pd
|
|
3
|
-
|
|
4
2
|
from synkit.Chem.Fingerprint.fp_calculator import FPCalculator
|
|
5
3
|
|
|
6
4
|
|
|
7
5
|
class TestFPCalculator(unittest.TestCase):
|
|
8
6
|
def setUp(self):
|
|
9
7
|
# Sample data setup
|
|
10
|
-
self.data =
|
|
8
|
+
self.data = [
|
|
11
9
|
{
|
|
12
10
|
"smiles": [
|
|
13
11
|
(
|
|
@@ -25,39 +23,36 @@ class TestFPCalculator(unittest.TestCase):
|
|
|
25
23
|
],
|
|
26
24
|
"ID": [1, 2, 3],
|
|
27
25
|
}
|
|
28
|
-
|
|
29
|
-
self.
|
|
26
|
+
]
|
|
27
|
+
self.smiles_key = "smiles"
|
|
30
28
|
self.fp_type = "drfp"
|
|
31
29
|
self.n_jobs = 2
|
|
32
30
|
self.verbose = 0
|
|
33
|
-
self.save_path = None
|
|
34
31
|
|
|
35
32
|
# Instantiate the FPCalculator
|
|
36
33
|
self.fp_calculator = FPCalculator(
|
|
37
|
-
|
|
38
|
-
smiles_column=self.smiles_column,
|
|
34
|
+
smiles_key=self.smiles_key,
|
|
39
35
|
fp_type=self.fp_type,
|
|
40
36
|
n_jobs=self.n_jobs,
|
|
41
37
|
verbose=self.verbose,
|
|
42
|
-
save_path=self.save_path,
|
|
43
38
|
)
|
|
44
39
|
|
|
45
40
|
def test_init_invalid_fp_type(self):
|
|
46
41
|
with self.assertRaises(ValueError):
|
|
47
|
-
FPCalculator(
|
|
42
|
+
FPCalculator(smiles_key=self.smiles_key, fp_type="invalid_type")
|
|
48
43
|
|
|
49
44
|
def test_fit_missing_column(self):
|
|
50
45
|
with self.assertRaises(ValueError):
|
|
51
46
|
fp_calculator = FPCalculator(
|
|
52
|
-
|
|
47
|
+
smiles_key=self.smiles_key,
|
|
48
|
+
fp_type=self.fp_type,
|
|
53
49
|
)
|
|
54
|
-
fp_calculator.
|
|
50
|
+
fp_calculator.dict_process({"not_smiles": ["C"]}, "smiles")
|
|
55
51
|
|
|
56
52
|
def test_constructor_and_attribute_assignment(self):
|
|
57
|
-
self.assertEqual(self.fp_calculator.
|
|
53
|
+
self.assertEqual(self.fp_calculator.smiles_key, "smiles")
|
|
58
54
|
self.assertEqual(self.fp_calculator.fp_type, "drfp")
|
|
59
55
|
self.assertEqual(self.fp_calculator.n_jobs, 2)
|
|
60
|
-
self.assertIsNone(self.fp_calculator.save_path)
|
|
61
56
|
|
|
62
57
|
|
|
63
58
|
if __name__ == "__main__":
|
|
@@ -2,7 +2,12 @@ import unittest
|
|
|
2
2
|
from synkit.IO.data_io import load_from_pickle
|
|
3
3
|
from synkit.IO.chem_converter import rsmi_to_its
|
|
4
4
|
from synkit.Graph.ITS.its_decompose import get_rc
|
|
5
|
-
from synkit.Graph.Cluster.graph_morphism import
|
|
5
|
+
from synkit.Graph.Cluster.graph_morphism import (
|
|
6
|
+
graph_isomorphism,
|
|
7
|
+
subgraph_isomorphism,
|
|
8
|
+
maximum_connected_common_subgraph,
|
|
9
|
+
heuristics_MCCS,
|
|
10
|
+
)
|
|
6
11
|
|
|
7
12
|
|
|
8
13
|
class TestGraphMorphism(unittest.TestCase):
|
|
@@ -46,6 +51,21 @@ class TestGraphMorphism(unittest.TestCase):
|
|
|
46
51
|
result = subgraph_isomorphism(self.rc, self.its, check_type="induced")
|
|
47
52
|
self.assertFalse(result)
|
|
48
53
|
|
|
54
|
+
def test_maximum_connected_common_subgraph(self):
|
|
55
|
+
mcs = maximum_connected_common_subgraph(
|
|
56
|
+
self.graphs[0]["RC"], self.graphs[1]["RC"]
|
|
57
|
+
)
|
|
58
|
+
self.assertEqual(mcs.number_of_nodes(), 3)
|
|
59
|
+
self.assertGreater(
|
|
60
|
+
self.graphs[0]["RC"].number_of_nodes(), mcs.number_of_nodes()
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def test_heuristics_MCCS(self):
|
|
64
|
+
graphs = [value["RC"] for value in self.graphs]
|
|
65
|
+
mcs = heuristics_MCCS(graphs[:3])
|
|
66
|
+
self.assertEqual(mcs.number_of_nodes(), 1)
|
|
67
|
+
self.assertGreater(graphs[0].number_of_nodes(), mcs.number_of_nodes())
|
|
68
|
+
|
|
49
69
|
|
|
50
70
|
if __name__ == "__main__":
|
|
51
71
|
unittest.main()
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from copy import deepcopy
|
|
3
|
+
from synkit.IO.data_io import load_from_pickle
|
|
4
|
+
from synkit.Graph.Context.hier_context import HierContext
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestRuleCluster(unittest.TestCase):
|
|
8
|
+
def setUp(self) -> None:
|
|
9
|
+
# Create an instance of HierContext with max_radius=3.
|
|
10
|
+
self.cluster = HierContext(max_radius=3)
|
|
11
|
+
# Load test data from a pickle file.
|
|
12
|
+
# Ensure this file exists at the specified location: "Data/Testcase/graph.pkl.gz"
|
|
13
|
+
self.data = load_from_pickle("Data/Testcase/graph.pkl.gz")
|
|
14
|
+
# Verify that the loaded data is a non-empty list.
|
|
15
|
+
self.assertIsInstance(self.data, list)
|
|
16
|
+
self.assertGreater(len(self.data), 0, "Loaded test data should not be empty.")
|
|
17
|
+
|
|
18
|
+
def test_group_class(self):
|
|
19
|
+
"""
|
|
20
|
+
Tests the _group_class function by grouping dictionaries based on a key.
|
|
21
|
+
"""
|
|
22
|
+
data = [
|
|
23
|
+
{"a": 1, "value": "x"},
|
|
24
|
+
{"a": 2, "value": "y"},
|
|
25
|
+
{"a": 1, "value": "z"},
|
|
26
|
+
{"a": 3, "value": "w"},
|
|
27
|
+
]
|
|
28
|
+
grouped = HierContext._group_class(data, "a")
|
|
29
|
+
expected = {
|
|
30
|
+
1: [{"a": 1, "value": "x"}, {"a": 1, "value": "z"}],
|
|
31
|
+
2: [{"a": 2, "value": "y"}],
|
|
32
|
+
3: [{"a": 3, "value": "w"}],
|
|
33
|
+
}
|
|
34
|
+
self.assertEqual(
|
|
35
|
+
grouped,
|
|
36
|
+
expected,
|
|
37
|
+
"The grouped output does not match the expected grouping.",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def test_update_child_idx(self):
|
|
41
|
+
"""
|
|
42
|
+
Tests the _update_child_idx function to ensure that child IDs are correctly added
|
|
43
|
+
based on parent–cluster relationships.
|
|
44
|
+
"""
|
|
45
|
+
# Create a two-layer hierarchy:
|
|
46
|
+
# Layer 0: One node with 'class' = 1.
|
|
47
|
+
# Layer 1: Two nodes with 'class' = 2 and 3, each having Parent set to 1.
|
|
48
|
+
layer0 = [{"class": 1}]
|
|
49
|
+
layer1 = [{"class": 2, "Parent": 1}, {"class": 3, "Parent": 1}]
|
|
50
|
+
data = [layer0, layer1]
|
|
51
|
+
updated = HierContext._update_child_idx(data, cls_id="class")
|
|
52
|
+
|
|
53
|
+
# The node from layer 0 should have its "Child" field updated with the class IDs from layer 1.
|
|
54
|
+
self.assertIn("Child", updated[0][0])
|
|
55
|
+
self.assertEqual(
|
|
56
|
+
set(updated[0][0]["Child"]),
|
|
57
|
+
{2, 3},
|
|
58
|
+
"The 'Child' list of the parent node does not contain the expected child class IDs.",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def test_process(self):
|
|
62
|
+
"""
|
|
63
|
+
Tests the _process function which extracts a context, computes a hash,
|
|
64
|
+
and clusters the data.
|
|
65
|
+
"""
|
|
66
|
+
# Use the loaded test data.
|
|
67
|
+
data = deepcopy(self.data)
|
|
68
|
+
cluster_results, templates = HierContext._process(
|
|
69
|
+
data,
|
|
70
|
+
k=1,
|
|
71
|
+
its_key="ITS",
|
|
72
|
+
context_key="K",
|
|
73
|
+
cls_func=self.cluster.cluster,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Validate that the first processed data entry has updated keys.
|
|
77
|
+
self.assertIn(
|
|
78
|
+
"R_1", cluster_results[0], "Cluster result should include the key 'R_1'."
|
|
79
|
+
)
|
|
80
|
+
self.assertIn(
|
|
81
|
+
"K",
|
|
82
|
+
cluster_results[0],
|
|
83
|
+
"Cluster result should include the context key 'K'.",
|
|
84
|
+
)
|
|
85
|
+
self.assertIsInstance(
|
|
86
|
+
cluster_results[0]["R_1"],
|
|
87
|
+
int,
|
|
88
|
+
"Cluster identifier 'R_1' should be an integer.",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Check that templates are processed correctly.
|
|
92
|
+
# Depending on your dummy clustering behavior, update these expected values.
|
|
93
|
+
self.assertGreater(len(templates), 0, "Templates list should not be empty.")
|
|
94
|
+
self.assertEqual(
|
|
95
|
+
templates[0]["class"],
|
|
96
|
+
0,
|
|
97
|
+
"Expected the first template's 'class' to be 0 after processing.",
|
|
98
|
+
)
|
|
99
|
+
# If you expect a specific number of templates from your test data, verify it.
|
|
100
|
+
# Here, we expect 61 templates. Change if necessary.
|
|
101
|
+
self.assertEqual(len(templates), 61, "Unexpected number of templates produced.")
|
|
102
|
+
self.assertIn("K", templates[0], "Template should contain the context key 'K'.")
|
|
103
|
+
|
|
104
|
+
def test_process_level(self):
|
|
105
|
+
"""
|
|
106
|
+
Tests the _process_level function by grouping data based on parent cluster IDs,
|
|
107
|
+
processing each group, and then verifying that cluster keys and templates are updated.
|
|
108
|
+
"""
|
|
109
|
+
# Use the loaded test data for processing at a child level.
|
|
110
|
+
data = deepcopy(self.data)
|
|
111
|
+
cluster_indices, templates = self.cluster._process_level(
|
|
112
|
+
data, "ITS", "K", self.cluster.cluster, 1
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Check that each clustered result has the "R_1" field.
|
|
116
|
+
self.assertIn(
|
|
117
|
+
"R_1",
|
|
118
|
+
cluster_indices[0],
|
|
119
|
+
"Each cluster result should have the 'R_1' field for level 1 clustering.",
|
|
120
|
+
)
|
|
121
|
+
self.assertIn(
|
|
122
|
+
"K", cluster_indices[0], "Each cluster result should contain the key 'K'."
|
|
123
|
+
)
|
|
124
|
+
# Validate that templates include the necessary keys.
|
|
125
|
+
self.assertIn("K", templates[0], "Each template should contain the key 'K'.")
|
|
126
|
+
self.assertIn(
|
|
127
|
+
"Parent",
|
|
128
|
+
templates[0],
|
|
129
|
+
"Each template should contain the key 'Parent' to link to a parent cluster.",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
def test_fit(self):
|
|
133
|
+
"""
|
|
134
|
+
Tests the fit method which processes a list of graph data entries, classifying each based on
|
|
135
|
+
hierarchical clustering, and verifies that cluster indices and templates are updated at multiple levels.
|
|
136
|
+
"""
|
|
137
|
+
data, templates = self.cluster.fit(self.data, its_key="ITS", context_key="K")
|
|
138
|
+
|
|
139
|
+
# Check that each data entry has keys for the expected levels.
|
|
140
|
+
for level in range(4): # Levels 0, 1, 2, 3 (since max_radius=3)
|
|
141
|
+
self.assertIn(
|
|
142
|
+
f"R_{level}",
|
|
143
|
+
data[0],
|
|
144
|
+
f"Data entry should include the key 'R_{level}' after processing.",
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# Check that a template list exists for each hierarchical level.
|
|
148
|
+
self.assertEqual(
|
|
149
|
+
len(templates), 4, "There should be 4 levels of templates (0, 1, 2, 3)."
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Validate that the first template of the parent level contains required keys.
|
|
153
|
+
self.assertIn(
|
|
154
|
+
"K",
|
|
155
|
+
templates[0][0],
|
|
156
|
+
"The first template in level 0 should contain the key 'K'.",
|
|
157
|
+
)
|
|
158
|
+
self.assertIn(
|
|
159
|
+
"Child",
|
|
160
|
+
templates[0][0],
|
|
161
|
+
"The first template in level 0 should contain the key 'Child' if child relationships were established.",
|
|
162
|
+
)
|
|
163
|
+
# Validate that a template in level 1 contains a Parent key.
|
|
164
|
+
if len(templates) > 1 and templates[1]:
|
|
165
|
+
self.assertIn(
|
|
166
|
+
"Parent",
|
|
167
|
+
templates[1][0],
|
|
168
|
+
"Templates at level 1 should contain the key 'Parent' linking to the parent cluster.",
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
if __name__ == "__main__":
|
|
173
|
+
unittest.main()
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
import networkx as nx
|
|
3
|
+
from synkit.IO.data_io import load_from_pickle
|
|
4
|
+
from synkit.Graph.ITS.its_decompose import get_rc
|
|
5
|
+
from synkit.Graph.Context.radius_expand import RadiusExpand
|
|
6
|
+
from synkit.Graph.Cluster.graph_morphism import graph_isomorphism, subgraph_isomorphism
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestRadiusExpand(unittest.TestCase):
|
|
10
|
+
|
|
11
|
+
def setUp(self):
|
|
12
|
+
self.data = load_from_pickle("Data/Testcase/graph.pkl.gz")
|
|
13
|
+
|
|
14
|
+
def test_find_unequal_order_edges(self):
|
|
15
|
+
# Create a graph with edges that include various 'order' and 'standard_order' attributes.
|
|
16
|
+
G = nx.Graph()
|
|
17
|
+
# Edge qualifies: unequal order and standard_order != 0.
|
|
18
|
+
G.add_edge(1, 2, order=(1, 2), standard_order=1)
|
|
19
|
+
# Edge does not qualify: equal order.
|
|
20
|
+
G.add_edge(2, 3, order=(1, 1), standard_order=1)
|
|
21
|
+
# Edge qualifies.
|
|
22
|
+
G.add_edge(3, 4, order=(2, 3), standard_order=1)
|
|
23
|
+
# Edge does not qualify because standard_order == 0.
|
|
24
|
+
G.add_edge(1, 3, order=(1, 2), standard_order=0)
|
|
25
|
+
result = set(RadiusExpand.find_unequal_order_edges(G))
|
|
26
|
+
expected = {1, 2, 3, 4}
|
|
27
|
+
self.assertEqual(result, expected)
|
|
28
|
+
|
|
29
|
+
def test_extract_subgraph(self):
|
|
30
|
+
# Create a test graph
|
|
31
|
+
G = nx.Graph()
|
|
32
|
+
G.add_edges_from([(1, 2), (2, 3), (3, 4)])
|
|
33
|
+
|
|
34
|
+
# Node indices for subgraph extraction
|
|
35
|
+
node_indices = [2, 3]
|
|
36
|
+
|
|
37
|
+
# Extract subgraph and test
|
|
38
|
+
subgraph = RadiusExpand.extract_subgraph(G, node_indices)
|
|
39
|
+
self.assertTrue(nx.is_isomorphic(subgraph, nx.Graph([(2, 3)])))
|
|
40
|
+
|
|
41
|
+
def test_longest_radius_extension(self):
|
|
42
|
+
# Create a graph where a chain of edges with standard_order == 0 exists.
|
|
43
|
+
G = nx.Graph()
|
|
44
|
+
G.add_edge(0, 1, standard_order=0)
|
|
45
|
+
G.add_edge(1, 2, standard_order=0)
|
|
46
|
+
# This edge is blocked because standard_order != 0.
|
|
47
|
+
G.add_edge(2, 3, standard_order=1)
|
|
48
|
+
# Compute longest extension from node 0.
|
|
49
|
+
path = RadiusExpand.longest_radius_extension(G, [0])
|
|
50
|
+
self.assertEqual(path, [0, 1, 2])
|
|
51
|
+
|
|
52
|
+
# Add an alternative branch: from node 1 to node 4.
|
|
53
|
+
G.add_edge(1, 4, standard_order=0)
|
|
54
|
+
# Now, DFS might find either [0, 1, 2] or [0, 1, 4]. Both have length 3.
|
|
55
|
+
path2 = RadiusExpand.longest_radius_extension(G, [0])
|
|
56
|
+
self.assertEqual(len(path2), 3)
|
|
57
|
+
self.assertTrue(set(path2).issubset(set(G.nodes())))
|
|
58
|
+
|
|
59
|
+
def test_remove_normal_edges(self):
|
|
60
|
+
# Build a graph with a custom attribute 'weight' and remove those edges where weight == 0.
|
|
61
|
+
G = nx.Graph()
|
|
62
|
+
G.add_edge(1, 2, weight=0)
|
|
63
|
+
G.add_edge(2, 3, weight=1)
|
|
64
|
+
G.add_edge(3, 4, weight=0)
|
|
65
|
+
G.add_edge(4, 5, weight=2)
|
|
66
|
+
modified = RadiusExpand.remove_normal_edges(G, "weight")
|
|
67
|
+
# Expected to keep only edges where weight is not 0: (2,3) and (4,5).
|
|
68
|
+
expected_edges = {(2, 3), (4, 5)}
|
|
69
|
+
self.assertEqual(set(modified.edges()), expected_edges)
|
|
70
|
+
|
|
71
|
+
def test_extract_k(self):
|
|
72
|
+
its = self.data[0]["ITS"]
|
|
73
|
+
rc = get_rc(its)
|
|
74
|
+
context = RadiusExpand.extract_k(its, 0)
|
|
75
|
+
self.assertTrue(graph_isomorphism(rc, context, use_defaults=True))
|
|
76
|
+
|
|
77
|
+
# Test with a positive n_knn value.
|
|
78
|
+
context = RadiusExpand.extract_k(its, 1)
|
|
79
|
+
self.assertTrue(subgraph_isomorphism(rc, context))
|
|
80
|
+
self.assertTrue(subgraph_isomorphism(context, its))
|
|
81
|
+
|
|
82
|
+
# Test with n_knn == -1 to automatically determine neighbor expansion.
|
|
83
|
+
context = RadiusExpand.extract_k(its, -1)
|
|
84
|
+
self.assertTrue(graph_isomorphism(its, context, use_defaults=True))
|
|
85
|
+
|
|
86
|
+
def test_context_extraction(self):
|
|
87
|
+
data = self.data[0]
|
|
88
|
+
result = RadiusExpand.context_extraction(
|
|
89
|
+
data, its_key="ITS", context_key="K", n_knn=1
|
|
90
|
+
)
|
|
91
|
+
self.assertIn("K", result)
|
|
92
|
+
self.assertTrue(subgraph_isomorphism(result["RC"], result["K"]))
|
|
93
|
+
self.assertTrue(subgraph_isomorphism(result["K"], result["ITS"]))
|
|
94
|
+
|
|
95
|
+
def test_paralle_context_extraction(self):
|
|
96
|
+
data_list = self.data[0:3]
|
|
97
|
+
results = RadiusExpand.paralle_context_extraction(
|
|
98
|
+
data_list, its_key="ITS", context_key="K", n_jobs=1, verbose=0, n_knn=1
|
|
99
|
+
)
|
|
100
|
+
self.assertEqual(len(results), 3)
|
|
101
|
+
for res in results:
|
|
102
|
+
self.assertIn("K", res)
|
|
103
|
+
self.assertTrue(subgraph_isomorphism(res["RC"], res["K"]))
|
|
104
|
+
self.assertTrue(subgraph_isomorphism(res["K"], res["ITS"]))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
unittest.main()
|
|
@@ -2,7 +2,7 @@ import unittest
|
|
|
2
2
|
from synkit.Graph.ITS.aam_validator import AAMValidator
|
|
3
3
|
from synkit.Graph.Cluster.graph_morphism import graph_isomorphism
|
|
4
4
|
from synkit.IO.chem_converter import rsmi_to_graph, graph_to_rsmi
|
|
5
|
-
from synkit.Graph.
|
|
5
|
+
from synkit.Graph.Hyrogen._misc import implicit_hydrogen, explicit_hydrogen
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class TestGraphH(unittest.TestCase):
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
import networkx as nx
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from synkit.IO.data_io import load_from_pickle
|
|
5
|
+
from synkit.Graph.ITS.its_decompose import its_decompose
|
|
6
|
+
from synkit.Graph.Hyrogen.hcomplete import HComplete
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestHComplete(unittest.TestCase):
|
|
10
|
+
|
|
11
|
+
def setUp(self):
|
|
12
|
+
"""Setup before each test."""
|
|
13
|
+
# Create sample graphs
|
|
14
|
+
self.data = load_from_pickle("./Data/Testcase/hydro/hydrogen_test.pkl.gz")
|
|
15
|
+
|
|
16
|
+
def test_process_single_graph_data_success(self):
|
|
17
|
+
"""Test the process_single_graph_data method."""
|
|
18
|
+
processed_data = HComplete.process_single_graph_data(self.data[0], "ITS", "RC")
|
|
19
|
+
self.assertTrue(isinstance(processed_data["ITS"], nx.Graph))
|
|
20
|
+
self.assertTrue(isinstance(processed_data["RC"], nx.Graph))
|
|
21
|
+
|
|
22
|
+
def test_process_single_graph_data_fail(self):
|
|
23
|
+
"""Test the process_single_graph_data method."""
|
|
24
|
+
processed_data = HComplete.process_single_graph_data(self.data[16], "ITS", "RC")
|
|
25
|
+
self.assertIsNone(processed_data["ITS"])
|
|
26
|
+
self.assertIsNone(processed_data["RC"])
|
|
27
|
+
|
|
28
|
+
def test_process_single_graph_data_empty_graph(self):
|
|
29
|
+
"""Test that an empty graph results in empty ITSGraph and GraphRules."""
|
|
30
|
+
empty_graph_data = {
|
|
31
|
+
"ITS": None,
|
|
32
|
+
"RC": None,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
processed_data = HComplete.process_single_graph_data(
|
|
36
|
+
empty_graph_data, "ITSGraph"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Ensure the result is None or empty as expected for an empty graph
|
|
40
|
+
self.assertIsNone(processed_data["ITS"])
|
|
41
|
+
self.assertIsNone(processed_data["RC"])
|
|
42
|
+
|
|
43
|
+
def test_process_graph_data_parallel(self):
|
|
44
|
+
"""Test the process_graph_data_parallel method."""
|
|
45
|
+
result = HComplete().process_graph_data_parallel(
|
|
46
|
+
self.data,
|
|
47
|
+
"ITS",
|
|
48
|
+
"RC",
|
|
49
|
+
n_jobs=1,
|
|
50
|
+
verbose=0,
|
|
51
|
+
)
|
|
52
|
+
result = [value for value in result if value["ITS"]]
|
|
53
|
+
# Check if the result matches the input data structure
|
|
54
|
+
self.assertEqual(len(result), 45) # 45 valid graphs
|
|
55
|
+
|
|
56
|
+
def test_process_multiple_hydrogens(self):
|
|
57
|
+
"""Test the process_multiple_hydrogens method."""
|
|
58
|
+
graphs = deepcopy(self.data[0])
|
|
59
|
+
its = graphs["ITS"]
|
|
60
|
+
react_graph, prod_graph = its_decompose(its)
|
|
61
|
+
|
|
62
|
+
result = HComplete.process_multiple_hydrogens(
|
|
63
|
+
graphs,
|
|
64
|
+
"ITS",
|
|
65
|
+
"RC",
|
|
66
|
+
react_graph,
|
|
67
|
+
prod_graph,
|
|
68
|
+
ignore_aromaticity=False,
|
|
69
|
+
balance_its=True,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
self.assertTrue(isinstance(result["ITS"], nx.Graph))
|
|
73
|
+
self.assertTrue(isinstance(result["RC"], nx.Graph))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
unittest.main()
|
synkit-0.0.5/doc/conf.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Configuration file for the Sphinx documentation builder.
|
|
2
|
+
#
|
|
3
|
+
# For the full list of built-in configuration values, see the documentation:
|
|
4
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
5
|
+
|
|
6
|
+
# -- Project information -----------------------------------------------------
|
|
7
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
|
8
|
+
|
|
9
|
+
project = "synkit"
|
|
10
|
+
copyright = "2025, Tieu-Long Phan"
|
|
11
|
+
author = "Tieu-Long Phan"
|
|
12
|
+
|
|
13
|
+
# -- General configuration ---------------------------------------------------
|
|
14
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
15
|
+
|
|
16
|
+
extensions = [
|
|
17
|
+
"sphinx.ext.autodoc",
|
|
18
|
+
"sphinx.ext.autosectionlabel",
|
|
19
|
+
"sphinx.ext.githubpages",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
templates_path = ["_templates"]
|
|
23
|
+
exclude_patterns = []
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# -- Options for HTML output -------------------------------------------------
|
|
27
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
|
28
|
+
|
|
29
|
+
html_theme = "sphinx_rtd_theme"
|
|
30
|
+
html_static_path = ["_static"]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
.. _getting-started-synkit:
|
|
2
|
+
|
|
3
|
+
===============
|
|
4
|
+
Getting Started
|
|
5
|
+
===============
|
|
6
|
+
|
|
7
|
+
Welcome to the **synkit** documentation. This guide will assist you in setting up **synkit**, a versatile toolkit designed to streamline and enhance your workflows.
|
|
8
|
+
|
|
9
|
+
Introduction
|
|
10
|
+
------------
|
|
11
|
+
|
|
12
|
+
**synkit** is designed to provide tools and functions that simplify complex tasks and improve productivity. It is essential for professionals looking to optimize their processes efficiently.
|
|
13
|
+
|
|
14
|
+
Installation
|
|
15
|
+
============
|
|
16
|
+
|
|
17
|
+
Installing **synkit** is straightforward using pip, the Python package installer. For a more controlled and conflict-free environment, we recommend setting up **synkit** within a virtual environment.
|
|
18
|
+
|
|
19
|
+
Requirements
|
|
20
|
+
------------
|
|
21
|
+
|
|
22
|
+
Before installing **synkit**, ensure you have Python 3.11 or later installed on your machine. The use of a virtual environment is recommended to avoid conflicts with other Python packages.
|
|
23
|
+
|
|
24
|
+
Creating a Virtual Environment (Optional)
|
|
25
|
+
-----------------------------------------
|
|
26
|
+
|
|
27
|
+
Setting up a virtual environment for **synkit** is an optional but recommended step. It isolates the installation and dependencies of **synkit** from other Python projects, which helps prevent conflicts and maintain a clean workspace.
|
|
28
|
+
|
|
29
|
+
1. **Create a virtual environment**:
|
|
30
|
+
|
|
31
|
+
Use the following command to create a virtual environment named `synkit_env`. This step requires the `conda` package manager, which can be installed via the Anaconda distribution.
|
|
32
|
+
|
|
33
|
+
.. code-block:: bash
|
|
34
|
+
|
|
35
|
+
conda create -n synkit_env python=3.11
|
|
36
|
+
|
|
37
|
+
2. **Activate the virtual environment**:
|
|
38
|
+
|
|
39
|
+
Once the environment is created, activate it using:
|
|
40
|
+
|
|
41
|
+
.. code-block:: bash
|
|
42
|
+
|
|
43
|
+
conda activate synkit_env
|
|
44
|
+
|
|
45
|
+
Installing **synkit** via Pip
|
|
46
|
+
---------------------------------
|
|
47
|
+
|
|
48
|
+
After setting up and activating your virtual environment, install **synkit** using pip by running the following command:
|
|
49
|
+
|
|
50
|
+
.. code-block:: bash
|
|
51
|
+
|
|
52
|
+
pip install synkit
|
|
53
|
+
|
|
54
|
+
This command will download and install the latest version of **synkit** along with its required dependencies.
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
Further Resources
|
|
58
|
+
=================
|
|
59
|
+
|
|
60
|
+
For more detailed documentation, usage examples, and API guides, visit the [official **synkit** documentation](https://tieulongphan.github.io/SynKit).
|
|
61
|
+
|
|
62
|
+
Support
|
|
63
|
+
-------
|
|
64
|
+
|
|
65
|
+
If you encounter any issues or require assistance, please refer to the community support forums or file an issue on the [**synkit** GitHub page](https://github.com/TieuLongPhan/SynKit/issues).
|
|
66
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
.. synutility documentation master file, created by
|
|
2
|
+
sphinx-quickstart on Fri Oct 18 11:47:09 2024.
|
|
3
|
+
You can adapt this file completely to your liking, but it should at least
|
|
4
|
+
contain the root `toctree` directive.
|
|
5
|
+
|
|
6
|
+
Welcome to synkit documentation!
|
|
7
|
+
====================================
|
|
8
|
+
|
|
9
|
+
Add your content using ``reStructuredText`` syntax. See the
|
|
10
|
+
`reStructuredText <https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html>`_
|
|
11
|
+
documentation for details.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
.. toctree::
|
|
15
|
+
:maxdepth: 2
|
|
16
|
+
|
|
17
|
+
getting_started
|
|
18
|
+
io
|
|
19
|
+
graph
|
|
20
|
+
reactor
|
|
21
|
+
rule
|
|
22
|
+
references
|
|
23
|
+
|