r"""
Fresnel diffraction and the Poisson/Arago spot
===================================================

Augustin-Jean Fresnel combined Huygens' wavelet construction with Young's
principle of interference into a quantitative near-field diffraction
theory. Simeon Poisson pointed out -- intending it as a reductio ad
absurdum -- that Fresnel's own theory predicted a bright spot at the
center of the shadow of a circular obstacle; Francois Arago promptly
observed the "Poisson spot" in the laboratory, turning a supposed
refutation into the theory's most dramatic confirmation.

:func:`~physicskit.optics.wave.fresnel_diffraction` implements the
near-field quadratic-phase (paraxial) propagator that predicts this
effect, computed as a single Fourier transform of the field
:math:`U_0(x,y)` immediately after the obstacle:

.. math::

    U(x',y') = \frac{e^{ikz}}{i\lambda z}
        e^{i\frac{k}{2z}(x'^2+y'^2)}\,
        \mathcal{F}\!\left[U_0(x,y)\,
        e^{i\frac{k}{2z}(x^2+y^2)}\right]_{f_x=x'/(\lambda z),\ f_y=y'/(\lambda z)},

with wavenumber :math:`k = 2\pi/\lambda` and propagation distance
:math:`z`. Here :math:`U_0` is generated by
:func:`~physicskit.optics.wave.circular_aperture`, inverted so that it is
1 everywhere *except* a disk of radius ``disk_radius`` -- the
complementary transmittance of an opaque circular obstacle -- and
propagated a distance ``z = 200`` mm at wavelength ``wavelength =
0.5e-3`` mm. Wavelets diffracting around the rim of the disk travel
equal path lengths to the axis and interfere constructively there,
reproducing the on-axis bright spot Arago observed.
"""

import numpy as np

from physicskit.optics.visualizers import plot_diffraction_pattern
from physicskit.optics.wave import circular_aperture, fresnel_diffraction, intensity

# %%
# An opaque circular obstacle: transmittance 1 everywhere except the disk
# ---------------------------------------------------------------------------

wavelength = 0.5e-3  # mm
dx = 0.004
N = 512
disk_radius = 0.15
disk = (1.0 - circular_aperture((N, N), dx=dx, radius=disk_radius)).astype(complex)

U = fresnel_diffraction(disk, wavelength=wavelength, z=200.0, dx=dx)

fig, ax = plot_diffraction_pattern(U, dx=dx, log_scale=True)
ax.set_title("Poisson/Arago spot: bright point at the center of the shadow")
fig.tight_layout()

# %%
# The unobstructed on-axis intensity (no disk at all) is the baseline a
# "reductio ad absurdum" argument implicitly compares against: Poisson's
# point was that Fresnel's theory predicts a bright spot in the *shadow* of
# the disk, comparably bright to the unobstructed beam -- not simply "some
# nonzero intensity."

I_shadow = intensity(U)
center = I_shadow[N // 2, N // 2]

unobstructed = np.ones((N, N), dtype=complex)
U_open = fresnel_diffraction(unobstructed, wavelength=wavelength, z=200.0, dx=dx)
I_open_center = intensity(U_open)[N // 2, N // 2]

print(f"disk radius: {disk_radius} mm")
print(f"intensity at the center of the disk's geometric shadow: {center:.4f}")
print(f"intensity with no disk at all (unobstructed reference): {I_open_center:.4f}")
print("a bright spot at the center of the shadow, comparable to the")
print("unobstructed beam, is exactly the 'absurd' prediction Arago confirmed.")
