Finding specific peaks and valleys
17 次查看(过去 30 天)
显示 更早的评论
I have a periodic signal with 6 peaks and 6 valleys. I am able to find all 6 peaks and all 6 valleys using the code below:
% plot periodic signal
plot(angle,signal)
hold on;
% fit to avoid noisy oscillations and find 6 global peaks
f = fit(angle,signal,'sin9');
yfitted = feval(f,angle);
plot(angle,yfitted,'r')
% find peaks and corresponding angles
[ypk0,idx0] = findpeaks(yfitted);
peaks = signal(idx0);
max_angles = angle(idx0);
% invert fitted signal to find 6 global valleys and corresponding angles
yfittedinv = max(yfitted) - yfitted;
[ypk,idx] = findpeaks(yfittedinv);
valleys = signal(idx);
min_angles = angle(idx);
Furthermore, I am able to find the global minimum (i.e., the lowest valley) using this line:
% find the global minimum
minangle = min_angles(valleys == min(valleys));
Both the arrays "max_angles" and "min_angles" have 6 elements. The question is how to reduce the number of elements in the array "min_angles" from 6 to 3, where I will have only the global minimum and the 2 non-neighbor valleys. The attached pic should help. I am able to find the green circle, but I also need to find the 2 red circles. Note that the global valley (green circle) is not always in the middle. It can be the first element of the array "min_angles", or it can be the last one. In the picture below, it's number 4.

2 个评论
Image Analyst
2025-1-30
Make it easy for us to help you, not hard. Attach your variables "angle" and "signal" in a .mat or text file. That way we'll have something to work with and won't have to try to create data on our own.
save('answers.mat', 'angle', 'signal');
If you have any more questions, then attach your data and code to read it in with the paperclip icon after you read this:
采纳的回答
Star Strider
2025-1-30
编辑:Star Strider
2025-1-30
To find specific valleys, one option might be to use the MinPeakProminence value. The prominences are the tthird output returned by findpeaks, so you can look at those to see iif that option would work.
Another option is to get the peak values and use the mink (or maxk) function to return thee three lowest values (since that appears to be what the green circle and the red circles represent). Return both outputs from mink beecausee the second will be the index values of the minima (or maxima, depending on you you have the results returned), and you can use those indices with the returned values for the peaks and their locations to isolate the ones you want.
This is based on the figure you posted.
.
EDIT — (30 Jan 2025 at 21:33)
Example —
a = linspace(0,360).';
s = sin(2*pi*a/360*6)-sin(2*pi*a/720);
[vlys,vlocs] = findpeaks(-s)
[minpks, minpksidx] = mink(-vlys,3)
figure
plot(a, s)
hold on
plot(a(vlocs(minpksidx)), -vlys(minpksidx), 'rs')
hold off
grid
ylim([-2.5 1])
.
8 个评论
Star Strider
2025-2-1
I am still not certain what you want, since I am still uncertain of the criteria.
See if this works —
loaddata = readmatrix('testdata.csv');
angle = loaddata(:,1);
signal = loaddata(:,2);
[pks,plocs,pprm] = findpeaks(signal, MinPeakProminence=10);
[vys,vlocs,vprm] = findpeaks(-signal, MinPeakProminence=10);
[minvly,minidx] = min(-vys); % Minimum Valley & Associated Valley Index
idxrng = [max(1,(minidx-2)) minidx min((minidx+2),numel(vlocs))] % Valley Indices ±2 Positions From Minimum
Results = table(angle(vlocs(idxrng)), signal(vlocs(idxrng)), VariableNames=["Angle","Value"])
figure
plot(angle, signal, DisplayName='Signal')
hold on
plot(angle(plocs), pks, 'vg', DisplayName='Peaks')
plot(angle(vlocs), -vys, '^r', DisplayName='Valleys')
plot(angle(vlocs(idxrng)), signal(vlocs(idxrng)), 'ms', MarkerSize=12, DisplayName='Selected')
hold off
grid
xlabel('Angle (°)')
ylabel('Signal (mV)')
legend(Location='best')
The ‘idxrng’ calculation contains a ‘fail safe’ to prevent finding indices outside the allotted range.
.
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Descriptive Statistics 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!