mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 22:49:08 +09:00
606 lines
22 KiB
Matlab
606 lines
22 KiB
Matlab
% [resolution stat] = aligned_FSC(file1,file2,param)
|
|
%
|
|
% Receives two filenames with path for ptychography reconstructions and a
|
|
% structure with parameters. The routine reads the reconstructions, matches
|
|
% the linear phase between them, registers the images, and returns the
|
|
% resolution estimates based on first and last crossing of the FSC with the
|
|
% threshold.
|
|
%
|
|
% Modified by YJ for electron ptychography
|
|
%
|
|
% References relevant to this code:
|
|
% For using this FSC code with ptychography: J. Vila-Comamala, et al., "Characterization of high-resolution diffractive X-ray optics by ptychographic coherent diffractive imaging," Opt. Express 19, 21333-21344 (2011).
|
|
% For subpixel alignment: M. Guizar-Sicairos, et al., "Efficient subpixel image registration algorithms," Opt. Lett. 33, 156 (2008).
|
|
% For matching of phase ramp by approximate least squared error: M. Guizar-Sicairos, et al., "Phase tomography from x-ray coherent diffractive imaging projections," Opt. Express 19, 21345-21357 (2011).
|
|
%
|
|
% Outputs:
|
|
%
|
|
% resolution A two element variable that contains the resolution
|
|
% obtained from first and last crossing of the FSC curve with
|
|
% the threshold curve.
|
|
% stat structure containing other statistics such as
|
|
% spectral signal to noise ratio (SSNR), average SNR and area under FSC curve
|
|
%
|
|
% Inputs:
|
|
%
|
|
% file1 Filename with path of reconstruction 1 or directly a 2D numerical array
|
|
% file2 Filename with path of reconstruction 2 or directly a 2D numerical array
|
|
% param Structure with parameters as describred below
|
|
%
|
|
% param.flipped_images Flip one input image horizontally (= true or false).
|
|
% Useful when comparing 0 and 180 degree projections
|
|
% in tomography (default = false).
|
|
% param.crop = ''; for using the default half size of the probe
|
|
% = 'manual' for using GUI to select region. This will display the range, e.g. {600:800, 600:800}
|
|
% = {600:800, 600:800} for custom vertical and horizontal cropping, respectively
|
|
% param.GUIguess To click for an initial alignment guess, if used it ignores
|
|
% the values of param.guessx and param.guessy (default
|
|
% = false)
|
|
% param.guessx
|
|
% param.guessy An intial guess for x and y alignment (default = [])
|
|
% param.remove_ramp Try to remove linear phase from whole image before initial
|
|
% alignment (default = true)
|
|
% param.image_prop = 'complex'
|
|
% = 'phasor' (phase with unit amplitude, default)
|
|
% = 'phase' (Note: phase should not be used if there is phase wrapping)
|
|
% param.taper = 20 (default) Pixels to taper images - Increase until the FSC does not change anymore
|
|
% param.plotting Display plots (default = false)
|
|
% param.dispfsc Display FSC plot (default = true)
|
|
% param.SNRt SNR for FSC threshold curve
|
|
% SNRt = 0.2071 for 1/2 bit threshold for resolution of the average of the 2 images
|
|
% SNRt = 0.5 for 1 bit threshold for resolution of each individual image (default)
|
|
% param.thickring Thickness of Fourier domain ring for FSC in pixels (default = 1)
|
|
% param.freq_thr To ignore the crossings before freq_thr for determining resolution (default 0.02)
|
|
% param.out_fn Filename of output of jpeg for FSC
|
|
% param.pixel_size Pixel size in the reconstruction, it is used only
|
|
% if file1 / file2 are not paths to the reconsturcted files
|
|
|
|
function [resolution,stat] = aligned_FSC(file1,file2,param)
|
|
import utils.*
|
|
import math.*
|
|
import io.*
|
|
import plotting.*
|
|
|
|
file{1} = file1;
|
|
file{2} = file2;
|
|
|
|
for ii = 1:2
|
|
if ischar(file{ii})
|
|
[~,file_path{ii},~] = fileparts(file{ii});
|
|
else
|
|
file_path{ii} = sprintf('image_id_%i', ii);
|
|
end
|
|
end
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%%% Checks and defaults %%%
|
|
if isfield(param,'flag_imread')
|
|
flag_imread = param.flag_imread;
|
|
else
|
|
if ~(ischar(file1) && ischar(file2)) || (~isempty(regexpi(file1,'\.mat|\.h5')) && ~isempty(regexpi(file2,'\.mat|\.h5')))
|
|
flag_imread = false;
|
|
else
|
|
flag_imread = true;
|
|
warning('Files not in .mat: using ''imread'' for loading; image in real number (ignoring remove_ramp and image_prop)')
|
|
end
|
|
end
|
|
|
|
|
|
% parse inputs
|
|
check_input = @(x) islogical(x) || isnumeric(x);
|
|
check_crop = @(x) isempty(x) || ischar(x) || iscell(x);
|
|
check_image_prop = @(x) assert(any(contains({'complex', 'phasor', 'phase', 'variation'}, x)), ...
|
|
'image_prop must be either "complex", "phasor", "phase" or "variation".');
|
|
parse_param = inputParser;
|
|
parse_param.KeepUnmatched = true;
|
|
|
|
parse_param.addParameter('flipped_images', false, check_input)
|
|
parse_param.addParameter('crop', '', check_crop)
|
|
parse_param.addParameter('GUIguess', false, check_input)
|
|
parse_param.addParameter('guessx', [], check_input)
|
|
parse_param.addParameter('guessy', [], check_input)
|
|
parse_param.addParameter('plotting',false, check_input)
|
|
parse_param.addParameter('remove_ramp', false, check_input)
|
|
parse_param.addParameter('image_prop', 'phasor', check_image_prop)
|
|
parse_param.addParameter('SNRt', 0.5, @isnumeric)
|
|
parse_param.addParameter('thickring', 1, @isnumeric)
|
|
parse_param.addParameter('freq_thr', 0.02, @isnumeric)
|
|
parse_param.addParameter('prop_obj', [], check_input)
|
|
parse_param.addParameter('apod', [], check_input)
|
|
parse_param.addParameter('filter_FFT', [], check_input)
|
|
parse_param.addParameter('crop_factor', 1, @isnumeric)
|
|
parse_param.addParameter('crop_asize', [], @isnumeric)
|
|
parse_param.addParameter('z_lens', [], @isnumeric)
|
|
parse_param.addParameter('fourier_ptycho', false, check_input)
|
|
parse_param.addParameter('lambda', [], @isnumeric)
|
|
parse_param.addParameter('pixel_size', [], @isnumeric)
|
|
parse_param.addParameter('electron', false, check_input) %added by YJ for electron ptychography
|
|
parse_param.addParameter('verbose_level', 3, @isnumeric)
|
|
parse_param.addParameter('fname', [], @iscell)
|
|
parse_param.addParameter('show_summary', true, check_input)
|
|
parse_param.addParameter('xlabel_type', 'nyquist', @(x)ismember(lower(x), {'nyquist', 'resolution'})) % select X axis units
|
|
|
|
parse_param.parse(param)
|
|
param = parse_param.Results;
|
|
|
|
if isempty(param.crop)
|
|
utils.verbose(3,'Cropping half size of the probe (default)')
|
|
end
|
|
|
|
if isfield(param,'taper')
|
|
taper = param.taper;
|
|
else
|
|
taper = 20;
|
|
utils.verbose(3,'Using taper = 20 (default)')
|
|
end
|
|
|
|
if isempty(param.fname)
|
|
param.fname = file_path;
|
|
end
|
|
|
|
utils.verbose(param.verbose_level);
|
|
utils.verbose(struct('prefix', {'FSC'}))
|
|
|
|
% set dispfsc value - used in utils.fourier_shell_corr_3D_2
|
|
param.dispfsc = (param.plotting > 0);
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
if ischar(file{1})
|
|
if ~flag_imread
|
|
%%% Checking if file exist and loading %%%
|
|
if exist(file{1},'file')
|
|
param.fourier_ptycho = io.HDF.hdf5_load(file{1}, '/reconstruction/p/fourier_ptycho');
|
|
utils.verbose(2, ['Loading: ' file{1}])
|
|
recons{1} = load_ptycho_recons(file{1}, 'object');
|
|
if param.fourier_ptycho
|
|
recons{1} = FP_FSC_preprocess(recons{1}, file{1}, param);
|
|
end
|
|
else
|
|
error(['Not found: ' file{1}])
|
|
end
|
|
if exist(file{2},'file')
|
|
utils.verbose(2, ['Loading: ' file{2}])
|
|
recons{2} = load_ptycho_recons(file{2}, 'object');
|
|
if param.fourier_ptycho
|
|
recons{2} = FP_FSC_preprocess(recons{2}, file{2}, param);
|
|
end
|
|
else
|
|
error(['Not found: ' file{2}])
|
|
end
|
|
|
|
img1 = recons{1}.object;
|
|
img2 = recons{2}.object;
|
|
|
|
% load additional parameters
|
|
asize = double(io.HDF.hdf5_load(file{1}, '/reconstruction/p/asize'));
|
|
if ~param.fourier_ptycho
|
|
param.pixel_size = io.HDF.hdf5_load(file{1}, '/reconstruction/p/dx_spec');
|
|
else
|
|
param.pixel_size = recons{1}.p.objpix;
|
|
end
|
|
try
|
|
if isempty(param.lambda) && io.HDF.hdf5_dset_exists(file{1}, 'lambda', '/reconstruction/p', true)
|
|
param.lambda = io.HDF.hdf5_load(file{1}, '/reconstruction/p/lambda');
|
|
end
|
|
end
|
|
else
|
|
if ~isnumeric(file{1})
|
|
img1 = imread(file{1});
|
|
else
|
|
img1 = file{1}; %input provides directly the numeric array
|
|
end
|
|
if ~isnumeric(file{2})
|
|
img2 = imread(file{2});
|
|
else
|
|
img2 = file{2}; %input provides directly the numeric array
|
|
end
|
|
asize = [1 1];
|
|
if isempty(param.pixel_size)
|
|
param.pixel_size = 1e-6;
|
|
warning('Using pixel size 1um')
|
|
end
|
|
end
|
|
else
|
|
img1 = file{1}; %input provides directly the numeric array
|
|
img2 = file{2}; %input provides directly the numeric array
|
|
if ~isfield(param, 'asize')
|
|
asize = [1 1];
|
|
else
|
|
asize = param.asize;
|
|
end
|
|
if isempty(param.pixel_size)
|
|
param.pixel_size = 1e-6;
|
|
warning('Using pixel size 1um')
|
|
end
|
|
end
|
|
|
|
if param.flipped_images
|
|
img2 = fliplr(img2);
|
|
end
|
|
|
|
% apply apodization
|
|
|
|
% check if apodization was used in the reconstruction
|
|
if isempty(param.apod)
|
|
try
|
|
param.apod = io.HDF.hdf5_load(file{1}, '/reconstruction/p/plot/obj_apod');
|
|
catch
|
|
warning('Unable to load apodization parameter from reconstruction file.')
|
|
param.apod = false;
|
|
end
|
|
end
|
|
if param.apod
|
|
img1 = apply_apod(img1, asize);
|
|
img2 = apply_apod(img2, asize);
|
|
end
|
|
|
|
% propagate if needed
|
|
if isempty(param.prop_obj) || param.prop_obj
|
|
if isempty(param.lambda)
|
|
try
|
|
param.lambda = io.HDF.hdf5_load(file{1}, '/reconstruction/p/lambda');
|
|
catch
|
|
try
|
|
param.energy = io.HDF.hdf5_load(file{1}, '/reconstruction/p/energy');
|
|
param.lambda = 12.4/param.energy*1e-10;
|
|
catch
|
|
error('Please specify your wavelength (param.lambda).')
|
|
end
|
|
end
|
|
end
|
|
if isempty(param.prop_obj) || islogical(param.prop_obj) && param.prop_obj
|
|
% get values from file
|
|
try
|
|
param.prop_obj = io.HDF.hdf5_load(file{1}, '/reconstruction/p/prop_obj');
|
|
catch
|
|
error('Please specify the propagation distance or set it to "false" (param.prop_obj).')
|
|
end
|
|
end
|
|
|
|
img1 = utils.prop_free_nf(img1, param.lambda, param.prop_obj, param.pixel_size);
|
|
img2 = utils.prop_free_nf(img2, param.lambda, param.prop_obj, param.pixel_size);
|
|
end
|
|
|
|
|
|
screensize = get( 0, 'Screensize' );
|
|
% Show phase images (not cropped)%
|
|
if param.plotting > 1
|
|
plotting.smart_figure(21)
|
|
set(gcf,'Outerposition',[1 screensize(4)-550 500 500]) %[left, bottom, width, height
|
|
if ~isreal(img1)
|
|
imagesc(angle(img1), math.sp_quantile(angle(img1),[1e-2, 1-1e-2],10));
|
|
if ~param.fourier_ptycho
|
|
rectangle('Position',[asize([2,1])/2, [size(img1,2),size(img1,1)]-asize([2,1])], 'EdgeColor', 'red')
|
|
end
|
|
else
|
|
imagesc(img1, math.sp_quantile((img1),[1e-2, 1-1e-2],10));
|
|
end
|
|
axis xy equal tight
|
|
colormap bone
|
|
colorbar
|
|
if param.prop_obj
|
|
[si_unit, val] = utils.get_unit_length(param.prop_obj);
|
|
title(sprintf([param.fname{1} '\npropagated by %d %s'], val, si_unit),'interpreter','none')
|
|
else
|
|
title(param.fname{1},'interpreter','none')
|
|
end
|
|
plotting.smart_figure(22)
|
|
if ~isreal(img1)
|
|
imagesc(angle(img2), math.sp_quantile(angle(img2),[1e-2, 1-1e-2],10));
|
|
else
|
|
imagesc(img2, math.sp_quantile(img2,[1e-2, 1-1e-2],10));
|
|
end
|
|
if ~param.fourier_ptycho
|
|
rectangle('Position',[asize([2,1])/2, [size(img2,2),size(img2,1)]-asize([2,1])], 'EdgeColor', 'red')
|
|
end
|
|
axis xy equal tight
|
|
colormap bone
|
|
colorbar
|
|
if param.prop_obj
|
|
[si_unit, val] = utils.get_unit_length(param.prop_obj);
|
|
title(sprintf([param.fname{2} '\npropagated by %d %s'], val, si_unit),'interpreter','none')
|
|
else
|
|
title(param.fname{2},'interpreter','none')
|
|
end
|
|
set(gcf,'Outerposition',[500 screensize(4)-550 500 500]) %[left, bottom, width, height
|
|
end
|
|
|
|
% Crop images - default is half the size of the probe on each side plus
|
|
% whatever needed to make them of equal size
|
|
if isempty(param.crop)
|
|
minsize = min(size(img1),size(img2))-asize;
|
|
img1 = crop_pad(img1,minsize );
|
|
img2 = crop_pad(img2,minsize );
|
|
elseif strcmpi(param.crop, 'manual')
|
|
figure()
|
|
imagesc(angle(img1), math.sp_quantile(angle(img1),[1e-2, 1-1e-2],10));
|
|
if ~param.fourier_ptycho
|
|
rectangle('Position',[asize([2,1])/2, [size(img1,2),size(img1,1)]-asize([2,1])], 'EdgeColor', 'red')
|
|
end
|
|
colormap bone
|
|
axis image xy
|
|
title('Select compared region')
|
|
disp('Manually select the compared region ... ')
|
|
rect = round(getrect);
|
|
param.crop = {rect(2)+(1:rect(4)),rect(1)+(1:rect(3))};
|
|
disp('===========================')
|
|
fprintf('Selected region: {%i:%i,%i:%i}\n',rect(2), rect(2)+rect(4), rect(1), rect(1)+rect(3));
|
|
disp('===========================')
|
|
pause(1)
|
|
end
|
|
if ~isempty(param.crop)
|
|
img1 = img1(param.crop{:});
|
|
img2 = img2(param.crop{:});
|
|
end
|
|
|
|
if param.GUIguess
|
|
plotting.smart_figure(21)
|
|
disp(['Click on a feature on figure 2'])
|
|
[xin yin] = ginput(1);
|
|
plotting.smart_figure(22)
|
|
disp(['Click on a feature on figure 3'])
|
|
[xin2 yin2] = ginput(1);
|
|
param.guessx = round(xin-xin2);
|
|
param.guessy = round(yin-yin2);
|
|
end
|
|
|
|
if ~isempty(param.guessx)
|
|
switch sign(param.guessx)
|
|
case 1
|
|
img1 = img1(:,1+param.guessx:end);
|
|
img2 = img2(:,1:end-param.guessx);
|
|
case -1
|
|
img1 = img1(:,1:end+param.guessx);
|
|
img2 = img2(:,1-param.guessx:end);
|
|
end
|
|
end
|
|
if ~isempty(param.guessy)
|
|
switch sign(param.guessy)
|
|
case 1
|
|
img1 = img1(1+param.guessy:end,:);
|
|
img2 = img2(1:end-param.guessy,:);
|
|
case -1
|
|
img1 = img1(1:end+param.guessy,:);
|
|
img2 = img2(1-param.guessy:end,:);
|
|
end
|
|
end
|
|
|
|
|
|
% Remove ramp
|
|
if param.remove_ramp
|
|
utils.verbose(3,'Removing ramp for initial alignment')
|
|
img1 = utils.stabilize_phase(img1,'binning', 4);
|
|
img2 = utils.stabilize_phase(img2, img1, 'binning', 4);
|
|
end
|
|
|
|
if param.plotting >2
|
|
plotting.smart_figure(23)
|
|
set(gcf,'Outerposition',[1 1 500 476]) %[left, bottom, width, height
|
|
if ~isreal(img1)
|
|
imagesc(angle(img1));
|
|
else
|
|
imagesc(img1);
|
|
end
|
|
axis xy equal tight
|
|
colormap bone; colorbar
|
|
ax23 = gca;
|
|
title(param.fname{1},'interpreter','none')
|
|
plotting.smart_figure(24);
|
|
if ~isreal(img2)
|
|
imagesc(angle(img2));
|
|
else
|
|
imagesc(img2);
|
|
end
|
|
axis xy equal tight
|
|
colormap bone; colorbar
|
|
title(param.fname{2},'interpreter','none')
|
|
set(gcf,'Outerposition',[500 1 500 476]) %[left, bottom, width, height]
|
|
ax34 = gca;
|
|
linkaxes([ax23, ax34], 'xy')
|
|
end
|
|
|
|
|
|
|
|
% img1 = img1 - utils.imgaussfilt2_fft(img1, 20);
|
|
% img2 = img2 - utils.imgaussfilt2_fft(img2, 20);
|
|
% image_prop= 'complex';
|
|
|
|
%%% Initial alignment %%%
|
|
utils.verbose(2,'Initial alignment')
|
|
if ~flag_imread
|
|
switch lower(param.image_prop)
|
|
case 'complex'
|
|
imgalign1 = img1;
|
|
imgalign2 = img2;
|
|
utils.verbose(2,'Registering complex valued images')
|
|
case 'phasor'
|
|
imgalign1 = ones(size(img1)).*exp(1i*angle(img1));
|
|
imgalign2 = ones(size(img2)).*exp(1i*angle(img2));
|
|
utils.verbose(2,'Registering phasor of complex valued images')
|
|
case 'phase'
|
|
imgalign1 = angle(img1);
|
|
imgalign2 = angle(img2);
|
|
utils.verbose(2,'Registering phase of complex valued images')
|
|
case 'variation'
|
|
[dX,dY] = math.get_phase_gradient_2D(img1);
|
|
imgalign1 = sqrt(dX.^2+dY.^2);
|
|
[dX,dY] = math.get_phase_gradient_2D(img2);
|
|
imgalign2 = sqrt(dX.^2+dY.^2);
|
|
|
|
end
|
|
else
|
|
imgalign1 = img1;
|
|
imgalign2 = img2;
|
|
end
|
|
|
|
upsamp = 100;
|
|
displ = utils.verbose>3;
|
|
W = 1;
|
|
x1 = [];%[1:150];
|
|
x2 = x1;
|
|
y1 = [];%[1:238];
|
|
y2 = y1;
|
|
|
|
|
|
|
|
% imgalign2 = shiftpp2(imgalign2,10,-10); % To test range adjustment
|
|
[subim1, subim2, delta, deltafine, regionsout] = registersubimages_2(imgalign1,imgalign2, x1, y1, x2, y2, upsamp, displ,1);
|
|
|
|
%%% Fine alignment (second round) %%%
|
|
|
|
% Remove ramp for fine alignment
|
|
utils.verbose(2,'Removing ramp for fine alignment')
|
|
%%% A patch for deltafine large
|
|
if max(regionsout.y2+round(delta(1)))>size(img2,1)
|
|
warning('First subpixel registration refinement found large values')
|
|
regionsout.y2 = [min(regionsout.y2):size(img2,1)-round(delta(1))];
|
|
regionsout.y1 = regionsout.y2;
|
|
end
|
|
if max(regionsout.x2+round(delta(2)))>size(img2,2)
|
|
warning('First subpixel registration refinement found large values')
|
|
regionsout.x2 = [min(regionsout.x2):size(img2,2)-round(delta(2))];
|
|
regionsout.x1 = regionsout.x2;
|
|
end
|
|
%%%
|
|
subimg1 = img1(regionsout.y1,regionsout.x1);
|
|
subimg2 = img2(regionsout.y2+round(delta(1)),regionsout.x2+round(delta(2)));
|
|
if ~flag_imread
|
|
subimg1 = remove_linearphase_v2(subimg1,ones(size(subimg1)),100);
|
|
subimg2 = remove_linearphase_v2(subimg2,ones(size(subimg2)),100);
|
|
end
|
|
|
|
|
|
% Remove ramp
|
|
if param.remove_ramp
|
|
utils.verbose(2,'Removing ramp for initial alignment')
|
|
subimg1 = utils.stabilize_phase(subimg1,'binning', 4);
|
|
subimg2 = utils.stabilize_phase(subimg2, subimg1, 'binning', 4);
|
|
end
|
|
|
|
if ~flag_imread
|
|
switch lower(param.image_prop)
|
|
case 'complex'
|
|
subimgalign1 = subimg1;
|
|
subimgalign2 = subimg2;
|
|
utils.verbose(2,'Registering complex valued images')
|
|
case 'phasor'
|
|
subimgalign1 = ones(size(subimg1)).*exp(1i*angle(subimg1));
|
|
subimgalign2 = ones(size(subimg1)).*exp(1i*angle(subimg2));
|
|
utils.verbose(2,'Registering phasor of complex valued images')
|
|
case 'phase'
|
|
subimgalign1 = angle(subimg1);
|
|
subimgalign2 = angle(subimg2);
|
|
utils.verbose(2,'Registering phase of complex valued images')
|
|
case 'variation'
|
|
[dX,dY] = math.get_phase_gradient_2D(subimg1);
|
|
subimgalign1 = sqrt(dX.^2+dY.^2);
|
|
[dX,dY] = math.get_phase_gradient_2D(subimg2);
|
|
subimgalign2 = sqrt(dX.^2+dY.^2);
|
|
end
|
|
else
|
|
subimgalign1 = subimg1;
|
|
subimgalign2 = subimg2;
|
|
end
|
|
|
|
% Fine alignment %
|
|
utils.verbose(2,'Fine alignment')
|
|
[subim1, subim2, delta, deltafine, regionsout] = registersubimages_2(subimgalign1,subimgalign2, x1, y1, x2, y2, upsamp, displ,1);
|
|
|
|
%%% propare images for FSC if variation was used for alignement
|
|
if strcmpi(param.image_prop, 'variation')
|
|
subim1 = subimg1(regionsout.y1, regionsout.x1);
|
|
subim2 = subimg2(regionsout.y2, regionsout.x2);
|
|
subim2 = shiftpp2(subim2,-deltafine(1), -deltafine(2)); %% Suboptimal, change to use a routine that receives FT data
|
|
% convert images to phasor
|
|
subim1 = exp(1i*angle(subim1));
|
|
subim2 = exp(1i*angle(subim2));
|
|
end
|
|
|
|
%%% Tapering %%%
|
|
filterx = fract_hanning_pad(size(subim1,2),size(subim1,2),size(subim1,2)-2*taper);
|
|
filterx = fftshift(filterx(1,:));
|
|
filtery = fract_hanning_pad(size(subim1,1),size(subim1,1),size(subim1,1)-2*taper);
|
|
filtery = fftshift(filtery(:,1));
|
|
filterxy = filterx.*filtery;
|
|
|
|
% Taper subimages %
|
|
subim1 = subim1.*filterxy;% + (1-filterxy).*mean(subim1(:));
|
|
subim2 = subim2.*filterxy;% + (1-filterxy).*mean(subim2(:));
|
|
|
|
if param.plotting > 1
|
|
plotting.smart_figure(23)
|
|
set(gcf,'Outerposition',[1 1 500 476]) %[left, bottom, width, height
|
|
if strcmpi(param.image_prop,'phase') || flag_imread
|
|
imagesc(subim1);
|
|
else
|
|
imagesc(angle(subim1));
|
|
end
|
|
axis xy equal tight
|
|
colormap bone; colorbar
|
|
if param.prop_obj
|
|
[si_unit, val] = utils.get_unit_length(param.prop_obj);
|
|
title(sprintf([param.fname{1} '\npropagated by %d %s'], val, si_unit),'interpreter','none')
|
|
else
|
|
title(param.fname{1},'interpreter','none')
|
|
end
|
|
plotting.smart_figure(24)
|
|
if strcmpi(param.image_prop,'phase') || flag_imread
|
|
imagesc(real(subim2));
|
|
else
|
|
imagesc(angle(subim2));
|
|
end
|
|
axis xy equal tight
|
|
colormap bone; colorbar
|
|
if param.prop_obj
|
|
[si_unit, val] = utils.get_unit_length(param.prop_obj);
|
|
title(sprintf([param.fname{2} '\npropagated by %d %s'], val, si_unit),'interpreter','none')
|
|
else
|
|
title(param.fname{2},'interpreter','none')
|
|
end
|
|
set(gcf,'Outerposition',[500 1 500 476]) %[left, bottom, width, height
|
|
end
|
|
%% Computing the FSC
|
|
param.st_title = sprintf('%s\n %s\n flipped_images %d, taper %d',param.fname{1}, param.fname{2}, param.flipped_images, taper);
|
|
if flag_imread
|
|
subim1 = real(subim1);
|
|
subim2 = real(subim2);
|
|
warning('Assuming images are in real number!');
|
|
end
|
|
|
|
subim1 = utils.stabilize_phase(subim1, subim2, 'binning', 4, 'fourier_guess', false);
|
|
|
|
if param.electron %special version for electron ptychography. unit: angstrom
|
|
[resolution,FSC,T,freq,n,stat] = fourier_shell_corr_3D_2e(subim1,subim2, param);
|
|
else
|
|
[resolution,FSC,T,freq,n,stat] = fourier_shell_corr_3D_2(subim1,subim2, param);
|
|
end
|
|
|
|
%% visually compare alignment quality
|
|
if param.plotting>2
|
|
plotting.smart_figure(4545)
|
|
subplot(1,2,1)
|
|
imagesc3D(angle(subim1 .* conj( subim2)))
|
|
colormap bone
|
|
axis off image
|
|
colorbar
|
|
title('Phase difference between aligned sub-images')
|
|
|
|
subplot(1,2,2)
|
|
imagesc3D(cat(3,angle(subim1),angle(subim2)))
|
|
colormap bone
|
|
axis off image
|
|
title('Compare aligned sub-images')
|
|
colorbar
|
|
plotting.suptitle('Visually compare quality and verify alignement / drifts')
|
|
end
|
|
|
|
end
|
|
|
|
|
|
function img = apply_apod(img, asize)
|
|
ob_good_range = {asize(1)/2:size(img,1)-asize(1)/2, asize(2)/2:size(img,2)-asize(2)/2};
|
|
filt_size = [size(ob_good_range{1},2) size(ob_good_range{2},2)];
|
|
img = img.*fftshift(utils.filt2d_pad(size(img), max(1,filt_size), max(1,filt_size-min(floor(filt_size.*0.05)))));
|
|
end |