0001 function img=inv_solve_abs_pdipm( inv_model, data);
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 pp= process_parameters(inv_model);
0024
0025 img_bkgnd = homogeneous_estimate( inv_model, data );
0026
0027 alpha=calc_hyperparameter( inv_model );
0028 L= calc_R_prior( inv_model );
0029 W= calc_meas_icov( inv_model );
0030
0031 img= feval(pp.fn, img_bkgnd, W,alpha*L,data, pp);
0032
0033 img.name = sprintf('inv_solve_abs_pdipm-nd%d-ni%d',pp.norm_data,pp.norm_image);
0034
0035
0036
0037 function img= pdipm_2_2( img,W,L,d, pp);
0038 img0 = img;
0039 hp2RtR = L'*L;
0040 for i = 1:pp.max_iter
0041 dv = sim_diff( img, d);
0042 J = calc_jacobian( img );
0043
0044 RDs = hp2RtR*(img0.elem_data - img.elem_data);
0045 ds = (J'*W*J + hp2RtR)\(J'*dv + RDs);
0046
0047 img = line_optimize(img, ds, d);
0048
0049 pp = manage_beta(pp);
0050 loop_display(i)
0051 end
0052
0053 function img= pdipm_1_2( img,W,L,d, pp);
0054 [M] = size(W,1);
0055 [jnk,N] = size(L);
0056 x= zeros( M, 1 );
0057
0058 for loop = 1:pp.max_iter
0059
0060 J = calc_jacobian( img );
0061 dv = -sim_diff(img, d);
0062 s = img.elem_data;
0063
0064
0065 f = dv; F= spdiags(f,0,M,M);
0066 X= spdiags(x,0,M,M);
0067 e = sqrt(f.^2 + pp.beta);E= spdiags(e,0,M,M);
0068
0069
0070 dFc_ds = (speye(M,M) - X*inv(E)*F)*J;
0071 dFc_dx = -E;
0072 dFf_ds = L'*L;
0073 dFf_dx = J'*W;
0074
0075 dsdx = -[dFc_ds, dFc_dx; dFf_ds, dFf_dx] \ ...
0076 [ f-E*x; J'*W*x + L'*L*s ];
0077
0078 ds = dsdx(1:N);
0079 img = line_optimize(img, ds, d);
0080
0081 dx = x_update(x, dsdx(N+(1:M)));
0082 x= x + dx;
0083
0084 pp = manage_beta(pp);
0085 loop_display(i)
0086 end
0087
0088 function img= pdipm_2_1(img,W,L,d, pp);
0089 [M] = size(W,1);
0090 [G,N] = size(L);
0091 x= zeros( G, 1 );
0092
0093 for loop = 1:pp.max_iter
0094
0095 J = calc_jacobian( img );
0096 dv = -sim_diff(img, d);
0097
0098
0099 f = L*img.elem_data; F= spdiags(f,0,G,G);
0100 X= spdiags(x,0,G,G);
0101 e = sqrt(f.^2 + pp.beta);E= spdiags(e,0,G,G);
0102
0103
0104 dFc_ds = (speye(G,G) - X*inv(E)*F)*L;
0105 dFc_dx = -E;
0106 dFf_ds = J'*J;
0107 dFf_dx = L';
0108
0109 dsdx = -[dFc_ds, dFc_dx; dFf_ds, dFf_dx] \ ...
0110 [ f-E*x; J'*dv + L'*x ];
0111
0112 ds = dsdx(1:N);
0113 img = line_optimize(img, ds, d);
0114
0115 dx = x_update(x, dsdx(N+(1:G)));
0116 x= x + dx;
0117
0118 pp = manage_beta(pp);
0119 loop_display(i)
0120 end
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137 function img= pdipm_1_1( img,W,L,d, pp);
0138 [M] = size(W,1);
0139 [D,N] = size(L);
0140 s= img.elem_data;
0141 y= zeros( D, 1 );
0142 x= zeros( M, 1 );
0143
0144 for loop = 1:pp.max_iter
0145
0146 J = calc_jacobian( img );
0147 dv = -sim_diff(img, d);
0148
0149
0150 g = L*img.elem_data; G= spdiags(g,0,D,D);
0151 s = sqrt(g.^2 + pp.beta);S= spdiags(s,0,D,D);
0152 Y= spdiags(y,0,D,D);
0153
0154 f = dv; F= spdiags(f,0,M,M);
0155 e = sqrt(f.^2 + pp.beta);E= spdiags(e,0,M,M);
0156 X= spdiags(x,0,M,M);
0157
0158
0159 As1 = sparse(N,N);
0160 As2 = (speye(M,M) - X/E*F) * J;
0161 As3 = (speye(D,D) - Y/S*G) * L;
0162 Ax1 = J'*W;
0163 Ax2 = -E;
0164 Ax3 = sparse(D,M);
0165 Ay1 = L';
0166 Ay2 = sparse(M,D);
0167 Ay3 = -S;
0168 B1 = J'*W*x + L'*y;
0169 B2 = f - E*x;
0170 B3 = g - S*y;
0171
0172
0173
0174
0175
0176
0177
0178 JtWiE = J'*W/E; LtiS = L'/S;
0179 dm= -(JtWiE*As2 + LtiS*As3)\(JtWiE*f + LtiS*g);
0180 dx= E\(B2 + As2*dm);
0181 dy= S\(B3 + As3*dm);
0182
0183 img = line_optimize(img, dm, d);
0184
0185 dx = x_update(x, dx);
0186 x= x + dx;
0187
0188 dy = x_update(y, dy);
0189 y= y + dy;
0190
0191 loop_display(i)
0192 pp = manage_beta(pp);
0193 end
0194
0195
0196 function dx = x_update( x, dx)
0197 dx(dx==0) = eps;
0198 sx = sign(dx);
0199
0200 clr = sx - x;
0201
0202 fac = clr./dx;
0203
0204 dx = dx*min(fac);
0205
0206 function pp = manage_beta(pp);
0207 pp.beta = pp.beta * pp.beta_reduce;
0208 if pp.beta < pp.beta_minimum;
0209 pp.beta = pp.beta_minimum;
0210 end
0211
0212 function pp= process_parameters(imdl);
0213 try pp.max_iter = imdl.parameters.max_iterations;
0214 catch pp.max_iter = 10;
0215 end
0216
0217 try pp.min_change = imdl.parameters.min_change;
0218 catch pp.min_change = 0;
0219 end
0220
0221 try pp.beta = imdl.inv_solve_abs_pdipm.beta;
0222 catch pp.beta = 1e-6;
0223 end
0224
0225 pp.beta_reduce = 0.2;
0226 pp.beta_minimum= 1e-16;
0227
0228 try pp.norm_data = imdl.inv_solve_abs_pdipm.norm_data;
0229 catch pp.norm_data = 2;
0230 end
0231
0232 try pp.norm_image = imdl.inv_solve_abs_pdipm.norm_image;
0233 catch pp.norm_image = 2;
0234 end
0235
0236 if pp.norm_data==2 && pp.norm_image==2;
0237 pp.fn = @pdipm_2_2;
0238 elseif pp.norm_data==2 && pp.norm_image==1;
0239 pp.fn = @pdipm_2_1;
0240 elseif pp.norm_data==1 && pp.norm_image==2;
0241 pp.fn = @pdipm_1_2;
0242 elseif pp.norm_data==1 && pp.norm_image==1;
0243 pp.fn = @pdipm_1_1;
0244 else
0245 error('norm_data and norm_image should be 1 or 2');
0246 end
0247
0248
0249
0250
0251
0252 function img = line_optimize(imgk, dx, data1);
0253 flist = [ 0.1, 0.5, 1.0];
0254 clim = mean(imgk.elem_data)/10;
0255 img = imgk;
0256 for i = 1:length(flist);
0257 img.elem_data = imgk.elem_data + flist(i)*dx;
0258 img.elem_data(img.elem_data <= clim ) = clim;
0259 dv = sim_diff( img, data1);
0260 mlist(i) = norm(dv);
0261 end
0262 pf = polyfit(flist, mlist, 2);
0263 fmin = -pf(2)/pf(1)/2;
0264 fmin(fmin>1) = 1; fmin(fmin<0) = 0;
0265
0266 img.elem_data = imgk.elem_data + flist(i)*dx;
0267 img.elem_data(img.elem_data <= clim ) = clim;
0268
0269 function img = homogeneous_estimate( imdl, data );
0270 img = calc_jacobian_bkgnd( imdl );
0271 vs = fwd_solve(img);
0272 data = data_vector( data, imdl );
0273
0274 pf = polyfit(data,vs.meas,1);
0275
0276 img.elem_data = img.elem_data*pf(1);
0277
0278 function data = data_vector( data, imdl );
0279 if isstruct(data)
0280 data = data.meas;
0281 else
0282 meas_select = [];
0283 try
0284 meas_select = imdl.fwd_model.meas_select;
0285 end
0286 if length(data) == length(meas_select)
0287 data = data(meas_select);
0288 end
0289 end
0290
0291 function dv = sim_diff( img, data1);
0292 vsim = fwd_solve( img );
0293 dv = calc_difference_data( vsim , data1, img.fwd_model);
0294
0295 function loop_display(i)
0296 fprintf('+');