Scipy Find Peaks

Recently, I was working on a signal processing project where I needed to identify peaks in time-series data from fitness trackers. The challenge was finding a reliable way to detect these peaks without manually parsing through thousands of data points.

That’s when I turned to SciPy’s find_peaks function. It’s an incredibly powerful tool that makes peak detection easy in Python.

In this article, I will share my practical experience with scipy.find_peaks and demonstrate how to use it effectively for your data analysis tasks.

What is SciPy Find Peaks?

SciPy find_peaks is a function from the scipy.signal module that detects local maxima (peaks) in a 1-dimensional array. It provides various parameters to fine-tune your peak detection requirements.

Unlike manual peak detection, which can be tedious and error-prone, scipy.find_peaks automates this process with just a few lines of code.

The basic syntax is quite simple:

from scipy.signal import find_peaks
peaks, _ = find_peaks(x)

Where x is your 1D array of data.

Get Started with Find Peaks

Let’s look at a basic example of how to use find_peaks:

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

# Create a sample signal with some peaks
x = np.sin(np.linspace(0, 10, 1000)) + 0.2*np.random.randn(1000)

# Find peaks
peaks, _ = find_peaks(x)

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(x)
plt.plot(peaks, x[peaks], "x", color='red')
plt.title("Basic Peak Detection")
plt.xlabel("Sample Index")
plt.ylabel("Amplitude")
plt.grid(True)
plt.show()

You can see the output in the screenshot below.

find_peaks python

In this example, we’ve created a noisy sine wave and detected its peaks. The red “x” marks show where the function identified peaks in our data.

Check out Python SciPy Exponential

Filter Peaks by Height

When analyzing real-world data, like stock market trends or heart rate measurements, you often want to filter out smaller peaks and focus on significant ones.

To do this, we can use the height parameter:

# Find peaks with a minimum height of 0.5
peaks, _ = find_peaks(x, height=0.5)

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(x)
plt.plot(peaks, x[peaks], "x", color='red')
plt.axhline(y=0.5, color='r', linestyle='--')
plt.title("Peak Detection with Minimum Height")
plt.xlabel("Sample Index")
plt.ylabel("Amplitude")
plt.grid(True)
plt.show()

You can see the output in the screenshot below.

find peaks scipy

This is particularly useful when you want to set a threshold for what constitutes a “significant” peak in your data.

Read Python SciPy Confidence Interval

Find Peaks with Minimum Distance

Another common requirement is finding peaks that are separated by a minimum distance. This helps avoid detecting multiple peaks in close proximity.

Here’s how to use the distance parameter:

# Find peaks with minimum separation of 50 samples
peaks, _ = find_peaks(x, distance=50)

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(x)
plt.plot(peaks, x[peaks], "x", color='red')
plt.title("Peak Detection with Minimum Distance")
plt.xlabel("Sample Index")
plt.ylabel("Amplitude")
plt.grid(True)
plt.show()

You can see the output in the screenshot below.

find_peaks_cwt

This approach is particularly valuable when analyzing periodic signals like ECG data, where you expect peaks to occur at regular intervals.

Read Python SciPy Minimize

Use Prominence to Find Significant Peaks

Prominence is a measure of how much a peak stands out relative to other nearby peaks. It’s one of the most powerful parameters for identifying meaningful peaks.

# Find peaks with minimum prominence of 0.5
peaks, properties = find_peaks(x, prominence=0.5)

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(x)
plt.plot(peaks, x[peaks], "x", color='red')
plt.title("Peak Detection with Prominence")
plt.xlabel("Sample Index")
plt.ylabel("Amplitude")
plt.grid(True)
plt.show()

# We can also visualize the prominences
plt.figure(figsize=(10, 6))
plt.plot(x)
plt.plot(peaks, x[peaks], "x", color='red')
plt.vlines(x=peaks, ymin=x[peaks] - properties["prominences"], ymax=x[peaks], color="red")
plt.title("Peaks with their Prominences")
plt.xlabel("Sample Index")
plt.ylabel("Amplitude")
plt.grid(True)
plt.show()

The prominence parameter is extremely useful for finding significant peaks in noisy data, as it helps filter out minor fluctuations.

Check out Python SciPy Freqz

Calculate Peak Width

Sometimes you need to know not just where peaks occur, but how wide they are. The width parameter helps with this:

