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.
Related
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.
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 have an interference fringe pattern. I applied Fourier transform on it which gave an image with few very sharp peaks corresponding to each spatial frequency. My question is that is there any way(algorithm) to detect coordinates(pixel value) corresponding to these intense peaks?
Please note that there are more than one peaks(but not many) with different magnitudes.
You can use the built-in findpeaks, for example:
[pks,locs] = findpeaks(data)
returns local maxima or peaks, pks, in the input data, with the indices of the local peaks locs. The input data requires a row or column vector with real-valued elements with a minimum length of three. findpeaks compares each element of data to its neighboring values. If an element of data is larger than both of its neighbors or equals Inf, the element is a local peak. If there are no local maxima, pks will be an empty vector.
To set a threshold use any of the following handles: 'MINPEAKHEIGHT' , 'MINPEAKDISTANCE', or , 'THRESHOLD'
for example:
[pks,locs] = findpeaks(data,'MINPEAKHEIGHT',10)
I am having a samll problem while converting a spectrum to a time series. I have read many article sand I htink I am applying the right procedure but I do not get the right results. Could you help to find the error?
I have a time series like:
When I compute the spectrum I do:
%number of points
nPoints=length(timeSeries);
%time interval
dt=time(2)-time(1);
%Fast Fourier transform
p=abs(fft(timeSeries))./(nPoints/2);
%power of positive frequencies
spectrum=p(1:(nPoints/2)).^2;
%frequency
dfFFT=1/tDur;
frequency=(1:nPoints)*dfFFT;
frequency=frequency(1:(nPoints)/2);
%plot spectrum
semilogy(frequency,spectrum); grid on;
xlabel('Frequency [Hz]');
ylabel('Power Spectrum [N*m]^2/[Hz]');
title('SPD load signal');
And I obtain:
I think the spectrum is well computed. However now I need to go back and obtain a time series from this spectrum and I do:
df=frequency(2)-frequency(1);
ap = sqrt(2.*spectrum*df)';
%random number form -pi to pi
epsilon=-pi + 2*pi*rand(1,length(ap));
%transform to time series
randomSeries=length(time).*real(ifft(pad(ap.*exp(epsilon.*i.*2.*pi),length(time))));
%Add the mean value
randomSeries=randomSeries+mean(timeSeries);
However, the plot looks like:
Where it is one order of magnitude lower than the original serie.
Any recommendation?
There are (at least) two things going on here. The first is that you are throwing away information, and then substituting random numbers for that information.
The FFT of a real sequence is a sequence of complex numbers consisting of a real and imaginary part. Converting those numbers to polar form gives you magnitude and phase angle. You are capturing the magnitude part with p=aps(fft(...)), but you are not capturing the phase angle (which would involve atan2(...)). You are then making up random numbers (epsilon=...) and using those to replace the original numbers when you reconstruct your time-series. Also, as the FFT of a real sequence has a particular symmetry, substituting random numbers for the phase angle destroys that symmetry, which means that the IFFT will in general no longer be a real sequence, but a sequence of complex numbers - and again, you're only looking at the real portion of the IFFT, so you're throwing away information again. If this is an audio signal, the results may sound somewhat like the original (or they may be completely different), but the waveform definitely won't match...
The second issue is that in many implementations, ifft(fft(...)) will scale the result by the number of points in the signal. There are several different ways to avoid that, with differing results, but sometimes more attractive in different scenarios, depending on what you are trying to do. You can either scale the fft() result before you do the ifft(), or scale the ifft() result at the end, or in some cases, I've even seen both being scaled by a factor of sqrt(N) - doing it twice has the end result of scaling the final result by N, but it is a bit less efficient since you do the scaling twice...
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.