Skip to content

Commit

Permalink
Add Janko Slavic findpeaks function
Browse files Browse the repository at this point in the history
  • Loading branch information
MonsieurV committed Nov 12, 2015
1 parent 9540d8e commit 261acd2
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 2 deletions.
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This is an overview of all the ready-to-use algorithms I've found to perform pea
| [peakutils.peak.indexes](#peakutilspeakindexes) | PyPI package PeakUtils<br> Depends on Scipy | Amplitude threshold<br>Minimum distance ||
| [peakdetect](#peakdetect-from-sixtenbe) | Single file source<br>Depends on Scipy | Minimum peak distance ||
| [Octave-Forge findpeaks](#octave-forge-findpeaks) | Requires an Octave-Forge distribution<br>+ PyPI package oct2py<br>Depends on Scipy | Minimum distance<br>Minimum height<br>Minimum peak width ||
| [Janko Slavic findpeaks](#Janko-Slavic-Findpeaks) | Single function<br>Depends on Numpy | Minimum distance<br>Minimum height ||
| [Lightweight standalone peaks](#lightweight-standalone-peaks) | Single function<br>Depends on Numpy | Amplitude threshold ||

## How to make your choice?
Expand Down Expand Up @@ -140,6 +141,26 @@ Requires a rather complicated and not very efficient setup to be called from Pyt

Although the function have an interface close to the MatLab `findpeaks`, it is harder to have the exact same results that with [detect_peaks](#detect_peaks-from-marcos-duarte) or [peakutils.peak.indexes](#peakutilspeakindexes).

## Janko Slavic findpeaks

![](/images/janko_slavic_findpeaks.png?raw=true "Janko Slavic findpeaks")

```python
import numpy as np
from vector import vector, plot_peaks
from libs.findpeaks import findpeaks
indexes = findpeaks(np.array(vector), spacing=, limit=7)
print('Peaks are: %s' % (indexes))
```

[Documentation](https://github.com/jankoslavic/py-tools/blob/master/findpeaks/Findpeaks%20example.ipynb).
[Source](https://github.com/jankoslavic/py-tools/blob/master/findpeaks/findpeaks.py).
[Sample code](/tests/janko_slavic_findpeaks.py).

Small and fast peak detection algorithm, with minimum distance and height filtering support. Comes as a single function depending only on Numpy.

The minimum distance filter miss fine granularity tuning (you may filter too many or too few peaks).

## Lightweight standalone peaks

![](/images/lightweight_standalone_peaks.png?raw=true "Lightweight standalone peaks")
Expand All @@ -155,9 +176,10 @@ print('Peaks are: %s' % (indexes))

[Source and documentation](/tests/lightweight_standalone_peaks.py#L7).

Straightforward, simple and lightweight.
Straightforward, simple and lightweight peak detection algorithm.

Miss minimum peak height filtering.

Definitely less complete filtering and tuning support than MatLab Signal Processing Toolbox `findpeaks`.

----------------------------------

Expand Down
Binary file added images/janko_slavic_findpeaks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions tests/janko_slavic_findpeaks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from vector import vector, plot_peaks
from libs.findpeaks import findpeaks

print('Detect peaks without any filters.')
indexes = findpeaks(np.array(vector), spacing=1)
print('Peaks are: %s' % (indexes))
plot_peaks(np.array(vector), np.array(indexes),
algorithm='findpeaks from Janko Slavic')

print('Detect peaks with distance and height filters.')
indexes = findpeaks(np.array(vector), spacing=2, limit=7)
print('Peaks are: %s' % (indexes))
plot_peaks(np.array(vector), np.array(indexes), mph=7, mpd=2,
algorithm='findpeaks from Janko Slavic')
52 changes: 52 additions & 0 deletions tests/libs/findpeaks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
""" Searches for peaks in data
History:
-nov 2015: Janko Slavic, update
-mar 2013: [email protected]
"""

import numpy as np

def findpeaks(data, spacing=10, limit=None):
"""Finds peaks in `data` which are of `spacing` width and >=`limit`.
:param data: values
:param spacing: minimum width for single peak
:param limit: peaks should have value greater or equal
:return:
"""
x = np.zeros(len(data)+2*spacing)
x[:spacing] = data[0]
x[-spacing:] = data[-1]
x[spacing:-spacing] = data
peak_candidate = np.zeros(x.size - 2*spacing - 2)
peak_candidate[:] = True
for s in range(spacing):
h_b = x[s:-2 * spacing + s - 2] # before
h_c = x[spacing: -spacing - 2] # central
h_a = x[spacing + s + 1: -spacing + s - 1] # after
peak_candidate = np.logical_and(peak_candidate, np.logical_and(h_c > h_b, h_c > h_a))

ind = np.argwhere(peak_candidate)
ind = ind.reshape(ind.size)
if limit is not None:
ind = ind[data[ind] > limit]
return ind


if __name__ == '__main__':
import matplotlib.pyplot as plt

n = 1000
m = 20
t = np.linspace(0., 1, n)
x = np.zeros(n)
np.random.seed(0)
phase = 2 * np.pi * np.random.random(m)
for i in range(m):
x += np.sin(phase[i] + 2 * np.pi * t * i)

peaks = findpeaks(x, spacing=100, limit=4.)
plt.plot(t, x)
plt.axhline(4, color='r')
plt.plot(t[peaks], x[peaks], 'ro')
plt.title('Peaks: minimum value 4., minimum width 100 points')
plt.show()

0 comments on commit 261acd2

Please sign in to comment.