version 1.0.0.0 (3.37 KB) by
Steffen Brueckner

Detect zero (or any other) level crossing of signals.

**Editor's Note:** This file was a File Exchange Pick of the Week

Detect the zero (or any other level) crossing of a given signal, either in discrete data points or using linear interpolation.

Steffen Brueckner (2021). crossing (https://www.mathworks.com/matlabcentral/fileexchange/2432-crossing), MATLAB Central File Exchange. Retrieved .

Created with
R2007a

Compatible with any release

**Inspired:**
Ringdown

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!Create scripts with code, output, and formatted text in a single executable document.

Conner HerndonBas-Jan ZandtThanks a lot! Like Krabbe commented, the addition can result in an error.

Weifumatlab 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 CiampoliniI used it with Pierre Mégevand fix. I am now trying Krabbe's fix. Will report issues if any occurs.

DavidgregaPls try:

load iddata1

crossing(z1.y)

If first element is about to cross zero, error's yielded. Pls fix.

Patrick KrabbeI 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);

big tedPerfect, and clearly documented. Many thanks!

NahidThis will do the job:

number_of_crossing_zero = nnz(diff(sign(input_array(find(input_array)))))

MonThanks

Raj SodhiNear 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);

===============

MatthiasHartmut 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 BPierre MégevandA 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 ArneNaty SExactly what i needed, Thanks!

Raj SodhiIf 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 ForsbergOne 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.

Claredoesn't seem to work

Index exceeds matrix dimensions.

Error in crossing (line 77)

t0 = t(ind);

Carlos MartinezIt doesn't work any more.

Patrick TamelliniGreat, worked ok for me.

Paulo EmmanuelDon'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 CuiM. A. HopcroftEric TFollowing generates error, same as Urs J error:

crossing([8 .1 -3 -5],[],1)

Nauman QureshiFirst LastHartmut WziontekNice 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);

René TruelsenExcellent. Just what I was looking for. A function to find the zero-crossings of my LoG filtered signal

Urs JHi

Search for zeros in a=[-1 1], and it will "crash" at line 99 because index is set to 0.

Abhinav JhaIs 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 ?

Islam Mohammedif 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.

Sergio GMIt worked for me! Thanks.

Howard FishmanFor 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);

Christian RothleitnerIn 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);

Alan CummingI 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).

Jonathan KelloggI 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.

Zach LewisI 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

Rajeeva KumarAndre Frotta MullerVery good!!!!

Thanks.

Mike Price