-
Notifications
You must be signed in to change notification settings - Fork 7
/
utilECG.m
319 lines (284 loc) · 8.74 KB
/
utilECG.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
function utilECG = utilECG
utilECG.detectRPeaks_FDeriv = @detectRPeaks_FDeriv;
utilECG.detectRPeaks = @detectRPeaks;
utilECG.detectRPeaksTh = @detectRPeaksTh;
utilECG.detectPQ = @detectPQ;
utilECG.detectTP = @detectTP;
utilECG.detectST = @detectST;
utilECG.instVariance = @instVariance;
utilECG.addBaseLine = @addBaseLine;
utilECG.addLineNoise = @addLineNoise;
utilECG.lowPassFilter = @lowPassFilter;
utilECG.highPassFilter = @highPassFilter;
utilECG.readECG_Discardia = @readECG_Discardia;
utilECG.FFTplot = @FFTplot;
utilECG.ECGx = @ECGx;
end
function [serieRRx,serieRRy] = detectRPeaks_FDeriv(ecgy)
% Detection of R wave using the first derivate
%
% ecgy: ECG signal
%
% serieRRx: X axis (time) position of R waves
% serieRRy: Y axis (amplitude) of R waves
%
% Reference:
%
% implemented by: Francisco Perdigon Romero
% email: fperdigon88@gmail.com
Decg = diff(ecgy);
[M,N]=size(ecgy);
c= 1; x= 1; ymax= max(Decg); flag=0;
y= ymax * 0.5;
for i=2 : M-1
if Decg(i) > y
y = Decg(i);
x = i;
flag = 1;
end
if Decg(i) <= 0.2*ymax && flag == 1;
serieRRx(c)= i + 1 ;
serieRRy(c)= ecgy(i + 1);
% serieRRx(c)= i;
% serieRRy(c)= ecgy(i);
y= ymax * 0.5;
flag= 0;
c = c + 1;
end
end
serieRRx = serieRRx';
serieRRy = serieRRy';
end
function [serieRRx,serieRRy] = detectRPeaks(ecgy, Vecg)
% Detection of R wave using the instant varince
%
% ecgy: ECG signal
%
% serieRRx: X axis (time) position of R waves
% serieRRy: Y axis (amplitude) of R waves
%
% Reference:
%
% implemented by: Francisco Perdigon Romero
% email: fperdigon88@gmail.com
VecgMax = max(max(Vecg));
[peaks_y,peaks_x] = findpeaks(Vecg, 'MINPEAKHEIGHT', VecgMax * 0.6, 'MINPEAKDISTANCE', 10);
l = length(peaks_x);
l1 = peaks_x(2) - peaks_x(1);
l2 = peaks_x(3) - peaks_x(2);
c = 1;
if (l2 < l1)
for i= 2:2:l-2
tmp = Vecg(peaks_x(i):peaks_x(i+1));
[p_y, p_x] = findpeaks(-tmp);
serieRRx(c) = peaks_x(i) + p_x(1) - 1; %Hay que restarle una muestra
serieRRy(c) = ecgy(serieRRx(c));
c = c + 1;
end
else
for i= 1:2:l-2
tmp = Vecg(peaks_x(i):peaks_x(i+1));
[p_y, p_x] = findpeaks(-tmp);
serieRRx(c) = peaks_x(i) + p_x;
serieRRy(c) = ecgy(serieRRx(c));
c = c + 1;
end
end
end
function [serieRRx,serieRRy] = detectRPeaksTh(ecgy)
% Detection of R wave using Threshold (0.8 of the max)
%
% ecgy: ECG signal
%
% serieRRx: X axis (time) position of R waves
% serieRRy: Y axis (amplitude) of R waves
%
% Reference:
%
% implemented by: Francisco Perdigon Romero
% email: fperdigon88@gmail.com
ecgMax = max(max(ecgy));
[serieRRy,serieRRx] = findpeaks(ecgy, 'MINPEAKHEIGHT',ecgMax * 0.8, 'MINPEAKDISTANCE', 10);
end
function [seriePQx,seriePQy] = detectPQ(ecgy, serieRRx, serieRRy, Vecg)
% Detection of PQ interval using the instant variance and
% the R points as reference
%
% ecgy: ECG signal
% serieRRx: X axis (time) position of R waves
% serieRRy: Y axis (amplitude) of R waves
% Vecg: Instant variance of the ECG signal TODO: calculate inside the method
%
% seriePQx: X axis (time) position of the center of PQ segment
% seriePQy: Y axis (amplitude) of the center PQ segment
%
% Reference:
%
% implemented by: Francisco Perdigon Romero
% email: fperdigon88@gmail.com
l = length(serieRRx);
seriePQx = zeros(l,1);
seriePQy = zeros(l,1);
meanDrr = mean(diff(serieRRx));
c= 1;
% NMu -> samples number before the R peak
NMu = 10;
for i=1:length(serieRRx)%
Vtmp = Vecg(serieRRx(i)-floor(meanDrr/4) : (serieRRx(i) - NMu));
[peaks_y,peaks_x] = findpeaks(-Vtmp);
t = length(peaks_x);
seriePQx(c) = (serieRRx(i) - NMu) - (length(Vtmp) - peaks_x(t));
seriePQy(c) = ecgy(seriePQx(c));
c = c + 1;
end
end
function Vecg = instVariance(ecgy, m, scale)
% Calculate the instant variance of the signal
% in a windows size = m * 2 + 1
l = length(ecgy);
Vecg = zeros(l,1);
[M,N]=size(ecgy);
for i = m+1 : M - m
Vecg(i) = var(ecgy(i-m : i+m));
end
Vecg = Vecg * scale;
end
function ecgy_BL = addSineBaseLine(ecgy, F, Fs, Amp)
% Add artificial (sine) BLW to the ecg signal
%
% ecgy: ECG signal
% F: Frequency of the BLW
% Fs: Sampling Frequency
% Amp: The BLW amplitude in proportion to the ECG (values between 0-1)
%
% ecgy_BL: ECG signal plus the artificial BLW
%
% Reference:
%
% implemented by: Francisco Perdigon Romero
% email: fperdigon88@gmail.com
[M,N] = size(ecgy);
maxx = max([M,N]);
ecgx = 0:maxx;
ecgx = ecgx/Fs;
AA = (max(ecgy)-min(ecgy)) * Amp;
bl = AA * sin(2 * pi * F * ecgx);
ecgy_BL = ecgy + bl;
end
function ecgy_LN = addLineNoise(ecgy, F, Fs)
% Add artificial electric line to the ecg signal
%
% ecgy: ECG signal
% F: Frequency of the line noise (50 or 60)
% Fs: Sampling Frequency
%
% ecgy_LN: ECG signal contaminated with artificial
% electric line noise
%
% Reference:
%
% implemented by: Francisco Perdigon Romero
% email: fperdigon88@gmail.com
[M,N] = size(ecgy);
maxx = max([M,N]);
ecgx = zeros(maxx);
AA = max(ecgy) * 0.005;
ln = AA * sin(2 * pi * F/Fs * ecgx);
ecgy_LN = ecgy + ln;
end
function ecgy_filt = lowPassFilter(ecgy, F, Fs)
% Low pass IIR filter
%
% ecgy: ECG signal
% F: Cut-off Frequency for the filter
% Fs: Sampling Frequency
%
% ecgy_filt: ECG signal contaminated with artificial
% electric line noise
%
% Reference:
%
% implemented by: Francisco Perdigon Romero
% email: fperdigon88@gmail.com
[b,a] = butter(4,F/Fs,'low');
ecgy_filt = filtfilt (b,a,ecgy); % bidirectional filteroing
end
function ecgy_filt = highPassFilter(ecgy, F, Fs)
% High pass IIR filter
%
% ecgy: ECG signal
% F: Cut-off Frequency for the filter
% Fs: Sampling Frequency
%
% ecgy_filt: ECG signal contaminated with artificial
% electric line noise
%
% Reference:
%
% implemented by: Francisco Perdigon Romero
% email: fperdigon88@gmail.com
[b,a] = butter(4,F/Fs,'high');
ecgy_filt = filtfilt (b,a,ecgy); % bidirectional filteroing
end
function [signal t]= readECG_Discardia(filename)
% Credits to Dicardia team
% [signal t] = ReadECG(filename)
%
% This function reads an ECG record from the DICARDIA database. It opens
% the desired file and stores the 8 ECG derivations in the independent
% variable 'signal'. The function also returns a time vector 't' that is
% used to plot the signals.
%
% Input:
%
% 'filename' is a sring containing the full path to the ECG record that
% will be read
%
% Output:
%
% 'signal' is an array of doubles containing 8 rows that correspond to
% the ECG derivations contained in the file. The rows contain the DI,
% DII, V1, V2, V3, V4, V5 and V6 derivations respectively. These signals
% have a 500Hz sampling frequency
%
% 't' is a time axis that is coherent with the signals. It may be used to
% plot the signals having a time reference.
%
% This routine was developed by the Simon Bolivar University's Applied
% Biophysics and Bioengineering Group (GBBA-USB) for free and public use.
% It is protected under the terms of the Creative Commons Attribution-Non
% Commercial 4.0 International License, no profit may come from any
% application that uses this function and proper credit must be given to
% the GBBA-USB. For further information consult
% http://creativecommons.org/licenses/by-nc/4.0/
freq = 500;
ConversionResolution = 3.06e-3;
NumberBits = 12;
ders= 1:8;
fid = fopen(filename,'r');
A = fread(fid,'short');
for i=1:8
x = [A(i:8:end)];
signal(i,:) = x(5000:end);
end
t = 0:1/freq:(length(signal)-1)/freq;
end
function [Y,f,h] = FFTplot(signal, Fs)
T = 1/Fs; % Sample time
L = max(size(signal)); % Length of signal
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(signal,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
% Plot single-sided amplitude spectrum.
h = figure();
set(gca, 'fontsize', 20, 'FontName','arial')
plot(f,2*abs(Y(1:NFFT/2+1))) ;
title('Single-Sided Amplitude Spectrum')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
%xlim([0 5])
end
function [ecgx] = ECGx(ecgy, Fs)
len = max(size(ecgy));
ecgx = [0:1/Fs:len]
end