codex/circular-rna-backbone-topology.py

circular-rna-backbone-topology.py
"""Original RNA connectivity schematic. Python 3.14 / Matplotlib 3.10.7.

Run from the media directory; output is written to the current directory.
"""
from math import cos, sin, pi
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 3, figsize=(8.4, 3.4), dpi=100, facecolor='white')
blue, orange = '#2166ac', '#d9822b'
linear = [(0.11 + i * 0.11, 0.50) for i in range(8)]
ring = [(0.5 + 0.29 * cos(pi/2 - i*pi/4), 0.49 + 0.29 * sin(pi/2 - i*pi/4)) for i in range(8)]
folded = [(0.25,0.23),(0.25,0.41),(0.25,0.59),(0.40,0.74),
          (0.60,0.74),(0.75,0.59),(0.75,0.41),(0.75,0.23)]
for ax, pts, title, detail, closed in zip(
    axes, [linear,ring,folded], ['Linear backbone','Circular backbone','Folded linear backbone'],
    ['8 nucleotides · 7 links\n2 free ends','8 nucleotides · 8 links\n0 free ends',
     '8 nucleotides · 7 links\n2 free ends'], [False,True,False]):
    draw = pts + [pts[0]] if closed else pts
    ax.plot(*zip(*draw),color=blue,lw=3,zorder=2)
    ax.scatter(*zip(*pts),s=55,color=orange,edgecolor='white',lw=0.8,zorder=3)
    ax.set_title(title,fontsize=11,pad=4)
    ax.text(0.5,-0.04,detail,ha='center',va='top',fontsize=10,transform=ax.transAxes)
    if not closed:
        for p,lab,dx in [(pts[0],"5′",-0.07),(pts[-1],"3′",0.07)]:
            ax.text(p[0]+dx,p[1]-0.095,lab,ha='center',fontsize=11,color=blue)
    ax.set(xlim=(0,1),ylim=(0.08,0.92),aspect='equal');ax.axis('off')
for i in range(3):
    a,b=folded[i],folded[7-i]
    axes[2].plot([a[0],b[0]],[a[1],b[1]],ls='--',lw=1.4,color='#999999',zorder=1)
fig.suptitle('Circularity is a property of the covalent backbone',fontsize=14,y=0.97)
fig.text(0.5,0.025,'Blue: covalent backbone   •   Dashed grey: illustrative base-pair contacts',ha='center',fontsize=10)
fig.subplots_adjust(left=0.02,right=0.98,bottom=0.22,top=0.82,wspace=0.13)
fig.savefig('circular-rna-backbone-topology.png',facecolor='white',dpi=100)
plt.close(fig)