codexpcr-primer-extension-polarity.py
pcr-primer-extension-polarity.py
"""Draw primer-directed copying; tested with Python 3.14 / matplotlib 3.10.7.
Run from _media; writes pcr-primer-extension-polarity.png in the CWD.
"""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch
def main():
plt.rcParams.update({'font.size': 12, 'font.family': 'DejaVu Sans'})
fig, axes = plt.subplots(2, 1, figsize=(10, 6.5), dpi=120)
fig.patch.set_facecolor('white')
gray, blue, green, orange = '#344054', '#2166ac', '#16704a', '#b65a0b'
panels = [
('Upper template: new strand grows leftward', 'AGTCCCTG', 'TCAGGGAC', "5′", "3′", "3′", "5′", 4, 8, green, 4, 0),
('Lower template: new strand grows rightward', 'TCAGGGAC', 'AGTCCCTG', "3′", "5′", "5′", "3′", 0, 4, blue, 4, 8),
]
for ax, (title, template, product, tl, tr, pl, pr, begin, end, color, start, finish) in zip(axes, panels):
ax.set(xlim=(-1.6, 9.6), ylim=(-1.1, 2.15))
ax.axis('off')
ax.set_title(title, loc='left', fontsize=14, weight='bold', pad=8)
ax.plot([0, 8], [1.25, 1.25], color=gray, lw=3)
ax.text(-0.65, 1.25, tl, ha='center', va='center', color=gray, fontsize=14)
ax.text(8.65, 1.25, tr, ha='center', va='center', color=gray, fontsize=14)
ax.text(9.1, 1.25, 'template', ha='left', va='center', color=gray, fontsize=11)
ax.plot([0, 8], [0.35, 0.35], color=orange, lw=5, solid_capstyle='butt')
ax.plot([begin, end], [0.35, 0.35], color=color, lw=7, solid_capstyle='butt')
for x, (a, b) in enumerate(zip(template, product)):
ax.text(x + 0.5, 1.5, a, ha='center', va='center', fontsize=17, family='DejaVu Sans Mono', color=gray)
ax.text(x + 0.5, 0.66, b, ha='center', va='center', fontsize=17, family='DejaVu Sans Mono', color=color if begin <= x < end else orange)
ax.plot([x + 0.5, x + 0.5], [0.8, 1.05], color='#a0a7b4', lw=1.2, ls=':')
ax.text(-0.65, 0.35, pl, ha='center', va='center', color=orange if start > finish else color, fontsize=14)
ax.text(8.65, 0.35, pr, ha='center', va='center', color=color if start > finish else orange, fontsize=14)
ax.text((begin + end)/2, -0.02, 'paired primer', color=color, ha='center', va='center', fontsize=11)
ax.text(2 if start > finish else 6, -0.02, 'added nucleotides', color=orange, ha='center', va='center', fontsize=11)
ax.add_patch(FancyArrowPatch((start, -0.45), (finish, -0.45), arrowstyle='-|>', mutation_scale=20, lw=2.2, color=orange))
ax.text(start, -0.72, 'original paired 3′ end', ha='center', va='center', fontsize=10)
ax.text(2 if start > finish else 6, -0.95, '5′ → 3′ synthesis', ha='center', va='center', fontsize=11, color=orange)
fig.suptitle('PCR extension: chemical direction is independent of page direction', fontsize=16, weight='bold', y=0.98)
fig.text(0.5, 0.025, 'Original 8-position schematic • Four-base primers illustrate polarity only • No flanking DNA shown', ha='center', fontsize=10, color=gray)
fig.subplots_adjust(left=0.06, right=0.88, top=0.89, bottom=0.12, hspace=0.45)
fig.savefig(Path.cwd() / (Path(__file__).stem + '.png'), facecolor='white', transparent=False)
plt.close(fig)
if __name__ == '__main__':
main()