locate op• 数据种类:sweep → measurement
• 调用:import interferometry; interferometry.csi_peak_position(signal, z_step_um=0.05, z_start_um=0.0, wavelength_um=0.6, mode='gaussian', remove_bias=True, min_visibility=0.3, max_edge_envelope=0.05, carrier_tolerance=2.0)(或 opsinterferometry.get("csi_peak_position"))
由一次 z 扫描求表面高度:相干包络峰的位置。
> 以下的详细说明为原文 —— 摘要与标题已翻译。
This is the operator the whole module is for. Unlike a phase, an envelope has
no period, so there is no fringe order to get wrong and no unwrapping to do —
the height is simply where the fringe contrast is greatest, and it is correct
for a surface step of any size that stays inside the scan.
*mode* picks the estimator. Measured on the reference scan (0.60 um
wavelength, 2.83 um envelope FWHM, 0.05 um step, surface centred, four
sub-step offsets), and then again with 1 % additive noise over 200 trials:
• `"peak"` — the scan plane with the largest envelope. Noiseless
2.50e-02 um, which is exactly the step quantisation
`z_step_um/2`. Noisy RMS 0.1395 um.
• `"centroid"` — the centroid of the whole envelope. Noiseless
4.55e-07 um, and the best estimator under noise
(RMS 0.0219 um, 6.4x better than the local fits, because
it averages 241 planes instead of looking at 3 samples
around an argmax that noise moves). Its own failure is
*window bias*: it is pulled toward the centre of the
scan. Measured on a 12 um scan, a surface at 2 um reads
+0.189 um high with no noise at all and +0.873 um
high with a 2 % noise floor; at 10 um the same bias runs
the other way (-0.189 / -0.851). Centre the scan on the
surface, or use a local estimator.
• `"parabolic"` — three-point parabola on the envelope. 4.21e-06 um
noiseless, 0.1403 um noisy.
• `"gaussian"` — three-point parabola on the log of the envelope,
which is algebraically exact for a Gaussian envelope:
1.43e-07 um noiseless — and the floor there is the
Hilbert envelope's own 1.8e-07 error, not the fit, since
the same fit on the analytic envelope is exact to 3e-14
— and 0.1403 um noisy. The default.
There is no single best estimator here and this module does not pretend
otherwise: `"gaussian" is 30x better than "parabolic"` on clean data and
indistinguishable from it on noisy data, where `"centroid"` beats both by
6.4x — and `"centroid"` is the only one of the four whose bias grows with
how far the surface sits from the middle of the scan.
signal: 1-D scan intensities.
z_step_um: spacing of the scan planes. Must be below the
`wavelength_um/4` Nyquist ceiling — see
:func:csi_design.
z_start_um: height of plane 0.
wavelength_um: mean wavelength, used only for the Nyquist check.
mode: one of :data:ESTIMATORS.
remove_bias: passed to :func:csi_envelope.
min_visibility: refuse a scan whose envelope prominence
`(max - median)/max` is below this. A real interferogram
scores 0.958; the chain fuzzer's generic `signal` (a
sinusoid plus 10 % noise, no coherence envelope at all)
scores 0.241 and is refused; a constant scores 0.000. The
argmax of a flat envelope is a plane noise chose, not a
surface.
max_edge_envelope: refuse a scan whose envelope has not decayed by the ends,
`max(env[0], env[-1]) / max(env) > this`. See
:func:_edge_level for the measured table this default of
0.05 comes from, and for the silent failure it exists to
catch — a surface at 0.500 um read as 0.119 um, from an
envelope peaking on an *interior* plane so that no
first-or-last-plane check fires. Pass 1.0 to disable the
check and accept that reading.
carrier_tolerance: refuse a scan whose fringe carrier is more than this
factor away from the `2/wavelength_um` the stated
wavelength implies. This is the unit guard, and it is
the only thing standing between a nanometre/micrometre
swap and a wrong answer: *wavelength_um* is otherwise used
only for the Nyquist ceiling, so writing 600 instead of
0.6 silently disables that ceiling while changing nothing
in the returned height (measured: the same 6.025 um either
way). The default factor of 2 is deliberately loose — the
measured ratio on real scans is 0.996 and stays there
under 10 % noise, a truncated envelope and a 0.3 um
envelope — because it exists to catch a factor of 1000,
not to re-derive the wavelength. Scans shorter than 16
planes skip it (the FFT cannot resolve the carrier: the
ratio is 0.667 at 9 planes). Pass 0 to disable.
Returns the height as a float, in the same units as *z_start_um* /
*z_step_um*.
Raises `ValueError: everything :func:csi_envelope` raises, plus an
unknown *mode*, a non-positive *z_step_um* / *wavelength_um*, a *z_step_um* at
or past the Nyquist ceiling, an envelope prominence below *min_visibility*, an
envelope edge level above *max_edge_envelope*, and an envelope peaking on the
first or last plane (the surface is at or beyond the end of the scan).
Those last three are the same trap in three shapes: each would otherwise
return a height that is finite, plausible, and wrong.
Honest scope of the boundary check: it is a backstop, not the workhorse.
The analytic-signal magnitude of a finite record is suppressed at its own
endpoints, so a surface at `z = 0.0 — or at -3.0 um`, entirely outside
the scan — comes back with its envelope maximum on plane 1, one plane
inside the boundary, and the first-or-last-plane test does not fire. It fires
for a genuinely monotone input (a ramp, an impulse on the first sample) and
for a dead pixel. Everything else is caught by *max_edge_envelope*, and the
tests pin both halves of that statement.
• 示例数据目录(下载 URL / 许可证) —— 2-D 用 skimage.data(BSD/公有领域)加合成图,3-D 给出真实数据源(Stanford/PDS 等)的下载 URL。
• 算子来历与参考文献 —— 该算子族所依据的研究/方法出处。
• 算法的正典(作者・年份)与用途见上面的族使用指南。
• coherence_scanning — py -3.11 examples/coherence_scanning.py
measurement 作为输入)—
locate)—
*Provenance: interferometry.py — INTERFEROMETRY 算子登记表。本条目由 tools/opdocs.py md 自动生成(请勿手工编辑)。*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.