Copyright (c) 2016, Steffen Brueckner
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Bas-Jan Zandt (view profile)
Thanks a lot! Like Krabbe commented, the addition can result in an error.
Weifu (view profile)
matlab should provide this function natively.
it works perfect on me :) thanks.
can change error(nargchk(1,4,nargin)); in line 35 to simply narginchk(1,4); to avoid the obselete warning.
Lorenzo Ciampolini (view profile)
I used it with Pierre Mégevand fix. I am now trying Krabbe's fix. Will report issues if any occurs.
Giurak (view profile)
grega (view profile)
Pls try:
load iddata1
crossing(z1.y)
If first element is about to cross zero, error's yielded. Pls fix.
Patrick Krabbe (view profile)
I really like this function and use it often.
The addition (starting from line 96) does not check for index bounds. THIS IS A BUG AND SHOULD BE FIXED.
You can of course fix it locally, I did it this way:
lower_ind = ind-1;
lower_ind(lower_ind < 1) = 1;
upper_ind = ind+1;
upper_ind(upper_ind > numel(S)) = numel(S);
[~,II] = min(abs([S(lower_ind) ; S(ind) ; S(upper_ind)]),[],1);
ind2 = ind + (II-2); %update indices
ind2(ind2 < 1) = 1;
ind2(ind2 > numel(S)) = numel(S);
t0close = t(ind2);
s0close = S(ind2);
Robert Stead (view profile)
Perfect, and clearly documented. Many thanks!
Nahid (view profile)
This will do the job:
number_of_crossing_zero = nnz(diff(sign(input_array(find(input_array)))))
Mon (view profile)
Thanks
Raj Sodhi (view profile)
Near the end, where it calculates closest points, I used the code:
===============
len = length(t) ;
[CC,II] = min(abs([S(max(ind-1,1)) ; S(ind) ; S(min(ind+1,len))]),[],1);
ind2 = max(ind + (II-2),1); %update indices
t0close = t(ind2);
s0close = S(ind2);
===============
Matthias (view profile)
Hartmut Wziontek has a nice fix for the problem with the endpoints in the program already, but just in case.
instead of
! [CC,II] = min(abs([S(ind(ind0)-1) ; S(ind(ind0)) ; S(ind(ind0)+1)]),[],1);
you can also do
! [CC,II] = min(abs([S(ind-ind0) ; S(ind) ; S(ind+ind0)]),[],1);
But it's pretty much the same I guess.
Mike B (view profile)
Pierre Mégevand (view profile)
A quick and dirty workaround for the error thrown by the function if the first zero crossing happens between samples 1 and 2 (cf. error message below) is to comment out the last 5 lines of the function (99:102). The first outputs of the function (ind, t0 and s0) remain unaffected.
---
??? Subscript indices must either be real positive integers or logicals.
Error in ==> crossing at 99
[CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
Tor Arne (view profile)
Naty S (view profile)
Exactly what i needed, Thanks!
Raj Sodhi (view profile)
If the sign change of S happens between index 1 and index 2, the code breaks, because S(ind-1) refers to S(0), which Matlab doesn't like.
Daniel Forsberg (view profile)
One of the last lines:
[CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
doesn't work if you have a zero-crossing between indices 1 and 2.
Clare (view profile)
doesn't seem to work
Index exceeds matrix dimensions.
Error in crossing (line 77)
t0 = t(ind);
Carlos Martinez (view profile)
It doesn't work any more.
Patrick Tamellini (view profile)
Great, worked ok for me.
Paulo Emmanuel (view profile)
Don't know what to do. I'm kinda new at this.
??? Subscript indices must either be real positive integers or logicals.
Error in ==> crossing at 99
[CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
Error in ==> AudioComp at 38
indexLeftZeroCross = crossing(leftFilteredData);
Yan Cui (view profile)
M. A. Hopcroft (view profile)
Eric T (view profile)
Following generates error, same as Urs J error:
crossing([8 .1 -3 -5],[],1)
Nauman Qureshi (view profile)
First Last (view profile)
Nice source, saved some time for me.
However, I'd suggest to following patch to avoid indexes out of range:
*** crossing.m.orig Tue Aug 26 07:41:32 2008
--- crossing.m Tue Aug 26 13:38:27 2008
*************** end
*** 96,103 ****
% Addition:
% Some people like to get the data points closest to the zero crossing,
% so we return these as well
! [CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
! ind2 = ind + (II-2); %update indices
t0close = t(ind2);
! s0close = S(ind2);
\ No newline at end of file
--- 96,108 ----
% Addition:
% Some people like to get the data points closest to the zero crossing,
% so we return these as well
! % --- hwz 2008-08-26
! % make it work for data starting/ending with a zero crossing!
! ind0 = find(ind > 1 & ind < length(S));
! [CC,II] = min(abs([S(ind(ind0)-1) ; S(ind(ind0)) ; S(ind(ind0)+1)]),[],1);
! II = ind0(II);
! ind2 = ind;
! ind2(ind0) = ind2(ind0) + (II-2); %update indices
t0close = t(ind2);
! s0close = S(ind2);
Excellent. Just what I was looking for. A function to find the zero-crossings of my LoG filtered signal
Hi
Search for zeros in a=[-1 1], and it will "crash" at line 99 because index is set to 0.
Is zero crossing, by definition, supposed to return all the indices at which the value of signal stays zero continually, or just the point at which zero is reached ? For eg if
a = [1 2 -1 0 0 0 1]
then should the return indices be
ind = [2 4 5 6],
or only
ind = [2 4].
Doesn't zero crossings mean the points at which zero is crossed ?
if you need the number of crossing, NC.
NC = length(ind1) + length(ind0);
this is because if the signal cross zero exactly at the sample time it will not be calculated in ind1.
It worked for me! Thanks.
For data far from 1, the eps test me not either not pass when you want to interpolate or pass when you shouldn't,
Change line 45 to
if abs(S(ind(ii))) > eps(S(ind(ii)))
Also change line 28 to
if nargin < 3 || isempty(level)
The condition of a peak (not a crossing) at exactly zero as described by Christian Rothleitner can be handled with the following
[t0, indx] = unique(t0);
ind = ind(indx);
In general a good algorithm. Just an improvement: First search for exact zeros. Otherwise you will count twice. Here the extension:
ind0 = find(S==0); %find amplitudes which are exactly zero
S1 = S(1:end-1) .* S(2:end);
ind1 = find(S1< 0);
ind_all_unsort = [ind0 ind1];
ind = sort(ind_all_unsort);%sorts values in ascending order
t0 = t(ind);
I found the same as Zach Lewis, it doesn't really find the correct point (it's one point off), and the interpolation doesn't work either (not only because the function specification line is wrong, either).
I found that if you wanted it to linearly interpolate between the t points that you give it, you need to go through the code and everywhere you see par.interpolation you need to change to just par or it breaks on the 'linear' string that put in. Otherwise works well for me.
I found that with discrete data, it can be off 1 data point to the actual closest value (closest to 0). I've added this as a check
[CC,II] = min(abs([S(ind-1) S(ind) S(ind+1)]),[],2); %find closest value to zero around crossing
ind = ind+(II-2); %update indices
Very good!!!!
Thanks.