shukdevdatta123 commited on
Commit
8cbf79a
·
verified ·
1 Parent(s): 57e492d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +175 -167
app.py CHANGED
@@ -1,128 +1,21 @@
1
  import streamlit as st
2
- import networkx as nx
3
  import matplotlib.pyplot as plt
 
 
4
 
5
  # Sidebar for selecting an option
6
  sidebar_option = st.sidebar.radio("Select an option",
7
  ["Select an option", "Basic: Properties",
8
  "Basic: Read and write graphs", "Basic: Simple graph",
9
- "Basic: Simple graph Directed", "Drawing: Custom Node Position",
10
- "Drawing: Chess Masters", "Drawing: Cluster Layout"])
11
 
12
  # Helper function to draw and display graph
13
- def draw_graph(G, pos=None, title="Graph Visualization", edgewidth=None, nodesize=None):
14
- if edgewidth is None:
15
- edgewidth = [1] * len(G.edges()) # Default edge width if not provided
16
-
17
- if nodesize is None:
18
- nodesize = [300] * len(G.nodes()) # Default node size if not provided
19
-
20
- plt.figure(figsize=(12, 12))
21
- nx.draw_networkx_edges(G, pos, alpha=0.3, width=edgewidth, edge_color="m")
22
- nx.draw_networkx_nodes(G, pos, node_size=nodesize, node_color="#210070", alpha=0.9)
23
- label_options = {"ec": "k", "fc": "white", "alpha": 0.7}
24
- nx.draw_networkx_labels(G, pos, font_size=14, bbox=label_options)
25
-
26
- # Title/legend
27
- font = {"fontname": "Helvetica", "color": "k", "fontweight": "bold", "fontsize": 14}
28
- ax = plt.gca()
29
- ax.set_title(title, font)
30
- ax.text(
31
- 0.80,
32
- 0.10,
33
- "edge width = # games played",
34
- horizontalalignment="center",
35
- transform=ax.transAxes,
36
- fontdict=font,
37
- )
38
- ax.text(
39
- 0.80,
40
- 0.06,
41
- "node size = # games won",
42
- horizontalalignment="center",
43
- transform=ax.transAxes,
44
- fontdict=font,
45
- )
46
-
47
- # Resize figure for label readability
48
- ax.margins(0.1, 0.05)
49
- plt.axis("off")
50
  st.pyplot(plt)
51
 
52
- # Drawing: Cluster Layout
53
- def display_cluster_layout():
54
- st.title("Drawing: Cluster Layout")
55
-
56
- option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
57
-
58
- if option == "Default Example":
59
- G = nx.davis_southern_women_graph()
60
-
61
- # Compute communities using greedy modularity community detection
62
- communities = nx.community.greedy_modularity_communities(G)
63
-
64
- # Compute positions for the node clusters as if they were themselves nodes in a supergraph
65
- supergraph = nx.cycle_graph(len(communities))
66
- superpos = nx.spring_layout(G, scale=50, seed=429)
67
-
68
- # Use the "supernode" positions as the center of each node cluster
69
- centers = list(superpos.values())
70
- pos = {}
71
- for center, comm in zip(centers, communities):
72
- pos.update(nx.spring_layout(nx.subgraph(G, comm), center=center, seed=1430))
73
-
74
- # Nodes colored by cluster
75
- for nodes, clr in zip(communities, ("tab:blue", "tab:orange", "tab:green")):
76
- nx.draw_networkx_nodes(G, pos=pos, nodelist=nodes, node_color=clr, node_size=100)
77
- nx.draw_networkx_edges(G, pos=pos)
78
-
79
- plt.tight_layout()
80
- st.pyplot(plt)
81
-
82
- elif option == "Create your own":
83
- uploaded_file = st.file_uploader("Upload your own graph file (in GML format)", type="gml")
84
- if uploaded_file is not None:
85
- G_custom = nx.read_gml(uploaded_file)
86
- # Compute communities using greedy modularity community detection
87
- communities = nx.community.greedy_modularity_communities(G_custom)
88
-
89
- # Compute positions for the node clusters as if they were themselves nodes in a supergraph
90
- supergraph = nx.cycle_graph(len(communities))
91
- superpos = nx.spring_layout(G_custom, scale=50, seed=429)
92
-
93
- # Use the "supernode" positions as the center of each node cluster
94
- centers = list(superpos.values())
95
- pos = {}
96
- for center, comm in zip(centers, communities):
97
- pos.update(nx.spring_layout(nx.subgraph(G_custom, comm), center=center, seed=1430))
98
-
99
- # Nodes colored by cluster
100
- for nodes, clr in zip(communities, ("tab:blue", "tab:orange", "tab:green")):
101
- nx.draw_networkx_nodes(G_custom, pos=pos, nodelist=nodes, node_color=clr, node_size=100)
102
- nx.draw_networkx_edges(G_custom, pos=pos)
103
-
104
- plt.tight_layout()
105
- st.pyplot(plt)
106
-
107
- # Display other sections
108
- def display_basic_properties():
109
- st.title("Basic: Properties")
110
- option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
111
-
112
- # Default example: 5x5 grid graph
113
- if option == "Default Example":
114
- G = nx.lollipop_graph(4, 6)
115
- display_graph_properties(G)
116
-
117
- elif option == "Create your own":
118
- num_nodes = st.number_input("Number of nodes:", min_value=2, max_value=50, value=5)
119
- num_edges = st.number_input("Number of edges per group (for lollipop graph):", min_value=1, max_value=10, value=3)
120
-
121
- if st.button("Generate"):
122
- if num_nodes >= 2 and num_edges >= 1:
123
- G_custom = nx.lollipop_graph(num_nodes, num_edges)
124
- display_graph_properties(G_custom)
125
-
126
  def display_graph_properties(G):
