codexconfocal-synthetic-axial-pinhole-response.py
confocal-synthetic-axial-pinhole-response.py
"""Synthetic Gaussian finite-pinhole axial model, explicitly not measurements.
Tested with Python 3.14, Matplotlib 3.10.7 and NumPy 2.3.5.
Run from _media with MPLBACKEND=Agg MPLCONFIGDIR=/tmp/codex-wiki-matplotlib.
Writes the matching basename PNG to the current working directory.
"""
import json
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def response(t, alpha):
q = 1 + np.asarray(t) ** 2
return -np.expm1(-alpha ** 2 / (2 * q)) / q
def half_width(alpha):
lo, hi = 0.0, 3.0
target = response(0.0, alpha) / 2
for _ in range(60):
mid = (lo + hi) / 2
if response(mid, alpha) > target:
lo = mid
else:
hi = mid
return (lo + hi) / 2
def main():
plt.rcParams.update({"font.size": 11, "axes.spines.top": False,
"axes.spines.right": False, "figure.facecolor": "white"})
t = np.linspace(-4, 4, 2401)
fig, axes = plt.subplots(1, 2, figsize=(11.2, 5.5))
fig.subplots_adjust(left=0.075, right=0.98, top=0.78, bottom=0.27, wspace=0.28)
metrics = []
for alpha, color in [(0.5, "#245ba3"), (1.5, "#a65324"), (4.0, "#187c52")]:
h = response(t, alpha)
peak = float(response(0.0, alpha))
width = 2 * half_width(alpha)
axes[0].plot(t, h, color=color, lw=2.2,
label=rf"$\alpha={alpha:g}$: peak {peak:.3f}")
axes[1].plot(t, h / peak, color=color, lw=2.2,
label=rf"$\alpha={alpha:g}$: FWHM {width:.3f} $z_0$")
metrics.append({"alpha": alpha, "peak_transmission": peak,
"FWHM_over_z0": width,
"relative_signal_at_t2": float(response(2.0, alpha) / peak)})
for ax in axes:
ax.plot(t, 1 / (1 + t ** 2), color="#626c75", ls="--", lw=1.5,
label="All collected emission accepted")
ax.set(xlim=(-4, 4), ylim=(0, 1.05), xlabel=r"Axial displacement $t=z/z_0$")
ax.axvline(0, color="#c1c6cb", lw=0.8)
ax.grid(alpha=0.2)
ax.legend(fontsize=9, frameon=False, loc="upper right")
axes[0].set(title="Common signal scale: throughput stays visible",
ylabel="Response / excitation-only in-focus signal")
axes[1].set(title="Each peak = 1: compare response widths",
ylabel="Response / its own peak")
axes[1].axhline(0.5, color="#949ca3", lw=0.8, ls=":")
fig.suptitle("Synthetic axial pinhole response — Gaussian toy model", fontsize=15)
fig.text(0.5, 0.85, r"$E(t)=1/(1+t^2)$, $D_\alpha(t)=1-\exp[-\alpha^2/(2(1+t^2))]$, $H_\alpha=E D_\alpha$",
ha="center", fontsize=12)
fig.text(0.5, 0.065,
"α = pinhole radius / in-focus detection Gaussian standard deviation; not Airy units.\n"
"The reference keeps the same scanned excitation. It is not uniform widefield illumination.\n"
"No instrument data, physical length calibration, noise or bleaching is included.",
ha="center", va="center", fontsize=10)
path = Path(__file__).stem + ".png"
fig.savefig(path, dpi=110, facecolor="white", transparent=False)
plt.close(fig)
print(json.dumps({"path": path, "dimensions": [1232, 605], "data": "synthetic model",
"apertures": metrics, "small_pinhole_limit_FWHM_over_z0":
float(2 * np.sqrt(np.sqrt(2) - 1)), "open_pinhole_limit_FWHM_over_z0": 2.0}))
if __name__ == "__main__":
main()