Skip to content
This repository was archived by the owner on Mar 21, 2025. It is now read-only.

Commit a8a6d67

Browse files
authored
Prepare release 0.0.13 (#14)
* update * test mod compatible * add graph visualizer * fix lint * add copy right for FGUtils * prepare release * add partial map expansion * add testcase for partial expansion ver1 * update new features * prepare release * prepare release * fix dependency * fix bug
1 parent 965ab58 commit a8a6d67

File tree

8 files changed

+519
-134
lines changed

8 files changed

+519
-134
lines changed

Test/SynGraph/Descriptor/test_graph_signature.py

Lines changed: 77 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,43 +10,92 @@ def setUp(self):
1010
data = load_from_pickle("Data/test.pkl.gz")
1111
self.rc = data[0]["GraphRules"][2]
1212
self.its = data[0]["ITSGraph"][2]
13+
self.graph_signature = GraphSignature(self.its)
1314

14-
def test_create_topology_signature(self):
15-
signature = GraphSignature(self.rc)
16-
self.assertEqual(
17-
signature.create_topology_signature(
18-
topo="Single Cyclic", cycle=[4], rstep=1
19-
),
20-
"114",
15+
def test_validate_graph(self):
16+
"""Test the validation of graph structure"""
17+
# Test should pass if graph is valid (no exceptions)
18+
try:
19+
self.graph_signature._validate_graph()
20+
except ValueError as e:
21+
self.fail(f"Graph validation failed: {str(e)}")
22+
23+
def test_edge_signature(self):
24+
"""Test edge signature creation"""
25+
edge_signature = self.graph_signature.create_edge_signature(
26+
include_neighbors=False, max_hop=1
27+
)
28+
29+
# Check that the edge signature is a non-empty string
30+
self.assertIsInstance(edge_signature, str)
31+
self.assertGreater(len(edge_signature), 0)
32+
self.assertIn("Br0", edge_signature)
33+
self.assertIn("{0.0,1.0}", edge_signature)
34+
self.assertIn("H0", edge_signature)
35+
36+
def test_edge_signature_with_neighbors(self):
37+
"""Test edge signature creation including neighbors"""
38+
edge_signature_with_neighbors = self.graph_signature.create_edge_signature(
39+
include_neighbors=True, max_hop=1
2140
)
2241

23-
def test_create_node_signature(self):
24-
signature = GraphSignature(self.rc)
25-
self.assertEqual(signature.create_node_signature(), "BrCHN")
42+
# Check that the edge signature with neighbors includes node degrees and neighbors
43+
self.assertIsInstance(edge_signature_with_neighbors, str)
44+
self.assertGreater(len(edge_signature_with_neighbors), 0)
45+
self.assertIn("d1", edge_signature_with_neighbors) # node degree for neighbor
2646

27-
def test_create_node_signature_condensed(self):
28-
signature = GraphSignature(self.its)
29-
self.assertEqual(signature.create_node_signature(), "BrC{23}ClHN{3}O{5}S")
47+
def test_wl_hash(self):
48+
"""Test the Weisfeiler-Lehman hash generation"""
49+
wl_hash = self.graph_signature.create_wl_hash(iterations=3)
3050

31-
def test_create_edge_signature(self):
32-
signature = GraphSignature(self.rc)
33-
self.assertEqual(
34-
signature.create_edge_signature(), "Br[-1]H/Br[1]C/C[-1]N/H[1]N"
51+
# Check that the WL hash is a valid hexadecimal string
52+
self.assertIsInstance(wl_hash, str)
53+
self.assertRegex(wl_hash, r"^[a-f0-9]{64}$") # SHA-256 hash format
54+
55+
def test_graph_signature(self):
56+
"""Test the complete graph signature creation"""
57+
complete_graph_signature = self.graph_signature.create_graph_signature(
58+
include_wl_hash=True, include_neighbors=True, max_hop=1
3559
)
3660

37-
def test_create_graph_signature(self):
38-
# Ensure the graph signature combines the results correctly
39-
signature = GraphSignature(self.rc)
40-
node_signature = "BrCHN"
41-
edge_signature = "Br[-1]H/Br[1]C/C[-1]N/H[1]N"
42-
topo_signature = "114"
43-
expected = f"{topo_signature}.{node_signature}.{edge_signature}"
44-
self.assertEqual(
45-
signature.create_graph_signature(topo="Single Cyclic", cycle=[4], rstep=1),
46-
expected,
61+
# Check that the graph signature is a non-empty string
62+
self.assertIsInstance(complete_graph_signature, str)
63+
self.assertGreater(len(complete_graph_signature), 0)
64+
65+
def test_invalid_node_attributes(self):
66+
"""Test for missing node attributes"""
67+
self.rc.add_node(4) # Missing 'element' and 'charge'
68+
69+
with self.assertRaises(ValueError) as context:
70+
invalid_graph_signature = GraphSignature(self.rc)
71+
invalid_graph_signature._validate_graph()
72+
73+
self.assertIn(
74+
"Node 4 is missing the 'element' attribute", str(context.exception)
4775
)
4876

77+
def test_invalid_edge_order(self):
78+
"""Test for invalid edge 'order' attribute"""
79+
self.its.add_edge(
80+
3, 4, order="invalid_order", state="steady"
81+
) # Invalid 'order' type
82+
83+
with self.assertRaises(ValueError) as context:
84+
invalid_graph_signature = GraphSignature(self.its)
85+
invalid_graph_signature._validate_graph()
86+
87+
self.assertIn("Edge (3, 4) has an invalid 'order'", str(context.exception))
88+
89+
def test_invalid_edge_state(self):
90+
"""Test for invalid edge 'state' attribute"""
91+
self.its.add_edge(2, 4, order=1.0, state="invalid_state") # Invalid 'state'
92+
93+
with self.assertRaises(ValueError) as context:
94+
invalid_graph_signature = GraphSignature(self.its)
95+
invalid_graph_signature._validate_graph()
96+
97+
self.assertIn("Edge (2, 4) has an invalid 'state'", str(context.exception))
98+
4999

50-
# Running the tests
51100
if __name__ == "__main__":
52101
unittest.main()

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "synutility"
7-
version = "0.0.12"
7+
version = "0.0.13"
88
authors = [
99
{name="Tieu Long Phan", email="tieu@bioinf.uni-leipzig.de"}
1010
]
@@ -22,6 +22,7 @@ dependencies = [
2222
"rdkit>=2024.3.3",
2323
"networkx>=3.3",
2424
"seaborn>=0.13.2",
25+
"requests>=2.32.3",
2526
]
2627

2728
[project.optional-dependencies]

requirements.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ rxn-chem-utils==1.5.0
77
rxn-utils==2.0.0
88
rxnmapper==0.3.0
99
rdkit >= 2024.3.3
10-
pandas>=2.2.0
10+
pandas>=2.2.0
11+
requests>=2.32.3
12+
torch==2.0.1

synutility/SynGraph/Descriptor/graph_descriptors.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,7 @@ def get_descriptors(
180180
)
181181

182182
GraphDescriptor._adjust_cycle_and_step(entry, "cycle", entry["topo"])
183-
entry["signature_rc"] = GraphSignature(graph).create_graph_signature(
184-
topo=entry["topo"],
185-
cycle=entry["cycle"],
186-
rstep=entry["rstep"],
187-
condensed=condensed,
188-
)
183+
entry["signature_rc"] = GraphSignature(graph).create_graph_signature()
189184

190185
# Initialize ITS descriptors and call adjust
191186
topo_its = GraphDescriptor.check_graph_type(its_graph)
@@ -195,12 +190,7 @@ def get_descriptors(
195190
entry, "cycle_its", topo_its, its_prefix="its"
196191
)
197192

198-
entry["signature_its"] = GraphSignature(its_graph).create_graph_signature(
199-
topo=topo_its,
200-
cycle=entry["cycle_its"],
201-
rstep=entry["rstep_its"],
202-
condensed=condensed,
203-
)
193+
entry["signature_its"] = GraphSignature(its_graph).create_graph_signature()
204194

205195
return entry
206196

0 commit comments

Comments
 (0)