Spaces:
Running
Running
File size: 6,106 Bytes
1c6109f bca6fdd b163a43 1c6109f bca6fdd 1c6109f bca6fdd 1c6109f bca6fdd 1c6109f bca6fdd 1c6109f bca6fdd 1c6109f bca6fdd 1c6109f bca6fdd 1c6109f bca6fdd 1c6109f bca6fdd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
import gradio as gr
import networkx as nx
import matplotlib.pyplot as plt
import random
import time
from graphGen7 import NetworkGenerator
def get_preset_dims(preset_mode, topology):
"""Calculates dimensions based on preset and topology."""
if preset_mode == "Custom":
# Enable inputs, keep current values (passed via state in UI, but here we just return interaction update)
return gr.update(interactive=True), gr.update(interactive=True)
# Preset Logic
if topology == "linear":
if preset_mode == "Small": dims = (4, 4)
elif preset_mode == "Medium": dims = (6, 11)
else: dims = (10, 26)
else: # Highly Connected / Bottlenecks
if preset_mode == "Small": dims = (4, 4)
elif preset_mode == "Medium": dims = (8, 8)
else: dims = (16, 16)
return gr.update(value=dims[0], interactive=False), gr.update(value=dims[1], interactive=False)
def update_void_settings(variant, width, height):
"""Calculates void fraction based on variant logic."""
if variant == "Custom":
return gr.update(interactive=True)
# Fixed Logic
area = width * height
val = 0.60 if area <= 20 else 0.35
return gr.update(value=val, interactive=False)
def generate_network_viz(topology, width, height, variant, void_frac):
try:
variant_code = "F" if variant == "Fixed" else "R"
generator = NetworkGenerator(
width=width,
height=height,
variant=variant_code,
topology=topology,
node_drop_fraction=void_frac
)
start = time.time()
graph = generator.generate()
end = time.time()
# Plotting
fig, ax = plt.subplots(figsize=(8, 8))
pos = {node: (node[0], node[1]) for node in graph.nodes()}
nx.draw_networkx_edges(graph, pos, ax=ax, width=2, alpha=0.6, edge_color="#333")
nx.draw_networkx_nodes(graph, pos, ax=ax, node_size=350, node_color="#4F46E5", edgecolors="white", linewidths=1.5)
nx.draw_networkx_labels(graph, pos, ax=ax, font_size=7, font_color="white", font_weight="bold")
ax.set_xlim(-1, width + 1)
ax.set_ylim(-1, height + 1)
ax.invert_yaxis() # Camera looks top-down (0 at top)
ax.grid(True, linestyle=':', alpha=0.3)
ax.set_axis_on()
ax.tick_params(left=True, bottom=True, labelleft=False, labelbottom=False)
ax.set_title(f"{topology.upper()} | {width}x{height} | Voids: {int(void_frac*100)}%")
# Metrics
info_text = (
f"**Nodes:** {len(graph.nodes())} | "
f"**Edges:** {len(graph.edges())} | "
f"**Density:** {nx.density(graph):.2f} | "
f"**Time:** {end - start:.3f}s"
)
return fig, info_text
except Exception as e:
return None, f"Error: {str(e)}"
with gr.Blocks(title="Spatial Network Generator") as demo:
gr.Markdown("# Spatial Network Generator")
gr.Markdown("Generate procedural room-like graphs with topological constraints.")
with gr.Row():
# --- LEFT COLUMN: CONTROLS ---
with gr.Column(scale=1):
topology_dd = gr.Dropdown(
choices=["highly_connected", "bottlenecks", "linear"],
value="highly_connected",
label="Topology"
)
preset_radio = gr.Radio(
choices=["Small", "Medium", "Large", "Custom"],
value="Medium",
label="Preset Size"
)
with gr.Row():
width_num = gr.Number(value=8, label="Width (X)", precision=0, interactive=False)
height_num = gr.Number(value=8, label="Height (Y)", precision=0, interactive=False)
gr.Markdown("---")
variant_dd = gr.Dropdown(
choices=["Fixed", "Custom"],
value="Fixed",
label="Variant",
info="Fixed = Standard density. Custom = Random density."
)
void_slider = gr.Slider(
minimum=0.0, maximum=0.9, value=0.35, step=0.05,
label="Void Fraction",
interactive=False,
info="Percentage of grid to leave empty."
)
gen_btn = gr.Button("Generate Network", variant="primary")
# --- RIGHT COLUMN: VISUALIZATION ---
with gr.Column(scale=2):
metrics_out = gr.Markdown("Click Generate to see metrics...")
plot_out = gr.Plot(label="Network Visualization")
# ==========================================
# EVENT LISTENERS
# ==========================================
# 1. Update Dimensions when Preset or Topology changes
# Note: We pass inputs to calculate new dims, and output to width/height inputs
input_group_dims = [preset_radio, topology_dd]
output_group_dims = [width_num, height_num]
preset_radio.change(fn=get_preset_dims, inputs=input_group_dims, outputs=output_group_dims)
topology_dd.change(fn=get_preset_dims, inputs=input_group_dims, outputs=output_group_dims)
# 2. Update Void Settings when Variant or Dimensions change
# (If user switches to Fixed, we lock slider. If dimensions change while Fixed, we recalc 0.60 vs 0.35)
input_group_void = [variant_dd, width_num, height_num]
variant_dd.change(fn=update_void_settings, inputs=input_group_void, outputs=void_slider)
width_num.change(fn=update_void_settings, inputs=input_group_void, outputs=void_slider)
height_num.change(fn=update_void_settings, inputs=input_group_void, outputs=void_slider)
# 3. Main Generation
input_group_gen = [topology_dd, width_num, height_num, variant_dd, void_slider]
output_group_gen = [plot_out, metrics_out]
gen_btn.click(fn=generate_network_viz, inputs=input_group_gen, outputs=output_group_gen)
# Launch
if __name__ == "__main__":
demo.launch() |