Source code for sofia_redux.spectroscopy.smoothres
# Licensed under a 3-clause BSD style license - see LICENSE.rst
from astropy import log
import numpy as np
from scipy.signal import convolve
import warnings
__all__ = ['smoothres']
[docs]
def smoothres(x, y, resolution, siglim=5):
"""
Smooth a data to a constant resolution
The procedure is:
1. Resample data to a constant spacing in log(wavelength).
2. Convolve resampled data with Gaussian kernel.
3. Interpolate back to linear wavelength spacing.
Parameters
----------
x : array_like of (int or float)
(N,) independent variable
y : array_like if (int or float)
(N,) dependent variable
resolution : int or float
Spectral resolution to smooth to
siglim : int or float, optional
Maximum fwhm deviation
Returns
-------
numpy.ndarray
(N,) The smoothed data array.
"""
x, y = np.array(x), np.array(y)
if x.shape != y.shape:
raise ValueError("x and y array shape mismatch")
elif x.ndim != 1:
raise ValueError("x and y arrays must have 1 dimension")
elif resolution < 0:
raise ValueError("resolution must be positive")
elif np.allclose(resolution, 0):
return y
n = x.size
with warnings.catch_warnings():
warnings.simplefilter('ignore', RuntimeWarning)
xmin, xmax = np.nanmin(x), np.nanmax(x)
a = (n - 1) / (np.log(xmax) - np.log(xmin))
b = n - (a * np.log(xmax))
xpon = np.arange(n, dtype=float) + 1
xlog = np.exp((xpon - b) / a)
ylog = np.interp(xlog, x, y)
# Resample to constant spacing in log lambda; dv/c = d(ln lambda)
sigma = 1 / (resolution * 2 * np.sqrt(2 * np.log(2)))
wgauss = (np.arange(n) - (n / 2)) / a
idx = np.abs(wgauss / sigma) <= siglim
nok = idx.sum()
if nok > (n / 2):
log.warning(
"Kernel too large; "
"only part of the input array will be correctly convolved")
elif nok < 2:
log.error("No data less than sigma limit: all data=%s" % np.nan)
return np.full(y.shape, np.nan)
psf = np.exp(-0.5 * ((wgauss[idx] / sigma) ** 2))
psf /= psf.sum()
# perform convolution
yconv = convolve(ylog, psf, mode='same')
yconv[~np.isfinite(yconv)] = 0
# Switch back to linear x-spacing
yout = np.interp(x, xlog, yconv)
return yout