-
Nicola Vigano authored
Signed-off-by:
Nicola Vigano <nicola.vigano@esrf.fr>
Nicola Vigano authoredSigned-off-by:
Nicola Vigano <nicola.vigano@esrf.fr>
gtDefFwdProjGvdm2P.m 7.64 KiB
function bl = gtDefFwdProjGvdm2P(grain, selectedph, gv, fedpars, parameters, det_ind, verbose)
if (~exist('det_ind', 'var'))
det_ind = 1;
end
if (~exist('verbose', 'var'))
verbose = true;
end
o = GtConditionalOutput(verbose);
o.fprintf('Forward projection (%s):\n', mfilename)
ph_step = gtAcqGetPhiStep(parameters, det_ind);
nbl = gtAcqTotNumberOfImages(parameters, det_ind);
uinds = gv.used_ind;
nv = numel(uinds);
labgeo = parameters.labgeo;
samgeo = parameters.samgeo;
% we pick the first because they are all the same!
if (strcmpi(fedpars.defmethod, 'rod_rightstretch'))
% In this case, the deformation is relative to [0, 0, 0], so we
% need crystal plane normals
if (isfield(grain.allblobs, 'plcry'))
pl_orig = grain.allblobs(det_ind).plcry(1, :)';
else
% We bring the plane normals back to the status of pl_cry
pl_orig = grain.allblobs(det_ind).plorig(1, :);
g = gtMathsRod2OriMat(grain.R_vector);
pl_orig = gtVectorLab2Cryst(pl_orig, g)';
end
else
% Here the deformation is relative to the average oriantion, so we
% need the undeformed sample plane normals
pl_orig = grain.allblobs(det_ind).plorig(1, :)';
end
if (~exist('selectedph', 'var') || isempty(selectedph))
lims_basetilt = parameters.acq(det_ind).range_basetilt;
within_lims = grain.allblobs(det_ind).phi > lims_basetilt(1) & grain.allblobs(det_ind).phi < lims_basetilt(2);
phinds = grain.allblobs(det_ind).phind(within_lims);
phinds_counts = histcounts(phinds, (1:5)-0.5);
[~, phind] = max(phinds_counts);
o.fprintf(' - selected phind: %d (counts: [%s])\n', phind, sprintf(' %d', phinds_counts))
selectedph = grain.allblobs(det_ind).phind == phind;
end
sinths = grain.allblobs(det_ind).sintheta(selectedph);
or_pw = grain.allblobs(det_ind).detector.uvpw(selectedph, 3);
omega = grain.allblobs(det_ind).omega(selectedph);
phinds = grain.allblobs(det_ind).phind(selectedph);
diff_acq = parameters.diffractometer(det_ind);
diff_ref = parameters.diffractometer(1);
rotcomp = gtMathsRotationMatrixComp(diff_acq.axes_basetilt', 'col');
rotdir = diff_acq.axes_basetilt';
instr_t = gtGeoDiffractometerTensor(diff_acq, 'sam2lab', ...
'reference_diffractometer', diff_ref, 'angles_rotation', omega);
pw_shifts = round(or_pw)';
linear_interp = ~(isfield(fedpars, 'projector') ...
&& isstruct(fedpars.projector) && isfield(fedpars.projector, 'interp') ...
&& strcmpi(fedpars.projector.interp, 'nearest'));
gvpow = gv.pow(1, uinds, :);
gvd = gv.d(:, uinds);
% Deformation tensor (relative to reference state) from its components
defT = gtFedDefTensorFromComps(gvd, fedpars.dcomps, fedpars.defmethod, 0);
%%% Computation of indices
o.fprintf(' * Computing indices and bbsizes: ')
t = tic();
p = cell(nbl, 1);
p_min = zeros(nbl, 1);
p_max = zeros(nbl, 1);
valid_voxels = false(nv, nbl);
for ii_b = 1:nbl
num_chars = o.fprintf('%03d/%03d', ii_b, nbl);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Calculate new detector coordinates
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% New deformed plane normals and relative elongations (relative to
% reference state)
% ! use plcry and not plsam to keep omega order below!
[pl_samd, drel] = gtStrainPlaneNormals(pl_orig, defT); % unit column vectors
% The plane normals need to be brought in the Lab reference where the
% beam direction and rotation axis are defined.
% Use the Sample -> Lab orientation transformation assuming omega=0;
% (vector length preserved for free vectors)
pl_samd = gtGeoSam2Lab(pl_samd', instr_t(:, :, ii_b), labgeo, samgeo, true)';
% New sin(theta)
sinth = sinths(ii_b) ./ drel;
% Predict omega angles: 4 for each plane normal
ph = gtFedPredictOmegaMultiple(pl_samd, sinth, ...
labgeo.beamdir', rotdir, rotcomp, phinds(ii_b));
ph = mod(ph + 180, 360) - 180;
valid_voxels(:, ii_b) = ~isnan(ph);
% Delete those where no reflection occurs
if (any(isnan(ph)))
inds_bad = find(isnan(ph));
gvd(:, inds_bad(1:min(10, numel(inds_bad))))
warning('gtFedFwdProjExact:bad_R_vectors', ...
'No diffraction from some elements after deformation (%d over %d) for blob %d.', ...
numel(inds_bad), numel(ph), ii_b)
end
p_bl = ph ./ ph_step;
% Transforming into offsets from average orientation
p_bl = p_bl - pw_shifts(ii_b);
p{ii_b} = p_bl;
p_min(ii_b) = min(p{ii_b});
p_max(ii_b) = max(p{ii_b});
if (any(p_min(ii_b) > 0) || any(p_max(ii_b) < 0))
warning([mfilename ':wrong_result'], ...
'\nThe average orientation seems to project outside the blob!\n')
end
o.fprintf(repmat('\b', [1, num_chars]));
end
o.fprintf('Done in %g s\n', toc(t));
o.fprintf(' * Computing max BBox size and feasibilities:\n')
if (linear_interp)
blob_p_sizes = ceil(p_max) - floor(p_min) + 1;
blob_orig_p_shifts = 1 - floor(p_min);
else
blob_p_sizes = round(p_max) - round(p_min) + 1;
blob_orig_p_shifts = 1 - round(p_min);
end
o.fprintf(' Computed Blob Phi sizes: [%s]\n', sprintf(' %d', blob_p_sizes));
bl = gtFwdSimBlobDefinition('sf_p', nbl);
%%% Blob projection
o.fprintf(' * Projecting volumes: ')
t = tic();
for ii_b = 1:nbl
num_chars = o.fprintf('%03d/%03d', ii_b, nbl);
% Detector coordinates U,V in blob
p_bl = p{ii_b}' + blob_orig_p_shifts(ii_b);
% Let's now filter valid voxels
p_bl = p_bl(valid_voxels(:, ii_b));
gvpow_v = reshape(gvpow(valid_voxels(:, ii_b)), [], 1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Sum intensities
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Distribute value over 8 pixels
if (linear_interp)
[ucbl8, ints8] = gtMathsGetInterpolationIndices(p_bl, gvpow_v, fedpars.bltype);
else
ucbl8 = round(p_bl);
ints8 = gvpow_v;
end
% Accumulate all intensities in the blob voxel-wise
% 'uvw' needs to be nx3; 'ints' is now 1xnx8
try
bl(ii_b).intm = accumarray(ucbl8, ints8, [blob_p_sizes(ii_b), 1]);
catch mexc
fprintf(['\n\nERROR\nThe error is probably caused by the', ...
' projected intensities falling outside the blob volume.', ...
'\nTry increasing the blob volume padding:', ...
' fedpars.detector(det_ind).blobsizeadd, or FIXING', ...
' YOUR CODE!!\n\n'])
disp('Blob ID:')
disp(ii_b)
disp('Blob size:')
disp(blob_p_sizes(ii_b))
disp('Min projected P coordinates:')
fprintf('\t%g \t(rounded: %d )\n', ...
min(p_bl, [], 1), min(ucbl8, [], 1))
disp('Max projected P coordinates:')
fprintf('\t%g \t(rounded: %d )\n', ...
max(p_bl, [], 1), max(ucbl8, [], 1))
new_exc = GtFedExceptionFwdProj(mexc, det_ind, [0 0 0]);
throw(new_exc)
end
bl(ii_b).bbsize = blob_p_sizes(ii_b);
im_low_lims = pw_shifts(ii_b) - blob_orig_p_shifts(ii_b) + 1;
bl(ii_b).bbpim = [im_low_lims, im_low_lims + blob_p_sizes(ii_b) - 1];
o.fprintf(repmat('\b', [1, num_chars]));
end
o.fprintf('Done in %g s\n', toc(t));
end