"""Draw qualitative control lanes, not measured Western blot data. Tested with Python 3.14, matplotlib 3.10.7 and numpy 2.3.5. Run from _media; the matching PNG is written to the current directory. """ from pathlib import Path import matplotlib.pyplot as plt from matplotlib.patches import Rectangle BLUE = "#1764a0" INK = "#203040" GRAY = "#818b93" def lane(ax, x, y, w, h): ax.add_patch(Rectangle((x, y), w, h, facecolor="white", edgecolor="#b8c5ce", lw=1.3)) def band(ax, x, y, w, color=BLUE, lw=6): ax.plot([x + .12, x + w - .12], [y, y], color=color, lw=lw, solid_capstyle="butt") def main(): fig, ax = plt.subplots(figsize=(12, 7.6), dpi=110, facecolor="white") ax.set(xlim=(0, 12), ylim=(0, 7.6)) ax.axis("off") ax.text(6, 7.28, "Western blot controls ask different questions", ha="center", fontsize=19, weight="bold", color=INK) ax.text(6, 6.88, "Invented qualitative lane symbols • no measured positions, intensities or confirmed identity", ha="center", fontsize=11.5, color=INK) ax.text(.45, 6.34, "A Is binding consistent with the proposed target?", fontsize=14, weight="bold", color=INK) xs = [1.8, 3.65, 5.5, 7.35] labels = ["Known positive", "Sample", "Target deleted", "No primary\n(matched sample)"] for x, label in zip(xs, labels): lane(ax, x, 3.7, 1.04, 1.75) ax.text(x + .52, 5.72, label, ha="center", va="center", fontsize=11, color=INK) for x in xs[:2]: band(ax, x, 4.96, 1.04) for x in xs[:3]: band(ax, x, 4.09, 1.04, GRAY, 5) ax.plot([.75, 8.6], [4.96, 4.96], color=BLUE, lw=.7, ls=":", zorder=0) ax.text(.52, 4.96, "candidate\nposition", ha="center", va="center", fontsize=9.5, color=BLUE) ax.text(9, 4.93, "Candidate disappears\nafter target deletion:\nsupports assignment", va="center", fontsize=11, color=BLUE) ax.text(9, 4.02, "Lower band persists:\nnot explained by target", va="center", fontsize=11, color=INK) ax.text(4.65, 3.36, "No-primary control tests secondary/reagent background; it cannot validate primary specificity.", ha="center", fontsize=10.3, color=INK) ax.text(.45, 2.85, "B Did loading or transfer change with the target readout?", fontsize=14, weight="bold", color=INK) for x, label in [(2, "Sample A"), (4.1, "Sample B"), (6.2, "Patchy transfer")]: ax.text(x + .5, 2.47, label, ha="center", fontsize=11, color=INK) lane(ax, x, 1.97, 1, .24) lane(ax, x, .58, 1, 1.02) band(ax, 2, 2.09, 1, BLUE, 3) band(ax, 4.1, 2.09, 1, BLUE, 6) for y in [.74, .96, 1.18, 1.43]: band(ax, 2, y, 1, GRAY, 2) band(ax, 4.1, y, 1, GRAY, 4) if y < 1.1: band(ax, 6.2, y, 1, GRAY, 3) ax.text(1.63, 2.09, "Target", ha="right", va="center", fontsize=11, color=BLUE) ax.text(1.63, 1.09, "Total-protein\nstain", ha="right", va="center", fontsize=11, color=INK) ax.text(8.06, 2.03, "A target difference can accompany\na difference in total transferred protein.", va="center", fontsize=11, color=INK) ax.text(8.06, 1.12, "Blank patches suggest transfer trouble.\nA target signal alone cannot diagnose why.", va="center", fontsize=11, color=INK) ax.text(6, .18, "Check proportional response before normalization. Symbol thickness is explanatory only.", ha="center", fontsize=11, color=INK) fig.subplots_adjust(left=.015, right=.985, bottom=.01, top=.99) fig.savefig(Path(__file__).with_suffix(".png").name, facecolor="white", transparent=False) plt.close(fig) if __name__ == "__main__": main()