mgbam commited on
Commit
7117e78
Β·
verified Β·
1 Parent(s): 7e2c73b

Update mcp/graph_metrics.py

Browse files
Files changed (1) hide show
  1. mcp/graph_metrics.py +38 -9
mcp/graph_metrics.py CHANGED
@@ -1,31 +1,60 @@
1
- # mcp/graph_metrics.py
2
  """
3
- Basic graph-analytics helpers (pure CPU, no heavy maths):
4
- β€’ build_nx – convert agraph nodes/edges β†’ NetworkX graph
5
- β€’ get_top_hubs – return top-k nodes by degree-centrality
6
- β€’ get_density – overall graph density
 
 
 
 
 
 
 
7
  """
8
 
9
  from typing import List, Dict, Tuple
10
  import networkx as nx
11
 
 
12
  # ----------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
13
  def build_nx(nodes: List[Dict], edges: List[Dict]) -> nx.Graph:
 
 
 
 
 
 
14
  G = nx.Graph()
 
 
15
  for n in nodes:
16
  G.add_node(n["id"], label=n.get("label", n["id"]))
 
 
17
  for e in edges:
18
- G.add_edge(e["source"], e["target"])
 
 
 
19
  return G
20
 
21
 
 
22
  def get_top_hubs(G: nx.Graph, k: int = 5) -> List[Tuple[str, float]]:
23
- """
24
- Return [(node_id, centrality)] sorted desc.
25
- """
26
  dc = nx.degree_centrality(G)
27
  return sorted(dc.items(), key=lambda x: x[1], reverse=True)[:k]
28
 
29
 
30
  def get_density(G: nx.Graph) -> float:
 
31
  return nx.density(G)
 
 
1
  """
2
+ Basic NetworkX helpers for MedGenesis graphs.
3
+
4
+ Key improvement:
5
+ build_nx() now accepts edge dictionaries in either of the two
6
+ common formats:
7
+
8
+ β€’ {'source': 'n1', 'target': 'n2'} (Streamlit-agraph)
9
+ β€’ {'from': 'n1', 'to': 'n2'} (PyVis)
10
+
11
+ This prevents KeyError crashes when nodes / edges come from different
12
+ UI toolchains.
13
  """
14
 
15
  from typing import List, Dict, Tuple
16
  import networkx as nx
17
 
18
+
19
  # ----------------------------------------------------------------------
20
+ def _edge_endpoints(e: Dict) -> Tuple[str, str] | None:
21
+ """Return (src, dst) if both ends exist; otherwise None."""
22
+ src = e.get("source") or e.get("from")
23
+ dst = e.get("target") or e.get("to")
24
+ if src and dst:
25
+ return src, dst
26
+ return None
27
+
28
+
29
  def build_nx(nodes: List[Dict], edges: List[Dict]) -> nx.Graph:
30
+ """
31
+ Convert agraph/PyVis node+edge dicts into a NetworkX Graph.
32
+
33
+ * Skips malformed edges rather than raising KeyError.
34
+ * Node label stored as attribute 'label'.
35
+ """
36
  G = nx.Graph()
37
+
38
+ # add nodes
39
  for n in nodes:
40
  G.add_node(n["id"], label=n.get("label", n["id"]))
41
+
42
+ # add edges
43
  for e in edges:
44
+ endpoints = _edge_endpoints(e)
45
+ if endpoints:
46
+ G.add_edge(*endpoints)
47
+
48
  return G
49
 
50
 
51
+ # ----------------------------------------------------------------------
52
  def get_top_hubs(G: nx.Graph, k: int = 5) -> List[Tuple[str, float]]:
53
+ """Top-k nodes by degree centrality."""
 
 
54
  dc = nx.degree_centrality(G)
55
  return sorted(dc.items(), key=lambda x: x[1], reverse=True)[:k]
56
 
57
 
58
  def get_density(G: nx.Graph) -> float:
59
+ """Return graph density in [0,1]."""
60
  return nx.density(G)