codextrypsin-peptide-cleavage-map.py
trypsin-peptide-cleavage-map.py
"""Draw an original sequence example under a simplified trypsin cleavage rule."""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import FancyBboxPatch
def main():
sequence = "AGKARPKAGRAK"
cuts = [i + 1 for i, aa in enumerate(sequence[:-1])
if aa in "KR" and sequence[i + 1] != "P"]
edges = [0, *cuts, len(sequence)]
fragments = [sequence[a:b] for a, b in zip(edges, edges[1:])]
assert cuts == [3, 7, 10]
assert fragments == ["AGK", "ARPK", "AGR", "AK"]
fig, ax = plt.subplots(figsize=(10, 5), dpi=120, facecolor="white")
fig.subplots_adjust(left=0.04, right=0.98, bottom=0.06, top=0.90)
ax.set(xlim=(-0.7, 11.9), ylim=(-2.6, 2.1))
ax.axis("off")
fig.suptitle("Trypsin: selected bonds, conserved residue order", fontsize=17)
ax.text(-0.5, 1.65, "N → C direction • constructed sequence", fontsize=12)
for i, aa in enumerate(sequence):
basic = aa in "KR"
color = "#e6f1fa" if basic else "#fff1dc" if aa == "P" else "#f0f2f4"
ax.add_patch(FancyBboxPatch((i - 0.32, 0.62), 0.64, 0.64,
boxstyle="round,pad=0.03", facecolor=color,
edgecolor="#496173", linewidth=1.2))
ax.text(i, 0.94, aa, fontsize=19, ha="center", va="center", weight="bold")
ax.text(i, 0.40, str(i + 1), fontsize=10, ha="center", color="#495664")
if basic:
ax.text(i + 0.28, 1.29, "+", fontsize=16, color="#236c9a", weight="bold")
if i < len(sequence) - 1:
ax.plot([i + 0.35, i + 0.65], [0.94, 0.94], color="#66717b", lw=1.8)
for cut in cuts:
x = cut - 0.5
ax.annotate("", xy=(x, 0.92), xytext=(x, 1.62),
arrowprops={"arrowstyle": "->", "color": "#b22936", "lw": 2})
ax.annotate("R–P: retained\nin this rule", xy=(4.5, 0.85), xytext=(4.45, -0.10),
ha="center", va="top", fontsize=11, color="#936011",
arrowprops={"arrowstyle": "->", "color": "#936011"})
ax.annotate("Terminal K:\nno following bond", xy=(11.25, 0.79), xytext=(10.6, -0.10),
ha="center", va="top", fontsize=11, color="#495664",
arrowprops={"arrowstyle": "->", "color": "#495664"})
colors = ["#dcebf8", "#e2f0e3", "#fff0cf", "#eadff4"]
for a, b, fragment, color in zip(edges, edges[1:], fragments, colors):
ax.add_patch(FancyBboxPatch((a - 0.32, -1.46), b - a - 0.36, 0.50,
boxstyle="round,pad=0.03", facecolor=color,
edgecolor="#52626e"))
ax.text((a + b - 1) / 2, -1.21, fragment, fontsize=17, ha="center", va="center")
ax.text((a + b - 1) / 2, -1.78, f"{len(fragment)} residues", fontsize=11, ha="center")
ax.text(-0.5, -2.15, "3 cuts → 4 fragments • 3 + 4 + 3 + 2 = 12 residues", fontsize=13)
ax.text(-0.5, -2.48, "+ marks a predominantly positive side chain near neutral pH, not total fragment charge.",
fontsize=10, color="#495664")
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()