Mitochondrial transfer between astrocytes and neurons¶
Notebook ID: nb-sda-2026-04-01-gap-v2-89432b95 · Analysis: sda-2026-04-01-gap-v2-89432b95 · Generated: 2026-04-10
Research question¶
Mitochondrial transfer between astrocytes and neurons
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-v2-89432b95 --force to refresh.
7 hypotheses were generated and debated. The knowledge graph has 106 edges.
Debate Summary¶
Quality score: 0.63 · 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}')
77 tool-call aggregates (last 30 days):
2. Target gene annotations¶
ann_rows = []
for g in ['TFAM']:
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 | TFAM | — | — | — |
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 ['TFAM']:
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 | TFAM | 0 | — |
7. Allen Brain Atlas ISH regional expression¶
ish_rows = []
for g in ['TFAM']:
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 | TFAM | 0 | — | — |
8. Hypothesis ranking (7 hypotheses)¶
hyp_data = [('AMPK hypersensitivity in astrocytes creates enhanced mi', 0.621), ('RAB27A-dependent extracellular vesicle engineering for ', 0.611), ('TFAM overexpression creates mitochondrial donor-recipie', 0.608), ('Designer TRAK1-KIF5 fusion proteins accelerate therapeu', 0.606), ('CX43 hemichannel engineering enables size-selective mit', 0.603), ('GAP43-mediated tunneling nanotube stabilization enhance', 0.602), ('Near-infrared light therapy stimulates COX4-dependent m', 0.533)]
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 astrocytes and neurons')
ax.grid(axis='x', alpha=0.3)
plt.tight_layout(); plt.show()
9. Score dimension heatmap (top 10)¶
labels = ['AMPK hypersensitivity in astrocytes crea', 'RAB27A-dependent extracellular vesicle e', 'TFAM overexpression creates mitochondria', 'Designer TRAK1-KIF5 fusion proteins acce', 'CX43 hemichannel engineering enables siz', 'GAP43-mediated tunneling nanotube stabil', 'Near-infrared light therapy stimulates C']
matrix = np.array([[0.8, 0.85, 0.75, 0.75, 0.037, 0.8, 0.75, 0.9, 0.7], [0.85, 0.45, 0.6, 0.45, 0.436, 0.5, 0.45, 0.4, 0.6], [0.7, 0.6, 0.7, 0.7, 0.469, 0.75, 0.7, 0.5, 0.55], [0.9, 0.25, 0.45, 0.35, 0.436, 0.35, 0.3, 0.2, 0.3], [0.7, 0.4, 0.6, 0.65, 0.436, 0.5, 0.45, 0.35, 0.45], [0.8, 0.3, 0.5, 0.4, 0.667, 0.45, 0.4, 0.25, 0.5], [0.75, 0.9, 0.65, 0.55, 0.486, 0.6, 0.65, 0.95, 0.9]])
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: AMPK hypersensitivity in astrocytes creates enhanced mitochondrial res¶
Target genes: PRKAA1 · Composite score: 0.621
AMPK Hypersensitivity Engineering for Neuroprotection: Astrocyte-Mediated Mitochondrial Rescue
Overview and Conceptual Framework
Neurons are exquisitely vulnerable to mitochondrial dysfunction due to their high metabolic demands and limited regenerative capacity. In Alzheimer's disease and other neurodegenerative conditions, mitochondrial impairment (reduced ATP production, increased ROS, impaired Ca2+ buffering) precedes overt cell death by months to years. During this "metabolic prod
hid = 'h-43f72e21'
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: RAB27A-dependent extracellular vesicle engineering for mitochondrial c¶
Target genes: RAB27A · Composite score: 0.611
Molecular Mechanism and Rationale
The RAB27A-dependent extracellular vesicle engineering approach leverages the sophisticated molecular machinery governing vesicle biogenesis and mitochondrial dynamics to create a revolutionary therapeutic delivery system. RAB27A, a member of the Rab family of small GTPases, serves as a master regulator of exosome secretion through its interaction with the ESCRT (Endosomal Sorting Complex Required for Transport) machinery and specific effector proteins. In
hid = 'h-250b34ab'
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: TFAM overexpression creates mitochondrial donor-recipient gradients fo¶
Target genes: TFAM · Composite score: 0.608
Molecular Mechanism and Rationale¶
The transcription factor A, mitochondrial (TFAM) serves as the master regulator of mitochondrial DNA (mtDNA) transcription and copy number maintenance, making it a critical determinant of cellular bioenergetic capacity. TFAM functions as a high-mobility group (HMG)-box transcription factor that binds to the heavy strand promoter (HSP1 and HSP2) and light strand promoter (LSP) regions of mtDNA, initiating transcription of the 13 protein-coding genes essen
hid = 'h-98b431ba'
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: Designer TRAK1-KIF5 fusion proteins accelerate therapeutic mitochondri¶
Target genes: TRAK1_KIF5A · Composite score: 0.606
Molecular Mechanism and Rationale
The therapeutic hypothesis centers on engineering chimeric proteins that combine the mitochondrial cargo-binding specificity of TRAK1 (Trafficking Kinesin Protein 1) with enhanced kinesin heavy chain motor domains, specifically modified KIF5A variants. TRAK1 functions as a critical adaptor protein that links mitochondria to the kinesin-1 motor complex through direct interactions with the mitochondrial outer membrane protein Miro1/2 (mitochondrial Rho GTPase
hid = 'h-346639e8'
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: CX43 hemichannel engineering enables size-selective mitochondrial tran¶
Target genes: GJA1 · Composite score: 0.603
Molecular Mechanism and Rationale
The proposed therapeutic approach centers on engineering connexin-43 (Cx43) hemichannels, encoded by the GJA1 gene, to create selective conduits for mitochondrial transfer between cells. Connexin-43 forms gap junctions through the assembly of two hemichannels (connexons), each composed of six Cx43 subunits arranged around a central pore. Under normal physiological conditions, these pores have a diameter of approximately 1.2-2.0 nanometers, permitting passag
hid = 'h-13ef5927'
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: GAP43-mediated tunneling nanotube stabilization enhances neuroprotecti¶
Target genes: GAP43 · Composite score: 0.602
Molecular Mechanism and Rationale
The growth-associated protein 43 (GAP43) represents a critical nexus in neuronal plasticity and cytoskeletal dynamics, making it an ideal candidate for enhancing intercellular mitochondrial transfer mechanisms. GAP43 is a membrane-associated phosphoprotein that localizes primarily to growth cones and presynaptic terminals, where it regulates actin polymerization through its interaction with calmodulin and protein kinase C (PKC). In the context of tunneling
hid = 'h-6ce4884a'
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: Near-infrared light therapy stimulates COX4-dependent mitochondrial mo¶
Target genes: COX4I1 · Composite score: 0.533
Molecular Mechanism and Rationale
Near-infrared (NIR) light therapy operates through a sophisticated molecular cascade that begins with photon absorption by cytochrome c oxidase (COX), the terminal enzyme complex of the mitochondrial electron transport chain. The COX4I1 gene encodes the COX4-1 subunit, a critical regulatory component that determines the enzyme's efficiency and response to cellular energy demands. When NIR light at wavelengths between 810-850 nm penetrates neural tissue, it
hid = 'h-fd1562a3'
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 (106 total)¶
edge_data = [{'source': 'PRKAA1', 'relation': 'encodes', 'target': 'AMPK_alpha1', 'strength': 0.8}, {'source': 'AMPK_alpha1', 'relation': 'regulates', 'target': 'energy_sensing_pathway', 'strength': 0.8}, {'source': 'energy_sensing_pathway', 'relation': 'activates', 'target': 'mitochondrial_biogenesis', 'strength': 0.8}, {'source': 'mitochondrial_biogenesis', 'relation': 'protects_against', 'target': 'neurodegeneration', 'strength': 0.8}, {'source': 'COX4I1', 'relation': 'encodes', 'target': 'cytochrome_c_oxidase', 'strength': 0.8}, {'source': 'cytochrome_c_oxidase', 'relation': 'participates_in', 'target': 'electron_transport_chain', 'strength': 0.8}, {'source': 'TFAM', 'relation': 'encodes', 'target': 'TFAM_protein', 'strength': 0.8}, {'source': 'TFAM_protein', 'relation': 'regulates', 'target': 'mitochondrial_DNA_transcriptio', 'strength': 0.8}, {'source': 'RAB27A', 'relation': 'encodes', 'target': 'RAB27A_protein', 'strength': 0.8}, {'source': 'RAB27A_protein', 'relation': 'regulates', 'target': 'exocytosis_pathway', 'strength': 0.8}, {'source': 'GAP43', 'relation': 'encodes', 'target': 'GAP43_protein', 'strength': 0.8}, {'source': 'GAP43_protein', 'relation': 'regulates', 'target': 'axonal_growth_pathway', 'strength': 0.8}, {'source': 'GJA1', 'relation': 'encodes', 'target': 'connexin43', 'strength': 0.8}, {'source': 'connexin43', 'relation': 'forms', 'target': 'gap_junction_pathway', 'strength': 0.8}, {'source': 'h-43f72e21', 'relation': 'implicated_in', 'target': 'neurodegeneration', 'strength': 0.65}, {'source': 'h-43f72e21', 'relation': 'targets', 'target': 'AMPK', 'strength': 0.65}, {'source': 'COX4I1', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.63}, {'source': 'h-98b431ba', 'relation': 'implicated_in', 'target': 'neurodegeneration', 'strength': 0.6}, {'source': 'TFAM', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.58}, {'source': 'PRKAA1', 'relation': 'participates_in', 'target': 'AMPK / energy sensing / metabo', 'strength': 0.58}, {'source': 'h-13ef5927', 'relation': 'implicated_in', 'target': 'neurodegeneration', 'strength': 0.55}, {'source': 'RAB27A', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.53}, {'source': 'h-fd1562a3', 'relation': 'implicated_in', 'target': 'neurodegeneration', 'strength': 0.5}, {'source': 'COX4I1', 'relation': 'participates_in', 'target': 'Mitochondrial dynamics / bioen', 'strength': 0.47}, {'source': 'TFAM', 'relation': 'participates_in', 'target': 'Mitochondrial dynamics / bioen', 'strength': 0.46}]
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.