MCP_Res / mcp /knowledge_graph.py
mgbam's picture
Update mcp/knowledge_graph.py
447d959 verified
raw
history blame
2.72 kB
# mcp/knowledge_graph.py
from pyvis.network import Network
import tempfile
import jinja2
assert jinja2.Environment is not None
def build_knowledge_graph(papers, umls, drugs):
"""
Build and return a pyvis Network object representing the knowledge graph.
Nodes: papers, UMLS concepts, drugs.
Edges: paper–concept, paper–drug, drug–concept.
"""
net = Network(height="550px", width="100%", bgcolor="#f3eaff", font_color="#222222", notebook=False, directed=False)
net.force_atlas_2based() # More visually appealing layout
# Add UMLS concept nodes
concept_nodes = {}
for concept in umls:
if concept["cui"]:
node_id = f"concept_{concept['cui']}"
net.add_node(node_id, label=concept["name"], color="#00b894", title=f"UMLS: {concept['cui']}\n{concept['definition'] or ''}")
concept_nodes[concept['name']] = node_id
# Add drug nodes
drug_nodes = {}
for drug_report in drugs:
if isinstance(drug_report, list):
# OpenFDA can return a list of dicts
for d in drug_report:
if "safety_report_id" in d:
node_id = f"drug_{d['safety_report_id']}"
drug_name = d.get('reactions', ['drug'])[0] if d.get('reactions') else 'drug'
net.add_node(node_id, label=drug_name, color="#d35400", title=str(d))
drug_nodes[drug_name] = node_id
# Add paper nodes and edges to concepts and drugs
for i, paper in enumerate(papers, 1):
paper_id = f"paper_{i}"
net.add_node(paper_id, label=paper["title"][:40] + "...", color="#0984e3", title=f"{paper['title']}\n{paper['summary']}\n{paper['link']}")
# Link paper to concepts by presence in summary/title
for cname, concept_id in concept_nodes.items():
if cname.lower() in (paper["summary"] + paper["title"]).lower():
net.add_edge(paper_id, concept_id, color="#00b894")
# Link paper to drugs if drug name is present in summary/title
for dname, drug_id in drug_nodes.items():
if dname.lower() in (paper["summary"] + paper["title"]).lower():
net.add_edge(paper_id, drug_id, color="#d35400")
# Optionally: link concepts to drugs if name overlap
for cname, concept_id in concept_nodes.items():
for dname, drug_id in drug_nodes.items():
if cname.lower() in dname.lower() or dname.lower() in cname.lower():
net.add_edge(concept_id, drug_id, color="#636e72")
# Save and return path to HTML
temp_path = tempfile.NamedTemporaryFile(delete=False, suffix=".html").name
net.show(temp_path)
return temp_path