codex/scanning-tunneling-microscope-feedback.py

scanning-tunneling-microscope-feedback.py
"""Draw a functional STM loop; Python 3.14, matplotlib 3.10.7.

Run from _media; writes scanning-tunneling-microscope-feedback.png to CWD.
"""

from pathlib import Path

import matplotlib.pyplot as plt
from matplotlib.patches import Circle, FancyBboxPatch, Polygon


def main():
    plt.rcParams.update({"font.size": 11, "font.family": "DejaVu Sans"})
    fig, ax = plt.subplots(figsize=(11, 6.5), dpi=120, facecolor="white")
    ax.set(xlim=(0, 12), ylim=(0, 7))
    ax.axis("off")
    blue, orange, green = "#23629a", "#aa4d13", "#28735d"

    def box(x, y, w, h, label, color=blue):
        ax.add_patch(FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.08",
                                   facecolor="white", edgecolor=color, linewidth=1.7))
        ax.text(x + w / 2, y + h / 2, label, ha="center", va="center", color=color)

    def arrow(points, color=blue):
        for start, end in zip(points[:-2], points[1:-1]):
            ax.plot([start[0], end[0]], [start[1], end[1]], color=color, lw=1.6)
        ax.annotate("", xy=points[-1], xytext=points[-2],
                    arrowprops={"arrowstyle": "->", "color": color, "lw": 1.6})

    ax.text(6, 6.75, "Scanning tunneling microscopy: current controls tip height",
            ha="center", va="center", fontsize=16, weight="bold")
    # A junction sketch, deliberately schematic rather than an atomic photograph.
    ax.add_patch(Polygon([(1.5, 5.85), (2.5, 5.85), (2, 4.45)],
                         facecolor="#b5c6d4", edgecolor=blue, lw=1.7))
    ax.text(0.7, 5.65, "Metal tip", color=blue)
    ax.plot([1.62, 0.75, 0.75], [5.5, 5.5, 4.73], color=orange, lw=1.4)
    ax.add_patch(Circle((0.75, 4.5), 0.23, facecolor="white", edgecolor=orange, lw=1.4))
    ax.text(0.75, 4.5, "V", ha="center", va="center", color=orange)
    ax.plot([0.75, 0.75], [4.27, 3.6], color=orange, lw=1.4)
    ax.plot([0.6, 3.7], [3.6, 3.6], color="#66513f", lw=3)
    ax.fill_between([0.6, 3.7], 3.2, 3.6, color="#ece2d7")
    ax.text(0.65, 3.36, "Conducting sample", fontsize=11)
    ax.annotate("", xy=(2, 4.38), xytext=(2, 3.67),
                arrowprops={"arrowstyle": "<->", "color": orange, "lw": 1.5})
    ax.text(2.2, 4.02, "Vacuum gap", va="center", color=orange)
    ax.text(0.7, 2.83, "Fixed tip–sample bias V", color=orange)
    ax.plot([0.6, 3.7], [2.45, 2.45], color=green, lw=4)
    ax.text(2.15, 2.1, "Vibration isolation", color=green, ha="center")
    box(4.65, 5.0, 2.6, 0.95, "Measure current I")
    box(8.25, 5.0, 2.9, 0.95, "Compare with target I₀")
    box(8.25, 2.9, 2.9, 1.15, "Feedback controller\nI > I₀: retract\nI < I₀: approach")
    box(4.65, 2.9, 2.6, 1.15, "Vertical piezo drive\nsets z", orange)
    box(0.6, 0.45, 3.1, 0.95, "Lateral piezo drives\nscan x and y", green)
    box(4.65, 0.45, 6.5, 0.95, "Record calibrated z(x, y) → image\nBoth geometry and electronic response contribute")
    arrow([(2, 5.85), (2, 6.15), (4.05, 6.15), (4.05, 5.48), (4.6, 5.48)])
    arrow([(7.33, 5.48), (8.17, 5.48)])
    arrow([(9.7, 4.92), (9.7, 4.13)])
    arrow([(8.17, 3.48), (7.33, 3.48)], orange)
    arrow([(4.57, 3.48), (4.15, 3.48), (4.15, 4.9), (2.42, 4.9)], orange)
    arrow([(5.95, 2.82), (5.95, 1.48)], orange)
    arrow([(2.15, 1.48), (2.15, 1.8), (0.28, 1.8), (0.28, 6.3), (2, 6.3), (2, 5.9)], green)
    ax.text(6, 0.05, "Functional schematic • not to scale • image is a feedback readout, not an atom photograph",
            ha="center", fontsize=10, color="#444444")
    fig.subplots_adjust(left=0.025, right=0.985, bottom=0.04, top=0.98)
    fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), facecolor="white")
    plt.close(fig)


if __name__ == "__main__":
    main()