Newer
Older
Nicola Vigano
committed
function sf = gtDefShapeFunctionsCreateW(sampler)
% FUNCTION sf = gtDefShapeFunctionsCreateW(sampler)
%
p = sampler.parameters;
Nicola Vigano
committed
det_ind = sampler.detector_index;
Nicola Vigano
committed
Nicola Vigano
committed
omstep = gtAcqGetOmegaStep(p, det_ind);
omstep_rod = tand(omstep / 2);
Nicola Vigano
committed
ref_gr = sampler.get_reference_grain();
Nicola Vigano
committed
ref_ond = ref_gr.proj(det_ind).ondet;
ref_inc = ref_gr.proj(det_ind).included;
ref_sel = ref_gr.proj(det_ind).selected;
ref_ab_sel = ref_ond(ref_inc(ref_sel));
ref_ab_inc = ref_ond(ref_inc);
num_inc_blobs = numel(ref_ab_sel);
Nicola Vigano
committed
if (isfield(ref_gr.allblobs, 'plcry'))
Nicola Vigano
committed
pl_cry = ref_gr.allblobs(det_ind).plcry(ref_ab_sel, :);
Nicola Vigano
committed
else
Nicola Vigano
committed
pl_samd = ref_gr.allblobs(det_ind).plorig(ref_ab_sel, :);
Nicola Vigano
committed
g = gtMathsRod2OriMat(ref_gr.R_vector');
pl_cry = gtVectorLab2Cryst(pl_samd, g)';
end
Nicola Vigano
committed
sub_space_size = tand(sampler.sampling_res / 2);
Nicola Vigano
committed
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)
Nicola Vigano
committed
ospace_samp_lattice = sampler.lattice(det_ind).gr;
Nicola Vigano
committed
else
Nicola Vigano
committed
ospace_samp_lattice = cat(4, sampler.lattice_ss(det_ind).gr{:});
Nicola Vigano
committed
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
Nicola Vigano
committed
Nicola Vigano
committed
% Let's first compute the W extent
half_rspace_sizes = sub_space_size / 2;
Nicola Vigano
committed
fprintf('Computing bounds of W shape functions: ')
c = tic();
Nicola Vigano
committed
tot_orientations = numel(ospace_samp_lattice);
Nicola Vigano
committed
Nicola Vigano
committed
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;
Nicola Vigano
committed
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', ref_gr.phaseid, ...
'center', 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), p, ...
Nicola Vigano
committed
'ref_omind', ref_gr.allblobs(det_ind).omind, ...
'included', ref_ab_inc );
Nicola Vigano
committed
fprintf(repmat('\b', [1 num_chars_gr_ii]));
end
fprintf('Done in %g seconds.\n', toc(c))
Nicola Vigano
committed
ref_ws = ref_gr.allblobs(det_ind).omega(ref_ab_sel) ./ omstep;
Nicola Vigano
committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
fprintf('Precomputing shared values..')
% 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
space_res = tand(sampler.estimate_maximum_resolution() ./ 2);
num_poins = max(ceil(sub_space_size ./ space_res ./ 2), 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);
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));
tot_sampling_points = num_poins(1) * num_poins(2);
ones_tot_sp = ones(tot_sampling_points, 1);
% 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];
Nicola Vigano
committed
w_tabs_int = w_tabs_int(ref_sel, :) ./ omstep;
Nicola Vigano
committed
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
w_tabs_int = gtGrainAnglesTabularFix360deg(w_tabs_int, ref_ws, p);
w_tabs_int = reshape(w_tabs_int, [], oris_bounds_size(1), oris_bounds_size(2), oris_bounds_size(3));
rotcomp_z = gtMathsRotationMatrixComp([0, 0, 1]', 'col');
rotcomp_w = gtMathsRotationMatrixComp(p.labgeo.rotdir', 'col');
% Precomputing A matrix components for all the used omegas
ref_round_int_ws = round(ref_ws + 0.5) - 0.5;
ref_round_ws = ref_round_int_ws .* omstep;
rot_w = gtMathsRotationTensor(ref_round_ws, rotcomp_w);
beamdirs = p.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;
Ac_part = Ac_part(:, :, ones_tot_sp);
As_part = As_part(:, :, ones_tot_sp);
Acc_part = Acc_part(:, :, ones_tot_sp);
fprintf('\b\b: Done in %g seconds.\n', toc(c))
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
Nicola Vigano
committed
or = ospace_samp_lattice{ii_g};
Nicola Vigano
committed
% 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)]);
% 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, []);
Nicola Vigano
committed
r_vecs = or.R_vector(ones_tot_sp, :)' + r_vecs;
Nicola Vigano
committed
gs = gtMathsRod2OriMat(r_vecs);
% Unrolling and transposing the matrices at the same time
% because we need g^-1
gs = reshape(gs, 3, [])';
ys = gs * pl_cry;
Nicola Vigano
committed
ys = reshape(ys, 3, [], num_inc_blobs);
Nicola Vigano
committed
ys = permute(ys, [3 1 2]);
% Starting here to compute initial shifts aligned with the
% rounded omega, by frst doing three scalar products
Ac = sum(Ac_part .* ys, 2);
As = sum(As_part .* ys, 2);
Acc = sum(Acc_part .* ys, 2);
Nicola Vigano
committed
Ac = reshape(Ac, num_inc_blobs, tot_sampling_points);
As = reshape(As, num_inc_blobs, tot_sampling_points);
Acc = reshape(Acc, num_inc_blobs, tot_sampling_points);
Nicola Vigano
committed
D = Ac .^ 2 + As .^ 2;
% Precomputing useful values, like sinthetas
Nicola Vigano
committed
ominds = or.allblobs(det_ind).omind(ref_sel);
Nicola Vigano
committed
ssp = ((ominds == 1) | (ominds == 2));
ss = ssp - ~ssp;
Nicola Vigano
committed
sinths = ss .* or.allblobs(det_ind).sintheta(ref_sel);
Nicola Vigano
committed
sinths = sinths(:, ones(tot_sampling_points, 1));
CC = Acc + sinths;
DD = D - CC .^ 2;
E = sqrt(DD);
ok = DD > 0;
% Apparently it is inverted, compared to the omega prediction
% function. Should be investigated
ssp = ~((ominds == 1) | (ominds == 3));
ss = ssp - ~ssp;
ss = ss(:, ones(tot_sampling_points, 1));
% Shift along z in orientation space, to align with the images
% in proections space
dz = (-As + ss .* ok .* E) ./ (CC - Ac);
ws_disps = [ ...
(lims_w_proj_g_int(:, 1) - 0.5 - ref_round_int_ws), ...
(lims_w_proj_g_int(:, 2) + 0.5 - ref_round_int_ws) ];
ws_disps = tand(ws_disps .* omstep / 2);
num_ds = lims_w_proj_g_int(:, 2) - lims_w_proj_g_int(:, 1) + 2;
Nicola Vigano
committed
bbwims = cell(num_inc_blobs, 1);
intms = cell(num_inc_blobs, 1);
bbsizes = cell(num_inc_blobs, 1);
Nicola Vigano
committed
% This is the most expensive operation because the different
% sizes of the omega spread, which depends on the blob itself,
% don't allow to have vectorized operations on all the blobs at
% the same time
Nicola Vigano
committed
for ii_b = 1:num_inc_blobs
Nicola Vigano
committed
d = (ws_disps(ii_b, 1):omstep_rod:ws_disps(ii_b, 2))';
d = d(:, ones(tot_sampling_points, 1)) + dz(ii_b * ones(num_ds(ii_b), 1), :);
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);
bbwims{ii_b} = lims_w_proj_g_int(ii_b, :);
intms{ii_b} = renorm_coeff * ints;
bbsizes{ii_b} = numel(ints);
end
Nicola Vigano
committed
sf_bls_w = gtFwdSimBlobDefinition('sf_w', num_inc_blobs);
Nicola Vigano
committed
[sf_bls_w(:).bbwim] = deal(bbwims{:});
[sf_bls_w(:).intm] = deal(intms{:});
[sf_bls_w(:).bbsize] = deal(bbsizes{:});
sf{ii_g} = sf_bls_w;
if (mod(ii_g, chunk_size) == 1)
fprintf(repmat('\b', [1, num_chars]));
end
end
fprintf('Done in %g seconds.\n', toc(c))
Nicola Vigano
committed
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