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