relative_illumination — OPTICS geometric op

• Data kinds: कोई नहीं → pairs (केवल arguments से तय होने वाला op — यह कोई image या data input नहीं लेता)

• Call: import fullseye as fs; fs.ledger.relative_illumination(half_angle_deg=20.0, samples=64, exponent=4.0) (implementation को सीधे call करना हो तो import optics; optics.relative_illumination(half_angle_deg=20.0, samples=64, exponent=4.0), registry से लेना हो तो opsoptics.get("relative_illumination"))

उपयोग

Natural vignetting: field angle के सापेक्ष relative image-plane illuminance।

> नीचे का विस्तृत विवरण मूल text में है — सारांश और headings का अनुवाद हो चुका है।

The cosine-fourth law E(theta)/E(0) = cos(theta)^4 — one cosine from the inverse-square increase in distance to the off-axis point (twice), one from the tilt of the exit pupil as seen from there, one from the tilt of the image plane. Sampled uniformly in angle from 0 to *half_angle_deg*.

Returns an (samples, 2) float64 pairs array: column 0 the field angle in degrees, column 1 the relative illuminance in [0, 1].

*exponent* exists because the fourth power is the *ideal symmetric* case:

a lens with pupil aberration, or a telecentric design, or one with a tilted entrance pupil, falls off closer to cos^3 (or is deliberately corrected flatter still). Setting the exponent is how you say which lens you have — it is not a fudge factor to be tuned after the fact.

Ground truth it reproduces exactly: cos^4(45 deg) = 1/4 and cos^4(60 deg) = 1/16, both to machine precision; the curve is 1.0 on axis and monotonically decreasing.

Raises ValueError: *half_angle_deg* outside (0, 90) — at 90 degrees the illuminance is exactly 0 and the "relative" curve carries no information; *samples* outside [2, MAX_GRID]; a negative or non-finite *exponent*.

This is the *natural* falloff only. Mechanical vignetting (a stop clipping the oblique beam) is a separate, lens-specific effect that no closed form covers — measure it with a flat field.

पूरी family का input contract (fail-closed)

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।

उपयोग की विस्तृत guide

• optics_imaging family guide

संदर्भ (sample data, साहित्य)

• 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 में दिए गए हैं।

चलाए जा सकने वाले उदाहरण (verified samples जो सच में यह op call करते हैं)

• optics_imaging — py -3.11 examples/optics_imaging.py

• poc_search_sweep_width — py -3.11 examples/poc_search_sweep_width.py

वे अगले ops जिनसे type जुड़ता है (pairs को input के रूप में लेते हैं)

mtf50

इसी category के (geometric)

thin_lens · abcd_matrix · abcd_trace · depth_of_field


*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.