Finding width of peaks
<p>I have a data set on which I'm trying to detect peaks and the left/right bounds of those peaks.</p>

<p>I'm successfully using <a href="http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks_cwt.html" rel="nofollow">scipy <code>find_peaks_cwt</code></a> to find the peaks, but I don't know how to then identify the left and right bounds of those peaks.</p>

<p>In the below graph, the line and circle markers on the peaks are being drawn programmatically, but the square markers were drawn by hand are what I'm now trying to do programmatically.</p>

<p><a href="http://i.stack.imgur.com/U1yg6.png" rel="nofollow"><img src="http://i.stack.imgur.com/U1yg6.png" alt="enter image description here"></a></p>

<p>Any advice on how to do this? I considered searching for inflection points, but that won't work because of the noise in the data.</p>

<p>If a Gaussian fit would be appropriate, you could take the number of peaks you have found and fit n Gaussian distributions (1 for each peak) plus a constant variable for the background noise (or you could add another Gaussian to the curve fit</p>

<pre class="lang-python prettyprint-override"><code>import numpy as np
from scipy.optimize import curve_fit
from scipy.signal import find_peaks_cwt
from math import *

peak_indices = find_peaks_cwt(data, *args)

#make a fitting function that takes x number of peak widths
def makeFunction(indices, data):
    def fitFunction(x, *args):
        #sum of gaussian functions with centers at peak_indices and heights at data[peak_indices] plus a constant for background noise (args[-1])
        return sum([data[indices[i]]*exp(-((x-indices[i])**2)/(2*args[i]**2)) for i in range(len(peak_indices))])+args[-1]                                                      #does my code golfing show? xD
    return fitFunction

f = makeFunction(peak_indices, data)

#you must provide the initial guess of "np.ones(len(peak_indices)+1)" for the parameters, because f(x, *args) will otherwise take a variable number of arguments.
popt, pcov = curve_fit(f, np.arange(len(data)), data, np.ones(len(peak_indices)+1))

#standard deviations (widths) of each gaussian peak and the average of the background noise
stdevs, background = popt[:-1], popt[-1]
#covariance of result variables
stdevcov, bgcov = pcov[:-1], pcov[-1]
</code></pre>

<p>This should give you a place to start, but you'll likely have to tweak the optimization function to work with your data (or maybe work at all, I didn't test)</p>

python numpy scipy