From 8d42d06e85593526772db81338ecc8152dc192dc Mon Sep 17 00:00:00 2001 From: Nicola Vigano <nicola.vigano@esrf.fr> Date: Fri, 6 May 2016 18:20:09 +0200 Subject: [PATCH] 6D-reconstruction: enabling ospace-super-sampling with the use of W-shape-functions Signed-off-by: Nicola Vigano <nicola.vigano@esrf.fr> --- zUtil_Deformation/Gt6DBlobReconstructor.m | 28 ++++++-- .../Gt6DReconstructionAlgorithmFactory.m | 44 ++++++++++-- zUtil_Deformation/GtOrientationSampling.m | 28 +++++--- .../gtDefShapeFunctionsCreateW.m | 70 ++++++++++++++----- 4 files changed, 133 insertions(+), 37 deletions(-) diff --git a/zUtil_Deformation/Gt6DBlobReconstructor.m b/zUtil_Deformation/Gt6DBlobReconstructor.m index c1a352c0..1fdf06b9 100644 --- a/zUtil_Deformation/Gt6DBlobReconstructor.m +++ b/zUtil_Deformation/Gt6DBlobReconstructor.m @@ -289,10 +289,18 @@ classdef Gt6DBlobReconstructor < Gt6DVolumeToBlobProjector num_bytes = 0; float_bytes = GtBenchmarks.getSizeVariable(zeros(1, 1, 'single')); num_geoms = self.get_number_geometries(); - for n = 1:num_geoms - sinogram_size = [ ... - self.proj_size(1), size(self.geometries{n}, 1), self.proj_size(2)]; - num_bytes = num_bytes + float_bytes * prod(sinogram_size); + if (isempty(self.ss_geometries)) + for n = 1:num_geoms + sinogram_size = [ ... + self.proj_size(1), size(self.geometries{n}, 1), self.proj_size(2)]; + num_bytes = num_bytes + float_bytes * prod(sinogram_size); + end + else + for n = 1:num_geoms + sinogram_size = [ ... + self.proj_size(1), size(self.ss_geometries{n}, 1), self.proj_size(2)]; + num_bytes = num_bytes + float_bytes * prod(sinogram_size); + end end end end @@ -514,8 +522,16 @@ classdef Gt6DBlobReconstructor < Gt6DVolumeToBlobProjector fprintf(' + Backprojecting ones sinos (fake bproj)..'); c = tic(); num_geoms = self.get_number_geometries(); - for ii = 1:num_geoms - self.bwd_weights{ii} = size(self.geometries{ii}, 1); + if (~isempty(self.geometries)) + for ii = 1:num_geoms + self.bwd_weights{ii} = size(self.geometries{ii}, 1); + end + else + % If this happens we are using oversampling with + % shape-functions + for ii = 1:num_geoms + self.bwd_weights{ii} = numel(self.blobs); + end end fprintf('\b\b (%2.1f s)\n', toc(c)); end diff --git a/zUtil_Deformation/Gt6DReconstructionAlgorithmFactory.m b/zUtil_Deformation/Gt6DReconstructionAlgorithmFactory.m index 694214bf..0142bee3 100644 --- a/zUtil_Deformation/Gt6DReconstructionAlgorithmFactory.m +++ b/zUtil_Deformation/Gt6DReconstructionAlgorithmFactory.m @@ -447,11 +447,18 @@ classdef Gt6DReconstructionAlgorithmFactory < handle sel_allb_idxs = sampler.ondet(sampler.included(sel_bls)); omegas = ref_gr.allblobs.omega(sel_allb_idxs); - orients = sampler.get_orientations(); - orients = [orients{:}]; + [orients, orients_ss] = sampler.get_orientations(); + + num_ospace_oversampling = prod(sampler.ss_factor); + if (num_ospace_oversampling == 1) + ors_struct = [orients{:}]; + else + ors_struct = cat(4, orients_ss{:}); + ors_struct = [ors_struct{:}]; + end % Array of structures that contain all the info relative to % each orientation, for each blob - grains_props = self.get_selected_props(orients, sel_bls); + grains_props = self.get_selected_props(ors_struct, sel_bls); [w_tab, ref_ws] = self.get_shape_funcs_w_tab(shape_funcs, omegas); [lims_blobs_w, lims_projs_w, paddings, ext_blobs_w_orig] = self.get_blob_lims(w_tab, bl, ref_ws); @@ -494,14 +501,39 @@ classdef Gt6DReconstructionAlgorithmFactory < handle psf = {}; end + tot_orient = sampler.get_total_num_orientations(); + if (num_ospace_oversampling == 1) + geometries_ss = {}; + offsets_ss = {}; + else + geometries = reshape(geometries, num_ospace_oversampling, []); + offsets = reshape(offsets, num_ospace_oversampling, []); + + geometries_ss = cell(tot_orient, 1); + offsets_ss = cell(tot_orient, 1); + for ii = 1:tot_orient + geometries_ss{ii} = geometries(:, ii); + + % merging all the orientation-space super-sampling + % projection coefficients into one structure per + % orientation. This is needed in order to fwd/bwd-project + % all the different sub-orientations together. + offsets_ss{ii} = self.merge_offsets(offsets(:, ii)); + end + + geometries = {}; + offsets = {}; + end + algo_params = struct( ... 'blobs', {blobs}, ... 'geometries', {geometries}, ... 'offsets', {offsets}, ... - 'geometries_ss', {{}}, ... - 'offsets_ss', {{}}, ... + 'geometries_ss', {geometries_ss}, ... + 'offsets_ss', {offsets_ss}, ... 'psf', {psf}, ... - 'good_orients', {true(1, numel(geometries))} ); + 'blobs_w_lims', lims_blobs_w, ... + 'good_orients', {true(1, tot_orient)} ); end function [sub_blob_slices, proj_coeffs] = get_sub_blobs(self, blobs, slices_interp, padding) diff --git a/zUtil_Deformation/GtOrientationSampling.m b/zUtil_Deformation/GtOrientationSampling.m index f544e63a..e8344cba 100644 --- a/zUtil_Deformation/GtOrientationSampling.m +++ b/zUtil_Deformation/GtOrientationSampling.m @@ -197,15 +197,24 @@ classdef GtOrientationSampling < handle gr = self.lattice(ii_o).gr{ii_g}; beg_pos = gr.R_vector - half_voxel_size + half_steps; end_pos = gr.R_vector + half_voxel_size - half_steps; - gr_ss = {}; - for ii_x = beg_pos(1):steps(1):end_pos(1) - for ii_y = beg_pos(2):steps(2):end_pos(2) - for ii_z = beg_pos(3):steps(3):end_pos(3) - gr_ss{end+1} = struct( ... - 'R_vector', {[ii_x, ii_y, ii_z]}, ... + + range_x = beg_pos(1):steps(1):end_pos(1); + range_y = beg_pos(2):steps(2):end_pos(2); + range_z = beg_pos(3):steps(3):end_pos(3); + + gr_ss = cell(self.ss_factor); + for ii_z = 1:self.ss_factor(3) + for ii_y = 1:self.ss_factor(2) + r_vecs = [ ... + range_x', ... + range_y(ii_y) * ones(self.ss_factor(1), 1), ... + range_z(ii_z) * ones(self.ss_factor(1), 1)]; + for ii_x = 1:self.ss_factor(1) + gr_ss{ii_x, ii_y, ii_z} = struct( ... + 'R_vector', {r_vecs(ii_x, :)}, ... 'center', {gr.center}, ... 'phaseid', {gr.phaseid}, ... - 'allblobs', {[]} ); %#ok<AGROW> + 'allblobs', {[]} ); end end end @@ -248,7 +257,10 @@ classdef GtOrientationSampling < handle num_lattices = numel(self.lattice); or_size = cell(num_lattices, 1); for ii = 1:num_lattices - or_size{ii} = size(self.lattice(ii).gr); + or_size{ii} = [ ... + size(self.lattice(ii).gr, 1), ... + size(self.lattice(ii).gr, 2), ... + size(self.lattice(ii).gr, 3) ]; end end diff --git a/zUtil_Deformation/gtDefShapeFunctionsCreateW.m b/zUtil_Deformation/gtDefShapeFunctionsCreateW.m index b40eabfe..dad67c49 100644 --- a/zUtil_Deformation/gtDefShapeFunctionsCreateW.m +++ b/zUtil_Deformation/gtDefShapeFunctionsCreateW.m @@ -7,30 +7,49 @@ function sf = gtDefShapeFunctionsCreateW(sampler) omstep = gtGetOmegaStepDeg(p, sampler.detector_index); omstep_rod = tand(omstep / 2); - sub_space_size = sampler.stats.sampling.gaps; - - % Let's first compute the W extent - half_rspace_sizes = sub_space_size / 2; - ref_incs = sampler.ondet(sampler.included); ref_inds = sampler.selected; num_blobs = numel(find(ref_inds)); ref_gr = sampler.get_reference_grain(); - pl_samd = ref_gr.allblobs.plorig(ref_incs(ref_inds), :); + if (isfield(ref_gr.allblobs, 'plcry')) + pl_cry = ref_gr.allblobs.plcry(ref_incs(ref_inds), :); + else + pl_samd = ref_gr.allblobs.plorig(ref_incs(ref_inds), :); + g = gtMathsRod2OriMat(ref_gr.R_vector'); + pl_cry = gtVectorLab2Cryst(pl_samd, g)'; + end +% pl_labd = gtGeoSam2Lab(pl_samd, eye(3), self.parameters.labgeo, self.parameters.samgeo, true, false)'; + + sub_space_size = sampler.stats.sampling.gaps; + ospace_samp_size = sampler.get_orientation_sampling_size(); + ospace_samp_size = ospace_samp_size{1}; + + num_ospace_oversampling = prod(sampler.ss_factor); + if (num_ospace_oversampling == 1) + ospace_samp_lattice = sampler.lattice.gr; + else + ospace_samp_lattice = cat(4, sampler.lattice_ss.gr{:}); + ospace_samp_lattice = reshape(ospace_samp_lattice, [sampler.ss_factor, ospace_samp_size]); + ospace_samp_lattice = permute(ospace_samp_lattice, [1 4 2 5 3 6]); + + ospace_samp_size = ospace_samp_size .* sampler.ss_factor; + sub_space_size = sub_space_size ./ sampler.ss_factor; + + ospace_samp_lattice = reshape(ospace_samp_lattice, ospace_samp_size); + end - g = gtMathsRod2OriMat(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)'; + % Let's first compute the W extent + half_rspace_sizes = sub_space_size / 2; fprintf('Computing bounds of W shape functions: ') c = tic(); - tot_orientations = numel(sampler.lattice.gr); + tot_orientations = numel(ospace_samp_lattice); - oris_bounds_size = [size(sampler.lattice.gr, 1), size(sampler.lattice.gr, 2), size(sampler.lattice.gr, 3)] + 1; - oris_lims_min = sampler.lattice.gr{1, 1, 1}.R_vector - half_rspace_sizes; - oris_lims_max = sampler.lattice.gr{end, end, end}.R_vector + half_rspace_sizes; + oris_bounds_size = ospace_samp_size + 1; + oris_lims_min = ospace_samp_lattice{1, 1, 1}.R_vector - half_rspace_sizes; + oris_lims_max = ospace_samp_lattice{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)); @@ -131,7 +150,7 @@ function sf = gtDefShapeFunctionsCreateW(sampler) num_chars = fprintf('%05d/%05d', ii_g, tot_orientations); end - gr = sampler.lattice.gr{ii_g}; + or = ospace_samp_lattice{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); @@ -145,7 +164,7 @@ function sf = gtDefShapeFunctionsCreateW(sampler) % 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_tot_sp, :)' + r_vecs; + r_vecs = or.R_vector(ones_tot_sp, :)' + r_vecs; gs = gtMathsRod2OriMat(r_vecs); % Unrolling and transposing the matrices at the same time @@ -169,10 +188,10 @@ function sf = gtDefShapeFunctionsCreateW(sampler) D = Ac .^ 2 + As .^ 2; % Precomputing useful values, like sinthetas - ominds = gr.allblobs.omind(ref_inds); + ominds = or.allblobs.omind(ref_inds); ssp = ((ominds == 1) | (ominds == 2)); ss = ssp - ~ssp; - sinths = ss .* gr.allblobs.sintheta(ref_inds); + sinths = ss .* or.allblobs.sintheta(ref_inds); sinths = sinths(:, ones(tot_sampling_points, 1)); CC = Acc + sinths; @@ -235,4 +254,21 @@ function sf = gtDefShapeFunctionsCreateW(sampler) end end fprintf('Done in %g seconds.\n', toc(c)) + + if (num_ospace_oversampling > 1) + fprintf('Re-grouping oversampled W shape functions: ') + c = tic(); + ospace_samp_size = sampler.get_orientation_sampling_size(); + ospace_samp_size = ospace_samp_size{1}; + tot_orient = sampler.get_total_num_orientations(); + + regroup = [ ... + sampler.ss_factor(1), ospace_samp_size(1), ... + sampler.ss_factor(2), ospace_samp_size(2), ... + sampler.ss_factor(3), ospace_samp_size(3) ]; + sf = reshape(sf, regroup); + sf = permute(sf, [1 3 5 2 4 6]); + sf = reshape(sf, num_ospace_oversampling, tot_orient); + fprintf('Done in %g seconds.\n', toc(c)) + end end -- GitLab