Skip to content

Commit b1b83b3

Browse files
committed
Document node-size drawing and cover randwalk ids
1 parent e323206 commit b1b83b3

4 files changed

Lines changed: 69 additions & 1 deletion

File tree

hypergraphx/viz/draw_hypergraph.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def draw_hypergraph(
8080
hyperedge_facecolor_by_order: Optional[dict] = None,
8181
edge_width: float = 1.2,
8282
hyperedge_alpha: Union[float, np.array] = 0.8,
83-
node_size: Union[int, np.array] = 150,
83+
node_size: Union[int, float, np.array, dict] = 150,
8484
node_color: Union[str, np.array] = "#E2E0DD",
8585
node_facecolor: Union[str, np.array] = "black",
8686
node_shape: str = "o",
@@ -97,6 +97,9 @@ def draw_hypergraph(
9797
9898
Parameters
9999
----------
100+
node_size : int, float, numpy.ndarray, or dict
101+
Node marker size. If a dict is provided, keys must be the hypergraph nodes and
102+
values are the corresponding marker sizes.
100103
show : bool
101104
If True, call plt.show().
102105
@@ -168,6 +171,10 @@ def _stable_color(order_value):
168171
node_size = {n: node_size[i] for i, n in enumerate(nodes)}
169172
elif not isinstance(node_size, dict):
170173
node_size = {n: node_size for n in nodes}
174+
if isinstance(node_size, dict):
175+
missing_sizes = set(nodes) - set(node_size.keys())
176+
if missing_sizes:
177+
raise ValueError("node_size is missing entries for some nodes.")
171178
if isinstance(node_color, np.ndarray):
172179
if len(node_color) != len(nodes):
173180
raise ValueError("node_color length must match number of nodes.")

tests/dynamics/test_randwalk.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,23 @@ def test_transition_matrix_rows_sum_to_one():
2222
assert np.allclose(T.sum(axis=1), 1.0)
2323

2424

25+
def test_transition_matrix_handles_non_contiguous_node_ids():
26+
hg = Hypergraph(edge_list=[(492, 938), (938, 1200), (1200, 5000)])
27+
28+
T = transition_matrix(hg).toarray()
29+
_, mapping = hg.binary_incidence_matrix(return_mapping=True)
30+
node_to_idx = {node: idx for idx, node in mapping.items()}
31+
32+
assert T.shape == (4, 4)
33+
assert np.allclose(T.sum(axis=1), 1.0)
34+
assert T[node_to_idx[492], node_to_idx[938]] == 1.0
35+
assert T[node_to_idx[938], node_to_idx[492]] == 0.5
36+
assert T[node_to_idx[938], node_to_idx[1200]] == 0.5
37+
assert T[node_to_idx[1200], node_to_idx[938]] == 0.5
38+
assert T[node_to_idx[1200], node_to_idx[5000]] == 0.5
39+
assert T[node_to_idx[5000], node_to_idx[1200]] == 1.0
40+
41+
2542
def test_random_walk_length():
2643
"""Test random walk length equals time + 1."""
2744
np.random.seed(0)
@@ -31,6 +48,15 @@ def test_random_walk_length():
3148
assert len(path) == 4
3249

3350

51+
def test_random_walk_returns_non_contiguous_node_ids():
52+
hg = Hypergraph(edge_list=[(492, 938), (938, 1200), (1200, 5000)])
53+
54+
path = random_walk(hg, s=492, time=5, seed=0)
55+
56+
assert path[0] == 492
57+
assert set(path).issubset({492, 938, 1200, 5000})
58+
59+
3460
def test_stationary_state_properties():
3561
"""Test stationary state is a valid distribution."""
3662
hg = _make_connected_hypergraph()

tests/viz/test_draws.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
matplotlib.use("Agg")
44

55
import matplotlib.pyplot as plt
6+
import pytest
67

78
from hypergraphx import Hypergraph
89
from hypergraphx.viz.draw_hypergraph import draw_hypergraph
@@ -24,6 +25,23 @@ def test_draw_hypergraph_smoke(monkeypatch):
2425
draw_hypergraph(hg)
2526

2627

28+
def test_draw_hypergraph_accepts_node_size_dict(monkeypatch):
29+
monkeypatch.setattr(plt, "show", lambda: None)
30+
hg = _make_hypergraph()
31+
32+
ax = draw_hypergraph(hg, node_size={0: 100, 1: 200, 2: 300, 3: 400})
33+
34+
assert ax is not None
35+
36+
37+
def test_draw_hypergraph_node_size_dict_requires_all_nodes(monkeypatch):
38+
monkeypatch.setattr(plt, "show", lambda: None)
39+
hg = _make_hypergraph()
40+
41+
with pytest.raises(ValueError, match="node_size is missing entries"):
42+
draw_hypergraph(hg, node_size={0: 100, 1: 200})
43+
44+
2745
def test_draw_projections(monkeypatch):
2846
"""Test draw_bipartite and draw_clique return axes."""
2947
monkeypatch.setattr(plt, "show", lambda: None)

tutorials/basics.ipynb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,23 @@
270270
"draw_hypergraph(H)"
271271
]
272272
},
273+
{
274+
"cell_type": "markdown",
275+
"metadata": {},
276+
"source": [
277+
"Node sizes can also be set per node with a dictionary keyed by node id.\n"
278+
]
279+
},
280+
{
281+
"cell_type": "code",
282+
"execution_count": null,
283+
"metadata": {},
284+
"outputs": [],
285+
"source": [
286+
"node_sizes = {node: 80 + 40 * H.degree(node) for node in H.get_nodes()}\n",
287+
"draw_hypergraph(H, node_size=node_sizes, with_node_labels=True)"
288+
]
289+
},
273290
{
274291
"cell_type": "code",
275292
"execution_count": 12,

0 commit comments

Comments
 (0)