|
|
|
|
|
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() |
|
|
|
|
|
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 |
|
|
|
|
|
drug_nodes = {} |
|
for drug_report in drugs: |
|
if isinstance(drug_report, list): |
|
|
|
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 |
|
|
|
|
|
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']}") |
|
|
|
|
|
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") |
|
|
|
|
|
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") |
|
|
|
|
|
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") |
|
|
|
|
|
temp_path = tempfile.NamedTemporaryFile(delete=False, suffix=".html").name |
|
net.show(temp_path) |
|
return temp_path |
|
|