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)