Senescent cell clearance as neurodegeneration therapy¶
Notebook ID: nb-SDA-2026-04-04-gap-senescent-clearance-neuro · Analysis: SDA-2026-04-04-gap-senescent-clearance-neuro · Generated: 2026-04-17
Research question¶
Investigate the therapeutic potential of clearing senescent cells (senolytics) to slow or reverse neurodegeneration. Key questions:
- Which senescent cell types in the brain contribute most to neurodegeneration (microglia, astrocytes, oligodendrocyte precursors)?
- What senolytic compounds (dasatinib+quercetin, navitoclax, fisetin) show BBB penetration and CNS efficacy?
- What is the evidence from animal models linking cellular senescence to Alzheimer's, Parkinson's, and other neurodegenerative diseases?
- What are the risks of removing senescent cells in the aging brain (e.g., loss of SASP-mediated repair signals)?
- What clinical trials exist or are planned for senolytics in neurodegeneration?
Approach¶
This notebook is generated programmatically from real Forge tool calls and SciDEX debate data. Code cells load cached evidence bundles from data/forge_cache/seaad/*.json and query live data from scidex.db. Re-run python3 scripts/regenerate_notebooks.py --analysis SDA-2026-04-04-gap-senescent-clearance-neuro --force to refresh.
7 hypotheses were generated and debated. The knowledge graph has 71 edges.
Debate Summary¶
Quality score: 0.95 · Rounds: 4 · Personas: Theorist, Skeptic, Domain_Expert, Synthesizer
1. Forge tool provenance¶
import json, sys, sqlite3
from pathlib import Path
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
matplotlib.rcParams['figure.dpi'] = 110
matplotlib.rcParams['figure.facecolor'] = 'white'
REPO = Path('.').resolve()
sys.path.insert(0, str(REPO))
CACHE_SUB = 'seaad'
CACHE = REPO / 'data' / 'forge_cache' / CACHE_SUB
def load(name):
p = CACHE / f'{name}.json'
if p.exists():
return json.loads(p.read_text())
return {}
db_path = Path('/home/ubuntu/scidex/scidex.db')
try:
db = sqlite3.connect(str(db_path))
prov = pd.read_sql_query('''
SELECT skill_id, status, COUNT(*) AS n_calls,
ROUND(AVG(duration_ms),0) AS mean_ms
FROM tool_calls
WHERE created_at >= date('now','-30 days')
GROUP BY skill_id, status
ORDER BY n_calls DESC
''', db)
db.close()
prov['tool'] = prov['skill_id'].str.replace('tool_', '', regex=False)
print(f'{len(prov)} tool-call aggregates (last 30 days):')
prov[['tool','status','n_calls','mean_ms']].head(20)
except Exception as e:
print(f'Provenance unavailable: {e}')
181 tool-call aggregates (last 30 days):
2. Target gene annotations¶
ann_rows = []
for g in ['APOE', 'BAX', 'BDNF', 'NAMPT']:
mg = load(f'mygene_{g}')
hpa = load(f'hpa_{g}')
if not mg and not hpa:
ann_rows.append({'gene': g, 'name': '—', 'protein_class': '—',
'disease_involvement': '—'})
continue
ann_rows.append({
'gene': g,
'name': (mg.get('name') or '')[:55],
'protein_class': ', '.join((hpa.get('protein_class') or [])[:2])[:55]
if isinstance(hpa.get('protein_class'), list)
else str(hpa.get('protein_class') or '—')[:55],
'disease_involvement': ', '.join((hpa.get('disease_involvement') or [])[:2])[:55]
if isinstance(hpa.get('disease_involvement'), list)
else str(hpa.get('disease_involvement') or '')[:55],
})
pd.DataFrame(ann_rows)
| gene | name | protein_class | disease_involvement | |
|---|---|---|---|---|
| 0 | APOE | apolipoprotein E | Cancer-related genes, Candidate cardiovascular... | Alzheimer disease, Amyloidosis |
| 1 | BAX | — | — | — |
| 2 | BDNF | — | — | — |
| 3 | NAMPT | — | — | — |
3. GO Biological Process enrichment (Enrichr)¶
go_bp = load('enrichr_GO_Biological_Process')
if isinstance(go_bp, list) and go_bp:
go_df = pd.DataFrame(go_bp[:10])[['term','p_value','odds_ratio','genes']]
go_df['p_value'] = go_df['p_value'].apply(lambda p: f'{p:.2e}')
go_df['odds_ratio'] = go_df['odds_ratio'].round(1)
go_df['term'] = go_df['term'].str[:60]
go_df['n_hits'] = go_df['genes'].apply(len)
go_df['genes'] = go_df['genes'].apply(lambda g: ', '.join(g))
go_df[['term','n_hits','p_value','odds_ratio','genes']]
else:
print('No GO:BP enrichment data')
# Visualize top GO BP enrichment
go_bp = load('enrichr_GO_Biological_Process')
if isinstance(go_bp, list) and go_bp:
top = go_bp[:8]
terms = [t['term'][:45] for t in top][::-1]
neglogp = [-np.log10(max(t['p_value'], 1e-300)) for t in top][::-1]
fig, ax = plt.subplots(figsize=(9, 4.5))
ax.barh(terms, neglogp, color='#4fc3f7')
ax.set_xlabel('-log10(p-value)')
ax.set_title('Top GO:BP enrichment (Enrichr)')
ax.grid(axis='x', alpha=0.3)
plt.tight_layout(); plt.show()
else:
print('No GO:BP data to plot')
4. KEGG pathway enrichment¶
kegg = load('enrichr_KEGG_Pathways')
if isinstance(kegg, list) and kegg:
kegg_df = pd.DataFrame(kegg[:10])[['term','p_value','odds_ratio','genes']]
kegg_df['genes'] = kegg_df['genes'].apply(lambda g: ', '.join(g))
kegg_df['p_value'] = kegg_df['p_value'].apply(lambda p: f'{p:.2e}')
kegg_df['odds_ratio'] = kegg_df['odds_ratio'].round(1)
kegg_df
else:
print('No KEGG enrichment data')
No KEGG enrichment data
5. STRING protein interaction network¶
ppi = load('string_network')
if isinstance(ppi, list) and ppi:
ppi_df = pd.DataFrame(ppi).sort_values('score', ascending=False)
display_cols = [c for c in ['protein1','protein2','score','escore','tscore'] if c in ppi_df.columns]
print(f'{len(ppi_df)} STRING edges')
ppi_df[display_cols].head(20)
else:
print('No STRING edges returned')
11 STRING edges
# Network figure
ppi = load('string_network')
if isinstance(ppi, list) and ppi:
import math
nodes = sorted({p for e in ppi for p in (e['protein1'], e['protein2'])})
n = len(nodes)
pos = {n_: (math.cos(2*math.pi*i/n), math.sin(2*math.pi*i/n)) for i, n_ in enumerate(nodes)}
fig, ax = plt.subplots(figsize=(7, 7))
for e in ppi:
x1,y1 = pos[e['protein1']]; x2,y2 = pos[e['protein2']]
ax.plot([x1,x2],[y1,y2], color='#888', alpha=0.3+0.5*e['score'],
linewidth=0.5+2*e['score'])
for name,(x,y) in pos.items():
ax.scatter([x],[y], s=450, color='#ffd54f', edgecolors='#333', zorder=3)
ax.annotate(name, (x,y), ha='center', va='center', fontsize=8, fontweight='bold', zorder=4)
ax.set_aspect('equal'); ax.axis('off')
ax.set_title(f'STRING PPI network ({len(ppi)} edges)')
plt.tight_layout(); plt.show()
else:
print('No STRING data to visualize')
6. Reactome pathway footprint¶
pw_rows = []
for g in ['APOE', 'BAX', 'BDNF', 'NAMPT']:
pws = load(f'reactome_{g}')
if isinstance(pws, list):
pw_rows.append({'gene': g, 'n_pathways': len(pws),
'top_pathway': (pws[0]['name'] if pws else '—')[:70]})
else:
pw_rows.append({'gene': g, 'n_pathways': 0, 'top_pathway': '—'})
pd.DataFrame(pw_rows).sort_values('n_pathways', ascending=False)
| gene | n_pathways | top_pathway | |
|---|---|---|---|
| 0 | APOE | 8 | Nuclear signaling by ERBB4 |
| 1 | BAX | 0 | — |
| 2 | BDNF | 0 | — |
| 3 | NAMPT | 0 | — |
7. Allen Brain Atlas ISH regional expression¶
ish_rows = []
for g in ['APOE', 'BAX', 'BDNF', 'NAMPT']:
ish = load(f'allen_ish_{g}')
regions = ish.get('regions') or [] if isinstance(ish, dict) else []
ish_rows.append({
'gene': g,
'n_ish_regions': len(regions),
'top_region': (regions[0].get('structure','') if regions else '—')[:45],
'top_energy': round(regions[0].get('expression_energy',0), 2) if regions else None,
})
pd.DataFrame(ish_rows)
| gene | n_ish_regions | top_region | top_energy | |
|---|---|---|---|---|
| 0 | APOE | 0 | — | — |
| 1 | BAX | 0 | — | — |
| 2 | BDNF | 0 | — | — |
| 3 | NAMPT | 0 | — | — |
8. Hypothesis ranking (7 hypotheses)¶
hyp_data = [('Metabolic Reprogramming to Reverse Senescence', 1.0), ('SASP Modulation Rather Than Cell Elimination', 0.981), ('Autophagy-Senescence Axis Therapeutic Window', 0.921), ('Oligodendrocyte Precursor Cell Senescence in White Matt', 0.769), ('Apoptosis-Senescence Decision Point Intervention', 0.649), ('APOE4-Driven Astrocyte Senescence as Primary Target', 0.629), ('Selective Microglial Senescence Targeting via TREM2 Mod', 0.459)]
titles = [h[0] for h in hyp_data][::-1]
scores = [h[1] for h in hyp_data][::-1]
fig, ax = plt.subplots(figsize=(10, max(8, len(titles)*0.4)))
colors = ['#ef5350' if s >= 0.6 else '#ffa726' if s >= 0.5 else '#66bb6a' for s in scores]
ax.barh(range(len(titles)), scores, color=colors)
ax.set_yticks(range(len(titles))); ax.set_yticklabels(titles, fontsize=7)
ax.set_xlabel('Composite Score'); ax.set_title('Senescent cell clearance as neurodegeneration therapy')
ax.grid(axis='x', alpha=0.3)
plt.tight_layout(); plt.show()
9. Score dimension heatmap (top 10)¶
labels = ['Metabolic Reprogramming to Reverse Senes', 'SASP Modulation Rather Than Cell Elimina', 'Autophagy-Senescence Axis Therapeutic Wi', 'Oligodendrocyte Precursor Cell Senescenc', 'Apoptosis-Senescence Decision Point Inte', 'APOE4-Driven Astrocyte Senescence as Pri', 'Selective Microglial Senescence Targetin']
matrix = np.array([[0.6, 0.9, 0.82, 0.8, 0.72, 0.8, 0.8, 0.9, 0.9], [0.7, 0.8, 0.78, 0.7, 0.65, 0.7, 0.7, 0.8, 0.8], [0.8, 0.6, 0, 0.8, 0, 0.7, 0.6, 0.7, 0.7], [0.8, 0.5, 0, 0.6, 0, 0.4, 0.5, 0.6, 0.7], [0.8, 0.2, 0, 0.6, 0, 0.6, 0.4, 0.3, 0.4], [0.7, 0.4, 0, 0.4, 0, 0.4, 0.3, 0.5, 0.5], [0.6, 0.1, 0, 0.3, 0, 0.5, 0.2, 0.2, 0.1]])
dims = ['novelty_score', 'feasibility_score', 'impact_score', 'mechanistic_plausibility_score', 'clinical_relevance_score', 'data_availability_score', 'reproducibility_score', 'druggability_score', 'safety_profile_score']
if matrix.size:
fig, ax = plt.subplots(figsize=(10, 5))
im = ax.imshow(matrix, cmap='RdYlGn', aspect='auto', vmin=0, vmax=1)
ax.set_xticks(range(len(dims)))
ax.set_xticklabels([d.replace('_score','').replace('_',' ').title() for d in dims],
rotation=45, ha='right', fontsize=8)
ax.set_yticks(range(len(labels))); ax.set_yticklabels(labels, fontsize=7)
ax.set_title('Score dimensions — top hypotheses')
plt.colorbar(im, ax=ax, shrink=0.8)
plt.tight_layout(); plt.show()
else:
print('No score data available')
10. PubMed evidence per hypothesis¶
Hypothesis 1: Metabolic Reprogramming to Reverse Senescence¶
Target genes: SIRT1,PGC1A,NAMPT · Composite score: 1.0
Metabolic Reprogramming to Reverse Senescence in Neurodegeneration: A Mechanistic Hypothesis¶
The Senescence Conundrum in Neurodegenerative Disease¶
Cellular senescence, traditionally characterized as an irreversible cell cycle arrest, has emerged as a critical pathophysiological feature across neurodegenerative conditions including Alzheimer's disease, Parkinson's disease, and amyotrophic lateral sclerosis. While senolytic approaches have gained traction as therapeutic strategies—focused o
hid = 'SDA-2026-04-16-hyp-e5bf6e0d'
papers = load(f'pubmed_{hid}')
if isinstance(papers, list) and papers:
lit = pd.DataFrame(papers)
cols = [c for c in ['year','journal','title','pmid'] if c in lit.columns]
if cols:
lit = lit[cols]
lit['title'] = lit['title'].str[:80]
if 'journal' in lit.columns:
lit['journal'] = lit['journal'].str[:30]
lit.sort_values('year', ascending=False, inplace=True)
display_df = lit
else:
display_df = pd.DataFrame(papers[:5])
else:
display_df = pd.DataFrame([{'note':'no PubMed results'}])
display_df
| note | |
|---|---|
| 0 | no PubMed results |
Hypothesis 2: SASP Modulation Rather Than Cell Elimination¶
Target genes: NFKB1,IL1B,BDNF · Composite score: 0.981
SASP Modulation Rather Than Cell Elimination¶
Hypothesis Expansion: Selectively Modulating the Senescence-Associated Secretory Phenotype Through NF-κB and Cytokine Pathway Targeting to Reduce Neurotoxic Inflammation While Preserving Neurotrophic Function¶
Background and Rationale¶
Cellular senescence represents an evolutionarily conserved stress response characterized by irreversible cell cycle arrest, chromatin reorganization, and a distinctive secretory program known as the senesc
hid = 'SDA-2026-04-16-hyp-daadc5c6'
papers = load(f'pubmed_{hid}')
if isinstance(papers, list) and papers:
lit = pd.DataFrame(papers)
cols = [c for c in ['year','journal','title','pmid'] if c in lit.columns]
if cols:
lit = lit[cols]
lit['title'] = lit['title'].str[:80]
if 'journal' in lit.columns:
lit['journal'] = lit['journal'].str[:30]
lit.sort_values('year', ascending=False, inplace=True)
display_df = lit
else:
display_df = pd.DataFrame(papers[:5])
else:
display_df = pd.DataFrame([{'note':'no PubMed results'}])
display_df
| note | |
|---|---|
| 0 | no PubMed results |
Hypothesis 3: Autophagy-Senescence Axis Therapeutic Window¶
Target genes: ATG7,BCL2,BCL2L1 · Composite score: 0.921
Autophagy-Senescence Axis Therapeutic Window: Sequential Targeting of ATG7 and BCL-2 Family Proteins in Neurodegeneration¶
Background and Conceptual Framework¶
The interplay between autophagy dysfunction and cellular senescence represents an emerging frontier in understanding neurodegenerative disease pathogenesis. Research indicates that these two fundamental cellular processes exist in a bidirectional relationship, where impaired autophagy promotes senescence accumulation, while senescent
hid = 'SDA-2026-04-16-hyp-4a6e22aa'
papers = load(f'pubmed_{hid}')
if isinstance(papers, list) and papers:
lit = pd.DataFrame(papers)
cols = [c for c in ['year','journal','title','pmid'] if c in lit.columns]
if cols:
lit = lit[cols]
lit['title'] = lit['title'].str[:80]
if 'journal' in lit.columns:
lit['journal'] = lit['journal'].str[:30]
lit.sort_values('year', ascending=False, inplace=True)
display_df = lit
else:
display_df = pd.DataFrame(papers[:5])
else:
display_df = pd.DataFrame([{'note':'no PubMed results'}])
display_df
| note | |
|---|---|
| 0 | no PubMed results |
Hypothesis 4: Oligodendrocyte Precursor Cell Senescence in White Matter Disease¶
Target genes: CSPG4,OLIG2,BCL2 · Composite score: 0.769
Background and Rationale
White matter diseases, including multiple sclerosis (MS), age-related white matter hyperintensities, and various leukoencephalopathies, are characterized by progressive demyelination and impaired remyelination capacity. Central to these pathologies is the dysfunction of oligodendrocyte precursor cells (OPCs), which are responsible for generating new oligodendrocytes to replace damaged myelin sheaths. Recent advances in cellular aging research have identified cellula
hid = 'SDA-2026-04-16-hyp-b29129dc'
papers = load(f'pubmed_{hid}')
if isinstance(papers, list) and papers:
lit = pd.DataFrame(papers)
cols = [c for c in ['year','journal','title','pmid'] if c in lit.columns]
if cols:
lit = lit[cols]
lit['title'] = lit['title'].str[:80]
if 'journal' in lit.columns:
lit['journal'] = lit['journal'].str[:30]
lit.sort_values('year', ascending=False, inplace=True)
display_df = lit
else:
display_df = pd.DataFrame(papers[:5])
else:
display_df = pd.DataFrame([{'note':'no PubMed results'}])
display_df
| note | |
|---|---|
| 0 | no PubMed results |
Hypothesis 5: Apoptosis-Senescence Decision Point Intervention¶
Target genes: TP53,BAX,BAK1,CASP3 · Composite score: 0.649
Background and Rationale
Cellular senescence represents a critical biological process where cells permanently exit the cell cycle in response to various stressors, including DNA damage, oxidative stress, and oncogene activation. While initially considered a tumor suppressor mechanism, accumulating evidence demonstrates that senescent cells contribute significantly to aging and age-related pathologies, including neurodegeneration, through the secretion of inflammatory cytokines, growth facto
hid = 'SDA-2026-04-16-hyp-a44afba2'
papers = load(f'pubmed_{hid}')
if isinstance(papers, list) and papers:
lit = pd.DataFrame(papers)
cols = [c for c in ['year','journal','title','pmid'] if c in lit.columns]
if cols:
lit = lit[cols]
lit['title'] = lit['title'].str[:80]
if 'journal' in lit.columns:
lit['journal'] = lit['journal'].str[:30]
lit.sort_values('year', ascending=False, inplace=True)
display_df = lit
else:
display_df = pd.DataFrame(papers[:5])
else:
display_df = pd.DataFrame([{'note':'no PubMed results'}])
display_df
| note | |
|---|---|
| 0 | no PubMed results |
Hypothesis 6: APOE4-Driven Astrocyte Senescence as Primary Target¶
Target genes: APOE,CDKN1A,BCL2L1 · Composite score: 0.629
Background and Rationale
The apolipoprotein E epsilon 4 (APOE4) allele represents the strongest genetic risk factor for late-onset Alzheimer's disease (AD), carried by approximately 25% of the population and conferring a 3-fold increased risk for heterozygotes and 8-15-fold increased risk for homozygotes. While traditional therapeutic approaches have focused on amyloid-beta (Aβ) and tau pathology as primary targets, emerging evidence suggests that APOE4-mediated cellular dysfunction may pre
hid = 'SDA-2026-04-16-hyp-96ec73b3'
papers = load(f'pubmed_{hid}')
if isinstance(papers, list) and papers:
lit = pd.DataFrame(papers)
cols = [c for c in ['year','journal','title','pmid'] if c in lit.columns]
if cols:
lit = lit[cols]
lit['title'] = lit['title'].str[:80]
if 'journal' in lit.columns:
lit['journal'] = lit['journal'].str[:30]
lit.sort_values('year', ascending=False, inplace=True)
display_df = lit
else:
display_df = pd.DataFrame(papers[:5])
else:
display_df = pd.DataFrame([{'note':'no PubMed results'}])
display_df
| note | |
|---|---|
| 0 | no PubMed results |
Hypothesis 7: Selective Microglial Senescence Targeting via TREM2 Modulation¶
Target genes: TREM2 · Composite score: 0.459
Background and Rationale
Microglia, the resident immune cells of the central nervous system, play dual roles in neurodegeneration—acting as both neuroprotective mediators and contributors to neuroinflammation. Recent research has highlighted the concept of microglial senescence, where these cells adopt a senescence-associated secretory phenotype (SASP) that perpetuates chronic inflammation and tissue damage. The Triggering Receptor Expressed on Myeloid cells 2 (TREM2) has emerged as a criti
hid = 'SDA-2026-04-16-hyp-f460e747'
papers = load(f'pubmed_{hid}')
if isinstance(papers, list) and papers:
lit = pd.DataFrame(papers)
cols = [c for c in ['year','journal','title','pmid'] if c in lit.columns]
if cols:
lit = lit[cols]
lit['title'] = lit['title'].str[:80]
if 'journal' in lit.columns:
lit['journal'] = lit['journal'].str[:30]
lit.sort_values('year', ascending=False, inplace=True)
display_df = lit
else:
display_df = pd.DataFrame(papers[:5])
else:
display_df = pd.DataFrame([{'note':'no PubMed results'}])
display_df
| note | |
|---|---|
| 0 | no PubMed results |
11. Knowledge graph edges (71 total)¶
edge_data = [{'source': 'p16INK4a', 'relation': 'activates', 'target': 'senescence', 'strength': 0.85}, {'source': 'SASP', 'relation': 'activates', 'target': 'neuroinflammation', 'strength': 0.8}, {'source': 'senescence', 'relation': 'contributes_to', 'target': 'neurodegeneration', 'strength': 0.8}, {'source': 'p21', 'relation': 'activates', 'target': 'senescence', 'strength': 0.8}, {'source': 'quercetin', 'relation': 'associated_with', 'target': 'senolytic_therapy', 'strength': 0.75}, {'source': 'dasatinib', 'relation': 'associated_with', 'target': 'senolytic_therapy', 'strength': 0.75}, {'source': 'diseases-psp', 'relation': 'investigated_in', 'target': 'SDA-2026-04-16-hyp-e5bf6e0d', 'strength': 0.75}, {'source': 'diseases-corticobasal-degenera', 'relation': 'investigated_in', 'target': 'SDA-2026-04-16-hyp-e5bf6e0d', 'strength': 0.75}, {'source': 'diseases-huntingtons', 'relation': 'investigated_in', 'target': 'SDA-2026-04-16-hyp-e5bf6e0d', 'strength': 0.75}, {'source': 'diseases-vascular-cognitive-im', 'relation': 'investigated_in', 'target': 'SDA-2026-04-16-hyp-e5bf6e0d', 'strength': 0.75}, {'source': 'diseases-prion-disease', 'relation': 'investigated_in', 'target': 'SDA-2026-04-16-hyp-e5bf6e0d', 'strength': 0.75}, {'source': 'diseases-machado-joseph-diseas', 'relation': 'investigated_in', 'target': 'SDA-2026-04-16-hyp-e5bf6e0d', 'strength': 0.75}, {'source': 'genes-rpl30', 'relation': 'investigated_in', 'target': 'SDA-2026-04-16-hyp-e5bf6e0d', 'strength': 0.75}, {'source': 'senolytic_therapy', 'relation': 'inhibits', 'target': 'senescence', 'strength': 0.7}, {'source': 'GFAP', 'relation': 'co_discussed', 'target': 'BMAL1', 'strength': 0.4}, {'source': 'GFAP', 'relation': 'co_discussed', 'target': 'LRP1', 'strength': 0.4}, {'source': 'GFAP', 'relation': 'co_discussed', 'target': 'APOE', 'strength': 0.4}, {'source': 'GFAP', 'relation': 'co_discussed', 'target': 'CLOCK', 'strength': 0.4}, {'source': 'GFAP', 'relation': 'co_discussed', 'target': 'SIRT1', 'strength': 0.4}, {'source': 'BMAL1', 'relation': 'co_discussed', 'target': 'LRP1', 'strength': 0.4}, {'source': 'BMAL1', 'relation': 'co_discussed', 'target': 'APOE', 'strength': 0.4}, {'source': 'BMAL1', 'relation': 'co_discussed', 'target': 'NLRP3', 'strength': 0.4}, {'source': 'LRP1', 'relation': 'co_discussed', 'target': 'CLOCK', 'strength': 0.4}, {'source': 'LRP1', 'relation': 'co_discussed', 'target': 'SIRT1', 'strength': 0.4}, {'source': 'APOE', 'relation': 'co_discussed', 'target': 'CLOCK', 'strength': 0.4}]
if edge_data:
pd.DataFrame(edge_data).head(25)
else:
print('No KG edge data available')
12. Caveats¶
This notebook uses real Forge tool calls cached from live APIs, but:
- Enrichment is against curated gene-set libraries, not genome-wide screens
- STRING/Reactome/HPA/MyGene reflect curated knowledge
- PubMed literature is search-relevance ranked, not systematic review
The cached evidence bundle is the minimum viable real-data analysis for this topic.