Find the highest unknown number of peak points in Matlab - matlab

I want to find the highest peak points in the below histogram. For example as it is seen in the figure, I should select 4 peak points, but I get this 4 points information after seeing the histogram, so I need to find it by coding. Is there any method or algorithm to solve this problem?
If I select manually I could solve the problem. However, I do not know the number of the highest peak points. Actually the main problem is determining a threshold.
[pks,locs] = findpeaks(difference)
[sortedX,sortingIndices] = sort(difference,'descend');
locsize=size(locs,2);
counter=1;
peak_order=[];
while counter<5
for j=1:locsize
if sortingIndices(counter)==locs(j)
peak_order(counter)=sortingIndices(counter);
counter=counter+1;
end
end
end
sorted_peak_order=sort(peak_order)enter code here

findpeaks has a series of options to refine your results. In your case, the option 'MinPeakProminence' should work; it thresholds according to the prominence of a peak to its neighbors.
[pks,locs] = findpeaks(difference,'MinPeakProminence',0.25*max(difference))

Related

Matlab findpeaks unable to detect peak

I have a 1d signal with a very clear peak, which I wish to characterise. For this, Matlab recommends the findpeak() function. I used it, but it could not detect any peaks.
Can anyone tell me why the peak detection fails, and how I could correct this? Is it because of the slight asymmetry, or because of its location close to the origin?
Here is the signal:
-0.749429547824983,-1.48893649456578,-3.69142404184161,-5.90518397007934,-8.94050442864937,-13.9397113416771,-18.6485000060921,-26.171050819591,-33.8321611238473,-42.6887187100784,-52.7848046259627,-64.0885716722416,-76.4819754427361,-89.7534943093904,-103.596636684011,-117.616848525362,-137.728485864984,-149.968644032202,-165.760526765682,-173.438446162355,-177.794367330021,-180.665504657482,-181.587837865151,-182.05669036563,-181.953081445756,-181.224964655595,-179.466956009378,-174.935326783301,-166.108729320377,-154.8188727578,-138.989450390713,-124.745660884327,-110.75406648731,-97.5101283485409,-85.3020579114654,-75.9579975036876,-67.4601854156705,-61.2940646311251,-55.6332658221936,-50.4524017554082,-45.7226429946525,-41.4134661940384,-37.4939178270878,-33.9335009233627,-30.7027744357005,-27.7737375478043,-25.120055867709,-22.7171735026633,-20.5423444708846,-18.1299037240041,-16.0034032566806,-13.4349709052746,-11.2814814601965,-9.22383728236694,-7.54259823223305,-6.16891326304915,-5.04643005083767,-4.12908680572436,-3.3792629187093,-2.76624567764036,-2.26496715909135,-1.85496794618472,-1.51954915870186,-1.24507971658957,-1.02043099016049,-0.836515683557349,-0.685911850401105,-0.562556362193813,-0.461494999843215,-0.378678691801432,-0.31079735465677,-0.255144373245673,-0.209506048358245,-0.172071392676599,-0.141358513015601,-0.116154515064569,-0.0954664351129079,-0.0784811657953865,-0.0645327193959676,-0.053075478741892,-0.0436623352584338,-0.035926816959731,-0.0295684746597058,-0.0243409295220307,-0.0200420949390602,-0.0165061752797916,-0.0135971170520871,-0.0112032475556222,-0.00923288465794644,-0.00761074093974044,-0.00627497778144994,-0.00517479134910001,-0.00426843397916662,-0.00352159205421904,-0.00290605583052415,-0.00239862841900826,-0.00198023071526613,-0.00163516691682862,-0.00135052167802519,-0.00111566519662662,-0.000881935744953948,-0.000697915251838727,-0.000524637598946218,-0.000394567839006708,-0.000296885161988861,-0.00020976002143167,-0.000148545955794115,-9.72008185405489e-05,-6.36690385791491e-05,-4.17477119966825e-05,-2.74018483759325e-05,-1.8003902287259e-05,-1.18410413188178e-05,-7.7955452552938e-06,-5.13728164003599e-06,-3.38881214609516e-06,-2.2376175188872e-06,-1.47892273125427e-06,-9.78415790827604e-07,-6.47913246914071e-07,-4.29460109665109e-07,-2.84930223745026e-07,-1.89217408323062e-07,-1.25773079886823e-07,-8.36787965589242e-08,-5.57238587861215e-08,-3.71416697587417e-08,-2.47783039314225e-08,-1.6544922828963e-08,-1.10567854116822e-08,-7.39503946153151e-09,-4.94938072790637e-09,-3.31402364108024e-09,-2.2188483621877e-09,-1.48377653147047e-09,-9.88495439963603e-10,-6.52325826840569e-10,-4.20789022022039e-10,-2.56587161450693e-10,-1.50808306057169e-10,-6.34502662515917e-11,-3.11362883724889e-11
and here is the x-data:
0.7,0.700231481481481,0.700462962962963,0.700925925925926,0.701388888888889,0.701851851851852,0.702777777777778,0.703472222222222,0.704166666666667,0.704861111111111,0.705555555555555,0.70625,0.706944444444444,0.707638888888889,0.708333333333333,0.709027777777778,0.709722222222222,0.711111111111111,0.711805555555555,0.7125,0.713194444444444,0.713541666666667,0.713888888888889,0.71412037037037,0.714351851851852,0.714814814814815,0.715277777777778,0.715740740740741,0.716666666666667,0.718055555555556,0.719097222222222,0.720138888888889,0.721180555555555,0.722222222222222,0.723263888888889,0.724305555555556,0.725,0.725694444444444,0.726388888888889,0.727083333333333,0.727777777777778,0.728472222222222,0.729166666666667,0.729861111111111,0.730555555555556,0.73125,0.731944444444444,0.732638888888889,0.733333333333333,0.734027777777778,0.735069444444444,0.736111111111111,0.7375,0.738888888888889,0.740277777777778,0.741666666666667,0.743055555555555,0.744444444444444,0.745833333333333,0.747222222222222,0.748611111111111,0.75,0.751388888888889,0.752777777777778,0.754166666666667,0.755555555555556,0.756944444444444,0.758333333333333,0.759722222222222,0.761111111111111,0.7625,0.763888888888889,0.765277777777778,0.766666666666667,0.768055555555555,0.769444444444444,0.770833333333333,0.772222222222222,0.773611111111111,0.775,0.776388888888889,0.777777777777778,0.779166666666667,0.780555555555555,0.781944444444444,0.783333333333333,0.784722222222222,0.786111111111111,0.7875,0.788888888888889,0.790277777777778,0.791666666666667,0.793055555555555,0.794444444444444,0.795833333333333,0.797222222222222,0.798611111111111,0.8,0.801388888888889,0.802777777777778,0.804166666666667,0.80625,0.808333333333333,0.810416666666667,0.8125,0.814583333333333,0.817708333333333,0.820833333333333,0.823958333333333,0.827083333333333,0.830208333333333,0.833333333333333,0.836458333333333,0.839583333333333,0.842708333333333,0.845833333333333,0.848958333333333,0.852083333333333,0.855208333333333,0.858333333333333,0.861458333333333,0.864583333333333,0.867708333333333,0.870833333333333,0.873958333333333,0.877083333333333,0.880208333333333,0.883333333333333,0.886458333333333,0.889583333333333,0.892708333333333,0.895833333333333,0.898958333333333,0.902083333333333,0.905208333333333,0.908333333333333,0.911458333333333,0.914583333333333,0.917708333333333,0.920833333333333,0.922916666666667,0.925
I copy-pasted them from a comma-delimited .txt file.
If you look at the help you can see:
PKS = findpeaks(Y) finds local peaks in the data vector Y. A local peak
is defined as a data sample which is either larger than the two
neighboring samples or is equal to Inf.
So by default it is looking for a positive peak, you can supply the -ve of the signal and it will find it.
I was able to find the peak by fitting the posted data to a three-parameter Extreme Value peak equation, "y = a * exp(-exp(-((x-b)/c))-((x-b)/c)+1.0)", with parameter b as the peak at approximately x = 0.714. Fitted parameters of a = -1.7877846561352214E+02, b = 7.1375869130522429E-01, and c = 6.4029302224962413E-03 yielded RMSE = 2.64 and R-squared = 0.997.

