codexccd-potential-wells-transfer-efficiency.py
ccd-potential-wells-transfer-efficiency.py
"""Original qualitative electron-energy wells and on-time packet model.
Tested with Python 3.14, matplotlib 3.10.7 and numpy 2.3.5.
Run in the desired output directory; writes the matching PNG there.
"""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np
def main():
plt.rcParams.update({"font.size": 11, "axes.spines.top": False,
"axes.spines.right": False, "savefig.facecolor": "white"})
fig = plt.figure(figsize=(11, 6.3), dpi=120, facecolor="white")
gs = fig.add_gridspec(3, 2, width_ratios=[1.25, 1], hspace=.65, wspace=.38)
fig.suptitle("CCD: move the well, preserve the packet", fontsize=17)
x = np.linspace(0, 3, 700)
profiles = [
-.95 * np.exp(-((x - .65) / .29)**6) - .15 * np.exp(-((x - 1.55) / .29)**6),
-.94 * np.exp(-((x - 1.1) / .78)**6),
-.15 * np.exp(-((x - .65) / .29)**6) - 1.02 * np.exp(-((x - 1.55) / .29)**6),
]
centers = [.65, 1.1, 1.55]
labels = ["1. Store under A", "2. Open adjacent region", "3. Raise old well; arrive under B"]
for i in range(3):
ax = fig.add_subplot(gs[i, 0])
ax.plot(x, profiles[i], color="#254f7d", lw=2)
for j, center in enumerate([.65, 1.55, 2.45]):
ax.add_patch(Rectangle((center - .34, .27), .68, .19,
facecolor="#d8e3ef", edgecolor="#254f7d"))
ax.text(center, .36, "ABC"[j], ha="center", va="center", fontsize=10)
cx = centers[i]
dots = np.array([cx - .16, cx, cx + .16])
ax.scatter(dots, np.interp(dots, x, profiles[i]) + .11,
color="#b45309", s=28, zorder=4)
if i < 2:
ax.annotate("", xy=(1.62, -.55), xytext=(.8, -.55),
arrowprops={"arrowstyle": "->", "color": "#b45309", "lw": 1.5})
ax.set(xlim=(0, 3), ylim=(-1.2, .55), yticks=[], xticks=[])
ax.set_ylabel("Electron\nenergy U", fontsize=10)
ax.set_title(labels[i], fontsize=11, loc="left")
if i == 2:
ax.set_xlabel("Position along channel; lower U attracts electrons", fontsize=10)
ax = fig.add_subplot(gs[:2, 1])
n = np.arange(0, 3001)
for eta, color in [(.9999, "#b45309"), (.99999, "#2563a4")]:
ax.plot(n, eta**n, label=f"η = {eta}", color=color, lw=2.2)
ax.scatter([2000], [eta**2000], color=color, s=28, zorder=4)
ax.axvline(2000, ls=":", color=".6")
ax.set(xlim=(0, 3000), ylim=(.7, 1.02), xlabel="Number of transfers n",
ylabel="On-time fraction ηⁿ", title="Repeated tiny errors accumulate")
ax.legend(loc="lower left", fontsize=10)
ax.grid(alpha=.2)
textax = fig.add_subplot(gs[2, 1])
textax.axis("off")
textax.text(0, 1, "Chosen input: 10 000 electrons; n = 2000\nη = 0.9999 → mean 8187.23 on time\nη = 0.99999 → mean 9801.99 on time\n\nDeficit may be delayed charge or true loss.\nThis model alone does not give a trail shape.",
va="top", fontsize=10, linespacing=1.4)
fig.text(.5, .015, "Original qualitative effective wells and stipulated model; no measured voltages, historical data or prototype wiring.",
ha="center", fontsize=9)
fig.subplots_adjust(left=.075, right=.975, top=.87, bottom=.1)
fig.savefig(Path(__file__).stem + ".png", facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()