0001 function [vh,vi,xyzr_pt]= simulate_3d_movement( n_sims, mdl_3d, rad_pr,movefcn )
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 if nargin <1
0034 n_sims = 200;
0035 end
0036
0037 if nargin<2 || isempty(mdl_3d)
0038 mdl_3d= mk_common_model('n3r2',[16,2]);
0039 mdl_3d= mdl_3d.fwd_model;
0040 end
0041
0042 if nargin<3 || isempty(rad_pr);
0043 rad_pr= [2/3, 0.05, 0.1, 0.9];
0044 end
0045
0046 if nargin<4
0047 movefcn = 1;
0048 end
0049 if isnumeric(movefcn)
0050 if movefcn==1
0051 movefcn = @helical_path;
0052 elseif movefcn==2
0053 movefcn = @radial_path;
0054 else
0055 error('value of movefcn not understood');
0056 end
0057 else
0058
0059 end
0060
0061
0062 if 0
0063 mdl_3d.solve= 'np_fwd_solve';
0064 mdl_3d.system_mat= 'np_calc_system_mat';
0065 mdl_3d.jacobian= 'np_calc_jacobian';
0066 mdl_3d.misc.perm_sym= '{n}';
0067 n_elems= size(mdl_3d.elems,1);
0068 end
0069
0070
0071 eidors_msg('simulate_3d_movement: step #1: homogeneous simulation',2);
0072
0073 sigma= ones( size(mdl_3d.elems,1) ,1);
0074 img= eidors_obj('image', 'homogeneous image', ...
0075 'elem_data', sigma, ...
0076 'fwd_model', mdl_3d );
0077 vh = fwd_solve( img);
0078
0079 eidors_msg('simulate_3d_movement: step #2: find points',2);
0080
0081 if 0
0082 npx=128;
0083 npy=128;
0084 npz=64;
0085 [radius,rp,z0,zt,x,y,z] = calc_point_grid(mdl_3d.nodes', rad_pr, npx, npy, npz);
0086
0087 clear pts;
0088 for i=1:n_sims
0089 f_frac= (i-1)/n_sims;
0090
0091
0092 [xp,yp,zp]= feval(movefcn, f_frac, radius, z0,zt);
0093
0094 ff= find( (x(:)-xp).^2 + (y(:)-yp).^2 + (z(:)-zp).^2 <= rp^2 )';
0095 pts{i} = ff;
0096 end
0097 pts_all = unique( [pts{:}] );
0098 pts_all = pts_all(:);
0099 for i=1:n_sims
0100 [jnk,idx_i]= intersect( pts_all, pts{i});
0101 pts_idx{i}= idx_i;
0102 end
0103
0104 [eptr,vol]= img_mapper3a(mdl_3d.nodes', mdl_3d.elems', ...
0105 x(pts_all), y(pts_all), z(pts_all));
0106 else
0107 mdl_pts = interp_mesh( mdl_3d, 2);
0108 x= mdl_pts(:,1,:);
0109 y= mdl_pts(:,2,:);
0110 z= mdl_pts(:,3,:);
0111 [radius,rp,z0,zt] = calc_point_grid(mdl_3d.nodes', rad_pr);
0112 end
0113
0114 target_conductivity= .1;
0115
0116 for i=1:n_sims
0117 if rem(i, max( floor(i/10), 10))==1; eidors_msg( ...
0118 'simulate_3d_movement: step #3 (%d of %d): target simulations', ...
0119 i, n_sims, 2);
0120 end
0121 if 0
0122 obj_n= sparse( eptr(pts_idx{i}),1,1, n_elems, 1);
0123 img.elem_data= 1 + target_conductivity * obj_n./vol;
0124
0125 else
0126 f_frac= (i-1)/n_sims;
0127 [xp,yp,zp]= feval(movefcn, f_frac, radius, z0,zt);
0128 ff= (x-xp).^2 + (y-yp).^2 + (z-zp).^2 <= rp^2;
0129 img.elem_data= 1 + target_conductivity * mean(ff,3);
0130 end
0131
0132 xyzr_pt(:,i)= [xp;-yp;zp;rp];
0133 vi(i)= fwd_solve( img );
0134 end
0135
0136 vi= [vi(:).meas];
0137 vh= [vh(:).meas];
0138
0139
0140
0141
0142 function [xp,yp,zp]= helical_path(f_frac, radius, z0,zt);
0143 xp= radius * cos(f_frac*2*pi);
0144 yp= radius * sin(f_frac*2*pi);
0145
0146 zp = z0 + (zt - z0) * f_frac;
0147
0148
0149 function [xp,yp,zp]= radial_path(f_frac, radius, z0,zt);
0150 rp= f_frac*radius;
0151 cv= 2*pi*f_frac;
0152 xp= rp * cos(cv);
0153 yp= rp * sin(cv);
0154 zp = mean([zt,z0]);
0155
0156
0157
0158
0159 function [EPTR, VOL] = img_mapper3a(NODE, ELEM, x,y,z );
0160
0161 elems = size(ELEM,2);
0162
0163 EPTR= zeros(prod(size(x)),1);
0164 VOL= zeros(elems,1);
0165
0166 for j= 1: elems
0167 if rem(j,5000)==0; fprintf('mapping %d / %d \n',j,elems); end
0168 xyz= NODE(:,ELEM(:,j))';
0169 min_x= min(xyz(:,1)); max_x= max(xyz(:,1));
0170 min_y= min(xyz(:,2)); max_y= max(xyz(:,2));
0171 min_z= min(xyz(:,3)); max_z= max(xyz(:,3));
0172
0173
0174 VOL(j)= abs(det(xyz'*[-1,1,0,0;-1,0,1,0;-1,0,0,1]'));
0175
0176 xlmax= x<=max_x; if ~any(xlmax); continue; end
0177 xgmin= x>=min_x; if ~any(xgmin); continue; end
0178 ylmax= y<=max_y; if ~any(ylmax); continue; end
0179 ygmin= y>=min_y; if ~any(ygmin); continue; end
0180 zlmax= z<=max_z; if ~any(zlmax); continue; end
0181 zgmin= z>=min_z; if ~any(zgmin); continue; end
0182
0183
0184 endr=find( xlmax & xgmin & ylmax & ygmin & zlmax & zgmin);
0185 ll= prod(size(endr));
0186 if isempty(ll);
0187 continue;
0188 end
0189
0190 nn= size(ELEM,1);
0191 vol=zeros(ll,nn);
0192 for i=1:nn
0193 i1= i; i2= rem(i,nn)+1; i3= rem(i+1,nn)+1;
0194 x1= xyz(i1,1)-x(endr); y1= xyz(i1,2)-y(endr); z1= xyz(i1,3)-z(endr);
0195 x2= xyz(i2,1)-x(endr); y2= xyz(i2,2)-y(endr); z2= xyz(i2,3)-z(endr);
0196 x3= xyz(i3,1)-x(endr); y3= xyz(i3,2)-y(endr); z3= xyz(i3,3)-z(endr);
0197 vol(:,i)= x1.*y2.*z3 - x1.*y3.*z2 - x2.*y1.*z3 + ...
0198 x3.*y1.*z2 + x2.*y3.*z1 - x3.*y2.*z1;
0199 end
0200
0201 endr( sum(abs(vol),2) - VOL(j) >1e-8 )=[];
0202 EPTR(endr)= j;
0203 end
0204
0205 function [radius, rp, zmin, zmax,x,y,z] = ...
0206 calc_point_grid(NODE, rad_pr, npx, npy, npz);
0207
0208 xmin = min(NODE(1,:)); xmax = max(NODE(1,:));
0209 xmean= mean([xmin,xmax]); xrange= xmax-xmin;
0210
0211 ymin = min(NODE(2,:)); ymax = max(NODE(2,:));
0212 ymean= mean([ymin,ymax]); yrange= ymax-ymin;
0213
0214 zmin = min(NODE(3,:)); zmax = max(NODE(3,:));
0215 zmean= mean([zmin,zmax]); zrange= zmax-zmin;
0216
0217 radius= rad_pr(1)*(xmax-xmin)/2;
0218 rp= rad_pr(2)*(xmax-xmin)/2;
0219 zmin= (rad_pr(3)-.5)*zrange + zmean;
0220 zmax= (rad_pr(4)-.5)*zrange + zmean;
0221
0222 if nargout<=4; return; end
0223 range= max([xrange, yrange,zrange]);
0224 [x y z]=ndgrid( ...
0225 linspace( xmean - range*0.5, xmean + range*0.5, npx ), ...
0226 linspace( ymean + range*0.5, ymean - range*0.5, npy ),...
0227 linspace( zmean - zrange*0.5, zmean + zrange*0.5, npz ));