Azzera filtri
Azzera filtri

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

34 visualizzazioni (ultimi 30 giorni)
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;
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;
% plot
hold on
legend('original signal','modified signal','peaks')

Risposta accettata

Mathieu NOE
Mathieu NOE il 23 Giu 2022
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;
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;
% 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 Commenti
Ganesh Naik
Ganesh Naik il 23 Giu 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

Accedi per commentare.

Più risposte (0)




Community Treasure Hunt

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

Start Hunting!

Translated by