Find flat regions in a signal above origin (time series data)

24 views (last 30 days)
Hi all, I would like to detect flat regions in a time series data above the origin. For your reference I have attached a figure and highlighted the region of interest in green color. I have also included the sample data for the same.
I have tried the following code and got the below figure, where it identifes too many flat regions and I dont know how to adjust it to get the above results. Any help in this regard is highly appreciated.
load data.mat;
x=1:numel(data);
y=data;
z = y;
thresh = 0.05; % height threshold
% find peaks
[pks,locs] = findpeaks(z,'MinPeakProminence',thresh);
% remove signal noise between peaks
for ii = 1:length(locs)-1
zz = z(locs(ii)+1:locs(ii+1)-1);
zz(abs(zz) < thresh) = 0;
z(locs(ii)+1:locs(ii+1)-1) = zz;
end
% plot
plot(x,y);
hold on
plot(x,z);
plot(x(locs),pks,'og');
legend('original signal','modified signal','peaks')

Accepted Answer

Mathieu NOE
Mathieu NOE on 23 Jun 2022
hello
IMHO, you don't need the peaks code (and the for loop) to make the low amplitude signals to zero
you can do it directly on the raw signal
then I added a new portion of code to detect the flat sections that are longer than min_contiguous_samples contiguous samples
so you can also discard if needed the short ones
see the demo below :
load data.mat;
x=1:numel(data);
y=data;
z = y;
thresh = 0.05; % height threshold
%% your for loop simplified :
ind = abs(z) < thresh; % NB we need ind in the new code below
z(ind) = 0;
%% new code
min_contiguous_samples = 300; % select segments only if they are at least this length => detect signal = 1
detect_signal = zeros(size(x))+0.5; % initialisation
% now define start en end point of segments above threshold
%%%%%%%%%%
% This locates the beginning /ending points of data groups
D = diff([0;ind;0]);
begin = find(D == 1);
ends = find(D == -1) - 1;
%%%%%%%%%%
length_ind = ends - begin;
ind2= length_ind>min_contiguous_samples; % check if their length is valid (above min_contiguous_samples value)
begin = begin(ind2); % selected points
ends = ends(ind2); % selected points
x2 = x(ind);
y2 = y(ind);
% define the begin / ending x, y values of raw data
x2_begin = x(begin);
y_begin = interp1(x,y,x2_begin);
x2_ends = x(ends);
y_ends = interp1(x,y,x2_ends);
for ci = 1:length(begin)
ind = (x>=x2_begin(ci) & x<=x2_ends(ci));
detect_signal(ind) = 1;
end
% plot
plot(x,y,x,z,x,detect_signal);xlim([2 2.3]*1e5);ylim([-1.5 1.5]);
legend('original signal','modified signal','flat sections detected')
  4 Comments
Ganesh Naik
Ganesh Naik on 23 Jun 2022
Dear Mahtieu, thanks for the answer, yes I can create a vector using x2_begin and x2_ends data. I will also adjust the min_contiguous_samples as per my requirements.
Thanks and regards

Sign in to comment.

More Answers (0)

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!