Find zero crossing points in a signal and plot them matlab

I have a signal 's' of voice of which you can see an extract here:
I would like to plot the zero crossing points in the same graph. I have tried with the following code:
zci = #(v) find(v(:).*circshift(v(:), [-1 0]) <= 0); % Returns Zero-Crossing Indices Of Argument Vector
zx = zci(s);
figure
set(gcf,'color','w')
plot(t,s)
hold on
plot(t(zx),s(zx),'o')
But it does not interpole the points in which the sign change, so the result is:
However, I'd like that the highlighted points were as near as possible to zero.
I hope someone can help me. Thanks you for your responses in advanced.
Try this?
w = 1;
crossPts=[];
for k=1:(length(s)-1)
if (s(k)*s(k+1)<0)
crossPts(w) = (t(k)+t(k+1))/2;
w = w + 1;
end
end
figure
set(gcf,'color','w')
plot(t,s)
hold on
plot(t, s)
plot(crossPts, zeros(length(crossPts)), 'o')
Important questions: what is the highest frequency conponent of the signal you are measuring? Can you remeasure this signal? What is your sampling rate? What is this analysis for? (Schoolwork or scholarly research). You may have quite a bit of trouble measuring the zeros of this function with any significance or accurracy because it looks like your waveform has a frequency greater than half of your sampling rate (greater than your Nyquist frequency). Upsampling/interpolating your entire waveform will allow you to find the zeros much more precisely (but with no greater degree of accurracy) but this is a huge no-no in the scientific community. While my method may not look super pretty, it's the most accurate method that doesn't make unsafe assumptions. If you just want it to look pretty, I would recommend interp1 and using the 'Spline' method. You can interpolate the whole waveform and then use the above answer to find more accurate zeros.
Also, you could calculate the zeros on the interpolated waveform and then display it on the raw data.
A remotely possible solution to improve your data;
If you're measuring a human voice, why not try filtering at the range of human speech? This should be fine mathematically and could possibly improve your waveform.

