Peakdetect
The library peakdetect
[1] is based on Billauers work [2] and this gist [3]. The method is directly incorporated in findpeaks
and has a strong advantage to
find the local maxima and minima in noisy signal. Noisy data is very common in real-life signals, which makes methods such as zero-derivates not applicable.
The typical solution is to smooth the curve with some low-pass filter but this comes with the trade-off that the peaks in the original signal may be lost.
This method works only for one-dimensional data.
One-dimensional data
For the peakdetect method, we need to set the lookahead parameter, which is the distance to look ahead from a peak candidate to determine if it is the actual peak. The default value is set to 200 but this value is way too large for small datasets (i.e., with <50 data points).
# Import library
from findpeaks import findpeaks
# Initialize
fp = findpeaks(method='peakdetect', lookahead=1, interpolate=None)
# Example 1d-vector
X = fp.import_example('1dpeaks')
# Fit topology method on the 1d-vector
results = fp.fit(X)
# The output contains multiple variables
print(results.keys())
# dict_keys([df'])
+----+-----+------+--------+----------+--------+
| | x | y | labx | valley | peak |
+====+=====+======+========+==========+========+
| 0 | 0 | 1.5 | 1 | True | False |
+----+-----+------+--------+----------+--------+
| 1 | 1 | 0.8 | 1 | False | False |
+----+-----+------+--------+----------+--------+
| 2 | 2 | 1.2 | 1 | False | False |
+----+-----+------+--------+----------+--------+
| 3 | 3 | 0.2 | 2 | True | False |
+----+-----+------+--------+----------+--------+
| 4 | 4 | 0.4 | 2 | False | False |
+----+-----+------+--------+----------+--------+
| 5 | 5 | 0.39 | 2 | False | False |
+----+-----+------+--------+----------+--------+
| 6 | 6 | 0.42 | 2 | False | True |
+----+-----+------+--------+----------+--------+
| 7 | 7 | 0.22 | 2 | False | False |
+----+-----+------+--------+----------+--------+
| 8 | 8 | 0.23 | 2 | False | False |
+----+-----+------+--------+----------+--------+
| 9 | 9 | 0.1 | 3 | True | False |
+----+-----+------+--------+----------+--------+
| 10 | 10 | 0.11 | 3 | False | False |
+----+-----+------+--------+----------+--------+
| 11 | 11 | 0.1 | 3 | False | False |
+----+-----+------+--------+----------+--------+
| 12 | 12 | 0.14 | 3 | False | True |
+----+-----+------+--------+----------+--------+
| 13 | 13 | 0.09 | 3 | False | False |
+----+-----+------+--------+----------+--------+
| 14 | 14 | 0.04 | 3 | False | False |
+----+-----+------+--------+----------+--------+
| 15 | 15 | 0.02 | 3 | False | False |
+----+-----+------+--------+----------+--------+
| 16 | 16 | 0.01 | 3 | True | False |
+----+-----+------+--------+----------+--------+
The output is a dictionary containing a single dataframe (df) that can be of use for follow-up analysis. See: findpeaks.findpeaks.findpeaks.peaks1d()
The strength of this approach becomes visible when we use a noisy dataset.
# Import library
from findpeaks import findpeaks
# Initialize
fp = findpeaks(method='peakdetect', lookahead=200, interpolate=None)
# Example 1d-vector
i = 10000
xs = np.linspace(0,3.7*np.pi,i)
X = (0.3*np.sin(xs) + np.sin(1.3 * xs) + 0.9 * np.sin(4.2 * xs) + 0.06 * np.random.randn(i))
# Fit topology method on the 1d-vector
results = fp.fit(X)
# Plot
fp.plot()