synkit 0.0.1__tar.gz → 0.0.2__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.1 → synkit-0.0.2}/.gitignore +1 -0
- synkit-0.0.2/Data/Testcase/Compose/SingleRule/R0/0.gml +17 -0
- synkit-0.0.2/Data/Testcase/Compose/SingleRule/R0/1.gml +17 -0
- synkit-0.0.2/Data/Testcase/Compose/SingleRule/R0/2.gml +17 -0
- {synkit-0.0.1 → synkit-0.0.2}/PKG-INFO +1 -1
- synkit-0.0.2/Test/Chem/Reaction/test_rsmi_utils.py +82 -0
- synkit-0.0.2/Test/Graph/Cluster/test_batch_cluster.py +109 -0
- synkit-0.0.2/Test/Graph/Cluster/test_graph_cluster.py +136 -0
- synkit-0.0.2/Test/Graph/Cluster/test_morphism.py +117 -0
- synkit-0.0.2/Test/ITS/test_its_expand.py +19 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/ITS/test_normalize_aam.py +3 -1
- synkit-0.0.2/Test/Reactor/test_multi_steps.py +73 -0
- synkit-0.0.2/Test/Reactor/test_reactor_engine.py +209 -0
- synkit-0.0.2/Test/Reactor/test_reactor_utils.py +92 -0
- synkit-0.0.2/Test/Rule/test_molecule_rule.py +139 -0
- synkit-0.0.2/Test/Rule/test_reactor_rule.py +58 -0
- synkit-0.0.2/Test/Rule/test_rule_compose.py +53 -0
- synkit-0.0.2/Test/Rule/test_rule_rbl.py +50 -0
- synkit-0.0.2/Test/Rule/test_rule_utils.py +186 -0
- synkit-0.0.2/Test/Rule/test_valance_constrain.py +102 -0
- {synkit-0.0.1 → synkit-0.0.2}/lint.sh +1 -1
- {synkit-0.0.1 → synkit-0.0.2}/pyproject.toml +1 -1
- synkit-0.0.2/synkit/Chem/Reaction/rsmi_utils.py +100 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Reaction/standardize.py +4 -2
- synkit-0.0.2/synkit/Graph/Cluster/batch_cluster.py +222 -0
- synkit-0.0.2/synkit/Graph/Cluster/graph_cluster.py +163 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/chem_converter.py +39 -5
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/dg_to_gml.py +4 -2
- synkit-0.0.2/synkit/ITS/its_expand.py +89 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/ITS/normalize_aam.py +2 -2
- synkit-0.0.2/synkit/Metrics/_base.py +50 -0
- synkit-0.0.2/synkit/Metrics/_plot.py +122 -0
- synkit-0.0.2/synkit/Metrics/_ranking.py +174 -0
- synkit-0.0.2/synkit/Reactor/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Reactor/core_engine.py +8 -14
- synkit-0.0.2/synkit/Reactor/multi_steps.py +135 -0
- synkit-0.0.2/synkit/Reactor/reactor_engine.py +227 -0
- synkit-0.0.2/synkit/Reactor/reactor_utils.py +350 -0
- synkit-0.0.2/synkit/Rule/MaxValence.json.gz +1 -0
- synkit-0.0.2/synkit/Rule/__init__.py +0 -0
- synkit-0.0.2/synkit/Rule/molecule_rule.py +117 -0
- synkit-0.0.2/synkit/Rule/reactor_rule.py +85 -0
- synkit-0.0.2/synkit/Rule/rule_compose.py +230 -0
- synkit-0.0.2/synkit/Rule/rule_rbl.py +78 -0
- synkit-0.0.1/synkit/IO/parse_rule.py → synkit-0.0.2/synkit/Rule/rule_utils.py +19 -0
- synkit-0.0.2/synkit/Rule/strip_rule.py +94 -0
- synkit-0.0.2/synkit/Rule/valence_constrain.py +105 -0
- synkit-0.0.2/synkit/Vis/__init__.py +0 -0
- synkit-0.0.2/synkit/__init__.py +0 -0
- synkit-0.0.1/Test/Reactor/test_multi_step.py +0 -50
- synkit-0.0.1/Test/Reactor/test_multiple_step_aam.py +0 -67
- synkit-0.0.1/Test/Reactor/test_reagent.py +0 -58
- synkit-0.0.1/synkit/ITS/partial_expand.py +0 -170
- synkit-0.0.1/synkit/Reactor/inference.py +0 -73
- synkit-0.0.1/synkit/Reactor/multi_step.py +0 -227
- synkit-0.0.1/synkit/Reactor/multi_step_aam.py +0 -82
- synkit-0.0.1/synkit/Reactor/reagent.py +0 -95
- synkit-0.0.1/synkit/Reactor/rule_apply.py +0 -81
- {synkit-0.0.1 → synkit-0.0.2}/.github/workflows/publish-package.yml +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/.github/workflows/test-and-lint.yml +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/CHANGELOG.md +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Data/Figure/synkit.png +0 -0
- /synkit-0.0.1/Test/Chem/Fingerprint/__init__.py → /synkit-0.0.2/Data/Testcase/Compose/ComposeRule/data.txt +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Data/Testcase/mech.json.gz +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/LICENSE +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/README.md +0 -0
- {synkit-0.0.1/Test/Chem/Molecule → synkit-0.0.2/Test/Chem/Fingerprint}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Fingerprint/test_fp_calculator.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Fingerprint/test_smiles_featurizer.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Fingerprint/test_transformation_fp.py +0 -0
- {synkit-0.0.1/Test/Chem/Reaction → synkit-0.0.2/Test/Chem/Molecule}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Molecule/test_standardize.py +0 -0
- {synkit-0.0.1/Test/Chem → synkit-0.0.2/Test/Chem/Reaction}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Reaction/test_balance_checker.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Reaction/test_cleanning.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Reaction/test_deionize.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Reaction/test_neutralize.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Reaction/test_reagent.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Reaction/test_standardize.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Chem/Reaction/test_tautomerize.py +0 -0
- {synkit-0.0.1/Test/Graph/Cluster → synkit-0.0.2/Test/Chem}/__init__.py +0 -0
- {synkit-0.0.1/Test/Graph/Feature → synkit-0.0.2/Test/Graph/Cluster}/__init__.py +0 -0
- {synkit-0.0.1/Test/Graph → synkit-0.0.2/Test/Graph/Feature}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Graph/Feature/test_graph_descriptors.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Graph/Feature/test_graph_fps.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Graph/Feature/test_graph_signature.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Graph/Feature/test_hash_fps.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Graph/Feature/test_morgan_fps.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Graph/Feature/test_path_fps.py +0 -0
- {synkit-0.0.1/Test/IO → synkit-0.0.2/Test/Graph}/__init__.py +0 -0
- {synkit-0.0.1/Test/ITS → synkit-0.0.2/Test/IO}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/IO/test_chemical_conversion.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/IO/test_gml_to_nx.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/IO/test_graph_to_mol.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/IO/test_mol_to_graph.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/IO/test_nx_to_gml.py +0 -0
- {synkit-0.0.1/Test/Reactor → synkit-0.0.2/Test/ITS}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/ITS/test_aam_validator.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/ITS/test_its_construction.py +0 -0
- {synkit-0.0.1/Test/Vis → synkit-0.0.2/Test/Reactor}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Reactor/test_core_engine.py +0 -0
- {synkit-0.0.1/Test → synkit-0.0.2/Test/Rule}/__init__.py +0 -0
- {synkit-0.0.1/synkit/Chem/Fingerprint → synkit-0.0.2/Test/Vis}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/Test/Vis/test_embedding.py +0 -0
- {synkit-0.0.1/synkit/Chem/Molecule → synkit-0.0.2/Test}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/pytest.sh +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/requirements.txt +0 -0
- {synkit-0.0.1/synkit/Chem/Reaction → synkit-0.0.2/synkit/Chem/Fingerprint}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
- {synkit-0.0.1/synkit/Graph/Cluster → synkit-0.0.2/synkit/Chem/Molecule}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Molecule/standardize.py +0 -0
- {synkit-0.0.1/synkit/Graph/Feature → synkit-0.0.2/synkit/Chem/Reaction}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Reaction/balance_check.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Reaction/cleanning.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Reaction/deionize.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Reaction/neutralize.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Reaction/reagent.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Chem/Reaction/tautomerize.py +0 -0
- {synkit-0.0.1/synkit/IO → synkit-0.0.2/synkit/Graph/Cluster}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Graph/Cluster/morphism.py +0 -0
- {synkit-0.0.1/synkit/Reactor → synkit-0.0.2/synkit/Graph/Feature}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Graph/Feature/graph_descriptors.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Graph/Feature/graph_fps.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Graph/Feature/graph_signature.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Graph/Feature/hash_fps.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Graph/Feature/morgan_fps.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Graph/Feature/path_fps.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Graph/__init.py +0 -0
- {synkit-0.0.1/synkit/Vis → synkit-0.0.2/synkit/IO}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/data_io.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/data_process.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/debug.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/gml_to_nx.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/graph_to_mol.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/mol_to_graph.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/nx_to_gml.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/IO/smiles_to_id.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/ITS/_misc.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/ITS/aam_validator.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/ITS/its_builder.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/ITS/its_construction.py +0 -0
- {synkit-0.0.1/synkit → synkit-0.0.2/synkit/Metrics}/__init__.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Vis/chemical_graph_visualizer.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Vis/chemical_reaction_visualizer.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Vis/chemical_space.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Vis/embedding.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Vis/graph_visualizer.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Vis/pdf_writer.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/Vis/rsmi_to_fig.py +0 -0
- {synkit-0.0.1 → synkit-0.0.2}/synkit/_misc.py +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
rule [
|
|
2
|
+
ruleID "0"
|
|
3
|
+
left [
|
|
4
|
+
edge [ source 1 target 2 label "-" ]
|
|
5
|
+
edge [ source 3 target 4 label "-" ]
|
|
6
|
+
]
|
|
7
|
+
context [
|
|
8
|
+
node [ id 1 label "H" ]
|
|
9
|
+
node [ id 2 label "N" ]
|
|
10
|
+
node [ id 3 label "C" ]
|
|
11
|
+
node [ id 4 label "Br" ]
|
|
12
|
+
]
|
|
13
|
+
right [
|
|
14
|
+
edge [ source 1 target 4 label "-" ]
|
|
15
|
+
edge [ source 2 target 3 label "-" ]
|
|
16
|
+
]
|
|
17
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
rule [
|
|
2
|
+
ruleID "1"
|
|
3
|
+
left [
|
|
4
|
+
edge [ source 1 target 2 label "-" ]
|
|
5
|
+
edge [ source 3 target 4 label "-" ]
|
|
6
|
+
]
|
|
7
|
+
context [
|
|
8
|
+
node [ id 1 label "Br" ]
|
|
9
|
+
node [ id 2 label "C" ]
|
|
10
|
+
node [ id 3 label "O" ]
|
|
11
|
+
node [ id 4 label "H" ]
|
|
12
|
+
]
|
|
13
|
+
right [
|
|
14
|
+
edge [ source 1 target 4 label "-" ]
|
|
15
|
+
edge [ source 2 target 3 label "-" ]
|
|
16
|
+
]
|
|
17
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
rule [
|
|
2
|
+
ruleID "2"
|
|
3
|
+
left [
|
|
4
|
+
edge [ source 1 target 2 label "-" ]
|
|
5
|
+
edge [ source 3 target 4 label "-" ]
|
|
6
|
+
]
|
|
7
|
+
context [
|
|
8
|
+
node [ id 1 label "C" ]
|
|
9
|
+
node [ id 2 label "Cl" ]
|
|
10
|
+
node [ id 3 label "N" ]
|
|
11
|
+
node [ id 4 label "H" ]
|
|
12
|
+
]
|
|
13
|
+
right [
|
|
14
|
+
edge [ source 1 target 3 label "-" ]
|
|
15
|
+
edge [ source 2 target 4 label "-" ]
|
|
16
|
+
]
|
|
17
|
+
]
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from synkit.Chem.Reaction.rsmi_utils import (
|
|
3
|
+
remove_common_reagents,
|
|
4
|
+
reverse_reaction,
|
|
5
|
+
remove_duplicates,
|
|
6
|
+
merge_reaction,
|
|
7
|
+
find_longest_fragment,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestChemicalReactions(unittest.TestCase):
|
|
12
|
+
|
|
13
|
+
def test_remove_common_reagents_no_common(self):
|
|
14
|
+
reaction = "A.B.C>>D.E.F"
|
|
15
|
+
expected_result = "A.B.C>>D.E.F"
|
|
16
|
+
result = remove_common_reagents(reaction)
|
|
17
|
+
self.assertEqual(result, expected_result)
|
|
18
|
+
|
|
19
|
+
def test_remove_common_reagents_with_common(self):
|
|
20
|
+
reaction = "A.B.C>>A.D.E"
|
|
21
|
+
expected_result = "B.C>>D.E"
|
|
22
|
+
result = remove_common_reagents(reaction)
|
|
23
|
+
self.assertEqual(result, expected_result)
|
|
24
|
+
|
|
25
|
+
def test_remove_common_reagents_all_common(self):
|
|
26
|
+
reaction = "A.B.C>>A.B.C"
|
|
27
|
+
expected_result = ">>"
|
|
28
|
+
result = remove_common_reagents(reaction)
|
|
29
|
+
self.assertEqual(result, expected_result)
|
|
30
|
+
|
|
31
|
+
def test_remove_duplicates(self):
|
|
32
|
+
input_list = ["CC", "C", "CC", "CCO", "C"]
|
|
33
|
+
expected_result = ["CC", "C", "CCO"]
|
|
34
|
+
result = remove_duplicates(input_list)
|
|
35
|
+
self.assertEqual(result, expected_result)
|
|
36
|
+
|
|
37
|
+
def test_reverse_reaction(self):
|
|
38
|
+
reaction_smiles = "C=C.O>>CCO"
|
|
39
|
+
expected_result = "CCO>>C=C.O"
|
|
40
|
+
result = reverse_reaction(reaction_smiles)
|
|
41
|
+
self.assertEqual(result, expected_result)
|
|
42
|
+
|
|
43
|
+
def test_merge_reaction(self):
|
|
44
|
+
rsmi_1 = "CCC(=O)OC.O>>CO.CCOC(=O)O"
|
|
45
|
+
rsmi_2 = "CCC(=O)O.CCO>>O.CCOC(=O)CC"
|
|
46
|
+
expected_result = "CCC(=O)OC.O.CCC(=O)O.CCO>>CO.CCOC(=O)O.O.CCOC(=O)CC"
|
|
47
|
+
result = merge_reaction(rsmi_1, rsmi_2)
|
|
48
|
+
self.assertEqual(result, expected_result)
|
|
49
|
+
|
|
50
|
+
def test_find_longest_fragment(self):
|
|
51
|
+
input_list = ["CCOC(=O)O", "O"]
|
|
52
|
+
expected_result = "CCOC(=O)O"
|
|
53
|
+
result = find_longest_fragment(input_list)
|
|
54
|
+
self.assertEqual(result, expected_result)
|
|
55
|
+
|
|
56
|
+
# Additional robustness for empty inputs or specific edge cases.
|
|
57
|
+
def test_remove_duplicates_empty(self):
|
|
58
|
+
input_list = []
|
|
59
|
+
expected_result = []
|
|
60
|
+
result = remove_duplicates(input_list)
|
|
61
|
+
self.assertEqual(result, expected_result)
|
|
62
|
+
|
|
63
|
+
def test_reverse_reaction_empty(self):
|
|
64
|
+
reaction_smiles = ">>"
|
|
65
|
+
expected_result = ">>"
|
|
66
|
+
result = reverse_reaction(reaction_smiles)
|
|
67
|
+
self.assertEqual(result, expected_result)
|
|
68
|
+
|
|
69
|
+
def test_merge_reaction_empty(self):
|
|
70
|
+
rsmi_1 = ">>"
|
|
71
|
+
rsmi_2 = ">>"
|
|
72
|
+
result = merge_reaction(rsmi_1, rsmi_2)
|
|
73
|
+
self.assertIsNone(result)
|
|
74
|
+
|
|
75
|
+
def test_find_longest_fragment_empty(self):
|
|
76
|
+
input_list = []
|
|
77
|
+
result = find_longest_fragment(input_list)
|
|
78
|
+
self.assertIsNone(result)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == "__main__":
|
|
82
|
+
unittest.main()
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import unittest
|
|
3
|
+
from synkit.IO.data_io import load_from_pickle
|
|
4
|
+
from synkit.Graph.Feature.graph_signature import GraphSignature
|
|
5
|
+
from synkit.Graph.Cluster.batch_cluster import BatchCluster
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestBatchCluster(unittest.TestCase):
|
|
9
|
+
@classmethod
|
|
10
|
+
def setUpClass(cls):
|
|
11
|
+
cls.graphs = load_from_pickle("Data/Testcase/graph.pkl.gz")
|
|
12
|
+
cls.templates = None
|
|
13
|
+
for value in cls.graphs:
|
|
14
|
+
value["rc_sig"] = GraphSignature(value["RC"]).create_graph_signature()
|
|
15
|
+
value["its_sig"] = GraphSignature(value["ITS"]).create_graph_signature()
|
|
16
|
+
|
|
17
|
+
def test_initialization(self):
|
|
18
|
+
"""Test initialization and verify if the attributes are set correctly."""
|
|
19
|
+
cluster = BatchCluster(["element", "charge"], ["*", 0], "bond_order")
|
|
20
|
+
self.assertEqual(cluster.nodeLabelNames, ["element", "charge"])
|
|
21
|
+
self.assertEqual(cluster.nodeLabelDefault, ["*", 0])
|
|
22
|
+
self.assertEqual(cluster.edgeAttribute, "bond_order")
|
|
23
|
+
|
|
24
|
+
def test_initialization_failure(self):
|
|
25
|
+
"""Test initialization failure when lengths of node labels and defaults do not match."""
|
|
26
|
+
with self.assertRaises(ValueError):
|
|
27
|
+
BatchCluster(["element"], ["*", 0, 1], "bond_order")
|
|
28
|
+
|
|
29
|
+
def test_batch_dicts(self):
|
|
30
|
+
"""Test the batching function to split data correctly."""
|
|
31
|
+
batch_cluster = BatchCluster(["element", "charge"], ["*", 0], "bond_order")
|
|
32
|
+
input_list = [{"id": i} for i in range(10)]
|
|
33
|
+
batches = batch_cluster.batch_dicts(input_list, 3)
|
|
34
|
+
self.assertEqual(len(batches), 4)
|
|
35
|
+
self.assertEqual(len(batches[0]), 3)
|
|
36
|
+
self.assertEqual(len(batches[-1]), 1)
|
|
37
|
+
|
|
38
|
+
def test_lib_check_functionality(self):
|
|
39
|
+
"""Test the lib_check method using directly comparable results."""
|
|
40
|
+
cluster = BatchCluster()
|
|
41
|
+
batch_1 = self.graphs[:50]
|
|
42
|
+
batch_2 = self.graphs[50:]
|
|
43
|
+
_, templates = cluster.fit(batch_1, None, "RC", "rc_sig")
|
|
44
|
+
for entry in batch_2:
|
|
45
|
+
_, templates = cluster.lib_check(entry, templates, "RC", "rc_sig")
|
|
46
|
+
self.assertEqual(len(templates), 30)
|
|
47
|
+
|
|
48
|
+
def test_cluster_integration(self):
|
|
49
|
+
"""Test the cluster method to ensure it processes data entries correctly."""
|
|
50
|
+
cluster = BatchCluster()
|
|
51
|
+
expected_template_count = 30
|
|
52
|
+
_, updated_templates = cluster.cluster(self.graphs, [], "RC", "rc_sig")
|
|
53
|
+
|
|
54
|
+
self.assertEqual(
|
|
55
|
+
len(updated_templates),
|
|
56
|
+
expected_template_count,
|
|
57
|
+
f"Failed: expected {expected_template_count} templates, got {len(updated_templates)}",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def test_fit(self):
|
|
61
|
+
cluster = BatchCluster()
|
|
62
|
+
batch_sizes = [None, 10]
|
|
63
|
+
expected_template_count = 30
|
|
64
|
+
|
|
65
|
+
for batch_size in batch_sizes:
|
|
66
|
+
start_time = time.time()
|
|
67
|
+
_, updated_templates = cluster.fit(
|
|
68
|
+
self.graphs, self.templates, "RC", "rc_sig", batch_size=batch_size
|
|
69
|
+
)
|
|
70
|
+
elapsed_time = time.time() - start_time
|
|
71
|
+
|
|
72
|
+
self.assertEqual(
|
|
73
|
+
len(updated_templates),
|
|
74
|
+
expected_template_count,
|
|
75
|
+
f"Failed for batch_size={batch_size}: expected "
|
|
76
|
+
+ f"{expected_template_count} templates, got {len(updated_templates)}",
|
|
77
|
+
)
|
|
78
|
+
print(
|
|
79
|
+
f"Test for batch_size={batch_size} completed in {elapsed_time:.2f} seconds."
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def test_fit_gml(self):
|
|
83
|
+
cluster = BatchCluster()
|
|
84
|
+
batch_sizes = [None, 10]
|
|
85
|
+
expected_template_count = (
|
|
86
|
+
30 # Assuming this is the expected number of templates after processing
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
for batch_size in batch_sizes:
|
|
90
|
+
start_time = time.time()
|
|
91
|
+
_, updated_templates = cluster.fit(
|
|
92
|
+
self.graphs, self.templates, "RC", "rc_sig", batch_size=batch_size
|
|
93
|
+
)
|
|
94
|
+
elapsed_time = time.time() - start_time
|
|
95
|
+
|
|
96
|
+
self.assertEqual(
|
|
97
|
+
len(updated_templates),
|
|
98
|
+
expected_template_count,
|
|
99
|
+
f"Failed for batch_size={batch_size}: expected"
|
|
100
|
+
+ f" {expected_template_count} templates, got {len(updated_templates)}",
|
|
101
|
+
)
|
|
102
|
+
print(
|
|
103
|
+
f"Test for batch_size={batch_size} completed in {elapsed_time:.2f} seconds."
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# To run the tests
|
|
108
|
+
if __name__ == "__main__":
|
|
109
|
+
unittest.main()
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import unittest
|
|
3
|
+
from synkit.IO.data_io import load_from_pickle
|
|
4
|
+
from synkit.Graph.Cluster.graph_cluster import GraphCluster
|
|
5
|
+
from synkit.Graph.Feature.graph_descriptors import GraphDescriptor
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestRCCluster(unittest.TestCase):
|
|
9
|
+
|
|
10
|
+
@classmethod
|
|
11
|
+
def setUpClass(cls):
|
|
12
|
+
# Load data once for all tests
|
|
13
|
+
cls.graphs = load_from_pickle("Data/Testcase/graph.pkl.gz")
|
|
14
|
+
for value in cls.graphs:
|
|
15
|
+
value = GraphDescriptor.get_descriptors(value)
|
|
16
|
+
cls.clusterer = GraphCluster()
|
|
17
|
+
|
|
18
|
+
def test_initialization(self):
|
|
19
|
+
"""Test the initialization and configuration of the RCCluster."""
|
|
20
|
+
self.assertIsInstance(self.clusterer.nodeLabelNames, list)
|
|
21
|
+
self.assertEqual(self.clusterer.edgeAttribute, "order")
|
|
22
|
+
self.assertEqual(
|
|
23
|
+
len(self.clusterer.nodeLabelNames), len(self.clusterer.nodeLabelDefault)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def test_auto_cluster(self):
|
|
27
|
+
"""Test the auto_cluster method functionality."""
|
|
28
|
+
rc = [value["RC"] for value in self.graphs]
|
|
29
|
+
cycles = [value["cycle"] for value in self.graphs]
|
|
30
|
+
signature = [value["signature_rc"] for value in self.graphs]
|
|
31
|
+
atom_count = [value["atom_count"] for value in self.graphs]
|
|
32
|
+
for att in [None, cycles, signature, atom_count]:
|
|
33
|
+
clusters, graph_to_cluster = self.clusterer.iterative_cluster(
|
|
34
|
+
rc,
|
|
35
|
+
att,
|
|
36
|
+
nodeMatch=self.clusterer.nodeMatch,
|
|
37
|
+
edgeMatch=self.clusterer.edgeMatch,
|
|
38
|
+
)
|
|
39
|
+
self.assertIsInstance(clusters, list)
|
|
40
|
+
self.assertIsInstance(graph_to_cluster, dict)
|
|
41
|
+
self.assertEqual(len(clusters), 30)
|
|
42
|
+
|
|
43
|
+
def test_auto_cluster_wrong_isomorphism(self):
|
|
44
|
+
rc = [value["RC"] for value in self.graphs]
|
|
45
|
+
cycles = [value["cycle"] for value in self.graphs]
|
|
46
|
+
signature = [value["signature_rc"] for value in self.graphs]
|
|
47
|
+
atom_count = [value["atom_count"] for value in self.graphs]
|
|
48
|
+
|
|
49
|
+
# cluster all
|
|
50
|
+
clusters, _ = self.clusterer.iterative_cluster(
|
|
51
|
+
rc, None, nodeMatch=None, edgeMatch=None
|
|
52
|
+
)
|
|
53
|
+
self.assertEqual(len(clusters), 8) # wrong value
|
|
54
|
+
|
|
55
|
+
# cluster with cycle
|
|
56
|
+
clusters, _ = self.clusterer.iterative_cluster(
|
|
57
|
+
rc, cycles, nodeMatch=None, edgeMatch=None
|
|
58
|
+
)
|
|
59
|
+
self.assertEqual(len(clusters), 8) # wrong value
|
|
60
|
+
|
|
61
|
+
# cluster with atom_count
|
|
62
|
+
clusters, _ = self.clusterer.iterative_cluster(
|
|
63
|
+
rc, atom_count, nodeMatch=None, edgeMatch=None
|
|
64
|
+
)
|
|
65
|
+
self.assertEqual(len(clusters), 27) # wrong value but almost correct
|
|
66
|
+
|
|
67
|
+
# cluster with signature
|
|
68
|
+
clusters, _ = self.clusterer.iterative_cluster(
|
|
69
|
+
rc, signature, nodeMatch=None, edgeMatch=None
|
|
70
|
+
)
|
|
71
|
+
self.assertEqual(len(clusters), 30) # correct by some magic. No proof for this
|
|
72
|
+
|
|
73
|
+
def test_fit(self):
|
|
74
|
+
"""Test the fit method to ensure it correctly updates data entries with cluster indices."""
|
|
75
|
+
|
|
76
|
+
clustered_data = self.clusterer.fit(
|
|
77
|
+
self.graphs, rule_key="RC", attribute_key="atom_count"
|
|
78
|
+
)
|
|
79
|
+
max_class = 0
|
|
80
|
+
for item in clustered_data:
|
|
81
|
+
print(item["class"])
|
|
82
|
+
max_class = item["class"] if item["class"] >= max_class else max_class
|
|
83
|
+
# print(max_class)
|
|
84
|
+
self.assertIn("class", item)
|
|
85
|
+
self.assertEqual(max_class, 29) # 30 classes start from 0 so max is 29
|
|
86
|
+
|
|
87
|
+
def test_fit_gml(self):
|
|
88
|
+
"""Test the fit method to ensure it correctly updates data entries with cluster indices."""
|
|
89
|
+
|
|
90
|
+
clustered_data = self.clusterer.fit(
|
|
91
|
+
self.graphs, rule_key="rc", attribute_key="atom_count"
|
|
92
|
+
)
|
|
93
|
+
max_class = 0
|
|
94
|
+
for item in clustered_data:
|
|
95
|
+
print(item["class"])
|
|
96
|
+
max_class = item["class"] if item["class"] >= max_class else max_class
|
|
97
|
+
# print(max_class)
|
|
98
|
+
self.assertIn("class", item)
|
|
99
|
+
self.assertEqual(max_class, 29) # 30 classes start from 0 so max is 29
|
|
100
|
+
|
|
101
|
+
def test_fit_time_compare(self):
|
|
102
|
+
attributes = {
|
|
103
|
+
"None": None,
|
|
104
|
+
"Cycles": "cycle",
|
|
105
|
+
"Signature": "signature_rc",
|
|
106
|
+
"Atom_count": "atom_count",
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
results = {}
|
|
110
|
+
for name, attr in attributes.items():
|
|
111
|
+
start_time = time.time()
|
|
112
|
+
clustered_data = self.clusterer.fit(
|
|
113
|
+
self.graphs, rule_key="RC", attribute_key=attr
|
|
114
|
+
)
|
|
115
|
+
elapsed_time = time.time() - start_time
|
|
116
|
+
|
|
117
|
+
# Optionally print out class information or verify correctness
|
|
118
|
+
max_class = max(item["class"] for item in clustered_data if "class" in item)
|
|
119
|
+
|
|
120
|
+
results[name] = elapsed_time
|
|
121
|
+
|
|
122
|
+
# Basic verification that 'class' is assigned and max class is as expected
|
|
123
|
+
self.assertTrue(all("class" in item for item in clustered_data))
|
|
124
|
+
self.assertEqual(
|
|
125
|
+
max_class, 29
|
|
126
|
+
) # Ensure the maximum class index is as expected
|
|
127
|
+
|
|
128
|
+
# Compare results to check which attribute took the least/most time
|
|
129
|
+
min_time_attr = min(results, key=results.get)
|
|
130
|
+
max_time_attr = max(results, key=results.get)
|
|
131
|
+
self.assertIn(min_time_attr, ["Atom_count", "Signature"])
|
|
132
|
+
self.assertIn(max_time_attr, ["None", "Cycles"])
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
if __name__ == "__main__":
|
|
136
|
+
unittest.main()
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from synkit.IO.data_io import load_from_pickle
|
|
3
|
+
from synkit.Graph.Cluster.morphism import graph_isomorphism, rule_isomorphism
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestRule(unittest.TestCase):
|
|
7
|
+
|
|
8
|
+
def setUp(self):
|
|
9
|
+
self.graphs = load_from_pickle("Data/Testcase/graph.pkl.gz")
|
|
10
|
+
|
|
11
|
+
self.small = """rule [
|
|
12
|
+
ruleID "Small"
|
|
13
|
+
left [
|
|
14
|
+
node [ id 1 label "H" ]
|
|
15
|
+
node [ id 2 label "O" ]
|
|
16
|
+
edge [ source 1 target 2 label "-" ]
|
|
17
|
+
]
|
|
18
|
+
right [
|
|
19
|
+
node [ id 1 label "H+" ]
|
|
20
|
+
node [ id 2 label "O-" ]
|
|
21
|
+
]
|
|
22
|
+
]"""
|
|
23
|
+
self.large = """rule [
|
|
24
|
+
ruleID "Large"
|
|
25
|
+
left [
|
|
26
|
+
node [ id 1 label "H" ]
|
|
27
|
+
node [ id 2 label "O" ]
|
|
28
|
+
edge [ source 1 target 2 label "-" ]
|
|
29
|
+
]
|
|
30
|
+
context [
|
|
31
|
+
node [ id 3 label "C" ]
|
|
32
|
+
edge [ source 2 target 3 label "-" ]
|
|
33
|
+
]
|
|
34
|
+
right [
|
|
35
|
+
node [ id 1 label "H+" ]
|
|
36
|
+
node [ id 2 label "O-" ]
|
|
37
|
+
]
|
|
38
|
+
]"""
|
|
39
|
+
|
|
40
|
+
self.gml = (
|
|
41
|
+
"rule [\n"
|
|
42
|
+
' ruleID "rule"\n'
|
|
43
|
+
" left [\n"
|
|
44
|
+
' edge [ source 1 target 4 label "-" ]\n'
|
|
45
|
+
' edge [ source 1 target 2 label "-" ]\n'
|
|
46
|
+
' edge [ source 2 target 3 label "-" ]\n'
|
|
47
|
+
" ]\n"
|
|
48
|
+
" context [\n"
|
|
49
|
+
' node [ id 1 label "C" ]\n'
|
|
50
|
+
' node [ id 4 label "H" ]\n'
|
|
51
|
+
' node [ id 2 label "C" ]\n'
|
|
52
|
+
' node [ id 3 label "O" ]\n'
|
|
53
|
+
" ]\n"
|
|
54
|
+
" right [\n"
|
|
55
|
+
' edge [ source 1 target 2 label "=" ]\n'
|
|
56
|
+
' edge [ source 4 target 3 label "-" ]\n'
|
|
57
|
+
" ]\n"
|
|
58
|
+
"]"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
self.gml_h = (
|
|
62
|
+
"rule [\n"
|
|
63
|
+
' ruleID "rule"\n'
|
|
64
|
+
" left [\n"
|
|
65
|
+
' edge [ source 1 target 2 label "-" ]\n'
|
|
66
|
+
' edge [ source 1 target 3 label "-" ]\n'
|
|
67
|
+
' edge [ source 3 target 4 label "-" ]\n'
|
|
68
|
+
" ]\n"
|
|
69
|
+
" context [\n"
|
|
70
|
+
' node [ id 1 label "C" ]\n'
|
|
71
|
+
' node [ id 2 label "H" ]\n'
|
|
72
|
+
' node [ id 3 label "C" ]\n'
|
|
73
|
+
' node [ id 4 label "O" ]\n'
|
|
74
|
+
' node [ id 5 label "H" ]\n'
|
|
75
|
+
' node [ id 6 label "H" ]\n'
|
|
76
|
+
' node [ id 7 label "H" ]\n'
|
|
77
|
+
' node [ id 8 label "H" ]\n'
|
|
78
|
+
' node [ id 9 label "H" ]\n'
|
|
79
|
+
' edge [ source 1 target 5 label "-" ]\n'
|
|
80
|
+
' edge [ source 1 target 6 label "-" ]\n'
|
|
81
|
+
' edge [ source 3 target 7 label "-" ]\n'
|
|
82
|
+
' edge [ source 3 target 8 label "-" ]\n'
|
|
83
|
+
' edge [ source 4 target 9 label "-" ]\n'
|
|
84
|
+
" ]\n"
|
|
85
|
+
" right [\n"
|
|
86
|
+
' edge [ source 1 target 3 label "=" ]\n'
|
|
87
|
+
' edge [ source 2 target 4 label "-" ]\n'
|
|
88
|
+
" ]\n"
|
|
89
|
+
"]"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def test_graph_isomorphism_true(self):
|
|
93
|
+
result = graph_isomorphism(
|
|
94
|
+
self.graphs[0]["RC"], self.graphs[3]["RC"], use_defaults=True
|
|
95
|
+
)
|
|
96
|
+
self.assertTrue(result)
|
|
97
|
+
|
|
98
|
+
def test_graph_isomorphism_false(self):
|
|
99
|
+
result = graph_isomorphism(
|
|
100
|
+
self.graphs[0]["RC"], self.graphs[1]["RC"], use_defaults=True
|
|
101
|
+
)
|
|
102
|
+
self.assertFalse(result)
|
|
103
|
+
|
|
104
|
+
def test_rule_isomorphism_isomorphism(self):
|
|
105
|
+
self.assertTrue(rule_isomorphism(self.small, self.small))
|
|
106
|
+
self.assertTrue(rule_isomorphism(self.large, self.large))
|
|
107
|
+
self.assertFalse(rule_isomorphism(self.small, self.large))
|
|
108
|
+
|
|
109
|
+
def test_rule_isomorphism_monomorphism(self):
|
|
110
|
+
# small is a subgraph of large
|
|
111
|
+
self.assertTrue(rule_isomorphism(self.small, self.large, "monomorphism"))
|
|
112
|
+
# large is not a subgraph of small
|
|
113
|
+
self.assertFalse(rule_isomorphism(self.large, self.small, "monomorphism"))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if __name__ == "__main__":
|
|
117
|
+
unittest.main()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from synkit.ITS.aam_validator import AAMValidator
|
|
3
|
+
from synkit.ITS.its_expand import ITSExpand
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestPartialExpand(unittest.TestCase):
|
|
7
|
+
|
|
8
|
+
def test_expand_aam_with_its(self):
|
|
9
|
+
input_rsmi = "CC[CH2:3][Cl:1].[NH2:2][H:4]>>CC[CH2:3][NH2:2].[Cl:1][H:4]"
|
|
10
|
+
output_rsmi = ITSExpand.expand_aam_with_its(input_rsmi, use_G=True)
|
|
11
|
+
expected_rsmi = (
|
|
12
|
+
"[CH3:1][CH2:2][CH2:3][Cl:4].[NH2:5][H:6]"
|
|
13
|
+
+ ">>[CH3:1][CH2:2][CH2:3][NH2:5].[Cl:4][H:6]"
|
|
14
|
+
)
|
|
15
|
+
self.assertTrue(AAMValidator.smiles_check(output_rsmi, expected_rsmi, "ITS"))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
unittest.main()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
import networkx as nx
|
|
3
3
|
from synkit.ITS.normalize_aam import NormalizeAAM
|
|
4
|
+
from synkit.ITS.aam_validator import AAMValidator
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class TestNormalizeAAM(unittest.TestCase):
|
|
@@ -55,7 +56,8 @@ class TestNormalizeAAM(unittest.TestCase):
|
|
|
55
56
|
+ "([CH3:4])[H:6])[H:5]"
|
|
56
57
|
)
|
|
57
58
|
result = self.normalizer.fit(input_rsmi)
|
|
58
|
-
|
|
59
|
+
print(result)
|
|
60
|
+
self.assertTrue(AAMValidator().smiles_check(result, expected_output))
|
|
59
61
|
|
|
60
62
|
|
|
61
63
|
# Run the unittest
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from synkit.IO.data_io import load_database
|
|
3
|
+
from synkit.Chem.Reaction.standardize import Standardize
|
|
4
|
+
from synkit.IO.chem_converter import smart_to_gml
|
|
5
|
+
from synkit.Reactor.reactor_utils import _add_reagent, _find_all_paths
|
|
6
|
+
from synkit.Reactor.multi_steps import MultiSteps
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestMultiStep(unittest.TestCase):
|
|
10
|
+
def setUp(self) -> None:
|
|
11
|
+
smarts = [
|
|
12
|
+
"[CH2:4]([CH:5]=[O:6])[H:7]>>[CH2:4]=[CH:5][O:6][H:7]",
|
|
13
|
+
(
|
|
14
|
+
"[CH2:2]=[O:3].[CH2:4]=[CH:5][O:6][H:7]>>[CH2:2]([O:3][H:7])[CH2:4]"
|
|
15
|
+
+ "[CH:5]=[O:6]"
|
|
16
|
+
),
|
|
17
|
+
"[CH2:4]([CH:5]=[O:6])[H:8]>>[CH2:4]=[CH:5][O:6][H:8]",
|
|
18
|
+
(
|
|
19
|
+
"[CH2:2]([OH:3])[CH:4]=[CH:5][O:6][H:8]>>[CH2:2]=[CH:4][CH:5]=[O:6]"
|
|
20
|
+
+ ".[OH:3][H:8]"
|
|
21
|
+
),
|
|
22
|
+
]
|
|
23
|
+
self.gml = [smart_to_gml(value) for value in smarts]
|
|
24
|
+
self.order = [0, 1, 0, -1]
|
|
25
|
+
self.rsmi = "CC=O.CC=O.CCC=O>>CC=O.CC=C(C)C=O.O"
|
|
26
|
+
self.data = load_database("Data/Testcase/mech.json.gz")
|
|
27
|
+
self.rsmi_2 = Standardize().fit(self.data[0]["reaction"])
|
|
28
|
+
|
|
29
|
+
def test_perform_multi_step_reaction(self):
|
|
30
|
+
results, _ = MultiSteps._process(self.gml, self.order, self.rsmi)
|
|
31
|
+
self.assertEqual(len(results), 4)
|
|
32
|
+
|
|
33
|
+
def test_get_aam(self):
|
|
34
|
+
test = self.data[0]["mechanisms"][2]
|
|
35
|
+
rule = [
|
|
36
|
+
smart_to_gml(value["smart_string"], core=True, explicit_hydrogen=True)
|
|
37
|
+
for value in test["steps"]
|
|
38
|
+
]
|
|
39
|
+
order = list(range(len(rule)))
|
|
40
|
+
rsmi = _add_reagent(self.rsmi, [test["cat"]])
|
|
41
|
+
|
|
42
|
+
results, reaction_tree = MultiSteps._process(rule, order, rsmi)
|
|
43
|
+
target_products = sorted(rsmi.split(">>")[1].split("."))
|
|
44
|
+
max_depth = len(results)
|
|
45
|
+
all_paths = _find_all_paths(reaction_tree, target_products, rsmi, max_depth)
|
|
46
|
+
real_path = all_paths[0][1:] # remove the original
|
|
47
|
+
all_steps = MultiSteps._get_aam(real_path, rule, order)
|
|
48
|
+
self.assertTrue(
|
|
49
|
+
all(m is not None for m in all_steps),
|
|
50
|
+
"All mechanism steps should have valid mappings",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
self.assertEqual(len(all_steps), len(test["steps"]))
|
|
54
|
+
|
|
55
|
+
def test_multi_steps(self):
|
|
56
|
+
test = self.data[0]["mechanisms"][2]
|
|
57
|
+
rule = [
|
|
58
|
+
smart_to_gml(value["smart_string"], core=True, explicit_hydrogen=True)
|
|
59
|
+
for value in test["steps"]
|
|
60
|
+
]
|
|
61
|
+
order = list(range(len(rule)))
|
|
62
|
+
all_steps = MultiSteps().multi_step(self.rsmi, rule, order, test["cat"])
|
|
63
|
+
print(all_steps)
|
|
64
|
+
self.assertTrue(
|
|
65
|
+
all(m is not None for m in all_steps),
|
|
66
|
+
"All mechanism steps should have valid mappings",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
self.assertEqual(len(all_steps), len(test["steps"]))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
unittest.main()
|