0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 function Results = EMD1D3V(u,v,w,t,param)
0034
0035
0036 [Nx] = length(u);
0037 B = length(v);
0038 C = length(w);
0039
0040
0041 if ~isfield(param,'nimfs')
0042 param.nimfs = 10;
0043 end
0044
0045 if ~isfield(param,'tol')
0046 param.tol = 0.05;
0047 end
0048
0049 if ~isfield(param,'type')
0050 param.type = 6;
0051 end
0052
0053 if ~isfield(param,'plot')
0054 param.plot = 'off';
0055 end
0056
0057 if(~all(ismember(param.type,[1,2,3,4,5,6,7])))
0058 error('Please enter a valid window size type')
0059 end
0060
0061 if(~all(Nx==B) || ~all(Nx==C))
0062 error('Inconsistent dimensions between channels. Please check input data');
0063 end
0064 clearvars B C
0065
0066 if(param.tol<=0.005)
0067 warning('Low sifting tolerance may cause oversifting');
0068 answer = questdlg('Would you like to continue?', ...
0069 'User set low sifting tolerance', ...
0070 'Yes','No','No');
0071
0072 switch answer
0073 case 'Yes'
0074
0075 case 'No'
0076 return;
0077 end
0078 end
0079
0080 if ~isfield(param,'plot')
0081 param.plot = 'off';
0082 end
0083
0084
0085 IMF.u = zeros(Nx, param.nimfs);
0086 IMF.v = zeros(Nx, param.nimfs);
0087 IMF.w = zeros(Nx, param.nimfs);
0088 Residue.u = u; Residue.v = v; Residue.w = w;
0089
0090 Windows = zeros(7,param.nimfs);
0091
0092 sift_cnt = zeros(1,param.nimfs);
0093 imf = 1;
0094
0095 while(imf <= param.nimfs)
0096
0097 H.u = Residue.u; H.v = Residue.v; H.w = Residue.w;
0098
0099 sift_stop = 0;
0100
0101 Combined = H.u/sqrt(3) + H.v/sqrt(3) + H.w/sqrt(3) ;
0102 [Maxima,MaxPos,Minima,MinPos] = extrema(Combined);
0103
0104
0105
0106 if (nnz(Maxima) < 3 || nnz(Minima) < 3)
0107 warning('Fewer than three extrema found in extrema map. Stopping now...');
0108 break;
0109 end
0110
0111
0112 Windows(:,imf) = filter_size1D(MaxPos,MinPos,param.type);
0113 w_sz = Windows(param.type,imf);
0114
0115
0116 while~(sift_stop)
0117 sift_cnt(imf) = sift_cnt(imf) + 1;
0118
0119 Env = OSF(H,w_sz);
0120
0121
0122 Env = Pad_smooth(Env,w_sz);
0123
0124
0125 Env.u.med = (Env.u.maxs + Env.u.mins)./2;
0126 Env.v.med = (Env.v.maxs + Env.v.mins)./2;
0127 Env.w.med = (Env.w.maxs + Env.w.mins)./2;
0128
0129
0130
0131
0132 H1.u = H.u - Env.u.med; H1.v = H.v - Env.v.med; H1.w = H.w - Env.w.med;
0133
0134
0135
0136
0137 mse_u = immse(H1.u,H.u); mse_v = immse(H1.v,H.v); mse_w = immse(H1.w,H.w);
0138 if (mse_u<param.tol && mse_v<param.tol && mse_w<param.tol && sift_cnt(imf)~=1)
0139 sift_stop = 1;
0140 end
0141
0142 H.u = H1.u; H.v = H1.v; H.w = H1.w;
0143 end
0144
0145
0146 IMF.u(:,imf) = H.u; IMF.v(:,imf) = H.v; IMF.w(:,imf) = H.w;
0147
0148
0149 Residue.u = Residue.u - IMF.u(:,imf);
0150 Residue.v = Residue.v - IMF.v(:,imf);
0151 Residue.w = Residue.w - IMF.w(:,imf);
0152
0153
0154 imf = imf + 1;
0155
0156 end
0157
0158
0159 if(any(sift_cnt>=5*ones(1,param.nimfs)))
0160 warning('Decomposition may be oversifted. Checking if window size increases monotonically...');
0161
0162 if( any (diff(Windows(param.type,:)) <= zeros(1,param.nimfs-1)) )
0163 warning('Filter window size does not increase monotonically')
0164 end
0165 end
0166
0167
0168 Results.IMF = IMF;
0169 Results.Residue = Residue;
0170 Results.Windows = Windows;
0171 Results.Sifts = sift_cnt;
0172
0173
0174 [Results.IO.u,Results.Error.u] = Orth_index(u,IMF.u,Residue.u);
0175 [Results.IO.v,Results.Error.v] = Orth_index(v,IMF.v,Residue.v);
0176 [Results.IO.w,Results.Error.w] = Orth_index(w,IMF.w,Residue.w);
0177
0178 switch(param.plot)
0179 case 'on'
0180 Plot_results(u,v,w,t,Results,param)
0181 end
0182 end
0183
0184 function Windows = filter_size1D(imax, imin, type)
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 edge_len_max = diff(sort(imax));
0205 edge_len_min = diff(sort(imin));
0206
0207
0208
0209
0210 d1 = min( min(edge_len_max) , min(edge_len_min) );
0211 d2 = max( min(edge_len_max) , min(edge_len_min) );
0212 d3 = min( max(edge_len_max) , max(edge_len_min) );
0213 d4 = max( max(edge_len_max) , max(edge_len_min) );
0214 d5 = (d1+d2+d3+d4)/4 ;
0215 d6 = median([edge_len_max; edge_len_min]);
0216 d7 = mode([edge_len_max; edge_len_min]);
0217
0218 Windows = [d1, d2, d3, d4, d5, d6, d7];
0219
0220
0221 Windows = 2*(floor(Windows./2))+1;
0222
0223 if(Windows(type)<3)
0224 warning('WARNING: Calculated Window size less than 3');
0225 warning('Overriding calculated value and setting window size = 3');
0226 Windows(type) = 3;
0227 end
0228
0229 end
0230
0231 function Env = OSF(H,w_sz)
0232
0233 Env.u.max = Ordfilt1(H.u, 'max', w_sz);
0234 Env.u.min = Ordfilt1(H.u, 'min', w_sz);
0235
0236 Env.v.max = Ordfilt1(H.v, 'max', w_sz);
0237 Env.v.min = Ordfilt1(H.v, 'min', w_sz);
0238
0239 Env.w.max = Ordfilt1(H.w, 'max', w_sz);
0240 Env.w.min = Ordfilt1(H.w, 'min', w_sz);
0241
0242 function f_signal = Ordfilt1(signal,order,window_size)
0243
0244
0245
0246
0247 [a,b,c] = size(signal);
0248 signal = squeeze(signal);
0249 L = length(signal);
0250 signal = reshape(signal, [L,1]);
0251
0252 r = (window_size-1)/2;
0253
0254
0255 x = [flip(signal(1:r)); signal ;flip(signal(end-(r-1):end))];
0256
0257 [M,~] = size(x);
0258 y = zeros(size(x));
0259
0260 switch order
0261 case 'max'
0262 for m = 1+r:M-r
0263
0264 temp = x((m-r):(m+r));
0265 w = sort(temp);
0266 y(m) = w(end);
0267 end
0268 case 'min'
0269 for m = 1+r:M-r
0270
0271 temp = x((m-r):(m+r));
0272 w = sort(temp);
0273 y(m) = w(1);
0274 end
0275 otherwise
0276 error('No such filering operation defined')
0277 end
0278
0279 f_signal = y(1+r:end-r);
0280
0281 f_signal = reshape(f_signal,[a,b,c]);
0282 end
0283
0284 end
0285
0286 function Env = Pad_smooth(Env,w_sz)
0287 h = floor(w_sz/2);
0288
0289
0290
0291 Env.u.maxp = padarray(Env.u.max,[h 0],'symmetric');
0292 Env.u.minp = padarray(Env.u.min,[h 0],'symmetric');
0293
0294 Env.v.maxp = padarray(Env.v.max,[h 0],'symmetric');
0295 Env.v.minp = padarray(Env.v.min,[h 0],'symmetric');
0296
0297 Env.w.maxp = padarray(Env.w.max,[h 0],'symmetric');
0298 Env.w.minp = padarray(Env.w.min,[h 0],'symmetric');
0299
0300
0301
0302 Env.u.maxs = movmean(Env.u.maxp,w_sz,1,'endpoints','discard');
0303 Env.u.mins = movmean(Env.u.minp,w_sz,1,'endpoints','discard');
0304
0305 Env.v.maxs = movmean(Env.v.maxp,w_sz,1,'endpoints','discard');
0306 Env.v.mins = movmean(Env.v.minp,w_sz,1,'endpoints','discard');
0307
0308 Env.w.maxs = movmean(Env.w.maxp,w_sz,1,'endpoints','discard');
0309 Env.w.mins = movmean(Env.w.minp,w_sz,1,'endpoints','discard');
0310
0311 end
0312
0313 function [IO,Error] = Orth_index(Signal,IMF,Residue)
0314
0315
0316
0317
0318 n_imf = size(IMF,2);
0319 numerator = zeros(size(Signal));
0320 I = sum(IMF,2) + Residue;
0321
0322 Error.map = (Signal-I)./Signal;
0323 Error.global = immse(I,Signal);
0324
0325 for j = 1:n_imf
0326 for k = 1:n_imf
0327 if(j~=k)
0328 numerator = numerator + IMF(:,j).*IMF(:,k);
0329 end
0330 end
0331 end
0332
0333 IO.map = numerator/(sum(Signal.^2));
0334 IO.global = sum(IO.map);
0335 end
0336
0337 function Plot_results(u,v,w,t,Results,param)
0338
0339 set(groot,'defaultaxesfontname','times');
0340 set(groot,'defaultaxesfontsize',12);
0341 set(groot,'defaulttextInterpreter','tex');
0342 set(groot,'defaultLineLineWidth',2);
0343
0344 figure(1)
0345 subplot(3,1,1)
0346 IMF_plot(u,t,0,'Channel','1');
0347 subplot(3,1,2)
0348 IMF_plot(v,t,0,'Channel','2');
0349 subplot(3,1,3)
0350 IMF_plot(w,t,0,'Channel','2');
0351
0352
0353 for i=1:param.nimfs
0354 figure(i+1)
0355 subplot(3,1,1)
0356 IMF_plot(Results.IMF.u(:,i),t,i,'IMF','Channel 1');
0357 subplot(3,1,2)
0358 IMF_plot(Results.IMF.v(:,i),t,i,'IMF','Channel 2');
0359 subplot(3,1,3)
0360 IMF_plot(Results.IMF.w(:,i),t,i,'IMF','Channel 3');
0361 end
0362
0363 figure(i+2)
0364 subplot(3,1,1)
0365 IMF_plot(Results.Residue.u,t,0,'Residue','Channel 1');
0366 subplot(3,1,2)
0367 IMF_plot(Results.Residue.v,t,0,'Residue','Channel 2');
0368 subplot(3,1,3)
0369 IMF_plot(Results.Residue.w,t,0,'Residue','Channel 3');
0370 end
0371
0372 function IMF_plot(signal,t,imf,name1,name2)
0373
0374 plot(t,signal,'-k');
0375 axis ([0 6*pi -5 5]);
0376 xlabel('t');
0377 set(gca,'TickLabelInterpreter','tex')
0378 switch(name1)
0379 case 'IMF'
0380 title(sprintf('%s %d %s',name1,imf,name2));
0381 case 'Channel'
0382 title(sprintf('%s %s',name1,name2));
0383 case 'Residue'
0384 title(sprintf('%s %s',name1,name2));
0385 end
0386
0387
0388 end
0389