Files
fold_slice/tomo/+nonrigid/show_deformation_field.m
2026-08-07 15:56:42 +09:00

167 lines
6.5 KiB
Matlab

% show_deformation_field - plot reconstructed deformation vector field
%
% show_deformation_field(rec_avg, deform_tensors, apodize_radial, Nsvd, binning, upscale_arrows, slice_axis, down_DVF)
%
% Inputs:
% **rec_avg optimal reconstuction
% **deform_tensors reconstructed DVF
% **apodize_radial apply radial appodization to crop artefacts around
% **Nsvd number of SVD modes to be plotted
% **binning currenlty used binning (used for scaling)
% **upscale_arrows (scalar) scaling constant for the plotted arrows
% **slice_axis axis along which the reconstruction will be sliced and plotted
% **down_DVF (int) donsample DVF to make the arrows more sparse in the plot
%
%*-----------------------------------------------------------------------*
%| |
%| Except where otherwise noted, this work is licensed under a |
%| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
%| International (CC BY-NC-SA 4.0) license. |
%| |
%| Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch) |
%| |
%| Author: CXS group, PSI |
%*-----------------------------------------------------------------------*
% You may use this code with the following provisions:
%
% If the code is fully or partially redistributed, or rewritten in another
% computing language this notice should be included in the redistribution.
%
% If this code, or subfunctions or parts of it, is used for research in a
% publication or if it is fully or partially rewritten for another
% computing language the authors and institution should be acknowledged
% in written form in the publication: “Data processing was carried out
% using the “cSAXS matlab package” developed by the CXS group,
% Paul Scherrer Institut, Switzerland.”
% Variations on the latter text can be incorporated upon discussion with
% the CXS group if needed to more specifically reflect the use of the package
% for the published work.
%
% A publication that focuses on describing features, or parameters, that
% are already existing in the code should be first discussed with the
% authors.
%
% This code and subroutines are part of a continuous development, they
% are provided “as they are” without guarantees or liability on part
% of PSI or the authors. It is the user responsibility to ensure its
% proper use and the correctness of the results.
function show_deformation_field(rec_avg, deform_tensors, apodize_radial, Nsvd, binning, upscale_arrows, slice_axis, down_DVF)
% show deformation vector field
Nblocks = length(deform_tensors);
for kk = 1:3
for ll = 1:Nblocks+1
if ll <= Nblocks
shift_3D_mat(:,:,:,kk,ll) = deform_tensors{ll}{1,kk};
else
shift_3D_mat(:,:,:,kk,ll) = deform_tensors{ll-1}{min(end,2),kk};
end
end
end
[~,mask_small] = utils.apply_3D_apodization(deform_tensors{1}{1}, apodize_radial);
% apply mask on the results
shift_3D_mat = shift_3D_mat .* mask_small;
% swap dimension to show the right plane
switch slice_axis
case 1
rec_avg = rot90(permute(rec_avg, [2,3,1]),1);
mask_small = rot90(permute(mask_small, [2,3,1]),1);
shift_3D_mat = rot90(permute(shift_3D_mat, [2,3,1,4,5]),1);
case 2
rec_avg = rot90(permute(rec_avg, [1,3,2]),1);
mask_small = rot90(permute(mask_small, [1,3,2]),1);
shift_3D_mat = rot90(permute(shift_3D_mat, [2,3,1,4,5]),1);
case 3
end
[Nx,Ny,Nlayers] = size(rec_avg);
Nps = size(shift_3D_mat);
mesh_2D = {1:down_DVF:Nps(1),1:down_DVF:Nps(2)};
frame_s = ceil(Nps(3)/2);
frame = ceil(Nlayers/2);
% calculate SVD
shift_3D_mat = reshape(shift_3D_mat,[],Nblocks+1);
[U,S,V] = math.fsvd(shift_3D_mat, Nsvd);
U = reshape(U, [Nps(1:3), 3, Nsvd]);
U = U * sign(mean(V(:,1)));
V = V * sign(mean(V(:,1)));
if slice_axis == 3
mean_amp = sqrt(mean(math.mean2(abs(U).^2 .* mask_small) ./ math.mean2(mask_small),3));
else
mean_amp = sqrt(mean(math.mean2(abs(U).^2)));
end
mean_amp = squeeze(mean_amp(1,1,1,:,1));
mean_amp = mean_amp .* S(1) * V(3,1);
mean_amp = mean_amp .* binning;
fprintf('Mean deformation x:%3.2gpx y:%3.2gpx z:%3.2gpx \n',mean_amp )
[~,S_tmp,~] = math.fsvd(shift_3D_mat, min(size(shift_3D_mat,2),Nsvd+10));
fprintf(['Relative power of the modes:', repmat(' %3.3g%%, ',1,size(S_tmp,1)) , ' \n'], diag(S_tmp ./ sum(S_tmp(:)))*100 )
figure(545)
for mode = 1:Nsvd
ax(mode) = subplot(2,Nsvd,mode);
for kk = 1:3
Q{mode,kk} = U(:,:,:,kk,mode) .* S(mode,mode);
Q{mode,kk} = utils.imgaussfilt3_fft(Q{mode,kk}, down_DVF);
end
ygrid = ((1:Nps(1))-0.5)/Nps(1)*Nx;
xgrid = ((1:Nps(2))-0.5)/Nps(2)*Ny;
[x,y] = meshgrid(xgrid, ygrid);
img = rec_avg(:,:,frame);
img = min(1,img / math.sp_quantile(rec_avg(:), 0.95,5));
imagesc(1-img, [-1,1]);
colormap bone
hold all
quiver(x(mesh_2D{:}),y(mesh_2D{:}),Q{mode,2}(mesh_2D{:},frame_s)*upscale_arrows, ...
Q{mode,1}(mesh_2D{:},frame_s)*upscale_arrows,0,'Linewidth',2);
axis off image
hold off
title(sprintf('%i. PCA of DVF field\n %ix upscaled',mode, upscale_arrows))
subplot(2,Nsvd,Nsvd + mode)
plot(V(:,mode))
grid on
axis tight
xlabel('Interpolation node id')
ylabel('Normalized evolution')
end
linkaxes(ax, 'xy')
plotting.suptitle('Singular value decomposition of the DVF evolution')
% end
figure(45545)
subplot(1,2,1)
plotting.imagesc3D(rec_avg, 'init_frame', size(rec_avg,3)/2)
axis off image ; colormap bone
colorbar
title('Reconstruction example')
subplot(1,2,2)
deform = Q{1,1}*binning;
plotting.imagesc3D(deform, 'init_frame', size(deform,3)/2)
caxis(gather(math.sp_quantile(deform, [0.001, 0.999],5)))
axis off image ; colormap bone
title('Vertical deformation vector field')
plotting.suptitle('1th PCA vector, horizontal cut')
drawnow
end