127
  pathlengths = []
128
  st.write("### Source vertex {target:length, }")
@@ -137,11 +30,7 @@ def display_graph_properties(G):
137
 
138
  dist = {}
139
  for p in pathlengths:
140
- if p in dist:
141
- dist[p] += 1
142
- else:
143
- dist[p] = 1
144
-
145
  st.write("### Length #paths")
146
  for d in sorted(dist.keys()):
147
  st.write(f"Length {d}: {dist[d]} paths")
@@ -154,69 +43,188 @@ def display_graph_properties(G):
154
  st.write(f"Periphery: {nx.periphery(G)}")
155
  st.write(f"Density: {nx.density(G)}")
156
 
 
157
  st.write("### Graph Visualization")
158
- pos = nx.spring_layout(G, seed=3068)
159
- plt.figure(figsize=(8, 6))
160
- nx.draw(G, pos=pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_weight='bold')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  st.pyplot(plt)
162
 
163
- # Display other sections
164
- def display_read_write_graph():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  st.title("Basic: Read and write graphs")
166
- G = nx.karate_club_graph()
167
 
168
- # Write the graph
169
- nx.write_gml(G, "karate_club.gml")
170
- st.write("Graph written to 'karate_club.gml'.")
171
 
172
- # Read the graph back
173
- G_new = nx.read_gml("karate_club.gml")
174
- st.write("Graph read back from 'karate_club.gml'.")
175
- nx.draw(G_new, with_labels=True)
176
- st.pyplot(plt)
177
 
178
- def display_simple_graph():
 
 
 
 
 
 
179
  st.title("Basic: Simple graph")
180
- G = nx.complete_graph(5)
181
- nx.draw(G, with_labels=True)
182
- st.pyplot(plt)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
- def display_simple_directed_graph():
 
185
  st.title("Basic: Simple graph Directed")
186
- G = nx.complete_graph(5, nx.DiGraph())
187
- nx.draw(G, with_labels=True)
188
- st.pyplot(plt)
189
 
190
- def display_custom_node_position():
191
- st.title("Drawing: Custom Node Position")
192
 
193
- # Create a graph with a few nodes and edges
194
- G = nx.Graph()
195
- G.add_edges_from([("A", "B"), ("B", "C"), ("C", "A")])
196
 
197
- # Define custom positions for the nodes
198
- pos = {"A": (1, 2), "B": (2, 3), "C": (3, 1)}
 
199
 
200
- # Draw the graph with the custom positions
201
- nx.draw(G, pos=pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_weight='bold')
202
- st.pyplot(plt)
203
 
 
 
 
 
 
 
 
 
204
 
 
 
 
 
 
205
 
206
- # Call the appropriate function based on sidebar selection
207
- if sidebar_option == "Basic: Properties":
208
- display_basic_properties()
209
- elif sidebar_option == "Basic: Read and write graphs":
210
- display_read_write_graph()
211
- elif sidebar_option == "Basic: Simple graph":
212
- display_simple_graph()
213
- elif sidebar_option == "Basic: Simple graph Directed":
214
- display_simple_directed_graph()
215
  elif sidebar_option == "Drawing: Custom Node Position":
216
- display_custom_node_position()
217
- elif sidebar_option == "Drawing: Chess Masters":
218
- display_chess_masters_graph()
219
- elif sidebar_option == "Drawing: Cluster Layout":
220
- display_cluster_layout()
221
- else:
222
- st.write("Please select a valid option from the sidebar.")
 
1
  import streamlit as st
 
2
  import matplotlib.pyplot as plt
