topicBuzz / visualizeTopic.py
Wyomike's picture
Init commit for hf
de99ac3
Raw
History Blame Contribute Delete
3.88 kB
import networkx as nx
from pyvis.network import Network
import pickle
import os
import random
# --- CONFIGURATION ---
CACHE_FILE = "mastodon_network.pkl"
OUTPUT_FILE = "topic_explorer.html"
# --- 1. Load Cache ---
if not os.path.exists(CACHE_FILE):
print("Please run 'build_graph_cache.py' first!")
exit()
print("Loading graph cache...")
with open(CACHE_FILE, 'rb') as f:
G = pickle.load(f)
print(f"Graph loaded! ({G.number_of_nodes()} nodes)")
# --- 2. Select Topic ---
while True:
print("\n--- Options ---")
print("1. Enter a Topic ID")
print("2. Pick a Random Topic")
print("q. Quit")
choice = input("Choice: ").strip()
if choice == 'q': break
target_topic_node = ""
if choice == '2':
# Find all nodes that start with "Topic_"
topic_nodes = [n for n in G.nodes if n.startswith("Topic_")]
target_topic_node = random.choice(topic_nodes)
# Get pretty label if available
label = G.nodes[target_topic_node].get('label', target_topic_node)
print(f"Selected random topic: {label}")
elif choice == '1':
tid = input("Enter Topic ID (e.g. 5): ").strip()
target_topic_node = f"Topic_{tid}"
if target_topic_node not in G:
print("❌ Topic not found in graph!")
continue
# --- 3. Extract Subgraph ---
print(f"\nExploring: {target_topic_node}")
print("1. View Participants (Users in this topic)")
print("2. View Ecosystem (Users + Other Topics they visit)")
depth = input("Select Depth (1 or 2): ").strip()
radius = int(depth) if depth in ['1', '2'] else 1
print(f"Extracting subgraph...")
# Get the "Ego Graph" centered on the topic
subgraph = nx.ego_graph(G, target_topic_node, radius=radius)
# Pruning for Radius 2 (Ecosystem) to prevent browser crash
# If a topic has 1000 users, and each visits 10 other topics, that's 10,000 nodes.
MAX_NODES = 1000
if subgraph.number_of_nodes() > MAX_NODES:
print(f"⚠️ Graph is massive ({subgraph.number_of_nodes()} nodes). trimming...")
# Priority 1: Keep the main Topic
nodes_to_keep = {target_topic_node}
# Priority 2: Keep its direct Users (Neighbors)
direct_users = list(G.neighbors(target_topic_node))
# If too many users, sample them
if len(direct_users) > 300:
direct_users = random.sample(direct_users, 300)
nodes_to_keep.update(direct_users)
# Priority 3 (Only if Radius=2): Keep 'Related Topics' connected to those users
if radius == 2:
related_topics = []
for u in direct_users:
# Find other topics this user visited
topics_visited = [n for n in G.neighbors(u) if n.startswith("Topic_") and n != target_topic_node]
related_topics.extend(topics_visited)
# Keep top 50 most frequent related topics
from collections import Counter
common_related = [t for t, c in Counter(related_topics).most_common(50)]
nodes_to_keep.update(common_related)
subgraph = G.subgraph(list(nodes_to_keep))
# --- 4. Visualize ---
nt = Network(height="750px", width="100%", bgcolor="#222222", font_color="white")
nt.from_nx(subgraph)
# Highlight the main Topic in Red/Gold
if target_topic_node in nt.get_nodes():
for node in nt.nodes:
if node['id'] == target_topic_node:
node['color'] = "#FFD700" # Gold
node['size'] = 40
break
# Physics settings for a nice spread
nt.barnes_hut(gravity=-4000, central_gravity=0.1, spring_length=150)
nt.save_graph(OUTPUT_FILE)
print(f"✅ Visualization saved to '{OUTPUT_FILE}'")