Unfaithful's picture
Update app.py
f4edfd4 verified
import random
import gradio as gr
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from matplotlib.colors import to_hex
import threading
from io import BytesIO
from PIL import Image
lock = threading.Lock()
class Node:
def __init__(self, x, y, value=1.0):
self.x = x
self.y = y
self.value = value
self.connections = []
def connect(self, other_node):
if other_node not in self.connections:
self.connections.append(other_node)
def grow(self, increment=0.1):
self.value = min(self.value + increment, 5.0)
class Network:
def __init__(self):
self.nodes = []
def add_node(self, x, y):
with lock:
new_node = Node(x, y, value=random.uniform(1.0, 2.0))
self.nodes.append(new_node)
return new_node
def connect_nodes(self, distance_threshold=75):
with lock:
for node1 in self.nodes:
for node2 in self.nodes:
if node1 != node2 and self.distance(node1, node2) < distance_threshold:
node1.connect(node2)
def grow_nodes(self):
with lock:
for node in self.nodes:
node.grow()
def reset(self):
with lock:
self.nodes = []
def render(self):
with lock:
G = nx.Graph()
for i, node in enumerate(self.nodes):
G.add_node(i, pos=(node.x, node.y), size=node.value*100, color=self.get_color(node.value))
for i, node in enumerate(self.nodes):
for conn in node.connections:
j = self.nodes.index(conn)
G.add_edge(i, j)
pos = nx.get_node_attributes(G, 'pos')
sizes = [data['size'] for _, data in G.nodes(data=True)]
colors = [data['color'] for _, data in G.nodes(data=True)]
plt.figure(figsize=(8,8))
nx.draw(G, pos, with_labels=False, node_size=sizes, node_color=colors, edge_color="gray")
plt.axis('off')
plt.tight_layout()
# Save the plot to an in-memory buffer
buf = BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
plt.close()
# Return a PIL image
return Image.open(buf)
@staticmethod
def get_color(value):
gradient = plt.cm.coolwarm
return to_hex(gradient(value / 5))
@staticmethod
def distance(node1, node2):
return np.sqrt((node1.x - node2.x)**2 + (node1.y - node2.y)**2)
network = Network()
def interact_network(x, y):
network.add_node(x, y)
network.connect_nodes()
network.grow_nodes()
return network.render()
def random_node():
x, y = random.randint(50, 450), random.randint(50, 450)
return interact_network(x, y)
def reset_network():
network.reset()
return network.render()
with gr.Blocks() as demo:
gr.Markdown("# Compassion Network (In-Memory Image Example)")
gr.Markdown("Add nodes and watch them grow and connect. Click Reset to start over.")
with gr.Row():
with gr.Column():
x_input = gr.Number(label="X Position", value=random.randint(50,450))
y_input = gr.Number(label="Y Position", value=random.randint(50,450))
add_button = gr.Button("Add Node")
random_button = gr.Button("Add Random Node")
reset_button = gr.Button("Reset Network")
with gr.Column():
graph_output = gr.Image(type="pil", interactive=False)
# Initialize the graph with an empty image
graph_output.update(value=network.render())
add_button.click(interact_network, inputs=[x_input, y_input], outputs=graph_output)
random_button.click(random_node, inputs=None, outputs=graph_output)
reset_button.click(reset_network, inputs=None, outputs=graph_output)
if __name__ == "__main__":
# Required for Hugging Face Spaces Docker
demo.launch(server_name="0.0.0.0", server_port=7860)