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