0001 function img = inv_solve_d_bar(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 if ischar(inv_model) && strcmp(inv_model,'UNIT_TEST'); test_d_bar; return; end
0028
0029 citeme(mfilename);
0030
0031 fmdl = inv_model.fwd_model;
0032 n_elec = num_elecs(fmdl);
0033
0034 try
0035 trunc_rad = inv_model.hyperparameter.truncation_radius;
0036 grid_size = inv_model.hyperparameter.grid_size;
0037 catch
0038 error('This does not look like a valid d-bar model!')
0039 end
0040
0041
0042 stim_pattern_mat = create_stim_pattern_matrix(fmdl);
0043 stim_pattern_mat = stim_pattern_mat./sqrt(sum(stim_pattern_mat.^2,1));
0044
0045
0046 elec_pos_angle = get_elec_pos_angle(fmdl);
0047
0048
0049 M = 2^grid_size;
0050
0051 stepsize_grid = 2*trunc_rad/(M - 1);
0052 grid_base_vec = [-trunc_rad:stepsize_grid:trunc_rad];
0053 [K_x, K_y] = meshgrid(grid_base_vec);
0054
0055 K = K_x + 1i*K_y;
0056
0057 K_inside_R = K( abs(K) < trunc_rad);
0058
0059 del_L = dirichlet_neumann_difference(fmdl,data1,data2);
0060
0061
0062 t_aporx = zeros(length(K_inside_R),1);
0063 for i = 1:length(K_inside_R)
0064 k = K_inside_R(i);
0065 c_k = (full(stim_pattern_mat))'*exp(1i*k*exp(1i*elec_pos_angle));
0066 d_k = (full(stim_pattern_mat))'*exp(1i*conj(k)*conj(exp(1i*elec_pos_angle)));
0067
0068 t_aporx(i) = conj(d_k)'*(del_L*c_k);
0069 end
0070
0071
0072
0073 begin_Q = trunc_rad*((2*M - 1)/(M - 1));
0074 grid_vec_Q = [-begin_Q:2*trunc_rad/(M-1):begin_Q];
0075 [Q_x, Q_y] = meshgrid(grid_vec_Q);
0076 Q = Q_x + 1i*Q_y;
0077
0078
0079 smooth_zone_factor = 1/4;
0080
0081 G_bar = 1./(pi*Q);
0082
0083 G_bar(abs(Q) > trunc_rad*(2 + smooth_zone_factor)) = 0;
0084
0085 smooth_zone = abs(Q) > trunc_rad*(2) & abs(Q) < trunc_rad*(2 + smooth_zone_factor);
0086
0087 G_bar(smooth_zone) = G_bar(smooth_zone).*((trunc_rad*(2 + smooth_zone_factor) - abs(Q(smooth_zone)))/(trunc_rad*smooth_zone_factor));
0088
0089
0090 scat = zeros(size(K));
0091 rad_idx = abs(K) < trunc_rad;
0092 scat(rad_idx) = t_aporx;
0093 scat = padarray_EIDORS(scat, [M/2 M/2], 0, 'both');
0094
0095
0096
0097 G_bar_fft = fft2(fftshift(G_bar));
0098
0099
0100 T_R_first = scat./(4*pi*conj(Q));
0101
0102
0103
0104
0105 rad_idx_dbar = abs(Q) < trunc_rad;
0106
0107 num_pts_in_R = sum(rad_idx_dbar(:));
0108
0109
0110 right_side_eq = [ones(num_pts_in_R,1);zeros(num_pts_in_R,1)];
0111
0112 recon_cords = interp_mesh(fmdl);
0113
0114 recon_pts = recon_cords(:, 1) + 1i*recon_cords(:, 2);
0115 num_rec_pts = length(recon_pts);
0116
0117 mu_final = ones(num_rec_pts,1);
0118 iniguess = [ones(num_pts_in_R,1);zeros(num_pts_in_R,1)];
0119
0120
0121 middle_val = size(T_R_first, 1)/2;
0122
0123 for iii = 1:num_rec_pts
0124
0125 z = recon_pts(iii);
0126
0127
0128 T_R = T_R_first.*(exp(-1i*(Q*z+conj(Q*z))));
0129
0130
0131
0132
0133 [sol, ~] = gmres(@DB_oper_demyst, right_side_eq, 40, 1e-4, 450, [], [], iniguess, M*2, rad_idx_dbar, num_pts_in_R, 2*trunc_rad/(M - 1), G_bar_fft, T_R);
0134
0135
0136 mu = zeros(size(Q));
0137 mu(rad_idx_dbar) = sol(1:num_pts_in_R) + 1i*sol((num_pts_in_R+1):end);
0138
0139
0140 mu_final(iii) = mean([mu(middle_val,middle_val), mu(middle_val+1,middle_val), mu(middle_val, middle_val+1), mu(middle_val+1, middle_val+1)]);
0141
0142 end
0143 img = struct;
0144 img.name= ['solved by D-Bar'];
0145 img.elem_data = get_conductivity(mu_final);
0146 img.fwd_model= fmdl;
0147 end
0148
0149
0150 function stim_pattern_mat = create_stim_pattern_matrix(fmdl)
0151
0152
0153 n_elec = length(fmdl.electrode);
0154 stim_pattern_mat = zeros(n_elec, n_elec-1);
0155
0156 for i = 1:n_elec-1
0157 stim_pattern_mat(:, i) = full(fmdl.stimulation(i).stim_pattern);
0158 end
0159 end
0160
0161 function elec_pos_angle = get_elec_pos_angle(fmdl)
0162
0163 n_elec = length(fmdl.electrode);
0164 elec_pos_cart = zeros(n_elec, 2);
0165
0166 for i = 1:n_elec
0167 elec_pos_cart(i, :) = [mean(fmdl.nodes(fmdl.electrode(i).nodes, 1)), mean(fmdl.nodes(fmdl.electrode(i).nodes, 2))];
0168 end
0169
0170 elec_pos_cart = [elec_pos_cart(:, 1) - mean(elec_pos_cart(:, 1)), elec_pos_cart(:, 2) - mean(elec_pos_cart(:, 2))];
0171
0172 elec_pos_angle = atan2(elec_pos_cart(:, 2), elec_pos_cart(:, 1));
0173
0174 elec_pos_angle(elec_pos_angle < 0) = elec_pos_angle(elec_pos_angle < 0) + 2*pi;
0175 end
0176
0177 function B = padarray_EIDORS(A,padsize,padval,direction)
0178
0179 if nargin < 4
0180 direction = 'both';
0181 end
0182 if nargin < 3
0183 padval = 0;
0184 end
0185 if strcmp(direction,'both')
0186 B = padval*ones(size(A)+2*padsize);
0187 B(padsize(1)+1:end-padsize(1),padsize(2)+1:end-padsize(2)) = A;
0188 elseif strcmp(direction,'pre')
0189 B = padval*ones(size(A)+padsize);
0190 B(padsize(1)+1:end,padsize(2)+1:end) = A;
0191 elseif strcmp(direction,'post')
0192 B = padval*ones(size(A)+padsize);
0193 B(1:size(A,1),1:size(A,2)) = A;
0194 end
0195 end
0196
0197 function [conductivity] = get_conductivity(mu)
0198
0199
0200
0201
0202
0203 conductivity = real(mu.^2);
0204 end
0205
0206 function [fmdl, inv_model] = mk_dbar_model(num_electrs)
0207
0208
0209 fmdl = ng_mk_cyl_models(.5,[num_electrs,0.25],[0.075]);
0210 [stim, ~]= mk_stim_patterns(num_electrs, 1, '{trig}', '{mono}', {'meas_current'}, 0.1);
0211 fmdl.stimulation = stim;
0212
0213 fmdl_2d = ng_mk_cyl_models([0,1,0.05],[num_electrs,0],[0.075]);
0214 fmdl_2d.stimulation = stim;
0215
0216 inv_model = struct;
0217 inv_model.name = 'EIDORS D-Bar model';
0218 inv_model.solve = 'inv_solve_d_bar';
0219 inv_model.RtR_prior = 'eidors_default';
0220
0221
0222 inv_model.hyperparameter.truncation_radius = 3.0;
0223 inv_model.hyperparameter.grid_size = 5;
0224
0225 inv_model.jacobian_bkgnd = 1;
0226 inv_model.type = 'inv_model';
0227 inv_model.fwd_model = fmdl_2d;
0228 end
0229
0230 function result = DB_oper_demyst(sol, M, rad_idx_dbar, num_pts_in_R, h, G_bar_fft, TR)
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 sol_square = zeros(M, M);
0250 sol_square(rad_idx_dbar) = sol(1:num_pts_in_R) + 1i*sol((num_pts_in_R+1):end);
0251
0252
0253
0254 result = sol_square - h^2*ifft2(G_bar_fft .* fft2( TR.*conj(sol_square) ));
0255
0256
0257
0258 result = [real(result(rad_idx_dbar)); imag(result(rad_idx_dbar))];
0259 end
0260
0261 function test_d_bar
0262 [fmdl, inv_model] = mk_dbar_model(16);
0263
0264 img = mk_image(fmdl, 1);
0265 vh = fwd_solve(img);
0266 img_inh = set_test_target(img);
0267 vi = fwd_solve(img_inh);
0268
0269 img_solved = inv_solve(inv_model, vi, vh);
0270 show_fem(img_solved);
0271 end
0272
0273 function img_out = set_test_target(img)
0274 cog = interp_mesh(img.fwd_model, 0);
0275 tar_offset = 0.6;
0276 cog(:,1,:) = cog(:,1,:) - tar_offset;
0277 tar_rad = 0.3;
0278 idx_tar = cog(:,1,:).^2 + cog(:,2,:).^2 < tar_rad.^2;
0279 img.elem_data(idx_tar) = img.elem_data(1)*1.2;
0280 img_out = img;
0281 end