fig, ax = plt.subplots(figsize=(12,8)); ax.set(xlim=(-6,6),ylim=(-4.5,4.5)); ax.axis("off")
mod_pos={"Immune regulation":(-3.7,2.7),"Inflammasomes":(0,3.2),"Barrier / adhesion":(3.7,2.7),
"Trophic signaling":(-3.7,-2.5),"Senescence":(0,-3.1),"Under-annotated":(3.7,-2.5)}
gene_groups={"Immune regulation":["IL10","CD86","SIGLEC5"],"Inflammasomes":["NLRP3","NLRC4"],
"Barrier / adhesion":["CDH1","CLMP"],"Trophic signaling":["GDNF"],"Senescence":["CDKN2A"],
"Under-annotated":["FAM217B","KIAA1614","RIBC2","FOXE1","SYNE1"]}
gene_pos={}
for mod,(mx,my) in mod_pos.items():
ax.add_patch(FancyBboxPatch((mx-1.3,my-.42),2.6,.84,boxstyle="round,pad=.08",fc=navy,ec="none"))
ax.text(mx,my,mod,ha="center",va="center",color="white",weight="bold")
gs=gene_groups[mod]
span = 2.0 if mod=="Under-annotated" else 1.0
offsets=np.linspace(-span,span,len(gs)) if len(gs)>1 else [0]
for off,g in zip(offsets,gs):
gx=mx+off; gy=my-1.15 if my>0 else my+1.15; gene_pos[g]=(gx,gy)
col=gray if mod=="Under-annotated" else teal
width = .92 if mod=="Under-annotated" else 1.1
ax.add_patch(FancyBboxPatch((gx-width/2,gy-.25),width,.5,boxstyle="round,pad=.05",fc=col,ec="white"))
ax.text(gx,gy,g,ha="center",va="center",color="white",weight="bold",fontsize=8 if mod=="Under-annotated" else 9)
ax.plot([mx,gx],[my-.45 if my>0 else my+.45,gy+.27 if my>0 else gy-.27],color=col,lw=1.8)
bridges=[("Immune regulation","Inflammasomes","immune restraint / activation"),
("Inflammasomes","Barrier / adhesion","pyroptosis · permeability"),
("Barrier / adhesion","Senescence","injury · repair · selection"),
("Senescence","Under-annotated","methylation markers"),
("Trophic signaling","Barrier / adhesion","survival · tissue repair")]
for a,b,label in bridges:
x1,y1=mod_pos[a]; x2,y2=mod_pos[b]
ax.add_patch(FancyArrowPatch((x1,y1),(x2,y2),arrowstyle="-|>",mutation_scale=14,
linestyle="--",color=coral,lw=1.8,connectionstyle="arc3,rad=.08",shrinkA=55,shrinkB=55))
ax.text((x1+x2)/2,(y1+y2)/2+.18,label,ha="center",fontsize=8,color=coral,
bbox=dict(fc="white",ec="none",alpha=.8,pad=1))
ax.text(0,4.15,"Curated neighborhoods connected by disease-level hypotheses",ha="center",weight="bold",fontsize=14,color=navy)
fig.tight_layout(); fig.savefig(OUT/"reactome-network.png",dpi=220,bbox_inches="tight"); plt.show()