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

조회 수: 16 (최근 30일)
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)

채택된 답변

Mathieu NOE
Mathieu NOE 2024년 4월 2일
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
Ncounts = 4
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
Annelise
Annelise 2024년 4월 3일
Nevermind, I didn't see the function definition at the end. This works, thank you so much!

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Jonas
Jonas 2024년 4월 2일
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
asBin = 1x26
1 1 2 2 2 2 2 2 2 1 1 1 2 2 2 2 2 2 2 1 1 1 2 2 2 2
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% to string without whitespace
asStr=erase(num2str(asBin),' ')
asStr = '11222222211122222221112222'
% remove duplicates
asStr=regexprep(asStr,'1+','1')
asStr = '122222221222222212222'
asStr=regexprep(asStr,'2+','2')
asStr = '121212'
% if you want to count pairs of "under threshold and then over threshold"
numel(strfind(asStr,'21'))
ans = 2
% or vice versa
numel(strfind(asStr,'12'))
ans = 3
  댓글 수: 2
Annelise
Annelise 2024년 4월 3일
My data is imported from an excel spreadsheet, with an x and y input. I like the way you solved this, I don't see how I would apply it to the formatting of my data.
Jonas
Jonas 2024년 4월 3일
the question is if you also want to know the location at which the crosses appear. if you are only interested in the number of times it crosses, then you dont need your x data, you can just read your y data (e.g. readmatrix) from the excel sheet

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Live Scripts and Functions에 대해 자세히 알아보기

제품


릴리스

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by