0001 function [imdl,distr] = GREIT3D_distribution(fmdl, vopt)
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 if ischar(fmdl) && strcmp(fmdl,'UNIT_TEST'); do_unit_test; return; end
0049
0050 imdl = select_imdl(fmdl,{'Basic GN dif'});
0051 imdl = mk_voxel_volume(imdl,vopt);
0052 msm = imdl.rec_model.mdl_slice_mapper;
0053 imdl.rec_model.mdl_slice_mapper.y_pts = ...
0054 fliplr(imdl.rec_model.mdl_slice_mapper.y_pts);
0055
0056 [xpts, ypts, zpts] = downsample_distr(msm.x_pts, msm.y_pts, msm.z_pts, vopt);
0057
0058 [x, y, z] = ndgrid(xpts, ypts, zpts);
0059
0060
0061 IN = point_in_vox(imdl.rec_model,[x(:),y(:),z(:)]);
0062 INdesity = nnz(IN)/numel(IN);
0063 if INdesity==0
0064 error('GREIT3D_distribution: grid doesn''t match model');
0065 elseif INdesity<0.5
0066 eidors_msg('GREIT3D_distribution: grid only matches %3.1f%% of model', INdesity*100, 1);
0067 end
0068 distr = [x(IN),y(IN),z(IN)]';
0069
0070 function out = point_in_vox(fmdl,points, epsilon)
0071
0072 if nargin < 3
0073 epsilon = 0;
0074 end
0075
0076 levels = unique(fmdl.nodes(:,3));
0077 out = false(numel(points)/3,1);
0078
0079 opt.faces = true;
0080 fmdl = fix_model(fmdl, opt);
0081
0082 jnk.nodes = fmdl.nodes(:,1:2);
0083 jnk.type = 'fwd_model';
0084
0085 for i = 1:numel(levels)-1
0086 idx = (points(:,3) - levels(i)) > epsilon;
0087 idx = idx & ((levels(i+1) - points(:,3)) > epsilon);
0088
0089 nidx = fmdl.nodes(:,3) == levels(i);
0090 F = all(nidx(fmdl.faces),2);
0091 jnk.elems = fmdl.faces(F,:);
0092 bnd = find_boundary(jnk);
0093 bnd = order_loop(jnk.nodes(unique(bnd(:)),:));
0094 out(idx) = out(idx) | inpolygon(points(idx,1),points(idx,2),bnd(:,1),bnd(:,2));
0095 end
0096
0097 function [xpts, ypts, zpts] = downsample_distr(xpts, ypts, zpts, vopt)
0098 if ~isfield(vopt, 'downsample')
0099 return
0100 end
0101
0102 P = zeros(3,1);
0103 N = ones(3,1);
0104 switch numel(vopt.downsample)
0105 case {1, 2}
0106 N(:) = vopt.downsample(1);
0107 try P(:) = vopt.downsample(2); end
0108 case 3
0109 N(:) = vopt.downsample(:);
0110 case 6
0111 N(:) = vopt.downsample(:,1);
0112 P(:) = vopt.downsample(:,2);
0113 otherwise
0114 error('EIDORS:WrongInput','vopt.downsample is wrong size.')
0115 end
0116 xpts = downsample(xpts,N(1),P(1));
0117 ypts = downsample(ypts,N(2),P(2));
0118 zpts = downsample(zpts,N(3),P(3));
0119
0120
0121 function pts = downsample(pts, N, P)
0122
0123
0124 if nargin < 3, P = 0; end
0125 pts = pts(1+P:N:end);
0126
0127
0128
0129 function do_small_test
0130 fmdl= ng_mk_cyl_models([4,1],[16,1.5,2.5],[0.10]);
0131 fmdl= mystim_square(fmdl);
0132 vopt.imgsz = [16 16];
0133 vopt.zvec = linspace( 0.5,3.5,4);
0134 [imdl,opt.distr] = GREIT3D_distribution(fmdl, vopt);
0135 unit_test_cmp('Coarse1 size:', size(opt.distr),[3,672]);
0136 unit_test_cmp('Corase1 vals:', opt.distr(:,1),[-0.4375;-0.9375;1],1e-7);
0137
0138 vopt.zvec = linspace(-1,1,3);
0139 [imdl,opt.distr] = GREIT3D_distribution(fmdl, vopt);
0140 unit_test_cmp('Coarse2 size:', size(opt.distr),[3,224]);
0141 unit_test_cmp('Corase2 vals:', opt.distr(:,1),[-0.4375;-0.9375;0.5],1e-7);
0142
0143 vopt.zvec = linspace(-2,0,3);
0144 try
0145 get_error = 0;
0146 [imdl,opt.distr] = GREIT3D_distribution(fmdl, vopt);
0147 catch
0148 get_error = 1;
0149 end
0150 unit_test_cmp('Coarse3: got error', get_error,1)
0151
0152 function do_unit_test
0153 do_small_test
0154 [vh,vi] = test_fwd_solutions;
0155
0156 fmdl= ng_mk_cyl_models([4,1,.5],[16,1.5,2.5],[0.05]);
0157 fmdl= mystim_square(fmdl);
0158
0159 vopt.imgsz = [32 32];
0160 vopt.zvec = linspace( 0.5,3.5,7);
0161 vopt.save_memory = 1;
0162
0163 [imdl,opt.distr] = GREIT3D_distribution(fmdl, vopt);
0164 n_weight = 18.1608;
0165 imdl = mk_GREIT_model(imdl, 0.2, n_weight, opt);
0166
0167 unit_test_cmp('RM size', size(imdl.solve_use_matrix.RM), [5136,928]);
0168 tst = imdl.solve_use_matrix.RM(1,1:2);
0169
0170 tst_= [8.572908305490031 -18.600780994066596];
0171 tst_= [8.572908283730975 -18.600781037986948];
0172 unit_test_cmp('RM', tst, tst_, 1e-7);
0173
0174 img = inv_solve(imdl, vh, vi);
0175 unit_test_cmp('img size', size(img.elem_data), [5136,5]);
0176 [mm,ll] =max(img.elem_data(:,1));
0177 tst_ = [0.582158646727019 1308];
0178 tst_ = [0.582158646971746 1308];
0179 unit_test_cmp('img', [mm,ll], ...
0180 [0.582158646727019, 1308], 1e-8);
0181
0182 img.show_slices.img_cols = 1;
0183 subplot(131); show_fem(fmdl); title 'fmdl'
0184 subplot(132); show_slices(img,[inf,inf,2]); title 'centre';
0185 subplot(133); show_slices(img,[inf,inf,1.5]); title 'bottom';
0186
0187
0188 function fmdl = mystim_square(fmdl);
0189 [~,fmdl] = elec_rearrange([16,2],'square', fmdl);
0190 [fmdl.stimulation, fmdl.meas_select] = ...
0191 mk_stim_patterns(32,1,[0,5],[0,5],{},1);
0192
0193 function [vh,vi] = test_fwd_solutions;
0194 posns= linspace(1.0,3.0,5);
0195 str=''; for i=1:length(posns);
0196 extra{i} = sprintf('ball%03d',round(posns(i)*100));
0197 str = [str,sprintf('solid %s=sphere(0.5,0,%f;0.1); ', extra{i}, posns(i))];
0198 end
0199 extra{i+1} = str;
0200 fmdl= ng_mk_cyl_models([4,1,.2],[16,1.5,2.5],[0.05],extra);
0201 fmdl = mystim_square(fmdl);
0202
0203 img= mk_image(fmdl,1);
0204 vh = fwd_solve(img);
0205
0206 for i=1:length(posns);
0207 img= mk_image(fmdl,1);
0208 img.elem_data(fmdl.mat_idx{i+1}) = 2;
0209 vi{i} = fwd_solve(img);
0210 end;
0211 vi = [vi{:}];