mgbam commited on
Commit
eadeaf9
·
verified ·
1 Parent(s): e202a39

Update mcp/knowledge_graph.py

Browse files
Files changed (1) hide show
  1. mcp/knowledge_graph.py +52 -62
mcp/knowledge_graph.py CHANGED
@@ -3,56 +3,55 @@
3
  from streamlit_agraph import Node, Edge, Config
4
  import re
5
 
6
- # Colors for graph nodes
7
- EDGE_COLOR = "#888"
8
- DRUG_COLOR = "#f39c12"
9
- CONCEPT_COLOR = "#00b894"
10
- PAPER_COLOR = "#3498db"
11
- HL_COLOR = "#f1c40f"
12
- DIM_COLOR = "#d3d3d3"
13
 
14
  def build_agraph(papers, umls, drug_safety):
15
  """
16
- Build a Streamlit-agraph network:
17
- - papers: list of PubMed/arXiv dicts
18
- - umls: list of UMLSConcept dicts (may have None values)
19
- - drug_safety: list of OpenFDA/other dicts
20
- Returns (nodes, edges, config)
21
  """
22
  nodes, edges = [], []
23
 
24
- # --- Add UMLS concept nodes ---
25
- for c in (umls or []):
26
- cui = c.get("cui") if c else None
27
- name = c.get("name") if c else None
28
- if not cui or not name:
29
  continue
30
- node_id = f"concept_{cui}"
31
- nodes.append(Node(id=node_id, label=name, size=22, color=CONCEPT_COLOR))
 
 
 
 
 
 
32
 
33
- # --- Add Drug nodes ---
34
- drug_ids = []
35
- for i, drug_blob in enumerate(drug_safety or []):
36
- # Support both list and dict style safety reports
37
- if not drug_blob:
38
  continue
39
- reports = drug_blob if isinstance(drug_blob, list) else [drug_blob]
40
- for j, rec in enumerate(reports):
41
- label = (
42
- rec.get("drug_name")
43
- or rec.get("patient", {}).get("drug")
44
- or rec.get("medicinalproduct")
45
- or f"drug_{i}_{j}"
46
- )
47
- drug_id = f"drug_{i}_{j}"
48
- drug_ids.append((drug_id, label))
49
- nodes.append(Node(id=drug_id, label=label, size=25, color=DRUG_COLOR))
 
 
50
 
51
- # --- Add Paper nodes and connect to concepts/drugs ---
52
  for k, p in enumerate(papers or []):
53
  pid = f"paper_{k}"
54
- title = p.get("title", f"Paper {k+1}")
55
- summary = p.get("summary", "")
56
  label = f"P{k+1}"
57
  nodes.append(Node(
58
  id=pid,
@@ -62,31 +61,22 @@ def build_agraph(papers, umls, drug_safety):
62
  color=PAPER_COLOR,
63
  ))
64
  txt = (title + " " + summary).lower()
 
 
 
 
 
 
 
 
 
 
65
 
66
- # Link to UMLS concepts if concept name in paper
67
- for c in (umls or []):
68
- cui = c.get("cui") if c else None
69
- name = c.get("name") if c else None
70
- if cui and name and isinstance(name, str) and name.lower() in txt:
71
- edges.append(Edge(source=pid, target=f"concept_{cui}", color=EDGE_COLOR))
72
-
73
- # Link to drug nodes if drug name appears in paper
74
- for drug_id, drug_name in drug_ids:
75
- if drug_name and isinstance(drug_name, str) and drug_name.lower() in txt:
76
- edges.append(Edge(source=pid, target=drug_id, color=EDGE_COLOR))
77
-
78
- # --- Graph config with physics enabled ---
79
- cfg = Config(
80
- width="100%",
81
- height="520",
82
- directed=False,
83
- physics=True,
84
- repulsion=True,
85
- nodeHighlightBehavior=True,
86
- highlightColor=HL_COLOR,
87
  collapsible=True,
88
  node={"labelProperty": "label"},
89
- edge={"color": EDGE_COLOR, "width": 1},
90
  )
91
- return nodes, edges, cfg
92
-
 
3
  from streamlit_agraph import Node, Edge, Config
4
  import re
5
 
6
+ # Set colors for node types
7
+ PAPER_COLOR = "#0984e3"
8
+ UMLS_COLOR = "#00b894"
9
+ DRUG_COLOR = "#d35400"
 
 
 
10
 
11
  def build_agraph(papers, umls, drug_safety):
12
  """
13
+ Build interactive agraph nodes and edges.
14
+ Defensive: handles unexpected types gracefully.
 
 
 
15
  """
16
  nodes, edges = [], []
17
 
18
+ # UMLS nodes
19
+ for c in umls or []:
20
+ if not isinstance(c, dict):
 
 
21
  continue
22
+ cui = str(c.get("cui", "") or "")
23
+ name = str(c.get("name", "") or "")
24
+ if cui and name:
25
+ nid = f"concept_{cui}"
26
+ nodes.append(Node(
27
+ id=nid, label=name, size=25, color=UMLS_COLOR,
28
+ tooltip=f"UMLS {cui}: {name}"
29
+ ))
30
 
31
+ # Drug nodes
32
+ drug_names = []
33
+ for i, dr in enumerate(drug_safety or []):
34
+ if not dr:
 
35
  continue
36
+ # Normalize to single dict
37
+ recs = dr if isinstance(dr, list) else [dr]
38
+ for j, rec in enumerate(recs):
39
+ if not isinstance(rec, dict):
40
+ continue
41
+ dn = rec.get("drug_name") \
42
+ or (rec.get("patient", {}) or {}).get("drug", "") \
43
+ or rec.get("medicinalproduct", "")
44
+ dn = str(dn or f"drug_{i}_{j}")
45
+ did = f"drug_{i}_{j}"
46
+ drug_names.append((did, dn))
47
+ nodes.append(Node(id=did, label=dn, size=25, color=DRUG_COLOR,
48
+ tooltip=f"Drug: {dn}"))
49
 
50
+ # Paper nodes and edges
51
  for k, p in enumerate(papers or []):
52
  pid = f"paper_{k}"
53
+ title = str(p.get("title", f"Paper {k+1}"))
54
+ summary = str(p.get("summary", ""))
55
  label = f"P{k+1}"
56
  nodes.append(Node(
57
  id=pid,
 
61
  color=PAPER_COLOR,
62
  ))
63
  txt = (title + " " + summary).lower()
64
+ # Link to concepts
65
+ for c in umls or []:
66
+ name = str(c.get("name", "") or "")
67
+ cui = str(c.get("cui", "") or "")
68
+ if name and name.lower() in txt and cui:
69
+ edges.append(Edge(source=pid, target=f"concept_{cui}", label="mentions"))
70
+ # Link to drugs
71
+ for did, dn in drug_names:
72
+ if dn and dn.lower() in txt:
73
+ edges.append(Edge(source=pid, target=did, label="mentions"))
74
 
75
+ config = Config(
76
+ width="100%", height="600", directed=False,
77
+ nodeHighlightBehavior=True, highlightColor="#f1c40f",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  collapsible=True,
79
  node={"labelProperty": "label"},
80
+ link={"labelProperty": "label"},
81
  )
82
+ return nodes, edges, config