From fbc0cfb847d55ed0bd7a8db85b10258b0acf782e Mon Sep 17 00:00:00 2001 From: Nicola Vigano <nicola.vigano@esrf.fr> Date: Tue, 23 Feb 2016 18:55:14 +0100 Subject: [PATCH] ODF-uvw-solver: added use of w-shape-functions Signed-off-by: Nicola Vigano <nicola.vigano@esrf.fr> --- zUtil_Deformation/GtGrainODFuvwSolver.m | 193 ++++++++++++++++++++++-- 1 file changed, 178 insertions(+), 15 deletions(-) diff --git a/zUtil_Deformation/GtGrainODFuvwSolver.m b/zUtil_Deformation/GtGrainODFuvwSolver.m index 54c7128d..5058697f 100644 --- a/zUtil_Deformation/GtGrainODFuvwSolver.m +++ b/zUtil_Deformation/GtGrainODFuvwSolver.m @@ -19,14 +19,31 @@ classdef GtGrainODFuvwSolver < GtGrainODFwSolver blob_dephs = arrayfun(@(x)size(x.intm, 3), bls); blob_dephs = reshape(blob_dephs, [], 1); - delta_omegas = self.sampler.get_omega_deviations(); + blob_lims = cat(1, bls(:).bbwim); + + with_shape_functions = ~isempty(self.shape_functions); + if (with_shape_functions) + for ii = numel(self.shape_functions):-1:1 + proj_lims(:, :, ii) = cat(1, self.shape_functions{ii}(:).bbwim); + end + proj_lims = [min(proj_lims(:, 1, :), [], 3), max(proj_lims(:, 2, :), [], 3)]; + + delta_omegas = proj_lims(:, 2) - proj_lims(:, 1) + 1; + else + [delta_omegas, proj_lims] = self.sampler.get_omega_deviations(with_shape_functions); + end chosen_depts = max(blob_dephs, delta_omegas(self.sampler.selected)); num_ws = max(chosen_depts) + 2; self.size_sino = [size(bls(1).intm, 1), size(bls(1).intm, 2), num_ws, num_blobs]; self.sino = zeros(self.size_sino); - self.pre_paddings = floor((num_ws - blob_dephs) / 2) + 1; + + % In the case that the sampled orientations determine the shift, we + % have to take it into account! + additional_shift = blob_lims(:, 1) - proj_lims(:, 1); + additional_shift(additional_shift < 0) = 0; + self.pre_paddings = floor((num_ws - chosen_depts) / 2) + 1 + additional_shift; for ii_b = 1:num_blobs ints_interval = self.pre_paddings(ii_b):(self.pre_paddings(ii_b) + blob_dephs(ii_b) -1); @@ -69,11 +86,16 @@ classdef GtGrainODFuvwSolver < GtGrainODFwSolver end end - function build_projection_matrices(self) - bls = self.sampler.bl(self.sampler.selected); + function build_projection_matrices_sf_none(self) + ref_gr = self.sampler.get_reference_grain(); + ref_omind = ref_gr.allblobs.omind; + ref_inc = self.sampler.ondet(self.sampler.included); + ref_sel = self.sampler.selected; + + om_step = gtGetOmegaStepDeg(self.parameters, self.sampler.detector_index); + + bls = self.sampler.bl(ref_sel); - fprintf('Computing projection matrices: ') - c = tic(); num_ws = self.get_num_ws(); bls_bbws = cat(1, bls(:).bbwim); @@ -99,19 +121,15 @@ classdef GtGrainODFuvwSolver < GtGrainODFwSolver self.St = cell(num_voxels, 1); shift_grs = cell(num_voxels, 1); - ref_gr = self.sampler.get_reference_grain(); - % computing shifts for ii_v = 1:num_voxels shift_grs{ii_v} = ref_gr; shift_grs{ii_v}.center = self.voxel_centers(ii_v, :); end - ref_omind = ref_gr.allblobs.omind; - ref_inc = self.sampler.ondet(self.sampler.included); shift_grs = gtCalculateGrain_p(shift_grs, self.parameters, ... 'ref_omind', ref_omind, 'included', ref_inc); - ref_uv = ref_gr.allblobs.detector(det_ind).uvw(ref_inc(self.sampler.selected), 1:2); + ref_uv = ref_gr.allblobs.detector(det_ind).uvw(ref_inc(ref_sel), 1:2); for ii_v = 1:num_voxels b_us = []; @@ -121,14 +139,14 @@ classdef GtGrainODFuvwSolver < GtGrainODFwSolver b_is = []; b_os = []; - shift_uv = shift_grs{ii_v}.allblobs.detector(det_ind).uvw(bl_selected, 1:2) - ref_uv; + shift_uv = shift_grs{ii_v}.allblobs.detector(det_ind).uvw(ref_sel, 1:2) - ref_uv; num_chars = fprintf('%03d/%03d', ii_v, num_voxels); for ii_o = 1:num_orients ab = grid_gr{ii_o}.allblobs; % W part - ws = ab.omega(self.sampler.selected) / om_step; + ws = ab.omega(ref_sel) / om_step; min_ws = floor(ws); max_ws = min_ws + 1; @@ -137,7 +155,7 @@ classdef GtGrainODFuvwSolver < GtGrainODFwSolver min_w_cs = 1 - max_w_cs; % UV part - uv = ab.detector(det_ind).uvw(self.sampler.selected, 1:2) + shift_uv; + uv = ab.detector(det_ind).uvw(ref_sel, 1:2) + shift_uv; num_pos = size(uv, 1); min_uvs = floor(uv); @@ -202,7 +220,152 @@ classdef GtGrainODFuvwSolver < GtGrainODFwSolver fprintf(repmat('\b', [1 num_chars])); end - fprintf('Done in %f seconds.\n', toc(c)); + end + + function build_projection_matrices_sf_w(self) + ref_gr = self.sampler.get_reference_grain(); + ref_omind = ref_gr.allblobs.omind; + ref_inc = self.sampler.ondet(self.sampler.included); + ref_sel = self.sampler.selected; + + bls = self.sampler.bl(self.sampler.selected); + + num_ws = self.get_num_ws(); + bls_bbws = cat(1, bls(:).bbwim); + min_w_conds = bls_bbws(:, 1) - self.pre_paddings + 1; + max_w_conds = min_w_conds + num_ws - 1; + + bls_bbus = cat(1, bls(:).bbuim); + bls_bbvs = cat(1, bls(:).bbvim); + + grid_gr = self.sampler.get_orientations(); + num_orients = numel(grid_gr); + + det_ind = self.sampler.detector_index; + + % We make now the approximation that by moving in XYZ inside the + % sample, the projection moves like if the incidence was always + % perpendicular. In reality, given small tilts of the detector or + % small scattering angles, this is hardly violated. + self.chose_voxel_centers(); + + num_voxels = size(self.voxel_centers, 1); + self.S = cell(num_voxels, 1); + self.St = cell(num_voxels, 1); + + shift_grs = cell(num_voxels, 1); + + % computing shifts + for ii_v = 1:num_voxels + shift_grs{ii_v} = ref_gr; + shift_grs{ii_v}.center = self.voxel_centers(ii_v, :); + end + shift_grs = gtCalculateGrain_p(shift_grs, self.parameters, ... + 'ref_omind', ref_omind, 'included', ref_inc); + + ref_uv = ref_gr.allblobs.detector(det_ind).uvw(ref_inc(ref_sel), 1:2); + + fprintf('\b\b: ') + + for ii_v = 1:num_voxels + b_us = []; + b_vs = []; + b_ws = []; + b_cs = []; + b_is = []; + b_os = []; + + shift_uv = shift_grs{ii_v}.allblobs.detector(det_ind).uvw(ref_sel, 1:2) - ref_uv; + + num_chars = fprintf('%03d/%03d', ii_v, num_voxels); + + for ii_o = 1:num_orients + ab = grid_gr{ii_o}.allblobs; + sf = self.shape_functions{ii_o}; + + w_cs = cat(3, sf(:).intm); + w_cs = reshape(w_cs, [], 1); + + num_blobs = numel(sf); + ws = cell(num_blobs, 1); + w_is = cell(num_blobs, 1); + for ii_b = 1:num_blobs + ws{ii_b} = sf(ii_b).bbwim(1):sf(ii_b).bbwim(2); + w_is{ii_b} = ii_b(ones(sf(ii_b).bbsize(3), 1)); + end + + ws = reshape([ws{:}], [], 1); + w_is = cat(1, w_is{:}); + + % UV part + uv = ab.detector(det_ind).uvw(ref_sel, 1:2) + shift_uv; + + min_uvs = floor(uv); + max_uvs = min_uvs + 1; + + max_uv_cs = uv - min_uvs; + min_uv_cs = 1 - max_uv_cs; + + % Acceptance criteria + ok_u_mins = (min_uvs(:, 1) >= bls_bbus(:, 1)) & (min_uvs(:, 1) <= bls_bbus(:, 2)); + ok_u_maxs = (max_uvs(:, 1) >= bls_bbus(:, 1)) & (max_uvs(:, 1) <= bls_bbus(:, 2)) & (max_uv_cs(:, 1) > eps('single')); + + ok_v_mins = (min_uvs(:, 2) >= bls_bbvs(:, 1)) & (min_uvs(:, 2) <= bls_bbvs(:, 2)); + ok_v_maxs = (max_uvs(:, 2) >= bls_bbvs(:, 1)) & (max_uvs(:, 2) <= bls_bbvs(:, 2)) & (max_uv_cs(:, 2) > eps('single')); + + u_oks = [ok_u_mins, ok_u_maxs]; + v_oks = [ok_v_mins, ok_v_maxs]; + + u_cs = [min_uv_cs(:, 1), max_uv_cs(:, 1)]; + v_cs = [min_uv_cs(:, 2), max_uv_cs(:, 2)]; + + pos_us = [(min_uvs(:, 1) - bls_bbus(:, 1) + 1), (max_uvs(:, 1) - bls_bbus(:, 1) + 1)]; + pos_vs = [(min_uvs(:, 2) - bls_bbvs(:, 1) + 1), (max_uvs(:, 2) - bls_bbvs(:, 1) + 1)]; + pos_ws = ws - min_w_conds(w_is) + 1; + + uvw_oks = u_oks(w_is, [1 1 2 2]) & v_oks(w_is, [1 2 1 2]); + uvw_cs = u_cs(w_is, [1 1 2 2]) .* v_cs(w_is, [1 2 1 2]) .* w_cs(:, [1 1 1 1]); + + pos_us = pos_us(w_is, [1 1 2 2]); + pos_vs = pos_vs(w_is, [1 2 1 2]); + pos_ws = pos_ws(:, [1 1 1 1]); + + indx = find(uvw_oks); + indx_mod = mod(indx - 1, numel(w_is)) + 1; + + wrong_w = ws < min_w_conds(w_is) | ws > max_w_conds(w_is); + if (any(wrong_w)) + ii_o + find(wrong_w) + [min_w_conds(w_is(wrong_w)), ws(wrong_w), max_w_conds(w_is(wrong_w)), ... + (max_w_conds(w_is(wrong_w)) - min_w_conds(w_is(wrong_w)) + 1), ... + (ws(wrong_w) - min_w_conds(w_is(wrong_w)) + 1) ] + end + + b_us = [b_us; pos_us(indx)]; + b_vs = [b_vs; pos_vs(indx)]; + b_ws = [b_ws; pos_ws(indx)]; + + b_cs = [b_cs; uvw_cs(indx)]; + + b_is = [b_is; w_is(indx_mod)]; + b_os = [b_os; ii_o(ones(numel(indx), 1))]; + end + +% sino_indx = sub2ind(self.size_sino, b_us, b_vs, b_ws, b_is); + sino_indx = b_us ... + + self.size_sino(1) * (b_vs - 1 ... + + self.size_sino(2) * (b_ws - 1 ... + + self.size_sino(3) * (b_is - 1))); + + self.S{ii_v} = sparse( ... + sino_indx, b_os, b_cs, ... + numel(self.sino), num_orients); + + self.St{ii_v} = self.S{ii_v}'; + + fprintf(repmat('\b', [1 num_chars])); + end end function vol = get_volume(self) -- GitLab