Context
The pure-Python convolution (tetrapy/convolve.py) validates against specpr's output at median RMS ~4.4e-5 (reflectance 0-1). Two minor algorithmic differences remain vs the Fortran implementation in specpr/src.specpr/fcn17-19/:
Differences
1. delx channel-spacing weight (convol.r:70)
Specpr's convol subroutine multiplies each Gaussian weight by delx(x, t, r, j, nchans) — a trapezoidal integration factor accounting for non-uniform channel spacing in the native library. Our Python just does a straight weighted average without this factor.
For uniformly-spaced channels this nearly cancels in the normalization (hence the small RMS), but for spectra with irregular native grids it could matter more.
2. tlim threshold (f17.r:149)
Specpr defaults to tlim = 0.1e-7 — Gaussian weights below this are zeroed. Our Python uses w > 1e-6 (10x higher). This means we exclude slightly more of the Gaussian tails.
3. Edge case: output FWHM ≤ native FWHM (gfiles.r:284-289)
Specpr sets bwidth = native_fwhm * 0.01 and snaps the center to the nearest native channel. Our Python uses output_fwhm * 0.05. Both are degenerate-case fallbacks; specpr's is more aggressive (narrower kernel, delta-like interpolation).
What matches
- Gaussian formula (identical math)
- Quadrature correction
√(out² - native²) (specpr gfiles.r:292, Python convolve.py:172)
- Normalization mode (
nmode=1, set by the n in conv.s06emitc.cmds → work/convolve.cmds.work:4)
References
specpr/src.specpr/fcn17-19/convol.r — the convolution kernel
specpr/src.specpr/fcn17-19/ggauss.r — Gaussian generation
specpr/src.specpr/fcn17-19/gfiles.r — quadrature correction + file I/O
specpr/src.specpr/fcn17-19/f17.r — the driver (sets nmode/tlim/gmode, loops over output channels)
spectroscopy-tetracorder/sl1/usgs/library06.conv/work/convolve.cmds.work — the command sequence
Context
The pure-Python convolution (
tetrapy/convolve.py) validates against specpr's output at median RMS ~4.4e-5 (reflectance 0-1). Two minor algorithmic differences remain vs the Fortran implementation inspecpr/src.specpr/fcn17-19/:Differences
1.
delxchannel-spacing weight (convol.r:70)Specpr's
convolsubroutine multiplies each Gaussian weight bydelx(x, t, r, j, nchans)— a trapezoidal integration factor accounting for non-uniform channel spacing in the native library. Our Python just does a straight weighted average without this factor.For uniformly-spaced channels this nearly cancels in the normalization (hence the small RMS), but for spectra with irregular native grids it could matter more.
2.
tlimthreshold (f17.r:149)Specpr defaults to
tlim = 0.1e-7— Gaussian weights below this are zeroed. Our Python usesw > 1e-6(10x higher). This means we exclude slightly more of the Gaussian tails.3. Edge case: output FWHM ≤ native FWHM (
gfiles.r:284-289)Specpr sets
bwidth = native_fwhm * 0.01and snaps the center to the nearest native channel. Our Python usesoutput_fwhm * 0.05. Both are degenerate-case fallbacks; specpr's is more aggressive (narrower kernel, delta-like interpolation).What matches
√(out² - native²)(specprgfiles.r:292, Pythonconvolve.py:172)nmode=1, set by theninconv.s06emitc.cmds→work/convolve.cmds.work:4)References
specpr/src.specpr/fcn17-19/convol.r— the convolution kernelspecpr/src.specpr/fcn17-19/ggauss.r— Gaussian generationspecpr/src.specpr/fcn17-19/gfiles.r— quadrature correction + file I/Ospecpr/src.specpr/fcn17-19/f17.r— the driver (sets nmode/tlim/gmode, loops over output channels)spectroscopy-tetracorder/sl1/usgs/library06.conv/work/convolve.cmds.work— the command sequence