File size: 2,758 Bytes
08a3e96 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
"""
graph_metrics.py Β· Lightweight NetworkX helpers for MedGenesis
Key features
ββββββββββββ
β’ Accepts edge dictionaries in either Streamlit-agraph or PyVis style:
{"source": "n1", "target": "n2"} β agraph
{"from": "n1", "to": "n2"} β PyVis
β’ Silently skips malformed edges (no KeyError).
β’ Provides three public helpers:
build_nx(nodes, edges) β networkx.Graph
get_top_hubs(G, k=5) β List[(node_id, degree_centrality)]
get_density(G) β float (0β1)
"""
from __future__ import annotations
from typing import List, Dict, Tuple
import networkx as nx
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Internal helpers
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def _edge_ends(e: Dict) -> Tuple[str, str] | None:
"""Return (src, dst) tuple if both ends exist; else None."""
src = e.get("source") or e.get("from")
dst = e.get("target") or e.get("to")
if src and dst:
return src, dst
return None
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Public API
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def build_nx(nodes: List[Dict], edges: List[Dict]) -> nx.Graph:
"""
Convert agraph / PyVis node+edge dicts into a NetworkX Graph.
Nodes: must contain "id" (a unique string)
Edges: accepted shapes β {"source":, "target":} or {"from":, "to":}
"""
G = nx.Graph()
# Add nodes with label attribute (used by Metrics tab)
for n in nodes:
G.add_node(n["id"], label=n.get("label", n["id"]))
# Add edges (skip malformed)
for e in edges:
ends = _edge_ends(e)
if ends:
G.add_edge(*ends)
return G
def get_top_hubs(G: nx.Graph, k: int = 5) -> List[Tuple[str, float]]:
"""
Return top-k nodes by degree-centrality.
Example output: [('TP53', 0.42), ('EGFR', 0.36), ...]
"""
dc = nx.degree_centrality(G)
return sorted(dc.items(), key=lambda x: x[1], reverse=True)[:k]
def get_density(G: nx.Graph) -> float:
"""Graph density in [0, 1]."""
return nx.density(G)
|