From b96820c0d69ba28eb0c1424926564c5c28d137ad Mon Sep 17 00:00:00 2001
From: Nicola Vigano <nicola.vigano@esrf.fr>
Date: Mon, 22 Feb 2016 17:03:57 +0100
Subject: [PATCH] GtOrientationSampling: added orientation-space shape
 functions generation for the sampled grid

Signed-off-by: Nicola Vigano <nicola.vigano@esrf.fr>
---
 zUtil_Deformation/GtOrientationSampling.m | 220 ++++++++++++++++++++++
 1 file changed, 220 insertions(+)

diff --git a/zUtil_Deformation/GtOrientationSampling.m b/zUtil_Deformation/GtOrientationSampling.m
index b7dbb170..fa0de10c 100644
--- a/zUtil_Deformation/GtOrientationSampling.m
+++ b/zUtil_Deformation/GtOrientationSampling.m
@@ -505,6 +505,226 @@ classdef GtOrientationSampling < handle
             end
         end
 
+        function sf = compute_shape_functions_w(self)
+        % FUNCTION sf = compute_shape_functions_w(self)
+        %
+
+            omstep = gtGetOmegaStepDeg(self.parameters, self.detector_index);
+
+            sub_space_size = self.stats.sampling.gaps;
+
+            % Let's first compute the W extent
+            half_rspace_sizes = sub_space_size / 2;
+
+            ref_inds = self.selected;
+            num_blobs = numel(ref_inds);
+
+            pl_samd = self.ref_gr.allblobs.plorig(self.ondet(self.included(ref_inds)), :);
+
+            g = gtMathsRod2OriMat(self.ref_gr.R_vector');
+            pl_cry = gtVectorLab2Cryst(pl_samd, g)';
+%             pl_labd = gtGeoSam2Lab(pl_samd, eye(3), self.parameters.labgeo, self.parameters.samgeo, true, false)';
+
+            fprintf('Computing bounds of W shape functions: ')
+            c = tic();
+            tot_orientations = numel(self.lattice.gr);
+
+            oris_bounds_size = [size(self.lattice.gr, 1), size(self.lattice.gr, 2), size(self.lattice.gr, 3)] + 1;
+            oris_lims_min = self.lattice.gr{1, 1, 1}.R_vector - half_rspace_sizes;
+            oris_lims_max = self.lattice.gr{end, end, end}.R_vector + half_rspace_sizes;
+
+            oris_steps_x = linspace(oris_lims_min(1), oris_lims_max(1), oris_bounds_size(1));
+            oris_steps_y = linspace(oris_lims_min(2), oris_lims_max(2), oris_bounds_size(2));
+            oris_steps_z = linspace(oris_lims_min(3), oris_lims_max(3), oris_bounds_size(3));
+
+            oris_bounds = cell(oris_bounds_size);
+            for dx = 1:oris_bounds_size(1)
+                for dy = 1:oris_bounds_size(2)
+                    for dz = 1:oris_bounds_size(3)
+                        r_vec = [oris_steps_x(dx), oris_steps_y(dy), oris_steps_z(dz)];
+                        oris_bounds{dx, dy, dz} = struct( ...
+                            'phaseid', self.ref_gr.phaseid, ...
+                            'center', self.ref_gr.center, 'R_vector', r_vec );
+                    end
+                end
+            end
+
+            chunk_size = 250;
+            for ii = 1:chunk_size:numel(oris_bounds)
+                end_chunk = min(ii+chunk_size, numel(oris_bounds));
+                num_chars_gr_ii = fprintf('%05d/%05d', ii, numel(oris_bounds));
+
+                oris_bounds(ii:end_chunk) = gtCalculateGrain_p( ...
+                    oris_bounds(ii:end_chunk), self.parameters, ...
+                    'ref_omind', self.ref_gr.allblobs.omind, ...
+                    'included', self.ondet(self.included) );
+
+                fprintf(repmat('\b', [1 num_chars_gr_ii]));
+            end
+            fprintf('Done in %g seconds.\n', toc(c))
+
+            ref_ws = self.ref_gr.allblobs.omega(self.ondet(self.included(ref_inds))) ./ omstep;
+
+            fprintf('Precomputing shared values..')
+            % There is no point in computing the same rotation matrices each
+            % time, so we pre compute them here and store them for later
+            c = tic();
+            % selecting Ws to find the interval
+            ori_bounds = [oris_bounds{:}];
+            allblobs = [ori_bounds(:).allblobs];
+            w_tabs_int = [allblobs(:).omega];
+            w_tabs_int = w_tabs_int(ref_inds, :) ./ omstep;
+            w_tabs_int = gtGrainAnglesTabularFix360deg(w_tabs_int, ref_ws, self.parameters);
+
+            lims_w_proj_int = [min(w_tabs_int, [], 2), max(w_tabs_int, [], 2)];
+            lims_w_proj_int = [floor(lims_w_proj_int(:, 1)), ceil(lims_w_proj_int(:, 2))];
+
+            w_tabs_int = reshape(w_tabs_int, [], oris_bounds_size(1), oris_bounds_size(2), oris_bounds_size(3));
+
+            precomp_matrix_prods = cell(num_blobs, 1);
+
+            rotcomp_z = gtMathsRotationMatrixComp([0, 0, 1]', 'col');
+
+            rotcomp_w = gtMathsRotationMatrixComp(self.parameters.labgeo.rotdir', 'col');
+
+            % Precomputing A matrix components for all the used omegas
+            for ii_b = 1:num_blobs
+                ws_lims = (lims_w_proj_int(ii_b, 1)-0.5):(lims_w_proj_int(ii_b, 2)+0.5);
+                ws_lims = ws_lims .* omstep;
+
+                rot_w = gtMathsRotationTensor(ws_lims, rotcomp_w);
+
+                beamdirs = self.parameters.labgeo.beamdir * reshape(rot_w, 3, []);
+                beamdirs = reshape(beamdirs, 3, [])';
+
+                Ac_part = beamdirs * rotcomp_z.cos;
+                As_part = beamdirs * rotcomp_z.sin;
+                Acc_part = beamdirs * rotcomp_z.const;
+
+                precomp_matrix_prods{ii_b} = struct( ...
+                    'w', [lims_w_proj_int(ii_b, 1) lims_w_proj_int(ii_b, 2)], ...
+                    'Ac', Ac_part, 'As', As_part, 'Acc', Acc_part );
+            end
+            fprintf('\b\b: Done in %g seconds.\n', toc(c))
+
+            space_res = self.estimate_maximum_resolution() ./ 5;
+            num_poins = max(ceil(sub_space_size ./ space_res), 5);
+            pos_x = linspace(-half_rspace_sizes(1), half_rspace_sizes(1), num_poins(1)+1);
+            pos_y = linspace(-half_rspace_sizes(2), half_rspace_sizes(2), num_poins(2)+1);
+
+            renorm_coeff = (pos_x(2) - pos_x(1)) * (pos_y(2) - pos_y(1)) / prod(sub_space_size);
+
+            % Forming the grid in orientation space, on the plane that is
+            % perpendicular to the axis of rotation (z-axis in the w case),
+            % where to sample the sub-regions of the orientation-space voxels
+            pos_x = (pos_x(1:end-1) + pos_x(2:end)) / 2;
+            pos_y = (pos_y(1:end-1) + pos_y(2:end)) / 2;
+
+            pos_x_exp = reshape(pos_x, 1, [], 1);
+            pos_x_exp = pos_x_exp(1, :, ones(1, num_poins(2)));
+            pos_y_exp = reshape(pos_y, 1, 1, []);
+            pos_y_exp = pos_y_exp(1, ones(1, num_poins(1)), :);
+            pos_z_exp = zeros(1, num_poins(1), num_poins(2));
+
+            sf = cell(tot_orientations, 1);
+
+            [o_x, o_y, o_z] = ind2sub(oris_bounds_size-1, 1:tot_orientations);
+
+            fprintf('Computing W shape functions: ')
+            c = tic();
+            for ii_g = 1:tot_orientations
+                if (mod(ii_g, chunk_size) == 1)
+                    num_chars = fprintf('%05d/%05d', ii_g, tot_orientations);
+                end
+
+                sf{ii_g}(1:num_blobs) = gtFwdSimBlobDefinition();
+
+                gr = self.lattice.gr{ii_g};
+
+                % Extracting ospace boundaries for the given voxel
+                w_tab_int = w_tabs_int(:, o_x(ii_g):o_x(ii_g)+1, o_y(ii_g):o_y(ii_g)+1, o_z(ii_g):o_z(ii_g)+1);
+                w_tab_int = reshape(w_tab_int, [], 8);
+
+                lims_w_proj_g_int = round([min(w_tab_int, [], 2), max(w_tab_int, [], 2)]);
+
+                % the extra index is needed for the last boundary point
+                As_inds = [ ...
+                    lims_w_proj_g_int(:, 1) - lims_w_proj_int(:, 1) ...
+                    lims_w_proj_g_int(:, 2) - lims_w_proj_int(:, 1) + 1] + 1;
+
+                % Forming the grid in orientation space, on the plane that is
+                % perpendicular to the axis of rotation (z-axis in the w case),
+                % where to sample the sub-regions of the orientation-space voxel
+                % that we want to integrate.
+                r_vecs = [pos_x_exp; pos_y_exp; pos_z_exp];
+                r_vecs = reshape(r_vecs, 3, []);
+                r_vecs = gr.R_vector(ones(1, size(r_vecs, 2)), :)' + r_vecs;
+
+                gs = gtMathsRod2OriMat(r_vecs);
+                % Unrolling and transposing the matrices at the same time
+                % because we need g^-1
+                gs = reshape(gs, 3, [])';
+
+                pls = gs * pl_cry;
+                pls = reshape(pls, 3, [], num_blobs);
+
+                ominds = gr.allblobs.omind(ref_inds);
+                ssp = ((ominds == 1) | (ominds == 2));
+                ss  = ssp - ~ssp;
+                sinths = ss .* gr.allblobs.sintheta(ref_inds);
+
+                % Apparently it is inverted, compared to the omega prediction
+                % function. Should be investigated
+                ssp = ~((ominds == 1) | (ominds == 3));
+                ss  = ssp - ~ssp;
+
+                for ii_b = 1:num_blobs
+                    A_inds = As_inds(ii_b, 1):As_inds(ii_b, 2);
+
+                    Ac_g_part = precomp_matrix_prods{ii_b}.Ac(A_inds, :);
+                    As_g_part = precomp_matrix_prods{ii_b}.As(A_inds, :);
+                    Acc_g_part = precomp_matrix_prods{ii_b}.Acc(A_inds, :);
+
+                    pls_blob = pls(:, :, ii_b);
+
+                    Ac = Ac_g_part * pls_blob;
+                    As = As_g_part * pls_blob;
+                    Acc = Acc_g_part * pls_blob;
+
+                    D = Ac .^ 2 + As .^ 2;
+
+                    CC = Acc + sinths(ii_b);
+                    DD = D - CC .^ 2;
+                    E  = sqrt(DD);
+                    ok = DD > 0;
+
+                    % finding what the positions in w-space, correspond to in
+                    % orientation-space, on the z-axis, at the sampled x and y
+                    % positions around in the considered volume.
+                    d = (-As + ss(ii_b) .* ok .* E) ./ (CC - Ac);
+
+                    upper_limits = min(d(2:end, :), half_rspace_sizes(3));
+                    lower_limits = max(d(1:end-1, :), -half_rspace_sizes(3));
+
+                    % integration is simple and linear: for every w and
+                    % xy-position, we consider the corresponding segment on the
+                    % z-direction
+                    ints = upper_limits - lower_limits;
+                    ints(ints < 0) = 0;
+                    ints = sum(ints, 2);
+                    ints = reshape(ints, 1, 1, []);
+
+                    sf{ii_g}(ii_b).bbwim = lims_w_proj_g_int(ii_b, :);
+                    sf{ii_g}(ii_b).intm = renorm_coeff * ints;
+                    sf{ii_g}(ii_b).bbsize = [1, 1, numel(ints)];
+                end
+                if (mod(ii_g, chunk_size) == 1)
+                    fprintf(repmat('\b', [1, num_chars]));
+                end
+            end
+            fprintf('Done in %g seconds.\n', toc(c))
+        end
+
         function resolution = estimate_maximum_resolution(self)
             sel = self.ondet(self.included(self.selected));
 
-- 
GitLab