How to find the relative minimums of a vector (not the minimum value)

Let's suposse I have a vector of values whose representation is the following one:
The vector of data has 2000 elements and as you see, there is another vector with degrees between -180º and 180º. I'd like to find the indices of each minimum peak, but I don't know how to implement the algorithm.
In other cases, I set a threshold value (for example -75dBm) and considered a minimum any value under -75dBm, but in this case, there are peaks above -70dBm and I can't increase the threshold value since my measurements will be wrong.
I hope someone can help me. Thank you for your responses.
For data like this, your best bet is to smooth it and then use findpeaks.
For an example
%% parameters to adjsut
%smoothing window length
smthwin=50;
%minimum peak prominence
mpp=0.01;
%% create some test data
x=(1:1000)/1000;
y=sin(3*x-0.5).*sin(5*x).*sin(9*x-0.1).*sin(15*x-0.3)+rand(size(x))/10;
%% smooth and findpeaks
%smooth it
%here I use a median filter, but smooth() is a great function too with lots of options
ysmth=medfilt1(y,smthwin);
%use findpeaks on -y to find local minima
[pks,pks_loc]=findpeaks(-ysmth,'MinPeakProminence',mpp);
%the location of the local minima is
mins=x(pks_loc);
%%plot to check
figure
plot(x,y)
hold on
plot(mins,-pks,'o','LineWidth',2)

Measuring Distance Between Peaks

I have used the (findpeaks) function in Matlab, in order to find the locations and the value of the peaks in the signal.
findpeaks(X_Segments{1});
X_Segments contains the data, here is sample of the figure that I got
As shown in the figure, some of the peaks are very close to each other, therefore, I'd to filter out these peaks (remove them) in order to have Peaks in the signal at regular intervals.
If you pass the parameter MinPeakDistance into the findpeaks function you can set the minimum distance between peaks. In your case:
findpeaks(X_Segments{1}, 'MinPeakDistance', 10);
Alternatively, you may find the MinPeakProminence or threshold parameters useful. See the examples here.

MATLAB: count number of peaks

I have a graph like this and I want to determine the number of peaks. Since it's a wave function the whole graph has many peaks that is why I was unsuccefull in finding the number of peaks using functions such as findpeaks for the graph below it returns a number of peaks around 3000 whereas I want to have the number 7.
My idea was to do a for or while loop that counts the number of instances where the average is higher than 0.5. So ultimately I want a function that iterates in segments over the graph returns the number of peaks and the range of y index values for which this peak occurs (I think the best way to do this would to save them to a zeros matrix).
link of file data: https://www.dropbox.com/s/vv8vqv28mqzfr9l/Example_data.mat?dl=0
Do you mean you are trying to count the 'on' parts of your data?
You're on the right track using findpeaks. If you scroll to the bottom of the documentation you'll see that you can actually tweak the routine in various ways, for example specifying the minimum distance between peaks, or the minimum difference between a point and its neighbour before it is considered a peak.
By defining the minimum distance between peaks, I detected the following 7 peaks. Code is included below. Alternatively you can play around with the other parameters you can pass into findpeaks.
The only other thing to note is that I took the absolute value of your data.
load('Example_data.mat')
indx = 1:numel(number11);
[pks, locs] = findpeaks(abs(number11), indx, 'MinPeakDistance', 0.25e4);
hold on
plot(number11)
plot(locs,pks, 'rx')
disp(numel(pks))