Spaces:
Sleeping
Sleeping
File size: 5,367 Bytes
faef703 5f71d94 937ad52 5f71d94 937ad52 5f71d94 937ad52 5f71d94 937ad52 5f71d94 937ad52 5f71d94 937ad52 5f71d94 937ad52 5f71d94 937ad52 5f71d94 937ad52 5f71d94 937ad52 5f71d94 faef703 937ad52 faef703 937ad52 faef703 937ad52 5f71d94 937ad52 5f71d94 937ad52 faef703 937ad52 faef703 937ad52 5f71d94 faef703 937ad52 faef703 937ad52 5f71d94 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# genesis/visualization.py
"""
Visualization utilities for GENESIS-AI
Generates interactive pathway and funding network graphs from Neo4j data.
"""
import os
import logging
from typing import List, Tuple, Optional
import plotly.graph_objects as go
# Optional Neo4j import
try:
from neo4j import GraphDatabase
except ImportError:
GraphDatabase = None
# =========================
# CONFIGURATION
# =========================
NEO4J_URI = os.getenv("NEO4J_URI")
NEO4J_USER = os.getenv("NEO4J_USER")
NEO4J_PASSWORD = os.getenv("NEO4J_PASSWORD")
COLOR_PATHWAY_NODE = "#00FF99" # Biotech green
COLOR_FUNDING_NODE = "#FF9900" # Orange
COLOR_EDGE = "#AAAAAA"
# =========================
# NEO4J CONNECTION
# =========================
driver = None
if GraphDatabase and NEO4J_URI and NEO4J_USER and NEO4J_PASSWORD:
try:
driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USER, NEO4J_PASSWORD))
logging.info("[Neo4j] Connected for visualization.")
except Exception as e:
logging.error(f"[Neo4j] Connection failed: {e}")
driver = None
else:
logging.info("[Neo4j] No URI/user/password set β skipping graph_tools connection.")
def run_neo4j_query(query: str, params: dict = None) -> list:
"""Run a Cypher query and return results."""
if not driver:
logging.warning("[Neo4j] No active connection β returning empty result.")
return []
with driver.session() as session:
return list(session.run(query, params or {}))
# =========================
# GRAPH UTILS
# =========================
def create_plotly_graph(nodes: List[Tuple[str, str, str]], edges: List[Tuple[str, str]], title: str):
"""Creates an interactive Plotly network graph."""
import networkx as nx
G = nx.Graph()
for node_id, label, color in nodes:
G.add_node(node_id, label=label, color=color)
for src, dst in edges:
G.add_edge(src, dst)
pos = nx.spring_layout(G, seed=42, k=0.5)
edge_x, edge_y = [], []
for src, dst in edges:
x0, y0 = pos[src]
x1, y1 = pos[dst]
edge_x.extend([x0, x1, None])
edge_y.extend([y0, y1, None])
node_x, node_y, node_text, node_color = [], [], [], []
for node_id, label, color in nodes:
x, y = pos[node_id]
node_x.append(x)
node_y.append(y)
node_text.append(label)
node_color.append(color)
edge_trace = go.Scatter(
x=edge_x, y=edge_y,
line=dict(width=1, color=COLOR_EDGE),
hoverinfo='none',
mode='lines'
)
node_trace = go.Scatter(
x=node_x, y=node_y,
mode='markers+text',
text=node_text,
textposition="top center",
hoverinfo="text",
marker=dict(
color=node_color,
size=18,
line=dict(width=2, color='#000000')
)
)
fig = go.Figure(data=[edge_trace, node_trace])
fig.update_layout(
title=title,
title_x=0.5,
plot_bgcolor="#111111",
paper_bgcolor="#111111",
font=dict(color="#FFFFFF"),
showlegend=False,
margin=dict(l=10, r=10, t=40, b=10)
)
return fig
# =========================
# PATHWAY GRAPH
# =========================
def generate_pathway_graph(pathway_name: str) -> Optional[go.Figure]:
"""
Generate an interactive graph for a given metabolic pathway.
Only takes pathway_name β matches pipeline.py signature.
"""
query = """
MATCH (p:Pathway {name: $name})-[r:INVOLVES]->(m:Molecule)
RETURN p.name AS pathway, m.name AS molecule
"""
results = run_neo4j_query(query, {"name": pathway_name})
if not results:
return None
nodes = [(pathway_name, pathway_name, COLOR_PATHWAY_NODE)]
edges = []
seen_nodes = {pathway_name}
for record in results:
mol_name = record["molecule"]
if mol_name not in seen_nodes:
nodes.append((mol_name, mol_name, "#00BFFF")) # Blue for molecules
seen_nodes.add(mol_name)
edges.append((pathway_name, mol_name))
return create_plotly_graph(nodes, edges, f"Metabolic Pathway: {pathway_name}")
# =========================
# FUNDING NETWORK
# =========================
def generate_funding_network(industry_keyword: str) -> Optional[go.Figure]:
"""
Generate an interactive funding network graph for companies in a given biotech domain.
"""
query = """
MATCH (c:Company)-[f:FUNDED_BY]->(i:Investor)
WHERE toLower(c.industry) CONTAINS toLower($keyword)
RETURN c.name AS company, i.name AS investor
"""
results = run_neo4j_query(query, {"keyword": industry_keyword})
if not results:
return None
nodes = []
edges = []
seen_nodes = set()
for record in results:
comp = record["company"]
inv = record["investor"]
if comp not in seen_nodes:
nodes.append((comp, comp, COLOR_FUNDING_NODE))
seen_nodes.add(comp)
if inv not in seen_nodes:
nodes.append((inv, inv, "#FFD700")) # Gold for investors
seen_nodes.add(inv)
edges.append((comp, inv))
return create_plotly_graph(nodes, edges, f"Funding Network: {industry_keyword}")
# =========================
# CLEANUP
# =========================
def close_driver():
if driver:
driver.close()
|