Neuroinflammation resolution mechanisms and pro-resolving mediators¶
Notebook ID: nb-sda-2026-04-01-gap-014 · Analysis: sda-2026-04-01-gap-014 · Generated: 2026-04-10
Research question¶
SPMs (resolvins, protectins, maresins) from omega-3s may promote inflammation resolution. Are resolution failures druggable?
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-014 --force to refresh.
7 hypotheses were generated and debated. The knowledge graph has 140 edges.
Debate Summary¶
Quality score: 0.5 · 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 ['TFRC']:
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 | TFRC | — | — | — |
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 ['TFRC']:
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 | TFRC | 0 | — |
7. Allen Brain Atlas ISH regional expression¶
ish_rows = []
for g in ['TFRC']:
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 | TFRC | 0 | — | — |
8. Hypothesis ranking (7 hypotheses)¶
hyp_data = [('Senescent Microglia Resolution via Maresins-Senolytics ', 0.59), ('Astrocytic Lipoxin A4 Pathway Restoration via ALOX15 Ge', 0.575), ('Circadian-Gated Maresin Biosynthesis Amplification', 0.571), ('Microglial Efferocytosis Enhancement via GPR32 Superago', 0.566), ('Mitochondrial SPM Synthesis Platform Engineering', 0.564), ('Blood-Brain Barrier SPM Shuttle System', 0.533), ('Oligodendrocyte Protectin D1 Mimetic for Myelin Resolut', 0.522)]
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('Neuroinflammation resolution mechanisms and pro-resolving mediators')
ax.grid(axis='x', alpha=0.3)
plt.tight_layout(); plt.show()
9. Score dimension heatmap (top 10)¶
labels = ['Senescent Microglia Resolution via Mares', 'Astrocytic Lipoxin A4 Pathway Restoratio', 'Circadian-Gated Maresin Biosynthesis Amp', 'Microglial Efferocytosis Enhancement via', 'Mitochondrial SPM Synthesis Platform Eng', 'Blood-Brain Barrier SPM Shuttle System', 'Oligodendrocyte Protectin D1 Mimetic for']
matrix = np.array([[0.8, 0.7, 0.8, 0.7, 0.6, 0.7, 0.7, 0.8, 0.6], [0.7, 0.4, 0.7, 0.5, 0.52, 0.5, 0.4, 0.8, 0.5], [0.8, 0.6, 0.6, 0.5, 0.49, 0.5, 0.5, 0.6, 0.7], [0.7, 0.6, 0.7, 0.6, 0.436, 0.6, 0.6, 0.7, 0.5], [0.9, 0.1, 0.6, 0.2, 0.512, 0.2, 0.2, 0.2, 0.3], [0.6, 0.9, 0.8, 0.8, 0.688, 0.8, 0.8, 0.9, 0.8], [0.8, 0.5, 0.7, 0.4, 0.436, 0.4, 0.4, 0.5, 0.6]])
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: Senescent Microglia Resolution via Maresins-Senolytics Combination¶
Target genes: BCL2L1 · Composite score: 0.59
Mechanistic Foundation
Senescent microglia represent a distinct pathological cell state in Alzheimer's disease and aging that combines features of cellular senescence (growth arrest, senescence-associated secretory phenotype/SASP) with impaired microglial-specific functions (phagocytosis, surveillance, synaptic pruning). These "zombie" microglia accumulate in aged and diseased brains, constituting up to 30% of the microglial population in advanced Alzheimer's disease. Unlike reversibly acti
hid = 'h-3f02f222'
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: Astrocytic Lipoxin A4 Pathway Restoration via ALOX15 Gene Therapy¶
Target genes: ALOX15 · Composite score: 0.575
Molecular Mechanism and Rationale
The molecular foundation of this therapeutic approach centers on restoring the biosynthetic capacity for lipoxin A4 (LXA4), a specialized pro-resolving mediator (SPM), specifically within reactive astrocytes through targeted ALOX15 gene delivery. ALOX15 (15-lipoxygenase) serves as the rate-limiting enzyme in the biosynthetic pathway that converts arachidonic acid to 15-HETE, which is subsequently converted to LXA4 through a transcellular mechanism involving
hid = 'h-ac55ff26'
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: Circadian-Gated Maresin Biosynthesis Amplification¶
Target genes: ALOX12 · Composite score: 0.571
Molecular Mechanism and Rationale
The molecular foundation of circadian-gated maresin biosynthesis amplification centers on the intricate interplay between the circadian clock machinery and specialized pro-resolving mediator (SPM) biosynthesis, specifically targeting the 12-lipoxygenase (ALOX12) pathway for maresin 1 (MaR1) production. The circadian clock operates through transcriptional-translational feedback loops involving core clock genes including CLOCK, BMAL1, PER1-3, and CRY1-2, whic
hid = 'h-83efeed6'
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: Microglial Efferocytosis Enhancement via GPR32 Superagonists¶
Target genes: CMKLR1 · Composite score: 0.566
Molecular Mechanism and Rationale
The G-protein coupled receptor 32 (GPR32), encoded by the CMKLR1 gene, serves as the primary receptor for resolvin D1 (RvD1), a specialized pro-resolving mediator (SPM) derived from docosahexaenoic acid. In the context of neurodegeneration, GPR32 represents a critical molecular switch that governs microglial transition from inflammatory to resolution phenotypes. Under physiological conditions, RvD1 binding to GPR32 initiates a cascade involving Gα(i/o) prot
hid = 'h-470ff83e'
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: Mitochondrial SPM Synthesis Platform Engineering¶
Target genes: ALOX5 · Composite score: 0.564
Molecular Mechanism and Rationale
The engineered mitochondrial specialized pro-resolving mediator (SPM) synthesis platform represents a paradigm shift in addressing chronic neuroinflammation through targeted delivery of cellular organelles capable of sustained lipid mediator production. The core mechanism centers on the genetic modification of isolated mitochondria to overexpress key enzymes in the SPM biosynthetic pathway, particularly targeting ALOX5 (5-lipoxygenase) and its associated en
hid = 'h-13bbfdc5'
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: Blood-Brain Barrier SPM Shuttle System¶
Target genes: TFRC · Composite score: 0.533
Mechanistic Foundation
Specialized pro-resolving mediators (SPMs) - including resolvins, protectins, and maresins - are endogenous lipid mediators that actively terminate neuroinflammation and promote tissue repair. Unlike anti-inflammatory drugs that merely block inflammatory pathways, SPMs actively stimulate resolution programs: clearance of apoptotic debris, restoration of blood-brain barrier integrity, and regeneration of damaged neural tissue. In Alzheimer's disease, SPM biosynthesis i
hid = 'h-959a4677'
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: Oligodendrocyte Protectin D1 Mimetic for Myelin Resolution¶
Target genes: GPR37 · Composite score: 0.522
Molecular Mechanism and Rationale
The therapeutic strategy centers on targeting GPR37 (G-protein coupled receptor 37), an orphan receptor highly expressed in oligodendrocytes, through specialized protectin D1 (PD1) mimetics designed to activate endogenous myelin repair mechanisms. GPR37, also known as the parkin-associated endothelin-like receptor (Pael-R), serves as a critical mediator of oligodendrocyte survival and function under inflammatory conditions. The receptor exhibits preferentia
hid = 'h-f71a9791'
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 (140 total)¶
edge_data = [{'source': 'TFRC', 'relation': 'encodes', 'target': 'transferrin_receptor', 'strength': 0.8}, {'source': 'transferrin_receptor', 'relation': 'mediates', 'target': 'blood_brain_barrier_transport', 'strength': 0.8}, {'source': 'CMKLR1', 'relation': 'encodes', 'target': 'GPR32', 'strength': 0.8}, {'source': 'GPR32', 'relation': 'regulates', 'target': 'microglial_efferocytosis', 'strength': 0.8}, {'source': 'microglial_efferocytosis', 'relation': 'resolves', 'target': 'neuroinflammation', 'strength': 0.8}, {'source': 'BCL2L1', 'relation': 'encodes', 'target': 'BCL-xL', 'strength': 0.8}, {'source': 'BCL-xL', 'relation': 'promotes', 'target': 'senescent_cell_survival', 'strength': 0.8}, {'source': 'ALOX12', 'relation': 'encodes', 'target': '12-lipoxygenase', 'strength': 0.8}, {'source': '12-lipoxygenase', 'relation': 'catalyzes', 'target': 'maresin_biosynthesis', 'strength': 0.8}, {'source': 'ALOX15', 'relation': 'encodes', 'target': '15-lipoxygenase', 'strength': 0.8}, {'source': '15-lipoxygenase', 'relation': 'catalyzes', 'target': 'lipoxin_A4_synthesis', 'strength': 0.8}, {'source': 'lipoxin_A4_synthesis', 'relation': 'regulates', 'target': 'astrocyte_polarization', 'strength': 0.8}, {'source': 'GPR37', 'relation': 'encodes', 'target': 'GPR37_receptor', 'strength': 0.8}, {'source': 'GPR37_receptor', 'relation': 'mediates', 'target': 'oligodendrocyte_survival', 'strength': 0.8}, {'source': 'h-959a4677', 'relation': 'implicated_in', 'target': 'neurodegeneration', 'strength': 0.7}, {'source': 'TFRC', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.66}, {'source': 'BCL2L1', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.66}, {'source': 'h-3f02f222', 'relation': 'implicated_in', 'target': 'neurodegeneration', 'strength': 0.6}, {'source': 'CMKLR1', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.59}, {'source': 'ALOX12', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.58}, {'source': 'GPR37', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.56}, {'source': 'ALOX15', 'relation': 'associated_with', 'target': 'neurodegeneration', 'strength': 0.55}, {'source': 'TFRC', 'relation': 'participates_in', 'target': 'Transferrin receptor / BBB tra', 'strength': 0.53}, {'source': 'BCL2L1', 'relation': 'participates_in', 'target': 'Microglial activation / TREM2 ', 'strength': 0.52}, {'source': 'h-470ff83e', 'relation': 'implicated_in', 'target': 'neurodegeneration', 'strength': 0.5}]
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.