codexdna-reverse-complement.py
dna-reverse-complement.py
"""Draw complement then reverse; write dna-reverse-complement.png in CWD.
Run from _media: python ../dna-reverse-complement.py
Tested with Python 3.14.4, Matplotlib 3.10.7 and NumPy 2.3.5.
This is a sequence-operation diagram, not a drawing of molecular motion.
"""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import FancyBboxPatch
def main():
sequence = "ACGTAC"
mapping = str.maketrans("ACGT", "TGCA")
partner = sequence.translate(mapping)
reverse_complement = partner[::-1]
assert partner == "TGCATG" and reverse_complement == "GTACGT"
assert reverse_complement.translate(mapping)[::-1] == sequence
colors = {"A": "#f4cb72", "T": "#a9dce8", "G": "#c8b9e7", "C": "#add8b0"}
ink = "#31485c"
plt.rcParams.update({"font.size": 12, "figure.facecolor": "white"})
fig, ax = plt.subplots(figsize=(8.8, 5.4))
fig.subplots_adjust(left=0.03, right=0.98, top=0.87, bottom=0.05)
ax.set(xlim=(-2.8, 6.0), ylim=(-0.65, 4.3))
ax.axis("off")
fig.suptitle("Reverse complement: complement letters, then reverse order", fontsize=15)
for y, text, label, left, right in [
(3.8, sequence, "Original strand", "5′", "3′"),
(2.0, partner, "Aligned partner", "3′", "5′"),
(0.2, reverse_complement, "Partner read 5′ → 3′", "5′", "3′"),
]:
ax.text(-2.6, y, label, ha="left", va="center", fontsize=11)
ax.text(-0.55, y, left, ha="center", va="center", fontsize=17)
ax.text(5.65, y, right, ha="center", va="center", fontsize=17)
for i, base in enumerate(text):
ax.add_patch(FancyBboxPatch((i - 0.3, y - 0.28), 0.6, 0.56,
boxstyle="round,pad=0.02", facecolor=colors[base],
edgecolor=ink, zorder=3))
ax.text(i, y, base, ha="center", va="center", fontsize=18, zorder=4)
for i in range(6):
ax.annotate("", (i, 2.36), (i, 3.44),
arrowprops={"arrowstyle": "->", "color": "#176b92", "lw": 1.3})
ax.text(2.5, 2.89, "1. Complement: A ↔ T, C ↔ G", ha="center", va="center",
fontsize=12, bbox={"fc": "white", "ec": "none", "pad": 3}, zorder=5)
ax.text(2.5, 1.12, "2. Reverse aligned lettering: T G C A T G → G T A C G T",
ha="center", va="center", fontsize=11)
ax.text(2.5, -0.48, "Same partner strand; only the direction used to write it changes",
ha="center", fontsize=11, color=ink)
fig.savefig(Path(Path(__file__).stem + ".png"), dpi=120,
facecolor="white", transparent=False)
plt.close(fig)
print(f"{sequence} → aligned {partner} → reverse complement {reverse_complement}")
if __name__ == "__main__":
main()