Mitochondrial transfer between neurons and glia¶
Notebook ID: nb-sda-2026-04-01-gap-20260401231108 · Analysis: sda-2026-04-01-gap-20260401231108 · Generated: 2026-04-17
Research question¶
Mitochondrial transfer between neurons and glia?
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-01-gap-20260401231108 --force to refresh.
7 hypotheses were generated and debated. The knowledge graph has 67 edges.
Debate Summary¶
Quality score: 0.81 · 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 ['FUSION', 'PROTEINS', 'SYNTHETIC']:
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 | FUSION | — | — | — |
| 1 | PROTEINS | — | — | — |
| 2 | SYNTHETIC | — | — | — |
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 ['FUSION', 'PROTEINS', 'SYNTHETIC']:
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 | FUSION | 0 | — |
| 1 | PROTEINS | 0 | — |
| 2 | SYNTHETIC | 0 | — |
7. Allen Brain Atlas ISH regional expression¶
ish_rows = []
for g in ['FUSION', 'PROTEINS', 'SYNTHETIC']:
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 | FUSION | 0 | — | — |
| 1 | PROTEINS | 0 | — | — |
| 2 | SYNTHETIC | 0 | — | — |
8. Hypothesis ranking (7 hypotheses)¶
hyp_data = [('Astrocytic Connexin-43 Upregulation Enhances Neuroprote', 0.692), ('Miro1-Mediated Mitochondrial Trafficking Enhancement Th', 0.645), ('Gap Junction Hemichannel Modulation for Controlled Mito', 0.631), ('Synthetic Biology Approach: Designer Mitochondrial Expo', 0.627), ('PINK1/Parkin-Independent Mitophagy Bypass for Enhanced ', 0.624), ('Optogenetic Control of Mitochondrial Transfer Networks', 0.612), ('Microglia-Derived Extracellular Vesicle Engineering for', 0.587)]
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('Mitochondrial transfer between neurons and glia')
ax.grid(axis='x', alpha=0.3)
plt.tight_layout(); plt.show()
9. Score dimension heatmap (top 10)¶
labels = ['Astrocytic Connexin-43 Upregulation Enha', 'Miro1-Mediated Mitochondrial Trafficking', 'Gap Junction Hemichannel Modulation for ', 'Synthetic Biology Approach: Designer Mit', 'PINK1/Parkin-Independent Mitophagy Bypas', 'Optogenetic Control of Mitochondrial Tra', 'Microglia-Derived Extracellular Vesicle ']
matrix = np.array([[0.7, 0.7, 0.6, 0.4, 0.385, 0.7, 0.6, 0.8, 0.5], [0.8, 0.4, 0.7, 0.5, 0.385, 0.6, 0.5, 0.3, 0.5], [0.6, 0.6, 0.4, 0.2, 0.09, 0.5, 0.4, 0.7, 0.4], [0.9, 0.2, 0.8, 0.3, 0.385, 0.2, 0.2, 0.1, 0.2], [0.7, 0.5, 0.6, 0.6, 0.13, 0.5, 0.5, 0.6, 0.4], [0.8, 0.3, 0.6, 0.4, 0.385, 0.4, 0.4, 0.2, 0.3], [0.8, 0.3, 0.7, 0.2, 0.385, 0.4, 0.3, 0.4, 0.3]])
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: Astrocytic Connexin-43 Upregulation Enhances Neuroprotective Mitochond¶
Target genes: GJA1 · Composite score: 0.692
Background and Rationale
Astrocytes, the most abundant glial cells in the central nervous system, play crucial roles beyond their traditional supportive functions, emerging as active participants in neuronal health and disease progression. Recent advances in neurobiology have revealed that astrocytes possess remarkable neuroprotective capabilities, including the ability to transfer healthy mitochondria to metabolically compromised neurons through specialized cellular structures called tunne
hid = 'h-16ee87a4'
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: Miro1-Mediated Mitochondrial Trafficking Enhancement Therapy¶
Target genes: RHOT1 · Composite score: 0.645
Background and Rationale
Mitochondrial dysfunction represents a central pathological hallmark across neurodegenerative diseases, including Alzheimer's disease, Parkinson's disease, Huntington's disease, and amyotrophic lateral sclerosis (ALS). The maintenance of healthy mitochondrial networks depends critically on dynamic processes including biogenesis, fusion, fission, mitophagy, and crucially, intracellular trafficking. Miro1 (Mitochondrial Rho GTPase 1), encoded by the RHOT1 gene, serves
hid = 'h-91bdb9ad'
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: Gap Junction Hemichannel Modulation for Controlled Mitochondrial Excha¶
Target genes: PANX1 · Composite score: 0.631
Background and Rationale
Neurodegeneration fundamentally represents a failure of cellular bioenergetics, where compromised mitochondrial function leads to insufficient ATP production, oxidative stress accumulation, and eventual cell death. Traditional therapeutic approaches have focused on slowing mitochondrial decline rather than providing immediate bioenergetic rescue. However, emerging evidence reveals that healthy cells can transfer functional mitochondria to distressed neighbors throug
hid = 'h-9adb5c9e'
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: Synthetic Biology Approach: Designer Mitochondrial Export Systems¶
Target genes: Synthetic fusion proteins · Composite score: 0.627
Background and Rationale
Mitochondrial dysfunction is a hallmark of numerous neurodegenerative diseases, including Alzheimer's disease, Parkinson's disease, amyotrophic lateral sclerosis (ALS), and Huntington's disease. These organelles serve as the cellular powerhouses, generating ATP through oxidative phosphorylation, but also play critical roles in calcium homeostasis, apoptosis regulation, and reactive oxygen species (ROS) production. In neurodegenerative conditions, mitochondria accumu
hid = 'h-495454ef'
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: PINK1/Parkin-Independent Mitophagy Bypass for Enhanced Donor Mitochond¶
Target genes: BNIP3/BNIP3L · Composite score: 0.624
Background and Rationale
Intercellular mitochondrial transfer has emerged as a fundamental mechanism of cellular rescue in the central nervous system, representing a paradigm shift in our understanding of how cells respond to bioenergetic crises. Astrocytes donate functional mitochondria to neurons after ischemic, excitotoxic, or degenerative insults through CD38-dependent extracellular vesicle release and connexin-43-mediated tunneling nanotubes. Mesenchymal stem cells (MSCs) also transfer
hid = 'h-2a4e4ad2'
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: Optogenetic Control of Mitochondrial Transfer Networks¶
Target genes: ChR2 · Composite score: 0.612
Background and Rationale
Mitochondrial dysfunction represents a central pathological hallmark across the spectrum of neurodegenerative diseases, including Alzheimer's disease, Parkinson's disease, amyotrophic lateral sclerosis, and Huntington's disease. Compromised mitochondrial bioenergetics, impaired calcium buffering, and excessive reactive oxygen species production contribute to neuronal vulnerability and progressive cell death. Recent groundbreaking discoveries have revealed that astro
hid = 'h-826df660'
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: Microglia-Derived Extracellular Vesicle Engineering for Targeted Mitoc¶
Target genes: RAB27A/LAMP2B · Composite score: 0.587
Background and Rationale
Mitochondrial dysfunction represents a central pathological mechanism across neurodegenerative diseases, including Alzheimer's disease, Parkinson's disease, and amyotrophic lateral sclerosis. Neurons are particularly vulnerable to mitochondrial impairment due to their high energy demands and limited regenerative capacity. Traditional therapeutic approaches targeting mitochondrial dysfunction have shown limited success, largely due to challenges in delivering functio
hid = 'h-d78123d1'
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 (67 total)¶
edge_data = [{'source': 'RHOT1', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.57}, {'source': 'BNIP3', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.55}, {'source': 'BNIP3L', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.55}, {'source': 'h-16ee87a4', 'relation': 'targets', 'target': 'GJA1', 'strength': 0.5}, {'source': 'h-91bdb9ad', 'relation': 'targets', 'target': 'RHOT1', 'strength': 0.5}, {'source': 'h-826df660', 'relation': 'targets', 'target': 'ChR2', 'strength': 0.5}, {'source': 'h-d78123d1', 'relation': 'targets', 'target': 'RAB27A/LAMP2B', 'strength': 0.5}, {'source': 'h-495454ef', 'relation': 'targets', 'target': 'Synthetic fusion proteins', 'strength': 0.5}, {'source': 'PANX1', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.47}, {'source': 'RAB27A', 'relation': 'interacts_with', 'target': 'LAMP2B', 'strength': 0.43}, {'source': 'LAMP2B', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.43}, {'source': 'LAMP2B', 'relation': 'interacts_with', 'target': 'RAB27A', 'strength': 0.43}, {'source': 'Synthetic fusion proteins', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.4}, {'source': 'ChR2', 'relation': 'co_discussed', 'target': 'BNIP3L', 'strength': 0.4}, {'source': 'ChR2', 'relation': 'co_discussed', 'target': 'RHOT1', 'strength': 0.4}, {'source': 'ChR2', 'relation': 'co_discussed', 'target': 'PANX1', 'strength': 0.4}, {'source': 'ChR2', 'relation': 'co_discussed', 'target': 'RAB27A', 'strength': 0.4}, {'source': 'ChR2', 'relation': 'co_discussed', 'target': 'BNIP3', 'strength': 0.4}, {'source': 'ChR2', 'relation': 'co_discussed', 'target': 'Synthetic fusion proteins', 'strength': 0.4}, {'source': 'ChR2', 'relation': 'co_discussed', 'target': 'GJA1', 'strength': 0.4}, {'source': 'BNIP3L', 'relation': 'co_discussed', 'target': 'RHOT1', 'strength': 0.4}, {'source': 'BNIP3L', 'relation': 'co_discussed', 'target': 'PANX1', 'strength': 0.4}, {'source': 'BNIP3L', 'relation': 'co_discussed', 'target': 'RAB27A', 'strength': 0.4}, {'source': 'BNIP3L', 'relation': 'co_discussed', 'target': 'BNIP3', 'strength': 0.4}, {'source': 'BNIP3L', 'relation': 'co_discussed', 'target': 'Synthetic fusion proteins', '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.