codex/cherenkov-dispersive-threshold-angle-yield.py

cherenkov-dispersive-threshold-angle-yield.py
"""Original hypothetical finite-band model; no measured optical constants.
Python 3.14, NumPy 2.3.5, Matplotlib 3.10.7. Run from _media.
"""
from pathlib import Path
import numpy as np
import matplotlib.pyplot as plt


def main():
    wavelength_nm = np.linspace(400, 700, 1601)
    wavelength_m = wavelength_nm * 1e-9
    index = 1.28 + .04*(500/wavelength_nm)**2
    alpha = 1/137.036  # explicitly chosen rounded fine-structure constant
    colors = ['#bf571c', '#007c83', '#6359a5']
    fig, axes = plt.subplots(1, 3, figsize=(11.6, 4.5), dpi=130, facecolor='white')
    axes[0].plot(wavelength_nm, index, color='#183e66', lw=2.5, label=r'$n(\lambda)$')
    axes[0].axhline(1/.75, color=colors[0], ls='--', label=r'$1/\beta$ for $\beta=0.75$')
    cutoff = 500*np.sqrt(.04/(1/.75-1.28))
    axes[0].axvline(cutoff, color=colors[0], ls=':', lw=1.4)
    axes[0].text(447, 1.337, f'{cutoff:.2f} nm\nthreshold', fontsize=10, color=colors[0])
    for beta, color in zip([.75, .78, .90], colors):
        active = beta*index > 1
        angle = np.full_like(index, np.nan)
        angle[active] = np.degrees(np.arccos(1/(beta*index[active])))
        yield_m2 = 2*np.pi*alpha/wavelength_m**2*np.maximum(0, 1-1/(beta*index)**2)
        # dN/(dx_cm d lambda_nm) = SI density * 1e-2 * 1e-9
        axes[1].plot(wavelength_nm, angle, color=color, lw=2.3, label=rf'$\beta={beta:.2f}$')
        axes[2].plot(wavelength_nm, yield_m2*1e-11, color=color, lw=2.3, label=rf'$\beta={beta:.2f}$')
    axes[0].set_ylabel('Refractive index (dimensionless)')
    axes[1].set_ylabel('Emission angle to track (degrees)')
    axes[2].set_ylabel(r'Produced photons / (cm $\cdot$ nm)')
    for ax, title in zip(axes, ['Index and onset', 'Allowed directions', 'Frank–Tamm spectrum, z = 1']):
        ax.set_title(title, fontsize=12)
        ax.set_xlabel('Vacuum wavelength (nm)')
        ax.set_xlim(400, 700)
        ax.grid(alpha=.23)
        ax.legend(fontsize=9, frameon=False, loc='best')
    axes[1].set_ylim(0, 40)
    axes[2].set_ylim(bottom=0)
    fig.suptitle(r'Chosen model: $n(\lambda)=1.28+0.04(500\,\mathrm{nm}/\lambda)^2$', fontsize=15)
    fig.text(.5, .02,
             '400–700 nm only; constant particle speed; no absorption or collection losses; calculated emission, not observed glow',
             ha='center', fontsize=10)
    fig.tight_layout(rect=(0, .06, 1, .91), w_pad=2)
    fig.savefig(Path(__file__).stem+'.png', facecolor='white')
    plt.close(fig)


if __name__ == '__main__':
    main()