TahaRasouli's picture
Rename app.py to app1.py
52c828d verified
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()