Skip to content

Commit b34a3a6

Browse files
fix(pygal): address review feedback for network-force-directed
Attempt 1/3 - fixes based on AI review
1 parent ac326d6 commit b34a3a6

1 file changed

Lines changed: 39 additions & 16 deletions

File tree

  • plots/network-force-directed/implementations/python

plots/network-force-directed/implementations/python/pygal.py

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
""" anyplot.ai
1+
"""anyplot.ai
22
network-force-directed: Force-Directed Graph
33
Library: pygal 3.1.3 | Python 3.13.14
44
Quality: 84/100 | Created: 2026-07-01
@@ -46,17 +46,17 @@
4646
# Intra-module edges (dense within functional groups)
4747
for i in range(15):
4848
for j in range(i + 1, 15):
49-
if np.random.random() < 0.35:
49+
if np.random.random() < 0.25:
5050
edges.append((i, j))
5151

5252
for i in range(15, 28):
5353
for j in range(i + 1, 28):
54-
if np.random.random() < 0.35:
54+
if np.random.random() < 0.25:
5555
edges.append((i, j))
5656

5757
for i in range(28, 38):
5858
for j in range(i + 1, 38):
59-
if np.random.random() < 0.35:
59+
if np.random.random() < 0.25:
6060
edges.append((i, j))
6161

6262
# Cross-module interactions (sparse bridges — crosstalk between pathways)
@@ -105,10 +105,10 @@
105105
if disp_norm > 0:
106106
positions[i] += (displacement[i] / disp_norm) * min(disp_norm, 0.15 * temperature)
107107

108-
# Normalize positions to padded plot range
108+
# Normalize positions with ~15% margin on each side to keep clusters away from canvas edges
109109
pos_min = positions.min(axis=0)
110110
pos_max = positions.max(axis=0)
111-
positions = (positions - pos_min) / (pos_max - pos_min + 1e-6) * 10 + 1
111+
positions = (positions - pos_min) / (pos_max - pos_min + 1e-6) * 9 + 1.5
112112
pos = {node["id"]: positions[i] for i, node in enumerate(nodes)}
113113

114114
# Node degrees (for size encoding)
@@ -117,9 +117,10 @@
117117
degrees[src] += 1
118118
degrees[tgt] += 1
119119

120-
# Style — module series use Imprint positions 1-3; edge series uses INK_MUTED (muted semantic anchor)
120+
# Style — module series use Imprint positions 1-3; intra edges use INK_MUTED; bridge edges use Imprint[3]
121121
module_colors = IMPRINT[: len(module_names)]
122-
series_colors = module_colors + (INK_MUTED,) # nodes first → Metabolism gets #009E73
122+
BRIDGE_COLOR = IMPRINT[3] # #BD8233 amber — visually distinct cross-module connector
123+
series_colors = module_colors + (INK_MUTED, BRIDGE_COLOR) # nodes first → Metabolism gets #009E73
123124

124125
custom_style = Style(
125126
background=PAGE_BG,
@@ -152,9 +153,9 @@
152153
show_y_labels=False,
153154
stroke=True,
154155
dots_size=18,
155-
stroke_style={"width": 1.5, "linecap": "round"},
156+
stroke_style={"width": 2.5, "linecap": "round"},
156157
legend_at_bottom=True,
157-
legend_at_bottom_columns=4,
158+
legend_at_bottom_columns=5,
158159
legend_box_size=24,
159160
margin=60,
160161
range=(0, 12),
@@ -177,16 +178,38 @@
177178
node_points.append({"value": (x, y), "label": label, "node": {"r": round(radius, 1)}})
178179
chart.add(mod_name, node_points, stroke=False)
179180

180-
# Edge series added LAST (series 3) — uses INK_MUTED via colors position 3
181-
edge_points = []
181+
# Build intra-module edge set for fast lookup
182+
bridge_edge_set = set(map(tuple, bridge_edges))
183+
184+
# Intra-module edges (series 3) — uses INK_MUTED via colors position 3
185+
intra_edge_points = []
182186
for src, tgt in edges:
187+
if (src, tgt) not in bridge_edge_set and (tgt, src) not in bridge_edge_set:
188+
x1, y1 = pos[src]
189+
x2, y2 = pos[tgt]
190+
intra_edge_points.append((x1, y1))
191+
intra_edge_points.append((x2, y2))
192+
intra_edge_points.append(None)
193+
194+
chart.add("Interactions", intra_edge_points, stroke=True, show_dots=False, fill=False)
195+
196+
# Cross-module bridge edges (series 4) — amber #BD8233, dashed to signal inter-pathway crosstalk
197+
bridge_edge_points = []
198+
for src, tgt in bridge_edges:
183199
x1, y1 = pos[src]
184200
x2, y2 = pos[tgt]
185-
edge_points.append((x1, y1))
186-
edge_points.append((x2, y2))
187-
edge_points.append(None)
201+
bridge_edge_points.append((x1, y1))
202+
bridge_edge_points.append((x2, y2))
203+
bridge_edge_points.append(None)
188204

189-
chart.add("Interactions", edge_points, stroke=True, show_dots=False, fill=False)
205+
chart.add(
206+
"Cross-module Bridges",
207+
bridge_edge_points,
208+
stroke=True,
209+
show_dots=False,
210+
fill=False,
211+
stroke_style={"width": 2.5, "dasharray": "8 5", "linecap": "round"},
212+
)
190213

191214
# Save outputs (theme-aware filenames)
192215
chart.render_to_file(f"plot-{THEME}.svg")

0 commit comments

Comments
 (0)