Spaces:
Sleeping
Sleeping
import streamlit as st | |
import networkx as nx | |
import matplotlib.pyplot as plt | |
# Sidebar for selecting an option | |
sidebar_option = st.sidebar.radio("Select an option", | |
["Select an option", "Basic: Properties", | |
"Basic: Read and write graphs", "Basic: Simple graph", | |
"Basic: Simple graph Directed", "Drawing: Custom Node Position", | |
"Drawing: Chess Masters", "Drawing: Cluster Layout"]) | |
# Helper function to draw and display graph | |
def draw_graph(G, pos=None, title="Graph Visualization", edgewidth=None, nodesize=None): | |
if edgewidth is None: | |
edgewidth = [1] * len(G.edges()) # Default edge width if not provided | |
if nodesize is None: | |
nodesize = [300] * len(G.nodes()) # Default node size if not provided | |
plt.figure(figsize=(12, 12)) | |
nx.draw_networkx_edges(G, pos, alpha=0.3, width=edgewidth, edge_color="m") | |
nx.draw_networkx_nodes(G, pos, node_size=nodesize, node_color="#210070", alpha=0.9) | |
label_options = {"ec": "k", "fc": "white", "alpha": 0.7} | |
nx.draw_networkx_labels(G, pos, font_size=14, bbox=label_options) | |
# Title/legend | |
font = {"fontname": "Helvetica", "color": "k", "fontweight": "bold", "fontsize": 14} | |
ax = plt.gca() | |
ax.set_title(title, font) | |
ax.text( | |
0.80, | |
0.10, | |
"edge width = # games played", | |
horizontalalignment="center", | |
transform=ax.transAxes, | |
fontdict=font, | |
) | |
ax.text( | |
0.80, | |
0.06, | |
"node size = # games won", | |
horizontalalignment="center", | |
transform=ax.transAxes, | |
fontdict=font, | |
) | |
# Resize figure for label readability | |
ax.margins(0.1, 0.05) | |
plt.axis("off") | |
st.pyplot(plt) | |
# Drawing: Cluster Layout | |
def display_cluster_layout(): | |
st.title("Drawing: Cluster Layout") | |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own")) | |
if option == "Default Example": | |
G = nx.davis_southern_women_graph() | |
# Compute communities using greedy modularity community detection | |
communities = nx.community.greedy_modularity_communities(G) | |
# Compute positions for the node clusters as if they were themselves nodes in a supergraph | |
supergraph = nx.cycle_graph(len(communities)) | |
superpos = nx.spring_layout(G, scale=50, seed=429) | |
# Use the "supernode" positions as the center of each node cluster | |
centers = list(superpos.values()) | |
pos = {} | |
for center, comm in zip(centers, communities): | |
pos.update(nx.spring_layout(nx.subgraph(G, comm), center=center, seed=1430)) | |
# Nodes colored by cluster | |
for nodes, clr in zip(communities, ("tab:blue", "tab:orange", "tab:green")): | |
nx.draw_networkx_nodes(G, pos=pos, nodelist=nodes, node_color=clr, node_size=100) | |
nx.draw_networkx_edges(G, pos=pos) | |
plt.tight_layout() | |
st.pyplot(plt) | |
elif option == "Create your own": | |
uploaded_file = st.file_uploader("Upload your own graph file (in GML format)", type="gml") | |
if uploaded_file is not None: | |
G_custom = nx.read_gml(uploaded_file) | |
# Compute communities using greedy modularity community detection | |
communities = nx.community.greedy_modularity_communities(G_custom) | |
# Compute positions for the node clusters as if they were themselves nodes in a supergraph | |
supergraph = nx.cycle_graph(len(communities)) | |
superpos = nx.spring_layout(G_custom, scale=50, seed=429) | |
# Use the "supernode" positions as the center of each node cluster | |
centers = list(superpos.values()) | |
pos = {} | |
for center, comm in zip(centers, communities): | |
pos.update(nx.spring_layout(nx.subgraph(G_custom, comm), center=center, seed=1430)) | |
# Nodes colored by cluster | |
for nodes, clr in zip(communities, ("tab:blue", "tab:orange", "tab:green")): | |
nx.draw_networkx_nodes(G_custom, pos=pos, nodelist=nodes, node_color=clr, node_size=100) | |
nx.draw_networkx_edges(G_custom, pos=pos) | |
plt.tight_layout() | |
st.pyplot(plt) | |
# Display other sections | |
def display_basic_properties(): | |
st.title("Basic: Properties") | |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own")) | |
# Default example: 5x5 grid graph | |
if option == "Default Example": | |
G = nx.lollipop_graph(4, 6) | |
display_graph_properties(G) | |
elif option == "Create your own": | |
num_nodes = st.number_input("Number of nodes:", min_value=2, max_value=50, value=5) | |
num_edges = st.number_input("Number of edges per group (for lollipop graph):", min_value=1, max_value=10, value=3) | |
if st.button("Generate"): | |
if num_nodes >= 2 and num_edges >= 1: | |
G_custom = nx.lollipop_graph(num_nodes, num_edges) | |
display_graph_properties(G_custom) | |
def display_graph_properties(G): | |
pathlengths = [] | |
st.write("### Source vertex {target:length, }") | |
for v in G.nodes(): | |
spl = dict(nx.single_source_shortest_path_length(G, v)) | |
st.write(f"Vertex {v}: {spl}") | |
for p in spl: | |
pathlengths.append(spl[p]) | |
avg_path_length = sum(pathlengths) / len(pathlengths) | |
st.write(f"### Average shortest path length: {avg_path_length}") | |
dist = {} | |
for p in pathlengths: | |
if p in dist: | |
dist[p] += 1 | |
else: | |
dist[p] = 1 | |
st.write("### Length #paths") | |
for d in sorted(dist.keys()): | |
st.write(f"Length {d}: {dist[d]} paths") | |
st.write("### Properties") | |
st.write(f"Radius: {nx.radius(G)}") | |
st.write(f"Diameter: {nx.diameter(G)}") | |
st.write(f"Eccentricity: {nx.eccentricity(G)}") | |
st.write(f"Center: {nx.center(G)}") | |
st.write(f"Periphery: {nx.periphery(G)}") | |
st.write(f"Density: {nx.density(G)}") | |
st.write("### Graph Visualization") | |
pos = nx.spring_layout(G, seed=3068) | |
plt.figure(figsize=(8, 6)) | |
nx.draw(G, pos=pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_weight='bold') | |
st.pyplot(plt) | |
# Display other sections | |
def display_read_write_graph(): | |
st.title("Basic: Read and write graphs") | |
G = nx.karate_club_graph() | |
# Write the graph | |
nx.write_gml(G, "karate_club.gml") | |
st.write("Graph written to 'karate_club.gml'.") | |
# Read the graph back | |
G_new = nx.read_gml("karate_club.gml") | |
st.write("Graph read back from 'karate_club.gml'.") | |
nx.draw(G_new, with_labels=True) | |
st.pyplot(plt) | |
def display_simple_graph(): | |
st.title("Basic: Simple graph") | |
G = nx.complete_graph(5) | |
nx.draw(G, with_labels=True) | |
st.pyplot(plt) | |
def display_simple_directed_graph(): | |
st.title("Basic: Simple graph Directed") | |
G = nx.complete_graph(5, nx.DiGraph()) | |
nx.draw(G, with_labels=True) | |
st.pyplot(plt) | |
def display_custom_node_position(): | |
st.title("Drawing: Custom Node Position") | |
pos = {"A": (1, 2), "B": (2, 3), "C": (3, 1)} | |
G = nx.Graph(pos) | |
nx.draw(G, pos=pos, with_labels=True) | |
st.pyplot(plt) | |
# Call the appropriate function based on sidebar selection | |
if sidebar_option == "Basic: Properties": | |
display_basic_properties() | |
elif sidebar_option == "Basic: Read and write graphs": | |
display_read_write_graph() | |
elif sidebar_option == "Basic: Simple graph": | |
display_simple_graph() | |
elif sidebar_option == "Basic: Simple graph Directed": | |
display_simple_directed_graph() | |
elif sidebar_option == "Drawing: Custom Node Position": | |
display_custom_node_position() | |
elif sidebar_option == "Drawing: Chess Masters": | |
display_chess_masters_graph() | |
elif sidebar_option == "Drawing: Cluster Layout": | |
display_cluster_layout() | |
else: | |
st.write("Please select a valid option from the sidebar.") | |