shukdevdatta123's picture
Update app.py
8ae1a9a verified
raw
history blame
12.1 kB
import streamlit as st
import matplotlib.pyplot as plt
import networkx as nx
import numpy as np
# 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: Cluster Layout"])
# Helper function to draw and display graph
def draw_graph(G, pos=None, title="Graph Visualization"):
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)
# Function to display properties and graph for Basic: Properties
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:
dist[p] = dist.get(p, 0) + 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)}")
# Visualize the graph
st.write("### Graph Visualization")
pos = nx.spring_layout(G, seed=3068) # Seed layout for reproducibility
draw_graph(G, pos)
# Function to display graph for Basic: Read and write graphs
def display_read_write_graph(G):
st.write("### Adjacency List:")
for line in nx.generate_adjlist(G):
st.write(line)
# Write the graph's edge list to a file
st.write("### Writing Edge List to 'grid.edgelist' file:")
nx.write_edgelist(G, path="grid.edgelist", delimiter=":") # Save edge list
st.write("Edge list written to 'grid.edgelist'")
# Read the graph from the edge list
st.write("### Reading Edge List from 'grid.edgelist' file:")
H = nx.read_edgelist(path="grid.edgelist", delimiter=":")
st.write("Edge list read into graph H")
# Visualize the graph
st.write("### Graph Visualization:")
pos = nx.spring_layout(H, seed=200) # Seed for reproducibility
draw_graph(H, pos)
# Function to display Simple Graphs for Basic: Simple graph
def display_simple_graph(G, pos=None):
options = {
"font_size": 36,
"node_size": 3000,
"node_color": "white",
"edgecolors": "black",
"linewidths": 5,
"width": 5,
}
# Draw the network
nx.draw_networkx(G, pos, **options)
# Set margins for the axes so that nodes aren't clipped
ax = plt.gca()
ax.margins(0.20)
plt.axis("off")
st.pyplot(plt)
# Function to display Simple Directed Graphs for Basic: Simple graph Directed
def display_simple_directed_graph(G, pos=None):
options = {
"node_size": 500,
"node_color": "lightblue",
"arrowsize": 20,
"width": 2,
"edge_color": "gray",
}
# Draw the directed graph with the given positions and options
nx.draw_networkx(G, pos, **options)
# Set margins for the axes so that nodes aren't clipped
ax = plt.gca()
ax.margins(0.20)
plt.axis("off")
st.pyplot(plt)
# Function to display Custom Node Position Graphs for Drawing: Custom Node Position
def display_custom_node_position():
st.title("Drawing: Custom Node Position")
# Default example graph (path graph with custom node position)
G = nx.path_graph(20)
center_node = 5
edge_nodes = set(G) - {center_node}
# Ensure the nodes around the circle are evenly distributed
pos = nx.circular_layout(G.subgraph(edge_nodes))
pos[center_node] = np.array([0, 0]) # Manually specify node position
# Draw the graph
draw_graph(G, pos)
# Function to display Cluster Layout for 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() # Example graph
communities = nx.community.greedy_modularity_communities(G)
# Compute positions for the node clusters as if they were themselves nodes in a supergraph using a larger scale factor
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":
st.write("For custom graph creation, you can specify the number of nodes and edges.")
# Here you can add functionality for custom graph creation if required
# Input for the number of nodes
num_nodes = st.number_input("Number of nodes:", min_value=2, max_value=100, value=5)
# Input for edges: users can input edges manually
edge_input = st.text_area("Enter edges (format: u,v):", value="0,1\n1,2\n2,3")
# Button to generate the graph
if st.button("Generate Graph"):
edges = []
if edge_input:
# Parse the input string to create the edges
edge_list = edge_input.split("\n")
for edge in edge_list:
try:
u, v = map(int, edge.split(","))
edges.append((u, v))
except ValueError:
st.error("Invalid edge format. Please use the format 'u,v'.")
# Create a graph and add the edges
G_custom = nx.Graph()
G_custom.add_edges_from(edges)
if len(G_custom.nodes) == 0:
st.error("No nodes found. Please ensure you have specified edges correctly.")
else:
# Compute clusters (communities) and layout
communities = list(nx.community.greedy_modularity_communities(G_custom))
# Compute positions for the node clusters as if they were themselves nodes in a supergraph using a larger scale factor
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 Basic: Properties if selected
if sidebar_option == "Basic: Properties":
st.title("Basic: Properties")
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
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)
# Display Basic: Read and write graphs if selected
elif sidebar_option == "Basic: Read and write graphs":
st.title("Basic: Read and write graphs")
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
if option == "Default Example":
G = nx.grid_2d_graph(5, 5)
display_read_write_graph(G)
elif option == "Create your own":
rows = st.number_input("Number of rows:", min_value=2, max_value=20, value=5)
cols = st.number_input("Number of columns:", min_value=2, max_value=20, value=5)
if st.button("Generate"):
if rows >= 2 and cols >= 2:
G_custom = nx.grid_2d_graph(rows, cols)
display_read_write_graph(G_custom)
# Display Basic: Simple Graph if selected
elif sidebar_option == "Basic: Simple graph":
st.title("Basic: Simple graph")
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
if option == "Default Example":
G = nx.Graph()
G.add_edge(1, 2)
G.add_edge(1, 3)
G.add_edge(1, 5)
G.add_edge(2, 3)
G.add_edge(3, 4)
G.add_edge(4, 5)
pos = {1: (0, 0), 2: (-1, 0.3), 3: (2, 0.17), 4: (4, 0.255), 5: (5, 0.03)}
display_simple_graph(G, pos)
elif option == "Create your own":
edges = []
edge_input = st.text_area("Edges:", value="1,2\n1,3\n2,3")
if edge_input:
edge_list = edge_input.split("\n")
for edge in edge_list:
u, v = map(int, edge.split(","))
edges.append((u, v))
if st.button("Generate"):
G_custom = nx.Graph()
G_custom.add_edges_from(edges)
pos = nx.spring_layout(G_custom, seed=42)
display_simple_graph(G_custom, pos)
# Display Basic: Simple Directed Graph if selected
elif sidebar_option == "Basic: Simple graph Directed":
st.title("Basic: Simple graph Directed")
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
if option == "Default Example":
G = nx.DiGraph([(0, 3), (1, 3), (2, 4), (3, 5), (3, 6), (4, 6), (5, 6)])
left_nodes = [0, 1, 2]
middle_nodes = [3, 4]
right_nodes = [5, 6]
pos = {n: (0, i) for i, n in enumerate(left_nodes)}
pos.update({n: (1, i + 0.5) for i, n in enumerate(middle_nodes)})
pos.update({n: (2, i + 0.5) for i, n in enumerate(right_nodes)})
display_simple_directed_graph(G, pos)
elif option == "Create your own":
edges = []
edge_input = st.text_area("Edges:", value="1,2\n1,3\n2,3")
if edge_input:
edge_list = edge_input.split("\n")
for edge in edge_list:
u, v = map(int, edge.split(","))
edges.append((u, v))
if st.button("Generate"):
G_custom = nx.DiGraph()
G_custom.add_edges_from(edges)
pos = nx.spring_layout(G_custom, seed=42)
display_simple_directed_graph(G_custom, pos)
# Display Drawing: Custom Node Position if selected
elif sidebar_option == "Drawing: Custom Node Position":
display_custom_node_position()
# Display Drawing: Cluster Layout if selected
elif sidebar_option == "Drawing: Cluster Layout":
display_cluster_layout()