Identify point in signal where it moves away from zero

22 views (last 30 days)
pkll201
pkll201 on 9 Apr 2024 at 11:31
Answered: Star Strider on 9 Apr 2024 at 13:43
I have some data here, there are three columns. I am looking to identify the points (as marked on the graph with arrows) where the signal essentially goes away from and goes back to zero. I tried to apply a threshold but I wan't sure about how to do this with three columns of data. The signal also keeps crossing the 0 so my code kept identifying every point where this crosses. I'm not too sure how else to approach this task, so it would be great if anyone has any ideas about how I should approach this! I have attached some sample data.

Answers (1)

Star Strider
Star Strider on 9 Apr 2024 at 13:43
Your signals are difficult to work with. That there are several together makes this more challenging than it might otherwise be.
One approach is to calculate the envelope function for the maxima of the arrays, and then use it to define where the signal approaches zero. That works reasonably well on the first data set, however the code may need a bit of tweaking for the second data set. The approach is then to find the index locations where the signal is near zero (‘Lv1’), and then find the two closest locations to a specific peak (‘Lvmax’). That is done by first defining the ‘loc’ values, and then the relative index (‘relidx’) values with respect to each peak. I did not filter your data, although that might have made your signals easier to work with.
load('sampledata')
% whos
Fs{1} = 1;
SD{1} = fillmissing(sampledata1, 'linear');
t{1} = linspace(0, size(SD{1},1)-1, size(SD{1},1)).'/Fs{1};
Fs{2} = 1;
SD{2} = fillmissing(sampledata2, 'linear');
t{2} = linspace(0, size(SD{2},1)-1, size(SD{2},1)).'/Fs{2};
envwnd = 5;
for k = 1:numel(SD)
[envu, envd] = envelope(max(SD{k},[],2), envwnd, 'peak');
Lv1 = (envu > 0) & (envu < 1);
NumChanges = nnz(Lv1)
Lvmax = islocalmax(envu, 'MinProminence',30);
NumPks = nnz(Lvmax)
Nv1 = find(Lv1);
Nvmax = find(Lvmax);
relidx = {};
for k2 = 1:numel(Nvmax)
loc{k2} = mink(abs(Nvmax(k2)-Nv1),2);
relidx{k2} = Nvmax(k2)+(loc{k2}).*[-1; 1];
end
% relidx{:}
figure
plot(t{k}, SD{k})
hold on
plot(t{k}, envu, '-r')
plot(t{k}(Lv1), envu(Lv1), 'rs')
plot(t{k}(Lvmax), envu(Lvmax), 'vg')
for k2 = 1:numel(Nvmax)
plot(relidx{k2}, zeros(size(relidx{k2})), 'ks', 'MarkerFaceColor','k')
end
hold off
grid
xline(reshape(cell2mat(relidx), [], 1), '-k')
end
NumChanges = 235
NumPks = 10
NumChanges = 163
NumPks = 6
This works reasonably well, however you will likely want to tweak it to get the result you want. (It will at least get you started.) A suitably-designed lowpass filter can substitute for the envelope call if you want to experiment with that.
.

Products


Release

R2023b

Community Treasure Hunt

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

Start Hunting!