Blood-brain barrier tight junction disruption by neuroinflammatory cytokines¶
Notebook ID: nb-SDA-2026-04-16-gap-bbb-tjp-20260416041707 · Analysis: SDA-2026-04-16-gap-bbb-tjp-20260416041707 · Generated: 2026-04-17
Research question¶
Analyze how neuroinflammatory cascades disrupt blood-brain barrier (BBB) integrity through tight junction protein degradation.
Key mechanisms to investigate:
- TNF-alpha signaling cascade and its effects on claudin-5, occludin, and ZO-1 expression and localization
- IL-1beta-mediated activation of MMPs (matrix metalloproteinases) that cleave tight junction proteins
- IL-6 effects on BBB permeability and tight junction disruption
- Therapeutic targets that could restore BBB integrity (e.g., MMP inhibitors, cytokine receptor blockers, tight junction protein stabilizers)
Focus on: molecular mechanisms, therapeutic intervention points, and evidence for restoring BBB integrity 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-16-gap-bbb-tjp-20260416041707 --force to refresh.
7 hypotheses were generated and debated. The knowledge graph has 12 edges.
Debate Summary¶
Quality score: 0.87 · Rounds: 7 · Personas: Theorist, Skeptic, Domain_Expert, Computational_Biologist, Clinical_Trialist, Epidemiologist, 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 ['MULTIPLE', 'PPARA']:
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 | MULTIPLE | — | — | — |
| 1 | PPARA | — | — | — |
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 ['MULTIPLE', 'PPARA']:
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 | MULTIPLE | 0 | — |
| 1 | PPARA | 0 | — |
7. Allen Brain Atlas ISH regional expression¶
ish_rows = []
for g in ['MULTIPLE', 'PPARA']:
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 | MULTIPLE | 0 | — | — |
| 1 | PPARA | 0 | — | — |
8. Hypothesis ranking (7 hypotheses)¶
hyp_data = [('Palmitoylethanolamide-Based Endocannabinoid Therapy', 0.919), ('Neutrophil Extracellular Trap (NET) Inhibition', 0.806), ('Wnt/β-catenin Pathway Restoration', 0.686), ('Time-Dependent BBB Repair Strategy', 0.656), ('Peripheral-to-Central Inflammation Circuit Breaker', 0.626), ('Dual NF-κB/MMP Inhibition Strategy', 0.546), ('Cross-Tissue Communication Disruption', 0.466)]
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('Blood-brain barrier tight junction disruption by neuroinflammatory cytokines')
ax.grid(axis='x', alpha=0.3)
plt.tight_layout(); plt.show()
9. Score dimension heatmap (top 10)¶
labels = ['Palmitoylethanolamide-Based Endocannabin', 'Neutrophil Extracellular Trap (NET) Inhi', 'Wnt/β-catenin Pathway Restoration', 'Time-Dependent BBB Repair Strategy', 'Peripheral-to-Central Inflammation Circu', 'Dual NF-κB/MMP Inhibition Strategy', 'Cross-Tissue Communication Disruption']
matrix = np.array([[0, 0, 0, 0.7, 0, 0.8, 0.8, 0.9, 0.9], [0, 0, 0, 0.8, 0, 0.6, 0.6, 0.8, 0.5], [0, 0, 0, 0.9, 0, 0.7, 0.7, 0.5, 0.3], [0, 0, 0, 0.8, 0, 0.5, 0.3, 0.4, 0.4], [0, 0, 0, 0.7, 0, 0.4, 0.3, 0.6, 0.6], [0, 0, 0, 0.8, 0, 0.6, 0.5, 0.2, 0.3], [0, 0, 0, 0.4, 0, 0.2, 0.2, 0.2, 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: Palmitoylethanolamide-Based Endocannabinoid Therapy¶
Target genes: PPARA · Composite score: 0.919
Background and Rationale
Neuroinflammation represents a critical pathological hallmark across multiple neurodegenerative disorders, including Alzheimer's disease, Parkinson's disease, and amyotrophic lateral sclerosis. The endocannabinoid system has emerged as a pivotal regulatory network controlling neuroinflammatory responses through complex interactions between endogenous lipid mediators, their receptors, and downstream signaling cascades. Palmitoylethanolamide (PEA), an endogenous fatty
hid = 'h-b2aeabb1'
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: Neutrophil Extracellular Trap (NET) Inhibition¶
Target genes: PADI4 · Composite score: 0.806
Background and Rationale
Neutrophil extracellular traps (NETs) represent a specialized antimicrobial defense mechanism wherein neutrophils release web-like structures composed of decondensed chromatin, histones, and granular proteins to trap and neutralize pathogens. However, emerging evidence suggests that excessive or dysregulated NET formation (NETosis) contributes to pathological inflammation in various diseases, including neurodegenerative conditions. In the context of neurodegeneratio
hid = 'h-3b539acf'
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: Wnt/β-catenin Pathway Restoration¶
Target genes: CTNNB1 · Composite score: 0.686
Background and Rationale
The Wnt/β-catenin signaling pathway represents one of the most evolutionarily conserved mechanisms governing cellular fate determination, tissue homeostasis, and regenerative processes throughout development and adult life. In the central nervous system, this pathway plays critical roles in neurogenesis, synaptic plasticity, and neural stem cell maintenance. β-catenin (encoded by CTNNB1), the central effector of canonical Wnt signaling, functions both as a structura
hid = 'h-a54ec316'
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: Time-Dependent BBB Repair Strategy¶
Target genes: MULTIPLE · Composite score: 0.656
Background and Rationale
The blood-brain barrier (BBB) represents a critical physiological interface that maintains central nervous system homeostasis by selectively regulating molecular transport between the systemic circulation and brain parenchyma. Composed primarily of brain microvascular endothelial cells interconnected by tight junctions, the BBB serves as both a protective barrier and a selective gateway. However, BBB dysfunction is a hallmark of numerous neurological disorders, incl
hid = 'h-ec228866'
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: Peripheral-to-Central Inflammation Circuit Breaker¶
Target genes: IL1B · Composite score: 0.626
Background and Rationale
Neuroinflammation has emerged as a critical pathological hallmark across virtually all neurodegenerative diseases, including Alzheimer's disease (AD), Parkinson's disease (PD), amyotrophic lateral sclerosis (ALS), and multiple sclerosis (MS). The classical view of the central nervous system (CNS) as an "immune-privileged" site has been fundamentally challenged by mounting evidence demonstrating robust bidirectional communication between peripheral and central inflam
hid = 'h-efbedb10'
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: Dual NF-κB/MMP Inhibition Strategy¶
Target genes: NFKB1 · Composite score: 0.546
Background and Rationale
The blood-brain barrier (BBB) represents a critical interface between the peripheral circulation and the central nervous system, maintaining brain homeostasis through selective permeability and active transport mechanisms. BBB dysfunction is increasingly recognized as a pivotal pathological feature in numerous neurodegenerative diseases, including Alzheimer's disease, Parkinson's disease, multiple sclerosis, and amyotrophic lateral sclerosis. This dysfunction manife
hid = 'h-04a4889c'
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: Cross-Tissue Communication Disruption¶
Target genes: MULTIPLE · Composite score: 0.466
Background and Rationale
The traditional view of neurodegeneration as a brain-centric phenomenon has undergone significant revision with the recognition that peripheral tissues play crucial roles in central nervous system (CNS) pathology. Mounting evidence demonstrates that disrupted communication between peripheral organs and the CNS contributes to neurodegenerative disease progression through multiple interconnected pathways. The gut-brain axis, liver-brain communication, and muscle-brain
hid = 'h-c3354d65'
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 (12 total)¶
edge_data = [{'source': 'TJP1', 'relation': 'interacts_with_confidence', 'target': 'CLDN5', 'strength': 0.99}, {'source': 'OCLN', 'relation': 'interacts_with_confidence', 'target': 'CLDN5', 'strength': 0.99}, {'source': 'CTNNB1', 'relation': 'interacts_with_confidence', 'target': 'TJP1', 'strength': 0.97}, {'source': 'CTNNB1', 'relation': 'interacts_with_confidence', 'target': 'OCLN', 'strength': 0.78}, {'source': 'diseases-corticobasal-degenera', 'relation': 'investigated_in', 'target': 'h-b2aeabb1', 'strength': 0.75}, {'source': 'diseases-machado-joseph-diseas', 'relation': 'investigated_in', 'target': 'h-b2aeabb1', 'strength': 0.75}, {'source': 'genes-rpl30', 'relation': 'investigated_in', 'target': 'h-b2aeabb1', 'strength': 0.75}, {'source': 'NFKB1', 'relation': 'interacts_with_confidence', 'target': 'CTNNB1', 'strength': 0.69}, {'source': 'PPARA', 'relation': 'suppresses', 'target': 'neuroinflammation', 'strength': 0.5}, {'source': 'PADI4', 'relation': 'catalyzes', 'target': 'NET_formation', 'strength': 0.5}, {'source': 'NET_formation', 'relation': 'causes', 'target': 'BBB_disruption', 'strength': 0.5}, {'source': 'Wnt_signaling', 'relation': 'promotes', 'target': 'tight_junction_integrity', '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.