pythonGenerator.ts•8.27 kB
import { Person, Connection, NetworkAnalysis } from './types.js';
export class PythonCodeGenerator {
generateNetworkVisualization(people: Person[], connections: Connection[]): string {
const peopleData = JSON.stringify(people, null, 2);
const connectionsData = JSON.stringify(connections, null, 2);
return `
import networkx as nx
import matplotlib.pyplot as plt
import json
from matplotlib.patches import FancyBboxPatch
import numpy as np
# Data from evidence analysis
people_data = ${peopleData}
connections_data = ${connectionsData}
# Create a directed graph
G = nx.DiGraph()
# Add nodes (people) with attributes
for person in people_data:
G.add_node(person['name'],
organization=person.get('organization', ''),
role=person.get('role', ''))
# Add edges (connections) with weights
for connection in connections_data:
G.add_edge(connection['from'],
connection['to'],
relationship=connection['relationship'],
strength=connection['strength'],
evidence=connection['evidence'],
type=connection['type'])
# Create visualization
plt.figure(figsize=(16, 12))
# Use spring layout for better node positioning
pos = nx.spring_layout(G, k=3, iterations=50, seed=42)
# Define colors for different organizations
org_colors = {
'OpenAI': '#FF6B6B',
'Microsoft': '#4ECDC4',
'Meta': '#45B7D1',
'X': '#FFA07A',
'Tesla': '#98D8C8',
'SpaceX': '#FFCE56',
'': '#DDD' # Default color for unknown org
}
# Get node colors based on organization
node_colors = []
node_sizes = []
for node in G.nodes():
org = G.nodes[node].get('organization', '')
node_colors.append(org_colors.get(org, org_colors['']))
# Size based on degree centrality
centrality = nx.degree_centrality(G)[node]
node_sizes.append(1000 + centrality * 3000)
# Draw nodes
nx.draw_networkx_nodes(G, pos,
node_color=node_colors,
node_size=node_sizes,
alpha=0.8,
edgecolors='black',
linewidths=2)
# Draw edges with different styles based on connection strength
edge_colors = []
edge_widths = []
edge_styles = []
for edge in G.edges(data=True):
strength = edge[2]['strength']
conn_type = edge[2]['type']
# Color based on connection type
if conn_type == 'communication':
edge_colors.append('#FF6B6B')
elif conn_type == 'meeting':
edge_colors.append('#4ECDC4')
elif conn_type == 'witness':
edge_colors.append('#FFD93D')
else:
edge_colors.append('#999999')
# Width based on strength
edge_widths.append(max(1, strength / 2))
# Style based on strength
if strength >= 7:
edge_styles.append('solid')
elif strength >= 4:
edge_styles.append('dashed')
else:
edge_styles.append('dotted')
# Draw edges
for i, edge in enumerate(G.edges()):
nx.draw_networkx_edges(G, pos,
edgelist=[edge],
edge_color=edge_colors[i],
width=edge_widths[i],
style=edge_styles[i],
alpha=0.7,
arrowsize=20,
arrowstyle='->')
# Add labels
labels = {}
for node in G.nodes():
name = node
org = G.nodes[node].get('organization', '')
role = G.nodes[node].get('role', '')
label = name
if role:
label += f"\\n({role})"
if org:
label += f"\\n[{org}]"
labels[node] = label
nx.draw_networkx_labels(G, pos, labels, font_size=8, font_weight='bold')
# Add edge labels for strong connections
strong_edges = [(u, v) for u, v, d in G.edges(data=True) if d['strength'] >= 6]
edge_labels = {}
for u, v in strong_edges:
edge_data = G[u][v]
edge_labels[(u, v)] = f"{edge_data['relationship']}\\n(strength: {edge_data['strength']})"
nx.draw_networkx_edge_labels(G, pos, edge_labels, font_size=6)
# Add title and legend
plt.title("Network Analysis of People and Connections\\nBased on Evidence Analysis",
fontsize=16, fontweight='bold', pad=20)
# Create legend for organizations
legend_elements = []
for org, color in org_colors.items():
if org and any(G.nodes[node].get('organization', '') == org for node in G.nodes()):
legend_elements.append(plt.Line2D([0], [0], marker='o', color='w',
markerfacecolor=color, markersize=10,
label=org, markeredgecolor='black'))
if legend_elements:
plt.legend(handles=legend_elements, loc='upper left', bbox_to_anchor=(0.02, 0.98))
# Add connection type legend
connection_legend = [
plt.Line2D([0], [0], color='#FF6B6B', linewidth=2, label='Communication'),
plt.Line2D([0], [0], color='#4ECDC4', linewidth=2, label='Meeting'),
plt.Line2D([0], [0], color='#FFD93D', linewidth=2, label='Witness'),
plt.Line2D([0], [0], color='#999999', linewidth=2, label='Other')
]
plt.legend(handles=connection_legend, loc='upper right', bbox_to_anchor=(0.98, 0.98))
plt.axis('off')
plt.tight_layout()
# Print network statistics
print("=== NETWORK ANALYSIS REPORT ===")
print(f"Total people identified: {G.number_of_nodes()}")
print(f"Total connections found: {G.number_of_edges()}")
print("\\n--- Central Figures (by degree centrality) ---")
centrality = nx.degree_centrality(G)
sorted_centrality = sorted(centrality.items(), key=lambda x: x[1], reverse=True)
for person, score in sorted_centrality[:5]:
org = G.nodes[person].get('organization', 'Unknown')
print(f"{person} ({org}): {score:.3f}")
print("\\n--- Strongest Connections ---")
strongest_connections = sorted([(u, v, d['strength'], d['relationship'])
for u, v, d in G.edges(data=True)],
key=lambda x: x[2], reverse=True)
for conn in strongest_connections[:5]:
print(f"{conn[0]} -> {conn[1]}: {conn[3]} (strength: {conn[2]})")
print("\\n--- Organizations Involved ---")
orgs = set()
for node in G.nodes():
org = G.nodes[node].get('organization', '')
if org:
orgs.add(org)
for org in sorted(orgs):
members = [node for node in G.nodes() if G.nodes[node].get('organization', '') == org]
print(f"{org}: {', '.join(members)}")
# Show the plot
plt.show()
# Optionally save the plot
# plt.savefig('network_analysis.png', dpi=300, bbox_inches='tight')
print("\\nVisualization complete. Close the plot window to exit.")
`;
}
generateClusterAnalysis(people: Person[], connections: Connection[]): string[][] {
const clusters: string[][] = [];
const processed = new Set<string>();
for (const person of people) {
if (processed.has(person.name)) continue;
const cluster = [person.name];
processed.add(person.name);
// Find all people connected to this person
for (const connection of connections) {
if (connection.strength >= 5) { // Strong connections only
if (connection.from === person.name && !processed.has(connection.to)) {
cluster.push(connection.to);
processed.add(connection.to);
} else if (connection.to === person.name && !processed.has(connection.from)) {
cluster.push(connection.from);
processed.add(connection.from);
}
}
}
if (cluster.length > 1) {
clusters.push(cluster);
}
}
return clusters;
}
identifyCentralFigures(people: Person[], connections: Connection[]): string[] {
const connectionCounts = new Map<string, number>();
// Count connections for each person
for (const person of people) {
connectionCounts.set(person.name, 0);
}
for (const connection of connections) {
connectionCounts.set(connection.from, (connectionCounts.get(connection.from) || 0) + 1);
connectionCounts.set(connection.to, (connectionCounts.get(connection.to) || 0) + 1);
}
// Sort by connection count and return top figures
return Array.from(connectionCounts.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, Math.min(5, people.length))
.map(([name]) => name);
}
}