3
+ import networkx as nx
4
+ import numpy as np
5
 
6
  # Sidebar for selecting an option
7
  sidebar_option = st.sidebar.radio("Select an option",
8
  ["Select an option", "Basic: Properties",
9
  "Basic: Read and write graphs", "Basic: Simple graph",
10
+ "Basic: Simple graph Directed", "Drawing: Custom Node Position"])
 
11
 
12
  # Helper function to draw and display graph
13
+ def draw_graph(G, pos=None, title="Graph Visualization"):
14
+ plt.figure(figsize=(8, 6))
15
+ nx.draw(G, pos=pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_weight='bold')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  st.pyplot(plt)
17
 
18
+ # Function to display properties and graph for Basic: Properties
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  def display_graph_properties(G):
20
  pathlengths = []
21
  st.write("### Source vertex {target:length, }")
 
30
 
31
  dist = {}
32
  for p in pathlengths:
33
+ dist[p] = dist.get(p, 0) + 1
 
 
 
 
34
  st.write("### Length #paths")
35
  for d in sorted(dist.keys()):
36
  st.write(f"Length {d}: {dist[d]} paths")
 
43
  st.write(f"Periphery: {nx.periphery(G)}")
44
  st.write(f"Density: {nx.density(G)}")
45
 
46
+ # Visualize the graph
47
  st.write("### Graph Visualization")
48
+ pos = nx.spring_layout(G, seed=3068) # Seed layout for reproducibility
49
+ draw_graph(G, pos)
50
+
51
+ # Function to display graph for Basic: Read and write graphs
52
+ def display_read_write_graph(G):
53
+ st.write("### Adjacency List:")
54
+ for line in nx.generate_adjlist(G):
55
+ st.write(line)
56
+
57
+ # Write the graph's edge list to a file
58
+ st.write("### Writing Edge List to 'grid.edgelist' file:")
59
+ nx.write_edgelist(G, path="grid.edgelist", delimiter=":")
60
+ st.write("Edge list written to 'grid.edgelist'")
61
+
62
+ # Read the graph from the edge list
63
+ st.write("### Reading Edge List from 'grid.edgelist' file:")
64
+ H = nx.read_edgelist(path="grid.edgelist", delimiter=":")
65
+ st.write("Edge list read into graph H")
66
+
67
+ # Visualize the graph
68
+ st.write("### Graph Visualization:")
69
+ pos = nx.spring_layout(H, seed=200) # Seed for reproducibility
70
+ draw_graph(H, pos)
71
+
72
+ # Function to display Simple Graphs for Basic: Simple graph
73
+ def display_simple_graph(G, pos=None):
74
+ options = {
75
+ "font_size": 36,
76
+ "node_size": 3000,
77
+ "node_color": "white",
78
+ "edgecolors": "black",
79
+ "linewidths": 5,
80
+ "width": 5,
81
+ }
82
+
83
+ # Draw the network
84
+ nx.draw_networkx(G, pos, **options)
85
+
86
+ # Set margins for the axes so that nodes aren't clipped
87
+ ax = plt.gca()
88
+ ax.margins(0.20)
89
+ plt.axis("off")
90
+ st.pyplot(plt)
91
+
92
+ # Function to display Simple Directed Graphs for Basic: Simple graph Directed
93
+ def display_simple_directed_graph(G, pos=None):
94
+ options = {
95
+ "node_size": 500,
96
+ "node_color": "lightblue",
97
+ "arrowsize": 20,
98
+ "width": 2,
99
+ "edge_color": "gray",
100
+ }
101
+
102
+ # Draw the directed graph with the given positions and options
103
+ nx.draw_networkx(G, pos, **options)
104
+
105
+ # Set margins for the axes so that nodes aren't clipped
106
+ ax = plt.gca()
107
+ ax.margins(0.20)
108
+ plt.axis("off")
109
  st.pyplot(plt)
110
 