# Find peaks with a specified width
peaks, properties = find_peaks(x, width=5)

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(x)
plt.plot(peaks, x[peaks], "x", color='red')
plt.hlines(y=properties["width_heights"], xmin=properties["left_ips"], xmax=properties["right_ips"], color="red")
plt.title("Peaks with their Widths")
plt.xlabel("Sample Index")
plt.ylabel("Amplitude")
plt.grid(True)
plt.show()

This is particularly useful when analyzing signals where the duration of a peak carries important information, such as in chromatography or spectroscopy.

Read Python SciPy Stats Multivariate_Normal

Find Peaks using Wavelet Transform

For more complex signals, SciPy offers the find_peaks_cwt method, which uses the continuous wavelet transform:

from scipy.signal import find_peaks_cwt

# Create a more complex signal
x = np.sin(np.linspace(0, 10, 1000)) + 0.5*np.sin(np.linspace(0, 100, 1000))

# Find peaks using CWT
peak_indices = find_peaks_cwt(x, np.arange(1, 10))

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(x)
plt.plot(peak_indices, x[peak_indices], "x", color='red')
plt.title("Peak Detection using Wavelet Transform")
plt.xlabel("Sample Index")
plt.ylabel("Amplitude")
plt.grid(True)
plt.show()

The wavelet transform approach is particularly useful for signals with varying frequency components, like audio signals or complex biological measurements.

Check out Python SciPy Stats Mode

Find Both Peaks and Valleys

Sometimes you need to find both peaks (maxima) and valleys (minima). You can use find_peaks for both by inverting your signal:

# Create a sample signal
x = np.sin(np.linspace(0, 10, 1000))

# Find peaks (maxima)
peaks, _ = find_peaks(x)

# Find valleys (minima)
valleys, _ = find_peaks(-x)  # Invert the signal to find valleys

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(x)
plt.plot(peaks, x[peaks], "x", color='red', label='Peaks')
plt.plot(valleys, x[valleys], "o", color='green', label='Valleys')
plt.title("Detection of Peaks and Valleys")
plt.xlabel("Sample Index")
plt.ylabel("Amplitude")
plt.legend()
plt.grid(True)
plt.show()

This technique is valuable when analyzing oscillating data where both the high and low points carry significant information, such as in stock market analysis.

Read Python SciPy Eigenvalues

Real-World Example: Heart Rate Analysis

Let’s apply what we’ve learned to a practical example. Imagine we have ECG data and want to detect heartbeats:

# Create a simulated ECG signal
t = np.linspace(0, 10, 1000)
ecg = np.sin(2*np.pi*t) * np.exp(-0.2*t) + np.sin(2*np.pi*2.5*t) * np.exp(-0.1*t) + 0.1*np.random.randn(len(t))

# Find R-peaks (the highest peaks in ECG)
r_peaks, _ = find_peaks(ecg, height=0.5, distance=50)

# Calculate heart rate (assuming data is sampled at 100Hz)
if len(r_peaks) > 1:
    # Calculate average time between peaks
    peak_times = r_peaks / 100  # Convert to seconds
    rr_intervals = np.diff(peak_times)
    avg_heart_rate = 60 / np.mean(rr_intervals)  # beats per minute
    print(f"Average heart rate: {avg_heart_rate:.2f} BPM")

# Plot the results
plt.figure(figsize=(12, 6))
plt.plot(t, ecg)
plt.plot(t[r_peaks], ecg[r_peaks], "x", color='red', markersize=10)
plt.title("ECG R-Peak Detection for Heart Rate Analysis")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.grid(True)
plt.show()

This example demonstrates how scipy.find_peaks can be applied to biomedical signal processing to extract meaningful health metrics from raw data.

Check out Python SciPy Kdtree

Practical Tips for Using Find Peaks

Based on my experience working with various datasets, here are some practical tips:

  1. Start with basic parameters: Begin with just the array and then gradually add constraints like height, distance, or prominence.
  2. Visualize your results: Always plot your data with the detected peaks to verify they make sense.
  3. Combine parameters: For complex signals, combine multiple parameters, like prominence and distance, for more accurate detection.
  4. Preprocess your data: Consider smoothing noisy signals before peak detection using filters from scipy.signal.
  5. Use properties output: The second return value from find_peaks contains valuable information about the detected peaks.

Find_peaks is an incredibly versatile function that can be adapted to a wide range of signal processing tasks. Whether you’re analyzing stock market data, processing scientific measurements, or working with biomedical signals, it provides a robust foundation for peak detection.

If you’re working with more complex signals, you might want to explore other SciPy signal processing functions that complement find_peaks. The combination of these tools makes Python a powerful environment for signal analysis.

You can also read other SciPy tutorials:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.