linescan_acquire — OPTICS linescan op

• Data kinds: image2d → table

• Call: import fullseye as fs; fs.ledger.linescan_acquire(web=None, stages=8, photons_per_stage=200.0, eta=0.6, sigma_d=20.0, K=0.1, architecture='charge', full_well_e=None, dark_e=0.0, sync_error=0.0, yaw_deg=0.0, weave_px=0.0, weave_period_lines=200.0, encoder=False, encoder_error=None, lines=None, width=None, lens=None, noise=True, order=3, samples_per_px=4.0, oversample=1, seed=0) (implementation को सीधे call करना हो तो import linescan; linescan.linescan_acquire(web=None, stages=8, photons_per_stage=200.0, eta=0.6, sigma_d=20.0, K=0.1, architecture='charge', full_well_e=None, dark_e=0.0, sync_error=0.0, yaw_deg=0.0, weave_px=0.0, weave_period_lines=200.0, encoder=False, encoder_error=None, lines=None, width=None, lens=None, noise=True, order=3, samples_per_px=4.0, oversample=1, seed=0), registry से लेना हो तो opsoptics.get("linescan_acquire"))

उपयोग

reflectance map *web* को sensor के आगे से ले जाते हुए TDI line-scan camera से capture करना (table)।

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

*web*: 2-D の反射率 [0, 1] (行 = 流れ方向 MD、列 = 幅方向 CD)。1 行 = 公称の 1 ライン、1 列 = 1 画素の格子。センサ(幅 *width* 画素、既定 = web の幅から余白を除いた分)は web の中央を見る。

運動の模型(出力ライン k・段 s・段の中の時刻 u ∈ [0, 1)、τ = k + s + u):

web の進み T(τ) = ∫(1 + ε)(sync_error がスカラなら一定、1-D ならライン周期ごと —— 長さは

lines + stages 以上)、電荷の位置 r = s + u(1 周期に 1 行)、蛇行 w(τ) = weave_px·sin(2πτ/周期)。

web の行 = T(τ) − r·cos θ − x·sin θ、web の列 = x·cos θ − r·sin θ − w(τ)(x はセンサ中央からの画素)。

θ = 0・一定 ε なら行は k(1 + ε) + (s + u)ε —— optscene.linescan_capture と同じ規約で、N 段で

N·|ε| 画素の掃引(tdi_sync_mtf の閉形式)。encoder=True は web の進みからライン周期を作る

(速度の誤差が消え、ε = *encoder_error*(既定 None = 0、エンコーダの分解能の誤差)だけが残る —— encoder=False で

渡すと効かないので ValueError)。ヨーと蛇行は残る。

*oversample*(奇数、既定 1): web が 1 画素あたり何 web 画素で描かれているか。1 より大きいと、画素の開口(oversample × oversample の箱)を掛けてから標本を取る —— 細かい正弦波の板で MTF を測るときは補間の誤差が結果に混ざらないよう 5 などにする(3 次スプラインでも 0.4 c/px では補間だけで 2 割落ちる)。

時間積分は τ の一様な標本で取り、標本数は 1 段の道のり(滑り + 蛇行)から samples_per_px 点/画素で決める(完全同期なら 1 点で厳密)。補間は order(1 = 双線形、3 = 3 次スプライン、前置フィルタは 1 回だけ)。

雑音(noise=True、EMVA 1288 の線形模型): 平均電子 μ_e = Σ 段 ημ_p·R(+ 暗電流 *dark_e*/段)を Poisson 1 回で引き(Poisson の和は Poisson —— 厳密)、charge は読み出し σ_d を 1 回、digital は分散 Nσ_d² と量子化 N/12 DN² を正規雑音で(各段の丸めの近似)。full_well_e(既定 None = 飽和なし)は電荷加算では合計に、デジタル加算では 1 段の平均に掛ける。返す画像は DN = K·e(ADC の上限では切らない)。

*lens*: linescan_lens_columns の結果(列ごとの相対照度とガウスのぼけ)。光学像は運動の前に決まるので、ぼけと照度は地図に掛けてから搬送する(同じ列は同じぼけ —— 像高はセンサの列で決まる)。

返り値 dict: image (lines, width) DN / mean_e(雑音なしの期待電子)/ line_rows(各ラインの段の中央が見る web の行 [web 画素]、センサ中央の列で)/ col0(センサの列 0 が見る web の列 [web 画素])/ slip_scan / slip_cross / smear_scan_px / smear_cross_px / samples / stages / architecture。

Raises ValueError: web が 2-D の有限な [0, 1] でない / 段数・ライン数が範囲外 / ε が範囲外か長さ不足 / encoder=False で encoder_error を渡した / oversample が偶数 / 掃引・蛇行・ヨーで標本が web の外に出る(黙って端を繰り返さない)/ lens の列数が width と違う。

पूरी 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 करते हैं)

• poc_tdi_linescan — py -3.11 examples/poc_tdi_linescan.py

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

abcd_matrix · wavefront_stats · sfr_from_edge · paraxial_trace · seidel_coefficients · spot_stats · tolerance_analysis · wavefront_from_opd

इसी category के (linescan)

tdi_snr · tdi_sync_mtf · lens_field_profile · linescan_lens_columns · linescan_lens_example


*Provenance: linescan.py — OPTICS operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.