111
+ # Function to display Custom Node Position Graphs for Drawing: Custom Node Position
112
+ def display_custom_node_position():
113
+ st.title("Drawing: Custom Node Position")
114
+
115
+ # Default example graph (path graph with custom node position)
116
+ G = nx.path_graph(20)
117
+ center_node = 5
118
+ edge_nodes = set(G) - {center_node}
119
+
120
+ # Ensure the nodes around the circle are evenly distributed
121
+ pos = nx.circular_layout(G.subgraph(edge_nodes))
122
+ pos[center_node] = np.array([0, 0]) # Manually specify node position
123
+
124
+ # Draw the graph
125
+ draw_graph(G, pos)
126
+
127
+ # Display Basic: Properties if selected
128
+ if sidebar_option == "Basic: Properties":
129
+ st.title("Basic: Properties")
130
+ option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
131
+
132
+ if option == "Default Example":
133
+ G = nx.lollipop_graph(4, 6)
134
+ display_graph_properties(G)
135
+
136
+ elif option == "Create your own":
137
+ num_nodes = st.number_input("Number of nodes:", min_value=2, max_value=50, value=5)
138
+ num_edges = st.number_input("Number of edges per group (for lollipop graph):", min_value=1, max_value=10, value=3)
139
+
140
+ if st.button("Generate"):
141
+ if num_nodes >= 2 and num_edges >= 1:
142
+ G_custom = nx.lollipop_graph(num_nodes, num_edges)
143
+ display_graph_properties(G_custom)
144
+
145
+ # Display Basic: Read and write graphs if selected
146
+ elif sidebar_option == "Basic: Read and write graphs":
147
  st.title("Basic: Read and write graphs")
148
+ option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
149
 
150
+ if option == "Default Example":
151
+ G = nx.grid_2d_graph(5, 5)
152
+ display_read_write_graph(G)
153
 
154
+ elif option == "Create your own":
155
+ rows = st.number_input("Number of rows:", min_value=2, max_value=20, value=5)
156
+ cols = st.number_input("Number of columns:", min_value=2, max_value=20, value=5)
 
 
157
 
158
+ if st.button("Generate"):
159
+ if rows >= 2 and cols >= 2:
160
+ G_custom = nx.grid_2d_graph(rows, cols)
161
+ display_read_write_graph(G_custom)
162
+
163
+ # Display Basic: Simple Graph if selected
164
+ elif sidebar_option == "Basic: Simple graph":
165
  st.title("Basic: Simple graph")
166
+ option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
167
+
168
+ if option == "Default Example":
169
+ G = nx.Graph()
170
+ G.add_edge(1, 2)
171
+ G.add_edge(1, 3)
172
+ G.add_edge(1, 5)
173
+ G.add_edge(2, 3)
174
+ G.add_edge(3, 4)
175
+ G.add_edge(4, 5)
176
+
177
+ pos = {1: (0, 0), 2: (-1, 0.3), 3: (2, 0.17), 4: (4, 0.255), 5: (5, 0.03)}
178
+ display_simple_graph(G, pos)
179
+
180
+ elif option == "Create your own":
181
+ edges = []
182
+ edge_input = st.text_area("Edges:", value="1,2\n1,3\n2,3")
183
+ if edge_input:
184
+ edge_list = edge_input.split("\n")
185
+ for edge in edge_list:
186
+ u, v = map(int, edge.split(","))
187
+ edges.append((u, v))
188
+
189
+ if st.button("Generate"):
190
+ G_custom = nx.Graph()
191
+ G_custom.add_edges_from(edges)
192
+ pos = nx.spring_layout(G_custom, seed=42)
193
+ display_simple_graph(G_custom, pos)
194
 
195
+ # Display Basic: Simple Directed Graph if selected
196
+ elif sidebar_option == "Basic: Simple graph Directed":
197
  st.title("Basic: Simple graph Directed")
198
+ option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
 
 
199
 
200
+ if option == "Default Example":
201
+ G = nx.DiGraph([(0, 3), (1, 3), (2, 4), (3, 5), (3, 6), (4, 6), (5, 6)])
202
 
203
+ left_nodes = [0, 1, 2]
204
+ middle_nodes = [3, 4]
205
+ right_nodes = [5, 6]
206
 
207
+ pos = {n: (0, i) for i, n in enumerate(left_nodes)}
208
+ pos.update({n: (1, i + 0.5) for i, n in enumerate(middle_nodes)})
209
+ pos.update({n: (2, i + 0.5) for i, n in enumerate(right_nodes)})
210
 
211
+ display_simple_directed_graph(G, pos)
 
 
212
 
213
+ elif option == "Create your own":
214
+ edges = []
215
+ edge_input = st.text_area("Edges:", value="1,2\n1,3\n2,3")
216
+ if edge_input:
217
+ edge_list = edge_input.split("\n")
218
+ for edge in edge_list:
219
+ u, v = map(int, edge.split(","))
220
+ edges.append((u, v))
221
 
222
+ if st.button("Generate"):
223
+ G_custom = nx.DiGraph()
224
+ G_custom.add_edges_from(edges)
225
+ pos = nx.spring_layout(G_custom, seed=42)
226
+ display_simple_directed_graph(G_custom, pos)
227
 
228
+ # Display Drawing: Custom Node Position if selected
 
 
 
 
 
 
 
 
229
  elif sidebar_option == "Drawing: Custom Node Position":
230
+ display_custom_node_position()