0001 function PSF = GREIT_desired_img_sigmoid(xyz,radius, opt)
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
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 if ischar(xyz) && strcmp(xyz,'UNIT_TEST'), do_unit_test; return, end
0057
0058 [xyzr, radius, opt] = parse_opt(xyz, radius, opt);
0059
0060 copt.cache_obj = {xyzr, radius, opt.rec_model.nodes, opt.rec_model.elems, opt.steepness};
0061 copt.fstr = 'GREIT_desired_img_sigmoid';
0062 PSF = eidors_cache(@desired_soln,{xyzr, radius, opt},copt);
0063
0064
0065 end
0066
0067
0068
0069 function PSF = desired_soln(xyz, radius, opt)
0070 num_it = size(xyz,2);
0071 progress_msg('Composing desired images:',0,num_it);
0072 mdl = opt.rec_model;
0073 switch opt.n_dim
0074 case 3
0075 mdl.vox = [mdl.elems(1:6:end,:) mdl.elems(6:6:end,:)];
0076
0077 min_vox_edge = min( [min(diff(unique(mdl.nodes(:,1)))), ...
0078 min(diff(unique(mdl.nodes(:,2)))), ...
0079 min(diff(unique(mdl.nodes(:,3))))] );
0080 case 2
0081 mdl.vox = [mdl.elems(1:2:end,:) mdl.elems(2:2:end,:)];
0082 min_vox_edge = min( [min(diff(unique(mdl.nodes(:,1)))), ...
0083 min(diff(unique(mdl.nodes(:,2))))] );
0084
0085 end
0086 [Xnodes,Ynodes,Znodes] = voxnodes(mdl);
0087
0088
0089
0090 warned = false;
0091 interp_elem_new('reset',size(mdl.vox,1),[],opt);
0092
0093
0094 n_el = size(mdl.vox,1);
0095 n_pt = size(xyz,2);
0096 n_ep = n_el*n_pt;
0097 ll = eidors_msg('log_level',0);
0098 vox_box = sum(get_elem_volume(mdl));
0099 eidors_msg('log_level',ll);
0100 tgt_box = (2*mean(radius+opt.threshold./opt.steepness))^3;
0101 n_nz = ceil(n_ep*tgt_box/vox_box);
0102 SPARSE_STEP = ceil(n_nz/5);
0103 PSF = spalloc(n_el,n_pt,n_nz);
0104
0105 Npts = size(xyz,2);
0106 Nfailed = 0;
0107 for i=1:Npts
0108 if nnz(PSF) > n_nz
0109 n_nz = nnz(PSF) + SPARSE_STEP;
0110 [r,c,v] = find(PSF);
0111 PSF = sparse(r,c,v,n_el,n_pt,n_nz);
0112 end
0113 th = opt.threshold/opt.steepness(i);
0114 progress_msg(i,num_it);
0115 farel = far_elems(Xnodes,Ynodes,Znodes, xyz(:,i), radius(i), th);
0116
0117 close_el = false(size(farel));
0118 if radius(i) - th > min_vox_edge
0119 close_el = close_elems(Xnodes,Ynodes,Znodes, xyz(:,i), radius(i), th);
0120 end
0121 el_idx = find(~farel & ~close_el);
0122
0123 STEP = 1000;
0124 idx = zeros(STEP,1);
0125 factor = zeros(STEP,1);
0126 X = zeros(STEP,1);
0127 Y = zeros(STEP,1);
0128 Z = zeros(STEP,1);
0129 L = STEP;
0130 N = 1;
0131
0132 for e = el_idx'
0133 [x,y,z] = interp_elem_new(mdl,e,radius(i), opt);
0134 n = numel(x);
0135 N1 = N;
0136 N = N+n;
0137 if N > L
0138 fill = zeros(STEP,1);
0139 idx = [idx; fill];
0140 factor = [factor; fill];
0141 X = [X; fill]; Y = [Y; fill]; Z = [Z; fill];
0142 L = L + STEP;
0143 end
0144 v = N1:N-1;
0145 idx(v) = e;
0146 factor(v) = 1/n;
0147 X(v) = x; Y(v) = y; Z(v) = z;
0148 end
0149
0150 v = N:L;
0151 idx(v) = [];
0152 factor(v) = [];
0153 X(v) = []; Y(v) = []; Z(v) = [];
0154
0155 if isempty(X)
0156
0157
0158
0159
0160
0161
0162
0163 Nfailed = Nfailed + 1;
0164 continue;
0165 end
0166 V = [X Y Z];
0167 D = sqrt(sum(bsxfun(@minus,V(:,1:opt.n_dim),xyz(1:opt.n_dim,i)').^2, 2));
0168 x = D - radius(i);
0169 tmp = 1 ./ (1 + exp( opt.steepness(i) * x));
0170 PSF(:,i) = sparse(idx,1,tmp(:) .* factor,size(mdl.vox,1),1);
0171 PSF(close_el,i) = 1;
0172 end
0173 interp_elem_new('clear');
0174 if Nfailed==0
0175 progress_msg(Inf);
0176 else
0177 progress_msg(sprintf( ...
0178 'Interpolation failed for %d of %d points', ...
0179 Nfailed,Npts), Inf);
0180 end
0181
0182 end
0183
0184
0185
0186 function [X, Y, Z] = voxnodes(mdl)
0187 x = mdl.nodes(:,1); X = x(mdl.vox);
0188 y = mdl.nodes(:,2); Y = y(mdl.vox);
0189 try
0190 z = mdl.nodes(:,3); Z = z(mdl.vox);
0191 catch
0192 Z = [];
0193 end
0194 end
0195
0196 function [x,y,z] = interp_elem_new(mdl,e,radius,opt)
0197 persistent N_entries X Y Z MAP N minnode maxnode done_elems sep
0198 if ischar(mdl) && strcmp(mdl,'reset')
0199 N_entries = 0; X = []; Y = []; Z = []; MAP = [];
0200 N = ones(1,3);
0201 minnode = zeros(e,opt.n_dim);
0202 maxnode = zeros(e,opt.n_dim);
0203 sep = zeros(e,opt.n_dim);
0204 done_elems = false(e,1);
0205 return;
0206 end
0207 if ischar(mdl) && strcmp(mdl,'clear')
0208 clear N_entries X Y Z MAP N minnode maxnode done_elems sep
0209 return;
0210 end
0211 maxsep = radius/5;
0212
0213 if ~done_elems(e)
0214 minnode(e,:) = min(mdl.nodes(mdl.vox(e,:),:));
0215 maxnode(e,:) = max(mdl.nodes(mdl.vox(e,:),:));
0216 sep(e,:) = maxnode(e,:) - minnode(e,:);
0217 done_elems(e) = true;
0218 end
0219
0220 N(1:opt.n_dim) = max(3, ceil(sep(e,:)/maxsep)+1);
0221
0222 try
0223 entry = MAP(N(1),N(2),N(3));
0224 x = X{entry};
0225 y = Y{entry};
0226 z = Z{entry};
0227 catch
0228 entry = N_entries+1;
0229
0230 vx = linvec(0,1,N(1));
0231 vx = vx + .5*(vx(2) -vx(1));
0232
0233 vy = linvec(0,1,N(2));
0234 vy = vy + .5*(vy(2) -vy(1));
0235
0236
0237 switch opt.n_dim
0238 case 2
0239 [x, y] = grid2d(vx,vy);
0240 z = zeros(size(x));
0241 case 3
0242 vz = linvec(0,1,N(3));
0243 vz = vz + .5*(vz(2) -vz(1));
0244 [x, y, z] = grid3d(vx,vy,vz);
0245 end
0246 X{entry} = x;
0247 Y{entry} = y;
0248 Z{entry} = z;
0249 N_entries = entry;
0250 MAP(N(1),N(2),N(3)) = entry;
0251 end
0252 x = x*sep(e,1) + minnode(e,1);
0253 y = y*sep(e,2) + minnode(e,2);
0254 if opt.n_dim == 3
0255 z = z*sep(e,3) + minnode(e,3);
0256 end
0257
0258 end
0259
0260
0261
0262 function [x,y,z] = interp_elem(mdl,e,radius, opt)
0263 maxsep = radius/5;
0264
0265 minnode = min(mdl.nodes(mdl.vox(e,:),:));
0266 maxnode = max(mdl.nodes(mdl.vox(e,:),:));
0267
0268 sep = maxnode - minnode;
0269 N = max(3, ceil(sep/maxsep)+1);
0270
0271 vx = linvec(minnode(1),maxnode(1),N(1));
0272 vx = vx + .5*(vx(2) -vx(1));
0273
0274 vy = linvec(minnode(2),maxnode(2),N(2));
0275 vy = vy + .5*(vy(2) -vy(1));
0276
0277
0278 switch opt.n_dim
0279 case 2
0280 [x, y] = grid2d(vx,vy);
0281 z = [];
0282 case 3
0283 vz = linvec(minnode(3),maxnode(3),N(3));
0284 vz = vz + .5*(vz(2) -vz(1));
0285 [x, y, z] = grid3d(vx,vy,vz);
0286 end
0287 end
0288
0289
0290 function out = linvec(v1, v2, N)
0291
0292 out = v1 + (0:(N-2)).*(v2-v1)/(N-1);
0293
0294 end
0295
0296 function [x, y] = grid2d(vx, vy)
0297
0298 vx = vx.';
0299 x = repmat(vx,size(vy));
0300 y = repmat(vy,size(vx));
0301 end
0302
0303 function [x, y, z] = grid3d(vx,vy,vz)
0304
0305 sz = [numel(vx) numel(vy) numel(vz)];
0306 x = reshape(vx,[sz(1) 1 1]);
0307 x = repmat(x,[1 sz(2) sz(3)]);
0308
0309 y = reshape(vy,[1 sz(2) 1]);
0310 y = repmat(y,[sz(1) 1 sz(3)]);
0311
0312 z = reshape(vz,[1 1 sz(3)]);
0313 z = repmat(z,[sz(1) sz(2) 1]);
0314
0315
0316 end
0317
0318
0319
0320
0321 function farel = far_elems(Xnodes,Ynodes,Znodes,xyz,radius, th)
0322 farel = false(size(Xnodes,1),1);
0323
0324 nodes_test = Xnodes < xyz(1) - radius - th;
0325 farel = farel | all(nodes_test,2);
0326 if all(farel), return, end;
0327 nodes_test = Xnodes > xyz(1) + radius + th;
0328 farel = farel | all(nodes_test,2);
0329 if all(farel), return, end;
0330 nodes_test = Ynodes < xyz(2) - radius - th;
0331 farel = farel | all(nodes_test,2);
0332 if all(farel), return, end;
0333 nodes_test = Ynodes > xyz(2) + radius + th;
0334 farel = farel | all(nodes_test,2);
0335 if all(farel), return, end;
0336 if ~isempty(Znodes)
0337 nodes_test = Znodes > xyz(3) + radius + th;
0338 farel = farel | all(nodes_test,2);
0339 if all(farel), return, end;
0340 nodes_test = Znodes < xyz(3) - radius - th;
0341 farel = farel | all(nodes_test,2);
0342 if all(farel), return, end;
0343 end
0344 idx = find(~farel);
0345 end
0346
0347
0348
0349 function farel = close_elems(Xnodes,Ynodes,Znodes,xyz,radius, th)
0350
0351 farel = true(size(Xnodes,1),1);
0352
0353 nodes_test = Xnodes < xyz(1) + radius - th;
0354 farel = farel & all(nodes_test,2);
0355 if ~any(farel), return, end;
0356 nodes_test = Xnodes > xyz(1) - radius + th;
0357 farel = farel & all(nodes_test,2);
0358 if ~any(farel), return, end;
0359 nodes_test = Ynodes < xyz(2) + radius - th;
0360 farel = farel & all(nodes_test,2);
0361 if ~any(farel), return, end;
0362 nodes_test = Ynodes > xyz(2) - radius + th;
0363 farel = farel & all(nodes_test,2);
0364 if ~any(farel), return, end;
0365 if ~isempty(Znodes)
0366 nodes_test = Znodes > xyz(3) - radius + th;
0367 farel = farel & all(nodes_test,2);
0368 if ~any(farel), return, end;
0369 nodes_test = Znodes < xyz(3) + radius - th;
0370 farel = farel & all(nodes_test,2);
0371 if ~any(farel), return, end;
0372 end
0373 idx = find(farel);
0374 end
0375
0376
0377
0378
0379 function [xyz, radius, opt] = parse_opt(xyz, radius, opt)
0380
0381 scale_radius = false;
0382 if isempty(radius)
0383 radius = xyz(end,:);
0384 scale_radius = true;
0385 xyz(end,:) = [];
0386 end
0387
0388 if isfield(opt,'desired_img_radius')
0389 scale_radius = false;
0390 if isnumeric(opt.desired_img_radius)
0391 radius = opt.desired_img_radius;
0392 end
0393 if isa(opt.desired_img_radius, 'function_handle')
0394 radius = feval(opt.desired_img_radius,xyz);
0395 end
0396 end
0397
0398
0399
0400 mdl = opt.rec_model;
0401 opt.n_dim =mdl_dim(mdl);
0402 xyz = xyz(1:opt.n_dim, :);
0403
0404
0405
0406 opt.meshsz = [];
0407 try
0408 for i = 1:3
0409 opt.meshsz = [opt.meshsz min(mdl.nodes(:,i)) max(mdl.nodes(:,i))];
0410 end
0411 end
0412
0413 opt.n_dim = length(opt.meshsz)/2;
0414 opt.meshsz = reshape(opt.meshsz,2,[])';
0415
0416 opt.minpt = opt.meshsz(:,1);
0417 opt.maxpt = opt.meshsz(:,2);
0418 opt.range = opt.maxpt - opt.minpt;
0419 opt.maxrange = max(opt.range(1:2));
0420
0421
0422 xyz = 2*bsxfun(@minus, xyz, mean(opt.meshsz,2))/opt.maxrange;
0423 mdl.nodes = 2*bsxfun(@minus, mdl.nodes, mean(opt.meshsz(1:size(mdl.nodes,2),:),2)')/opt.maxrange;
0424 opt.rec_model = mdl;
0425 if scale_radius
0426 radius = 2*radius / opt.maxrange;
0427 end
0428
0429 if ~isfield(opt, 'steepness')
0430 opt.steepness = 10./radius;
0431 elseif isa(opt.steepness,'function_handle')
0432 opt.steepness = feval(opt.steepness,xyz);
0433 end
0434
0435 if numel(opt.steepness) == 1
0436 opt.steepness = ones(1,size(xyz,2)) * opt.steepness;
0437 end
0438
0439 if numel(radius) == 1
0440 radius = ones(1,size(xyz,2)) * radius;
0441 end
0442
0443 if opt.n_dim == 2
0444 xyz(3,:) = 0;
0445 end
0446
0447 if ~isfield(opt, 'threshold')
0448 opt.threshold = 1e-4;
0449 end
0450
0451 opt.threshold = log(1/opt.threshold - 1);
0452
0453 end
0454
0455
0456
0457 function do_unit_test
0458 eidors_cache clear_name GREIT_desired_img_sigmoid
0459 v = linspace(-1,1,32);
0460 mdl= mk_grid_model([],v,v,[0 .7 1:.2:2 2.3 3]);
0461 opt.rec_model = mdl;
0462 opt.steepness = @(xyz) 50./xyz(3,:);
0463 opt.desired_img_radius = @(xyz) xyz(3,:)/5;
0464
0465 xyzr(:,3) = .5:.5:2.5;
0466 xyzr(:,4) = .25;
0467 sol = GREIT_desired_img_sigmoid(xyzr',[],opt);
0468 img = mk_image(mdl,0);
0469 for i = 1:5
0470 subplot(2,3,i)
0471 img.elem_data= sol(:,i);
0472 show_3d_slices(img,xyzr(i,3),xyzr(i,2),xyzr(i,1));
0473 end
0474 eidors_msg('UNIT_TEST: Showed %d images to verify',i,0);
0475 eidors_cache on GREIT_desired_img_sigmoid
0476 end