codex/bragg-rays-and-extra-path-geometry.py

bragg-rays-and-extra-path-geometry.py
"""Original Bragg geometry; Python 3.14, matplotlib 3.10.7, numpy 2.3.5.

Run from _media; writes an opaque PNG to the current directory.
"""
from pathlib import Path

import matplotlib.pyplot as plt
from matplotlib.patches import Arc
import numpy as np


def main():
    plt.rcParams.update({"font.size": 12, "font.family": "DejaVu Sans"})
    fig = plt.figure(figsize=(11, 6.2), facecolor="white")
    ax = fig.add_axes((0.035, 0.21, 0.64, 0.66))
    theta = np.pi / 6  # Schematic angle chosen for clear geometry.
    u = np.array([np.cos(theta), -np.sin(theta)])
    v = np.array([np.cos(theta), np.sin(theta)])
    a, b = np.array([0., 0.]), np.array([0., -1.])
    c, e = b - np.sin(theta) * u, b + np.sin(theta) * v
    blue, orange, gray = "#2166ac", "#c45b10", "#6b7280"
    for y in (0, -1):
        ax.plot([-3.1, 3.1], [y, y], color=gray, lw=1.5)
    for p in (a, b):
        for start, end in ((p - 2.9 * u, p), (p, p + 2.9 * v)):
            ax.annotate("", xy=end, xytext=start,
                        arrowprops={"arrowstyle": "->", "color": blue, "lw": 2})
    for p in (c, e):
        ax.plot([a[0], p[0]], [a[1], p[1]], "--", color=gray, lw=1.4)
    ax.plot([c[0], b[0], e[0]], [c[1], b[1], e[1]], color=orange, lw=4)
    for p, name, offset in ((a, "A", (0, 13)), (b, "B", (0, -21)),
                            (c, "C", (-20, -5)), (e, "D", (13, -5))):
        ax.plot(*p, "o", color="#202938", ms=5)
        ax.annotate(name, p, xytext=offset, textcoords="offset points", ha="center")
    # Right-angle marks at the two wavefront/ray intersections.
    for p, along, normal in ((c, u, np.array([np.sin(theta), np.cos(theta)])),
                              (e, -v, np.array([-np.sin(theta), np.cos(theta)]))):
        corners = np.array([p + .11 * along, p + .11 * (along + normal),
                            p + .11 * normal])
        ax.plot(corners[:, 0], corners[:, 1], color=gray, lw=1)
    ax.annotate("", xy=(-2.95, 0), xytext=(-2.95, -1),
                arrowprops={"arrowstyle": "<->", "color": "#202938"})
    ax.text(-3.13, -.5, "$d$", ha="right", va="center", fontsize=17)
    ax.add_patch(Arc(a, 1.5, 1.5, theta1=150, theta2=180, color=blue, lw=1.5))
    ax.text(-1.02, .16, r"$\theta$", color=blue, fontsize=16)
    ax.text(-1.35, -.76, r"$CB=d\sin\theta$", ha="center", color=orange)
    ax.text(1.35, -.76, r"$BD=d\sin\theta$", ha="center", color=orange)
    ax.text(-2.65, 1.53, "Incoming parallel rays", color=blue)
    ax.text(1.25, 1.53, "Outgoing rays", color=blue)
    ax.text(1.65, -.32, "Upper lattice plane", color=gray, fontsize=11)
    ax.text(1.2, -1.20, "Adjacent lattice plane", color=gray, fontsize=11)
    ax.set(xlim=(-3.4, 3.4), ylim=(-1.6, 1.9), aspect="equal")
    ax.axis("off")

    inset = fig.add_axes((.72, .34, .25, .42))
    inset.annotate("", xy=(0, 0), xytext=(-1.3, 0),
                   arrowprops={"arrowstyle": "->", "color": blue, "lw": 2})
    inset.annotate("", xy=(.73, 1.26), xytext=(0, 0),
                   arrowprops={"arrowstyle": "->", "color": blue, "lw": 2})
    inset.plot([0, 1.3], [0, 0], "--", color=gray)
    inset.plot([-1.2, 1.4], [-1.2 / np.sqrt(3), 1.4 / np.sqrt(3)], color=gray)
    inset.add_patch(Arc((0, 0), 1.4, 1.4, theta1=0, theta2=60, color=orange))
    inset.text(.77, .32, r"$2\theta$", fontsize=17, color=orange)
    inset.add_patch(Arc((0, 0), 2.1, 2.1, theta1=0, theta2=30, color=blue))
    inset.text(1.05, .10, r"$\theta$", fontsize=14, color=blue)
    inset.text(-1.3, -.28, "Beam", color=blue)
    inset.text(.30, 1.48, "Scattered", color=blue)
    inset.text(-.7, -.85, "Planes tilted to beam", color=gray, fontsize=11)
    inset.set(xlim=(-1.5, 1.65), ylim=(-1.05, 1.8), aspect="equal")
    inset.axis("off")
    fig.text(.5, .94, "Bragg geometry: compare paths between equal-phase fronts",
             ha="center", fontsize=17, weight="bold")
    fig.text(.355, .18, r"Extra path: $CB+BD=2d\sin\theta$", ha="center", fontsize=16)
    fig.text(.5, .095, "Dashed AC and AD are wavefront comparisons, perpendicular to the rays.",
             ha="center", fontsize=12)
    fig.text(.5, .045, "Schematic coherent elastic scattering; planes represent periodic order, not reflecting surfaces.",
             ha="center", fontsize=11, color=gray)
    fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=100, facecolor="white")
    plt.close(fig)


if __name__ == "__main__":
    main()