Find peaks/valleys of a noisy signal

Illustration
Jasmin - 2020-12-28T12:56:41+00:00
Question: Find peaks/valleys of a noisy signal

I have this  signal which is noisy as well as it has too much data samples. When I try to find the peaks or valleys, it gives multiple peaks/valleys around the same point probably because the data is noisy and has too many samples. I did use the 'MinPeakDistance' and also tried using the 'MinPeakHeight' and also the 'Threshold' but all time I get many peaks's around a given time instant. In other words, I would want only one peak at the peak of the signal and one valley at the trough of the signal. I have the data attached to the post too. Thanks in advance.   It is just a two column data and I  plot the 2nd column wrt 1st one. I would prefer to measure valleys and I would actually need both.   [pks locs] = findpeaks(data_compact(:,2),'MinPeakHeight',0.992*max(data_compact(:,2)),'MinPeakDistance',5000e-3); % peaks data_inverted(:,1) = data_compact(:,1); data_inverted(:,2) = -data_compact(:,2); %[valley valleys_locs] = findpeaks(data_inverted(:,2),'MinPeakDistance',0.2e-3); % valleys

Expert Answer

Profile picture of John Williams John Williams answered . 2025-11-20

To address your challenge of finding a single peak and valley in a noisy signal, you can try using a smoothing technique to reduce noise before detecting peaks and valleys. Here's an approach using Python and the SciPy library:

  1. Smooth the Data: Use a moving average or a Savitzky-Golay filter to smooth the noisy signal.

  2. Find Peaks and Valleys: Use the find_peaks function from the scipy.signal module with appropriate parameters.

Here's an example of how to do this:

python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.signal import find_peaks, savgol_filter

# Load your data
data = pd.read_csv('path_to_your_data.csv', header=None)
x = data[0]
y = data[1]

# Smooth the data using Savitzky-Golay filter
window_size = 51  # Choose an appropriate window size
poly_order = 3  # Polynomial order
y_smooth = savgol_filter(y, window_size, poly_order)

# Find peaks
peaks, _ = find_peaks(y_smooth, distance=50)  # Adjust 'distance' as needed

# Find valleys (by finding peaks in the inverted signal)
valleys, _ = find_peaks(-y_smooth, distance=50)  # Adjust 'distance' as needed

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(x, y, label='Original Signal')
plt.plot(x, y_smooth, label='Smoothed Signal')
plt.plot(x[peaks], y_smooth[peaks], 'ro', label='Peaks')
plt.plot(x[valleys], y_smooth[valleys], 'go', label='Valleys')
plt.legend()
plt.xlabel('Time')
plt.ylabel('Signal')
plt.title('Peak and Valley Detection')
plt.show()

You can adjust the window_size, poly_order, and distance parameters to better suit your data. The window_size should be chosen based on the width of features in your signal, and distance should be set to avoid detecting multiple peaks/valleys around the same point.


Not satisfied with the answer ?? ASK NOW

Get a Free Consultation or a Sample Assignment Review!