0001 function img = inv_solve( inv_model, data1, data2)
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 if isstr(inv_model) && strcmp(inv_model,'UNIT_TEST'); do_unit_test; return; end
0053
0054 inv_model= eidors_model_params( inv_model );
0055 opts = parse_parameters( inv_model );
0056
0057 eidors_msg('inv_solve: %s', inv_model.solve,2);
0058
0059 if opts.abs_solve
0060 if nargin~=2;
0061 error('only one data set is allowed for a static reconstruction');
0062 end
0063
0064 imgc= feval( inv_model.solve, inv_model, ...
0065 filt_data(inv_model,data1) );
0066 else
0067 if nargin~=3;
0068 error('two data sets are required for a difference reconstruction');
0069 end
0070
0071
0072 data_width= max(num_frames(data1), num_frames(data2));
0073
0074 fdata1 = filt_data( inv_model, data1, data_width );
0075 fdata2 = filt_data( inv_model, data2, data_width );
0076
0077
0078 imgc= feval( inv_model.solve, inv_model, fdata1, fdata2);
0079 end
0080
0081 img = eidors_obj('image', imgc );
0082
0083
0084 if isfield(inv_model,'rec_model')
0085 img.fwd_model= inv_model.rec_model;
0086 end
0087
0088
0089 if opts.select_parameters;
0090 img.elem_data = img.elem_data( opts.select_parameters, :);
0091 end;
0092
0093 if ~opts.reconst_to_elems
0094 img.node_data= img.elem_data;
0095 img = rmfield(img,'elem_data');
0096 end
0097
0098
0099 try; img.elem_data = opts.offset + opts.scale * img.elem_data; end
0100 try; img.node_data = opts.offset + opts.scale * img.node_data; end
0101
0102 function opts = parse_parameters( imdl );
0103 if strcmp(imdl.reconst_type,'static') || ...
0104 strcmp(imdl.reconst_type,'absolute')
0105 opts.abs_solve = 1;
0106 elseif strcmp(imdl.reconst_type,'difference')
0107 opts.abs_solve = 0;
0108 else
0109 error('inv_model.reconst_type (%s) not understood', imdl.reconst_type);
0110 end
0111
0112 opts.select_parameters = [];
0113 try
0114 opts.select_parameters = imdl.inv_solve.select_parameters;
0115 end;
0116
0117 opts.reconst_to_elems = 1;
0118 try; if strcmp( imdl.reconst_to, 'nodes' )
0119 opts.reconst_to_elems = 0;
0120 end; end
0121
0122 opts.scale = 1;
0123 try; opts.scale = imdl.inv_solve.scale_solution.scale; end
0124
0125 opts.offset = 0;
0126 try; opts.offset = imdl.inv_solve.scale_solution.offset; end
0127
0128
0129
0130 function nf= num_frames(d0)
0131 if isnumeric( d0 )
0132 nf= size(d0,2);
0133 elseif d0(1).type == 'data';
0134 nf= size( horzcat( d0(:).meas ), 2);
0135 else
0136 error('Problem calculating number of frames. Expecting numeric or data object');
0137 end
0138
0139
0140 function d2= filt_data(inv_model, d0, data_width )
0141 if ~isnumeric( d0 )
0142
0143
0144 d1 = [];
0145 for i=1:length(d0)
0146 if strcmp( d0(i).type, 'data' )
0147 d1 = [d1, d0(i).meas];
0148 else
0149 error('expecting an object of type data');
0150 end
0151 end
0152
0153 else
0154
0155 d1 = d0;
0156 end
0157
0158 d1= double(d1);
0159
0160 if isfield(inv_model.fwd_model,'meas_select') && ...
0161 ~isempty(inv_model.fwd_model.meas_select)
0162
0163
0164 meas_select= inv_model.fwd_model.meas_select;
0165 if size(d1,1) == length(meas_select)
0166 d2= d1(meas_select,:);
0167 elseif size(d1,1) == sum(meas_select==1)
0168 d2= d1;
0169 else
0170 error('inconsistent difference data: (%d ~= %d). Maybe check fwd_model.meas_select', ...
0171 d2_width, data_width);
0172 end
0173 else
0174 d2= d1;
0175 end
0176
0177 if nargin==3
0178 d2_width= size(d2,2);
0179 if d2_width == data_width
0180
0181 elseif d2_width == 1
0182 d2= d2(:,ones(1,data_width));
0183 else
0184 error('inconsistent difference data: (%d ~= %d)', ...
0185 d2_width, data_width);
0186 end
0187 end
0188
0189
0190 function do_unit_test
0191 k=0; N=5; nd = 5;
0192
0193 imdl = mk_common_model('d2c2',16);
0194 imdl = select_imdl( imdl, {'Choose NF=2.5'});
0195 mvx = linspace(-0.8,0.8,nd);
0196 [vh,vi] = simulate_movement(mk_image(imdl), [mvx;0*mvx;0.05+0*mvx]);
0197
0198 img= inv_solve(imdl,vh,vi); img.show_slices.img_cols = 5;
0199 k=k+1; subplot(N,1,k); show_slices(img);
0200 unit_test_cmp('inv_solve: 1a', mean(img.elem_data), 3e-3, 1e-3);
0201 unit_test_cmp('inv_solve: 1b', std(img.elem_data), 1.5e-2, 1e-2);
0202
0203 vhm= eidors_obj('data','nn','meas',vh);
0204 img= inv_solve(imdl,vhm,vi);
0205 unit_test_cmp('inv_solve: 2a', mean(img.elem_data), 3e-3, 1e-3);
0206 unit_test_cmp('inv_solve: 2b', std(img.elem_data), 1.5e-2, 1e-2);
0207
0208 img= inv_solve(imdl,vh*ones(1,nd),vi);
0209 unit_test_cmp('inv_solve: 3a', mean(img.elem_data), 3e-3, 1e-3);
0210 unit_test_cmp('inv_solve: 3b', std(img.elem_data), 1.5e-2, 1e-2);
0211
0212 vim= eidors_obj('data','nn','meas',vi);
0213 img= inv_solve(imdl,vhm,vim);
0214 unit_test_cmp('inv_solve: 4a', mean(img.elem_data), 3e-3, 1e-3);
0215 unit_test_cmp('inv_solve: 4b', std(img.elem_data), 1.5e-2, 1e-2);
0216
0217 vhm= eidors_obj('data','nn','meas',vh*ones(1,nd));
0218 img= inv_solve(imdl,vhm,vi);
0219 unit_test_cmp('inv_solve: 5a', mean(img.elem_data), 3e-3, 1e-3);
0220 unit_test_cmp('inv_solve: 5b', std(img.elem_data), 1.5e-2, 1e-2);
0221
0222 vhm(1)= eidors_obj('data','nn','meas',vh*ones(1,2));
0223 vhm(2)= eidors_obj('data','nn','meas',vh*ones(1,nd-2));
0224 img= inv_solve(imdl,vhm,vi);
0225 unit_test_cmp('inv_solve: 6a', mean(img.elem_data), 3e-3, 1e-3);
0226 unit_test_cmp('inv_solve: 6b', std(img.elem_data), 1.5e-2, 1e-2);
0227
0228 vim(1)= eidors_obj('data','nn','meas',vi(:,1:3));
0229 vim(2)= eidors_obj('data','nn','meas',vi(:,4:end));
0230 img= inv_solve(imdl,vhm,vim);
0231 unit_test_cmp('inv_solve: 7a', mean(img.elem_data), 3e-3, 1e-3);
0232 unit_test_cmp('inv_solve: 7b', std(img.elem_data), 1.5e-2, 1e-2);
0233
0234 im2 = imdl; im2.inv_solve.select_parameters = 1:5;
0235 img= inv_solve(im2,vh,vi);
0236 unit_test_cmp('inv_solve: 10', size(img.elem_data), [5,nd]);
0237
0238
0239 im2 = imdl;
0240 im2.inv_solve.scale_solution.offset = 1;
0241 im2.inv_solve.scale_solution.scale = 2;
0242 img= inv_solve(im2,vh,vi); img.show_slices.img_cols = 5;
0243 unit_test_cmp('inv_solve: 20a', mean(img.elem_data), 1.006, 2e-3);
0244 unit_test_cmp('inv_solve: 20b', std(img.elem_data), 3e-2, 1e-2);
0245
0246 im2.inv_solve.scale_solution.offset = 0;
0247 d = interp_mesh( imdl.fwd_model); d= sqrt(sum(d.^2,2));
0248 im2.inv_solve.scale_solution.scale = spdiags(1-d,0,length(d),length(d));
0249 img= inv_solve(imdl,vh,vi); img.show_slices.img_cols = 5;
0250 k=k+1; subplot(N,1,k); show_slices(img);
0251
0252 im2 = select_imdl(imdl, {'Nodal GN dif'} );
0253 img= inv_solve(im2,vh,vi);
0254 unit_test_cmp('inv_solve: 30a', mean(img.node_data), 3e-3, 1e-3);
0255 unit_test_cmp('inv_solve: 30b', std(img.node_data), 1.5e-2, 1e-2);
0256
0257 im2.inv_solve.scale_solution.offset = 1;
0258 im2.inv_solve.scale_solution.scale = 2;
0259 img= inv_solve(im2,vh,vi); img.show_slices.img_cols = 5;
0260 unit_test_cmp('inv_solve: 31a', mean(img.node_data), 1.006, 2e-3);
0261 unit_test_cmp('inv_solve: 31b', std(img.node_data), 3e-2, 1.5e-2);
0262
0263 im2 = select_imdl(imdl, {'Basic GN abs'} );
0264 img= inv_solve(im2,vi(:,1));
0265 unit_test_cmp('inv_solve: 40a', mean(img.elem_data), 1.004, 1e-3);
0266 unit_test_cmp('inv_solve: 40b', std(img.elem_data), 1.5e-2, 1e-2);
0267
0268