wave op• Data kinds: कोई नहीं → cimage (केवल arguments से तय होने वाला op — यह कोई image या data input नहीं लेता)
• Call: import fullseye as fs; fs.ledger.fourier_plane_filter(size=64, kind='derivative_x', order=1, charge=1, radius_frac=0.25, pixel_pitch_um=1.0) (implementation को सीधे call करना हो तो import optics; optics.fourier_plane_filter(size=64, kind='derivative_x', order=1, charge=1, radius_frac=0.25, pixel_pitch_um=1.0), registry से लेना हो तो opsoptics.get("fourier_plane_filter"))
4f system के Fourier plane में रखा गया complex transmission function H(fx, fy)।
numpy.fft.fftfreq क्रम (fftshift नहीं किया गया) में shape (size, size) का complex128 array लौटाता है, जिसे सीधे four_f_filter को दिया जा सकता है। spatial frequency की इकाई cycles/um है (fftfreq(size, d=pixel_pitch_um))।
*kind*:
identity
H = 1। 4f system केवल image बनाता है —— आउटपुट, इनपुट को 180 degrees घुमाकर मिलता है।
block
H = 0। आउटपुट बिल्कुल शून्य है (Fourier plane बंद है)।
derivative_x / derivative_y
H = (i*2*pi*f)**order। आउटपुट *order* क्रम का spatial derivative है। इस 1 पंक्ति में lens derivative की गणना करता है; यही optical computing का मूल है।
laplacian
H = -(2*pi)**2 * (fx**2 + fy**2)। Isotropic 2nd-order derivative।
lowpass / highpass
वृत्ताकार aperture |f| <= radius_frac * f_nyquist (और उसका पूरक)।
f_nyquist = 1/(2*pixel_pitch_um)। spatial filtering का पाठ्यपुस्तक वाला उदाहरण।
hilbert_x
H = -i*sign(fx) (fx = 0 पर और सम लंबाइयों के Nyquist bin पर 0)।
एक-तरफ़ा phase edges को उभारता है —— schlieren method का numerical रूप। ★Nyquist bin को 0 रखा जाता है
क्योंकि सम लंबाइयों के लिए fftfreq केवल -1/2 लौटाता है और मेल खाता +1/2 नहीं होता;
यदि इसे रखा जाता, तो real even function का आउटपुट odd symmetry को सटीक रूप से संतुष्ट नहीं करता
(मापा गया 1.6e-09 → 0 करने पर: 2.3e-16)। discrete Hilbert transform का मानक उपचार।
vortex
Vortex phase plate H = exp(i*charge*phi)। *charge* phase का winding number है:
Fourier plane में एक बंद loop का 1 चक्कर लगाने पर phase ठीक 2*pi*charge बढ़ता है
—— एक integer invariant, इसलिए यह gate का काम कर सकता है। ★DC term को 0 रखा जाता है (क्योंकि origin पर phi
अपरिभाषित है)। परिणामस्वरूप mean गिरता है, इसलिए plate
isotropic edge enhancement (radial Hilbert transform) की तरह काम करती है।
Ground truth (यह op क्या पुनः उत्पन्न करता है):
• four_f_filter से गुज़रा identity 180 degrees घुमाए गए इनपुट से मेल खाता है —— मापा गया अधिकतम निरपेक्ष अंतर 3.4e-16 (64x64 Gaussian, pixel_pitch_um=1)। Bit-identical नहीं: FFT round trip 1e-16 के कण जोड़ता है। zero-distance propagation की तरह short-circuit करने से यह सटीक हो जाता, पर वह केवल identity के लिए विशेष उपचार होता।
• Gaussian exp(-x**2/w**2) पर लगाया गया derivative_x order=1, -2x/w**2 * exp(-x**2/w**2) से मेल खाता है (band limit के भीतर)।
• vortex का winding number: बंद loop के साथ phase अंतरों का योग 2*pi से भाग देने पर ठीक *charge* है।
• lowpass + highpass = identity (समान *radius_frac* के साथ ठीक 1)।
Raises ValueError: *kind* ऊपर की सूची में नहीं / *size* 2 से कम या MAX_GRID से अधिक / *order* 0..8 के बाहर / *charge* -32..32 के बाहर / *radius_frac* 0 या कम या 1 से अधिक / *pixel_pitch_um* धनात्मक नहीं या finite नहीं।
optics के सभी ops गणना से पहले input की जाँच करते हैं (कुछ भी चुपचाप पास नहीं होता):
• Unit argument के नाम में ही लिखी होती है — _mm / _um / _deg / _mrad। mm और µm की गड़बड़ी crash नहीं करती, बल्कि "सही दिखने वाला पर गलत उत्तर" देती है, इसलिए नाम से इसे रोका जाता है। मान के आकार से unit का अनुमान बिल्कुल नहीं लगाया जाता।
• String से ValueError — float('50') सफल हो जाता है, इसलिए बिना parse किया config value length के रूप में निकल जाता (मापा गया: thin_lens('50', '200') सही दिखने वाला 66.667 mm लौटा रहा था)। bool को भी True == 1 वाले implicit promotion के रूप में अस्वीकार किया जाता है।
• complex / masked array से ValueError (केवल real-valued slots; imaginary part को चुपचाप छोड़ना या mask हटाना अस्वीकार)। हर input पर NaN/Inf से ValueError।
• शून्य से भाग और उससे जुड़े मामलों को नाम लेकर अस्वीकार किया जाता है: focal length 0, radius of curvature 0, refractive index <= 0, पूरी तरह opaque aperture (सब 0, इसलिए normalisation 0/0), ऐसा PSF जिसका योग <= 0 हो, S0 = 0 वाला Stokes vector, और front focal point पर रखा object (image अनंत पर)।
• केवल 2 ops non-finite value लौटाते हैं, और वह भी contract के रूप में लिखा हुआ: depth_of_field hyperfocal distance से आगे far_mm = inf (hyperfocal distance की परिभाषा यही है) और gaussian_beam waist पर wavefront_radius_mm = inf (plane wavefront की radius of curvature)। दोनों साथ में एक finite साथी (far_is_infinite / curvature_per_mm) भी लौटाते हैं। इसके अलावा कोई भी चुपचाप आया NaN/Inf अंदर ही पकड़ा जाता है और ValueError देता है — "float64 overflow हुआ" और "उत्तर अनंत है" अलग-अलग दावे हैं, इसलिए पहले को दूसरे का चेहरा पहनाकर नहीं लौटाया जाता।
• Size की सीमा: generate होने वाले grid के लिए optics.MAX_GRID (4096), दिए गए field/PSF/aperture के लिए optics.MAX_FIELD_ELEMENTS (2^24), ABCD element chain के लिए optics.MAX_SYSTEM_ELEMENTS (1024), Zernike के लिए MAX_ZERNIKE_TERMS (512) / MAX_ZERNIKE_ORDER (40) / MAX_ZERNIKE_BASIS (2^25)। छोटे argument से बहुत बड़ा internal allocation होने वाले रास्तों (मापा गया: n_max=40 × 4096² पर 108 GB) को fail-closed ढंग से बंद किया गया है।
• भौतिक रूप से असंभव states भी अस्वीकार: degree of polarisation > 1 वाला Stokes vector, ऋणात्मक transmittance, ऋणात्मक intensity, और n-|m| odd जैसे अमान्य Zernike indices।
• Sample data catalog (DL URL / license) — 2-D के लिए skimage.data (BSD/public) + synthetic, 3-D के लिए real data sources (Stanford/PDS आदि) के DL URL।
• Operators का स्रोत और संदर्भ — इस op family के मूल research/methods के स्रोत।
• Algorithm का मानक स्रोत (लेखक, वर्ष) और उपयोग ऊपर की family usage guide में दिए गए हैं।
• optics_four_f_processor — py -3.11 examples/optics_four_f_processor.py
cimage को input के रूप में लेते हैं)angular_spectrum_propagate · four_f_filter · jones_apply
wave)airy_pattern · angular_spectrum_propagate · fraunhofer_pattern · four_f_filter · gaussian_beam · defocus_from_shift · pupil_psf · pupil_blur
*Provenance: optics.py — OPTICS operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.