linescan op• Data kinds: table → table
• Call: import fullseye as fs; fs.ledger.lens_field_profile(system=None, image_heights_mm=None, frequencies_lp_mm=(10.0, 20.0, 35.0), grid=96, wavelength_um=None) (to call the implementation directly, import linescan; linescan.lens_field_profile(system=None, image_heights_mm=None, frequencies_lp_mm=(10.0, 20.0, 35.0), grid=96, wavelength_um=None); from the registry, opsoptics.get("lens_field_profile"))
Relative illumination and MTF for each image height, by ray tracing (table, object at a finite distance — the line-scan use).
> The detailed description below is the original text — the summary and the headings are translated.
照度: Lambert の物点から射影立体角の一様格子で光線を出し、像面に届いた光束を数える(_flux_trace)。像面の照度 = 光束 ÷ 像の面積要素(径方向の倍率 × 接線方向の倍率、像高の有限差分 —— 歪曲も入る)。相対照度は 3 つの積に厳密に分かれる(どれも返す):
relative_illumination = cos4 × pupil_factor × area_gain
• cos4: 物体側の主光線角(物点から近軸の入射瞳の中心へ)の cos⁴ —— 自然な周辺減光の閉形式(optics.relative_illumination と同じ式)。
• pupil_factor = (光束の比) / cos4: 1 なら理想の cos⁴、1 未満は口径食(鏡筒・レンズの縁・面の球の端で光束が欠ける)、1 より大きいのは軸外で入射瞳が広がって見える(瞳収差)。
• area_gain = 軸上の面積要素 / その像高の面積要素: 樽型歪曲は像を縮めるので照度を上げる。
MTF: 通った光線の像面の座標から幾何光学の OTF の絶対値 |⟨exp(−2πi ν (x − x̄))⟩|(各光線は等しい光束)を、サジタル(像高に直交、x)とタンジェンシャル(像高の向き、y)で。回折の MTF(円形瞳、近軸の作動 F 値)を mtf_diffraction に並べ、mtf_sagittal / mtf_tangential は幾何 × 回折(積の近似 —— 収差が回折より十分大きいか小さいときに良い)。ラインセンサは径方向に 1 列に並ぶので、タンジェンシャル = 幅方向(画素の並び)、サジタル = 流れ方向。
*system*: raytrace.lens_system(有限距離の物体、既定 = linescan_lens_example("linescan"))。*image_heights_mm*: 像高(既定 0〜28.672 mm = 8192 × 7 µm の半分を 9 点)—— 物体高は近軸倍率で割って出す。像高の位置(面積要素)は主光線、主光線が通らなければ通った光線の重心で測る。返り値 dict: image_height_mm / object_height_mm / chief_image_mm / distortion_percent / relative_illumination / cos4 / pupil_factor / area_gain / flux_ratio / frequencies_lp_mm / mtf_sagittal / mtf_tangential(像高 × 周波数)/ mtf_geometric_sagittal / mtf_geometric_tangential / mtf_diffraction / covered(光線が 3 本以上届いたか)/ magnification / working_fno。届かない像高は照度 0・MTF NaN(covered False)。
Raises ValueError: 物体が無限遠(像の面積要素の扱いが違う —— optics.relative_illumination / lensimage を使う)/ 像高・周波数が非有限か負 / grid が [16, 256] の外 / 軸上で光線が 1 本も通らない / 窓を広げても光線が窓の縁を通る。
Every optics op validates its input before computing (nothing slips through silently):
• Units are baked into the argument name — _mm / _um / _deg / _mrad. Confusing mm with µm does not crash; it yields a plausible-looking wrong answer, so the name prevents it. Nothing here guesses the unit from the magnitude.
• Strings raise ValueError — float('50') succeeds, so an unparsed configuration value would slip through as a length (measured: thin_lens('50', '200') returned a plausible 66.667 mm). bool is refused too, as the implicit promotion True == 1.
• complex / masked arrays raise ValueError (real-valued slots only; silently dropping the imaginary part or peeling off the mask is refused). NaN/Inf raises ValueError on every input.
• Division by zero and its relatives are refused by name: focal length 0, radius of curvature 0, refractive index <= 0, a fully opaque aperture (all zeros, so the normalisation is 0/0), a PSF whose sum is <= 0, a Stokes vector with S0 = 0, and an object sitting at the front focal point (the image is at infinity).
• Only two ops return a non-finite value, and both state it as a contract: depth_of_field returns far_mm = inf beyond the hyperfocal distance (that is what the hyperfocal distance means), and gaussian_beam returns wavefront_radius_mm = inf at the waist (the radius of curvature of a plane wavefront). Both also return a finite companion (far_is_infinite / curvature_per_mm). Any other silent NaN/Inf is detected internally and raises ValueError — "float64 overflowed" and "the answer is infinite" are different claims, so the first is never returned wearing the face of the second.
• Size caps: generated grids are capped by optics.MAX_GRID (4096); supplied fields/PSFs/apertures by optics.MAX_FIELD_ELEMENTS (2^24); ABCD element chains by optics.MAX_SYSTEM_ELEMENTS (1024); Zernike by MAX_ZERNIKE_TERMS (512) / MAX_ZERNIKE_ORDER (40) / MAX_ZERNIKE_BASIS (2^25). This closes, fail-closed, the paths where a small argument triggers a huge internal allocation (measured: n_max=40 × 4096² needs 108 GB).
• Physically impossible states are refused too: a Stokes vector with degree of polarisation > 1, negative transmittance, negative intensity, and invalid Zernike indices such as n-|m| odd.
• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).
• Operator provenance and references — the sources of the research/methods this op family came from.
• The canonical algorithm (author, year) and its uses are named in the family usage guide above.
• poc_tdi_linescan — py -3.11 examples/poc_tdi_linescan.py
table as input)abcd_matrix · wavefront_stats · sfr_from_edge · paraxial_trace · seidel_coefficients · spot_stats · tolerance_analysis · wavefront_from_opd
linescan)tdi_snr · tdi_sync_mtf · linescan_acquire · linescan_lens_columns · linescan_lens_example
*Provenance: linescan.py — OPTICS operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.