mgbam commited on
Commit
b7556e4
·
verified ·
1 Parent(s): 39219c6

Update mcp/graph_metrics.py

Browse files
Files changed (1) hide show
  1. mcp/graph_metrics.py +50 -7
mcp/graph_metrics.py CHANGED
@@ -1,20 +1,63 @@
 
1
  """
2
- Minimal NetworkX helpers for MedGenesis graphs.
 
 
 
 
 
 
 
3
  """
4
- import networkx as nx
 
5
  from typing import List, Dict, Tuple
6
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  def build_nx(nodes: List[Dict], edges: List[Dict]) -> nx.Graph:
 
 
 
 
 
 
 
8
  G = nx.Graph()
 
 
9
  for n in nodes:
10
- G.add_node(n["id"])
 
 
 
 
 
 
11
  for e in edges:
12
- G.add_edge(e["source"], e["target"])
 
 
 
13
  return G
14
 
15
- def get_density(G: nx.Graph) -> float:
16
- return nx.density(G)
17
 
18
- def get_top_hubs(G: nx.Graph, k: int = 5) -> List[Tuple[str, float]]:
 
19
  dc = nx.degree_centrality(G)
20
  return sorted(dc.items(), key=lambda x: x[1], reverse=True)[:k]
 
 
 
 
 
 
1
+ # mcp/graph_metrics.py
2
  """
3
+ Tiny NetworkX helpers with forgiving edge parsing.
4
+
5
+ Why this exists
6
+ ---------------
7
+ Your Streamlit-agraph edges carry keys ``source/target`` while other
8
+ toolchains (PyVis, cytoscape, etc.) use ``from/to``. A naïve
9
+ ``e["target"]`` lookup therefore raises **KeyError**. The functions below
10
+ accept either spelling and silently skip malformed edges.
11
  """
12
+
13
+ from __future__ import annotations
14
  from typing import List, Dict, Tuple
15
 
16
+ import networkx as nx
17
+
18
+
19
+ # ── private -----------------------------------------------------------------
20
+ def _endpoints(edge: Dict) -> Tuple[str, str] | None:
21
+ """Return (src,dst) tuple or *None* if either end is missing."""
22
+ src = edge.get("source") or edge.get("from")
23
+ dst = edge.get("target") or edge.get("to")
24
+ return (src, dst) if src and dst else None
25
+
26
+
27
+ # ── public helpers ----------------------------------------------------------
28
  def build_nx(nodes: List[Dict], edges: List[Dict]) -> nx.Graph:
29
+ """
30
+ Convert generic node/edge dictionaries into a NetworkX ``Graph``.
31
+
32
+ • Nodes are added with an attribute ``label`` (fallback: id).
33
+ • Edges are added only when both src & dst exist.
34
+ • **No KeyError** even if edge-schema is mixed.
35
+ """
36
  G = nx.Graph()
37
+
38
+ # nodes
39
  for n in nodes:
40
+ try:
41
+ G.add_node(n["id"], label=n.get("label", n["id"]))
42
+ except KeyError:
43
+ # ignore malformed node dicts
44
+ continue
45
+
46
+ # edges
47
  for e in edges:
48
+ ends = _endpoints(e)
49
+ if ends:
50
+ G.add_edge(*ends)
51
+
52
  return G
53
 
 
 
54
 
55
+ def get_top_hubs(G: nx.Graph, k: int = 5):
56
+ """Return *k* nodes with highest degree-centrality."""
57
  dc = nx.degree_centrality(G)
58
  return sorted(dc.items(), key=lambda x: x[1], reverse=True)[:k]
59
+
60
+
61
+ def get_density(G: nx.Graph) -> float:
62
+ """Graph density ∈ [0,1]."""
63
+ return nx.density(G)