MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn moreOpportunities for recent engineering grads.

Apply Today
Asked by Valentin on 23 Jul 2013

Hello everyone

My goal is to find the maximums/minimums between two zeros and when it occurs for some velocity data that are in the form of a column vector.

I tried to find where are zeros upward, find where are zeros downward, and then to find the maximum/minimum in between.

The problem is that my code does not work and I do not understand why. I'm pretty sure I must not be far for the good answer.

How can I find the maximum of U between an upward going and a downward going zero and the minimum of U between a downward going and an upward going zero ?

My code is:

indx=find(U(1:end-1,1).*U(2:end,1) < 0);

new_U=zeros(length(indx),1);

for k=1:length(indx)

new_U(k,1)=max(U(indx(k))):U(indx(k+1));

end

But then I have a message error : ??? Subscripted assignment dimension mismatch.

Thank you very much in advance for your help

*No products are associated with this question.*

Answer by dpb on 23 Jul 2013

Edited by dpb on 24 Jul 2013

Accepted answer

OK, I can't seem to find a utility I had that does basically what you were/are looking for that I thought was around but here's a straightahead implementation using the above idea of diff()==2...

function pks = peaksbetween(x) % peaks from column vector x between zero crossings

ix=find(abs([0; diff(sign(x))])==2); % zero crossing loc's pks=zeros(length(ix)-1); % one less peak than x'ings for i=1:length(ix)-1 sx=x(ix(i):ix(i+1)-1); % subvector between x'ings [~,ipk]=max(abs(sx)); % peak location in subvector pks(i)=sx(ipk); % and signed max/min value end

To return the locations in the original vector means unwrapping the local location to the global--I left as "exercise for the student"... :)

If I can find the vectorized version I'll post it--I know it's around but this is a new install and it must not have gotten over from the utilities on the previous release or I put it somewhere other than I recall--altho *which* didn't find it so it's not on path... :(

Valentin on 24 Jul 2013

Thank you very much for your answer, it works really well. I knew little about diff()==2 before and I'm going to investigate this more. Regarding the vectorized version, I should be able to extract the first column of the matrix to turn it into a vector if you can't find it. I'll sort out how to return locations. Thank you again

dpb on 24 Jul 2013

*I knew little about diff()==2 before...*

You have to think about ways to find out what it is you're looking for to come up w/ such--in this case it's starts w/ realizing that you don't need the magnitude only the sign to determine the zero-crossing point and that then when the time vector is turned into simply the sign of the result that only when it changes is there any difference between adjacent values. The ==2 is simply owing to that being the difference between 1 and -1. To keep the index into the original vector at the same point one then just prepends a 0 to the difference vector.

For the routine to handle arrays you have to add the logic to handle the second dimension--it's doable but takes some pre-work to check on sizes and then the addressing and didn't figure worth confusing the logic of the algorithm w/ the details...I've forgotten exactly how I did implement it originally; it's been a number of years and I've not done much signal processing in last almost 15 yr since returned to family farm... :)

Answer by dpb on 27 Jul 2013

Updated version that also returns locations in original vector. I did for simplicity restrict the input to a column vector; just add logic to ensure correct orientation of the pieces internally if want to handle either...or just brute-force a row vector to a column vector internally and then return the same orientation as the input--that's actually probably the better idea but will leave as "exercise for the student" to choose/implement if wish.

function [pks, ipks] = peaksbetween(x) % peaks and locations from vector x between zero crossings and location

if size(x,1)==1, error('X must be a column vector'), end if numel(x)~=length(x),error('X must be a column vector'), end

ix=find(abs(diff(sign(x)))==2)+1; % zero crossing loc's L=length(ix)-1; % one less peak than x'ings ipk=zeros(L,1); for i=1:length(ix)-1 sx=x(ix(i):ix(i+1)-1); % subvector between x'ings [~,ipk(i)]=max(abs(sx)); % peak location in subvector end ipks=ix(1:end-1)+ipk-1; % max loc in original vector pks=x(ipks); % and signed max/min value end

dpb on 27 Jul 2013

One more variant...I'm still learning about accumarray and friends... :)

Using a local function to return the indices from max() then accumarray to remove the explicit loop. Too bad there's no syntax for returning alternate return values only.

function [pks, ipks] = peaksbetween(x) % peaks and locations from vector x between zero crossings and location

if size(x,1)==1, error('X must be a column vector'), end if numel(x)~=length(x),error('X must be a column vector'), end

ix=find(abs(diff(sign(x)))==2)+1; % zero crossing loc's L=length(ix)-1; % one less peak than x'ings ipk=accumarray([1:L]',[1:L]',[], @(i) imax(abs(x(ix(i):ix(i+1)-1))) ); ipks=ix(1:L)+ipk-1; % max loc in original vector pks=x(ipks); % and signed max/min value end

function idx=imax(x) % Return max() indices as first argument

[~,idx]=max(x); end

## 2 Comments

Direct link to this comment:http://www.mathworks.com/matlabcentral/answers/82941#comment_161227

Give a short example

Direct link to this comment:http://www.mathworks.com/matlabcentral/answers/82941#comment_161238

error : ??? Subscripted assignment dimension mismatch.Yes, there's no guarantee the number of elements from one set of indices is the same length as the next. If you want to save these subvectors then you'll have to use a cell array to handle the varying lengths.

Another way to find zero crossings is to look at

There are also a number of peak-finding routines on the FEX or findpeaks() in the Signal Processing Toolbox (altho iirc it doesn't isolate on the zero crossing intervals)