Update app.py
Browse files
app.py
CHANGED
|
@@ -245,7 +245,8 @@ def parse_path(text: str, d: int) -> List[int]:
|
|
| 245 |
|
| 246 |
# ---------- Figure builder (fixed UnboundLocalError) ----------
|
| 247 |
|
| 248 |
-
def make_figure(d: int,
|
|
|
|
| 249 |
path: List[int], scale_base: float):
|
| 250 |
nodes, edges = build_hypercube(d)
|
| 251 |
pts, width, height = layout_positions(d, base=scale_base)
|
|
@@ -319,34 +320,49 @@ def make_figure(d: int, show_labels: bool, node_r: int, edge_w: int,
|
|
| 319 |
# Nodes (3× size if on the path)
|
| 320 |
xs = [pos[v][0] for v in nodes]
|
| 321 |
ys = [pos[v][1] for v in nodes]
|
| 322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
|
| 324 |
in_path = set(path or [])
|
| 325 |
sizes = []
|
| 326 |
colors = []
|
| 327 |
for v in nodes:
|
| 328 |
base_size = node_r * 2
|
| 329 |
-
sizes.append(base_size * (3 if v in in_path else 1))
|
| 330 |
if path and (v == path[0] or v == path[-1]):
|
| 331 |
colors.append("#111")
|
| 332 |
else:
|
| 333 |
colors.append("#222")
|
| 334 |
|
| 335 |
node_trace = go.Scatter(
|
| 336 |
-
x=xs,
|
| 337 |
-
|
|
|
|
| 338 |
marker=dict(size=sizes, color=colors, line=dict(width=1, color="#333")),
|
| 339 |
-
text=texts
|
| 340 |
textposition="middle right",
|
| 341 |
textfont=dict(size=12, color="#333"),
|
| 342 |
hovertemplate=(
|
| 343 |
-
"id=%{customdata}<br>
|
| 344 |
else "id=%{customdata}<extra></extra>"
|
| 345 |
),
|
| 346 |
-
customdata=nodes,
|
| 347 |
name="vertices",
|
| 348 |
)
|
| 349 |
|
|
|
|
| 350 |
fig = go.Figure(edge_traces + [node_trace])
|
| 351 |
pad = max(40, 0.08 * max(width, height))
|
| 352 |
fig.update_layout(
|
|
@@ -401,8 +417,11 @@ app.layout = html.Div(
|
|
| 401 |
html.Div([
|
| 402 |
dcc.Checklist(
|
| 403 |
id="show_labels",
|
| 404 |
-
options=[
|
| 405 |
-
|
|
|
|
|
|
|
|
|
|
| 406 |
style={"marginTop": "8px"},
|
| 407 |
)
|
| 408 |
]),
|
|
@@ -614,10 +633,14 @@ def update_path(clickData,
|
|
| 614 |
Input("scale", "value"),
|
| 615 |
)
|
| 616 |
def render(d, show_labels_vals, path, scale_base):
|
| 617 |
-
|
|
|
|
|
|
|
|
|
|
| 618 |
fig = make_figure(
|
| 619 |
d=int(d),
|
| 620 |
-
|
|
|
|
| 621 |
node_r=DEFAULTS["node_radius"],
|
| 622 |
edge_w=DEFAULTS["edge_width"],
|
| 623 |
path=path or [],
|
|
@@ -625,6 +648,7 @@ def render(d, show_labels_vals, path, scale_base):
|
|
| 625 |
)
|
| 626 |
return fig
|
| 627 |
|
|
|
|
| 628 |
@app.callback(
|
| 629 |
Output("path_info", "children"),
|
| 630 |
Input("dim", "value"),
|
|
|
|
| 245 |
|
| 246 |
# ---------- Figure builder (fixed UnboundLocalError) ----------
|
| 247 |
|
| 248 |
+
def make_figure(d: int, show_bits: bool, show_ints: bool,
|
| 249 |
+
node_r: int, edge_w: int,
|
| 250 |
path: List[int], scale_base: float):
|
| 251 |
nodes, edges = build_hypercube(d)
|
| 252 |
pts, width, height = layout_positions(d, base=scale_base)
|
|
|
|
| 320 |
# Nodes (3× size if on the path)
|
| 321 |
xs = [pos[v][0] for v in nodes]
|
| 322 |
ys = [pos[v][1] for v in nodes]
|
| 323 |
+
|
| 324 |
+
bit_labels = [int_to_bin(v, d) for v in nodes]
|
| 325 |
+
int_labels = [str(v) for v in nodes]
|
| 326 |
+
|
| 327 |
+
# Decide what text to show per node
|
| 328 |
+
show_any_label = show_bits or show_ints
|
| 329 |
+
if show_bits and show_ints:
|
| 330 |
+
texts = [f"{iv}\n{bv}" for iv, bv in zip(int_labels, bit_labels)]
|
| 331 |
+
elif show_bits:
|
| 332 |
+
texts = bit_labels
|
| 333 |
+
elif show_ints:
|
| 334 |
+
texts = int_labels
|
| 335 |
+
else:
|
| 336 |
+
texts = None
|
| 337 |
|
| 338 |
in_path = set(path or [])
|
| 339 |
sizes = []
|
| 340 |
colors = []
|
| 341 |
for v in nodes:
|
| 342 |
base_size = node_r * 2
|
| 343 |
+
sizes.append(base_size * (3 if v in in_path else 1))
|
| 344 |
if path and (v == path[0] or v == path[-1]):
|
| 345 |
colors.append("#111")
|
| 346 |
else:
|
| 347 |
colors.append("#222")
|
| 348 |
|
| 349 |
node_trace = go.Scatter(
|
| 350 |
+
x=xs,
|
| 351 |
+
y=ys,
|
| 352 |
+
mode="markers+text" if show_any_label else "markers",
|
| 353 |
marker=dict(size=sizes, color=colors, line=dict(width=1, color="#333")),
|
| 354 |
+
text=texts,
|
| 355 |
textposition="middle right",
|
| 356 |
textfont=dict(size=12, color="#333"),
|
| 357 |
hovertemplate=(
|
| 358 |
+
"id=%{customdata}<br>label=%{text}<extra></extra>" if show_any_label
|
| 359 |
else "id=%{customdata}<extra></extra>"
|
| 360 |
),
|
| 361 |
+
customdata=nodes,
|
| 362 |
name="vertices",
|
| 363 |
)
|
| 364 |
|
| 365 |
+
|
| 366 |
fig = go.Figure(edge_traces + [node_trace])
|
| 367 |
pad = max(40, 0.08 * max(width, height))
|
| 368 |
fig.update_layout(
|
|
|
|
| 417 |
html.Div([
|
| 418 |
dcc.Checklist(
|
| 419 |
id="show_labels",
|
| 420 |
+
options=[
|
| 421 |
+
{"label": " Show bit labels", "value": "bits"},
|
| 422 |
+
{"label": " Show int labels", "value": "ints"},
|
| 423 |
+
],
|
| 424 |
+
value=[], # or ["bits"] if you want bits shown by default
|
| 425 |
style={"marginTop": "8px"},
|
| 426 |
)
|
| 427 |
]),
|
|
|
|
| 633 |
Input("scale", "value"),
|
| 634 |
)
|
| 635 |
def render(d, show_labels_vals, path, scale_base):
|
| 636 |
+
labels_vals = show_labels_vals or []
|
| 637 |
+
show_bits = "bits" in labels_vals
|
| 638 |
+
show_ints = "ints" in labels_vals
|
| 639 |
+
|
| 640 |
fig = make_figure(
|
| 641 |
d=int(d),
|
| 642 |
+
show_bits=show_bits,
|
| 643 |
+
show_ints=show_ints,
|
| 644 |
node_r=DEFAULTS["node_radius"],
|
| 645 |
edge_w=DEFAULTS["edge_width"],
|
| 646 |
path=path or [],
|
|
|
|
| 648 |
)
|
| 649 |
return fig
|
| 650 |
|
| 651 |
+
|
| 652 |
@app.callback(
|
| 653 |
Output("path_info", "children"),
|
| 654 |
Input("dim", "value"),
|