How to segment data using overlapping window

Hello, I have an ECG data of 20mins length (2x307200). I want to apply a 20 sec window(5120) with an overlap of 64samples. I want 20 sec segments so i can extract features from it. I tried to write a loop for window but it doesn't give me right answer. Can somebody help me.
ECG_data=[time; ECG];
N_max=length(ECG_data);
n_window=5120;
overlap_win=64;
count=1;
for n_start = 1:overlap_win:(N_max-n_window)
New_data(count,:) = ECG_data(n_start_1:(n_start+ n_window));
do something..
mean(count,:)=mean(new_data);
count=count+1;
end
The number of samples in each window is limited to 4720 sample(thats 18 sec) even though i need 20sec(5120). What am I doing wrong here? it something to do with the termination of window?? Also how can i retain the time information after applying window?

 Respuesta aceptada

Guillaume
Guillaume el 6 de Oct. de 2016
Editada: Guillaume el 6 de Oct. de 2016
Something that's really not clear is that your ECG_data has two rows, yet within your loop you're using linear indexing, which is not consistent. The end result, when n_start is 1 is that New_data(1, :) is [time(1), ECG(1), time(2), ECG(2), ...].
Assuming you only want the second row (ECG) of ECG_data in new_data, a very simple way to create it in one go, without a loop is with:
Matlab R2016b or later only:
new_data = ECG((0:64:307200)' + (1:5120));
Any version of matlab:
new_data = ECG(bsxfun(@plus, (0:64:307200)', 1:5120));
You can do the same with time if needed

8 comentarios

mahrukh jamil
mahrukh jamil el 7 de Oct. de 2016
Hello, Thank you for your answer. how ever this doesn't apply rightly to my case. I am not really sure about how the bsxfun works. i will get back to you shortly after i have enough information about it. but to the code you gave me totally distorted the signal.
one more question. what do you mean by linear indexing? like the way m giving (count,:) ? n how can i achieve it keeping in mind that i have to retain the time information too. Also the time vector is created by me to keep the track of it. i can not use it too but then i will have to recreate it after applying window?
Your ECG_data is 2 rows by N columns. The most common way to index such data is with subscript indexing where you index all dimensions at once, e.g.:
value = ECG_data(row, column);
However, in your assignment to New_data, you only use 1 index. This is called linear indexing. While you can use either, I don't think it was your intent since
ECG_data(1) is the same as ECG_data(1, 1) == Time(1)
ECG_data(2) is the same as ECG_data(2, 1) == ECG(1)
ECG_data(3) is the same as ECG_data(1, 2) == Time(2)
etc.
So your ECG_data(n_start_1:(n_start+ n_window)) ends up being an alternation of Time and ECG values.
As for the bsxfun (which is not needed anymore in R2016b), I took a guess at what your data looked like and what exact result you wanted. Possibly, it's not what I understood. Post an example of your data and the result you want to make it clear.
oh ok now i got it. so if i write
ECG_data(:,n_start_1:(n_start+ n_window))
it should work than? Here is some data for your reference.
time= [0 0.0039062 0.0078125 0.01171875 0.015625 0.01953125 0.0234375 0.02734375 0.03125 0.03515625 0.0390625 0.04296875 0.046875 0.05078125 0.0546875 0.058593 0.0625 0.06640625 0.0703125 0.07421875 0.0781250000000000 0.08203125 0.0859375 0.08984375 0.09375 0.09765625 0.1015625 0.1054687 0.109375 0.1132812 0.1171875 0.12109375 0.125 0.12890625 0.1328125 0.13671875 0.140625 0.14 0.1484375 0.152];
ECG=[106.475232684825 27.6578040741588 -15.8967257495995 31.1621915312428 73.7467569695582 42.0195348134584 -50.1270818036164 -68.8067185168231 -20.0581858548868 53.5339507438773 48.7779963378347 -38.8942684367133 -82.1671956969559 -95.2147811398490 73.8406244907301 174.560474708171 179.629320851453 66.9257170977340 84.2912085145342 83.1960874341954 97.3700831311513 60.8243282215610 82.1948338750286 -5.57129842069129 -201.848285191119 -42.8679934996567 147.683074479286 153.909620050355 75.4676615243762 71.5252256351567 72.2448766308079 9.32234827191572 17.0507741817349 8.66527562371247 100.092241245136 80.3800617990386 44.7729821011673 24.4350191805905 36.7316644541084];
You still haven't showed what should go in New_data, but I believe
ECG_data(:, n_start : min(end, nstart + n_window)); %the min is there to stop the last window exceeding the width of the matrix
may be what you want.
Dear Guillaume, Thank you for your reply. I want the segments of of ECG data so that i can apply some functions on it. for example to find the R peak for each segment. I tried your bsxfunc code. it is working for one row. but how can i use it for both time and ecg amplitude at the same time? keeping the both amplitude and time information?
That's what i did for ecg amplitude:
index=bsxfun(@plus, 1:no_of_window, (0:no_of_overlap:numel(data)-no_of_window).');
segment_matrix=data(index);
Guillaume
Guillaume el 11 de Oct. de 2016
Editada: Guillaume el 11 de Oct. de 2016
It's a bit more complicated if you want to apply the same indexing method on rows of a matrix as you have to move either the windows or the signals onto the third dimension
%inputs:
windowlength = 5120; %size of windows
windowstep = 64; %step between each window. If < windowlength, windows overlap
data = [Time; ECG]; %a 2D matrix to be split in windows along the column
[nrows, ncols] = size(data);
%switch signals along 3rd dimension:
segmented_data = data(bsxfun(@plus, ...
bsxfun(@plus, ...
1:windowlength, ...
(0:windowstep:ncols-windowlength).') * nrows, ...
permute(1-nrows:0, [1 3 2])))
%or switch windows along 3rd dimension:
segmented_data = data(bsxfun(@plus, ...
bsxfun(@plus, ...
1:windowlength, ...
permute(0:windowstep:ncols-windowlength, [1 3 2])) * nrows, ...
(1-nrows:0).'))
In either case, there may be leftover samples if the last window does not end exactly on the last sample.
edit: removed extra -1
mahrukh jamil
mahrukh jamil el 11 de Oct. de 2016
Thanks. thats seems like a nice explanation. I am gonna try it. but my question is now that i want all the samples covered, so what i plan to do is take some more samples from the next data (data ECG_2) enough to make it complete. I would need some help on it. if i define a condition that when the window don't find enough samples, take it from the next data. i could concatenate both data ( ECG1 and ECG2 ) apply my window, and than remove the remaining data that is not needed. would that be a right approach? But how would i define how many samples to take from next data? Also I don't understand how the overlap of window is affecting on the number of windows? if there is no overlap than no of window= length of data/length of window;
Note: I made a mistake in the above, there's a -1 that snuck in a few places. I've corrected that now.
As it is the number of windows is:
no_of_windows = max(1 + floor((size(data, 2) - windowlength) / windowstep), 0);
The numbers of columns to add to make sure the last samples are included is:
col_to_add = mod(windowlength - size(data, 2), windowstep);

Iniciar sesión para comentar.

Más respuestas (2)

LauraLee Austin
LauraLee Austin el 6 de Oct. de 2016
It was not clear to me how/where you wanted the overlap. Below is my quick stab at what I think you might be looking for. It is not efficient.
ECG_data=[time; ECG];
N_max=length(ECG_data);
n_window=5120;
overlap_win=64;
max_count = ceil((length(ECG_data)-n_window)/(n_window-overlap_win))+1;
new_data = zeros(max_count,n_window);
n_start=1;
for count = 1:max_count
n_end = n_start + n_window - 1;
if n_end > N_max
new_data(count,1:N_max-n_start+1) = ECG(n_start:N_max);
else
new_data(count,:) = ECG(n_start:n_end);
end
n_start = n_end-overlap_win;
% do something..
end
ECG_mean=mean(new_data');
Fars Samann
Fars Samann el 26 de Jun. de 2022

1 voto

Simply use buffer.m and define the length of the window and the overlapped part
with regards
Fars

1 comentario

Great suggestion. The 'buffer' function handles overlap, underlap, and no overlap. It's a compiled function (in Signal Processing toolbox) so should run very fast. The built-in documentation illustrates with an informative example:
x = 1:18; % Example input data to be buffered
y = buffer(x, 8, 4); % Create overlapping buffer matrix

Iniciar sesión para comentar.

Categorías

Preguntada:

el 6 de Oct. de 2016

Comentada:

el 21 de Jun. de 2023

Community Treasure Hunt

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

Start Hunting!

Translated by