Skip to content Skip to sidebar Skip to footer

Smoothing A Curve With Many Peaks With Gaussian

I have spectroscopy data with some very sharp peaks as seen in blue curve. I would like to make the peaks a bit more smooth like the orange curve in the plot. I thought the easies

Solution 1:

Looks like you want a "kernel density estimator" which is implemented by:

from scipy.stats import gaussian_kde

X = np.random.rand(50) * 3500
Y = np.random.rand(50) * 50
xi = linspace(0, 3500, 1000)

kde = gaussian_kde(X, weights = Y, bw_method = .01)  #tune `bw_method` to get the bandwidth you want
plt.plot(xi, kde.pdf(xi))

You may also need to adjust the y scaling of the graph to match your requirements

Solution 2:

This is manually reproducing the orange curve given in the OP. Turns out it is convoluted with a Lorentzian not Gaussian.

import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import find_peaks
from scipy.optimize import curve_fit

defgs( x, x0, a, s ):
    return a * np.exp( -( x - x0 )**2 / ( 2 * s**2 ) )

defcs( x, x0, a, s ):
    return a / ( ( x - x0 )**2 + s**2 )

conrange = 40000### gasiian is no good# ~condata = np.fromiter( ( gs(x, 0, 1, 1800 ) for x in np.arange( -5000, 5000 ) ), np.float )### Cauchy looks much better
condata = np.fromiter( 
    ( 
        cs( x, 0, 1, 2000 ) for x in np.arange( -conrange, conrange ) 
    ), np.float
)
### shift can be zero. ### Amplitude does not matter as it will be scaled later anyway### width matters of course, but is adjusted manually for the moment.

data = np.loadtxt("ir_data.txt")
xdata = data[:, 0]
ydata = data[:, 1]

xdataint = np.fromiter( ( int( x* 100 ) for x in xdata ), int ) 
xmin = xdataint[0]
xmax = xdataint[-1]
xfilled = np.arange( xmin , xdataint[-1] + 1 )
yfilled = np.zeros( len( xfilled ), dtype=np.float )
xfloat = np.fromiter( ( x / 100.for x in xfilled), float ) 


for x, y inzip( xdataint, ydata ):
    yfilled[ x - xmin ] = y
### just putting a manual scale here, but the real one can be calculated### from the convolution properties
yc = 1e6 * np.convolve( condata, yfilled, mode="full" )

xfull = np.arange(
    -conrange + xmin, xmin + conrange + len( xfilled ) - 1
)
xfloat = np.fromiter( ( 0.01 * x for x in xfull ), float )

fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )
ax.plot( xdata, ydata, ls='', marker='o', ms=2 )
ax.plot( xfloat, yc, ls='-')
plt.show()

Disclaimer

This are preliminary results and only posted due to request from the author of the OP. The might be some refinement.

Post a Comment for "Smoothing A Curve With Many Peaks With Gaussian"