# How do I count the number of times my graph crosses two separate lines?

5 views (last 30 days)

Show older comments

I have this graph:

I want to count the number of times that the graph goes from y=-0.08 (the bottom line) and y=0.16 (the top line). If it goes up and down inbetween those two lines, I don't care. I just want it to count every time it hits -0.08 and goes back to 0.16. For example, in the graph below, count should equal 3 (1 between 18.5 and 19 seconds; 1 between 19.5 and 20 seconds; 1 between 20.5 and 21 seconds; and it shouldn't count the tiny maximum peak at about 19.75 because the graph hadn't yet reached the bottom line again)

(I've seen this done with just a minimum or just a maximum but I don't know how to get it to only count from the bottom line to the top line)

##### 1 Comment

Dyuman Joshi
on 2 Apr 2024

Edited: Dyuman Joshi
on 2 Apr 2024

Please share what you have attempted yet.

### Accepted Answer

Mathieu NOE
on 2 Apr 2024

hello

maybe this ?

the second plot shows the valid points (Ncounts = 4)

% dummy data

n = 5000;

x = 50*(0:n-1)/n;

y = -0.3*sin(x).*(1+ 0.75*cos(x/4))/2;

% counts signal crossing from negative (threshold1) to positive (threshold1)

% only consecutive negative to positive crossing points are valid

threshold1 = -0.08; %

threshold2 = 0.16; %

[t0_pos1,t0_neg1] = find_zc(x,y,threshold1);

[t0_pos2,t0_neg2] = find_zc(x,y,threshold2);

% plot all crossing points

figure(1)

plot(x,y,'b',x,threshold1*ones(size(x)),'--r',x,threshold2*ones(size(x)),'--g',...

t0_pos1,threshold1*ones(size(t0_pos1)),'dr',t0_pos2,threshold2*ones(size(t0_pos2)),'dg','markersize',12);grid on

title('Signal plot');

legend('signal','lower threshold crossing points','upper threshold crossing points');

xlabel('time (s)')

ylabel('Amplitude')

% keep only valid points

% n_top = numel(t0_pos2);

n_low = numel(t0_pos1);

Ncounts = 0;

for ck = 1:n_low

if ck <= n_low-1 % look for valid upper crossing points (first existing upper crossing point between 2 lower crossing points)

ind = find(t0_pos2>t0_pos1(ck) & t0_pos2<=t0_pos1(ck+1),1,'first');

else % maybe we also have a last upper crossing point after the last lower crossing point (must be counted as well)

ind = find(t0_pos2>t0_pos1(ck),1,'first');

end

if~isempty(ind)

Ncounts = Ncounts+1;

t0_pos1_valid(Ncounts) = t0_pos1(ck);

t0_pos2_valid(Ncounts) = t0_pos2(ind);

end

end

figure(2)

plot(x,y,'b',x,threshold1*ones(size(x)),'--r',x,threshold2*ones(size(x)),'--g',...

t0_pos1_valid,threshold1*ones(size(t0_pos1_valid)),'dr',t0_pos2_valid,threshold2*ones(size(t0_pos2_valid)),'dg','markersize',12);grid on

title('Signal plot');

legend('signal','lower threshold valid crossing points','upper threshold valid crossing points');

xlabel('time (s)')

ylabel('Amplitude')

Ncounts

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [ZxP,ZxN] = find_zc(x,y,threshold)

% put data in rows

x = x(:);

y = y(:);

% positive slope "zero" crossing detection, using linear interpolation

y = y - threshold;

zci = @(data) find(diff(sign(data))>0); %define function: returns indices of +ZCs

ix=zci(y); %find indices of + zero crossings of x

ZeroX = @(x0,y0,x1,y1) x0 - (y0.*(x0 - x1))./(y0 - y1); % Interpolated x value for Zero-Crossing

ZxP = ZeroX(x(ix),y(ix),x(ix+1),y(ix+1));

% negative slope "zero" crossing detection, using linear interpolation

zci = @(data) find(diff(sign(data))<0); %define function: returns indices of +ZCs

ix=zci(y); %find indices of + zero crossings of x

ZeroX = @(x0,y0,x1,y1) x0 - (y0.*(x0 - x1))./(y0 - y1); % Interpolated x value for Zero-Crossing

ZxN = ZeroX(x(ix),y(ix),x(ix+1),y(ix+1));

end

##### 5 Comments

### More Answers (1)

Jonas
on 2 Apr 2024

maybe too caomplicated, but this can work:

data=[1:10 9:-1:1 2:10 9:-1:1 2:10]; % row vector to not get problems with num2str later

lowThr=3;

highThr=6;

% remove data between those thr as those are not interesting

data(data>=lowThr & data<=highThr)=[];

% create 1 if it is under lowThr and 2 of it is bigger than highThr

asBin=(data<lowThr)*1 + (data>highThr)*2

% to string without whitespace

asStr=erase(num2str(asBin),' ')

% remove duplicates

asStr=regexprep(asStr,'1+','1')

asStr=regexprep(asStr,'2+','2')

% if you want to count pairs of "under threshold and then over threshold"

numel(strfind(asStr,'21'))

% or vice versa

numel(strfind(asStr,'12'))

##### 2 Comments

Jonas
on 3 Apr 2024

### See Also

### Categories

### Community Treasure Hunt

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

Start Hunting!