I have a graph with five major peaks. I'd like to find the position and value of the first peak (the one furthest to the right). I have more than 100 different plots of this and the peak grows and shrinks in size in the various plots, and will need to use a for loop. I'm just stuck on determining the x and y values to a large number of significant figures using Matlab code.
Here's one of the many plots:
If you know for sure you're always gonna have 5 peaks I think the FileExchange function extrema will be very helpful, see here.
This will return you the maxima (and minima if needed) in descending order, so the first elements of output zmax and imax are respectively the maximal value and its index, their second elements are the second maximum value and its index and so on.
In the case if the peak you need is always the smallest of the five you'll just need zmax(5) and imax(5) to determine the 5th biggest maximum.
If you have access to Signal Processing Toolbox, findpeaks is the function you are looking for. It can be invoked using different options including number of peaks, which can be helpful when that information is available.
Related
Is the Matlab code available anywhere?
I'm trying to understand what exactly does it do. As I understood, it divides the data into segments with length tau (when tau increases each time) and then averages the data within each segment. After that, it compares the value attained from successive segments.
Am I correct in my understanding?
Thanks in advance!
You can view the code by typing edit allanvar into the command window.
Of course, this assumes you've already downloaded the associated toolbox.
I tried the same approach, but was also UNable to open the allanvar.p file. Despite the documentation I've found, if I use simple white noise and run allanvar on it, when I plot sqrt(this output), I get a line with a slope of -1/2 on a log-log scale (one order of magnitude drop in ADEV for two orders of magnitude increase in averaging interval value). A simple program to compute the OVERLAPPING Allan variance yields a -1/1 slope. Thus I am suspicious that the allanvar function does not compute the overlapping version!
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))
I am trying to take the derivative of the a spectrum with 125 bands using the following lines:
dW=diff(wavelength);
dR=diff(data);
df=dR./dW;
problem is in the next step i want to compare it with original spectrum numerically and also visually by plotting, but the size of df is 124 however my original wavelength is 125. Question is do i have to remove the first or the last band? however the output of some spectral analysis software is not changing the size. taking the average of bands also does not work, it make the graph to show crazy behavior.
diff is basically:
Y = [X(2)-X(1) X(3)-X(2) ... X(m)-X(m-1)]
which means it has to be one shorter than your input (you can't subtract something from nothing, right?).
What you have to do of course depends on what you want to do, but the least "meaning-altering" approach (kind of keeping causality with respect to sampling times) would be to prepend your dW and dR with a single arbitrary value.
By the way, your ratio df=dR./dW might have a lot of NaNs if dW has zeros (which happens as soon as two consecutive data values are the same).
I am solving a funcion which uses the moving average filter to remove noise. How can I determine index and value of first and second negative peak after I apply the filter to input data?
Use findpeaks on the negative of your data, then extract the first two elements to extract the first and second indices of where the negative peaks are located. Supposing your signal was stored in f, you would simply do:
[peaks, locs] = findpeaks(-f);
p = peaks(1:2);
loc = locs(1:2);
findpeaks works by finding local maxima. If you want to find local minima (i.e. negative peaks), you would apply findpeaks to the negative of your signal so that the local minima become local maxima, then apply the same algorithm. loc would contain the first two locations of where the negative peaks are, while p will determine those negative peak amplitudes.
However, you'll probably need to play around with the input parameters to findpeaks, instead of using the default ones to suit your data, but this should be enough to get you started.
Sidenote
If you don't have access to findpeaks, take a look at this post that I wrote to find peaks for FFT data. The data is different, but the overall logic is the same. However, this finds all peaks - both local maxima and minima. If you just want to find the minima, simply look at the negative of the signal rather than the absolute value.
I have a variable of equidistant values (suppose values=0:1e-3:1). I want to get the value and its correspondent index from values which is closest to a uniformly random value (suppose x=rand).
I could do [value,vIdx]=min(abs(values-x)), which would be the simplest minimization I could do. Unfortunately the min function won't take advantage from one property from the data, that is to be convex. I don't need to search all indexes, because as soon as find an index that is no more lesser than the previous I've found the global minimum. Said that, I don't want to substitute the matlab min function for a loop that would be slower depending on how distant it is from the value I will start. There are many methods that could be used, as the golden section, but I am not sure if using matlab fmincon would be faster than the min method.
Does anyone have any hints/ideas how to get the required value faster than using the described min method? I'll check the time performance when I have time, but if someone knows a good answer a priori, please let me know.
Possible Application: Snap to nearest graphic data
Since your points are equidistant you can use the value x to find the index:
vIdx = 1+round(x*(numel(values)-1));
The idea is that you are dividing the interval [0, 1] into numel(values)-1 equally sized intervals. Now by multiplying x by that number you map the interval to [0, numel(values)-1] where your points are mapped to integer values. Now using round you get the closest one and by adding 1 you get the one-based index that MATLAB requires.