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
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:
Smooth the Data: Use a moving average or a Savitzky-Golay filter to smooth the noisy signal.
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:
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.