mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 18:29:08 +09:00
initial commit
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
% GARRAY function that helps to wrap the GPU functions for user so that CPU and
|
||||
% GPU code is identical
|
||||
% If gpuDeviceCount > 0 or move_on_GPU == true, the returned array will be
|
||||
% moved to GPU, otherwise it will be returned as single
|
||||
%
|
||||
% array = Garray(array, move_on_GPU = true)
|
||||
%
|
||||
% Inputs:
|
||||
% **array Ndim array
|
||||
% **move_on_GPU if true, use GPU if possible
|
||||
% retuns:
|
||||
% ++array Ndim array single or gpuArray single
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 array = Garray(array, move_on_GPU)
|
||||
persistent use_gpu
|
||||
if nargin == 2 && ~isempty(move_on_GPU)
|
||||
use_gpu = move_on_GPU;
|
||||
elseif isempty(use_gpu)
|
||||
use_gpu = gpuDeviceCount > 0; % always use GPU if not asked otherwise
|
||||
end
|
||||
|
||||
if isa(array, 'double') && ~issparse(array)
|
||||
%% avoid doubles ...
|
||||
array = single(array);
|
||||
end
|
||||
|
||||
if isa(array, 'gpuArray') || ~use_gpu
|
||||
return
|
||||
end
|
||||
|
||||
array = gpuArray(array);
|
||||
|
||||
end
|
||||
@@ -0,0 +1,69 @@
|
||||
% ABSPATH translate special symbols such as ~, ../, ./, in path to the absolute
|
||||
% path
|
||||
%
|
||||
% filename_with_path = abspath(filename_with_path)
|
||||
% Inputs:
|
||||
% **filename_with_path original path
|
||||
% Outputs:
|
||||
% **filename_with_path corrected path without special symbols
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 filename_with_path = abspath(filename_with_path)
|
||||
if isunix
|
||||
% replace home path
|
||||
if startsWith(filename_with_path, '~/')
|
||||
filename_with_path = replace(filename_with_path, '~/', [char(java.lang.System.getProperty('user.home')), '/']);
|
||||
end
|
||||
% replace root
|
||||
nsteps = numel(strfind(filename_with_path, '../'));
|
||||
if nsteps > 0 && startsWith(filename_with_path, '../')
|
||||
new_path = pwd;
|
||||
for ii = 1:nsteps
|
||||
new_path = fileparts(new_path); % remove the last folder from the path
|
||||
end
|
||||
filename_with_path = replace(filename_with_path, repmat('../', [1 nsteps]), [new_path, '/']);
|
||||
end
|
||||
% replace current folder
|
||||
if startsWith(filename_with_path, './')
|
||||
filename_with_path = replace(filename_with_path, './', [pwd, '/']);
|
||||
end
|
||||
elseif ispc
|
||||
filename_with_path = replace(filename_with_path, '/', '\');
|
||||
filename_with_path = replace(filename_with_path, '.\', [pwd, '\']);
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
% full_array = add_to_3D_projection(small_array,full_array, positions_offset, indices,add_values, add_atomic, use_MEX)
|
||||
% add one small 3D block into a large 3D array with offset given by
|
||||
% positions_offset vector and perform this operation only for slices selected by
|
||||
% indiced vector
|
||||
%
|
||||
% Inputs:
|
||||
% **full_array - array to which the small_array will be added / written
|
||||
% **small_array - array used to be added to large array
|
||||
% **positions_offset - [Nangles x 2] offset from (1,1) coordinate in pixels
|
||||
% for each slice , if provide only [1x2] vector, assume the same
|
||||
% offset for each slice
|
||||
% **indices - add only to selected sliced of the full_array
|
||||
% *optional*
|
||||
% **add_values - (default==true) add values instead of rewritting
|
||||
% **add_atomic - (default==true) add values in atomic way, slow but it allows overlapping regions
|
||||
% **use_MEX - (use_MEX==true) use fast mex code
|
||||
% *returns*
|
||||
% ++full_array or none, results were writted !directly! to the input
|
||||
% array full_array, there is not need to take any output if MEX
|
||||
% function add_to_3D_projection was used
|
||||
%
|
||||
% Compilation from Matlab:
|
||||
% mex -R2018a 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" add_to_3D_projection_mex.cpp
|
||||
% Usage from Matlab:
|
||||
%
|
||||
% full_array = (rand(1000, 1000, 200, 'single'));
|
||||
% small_array = (zeros(500, 500, 100, 'single'));
|
||||
%
|
||||
% positions_offset = (10*rand(100,2));
|
||||
% indices = ([1:100]); % indices are starting from 1 !!
|
||||
% add_values = true;
|
||||
% add_to_3D_projection(small_array,full_array,positions_offset, indices,add_values);
|
||||
|
||||
|
||||
|
||||
% *-----------------------------------------------------------------------*
|
||||
% | |
|
||||
% | 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 full_array = add_to_3D_projection(small_array,full_array, positions_offset, indices,add_values, add_atomic, use_MEX)
|
||||
|
||||
if nargin < 7
|
||||
use_MEX = true;
|
||||
end
|
||||
if nargin < 6
|
||||
add_atomic = true;
|
||||
end
|
||||
if nargin < 5
|
||||
add_values = true;
|
||||
end
|
||||
if size(positions_offset,1)==1
|
||||
positions_offset = repmat(positions_offset, numel(indices), 1);
|
||||
end
|
||||
if use_MEX && ~isa(full_array, 'gpuArray') && ~verLessThan('matlab', '9.4') && ~islogical(small_array) % logical arrays not yet implemented
|
||||
%% run fast MEX-based code if possible
|
||||
try
|
||||
add_to_3D_projection_mex(small_array,full_array, int32(positions_offset), int32(indices),add_values>0,add_atomic>0);
|
||||
catch err
|
||||
% recompile the scripts if needed
|
||||
if any(strcmp(err.identifier, { 'MATLAB:UndefinedFunction','MATLAB:mex:ErrInvalidMEXFile'}))
|
||||
utils.verbose(0, 'Recompilation of MEX functions ... ')
|
||||
path = replace(mfilename('fullpath'), mfilename, '');
|
||||
mex('-R2018a','-O', 'CFLAGS="\$CFLAGS -fopenmp"', '-O','LDFLAGS="\$LDFLAGS -fopenmp"',[path,'private/add_to_3D_projection_mex.cpp'], '-output', [path, 'private/add_to_3D_projection_mex'])
|
||||
add_to_3D_projection_mex(small_array,full_array, int32(positions_offset), int32(indices),add_values>0,add_atomic>0);
|
||||
else
|
||||
rethrow(err)
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
%% matlab alternative to the MEX file , (much slower)
|
||||
positions_offset = round(positions_offset);
|
||||
N_f = size(full_array);
|
||||
N_s = size(small_array);
|
||||
|
||||
for ii = 1:size(positions_offset,1)
|
||||
jj = min(indices(ii),size(full_array,3));
|
||||
for i = 1:2
|
||||
ind_f{i} = max(1, 1+positions_offset(ii,i)):min(N_f(i),positions_offset(ii,i)+N_s(i));
|
||||
ind_s{i} = ((ind_f{i}(1)-positions_offset(ii,i))):(ind_f{i}(end)-positions_offset(ii,i));
|
||||
end
|
||||
if add_values
|
||||
full_array(ind_f{:},jj) = full_array(ind_f{:},jj) + small_array(ind_s{:},min(ii, size(small_array,3)));
|
||||
else
|
||||
full_array(ind_f{:},jj) = small_array(ind_s{:},min(ii, size(small_array,3)));
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
% function used to correct the image orientation of mcs_mesh data.
|
||||
% [output, output_pos] = adjust_projection(input, snake_scan, fast_axis_x, positions)
|
||||
% input = data to be corrected. For mcs the data should be a 2D matrix.
|
||||
% snake_scan = 0 for off and 1 for on
|
||||
% fast_axis_x = 1 for fast axis along x, 0 for fast axis along y
|
||||
%
|
||||
% output = corrected data
|
||||
% output_pos = corrected output positions, could be used to see if
|
||||
% there was a problem with the correction
|
||||
% For snake scans the routine decides the flipping based on the positions
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [output, output_pos] = adjust_projection(input, snake_scan, fast_axis_x, positions)
|
||||
|
||||
if nargin < 4
|
||||
positions = [];
|
||||
end
|
||||
|
||||
output_temp = input;
|
||||
output_pos = positions;
|
||||
|
||||
%%% Sanity checks %%%
|
||||
if ~isempty(output_pos)
|
||||
%%% fast axis direction %%%
|
||||
average_x_step_fast_axis = mean(mean(abs(diff(output_pos(:,:,1),1,1))));
|
||||
average_y_step_fast_axis = mean(mean(abs(diff(output_pos(:,:,2),1,1))));
|
||||
fast_axis_x_from_pos = fast_axis_x;
|
||||
if (fast_axis_x)&&(average_x_step_fast_axis < average_y_step_fast_axis)
|
||||
warning('You specified fast_axis_x true, but the positions seem to be for fast axis along y')
|
||||
fast_axis_x_from_pos = false;
|
||||
fast_axis_ind = 2;
|
||||
slow_axis_ind = 1;
|
||||
elseif (~fast_axis_x)&&(average_x_step_fast_axis > average_y_step_fast_axis)
|
||||
warning('You specified fast_axis_x false, but the positions seem to be for fast axis along x')
|
||||
fast_axis_x_from_pos = true;
|
||||
fast_axis_ind = 1;
|
||||
slow_axis_ind = 2;
|
||||
elseif fast_axis_x
|
||||
fast_axis_ind = 1;
|
||||
slow_axis_ind = 2;
|
||||
elseif ~fast_axis_x
|
||||
fast_axis_ind =2;
|
||||
slow_axis_ind = 1;
|
||||
end
|
||||
%%% Scan quality check %%%
|
||||
if ~any(output_pos(:)==0)
|
||||
aux_fast = abs(diff(output_pos(:,:,fast_axis_ind),1,1));
|
||||
aux_slow = abs(diff(output_pos(:,:,slow_axis_ind),1,2));
|
||||
average_fastaxis_absstep = mean(aux_fast(:));
|
||||
average_slowaxis_absstep = mean(aux_slow(:));
|
||||
std_fastaxis_absstep = std(aux_fast(:));
|
||||
std_slowaxis_absstep = std(aux_slow(:));
|
||||
step_text = sprintf('\n Step, (fast axis,slow axis) +/- (std,std) = (%.2f,%.2f) +/- (%.2f,%.2f) microns.',...
|
||||
average_fastaxis_absstep*1e3,average_slowaxis_absstep*1e3,std_fastaxis_absstep*1e3,std_slowaxis_absstep*1e3);
|
||||
if (std_fastaxis_absstep>average_fastaxis_absstep*0.05)||(std_slowaxis_absstep>average_slowaxis_absstep*0.05)
|
||||
warning(step_text)
|
||||
pause(2)
|
||||
else
|
||||
if nargout>1
|
||||
disp(step_text);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
%%% snake scans %%%
|
||||
average_fastaxis_step = mean(diff(output_pos(:,:,fast_axis_ind),1,1));
|
||||
% is this a snake scan?
|
||||
if abs(average_fastaxis_step(2)-average_fastaxis_step(3))==0
|
||||
% Do nothing, data has not been loaded
|
||||
snake_scan_from_pos = snake_scan;
|
||||
elseif abs(average_fastaxis_step(2)-average_fastaxis_step(3))>abs(average_fastaxis_step(1))
|
||||
snake_scan_from_pos = true;
|
||||
else
|
||||
snake_scan_from_pos = false;
|
||||
end
|
||||
|
||||
if snake_scan ~= snake_scan_from_pos
|
||||
warning(['You specified snake_scan = ' num2str(snake_scan) ' but from the positions it seems that snake_scan = ' num2str(snake_scan_from_pos)])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
%%% Handling the flipping of the data %%%
|
||||
if snake_scan %
|
||||
startflipind = 1;
|
||||
if ~isempty(output_pos)
|
||||
if mean(diff(output_pos(:,1,fast_axis_ind),1,1))>0
|
||||
startflipind = 2;
|
||||
else
|
||||
startflipind = 1;
|
||||
end
|
||||
output_pos(:,startflipind:2:end,:) = flipud(output_pos(:,startflipind:2:end,:));
|
||||
end
|
||||
output_temp(:,startflipind:2:end,:,:) = flipud(output_temp(:,startflipind:2:end,:,:));
|
||||
end
|
||||
|
||||
if fast_axis_x
|
||||
output_temp = permute(output_temp,[2 1 3]);
|
||||
output_pos = permute(output_pos, [2 1 3]);
|
||||
end
|
||||
|
||||
output = rot90(output_temp,2);
|
||||
output_pos = rot90(output_pos,2);
|
||||
|
||||
|
||||
% if ~isempty(output_pos)
|
||||
% if (mean(mean(diff(output_pos(:,:,1),1,2)))>0)||(mean(mean(diff(output_pos(:,:,2),1,2)))>0)
|
||||
% warning('Something is wrong with the positions, I dont know what so Ill show you in a figure of the positions after adjusting them. Positions should monotonically decrease with increase x or y coordinate')
|
||||
% figure(123)
|
||||
% subplot(1,2,1)
|
||||
% imagesc(output_pos(:,:,1))
|
||||
% title('X position')
|
||||
% subplot(1,2,2)
|
||||
% imagesc(output_pos(:,:,2))
|
||||
% title('Y position')
|
||||
% end
|
||||
% end
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
% APPLY_3D_APODIZATION Smoothly apodize tomogram to avoid sharp edges and air affecting
|
||||
% the FRC analysis
|
||||
%
|
||||
% [tomogram,circulo] = apply_3D_apodization(tomogram, rad_apod, axial_apod, radial_smooth)
|
||||
%
|
||||
% Inputs:
|
||||
% **tomogram - volume to be apodized
|
||||
% **rad_apod - number of pixels to be zeroed from edge of the tomogram
|
||||
% **axial_apod - roughly number of pixels to be zeroed from top / bottom
|
||||
% **radial_smooth - smoothness of the apodization in pixels, default = Npix/10
|
||||
% **layer_dim
|
||||
% Outputs:
|
||||
% ++tomogram - apodized volume
|
||||
% ++circulo -apodization mask
|
||||
% MODIFIED BY YJ TO ALLOW UNEVEN SIZES
|
||||
|
||||
function [tomogram,circulo] = apply_3D_apodization(tomogram, rad_apod, axial_apod, radial_smooth )
|
||||
import utils.*
|
||||
[Npix_y,Npix_x,Nlayers] = size(tomogram);
|
||||
Npix = max(Npix_y,Npix_x);
|
||||
if nargin < 4
|
||||
radial_smooth = Npix/10;
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
axial_apod = [];
|
||||
end
|
||||
if ~isempty(rad_apod)
|
||||
xt = -Npix/2:Npix/2-1;
|
||||
[X,Y] = meshgrid(xt,xt);
|
||||
radial_smooth = max(radial_smooth,1); % prevent division by zero
|
||||
circulo= single(1-radtap(X,Y,radial_smooth,round(Npix/2-rad_apod-radial_smooth)));
|
||||
if Npix_y~=Npix_x
|
||||
circulo= crop_pad( circulo, [Npix_y,Npix_x]);
|
||||
end
|
||||
tomogram = bsxfun(@times, tomogram, circulo);
|
||||
end
|
||||
if ~isempty(axial_apod) && Nlayers > 1
|
||||
filters = fract_hanning_pad(Nlayers,Nlayers,max(0,round(Nlayers-2*axial_apod)));
|
||||
filters = ifftshift(filters(:,1));
|
||||
tomogram = bsxfun(@times,tomogram,reshape(filters,1,1,[]));
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,215 @@
|
||||
% mask = auto_mask_find(im,[<name>,<value>])
|
||||
%
|
||||
% im Input complex valued image
|
||||
%
|
||||
% Optional parameters:
|
||||
%
|
||||
% margins Two element array that indicates the (y,x) margins to exclude
|
||||
% from the edge of the mask window. For example to exclude the
|
||||
% noise around ptychography reconstructions, default 0.
|
||||
% smoothing Size of averaging window on the phase derivative, default
|
||||
% 10.
|
||||
% gradientrange Size of the histogram windown when selecting valid gradient
|
||||
% regions, in radians per pixel, default 1;
|
||||
% show_bivariate Show the bivariate histogram of the gradient, useful
|
||||
% for debugging. Set to the number of figure you'd like
|
||||
% it to appear.
|
||||
%
|
||||
% Morphological operations to remove point details in the mask
|
||||
%
|
||||
% close_size Size of closing window, removes dark bubbles from the mask,
|
||||
% default 15. ( = 1 for no effect)
|
||||
% open_size Size of opening window, removes bright bubbles from mask,
|
||||
% default 120. ( = 1 for no effect)
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 mask = auto_mask_find(im,varargin)
|
||||
import plotting.franzmap
|
||||
|
||||
% Defaults
|
||||
margin = [0 0];
|
||||
smoothing = 10;
|
||||
gradientrange = 1;
|
||||
close_size = 15;
|
||||
open_size = 120;
|
||||
show_bivariate = 0;
|
||||
zero_columns = [];
|
||||
|
||||
% parse the variable input arguments not handled by auto_mask_find
|
||||
vararg = cell(0,0);
|
||||
for ind = 1:2:length(varargin)
|
||||
name = varargin{ind};
|
||||
value = varargin{ind+1};
|
||||
switch lower(name)
|
||||
case 'margin'
|
||||
margin = value;
|
||||
case 'smoothing'
|
||||
smoothing = value;
|
||||
case 'gradientrange'
|
||||
gradientrange = value;
|
||||
case 'close_size'
|
||||
close_size = value;
|
||||
case 'open_size'
|
||||
open_size = value;
|
||||
case 'show_bivariate'
|
||||
show_bivariate = value;
|
||||
case 'zero_columns'
|
||||
zero_columns = value;
|
||||
otherwise
|
||||
vararg{end+1} = name;
|
||||
vararg{end+1} = value;
|
||||
end
|
||||
end
|
||||
|
||||
% Some checks
|
||||
if numel(margin)~= 2
|
||||
error('Margin variable should have two elements')
|
||||
end
|
||||
|
||||
if close_size < 1
|
||||
error('erode_size must be an integer 1 or greater')
|
||||
end
|
||||
|
||||
if open_size < 1
|
||||
error('erode_size must be an integer 1 or greater')
|
||||
end
|
||||
|
||||
if gradientrange < 0
|
||||
error('gradientrange must be positive')
|
||||
end
|
||||
|
||||
mask = true(size(im));
|
||||
|
||||
|
||||
mask(1:1+margin(1),:) = false;
|
||||
mask(end-margin(1):end,:) = false;
|
||||
mask(:,1:1+margin(2)) = false;
|
||||
mask(:,end-margin(2):end) = false;
|
||||
if ~isempty(zero_columns)
|
||||
mask(:,zero_columns) = false;
|
||||
end
|
||||
|
||||
% Compute phase gradient based on phasor
|
||||
ph = exp(1i*angle(im));
|
||||
[gx, gy] = gradient(ph);
|
||||
gx = -real(1i*gx./ph);
|
||||
gy = -real(1i*gy./ph);
|
||||
|
||||
kernel = ones(smoothing);
|
||||
gx = conv2(gx,kernel,'same');
|
||||
gy = conv2(gy,kernel,'same');
|
||||
|
||||
gaux(:,1) = gy(mask(:));
|
||||
gaux(:,2) = gx(mask(:));
|
||||
|
||||
[N,C] = hist3_own(gaux,[100 100]);
|
||||
[ny nx] = find(N == max(N(:)),1);
|
||||
|
||||
% masky = (gy>C{1}(ny-gradientrange))&(gy<C{1}(ny+gradientrange));
|
||||
% maskx = (gx>C{2}(nx-gradientrange))&(gx<C{2}(nx+gradientrange));
|
||||
masky = (gy>C{1}(ny)-gradientrange)&(gy<C{1}(ny)+gradientrange);
|
||||
maskx = (gx>C{2}(nx)-gradientrange)&(gx<C{2}(nx)+gradientrange);
|
||||
|
||||
maskxy = maskx&masky;
|
||||
% figure(1000); imagesc(masky); axis xy; colormap franzmap
|
||||
% % Erosion
|
||||
% erodemask = ones(erode_size);
|
||||
% maskxy = erode_own(maskxy,erodemask);
|
||||
%
|
||||
% % Dilation
|
||||
% dilatemask = ones(dilate_size);
|
||||
% maskxy = dilate_own(maskxy,dilatemask);
|
||||
|
||||
maskxy = close_own(maskxy,ones(close_size));
|
||||
maskxy = open_own(maskxy,ones(open_size));
|
||||
|
||||
mask = mask&maskxy;
|
||||
|
||||
if show_bivariate > 0
|
||||
figure(show_bivariate);
|
||||
imagesc(log10(N));
|
||||
colormap franzmap
|
||||
end
|
||||
end
|
||||
|
||||
function imout = erode_own(im,erodemask)
|
||||
% My own erosion to avoid using Image Processing Toolbox
|
||||
% Receives a binary image and kernel and performs erosion of the image
|
||||
erodemask = erodemask/sum(erodemask(:));
|
||||
imout = conv2(double(im),erodemask,'same');
|
||||
imout = imout>0.99999;
|
||||
end
|
||||
|
||||
function imout = dilate_own(im,dilatemask)
|
||||
% My own dilation to avoid using Image Processing Toolbox
|
||||
% Receives a binary image and kernel and performs erosion of the image
|
||||
dilatemask = dilatemask/sum(dilatemask(:));
|
||||
imout = conv2(double(im),dilatemask,'same');
|
||||
imout = imout>0;
|
||||
end
|
||||
|
||||
function imout = open_own(im,openmask)
|
||||
imout = dilate_own(erode_own(im,openmask),openmask);
|
||||
end
|
||||
|
||||
function imout = close_own(im,closemask)
|
||||
imout = erode_own(dilate_own(im,closemask),closemask);
|
||||
end
|
||||
|
||||
function [histout, C] = hist3_own(gaux,bins)
|
||||
eps = 0.001; % esther
|
||||
min_gaux1 = min(gaux(:,1));
|
||||
max_gaux1 = max(gaux(:,1));
|
||||
inter_1 = (max_gaux1-min_gaux1)/bins(1);
|
||||
|
||||
min_gaux2 = min(gaux(:,2));
|
||||
max_gaux2 = max(gaux(:,2));
|
||||
inter_2 = (max_gaux2-min_gaux2)/bins(2);
|
||||
|
||||
indarray1 = floor( (1-eps)*bins(1)*( gaux(:,1)-min_gaux1 )./( max_gaux1-min_gaux1 ) + 1 );
|
||||
indarray2 = floor( (1-eps)*bins(2)*( gaux(:,2)-min_gaux2 )./( max_gaux2-min_gaux2 ) + 1 );
|
||||
|
||||
histout = zeros(bins);
|
||||
|
||||
for ii = 1:numel(indarray1)
|
||||
histout(indarray1(ii),indarray2(ii)) = histout(indarray1(ii),indarray2(ii)) + 1;
|
||||
end
|
||||
|
||||
C{1} = linspace(min_gaux1+inter_1/2,max_gaux1-inter_1/2,bins(1));
|
||||
C{2} = linspace(min_gaux2+inter_2/2,max_gaux2-inter_2/2,bins(2));
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
% BINNING_2D - bin data along first two axis,
|
||||
% x = binning_2D(x, binning, centered)
|
||||
%
|
||||
% Inputs:
|
||||
% **x - original array, upsampling will be performed only along the first two axis, array size has to be dividable by binning size
|
||||
% **binning - scalar or (2,1) array, positive integer binning factor
|
||||
% *Optional*:
|
||||
% **centered - default false, shift the binning by binning/2 offset
|
||||
%
|
||||
% Outputs:
|
||||
% ++x - binned array
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 x = binning_2D(x, binning, centered)
|
||||
|
||||
if all(binning <= 1); return ; end
|
||||
|
||||
if nargin < 3
|
||||
centered = false;
|
||||
end
|
||||
Npix = [size(x,1), size(x,2), size(x,3)];
|
||||
if isscalar(binning); binning = repmat(binning, 1,2); end
|
||||
binning = reshape(binning,1,[]);
|
||||
|
||||
if all(Npix(1:2) >= binning(:))
|
||||
% faster but less general version
|
||||
if centered
|
||||
% it will be slower due to memory copy
|
||||
x = x(ceil(binning(1)/2):end-ceil(binning(1)/2)-1, ceil(binning(2)/2):end-ceil(binning(2)/2)-1,:);
|
||||
Npix(1:2) = Npix(1:2) - binning;
|
||||
end
|
||||
if any(~math.isint(Npix(1:2)./binning))
|
||||
% is the array cannot be easily split for binning, crop it
|
||||
% it will be slower due to memory copy
|
||||
Npix(1:2) = floor(Npix(1:2)./binning) .* binning;
|
||||
x = x(1:Npix(1),1:Npix(2),:);
|
||||
end
|
||||
x = reshape(x,binning(1), Npix(1)/binning(1), binning(2), Npix(2)/binning(2), Npix(3));
|
||||
x = squeeze(sum(sum(x,1),3));
|
||||
x = x / prod(binning(1:2));
|
||||
if centered
|
||||
x = padarray(x, [1,1], 'replicate', 'post'); % account for the removed pixels to keep the size
|
||||
end
|
||||
else
|
||||
x = convn(single(x), ones(binning, 'single'), 'same');
|
||||
norm = binning.^2;
|
||||
ind = {ceil(binning(1)/2):binning(1):Npix(1), ceil(binning(2)/2):binning(2):Npix(2)};
|
||||
% avoid issues with void dimensions
|
||||
for i = find(Npix == 1)
|
||||
ind{i} = ':';
|
||||
norm = norm / binning(i); %% avoid summing up by convolution
|
||||
end
|
||||
x = x(ind{:},:) / norm;
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
% BINNING_3D - bin data along first three axis,
|
||||
% x = binning_3D(x, binning, centered)
|
||||
%
|
||||
% Inputs:
|
||||
% **x - original array, upsampling will be performed only along the first three axis, array size has to be dividable by binning size
|
||||
% **binning - scalar or (3,1) array, positive integer binning factor
|
||||
% *optional*
|
||||
% **centered - default false, shift the binning by binning/2 offset
|
||||
%
|
||||
% returns:
|
||||
% ++x - binned array
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 x = binning_3D(x, binning, centered)
|
||||
if all(binning == 1); return ; end
|
||||
if nargin < 3
|
||||
centered = false;
|
||||
end
|
||||
if ismatrix(x)
|
||||
x = utils.binning_2D(x,binning, centered);
|
||||
return
|
||||
end
|
||||
binning = reshape(binning,1,[]);
|
||||
|
||||
assert(ndims(x) == 3, 'Input has to be 3D array')
|
||||
assert(all(mod(size(x),binning)==0), 'Array has to splitable by binning')
|
||||
assert(all(size(x) >binning ), 'Array has to larger than binning')
|
||||
|
||||
Npix = size(x);
|
||||
if isscalar(binning)
|
||||
binning = repmat(binning,3,1);
|
||||
end
|
||||
|
||||
if centered
|
||||
% make the bins centered
|
||||
x = x(ceil(binning(1)/2):end-ceil(binning(1)/2)-1, ceil(binning(2)/2):end-ceil(binning(2)/2)-1,ceil(binning(3)/2):end-ceil(binning(3)/2)-1);
|
||||
Npix(1:3) = Npix(1:3) - reshape(binning,1,[]);
|
||||
end
|
||||
|
||||
x = reshape(x,binning(1), Npix(1)/binning(1), binning(2), Npix(2)/binning(2), binning(3), Npix(3)/binning(3) );
|
||||
x = squeeze(sum(sum(sum(x,1),3),5));
|
||||
x = x / prod(binning);
|
||||
|
||||
end
|
||||
@@ -0,0 +1,110 @@
|
||||
% [outstr] = char_to_cellstr(inchars,nl_only)
|
||||
% Convert an array of text to a cell array of lines.
|
||||
|
||||
% Filename: $RCSfile: char_to_cellstr.m,v $
|
||||
%
|
||||
% $Revision: 1.4 $ $Date: 2014/04/11 10:57:20 $
|
||||
% $Author: $
|
||||
% $Tag: $
|
||||
%
|
||||
% Description:
|
||||
% Convert an array of text to a cell array of lines.
|
||||
%
|
||||
% Note:
|
||||
% Used for making file headers accessible.
|
||||
%
|
||||
% Dependencies:
|
||||
% none
|
||||
%
|
||||
%
|
||||
% history:
|
||||
%
|
||||
% June 22nd 2008: bug fix for fliread adding the nl_only
|
||||
% parameter, to be replaced by named parameter later on
|
||||
%
|
||||
% May 9th 2008: 1st version
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [outstr] = char_to_cellstr(inchars,nl_only)
|
||||
|
||||
if (nargin < 2)
|
||||
nl_only = 0;
|
||||
end
|
||||
|
||||
% get positions of end-of-line signatures
|
||||
eol_ind = regexp(inchars,'\r\n');
|
||||
eol_offs = 1;
|
||||
if ((length(eol_ind) < 1) || (nl_only))
|
||||
eol_ind = regexp(inchars,'\n');
|
||||
eol_offs = 0;
|
||||
end
|
||||
if (length(eol_ind) < 1)
|
||||
eol_ind = length(inchars) +1;
|
||||
end
|
||||
if (length(eol_ind) < 1)
|
||||
outstr = [];
|
||||
return;
|
||||
end
|
||||
|
||||
% dimension return array with number of lines
|
||||
outstr = cell(length(eol_ind),1);
|
||||
|
||||
% copy the lines to the return array, not suppressing empty lines
|
||||
start_pos = 1;
|
||||
ind_out = 1;
|
||||
for (ind = 1:length(eol_ind))
|
||||
end_pos = eol_ind(ind) -1;
|
||||
% cut off trailing spaces
|
||||
while ((end_pos >= start_pos) && (inchars(end_pos) == ' '))
|
||||
end_pos = end_pos -1;
|
||||
end
|
||||
% store non-empty strings
|
||||
if (end_pos >= start_pos)
|
||||
outstr{ind_out} = inchars(start_pos:end_pos);
|
||||
else
|
||||
outstr{ind_out} = '';
|
||||
end
|
||||
ind_out = ind_out +1;
|
||||
|
||||
start_pos = eol_ind(ind) +1 + eol_offs;
|
||||
ind = ind +1;
|
||||
end
|
||||
|
||||
% resize cell array in case of empty lines
|
||||
if (ind_out <= length(eol_ind))
|
||||
outstr = outstr(1:(ind_out-1));
|
||||
end
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
|
||||
% FUNCTION [mem_avail, mem_total] = check_availible_memory()
|
||||
% get availible free memory in linux in MB
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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) 2018 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 varargout =check_available_memory()
|
||||
|
||||
if isunix
|
||||
meminfo = importdata('/proc/meminfo');
|
||||
mem_total = str2num((regexprep(meminfo.textdata{1}, '[a-zA-Z \:]', '')))/1e3;
|
||||
mem_avail = str2num((regexprep(meminfo.textdata{3}, '[a-zA-Z \:]', '')))/1e3;
|
||||
|
||||
|
||||
if nargout > 0
|
||||
vlevel = 2;
|
||||
else
|
||||
vlevel = 0;
|
||||
end
|
||||
utils.verbose(vlevel, '==== %.0f GB == %.0f%% RAM free ====', mem_avail/1e3, mem_avail/mem_total*100);
|
||||
|
||||
if mem_avail/mem_total < 0.2
|
||||
warning('Less than 20% RAM left..');
|
||||
!free -h
|
||||
end
|
||||
elseif ispc
|
||||
[~,sV] = memory;
|
||||
mem_avail = sV.PhysicalMemory.Available/1e6;
|
||||
mem_total = sV.PhysicalMemory.Total/1e6;
|
||||
else
|
||||
error('Unsupported architecture')
|
||||
end
|
||||
|
||||
|
||||
if nargout > 0
|
||||
varargout = {mem_avail, mem_total};
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,144 @@
|
||||
% CHECK_CPU_LOAD returns user cpu usage of specified hosts
|
||||
%
|
||||
% hosts (optional)... list of nodes; use 'x12sa' for all x12sa nodes
|
||||
% used_nodes (optional)... prints warning/summary for used nodes (default: true)
|
||||
% ssh_auth (optional) ... system echo if ssh authentication is needed (default: false)
|
||||
% thr (optional)... set threshold for used nodes (default: 15 %)
|
||||
% vm_cycles (optional)... number of cycles for cpu usage (default: 2)
|
||||
|
||||
% 03/2017
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ cpu_load_bl, any_used_cpu ] = check_cpu_load( varargin)
|
||||
|
||||
any_used_cpu = false;
|
||||
|
||||
[~, hostname] = system('hostname');
|
||||
host_pre = strsplit(hostname, '-');
|
||||
switch host_pre{1}
|
||||
case 'ra'
|
||||
vmstat_nr = 13;
|
||||
case 'x12sa'
|
||||
vmstat_nr = 15;
|
||||
otherwise
|
||||
vmstat_nr = 15;
|
||||
end
|
||||
|
||||
if nargin < 1
|
||||
|
||||
switch host_pre{1}
|
||||
case 'x12sa'
|
||||
hosts = {'x12sa-cn-1', 'x12sa-cn-2', 'x12sa-cn-3', 'x12sa-cn-4', 'x12sa-cn-5', 'x12sa-cn-6'};
|
||||
otherwise
|
||||
error('Please specify your hosts.');
|
||||
end
|
||||
else
|
||||
if ischar(varargin{1})
|
||||
varargin{1} = strcell(varargin{1}); % backward compatibility
|
||||
end
|
||||
hosts = varargin{1};
|
||||
if strcmp(varargin{1}, 'x12sa')
|
||||
hosts = {'x12sa-cn-1', 'x12sa-cn-2', 'x12sa-cn-3', 'x12sa-cn-4', 'x12sa-cn-5', 'x12sa-cn-6'};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% check if warnings/summary are needed
|
||||
if nargin > 1
|
||||
used_nodes = varargin{2};
|
||||
else
|
||||
used_nodes = true;
|
||||
end
|
||||
|
||||
% check ssh_auth
|
||||
if nargin > 2
|
||||
ssh_auth = varargin{3};
|
||||
else
|
||||
ssh_auth = false;
|
||||
end
|
||||
|
||||
% check if thr for cpu load is specified
|
||||
if nargin > 3
|
||||
thr = varargin{4};
|
||||
else
|
||||
thr = 15;
|
||||
end
|
||||
|
||||
% check if cycles are specified
|
||||
if nargin > 4
|
||||
top_cycles = varargin{5};
|
||||
else
|
||||
top_cycles = 2;
|
||||
end
|
||||
|
||||
cycles = sprintf('%i', top_cycles);
|
||||
|
||||
cpu_load_bl = zeros(length(hosts),1);
|
||||
|
||||
% ssh to hosts and check cpu load
|
||||
for i=1:size(hosts,1)
|
||||
|
||||
ssh_call_cpu = ['ssh ' hosts{i}, ' vmstat 1 ' cycles ' | tail -1 | awk ''{print 100 - $' num2str(vmstat_nr) '}'''];
|
||||
|
||||
if ssh_auth
|
||||
[~, result] = system(ssh_call_cpu, '-echo');
|
||||
else
|
||||
[~, result] = system(ssh_call_cpu);
|
||||
end
|
||||
res = strsplit(result, '\n');
|
||||
for j=1:size(res,2)
|
||||
if ~isnan(str2double(res{j}))
|
||||
cpu_load_bl(i) = str2double(res{j});
|
||||
if used_nodes
|
||||
fprintf('%s: %i%%\n', hosts{i}, cpu_load_bl(i));
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% print warnings and summary if needed
|
||||
if used_nodes
|
||||
for i=1:size(hosts)
|
||||
if cpu_load_bl(i) > thr
|
||||
fprintf('Host %s is currently used!\n', hosts{i});
|
||||
any_used_cpu = true;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
%CHECK_MATLAB_VERSION check matlab version to make sure it is compatible
|
||||
% ver... compatible version number in STRING
|
||||
%
|
||||
% EXAMPLE:
|
||||
% check_matlab_version('9.2')
|
||||
%
|
||||
% MATLAB 9.0 - 2016a
|
||||
% MATLAB 9.1 - 2016b
|
||||
% MATLAB 9.2 - 2017a
|
||||
% MATLAB 9.3 - 2017b
|
||||
|
||||
% modified by YJ for newer versions
|
||||
|
||||
function check_matlab_version( ver )
|
||||
|
||||
current_version = version;
|
||||
ver_str = strsplit(current_version, '.');
|
||||
ver_input_str = strsplit(ver, '.');
|
||||
|
||||
ver_input_num = [str2double(ver_input_str{1}), str2double(ver_input_str{2})];
|
||||
ver_num = [str2double(ver_str{1}), str2double(ver_str{2})];
|
||||
|
||||
if ver_num(1) == ver_input_num(1)
|
||||
if ver_num(2) < ver_input_num(2)
|
||||
warning('You are using Maltab version %d.%02d but the code was designed and tested with %d.%02d.',...
|
||||
ver_num(1),ver_num(2),ver_input_num(1),ver_input_num(2));
|
||||
end
|
||||
elseif ver_num(1) < ver_input_num(1)
|
||||
warning('You are using Maltab version %d.%02d but the code was designed and tested with %d.%02d.',...
|
||||
ver_num(1),ver_num(2),ver_input_num(1),ver_input_num(2));
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#! /bin/bash
|
||||
|
||||
path=$1
|
||||
|
||||
if [ -r $path ]
|
||||
then
|
||||
echo 1
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
|
||||
if [ -w $path ]
|
||||
then
|
||||
echo 1
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
|
||||
if [ -x $path ]
|
||||
then
|
||||
echo 1
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
%CHECK_PERM check r w x permissions for given path
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ result ] = check_perm( path )
|
||||
|
||||
external_call = ['./+utils/check_perm ' path];
|
||||
[~, stat] = system(external_call);
|
||||
stat = strsplit(stat, '\n');
|
||||
result = [str2double(stat{1}) str2double(stat{2}) str2double(stat{3}) ];
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
%COMPILE_APS_DIRNAME returns the default APS directory tree for a
|
||||
% given scan number
|
||||
%
|
||||
% EXAMPLE:
|
||||
% scan_dir = utils.compile_x12sa_dirname(10);
|
||||
% -> scan_dir = 'S00000-00999/S00010/'
|
||||
%
|
||||
% written by Yi Jiang, based on PSI's code
|
||||
|
||||
function scan_dir = compile_aps_dirname(scan_no)
|
||||
|
||||
scan_dir = sprintf('S%05d-%05d/S%05d/',floor(scan_no/1000)*1000, ...
|
||||
floor(scan_no/1000)*1000 + 999, ...
|
||||
scan_no);
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
%COMPILE_APS_DIRNAME returns the default APS directory tree for a
|
||||
% given scan number
|
||||
%
|
||||
% EXAMPLE:
|
||||
% scan_dir = utils.compile_x12sa_dirname(10);
|
||||
% -> scan_dir = 'S00000-00999/S00010/'
|
||||
%
|
||||
% written by Yi Jiang, based on PSI's code
|
||||
|
||||
function scan_dir = compile_cu_dirname(scan_no)
|
||||
|
||||
scan_dir = sprintf('S%05d-%05d/S%05d/',floor(scan_no/1000)*1000, ...
|
||||
floor(scan_no/1000)*1000 + 999, ...
|
||||
scan_no);
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
%COMPILE_X12SA_DIRNAME returns the default cSAXS directory tree for a
|
||||
% given scan number
|
||||
%
|
||||
% EXAMPLE:
|
||||
% scan_dir = utils.compile_x12sa_dirname(10);
|
||||
% -> scan_dir = 'S00000-00999/S00010/'
|
||||
%
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 scan_dir = compile_x12sa_dirname(scan_no)
|
||||
|
||||
scan_dir = sprintf('S%05d-%05d/S%05d/',floor(scan_no/1000)*1000, ...
|
||||
floor(scan_no/1000)*1000 + 999, ...
|
||||
scan_no);
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
% Call function without arguments for a detailed explanation of its use
|
||||
|
||||
% Filename: $RCSfile: compile_x12sa_filename.m,v $
|
||||
%
|
||||
% $Revision: 1.10 $ $Date: 2012/08/07 16:39:07 $
|
||||
% $Author: $
|
||||
% $Tag: $
|
||||
%
|
||||
% Description:
|
||||
% plot a STXM scan
|
||||
%
|
||||
% Note:
|
||||
% Call without arguments for a brief help text.
|
||||
%
|
||||
% Dependencies:
|
||||
% - image_read
|
||||
%
|
||||
% history:
|
||||
%
|
||||
% October 9th 2009:
|
||||
% remove BurstScan parameter, add DetectorNumber and SubExpWildcard
|
||||
% parameter
|
||||
%
|
||||
% August 5th 2009:
|
||||
% return just the directory in case of a negative point number
|
||||
%
|
||||
% September 5th 2009:
|
||||
% 1st version
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ filename, vararg_remain ] = compile_x12sa_filename(scan_no,point_no,varargin)
|
||||
import beamline.identify_eaccount
|
||||
import io.image_read
|
||||
import utils.identify_system
|
||||
import utils.compile_x12sa_dirname
|
||||
|
||||
% set default values
|
||||
sys_id = identify_system();
|
||||
switch sys_id
|
||||
case 'X12SA'
|
||||
base_path = '~/Data10/pilatus_1/';
|
||||
case 'CXS compute node'
|
||||
base_path = '/afs/psi.ch/project/cxs/';
|
||||
otherwise
|
||||
base_path = '';
|
||||
end
|
||||
|
||||
% base name, default starts with the current user name
|
||||
base_name = identify_eaccount();
|
||||
if (isempty(base_name))
|
||||
base_name = 'image_';
|
||||
else
|
||||
base_name = [ base_name '_' ];
|
||||
end
|
||||
|
||||
add_scan_dir = 1;
|
||||
|
||||
sub_exp_no = 0;
|
||||
|
||||
point_wildcard = 0;
|
||||
|
||||
subexp_wildcard = 0;
|
||||
|
||||
detector_number = 1;
|
||||
|
||||
file_extension = 'cbf';
|
||||
|
||||
% exit with an error message if unhandled named parameters are left at the
|
||||
% end of this macro
|
||||
if (nargout > 1)
|
||||
unhandled_par_error = 0;
|
||||
else
|
||||
unhandled_par_error = 1;
|
||||
end
|
||||
|
||||
% check minimum number of input arguments
|
||||
if (nargin < 2)
|
||||
fprintf('Usage:\n')
|
||||
fprintf('[filename]=%s(scan_no,point_no, [,<name>,<value>] ...]);\n',...
|
||||
mfilename);
|
||||
fprintf('The optional <name>,<value> pairs are:\n');
|
||||
fprintf('''BasePath'',<''path''> default is ''%s'', the scan directory is added\n',base_path);
|
||||
fprintf('''AddScanDir'',<0-no,1-yes> add the scan number specific directory part, default is %d\n',add_scan_dir);
|
||||
fprintf('''BaseName'',<''name''> default is ''%s''\n',base_name);
|
||||
fprintf('''FileExtension'',<''extension''> default is ''%s''\n',file_extension);
|
||||
fprintf('''SubExpNo'',<integer no.> sub exposure number at the end of the file name (not in burst mode), default is %d\n',sub_exp_no);
|
||||
fprintf('''DetectorNumber'',<1-Pilatus 2M, 2-Pilatus 300k, 3-Pilatus 100k>\n');
|
||||
fprintf(' specifies the detector, default is %d\n',detector_number);
|
||||
fprintf('''PointWildcard'',<0-no,1-yes> return a * for the point number in the filename, default is %d\n',point_wildcard);
|
||||
fprintf('''SubExpWildcard'',<0-no,1-yes> return a * for the sub-exposure number in the filename, default is %d\n',subexp_wildcard);
|
||||
fprintf('If a negative point number is specified then just the directory is returned.\n');
|
||||
fprintf('\n');
|
||||
error('At least the scan and point number have to be specified as input parameter.');
|
||||
end
|
||||
|
||||
% accept cell array with name/value pairs as well
|
||||
no_of_in_arg = nargin;
|
||||
if (nargin == 3)
|
||||
if (isempty(varargin))
|
||||
% ignore empty cell array
|
||||
no_of_in_arg = no_of_in_arg -1;
|
||||
else
|
||||
if (iscell(varargin{1}))
|
||||
% use a filled one given as first and only variable parameter
|
||||
varargin = varargin{1};
|
||||
no_of_in_arg = 2 + length(varargin);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% check number of input arguments
|
||||
if (rem(no_of_in_arg,2) ~= 0)
|
||||
error('The optional parameters have to be specified as ''name'',''value'' pairs');
|
||||
end
|
||||
|
||||
|
||||
% parse the variable input arguments
|
||||
vararg_remain = cell(0,0);
|
||||
for ind = 1:2:length(varargin)
|
||||
name = varargin{ind};
|
||||
value = varargin{ind+1};
|
||||
switch name
|
||||
case 'BasePath'
|
||||
base_path = value;
|
||||
case 'BaseName'
|
||||
base_name = value;
|
||||
case 'FileExtension'
|
||||
file_extension = value;
|
||||
case 'DetectorNumber'
|
||||
detector_number = value;
|
||||
if ((detector_number ~= 1) && (strcmp(base_path,'~/Data10/pilatus_1/')))
|
||||
base_path = sprintf('~/Data10/pilatus_%d/',detector_number);
|
||||
end
|
||||
case 'AddScanDir'
|
||||
add_scan_dir = value;
|
||||
case 'SubExpNo'
|
||||
sub_exp_no = value;
|
||||
case 'PointWildcard'
|
||||
point_wildcard = value;
|
||||
case 'SubExpWildcard'
|
||||
subexp_wildcard = value;
|
||||
case 'UnhandledParError'
|
||||
unhandled_par_error = value;
|
||||
otherwise
|
||||
vararg_remain{end+1} = name; %#ok<AGROW>
|
||||
vararg_remain{end+1} = value; %#ok<AGROW>
|
||||
end
|
||||
end
|
||||
% exit in case of unhandled named parameters, if this has not been switched
|
||||
% off
|
||||
if ((unhandled_par_error) && (~isempty(vararg_remain)))
|
||||
vararg_remain %#ok<NOPRT>
|
||||
error('Not all named parameters have been handled.');
|
||||
end
|
||||
|
||||
% add the detector number to the base name
|
||||
base_name = [ base_name num2str(detector_number) '_' ];
|
||||
|
||||
% compile the name of the automatically created scan directory
|
||||
if (add_scan_dir)
|
||||
scan_dir = compile_x12sa_dirname(scan_no);
|
||||
else
|
||||
scan_dir = '';
|
||||
end
|
||||
|
||||
% compile path and filename
|
||||
if (point_no < 0)
|
||||
% just the directory without a file name
|
||||
filename = fullfile(base_path,scan_dir);
|
||||
else
|
||||
filename = fullfile(base_path,scan_dir,sprintf('%s%05d_',base_name,scan_no));
|
||||
if (point_wildcard)
|
||||
filename = sprintf('%s*_',filename);
|
||||
else
|
||||
filename = sprintf('%s%05d_',filename,point_no);
|
||||
end
|
||||
|
||||
if (subexp_wildcard)
|
||||
filename = sprintf('%s*.%s',filename,file_extension);
|
||||
else
|
||||
filename = sprintf('%s%05d.%s',filename,sub_exp_no,file_extension);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,180 @@
|
||||
%CONVERT2HDF5_WRAPPER converts Eiger 1.5M raw data files to HDF5 and
|
||||
% deletes the raw files if the conversion has finished successfully
|
||||
% convert2hdf5_wrapper(raw_data_path)
|
||||
%
|
||||
% ** raw_data_path path to the eiger directory, e.g. ~/Data10/
|
||||
%
|
||||
% *optional*
|
||||
% ** scanID start at the given scan number
|
||||
%
|
||||
% EXAMPLES:
|
||||
% % start at scan number 1:
|
||||
% convert2hdf5_wrapper('~/Data10/');
|
||||
%
|
||||
% % start at scan number 150:
|
||||
% convert2hdf5_wrapper('~/Data10/', 150);
|
||||
%
|
||||
% Pleas note that the script is designed to be used during an ongoing
|
||||
% measurement, and therefore only converts n-1 datasets, that is it waits
|
||||
% until the next measurement has started.
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 convert2hdf5_wrapper(raw_data_path, varargin)
|
||||
import utils.*
|
||||
if nargin > 1
|
||||
scanID = varargin{1};
|
||||
else
|
||||
scanID = 1;
|
||||
end
|
||||
while true
|
||||
[started, newScan, specDatFile] = beamline.next_scan_started(raw_data_path, scanID);
|
||||
if started
|
||||
convert2hdf5(scanID, raw_data_path, specDatFile);
|
||||
fprintf('Converting scan %d\n', scanID);
|
||||
scanID = newScan;
|
||||
else
|
||||
fprintf('Waiting for next scan to start.\n');
|
||||
pause(1);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
function convert2hdf5(scan, raw_data_path, specDatFile)
|
||||
|
||||
% some defaults
|
||||
convertor_path = '~/Data10/bin/eiger1p5M_converter/hdf5MakerOMNY';
|
||||
xmlLayoutFile = '~/Data10/bin/nexus/layout.xml';
|
||||
orchestraPath = '~/Data10/specES1/scan_positions/';
|
||||
specParser = '~/Data10/matlab/+io/spec_reader/spec_reader';
|
||||
|
||||
% check if orchestraPath exists
|
||||
if exist(orchestraPath, 'dir')
|
||||
orchestraPath = ['--orchestra ' orchestraPath];
|
||||
else
|
||||
orchestraPath = '';
|
||||
end
|
||||
|
||||
load_dir = utils.compile_x12sa_dirname(scan);
|
||||
if exist('raw_data_path','var')&&exist(fullfile(raw_data_path,load_dir),'dir')
|
||||
load_dir = fullfile(raw_data_path,load_dir);
|
||||
elseif exist(['~/Data10/eiger_4/'],'dir')
|
||||
load_dir = ['~/Data10/eiger_4/' load_dir];
|
||||
elseif exist([raw_data_path,'eiger_4/'])
|
||||
load_dir = [raw_data_path,'/eiger_4/' load_dir];
|
||||
elseif exist([raw_data_path,'/eigeromny/'])
|
||||
load_dir = [raw_data_path,'/eigeromny/' load_dir];
|
||||
end
|
||||
|
||||
if ~exist(load_dir, 'dir')
|
||||
warning('Raw data path %s not found', load_dir)
|
||||
return
|
||||
end
|
||||
|
||||
testDir = [load_dir, '/deleteMe'];
|
||||
% test for write permissions by creating a folder and then deleting it
|
||||
isWritable = mkdir(testDir);
|
||||
% check if directory creation was successful
|
||||
if isWritable == 1
|
||||
rmdir(fullfile(testDir));
|
||||
end
|
||||
|
||||
list_h5 = dir([load_dir, '/run_*.h5']);
|
||||
|
||||
|
||||
file_sizes = [list_h5.bytes];
|
||||
if any(file_sizes < 1e6) % find files < 1MB
|
||||
warning('H5 files in scan %i seem damaged, generate again ... ', scan)
|
||||
list_raw = dir([load_dir, '/run_d0_f0000000*.raw']);
|
||||
if isempty(list_raw)
|
||||
warning('RAW data is missing, data cannot be converted')
|
||||
return
|
||||
else
|
||||
delete(sprintf('%s/*.h5',load_dir))
|
||||
end
|
||||
list_h5 = dir([load_dir, '/run_*.h5']);
|
||||
end
|
||||
% toc
|
||||
if isempty(list_h5)
|
||||
if ~isWritable
|
||||
warning('Conversion failed because folder %s is not writable', load_dir)
|
||||
return
|
||||
end
|
||||
|
||||
list_raw = dir(fullfile(load_dir, 'run_d0_f0000000*.raw'));
|
||||
|
||||
Nscans = length(list_raw);
|
||||
|
||||
for ii = 1:Nscans
|
||||
ind_scans(ii) = str2num(list_raw(ii).name(16:17));
|
||||
end
|
||||
|
||||
for ii = 1:Nscans
|
||||
systemcall = [convertor_path ' ' fullfile(list_raw(1).folder,list_raw(1).name)];
|
||||
fprintf('%s\n',systemcall);
|
||||
[stat,out] = system(systemcall);
|
||||
systemcall = sprintf('%s -s %s --scanNr %u --hdf5 --xmlLayout %s -o %s %s', specParser, specDatFile, scan, xmlLayoutFile, fullfile(load_dir, sprintf('run_%05d_000000000000.h5',scan)), orchestraPath);
|
||||
[stat, out_spec] = system(systemcall);
|
||||
end
|
||||
|
||||
list_h5 = dir([load_dir, '/*.h5']);
|
||||
if isempty(list_h5)
|
||||
error(sprintf('After conversion did not find any h5 in %s\n',load_dir))
|
||||
return
|
||||
end
|
||||
if numel(list_h5)>1
|
||||
error(sprintf('After conversion I found more than one h5 in %s\n',load_dir))
|
||||
return
|
||||
end
|
||||
|
||||
h5fileinfo = h5info(fullfile(list_h5.folder,list_h5.name), '/entry/instrument/eiger_4/data');
|
||||
|
||||
nframes_converted = h5fileinfo.Dataspace.Size(3);
|
||||
out = splitlines(out);
|
||||
nframes_expected = str2num(out{end-2}(14:end));
|
||||
fprintf('Frames expected: %i, frames converted %i \n', nframes_expected, nframes_converted)
|
||||
if nframes_converted == nframes_expected
|
||||
fprintf('Scan %i succefully converted to H5\n', scan);
|
||||
delete(sprintf('%s/*.raw',load_dir))
|
||||
else
|
||||
error('Scan %i WAS NOT CONVERTED to H5\n', scan)
|
||||
delete(sprintf('%s/*.h5',load_dir))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,181 @@
|
||||
%CONVERT2HDF5_WRAPPER converts Eiger 1.5M raw data files to HDF5 and
|
||||
% deletes the raw files if the conversion has finished successfully
|
||||
% convert2hdf5_wrapper(raw_data_path)
|
||||
%
|
||||
% ** raw_data_path path to the eiger directory, e.g. ~/Data10/
|
||||
%
|
||||
% *optional*
|
||||
% ** scanID start at the given scan number
|
||||
%
|
||||
% EXAMPLES:
|
||||
% % start at scan number 1:
|
||||
% convert2hdf5_wrapper('~/Data10/');
|
||||
%
|
||||
% % start at scan number 150:
|
||||
% convert2hdf5_wrapper('~/Data10/', 150);
|
||||
%
|
||||
% Pleas note that the script is designed to be used during an ongoing
|
||||
% measurement, and therefore only converts n-1 datasets, that is it waits
|
||||
% until the next measurement has started.
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 convert2hdf5_wrapper(raw_data_path, varargin)
|
||||
import utils.*
|
||||
if nargin > 1
|
||||
scanID = varargin{1};
|
||||
else
|
||||
scanID = 1;
|
||||
end
|
||||
while true
|
||||
[started, newScan, specDatFile] = beamline.next_scan_started(raw_data_path, scanID);
|
||||
if started
|
||||
convert2hdf5(scanID, raw_data_path, specDatFile);
|
||||
fprintf('Converting scan %d\n', scanID);
|
||||
scanID = newScan;
|
||||
else
|
||||
fprintf('Waiting for next scan to start.\n');
|
||||
pause(1);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
function convert2hdf5(scan, raw_data_path, specDatFile)
|
||||
|
||||
% some defaults
|
||||
convertor_path = '~/Data10/bin/eiger1p5M_converter/hdf5MakerOMNY';
|
||||
xmlLayoutFile = '~/Data10/bin/nexus/layout.xml';
|
||||
orchestraPath = '~/Data10/specES1/scan_positions/';
|
||||
specParser = '~/Data10/matlab/+io/spec_reader/spec_reader';
|
||||
|
||||
% check if orchestraPath exists
|
||||
if exist(orchestraPath, 'dir')
|
||||
% orchestraPath = '--orchestra ' + orchestraPath;
|
||||
orchestraPath = ['--orchestra ' orchestraPath];
|
||||
else
|
||||
orchestraPath = '';
|
||||
end
|
||||
|
||||
load_dir = utils.compile_x12sa_dirname(scan);
|
||||
if exist('raw_data_path','var')&&exist(fullfile(raw_data_path,load_dir),'dir')
|
||||
load_dir = fullfile(raw_data_path,load_dir);
|
||||
elseif exist(['~/Data10/eiger_4/'],'dir')
|
||||
load_dir = ['~/Data10/eiger_4/' load_dir];
|
||||
elseif exist([raw_data_path,'eiger_4/'])
|
||||
load_dir = [raw_data_path,'/eiger_4/' load_dir];
|
||||
elseif exist([raw_data_path,'/eigeromny/'])
|
||||
load_dir = [raw_data_path,'/eigeromny/' load_dir];
|
||||
end
|
||||
|
||||
if ~exist(load_dir, 'dir')
|
||||
warning('Raw data path %s not found', load_dir)
|
||||
return
|
||||
end
|
||||
|
||||
testDir = [load_dir, '/deleteMe'];
|
||||
% test for write permissions by creating a folder and then deleting it
|
||||
isWritable = mkdir(testDir);
|
||||
% check if directory creation was successful
|
||||
if isWritable == 1
|
||||
rmdir(fullfile(testDir));
|
||||
end
|
||||
|
||||
list_h5 = dir([load_dir, '/run_*.h5']);
|
||||
|
||||
|
||||
file_sizes = [list_h5.bytes];
|
||||
if any(file_sizes < 1e6) % find files < 1MB
|
||||
warning('H5 files in scan %i seem damaged, generate again ... ', scan)
|
||||
list_raw = dir([load_dir, '/run_d0_f0000000*.raw']);
|
||||
if isempty(list_raw)
|
||||
warning('RAW data is missing, data cannot be converted')
|
||||
return
|
||||
else
|
||||
delete(sprintf('%s/*.h5',load_dir))
|
||||
end
|
||||
list_h5 = dir([load_dir, '/run_*.h5']);
|
||||
end
|
||||
% toc
|
||||
if isempty(list_h5)
|
||||
if ~isWritable
|
||||
warning('Conversion failed because folder %s is not writable', load_dir)
|
||||
return
|
||||
end
|
||||
|
||||
list_raw = dir(fullfile(load_dir, 'run_d0_f0000000*.raw'));
|
||||
|
||||
Nscans = length(list_raw);
|
||||
|
||||
for ii = 1:Nscans
|
||||
ind_scans(ii) = str2num(list_raw(ii).name(16:17));
|
||||
end
|
||||
|
||||
for ii = 1:Nscans
|
||||
systemcall = [convertor_path ' ' fullfile(list_raw(1).folder,list_raw(1).name)];
|
||||
fprintf('%s\n',systemcall);
|
||||
[stat,out] = system(systemcall);
|
||||
systemcall = sprintf('%s -s %s --scanNr %u --hdf5 --xmlLayout %s -o %s %s', specParser, specDatFile, scan, xmlLayoutFile, fullfile(load_dir, sprintf('run_%05d_000000000000.h5',scan)), orchestraPath);
|
||||
[stat, out] = system(systemcall);
|
||||
end
|
||||
|
||||
list_h5 = dir([load_dir, '/*.h5']);
|
||||
if isempty(list_h5)
|
||||
error(sprintf('After conversion did not find any h5 in %s\n',load_dir))
|
||||
return
|
||||
end
|
||||
if numel(list_h5)>1
|
||||
error(sprintf('After conversion I found more than one h5 in %s\n',load_dir))
|
||||
return
|
||||
end
|
||||
|
||||
h5fileinfo = h5info(fullfile(list_h5.folder,list_h5.name), '/entry/instrument/eiger_4/data');
|
||||
|
||||
nframes_converted = h5fileinfo.Dataspace.Size(3);
|
||||
out = splitlines(out);
|
||||
nframes_expected = str2num(out{end-2}(14:end));
|
||||
fprintf('Frames expected: %i, frames converted %i \n', nframes_expected, nframes_converted)
|
||||
if nframes_converted == nframes_expected
|
||||
fprintf('Scan %i succefully converted to H5\n', scan);
|
||||
delete(sprintf('%s/*.raw',load_dir))
|
||||
else
|
||||
error('Scan %i WAS NOT CONVERTED to H5\n', scan)
|
||||
delete(sprintf('%s/*.h5',load_dir))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,60 @@
|
||||
% CROP_OUTLIERS in 2D binary slice identify the N largest structures and
|
||||
% remove all smallers
|
||||
%
|
||||
% mask_new = crop_outliers(mask, number_of_objects)
|
||||
%
|
||||
% Inputs
|
||||
% **mask original 2D binary mask
|
||||
% **number_of_objects Number of object to be left
|
||||
% *returns*
|
||||
% ++mask_new updated mask
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 mask_new = crop_outliers(mask, number_of_objects)
|
||||
if nargin == 1
|
||||
number_of_objects = 1;
|
||||
end
|
||||
|
||||
L0 = double(labelmatrix(bwconncomp(mask)));
|
||||
[m,n] = hist(L0(L0>0),unique(L0(L0>0)));
|
||||
[~,ind] = sort(m);
|
||||
try
|
||||
mask_new = ismember(L0, n(ind(max(1,end - number_of_objects+1):end)));
|
||||
catch
|
||||
keyboard
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,53 @@
|
||||
% CROP_PAD adjusts the size by zero padding or cropping
|
||||
% Inputs:
|
||||
% **img input image
|
||||
% **outsize size of final image
|
||||
% *optional:*
|
||||
% **fill value to fill padded regions
|
||||
% returns:
|
||||
% ++imout cropped image
|
||||
|
||||
|
||||
function [ imout ] = crop_pad( img, outsize, fill)
|
||||
|
||||
if nargin < 1
|
||||
fprintf('CROP_PAD: adjusts the size by zero padding or cropping\n');
|
||||
fprintf('crop_pad(img, outsize)\n');
|
||||
return
|
||||
end
|
||||
|
||||
Nin = size(img);
|
||||
|
||||
if isempty(outsize) || all(outsize(1:2) == Nin(1:2))
|
||||
imout = img; % if outsize == [], return the same image without changes
|
||||
return
|
||||
end
|
||||
|
||||
Nout = outsize(1:2);
|
||||
|
||||
if nargin < 3
|
||||
fill = 0;
|
||||
end
|
||||
|
||||
|
||||
|
||||
center = floor(Nin(1:2)/2)+1;
|
||||
|
||||
imout = zeros([Nout,Nin(3:end)],'like',img);
|
||||
|
||||
if fill ~= 0
|
||||
imout = imout + fill;
|
||||
end
|
||||
|
||||
centerout = floor(Nout/2)+1;
|
||||
|
||||
cenout_cen = centerout - center;
|
||||
imout(max(cenout_cen(1)+1,1):min(cenout_cen(1)+Nin(1),Nout(1)),max(cenout_cen(2)+1,1):min(cenout_cen(2)+Nin(2),Nout(2)),:,:) ...
|
||||
= img(max(-cenout_cen(1)+1,1):min(-cenout_cen(1)+Nout(1),Nin(1)),max(-cenout_cen(2)+1,1):min(-cenout_cen(2)+Nout(2),Nin(2)),:,:);
|
||||
|
||||
if ~isreal(img)
|
||||
imout = complex(imout);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
% CROP_PAD_3D adjusts the size by zero padding or cropping
|
||||
%
|
||||
% [ imout ] = crop_pad_3D( img, outsize, varargin)
|
||||
%
|
||||
% Inputs
|
||||
% **img input 3D volume
|
||||
% **outsize size of output volume
|
||||
% **fill value to fill the padded regions
|
||||
% Outputs
|
||||
% ++imout output volume after cropping / padding to size "outsize"
|
||||
%
|
||||
% Example :
|
||||
% volData = ones(100,100,100)
|
||||
% [ volData_out ] = crop_pad_3D( volData, [50,50,200])
|
||||
% size(volData_out) == [50,50,200]
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ imout ] = crop_pad_3D( img, outsize, fill)
|
||||
|
||||
if nargin < 1
|
||||
fprintf('CROP_PAD: adjusts the size by zero padding or cropping\n');
|
||||
fprintf('crop_pad(img, outsize)\n');
|
||||
return
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
fill = 0;
|
||||
end
|
||||
|
||||
Nout = outsize(1:3);
|
||||
|
||||
Nin = size(img);
|
||||
|
||||
if all(Nin ==Nout) % dont do anything if input array size == output size
|
||||
imout = img;
|
||||
return
|
||||
end
|
||||
|
||||
center = floor(Nin(1:3)/2)+1;
|
||||
|
||||
imout = zeros(outsize,'like',img) + fill;
|
||||
centerout = floor(Nout/2)+1;
|
||||
|
||||
cenout_cen = centerout - center;
|
||||
imout(max(cenout_cen(1)+1,1):min(cenout_cen(1)+Nin(1),Nout(1)),...
|
||||
max(cenout_cen(2)+1,1):min(cenout_cen(2)+Nin(2),Nout(2)),...
|
||||
max(cenout_cen(3)+1,1):min(cenout_cen(3)+Nin(3),Nout(3))) ...
|
||||
= img(max(-cenout_cen(1)+1,1):min(-cenout_cen(1)+Nout(1),Nin(1)),...
|
||||
max(-cenout_cen(2)+1,1):min(-cenout_cen(2)+Nout(2),Nin(2)),...
|
||||
max(-cenout_cen(3)+1,1):min(-cenout_cen(3)+Nout(3),Nin(3)));
|
||||
|
||||
if ~isreal(img)
|
||||
imout = complex(imout);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
%[default_value] = default_parameter_value(mfile_name,parameter_name,vararg)
|
||||
% identify the current system to set useful default parameters
|
||||
|
||||
% Filename: $RCSfile: default_parameter_value.m,v $
|
||||
%
|
||||
% $Revision: 1.10 $ $Date: 2011/08/13 14:10:58 $
|
||||
% $Author: $
|
||||
% $Tag: $
|
||||
%
|
||||
% Description:
|
||||
% identify the current system to set useful default parameters
|
||||
%
|
||||
% Note:
|
||||
% none
|
||||
%
|
||||
% Dependencies:
|
||||
% none
|
||||
%
|
||||
%
|
||||
% history:
|
||||
%
|
||||
% April 28th 2010:
|
||||
% add plot_radial_integ, find_files, radial_integ
|
||||
%
|
||||
% April 2009: 1st version
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [default_value] = ...
|
||||
default_parameter_value(mfile_name,parameter_name,vararg)
|
||||
import utils.identify_system
|
||||
|
||||
sys_id = identify_system();
|
||||
|
||||
% disable the use of the find command for non Unix/Linux based systems
|
||||
if (strcmp(parameter_name,'UseFind'))
|
||||
if (strcmp(sys_id,'Windows'))
|
||||
default_value = 0;
|
||||
else
|
||||
default_value = 1;
|
||||
end
|
||||
end
|
||||
|
||||
switch mfile_name
|
||||
case 'image_show'
|
||||
switch parameter_name
|
||||
case 'FigNo'
|
||||
default_value = 1;
|
||||
case 'FigClear'
|
||||
default_value = 1;
|
||||
case 'ImageHandle'
|
||||
default_value = 0;
|
||||
case 'AutoScale'
|
||||
switch sys_id
|
||||
case {'DPC lab', 'mDPC lab', 'cSAXS-mobile'}
|
||||
default_value = [1 1];
|
||||
otherwise
|
||||
default_value = [0 0];
|
||||
end
|
||||
case 'AxisMin'
|
||||
default_value = 1;
|
||||
case 'AxisMax'
|
||||
default_value = 1e5;
|
||||
case 'HistScale'
|
||||
default_value = [ 0.15 0.85 ];
|
||||
case 'LogScale'
|
||||
switch sys_id
|
||||
case {'DPC lab', 'mDPC lab', 'cSAXS-mobile'}
|
||||
default_value = 0;
|
||||
otherwise
|
||||
default_value = 1;
|
||||
end
|
||||
case 'XScale'
|
||||
default_value = 1.0;
|
||||
case 'YScale'
|
||||
default_value = 1.0;
|
||||
case 'XOffs'
|
||||
default_value = 0.0;
|
||||
case 'ColorBar'
|
||||
default_value = 1;
|
||||
case 'ColorMap'
|
||||
default_value = [];
|
||||
case 'Axes'
|
||||
default_value = 1;
|
||||
case 'DisplayTime'
|
||||
default_value = 1;
|
||||
case 'DisplayFtime'
|
||||
default_value = 1;
|
||||
case 'DisplayExptime'
|
||||
default_value = 1;
|
||||
case 'BgrData'
|
||||
default_value = [];
|
||||
case 'FrameNumber'
|
||||
default_value = 0;
|
||||
otherwise
|
||||
error('Unknown parameter name %s for m-file %s',...
|
||||
parameter_name,mfile_name);
|
||||
end
|
||||
|
||||
|
||||
|
||||
case 'image_read'
|
||||
switch parameter_name
|
||||
case 'OrientByExtension'
|
||||
switch sys_id
|
||||
case 'mDPC lab'
|
||||
default_value = 0;
|
||||
otherwise
|
||||
default_value = 1;
|
||||
end
|
||||
case 'DataType'
|
||||
default_value = 'double';
|
||||
case 'ForceFileType'
|
||||
default_value = [];
|
||||
case 'MatlabVar'
|
||||
default_value = 'data';
|
||||
case 'RowFrom'
|
||||
default_value = 0;
|
||||
case 'RowTo'
|
||||
default_value = 0;
|
||||
case 'ColumnFrom'
|
||||
default_value = 0;
|
||||
case 'ColumnTo'
|
||||
default_value = 0;
|
||||
case 'UnhandledParError'
|
||||
default_value = 1;
|
||||
case 'IsFmask'
|
||||
default_value = true;
|
||||
case 'DisplayFilename'
|
||||
default_value = 1;
|
||||
otherwise
|
||||
error('Unknown parameter name %s for m-file %s',...
|
||||
parameter_name,mfile_name);
|
||||
end
|
||||
|
||||
|
||||
|
||||
case 'image_orient'
|
||||
switch parameter_name
|
||||
case 'Transpose'
|
||||
default_value = 0;
|
||||
case 'FlipLR'
|
||||
switch sys_id
|
||||
case 'mDPC lab'
|
||||
default_value = 1;
|
||||
otherwise
|
||||
default_value = 0;
|
||||
end
|
||||
case 'FlipUD'
|
||||
default_value = 0;
|
||||
otherwise
|
||||
error('Unknown parameter name %s for m-file %s',...
|
||||
parameter_name,mfile_name);
|
||||
end
|
||||
|
||||
|
||||
case 'plot_radial_integ'
|
||||
switch parameter_name
|
||||
case 'FigNo'
|
||||
% figure number for plotting the integrated data
|
||||
default_value = 100;
|
||||
case 'NewFig'
|
||||
% no new figure for each plot
|
||||
default_value = 0;
|
||||
case 'ClearFig'
|
||||
% clear figure before plotting
|
||||
default_value = 1;
|
||||
case 'Axis'
|
||||
% auto scaling
|
||||
default_value = [];
|
||||
case 'SleepTime'
|
||||
% no sleep after each plot
|
||||
default_value = 0.0;
|
||||
case 'XLog'
|
||||
% linear scaling of the x-axis
|
||||
default_value = 0;
|
||||
case 'YLog'
|
||||
% logarithmic scaling of the y-axis
|
||||
default_value = 1;
|
||||
case 'PlotQ'
|
||||
% plot as a function of q rather than pixel number
|
||||
default_value = 0;
|
||||
case 'PlotAngle'
|
||||
% plot as a function of the azimuthal angle rather than q or radius
|
||||
default_value = 0;
|
||||
case 'RadiusRange'
|
||||
% average over this range in radius for the azimuthal plot
|
||||
default_value = [];
|
||||
case 'FilenameIntegMasks'
|
||||
% location of the integration masks, needed for normalization in case of
|
||||
% averaging over radii
|
||||
default_value = '~/Data10/analysis/data/pilatus_integration_masks.mat';
|
||||
case 'PixelSize_mm'
|
||||
% pixel size for q calculation
|
||||
default_value = [];
|
||||
case 'DetDist_mm'
|
||||
% detector distance for q calculation
|
||||
default_value = [];
|
||||
case 'E_keV'
|
||||
% x-ray energy for q calculation
|
||||
default_value = [];
|
||||
% plot in inverse nm rather than inverse Angstroem
|
||||
case 'Inverse_nm'
|
||||
default_value = 0;
|
||||
case 'QMulPow'
|
||||
% do not multiply by q to the power of this value
|
||||
default_value = [];
|
||||
case 'SegAvg'
|
||||
% average over segments
|
||||
default_value = 1;
|
||||
case 'SegRange'
|
||||
% segment range
|
||||
default_value = [];
|
||||
case 'LegendMulSeg'
|
||||
% legend in case of multi segment plots
|
||||
default_value = 1;
|
||||
case 'PointAvg'
|
||||
% plot the average over one Matlab file which is typically a scan line
|
||||
default_value = 1;
|
||||
case 'PointRange'
|
||||
% point range
|
||||
default_value = [];
|
||||
case 'BgrFilename'
|
||||
% background to subtract
|
||||
default_value = '';
|
||||
case 'BgrScale'
|
||||
% scaling factor for background data
|
||||
default_value = 1.0;
|
||||
case 'BgrPoint'
|
||||
% point within the background file to subtract
|
||||
default_value = 1;
|
||||
otherwise
|
||||
error('Unknown parameter name %s for m-file %s',...
|
||||
parameter_name,mfile_name);
|
||||
end
|
||||
|
||||
case 'find_files'
|
||||
switch parameter_name
|
||||
case 'UseFind'
|
||||
% the default is set above system dependent
|
||||
case 'UnhandledParError'
|
||||
% exit with an error message if unhandled named parameters are left at the
|
||||
% end of this macro
|
||||
default_value = 1;
|
||||
otherwise
|
||||
error('Unknown parameter name %s for m-file %s',...
|
||||
parameter_name,mfile_name);
|
||||
end
|
||||
|
||||
case 'radial_integ'
|
||||
switch parameter_name
|
||||
case 'OutdirData'
|
||||
% output directory for integrated intensities
|
||||
default_value = '~/Data10/analysis/radial_integration/';
|
||||
case 'FilenameIntegMasks'
|
||||
% location of the integration masks
|
||||
default_value = '~/Data10/analysis/data/pilatus_integration_masks.mat';
|
||||
case 'rMaxForced'
|
||||
% use the full range of integration masks
|
||||
default_value = 0;
|
||||
case 'FigNo'
|
||||
% do not plot integrated data
|
||||
default_value = 0;
|
||||
case 'SaveCombinedI'
|
||||
% combine integrated intensities from all files within one directory
|
||||
default_value = 1;
|
||||
case 'Recursive'
|
||||
% recursively integrate data from all sub directories
|
||||
default_value = 1;
|
||||
case 'ParTasksMax'
|
||||
% use parallel processing by default if the toolbox is
|
||||
% available
|
||||
[dummy, other_system_flags] = identify_system();
|
||||
default_value = 1;
|
||||
if (other_system_flags.parallel_computing_toolbox_available)
|
||||
default_value = 256;
|
||||
end
|
||||
case 'UseFind'
|
||||
% the default value is set above
|
||||
case 'UnhandledParError'
|
||||
% exit with an error message if unhandled named parameters are left at the
|
||||
% end of this macro
|
||||
default_value = 1;
|
||||
otherwise
|
||||
error('Unknown parameter name %s for m-file %s',...
|
||||
parameter_name,mfile_name);
|
||||
end
|
||||
|
||||
|
||||
otherwise
|
||||
error('No default parameters set for m-file %s (parameter name %s)',...
|
||||
mfile_name,parameter_name);
|
||||
end
|
||||
@@ -0,0 +1,223 @@
|
||||
function [output, Greg] = dftregistration(buf1ft,buf2ft,usfac)
|
||||
% function [output Greg] = dftregistration(buf1ft,buf2ft,usfac);
|
||||
% Efficient subpixel image registration by crosscorrelation. This code
|
||||
% gives the same precision as the FFT upsampled cross correlation in a
|
||||
% small fraction of the computation time and with reduced memory
|
||||
% requirements. It obtains an initial estimate of the crosscorrelation peak
|
||||
% by an FFT and then refines the shift estimation by upsampling the DFT
|
||||
% only in a small neighborhood of that estimate by means of a
|
||||
% matrix-multiply DFT. With this procedure all the image points are used to
|
||||
% compute the upsampled crosscorrelation.
|
||||
% Manuel Guizar - Dec 13, 2007
|
||||
%
|
||||
% Rewrote all code not authored by either Manuel Guizar or Jim Fienup
|
||||
% Manuel Guizar - May 13, 2016
|
||||
%
|
||||
% Citation for this algorithm:
|
||||
% Manuel Guizar-Sicairos, Samuel T. Thurman, and James R. Fienup,
|
||||
% "Efficient subpixel image registration algorithms," Opt. Lett. 33,
|
||||
% 156-158 (2008).
|
||||
%
|
||||
% Inputs
|
||||
% buf1ft Fourier transform of reference image,
|
||||
% DC in (1,1) [DO NOT FFTSHIFT]
|
||||
% buf2ft Fourier transform of image to register,
|
||||
% DC in (1,1) [DO NOT FFTSHIFT]
|
||||
% usfac Upsampling factor (integer). Images will be registered to
|
||||
% within 1/usfac of a pixel. For example usfac = 20 means the
|
||||
% images will be registered within 1/20 of a pixel. (default = 1)
|
||||
%
|
||||
% Outputs
|
||||
% output = [error,diffphase,net_row_shift,net_col_shift]
|
||||
% error Translation invariant normalized RMS error between f and g
|
||||
% diffphase Global phase difference between the two images (should be
|
||||
% zero if images are non-negative).
|
||||
% net_row_shift net_col_shift Pixel shifts between images
|
||||
% Greg (Optional) Fourier transform of registered version of buf2ft,
|
||||
% the global phase difference is compensated for.
|
||||
|
||||
% Copyright (c) 2016, Manuel Guizar Sicairos, James R. Fienup, University of Rochester
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
% * Neither the name of the University of Rochester nor the names
|
||||
% of its contributors may be used to endorse or promote products derived
|
||||
% from this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
if ~exist('usfac','var')
|
||||
usfac = 1;
|
||||
end
|
||||
|
||||
[nr,nc]=size(buf2ft);
|
||||
Nr = ifftshift(-fix(nr/2):ceil(nr/2)-1);
|
||||
Nc = ifftshift(-fix(nc/2):ceil(nc/2)-1);
|
||||
|
||||
if usfac == 0
|
||||
% Simple computation of error and phase difference without registration
|
||||
CCmax = sum(buf1ft(:).*conj(buf2ft(:)));
|
||||
row_shift = 0;
|
||||
col_shift = 0;
|
||||
elseif usfac == 1
|
||||
% Single pixel registration
|
||||
CC = ifft2(buf1ft.*conj(buf2ft));
|
||||
CCabs = abs(CC);
|
||||
[row_shift, col_shift] = find(CCabs == max(CCabs(:)));
|
||||
CCmax = CC(row_shift,col_shift)*nr*nc;
|
||||
% Now change shifts so that they represent relative shifts and not indices
|
||||
row_shift = Nr(row_shift);
|
||||
col_shift = Nc(col_shift);
|
||||
elseif usfac > 1
|
||||
% Start with usfac == 2
|
||||
CC = ifft2(FTpad(buf1ft.*conj(buf2ft),[2*nr,2*nc]));
|
||||
CCabs = abs(CC);
|
||||
[row_shift, col_shift] = find(CCabs == max(CCabs(:)),1,'first');
|
||||
CCmax = CC(row_shift,col_shift)*nr*nc;
|
||||
% Now change shifts so that they represent relative shifts and not indices
|
||||
Nr2 = ifftshift(-fix(nr):ceil(nr)-1);
|
||||
Nc2 = ifftshift(-fix(nc):ceil(nc)-1);
|
||||
row_shift = Nr2(row_shift)/2;
|
||||
col_shift = Nc2(col_shift)/2;
|
||||
% If upsampling > 2, then refine estimate with matrix multiply DFT
|
||||
if usfac > 2,
|
||||
%%% DFT computation %%%
|
||||
% Initial shift estimate in upsampled grid
|
||||
row_shift = round(row_shift*usfac)/usfac;
|
||||
col_shift = round(col_shift*usfac)/usfac;
|
||||
dftshift = fix(ceil(usfac*1.5)/2); %% Center of output array at dftshift+1
|
||||
% Matrix multiply DFT around the current shift estimate
|
||||
CC = conj(dftups(buf2ft.*conj(buf1ft),ceil(usfac*1.5),ceil(usfac*1.5),usfac,...
|
||||
dftshift-row_shift*usfac,dftshift-col_shift*usfac));
|
||||
% Locate maximum and map back to original pixel grid
|
||||
CCabs = abs(CC);
|
||||
[rloc, cloc] = find(CCabs == max(CCabs(:)),1,'first');
|
||||
CCmax = CC(rloc,cloc);
|
||||
rloc = rloc - dftshift - 1;
|
||||
cloc = cloc - dftshift - 1;
|
||||
row_shift = row_shift + rloc/usfac;
|
||||
col_shift = col_shift + cloc/usfac;
|
||||
end
|
||||
|
||||
% If its only one row or column the shift along that dimension has no
|
||||
% effect. Set to zero.
|
||||
if nr == 1,
|
||||
row_shift = 0;
|
||||
end
|
||||
if nc == 1,
|
||||
col_shift = 0;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
rg00 = sum(abs(buf1ft(:)).^2);
|
||||
rf00 = sum(abs(buf2ft(:)).^2);
|
||||
error = 1.0 - abs(CCmax).^2/(rg00*rf00);
|
||||
error = sqrt(abs(error));
|
||||
diffphase = angle(CCmax);
|
||||
|
||||
output=[error,diffphase,row_shift,col_shift];
|
||||
|
||||
% Compute registered version of buf2ft
|
||||
if (nargout > 1)&&(usfac > 0),
|
||||
[Nc,Nr] = meshgrid(Nc,Nr);
|
||||
Greg = buf2ft.*exp(1i*2*pi*(-row_shift*Nr/nr-col_shift*Nc/nc));
|
||||
Greg = Greg*exp(1i*diffphase);
|
||||
elseif (nargout > 1)&&(usfac == 0)
|
||||
Greg = buf2ft*exp(1i*diffphase);
|
||||
end
|
||||
return
|
||||
|
||||
function out=dftups(in,nor,noc,usfac,roff,coff)
|
||||
% function out=dftups(in,nor,noc,usfac,roff,coff);
|
||||
% Upsampled DFT by matrix multiplies, can compute an upsampled DFT in just
|
||||
% a small region.
|
||||
% usfac Upsampling factor (default usfac = 1)
|
||||
% [nor,noc] Number of pixels in the output upsampled DFT, in
|
||||
% units of upsampled pixels (default = size(in))
|
||||
% roff, coff Row and column offsets, allow to shift the output array to
|
||||
% a region of interest on the DFT (default = 0)
|
||||
% Recieves DC in upper left corner, image center must be in (1,1)
|
||||
% Manuel Guizar - Dec 13, 2007
|
||||
% Modified from dftus, by J.R. Fienup 7/31/06
|
||||
|
||||
% This code is intended to provide the same result as if the following
|
||||
% operations were performed
|
||||
% - Embed the array "in" in an array that is usfac times larger in each
|
||||
% dimension. ifftshift to bring the center of the image to (1,1).
|
||||
% - Take the FFT of the larger array
|
||||
% - Extract an [nor, noc] region of the result. Starting with the
|
||||
% [roff+1 coff+1] element.
|
||||
|
||||
% It achieves this result by computing the DFT in the output array without
|
||||
% the need to zeropad. Much faster and memory efficient than the
|
||||
% zero-padded FFT approach if [nor noc] are much smaller than [nr*usfac nc*usfac]
|
||||
|
||||
[nr,nc]=size(in);
|
||||
% Set defaults
|
||||
if exist('roff', 'var')~=1, roff=0; end
|
||||
if exist('coff', 'var')~=1, coff=0; end
|
||||
if exist('usfac','var')~=1, usfac=1; end
|
||||
if exist('noc', 'var')~=1, noc=nc; end
|
||||
if exist('nor', 'var')~=1, nor=nr; end
|
||||
% Compute kernels and obtain DFT by matrix products
|
||||
kernc=exp((-1i*2*pi/(nc*usfac))*( ifftshift(0:nc-1).' - floor(nc/2) )*( (0:noc-1) - coff ));
|
||||
kernr=exp((-1i*2*pi/(nr*usfac))*( (0:nor-1).' - roff )*( ifftshift([0:nr-1]) - floor(nr/2) ));
|
||||
out=kernr*in*kernc;
|
||||
return
|
||||
|
||||
|
||||
function [ imFTout ] = FTpad(imFT,outsize)
|
||||
% imFTout = FTpad(imFT,outsize)
|
||||
% Pads or crops the Fourier transform to the desired ouput size. Taking
|
||||
% care that the zero frequency is put in the correct place for the output
|
||||
% for subsequent FT or IFT. Can be used for Fourier transform based
|
||||
% interpolation, i.e. dirichlet kernel interpolation.
|
||||
%
|
||||
% Inputs
|
||||
% imFT - Input complex array with DC in [1,1]
|
||||
% outsize - Output size of array [ny nx]
|
||||
%
|
||||
% Outputs
|
||||
% imout - Output complex image with DC in [1,1]
|
||||
% Manuel Guizar - 2014.06.02
|
||||
|
||||
if ~ismatrix(imFT)
|
||||
error('Maximum number of array dimensions is 2')
|
||||
end
|
||||
Nout = outsize;
|
||||
Nin = size(imFT);
|
||||
imFT = fftshift(imFT);
|
||||
center = floor(size(imFT)/2)+1;
|
||||
|
||||
imFTout = zeros(outsize,'like', imFT);
|
||||
centerout = floor(size(imFTout)/2)+1;
|
||||
|
||||
% imout(centerout(1)+[1:Nin(1)]-center(1),centerout(2)+[1:Nin(2)]-center(2)) ...
|
||||
% = imFT;
|
||||
cenout_cen = centerout - center;
|
||||
imFTout(max(cenout_cen(1)+1,1):min(cenout_cen(1)+Nin(1),Nout(1)),max(cenout_cen(2)+1,1):min(cenout_cen(2)+Nin(2),Nout(2))) ...
|
||||
= imFT(max(-cenout_cen(1)+1,1):min(-cenout_cen(1)+Nout(1),Nin(1)),max(-cenout_cen(2)+1,1):min(-cenout_cen(2)+Nout(2),Nin(2)));
|
||||
|
||||
imFTout = ifftshift(imFTout)*Nout(1)*Nout(2)/(Nin(1)*Nin(2));
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Function:
|
||||
%
|
||||
% dose_calc(ptycho_recon, ptycho_data, param)
|
||||
%
|
||||
% Description:
|
||||
%
|
||||
% The function (1) takes one reconstruction and its data and estimate the
|
||||
% dose (2) saves the dose estimation into a .txt file.
|
||||
%
|
||||
% Input:
|
||||
%
|
||||
% ptycho_recon: reconstruction, including object, probe, and p
|
||||
% ptycho_data: data for the reconstruction
|
||||
% param_dose.mu = 1/(451*1e-6); % 1/attenuation_length in 1/m (for CH2 @6.2keV)
|
||||
% % 1/(152.7*1e-6) for zeolite Na2Al2Si3O102H4O with 2 g/cm3 density at 6.2 keV
|
||||
% param_dose.rho = 1000; % Density in kg/m^3
|
||||
% param_dose.setup_transmission = 0.55; % Intensity transmission of sample
|
||||
% % (e.g. air path after the sample, windows, He, detector efficiency)
|
||||
% % 0.943 for 700 cm He gas at 760 Torr and 295 K @ 6.2 keV
|
||||
% % 0.780 for 10 cm air at 760 Torr and 295 K @ 6.2 keV
|
||||
% % 0.976 for 13 micron Kapton (polymide) with 1.43
|
||||
% % g/cm3 @ 6.2 keV
|
||||
% % 0.841 for 7 micron muskovite mica
|
||||
% % (KAl3Si3O11.8H1.8F0.2) with 2.76 g/cm3 @ 6.2 keV
|
||||
% % 0.914 for 5 cm of air at 6.2 keV 750 Torr 295 K
|
||||
% % 0.55 for 300 micron of mylar C10H8O4 with density 1.38 g/cm3 at 6.2 keV
|
||||
% param_dose.overhead = 0.0; % Extra dose during movement overhead, only applicable
|
||||
% % if shutter is not closed between exposures
|
||||
% param_dose.fmask
|
||||
% param_dose.scan_number
|
||||
% param_dose.num_proj
|
||||
% param_dose.output_folder (default: ./)
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% one jpg for one_data_frame
|
||||
% one jpg for photons_per_shot_all
|
||||
% one jpg for photons_per_obj_pix
|
||||
% one txt for dose_estimate
|
||||
%
|
||||
% 2017-03-30
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 dose_calc(ptycho_recon, ptycho_data, param)
|
||||
import utils.*
|
||||
|
||||
|
||||
%Estimating detected photons
|
||||
probe = ptycho_recon.probe;
|
||||
object = ptycho_recon.object;
|
||||
p = ptycho_recon.p;
|
||||
data = ptycho_data.data;
|
||||
fmask = ptycho_data.fmask;
|
||||
|
||||
if isfield(param,'mu') && isfield(param,'rho') && isfield(param,'setup_transmission') && isfield(param,'overhead')
|
||||
mu = param.mu;
|
||||
rho = param.rho;
|
||||
setup_transmission = param.setup_transmission;
|
||||
overhead = param.overhead;
|
||||
else
|
||||
error('Please specify param.mu, param.rho, param.setup_transmission, and param.overhead.\n');
|
||||
end
|
||||
|
||||
if isfield(param,'num_proj')
|
||||
num_proj = param.num_proj;
|
||||
else
|
||||
verbose(0,'Using num_proj = 1');
|
||||
num_proj = 1;
|
||||
end
|
||||
|
||||
if isfield(param,'scan_number')
|
||||
scan_number = param.scan_number;
|
||||
else
|
||||
scan_number = [];
|
||||
end
|
||||
|
||||
if isfield(param,'output_folder')
|
||||
output_folder = param.output_folder;
|
||||
else
|
||||
verbose(0,'Using output_folder = ./');
|
||||
output_folder = '.';
|
||||
end
|
||||
|
||||
data = data .* fmask;
|
||||
photons_per_shot_all = sum(sum(data));
|
||||
photons_per_shot = max(photons_per_shot_all);
|
||||
|
||||
%Normalizing probe to photons per shot
|
||||
probe_norm = sum(abs(probe).^2,3);
|
||||
|
||||
probe_norm = probe_norm/sum(probe_norm(:));
|
||||
probe_norm = probe_norm*photons_per_shot;
|
||||
%
|
||||
asize = size(probe);
|
||||
%objaux = object*0;
|
||||
illum_sum = zeros(size(object,1)+10,size(object,2)+10);
|
||||
|
||||
|
||||
scanfirstindex = [1 cumsum(p.numpts)+1]; % First index for scan number
|
||||
for ii = 1:p.numscans
|
||||
p.scanindexrange(ii,:) = [scanfirstindex(ii) scanfirstindex(ii+1)-1];
|
||||
p.scanidxs{ii} = p.scanindexrange(ii,1):p.scanindexrange(ii,end);
|
||||
end
|
||||
|
||||
for ii = p.scanidxs{1}
|
||||
Indy = round(p.positions(ii,1)) + [1:asize(1)];
|
||||
Indx = round(p.positions(ii,2)) + [1:asize(2)];
|
||||
illum_sum(Indy,Indx) = illum_sum(Indy,Indx)+probe_norm;
|
||||
end
|
||||
|
||||
illum_sum = illum_sum(asize(1)/2:end-asize(1)/2,asize(2)/2:end-asize(2)/2);
|
||||
|
||||
% in case of laminography the field of view isnot rectangular ->
|
||||
% exclude the empty regions in the illumination function
|
||||
illum_mask = illum_sum > mean(illum_sum) * 0.1;
|
||||
|
||||
flux_in_area = sum(sum(illum_sum .* illum_mask)); %photons
|
||||
area = sum(illum_mask(:))*p.dx_spec(1)^2; % meters^2
|
||||
|
||||
I = flux_in_area/area; %ph/meters^2
|
||||
hv = 9.9334947e-16*(p.energy/6.2); %6.2keV in joules
|
||||
|
||||
D = mu*I*hv*num_proj/rho;
|
||||
D_with_gas = D/setup_transmission;
|
||||
D_with_overhead = D_with_gas*(1+overhead);
|
||||
verbose(0,'**********************************************')
|
||||
verbose(0,'Dose report for %d projections, Scan %d',num_proj, scan_number)
|
||||
verbose(0,'**********************************************')
|
||||
verbose(0,'Measured photons per frame = %.2e photons',photons_per_shot);
|
||||
verbose(0,'N_0 used for imaging for one projection = %.2e photons/micron^2',I*1e-12);
|
||||
verbose(0,'Dose used for imaging, D = %.2e Gy',D)
|
||||
verbose(0,'Accounting for experiment transmission, D = %.2e Gy',D_with_gas)
|
||||
verbose(0,'Accounting for experiment transmission and overhead, D = %.2e Gy',D_with_overhead)
|
||||
|
||||
%=======================
|
||||
figure(1); clf
|
||||
plotting.imagesc3D(log10(1+data));
|
||||
caxis([0,log10(max(data(:)))])
|
||||
colormap(plotting.franzmap); colorbar
|
||||
axis xy equal tight
|
||||
title('Data frames, log10')
|
||||
filename = fullfile(output_folder,sprintf('/%s_one_data_frame.jpg',p.run_name));
|
||||
verbose(1,'saving %s',filename);
|
||||
print('-djpeg','-r300',filename);
|
||||
|
||||
figure(2); clf
|
||||
plot(squeeze(photons_per_shot_all)); grid on;
|
||||
title(['Number of measured photons per frame = ' num2str(photons_per_shot)]);
|
||||
filename = fullfile(output_folder,sprintf('/%s_photons_per_shot_all.jpg',p.run_name));
|
||||
verbose(1,'saving %s',filename);
|
||||
print('-djpeg','-r300',filename);
|
||||
|
||||
figure(3); clf
|
||||
imagesc(illum_sum)
|
||||
colormap(plotting.franzmap); colorbar
|
||||
axis image xy
|
||||
title('Photons per pixel of the object')
|
||||
filename = fullfile(output_folder,sprintf('/%s_photons_per_obj_pix.jpg',p.run_name));
|
||||
verbose(1,'saving %s',filename);
|
||||
print('-djpeg','-r300',filename);
|
||||
|
||||
%=======================
|
||||
filename = fullfile(output_folder,sprintf('/%s_dose_estimate_S%05d.txt',p.run_name, scan_number));
|
||||
fid = fopen(filename,'w');
|
||||
fprintf(fid,'Scan = %d\n',scan_number);
|
||||
fprintf(fid,'Measured photons per frame = %.3e\n',photons_per_shot);
|
||||
fprintf(fid,'N_0 used for imaging for one projection (I*1e-12) = %.3e photons/micron^2\n',I*1e-12);
|
||||
fprintf(fid,'num_proj = %d\n',num_proj);
|
||||
fprintf(fid,'hv = %.5e\n\n',hv);
|
||||
fprintf(fid,'D = mu*I*hv*num_proj/rho \n');
|
||||
fprintf(fid,'D_with_gas = D/setup_transmission \n');
|
||||
fprintf(fid,'D_with_overhead = D_with_gas*(1+overhead) \n\n');
|
||||
fprintf(fid,'If mu = %.3e m^-1, rho = %.3e kg/m^3, setup_transmission = %.3f, then:\n', mu, rho, setup_transmission);
|
||||
fprintf(fid,'Accounting for experiment transmission, D_with_gas = %.3e Gy = %.3f MGy\n\n', D_with_gas, D_with_gas/1e6);
|
||||
fprintf(fid,'asize = %d, pixel size = %.4f nm\n', asize(1), p.dx_spec(1)*1e9);
|
||||
fclose(fid);
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
%FILT2D creates a 2d filter, based on fract_hanning
|
||||
%
|
||||
% outputdim... Size of the output array.
|
||||
% unmodsize... Size of the central array containing no modulation.
|
||||
% shape (optional)... 'rect' (default) or 'circ'
|
||||
% filter_type (optional)... 'hann' (default) or 'hamm', chebishev (only for unmodsize=0)
|
||||
%
|
||||
% example:
|
||||
% filt1 = filt2d(256,100,'circ','hann');
|
||||
% filt2 = filt2d(256,100);
|
||||
% filt3 = filt2d([512 420], [200 312]);
|
||||
%
|
||||
%
|
||||
%
|
||||
% Adapted from fract_hanning:
|
||||
%
|
||||
% fract_hanning(outputdim,unmodsize)
|
||||
% out = Square array containing a fractional separable Hanning window with
|
||||
% DC in upper left corner.
|
||||
% outputdim = size of the output array
|
||||
% unmodsize = Size of the central array containing no modulation.
|
||||
% Creates a square hanning window if unmodsize = 0 (or ommited), otherwise the output array
|
||||
% will contain an array of ones in the center and cosine modulation on the
|
||||
% edges, the array of ones will have DC in upper left corner.
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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.
|
||||
|
||||
% License for fract_hanning:
|
||||
% Copyright (c) 2016, Manuel Guizar Sicairos, James R. Fienup, University of Rochester
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
% * Neither the name of the University of Rochester nor the names
|
||||
% of its contributors may be used to endorse or promote products derived
|
||||
% from this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function out = filt2d(outputdim, unmodsize, varargin)
|
||||
|
||||
if nargin > 2
|
||||
shape = varargin{1};
|
||||
else
|
||||
shape = 'rect';
|
||||
end
|
||||
|
||||
if nargin > 3
|
||||
filt_type = varargin{2};
|
||||
else
|
||||
filt_type = 'hann';
|
||||
end
|
||||
|
||||
if nargin == 1
|
||||
unmodsize = 0;
|
||||
end
|
||||
|
||||
if length(outputdim)<2
|
||||
outputdim = [outputdim outputdim];
|
||||
elseif length(outputdim)>2
|
||||
error('3D filters are not supported.')
|
||||
end
|
||||
|
||||
if any(outputdim < unmodsize)
|
||||
error('Output dimension must be smaller or equal to size of unmodulated window'),
|
||||
end
|
||||
|
||||
if unmodsize<0
|
||||
unmodsize = 0;
|
||||
warning('Specified unmodsize<0, setting unmodsize = 0')
|
||||
end
|
||||
|
||||
if length(unmodsize)<2
|
||||
unmodsize = [unmodsize unmodsize];
|
||||
elseif length(unmodsize)>2
|
||||
error('3D filters are not supported.')
|
||||
end
|
||||
|
||||
switch lower(shape)
|
||||
case 'rect'
|
||||
N1 = [0:outputdim(2)-1];
|
||||
N2 = [0:outputdim(1)-1];
|
||||
[Nc,Nr] = meshgrid(N1,N2);
|
||||
case 'circ'
|
||||
assert(length(unique(outputdim))==1 && length(unique(unmodsize))==1, 'Option "circ" is supported for square arrays only.')
|
||||
N = [0:outputdim(1)-1];
|
||||
Nsz = (outputdim(1)-1)/2;
|
||||
xx = linspace(-Nsz,Nsz,outputdim(1));
|
||||
[x,y] = meshgrid(xx,xx);
|
||||
r = sqrt(x.^2 + y.^2);
|
||||
out = zeros(outputdim(1), outputdim(1));
|
||||
end
|
||||
|
||||
if unmodsize == 0
|
||||
switch lower(filt_type)
|
||||
case 'hann'
|
||||
switch lower(shape)
|
||||
case 'rect'
|
||||
out = (1+cos(2*pi*Nc/outputdim(1))).*(1+cos(2*pi*Nr/outputdim(2)))/4;
|
||||
case 'circ'
|
||||
out1d = (1+cos(2*pi*N/outputdim(1)))/2;
|
||||
out1d = fftshift(out1d);
|
||||
out(r<=Nsz) = interp1(xx,out1d,r(r<=Nsz));
|
||||
out = ifftshift(out);
|
||||
otherwise
|
||||
error('Unknown shape %s for filter %s', shape, filt_type);
|
||||
end
|
||||
case 'hamm'
|
||||
switch lower(shape)
|
||||
case 'rect'
|
||||
out = (0.54+0.46*cos(2*pi*Nc/(outputdim(1)-1))).*(0.54+0.46*cos(2*pi*Nr/(outputdim(2)-1)));
|
||||
case 'circ'
|
||||
out1d = (0.54+0.46*cos(2*pi*N/(outputdim(1)-1)));
|
||||
out1d = fftshift(out1d);
|
||||
out(r<=Nsz) = interp1(xx,out1d,r(r<=Nsz));
|
||||
out = ifftshift(out);
|
||||
|
||||
otherwise
|
||||
error('Unknown shape %s for filter %s', shape, filt_type);
|
||||
end
|
||||
case 'chebyshev'
|
||||
switch lower(shape)
|
||||
case 'rect'
|
||||
beta = cosh(1/outputdim(1)*acosh(10^5));
|
||||
w1 = cos(outputdim(1)*acos(beta.*cos(pi*Nc/outputdim(1))))/(cosh(1/outputdim(1)*acos(beta)));
|
||||
w1_fft = abs(fft(w1,[],2));
|
||||
beta = cosh(1/outputdim(2)*acosh(10^5));
|
||||
w2 = cos(outputdim(2)*acos(beta.*cos(pi*Nr/outputdim(2))))/(cosh(1/outputdim(2)*acos(beta)));
|
||||
w2_fft = abs(fft(w2,[],1));
|
||||
out = w2_fft.*w1_fft;
|
||||
otherwise
|
||||
error('Unknown shape %s for filter %s', shape, filt_type);
|
||||
|
||||
end
|
||||
otherwise
|
||||
error('Unknown filter %s', filt_type);
|
||||
end
|
||||
|
||||
else
|
||||
switch lower(filt_type)
|
||||
case 'hann'
|
||||
switch lower(shape)
|
||||
case 'rect'
|
||||
% Columns modulation
|
||||
out = (1+cos(2*pi*(Nc- floor((unmodsize(2)-1)/2) )/(outputdim(2)+1-unmodsize(2))))/2;
|
||||
if floor((unmodsize(2)-1)/2)>0
|
||||
out(:,1:floor((unmodsize(2)-1)/2)) = 1;
|
||||
end
|
||||
out(:,floor((unmodsize(2)-1)/2) + outputdim(2)+3-unmodsize(2):length(N1)) = 1;
|
||||
% Row modulation
|
||||
out2 = (1+cos(2*pi*(Nr- floor((unmodsize(1)-1)/2) )/(outputdim(1)+1-unmodsize(1))))/2;
|
||||
if floor((unmodsize(1)-1)/2)>0
|
||||
out2(1:floor((unmodsize(1)-1)/2),:) = 1;
|
||||
end
|
||||
out2(floor((unmodsize(1)-1)/2) + outputdim(1)+3-unmodsize(1):length(N2),:) = 1;
|
||||
|
||||
out = out.*out2;
|
||||
case 'circ'
|
||||
out1d = (1+cos(2*pi*(N- floor((unmodsize(1)-1)/2) )/(outputdim(1)+1-unmodsize(1))))/2;
|
||||
if floor((unmodsize(1)-1)/2)>0
|
||||
out1d(1:floor((unmodsize(1)-1)/2)) = 1;
|
||||
end
|
||||
out1d(floor((unmodsize(1)-1)/2) + outputdim(1)+3-unmodsize(1):length(N)) = 1;
|
||||
out1d = fftshift(out1d);
|
||||
out(r<=Nsz) = interp1(xx,out1d,r(r<=Nsz));
|
||||
out = ifftshift(out);
|
||||
|
||||
otherwise
|
||||
error('Unknown shape %s for filter %s', shape, filt_type);
|
||||
end
|
||||
|
||||
case 'hamm'
|
||||
switch lower(shape)
|
||||
case 'rect'
|
||||
% Columns modulation
|
||||
out = (0.54+0.46*cos(2*pi*(Nc-floor((unmodsize(2)-1)/2))/(outputdim(2)-unmodsize(2))));
|
||||
if floor((unmodsize(2)-1)/2)>0
|
||||
out(:,1:floor((unmodsize(2)-1)/2)) = 1;
|
||||
end
|
||||
% keyboard
|
||||
out(:,floor((unmodsize(2)-1)/2) + outputdim(2)+3-unmodsize(2):length(N1)) = 1;
|
||||
% Row modulation
|
||||
out2 = (0.54+0.46*cos(2*pi*(Nr-floor((unmodsize(1)-1)/2))/(outputdim(1)-unmodsize(1))));
|
||||
if floor((unmodsize(1)-1)/2)>0
|
||||
out2(1:floor((unmodsize(1)-1)/2),:) = 1;
|
||||
end
|
||||
out2(floor((unmodsize(1)-1)/2) + outputdim(1)+3-unmodsize(1):length(N2),:) = 1;
|
||||
|
||||
out = out.*out2;
|
||||
case 'circ'
|
||||
out1d = (0.54+0.46*cos(2*pi*(N-floor((unmodsize(1)-1)/2))/(outputdim(1)-unmodsize(1))));
|
||||
if floor((unmodsize(1)-1)/2)>0
|
||||
out1d(1:floor((unmodsize(1)-1)/2)) = 1;
|
||||
end
|
||||
out1d(floor((unmodsize(1)-1)/2) + outputdim(1)+3-unmodsize(1):length(N)) = 1;
|
||||
out1d = fftshift(out1d);
|
||||
out(r<=Nsz) = interp1(xx,out1d,r(r<=Nsz));
|
||||
out = ifftshift(out);
|
||||
otherwise
|
||||
error('Unknown shape %s for filter %s', shape, filt_type);
|
||||
|
||||
end
|
||||
|
||||
otherwise
|
||||
error('Unknown filter %s', filt_type);
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
% filt2d_pad(outputdim,filterdim,unmodsize)
|
||||
% out = Square array containing a fractional separable Hanning window with
|
||||
% DC in upper left corner.
|
||||
% outputdim = size of the output array
|
||||
% filterdim = size of filter (it will zero pad if filterdim<outputdim
|
||||
% unmodsize = Size of the central array containing no modulation.
|
||||
% Creates a square hanning window if unmodsize = 0 (or ommited), otherwise the output array
|
||||
% will contain an array of ones in the center and cosine modulation on the
|
||||
% edges, the array of ones will have DC in upper left corner.
|
||||
% Code based in fract_hanning_pad
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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.
|
||||
|
||||
|
||||
% License for fract_hanning_pad:
|
||||
% Manuel Guizar - August 17, 2009
|
||||
% Copyright (c) 2016, Manuel Guizar Sicairos, University of Rochester
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
% * Neither the name of the University of Rochester nor the names
|
||||
% of its contributors may be used to endorse or promote products derived
|
||||
% from this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function out = filt2d_pad(outputdim,filterdim,unmodsize, varargin)
|
||||
import utils.filt2d
|
||||
|
||||
if nargin == 1
|
||||
unmodsize = 0;
|
||||
filterdim = outputdim;
|
||||
end
|
||||
|
||||
if any(outputdim < unmodsize)
|
||||
error('Output dimension must be smaller or equal to size of unmodulated window'),
|
||||
end
|
||||
|
||||
if any(outputdim < filterdim)
|
||||
error('Filter cannot be larger than output size'),
|
||||
end
|
||||
|
||||
if any(unmodsize<0)
|
||||
unmodsize = [0 0];
|
||||
warning('Specified unmodsize<0, setting unmodsize = 0')
|
||||
end
|
||||
|
||||
if length(outputdim)<2
|
||||
outputdim = [outputdim outputdim];
|
||||
elseif length(outputdim)>2
|
||||
error('3D filters are not supported.')
|
||||
end
|
||||
|
||||
if length(unmodsize)<2
|
||||
unmodsize = [unmodsize unmodsize];
|
||||
elseif length(unmodsize)>2
|
||||
error('3D filters are not supported.')
|
||||
end
|
||||
|
||||
if length(filterdim)<2
|
||||
filterdim = [filterdim filterdim];
|
||||
elseif length(filterdim)>2
|
||||
error('3D filters are not supported.')
|
||||
end
|
||||
|
||||
out = zeros(outputdim);
|
||||
out(round(outputdim(1)/2+1-filterdim(1)/2):round(outputdim(1)/2+1+filterdim(1)/2-1),...
|
||||
round(outputdim(2)/2+1-filterdim(2)/2):round(outputdim(2)/2+1+filterdim(2)/2-1)) ...
|
||||
= fftshift(filt2d(filterdim,unmodsize,varargin{:}));
|
||||
out = fftshift(out);
|
||||
|
||||
return;
|
||||
@@ -0,0 +1,192 @@
|
||||
% Call function without arguments for a detailed explanation of its use
|
||||
|
||||
% Filename: $RCSfile: find_files.m,v $
|
||||
%
|
||||
% $Revision: 1.9 $ $Date: 2012/08/07 16:39:30 $
|
||||
% $Author: $
|
||||
% $Tag: $
|
||||
%
|
||||
% Description:
|
||||
% find file names matching the specified mask
|
||||
%
|
||||
% Note:
|
||||
% Call without arguments for a brief help text.
|
||||
%
|
||||
% Dependencies:
|
||||
% - Linux/Unix find command, if specified to use
|
||||
%
|
||||
% history:
|
||||
%
|
||||
% October 10th 2009:
|
||||
% only check for files if changing to the directory was possible
|
||||
%
|
||||
% September 14th 2008:
|
||||
% bug fix: add directory to filename in isdir check
|
||||
%
|
||||
% September 4th 2008:
|
||||
% bug fix: vararg_remain was not filled and unhandled parameters did not
|
||||
% cause an error
|
||||
%
|
||||
% June 16th 2008: send find output through sort
|
||||
%
|
||||
% June 10th 2008: 1st documented version
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ directory, fnames, vararg_remain ] = find_files( filename_mask, varargin )
|
||||
import io.image_read
|
||||
import utils.default_parameter_value
|
||||
|
||||
% initialize return arguments
|
||||
fnames = [ ];
|
||||
|
||||
% set default values
|
||||
use_find = default_parameter_value(mfilename,'UseFind');
|
||||
unhandled_par_error = default_parameter_value(mfilename,'UnhandledParError');
|
||||
|
||||
% check minimum number of input arguments
|
||||
if (nargin < 1)
|
||||
fprintf('\nUsage:\n');
|
||||
fprintf('[directory filenames]=%s(filename_mask, [[,<name>,<value>] ...]);\n',mfilename);
|
||||
fprintf('filename_mask can be something like ''*.cbf'' or ''image.cbf''\n');
|
||||
fprintf('The optional <name>,<value> pairs are:\n');
|
||||
fprintf('''UseFind'',<0-no, 1-yes> use Linux/Unix command find to interprete the filename mask, default is %d\n',use_find);
|
||||
fprintf('''UnhandledParError'',<0-no,1-yes> exit in case not all named parameters are used/known, default is %d\n',unhandled_par_error);
|
||||
fprintf('Examples:\n');
|
||||
fprintf('%s(''~/Data10/pilatus/mydatadir/*.cbf'',''OutdirData'',''~/Data10/analysis/my_int_dir/'');\n',mfilename);
|
||||
fprintf('Additional <name>,<value> pairs recognized by image_read can be specified.\n');
|
||||
error('At least the filename mask has to be specified as input argument.');
|
||||
end
|
||||
|
||||
|
||||
% accept cell array with name/value pairs as well
|
||||
no_of_in_arg = nargin;
|
||||
if (nargin == 2)
|
||||
if (isempty(varargin))
|
||||
% ignore empty cell array
|
||||
no_of_in_arg = no_of_in_arg -1;
|
||||
else
|
||||
if (iscell(varargin{1}))
|
||||
% use a filled one given as first and only variable parameter
|
||||
varargin = varargin{1};
|
||||
no_of_in_arg = 1 + length(varargin);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% check number of input arguments
|
||||
if (rem(no_of_in_arg,2) ~= 1)
|
||||
error('The optional parameters have to be specified as ''name'',''value'' pairs');
|
||||
end
|
||||
|
||||
% parse the variable input arguments:
|
||||
% initialize the list of unhandled parameters
|
||||
vararg_remain = cell(0,0);
|
||||
for ind = 1:2:length(varargin)
|
||||
name = varargin{ind};
|
||||
value = varargin{ind+1};
|
||||
switch name
|
||||
case 'UseFind'
|
||||
use_find = value;
|
||||
case 'UnhandledParError'
|
||||
unhandled_par_error = value;
|
||||
otherwise
|
||||
vararg_remain{end+1} = name; %#ok<AGROW>
|
||||
vararg_remain{end+1} = value; %#ok<AGROW>
|
||||
end
|
||||
end
|
||||
|
||||
[directory, name, ext] = fileparts(filename_mask);
|
||||
% add slash to directories
|
||||
if ((~isempty(directory)) && (directory(end) ~= '/'))
|
||||
directory = [ directory '/' ];
|
||||
end
|
||||
|
||||
% exit in case of unhandled named parameters, if this has not been switched
|
||||
% off
|
||||
if ((unhandled_par_error) && (~isempty(vararg_remain)))
|
||||
vararg_remain %#ok<NOPRT>
|
||||
error('Not all named parameters have been handled.');
|
||||
end
|
||||
|
||||
|
||||
% search matching filenames
|
||||
if (use_find)
|
||||
find_cmd = sprintf('find . -noleaf -maxdepth 1 -name ''%s''|sort',[ name ext ]);
|
||||
cd_cmd = '';
|
||||
if (~isempty(directory))
|
||||
%Note by YJ: different linux accounts use different "cd" commands.
|
||||
%cd_cmd may cause error for some users (e.g. user2idd)
|
||||
cd_cmd = sprintf('cd %s 2>/dev/null',directory);
|
||||
end
|
||||
|
||||
% if the directory exists check for files within it
|
||||
st = 1;
|
||||
if ((isempty(directory)) || (exist(directory,'dir')))
|
||||
[st,files]=system([cd_cmd ';' find_cmd ]);
|
||||
%disp([cd_cmd ';' find_cmd ])
|
||||
%disp(files)
|
||||
end
|
||||
% store names of files found in fnames
|
||||
if (st == 0)
|
||||
% count number of newline characters
|
||||
no_of_files = length(sscanf(files,'%*[^\n]%1c'));
|
||||
fnames = struct('name',cell(1,no_of_files),'isdir',cell(1,no_of_files));
|
||||
% extract file names
|
||||
file_ind = 1;
|
||||
while (~isempty(files))
|
||||
name = sscanf(files,'%[^\n]',1);
|
||||
files = files( (length(name)+2):end );
|
||||
if ((length(name) > 2) && (strcmp(name(1:2),'./')))
|
||||
name = name(3:end);
|
||||
end
|
||||
% exclude directory entries . and .. and error messages
|
||||
% starting with find: that may occur if temporary Pilatus files
|
||||
% vanish
|
||||
if ((~strcmp(name,'.')) && ...
|
||||
((length(name) < 5) || (~strcmp(name(1:5),'find:'))))
|
||||
fnames(file_ind).name = name;
|
||||
fnames(file_ind).isdir = isfolder([ directory fnames(file_ind).name ]);
|
||||
file_ind = file_ind +1;
|
||||
end
|
||||
end
|
||||
% shorten the result if for example '.' entries have been skipped
|
||||
if (file_ind <= no_of_files)
|
||||
fnames = fnames(1:(file_ind-1));
|
||||
end
|
||||
end
|
||||
else
|
||||
fnames = dir( filename_mask );
|
||||
end
|
||||
@@ -0,0 +1,103 @@
|
||||
% FIND_IMG_ROTATION_2D find object rotation that provides in projection most sparse features
|
||||
%
|
||||
% [angle] = find_img_rotation_2D(img)
|
||||
%
|
||||
% Inputs:
|
||||
% **img - 2D image to be rotated
|
||||
% *returns*:
|
||||
% ++angle - optimal rotation angle in degrees
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [angle_fine] = find_img_rotation_2D(img, max_range)
|
||||
import math.argmin
|
||||
if nargin < 2
|
||||
max_range = [-22.5,22.5];
|
||||
end
|
||||
|
||||
% grid search first => avoid local minimums
|
||||
|
||||
test_img = abs(img);
|
||||
test_img = max(0, test_img - median(test_img(:)));
|
||||
N = 50;
|
||||
score = zeros(N,1);
|
||||
alpha_range = linspace(max_range(1),max_range(end), N);
|
||||
for i = 1:N
|
||||
score(i) = gather(get_score(test_img, alpha_range(i)));
|
||||
end
|
||||
|
||||
alpha_range = alpha_range(argmin(score)) + (-1:0.1:1);
|
||||
clear score
|
||||
for i = 1:length(alpha_range)
|
||||
score(i) = gather(get_score(test_img, alpha_range(i)));
|
||||
end
|
||||
angle = alpha_range(argmin(score));
|
||||
|
||||
angle_fine = fminsearch(@(x)get_score(test_img, x), angle, struct('TolX', 1e-4));
|
||||
|
||||
|
||||
if isa(angle, 'gpuArray')
|
||||
angle = gather(angle);
|
||||
end
|
||||
fprintf('Optimal image rotation: %.3g°\n', angle_fine)
|
||||
|
||||
end
|
||||
|
||||
function score = get_score(data, angle)
|
||||
Npix = size(data);
|
||||
[X,Y] = meshgrid(-ceil(Npix(2)/2):floor(Npix(2)/2)-1,-ceil(Npix(1)/2):floor(Npix(1)/2)-1);
|
||||
data = data .* (X.^2 / (Npix(2)/2)^2 +Y.^2/(Npix(1)/2)^2 < 1/2);
|
||||
data = data - utils.imgaussfilt2_fft(data,5);
|
||||
|
||||
data = utils.imrotate_ax_fft(data, angle, 3);
|
||||
|
||||
data = data(ceil(end*0.1):floor(end*0.9), ceil(end*0.1):floor(end*0.9));
|
||||
data = (abs(math.fftshift_2D(fft2(data))));
|
||||
score = -mean([sparseness(nanmean(data,1)), ...
|
||||
sparseness(nanmean(data,2))]);
|
||||
score = gather(score);
|
||||
end
|
||||
|
||||
function spars = sparseness(x)
|
||||
%Hoyer's measure of sparsity for a vector
|
||||
% from scipy.linalg import norm
|
||||
|
||||
order_1 = 1;
|
||||
order_2 = 2;
|
||||
x = x(:);
|
||||
sqrt_n = sqrt(length(x));
|
||||
spars = (sqrt_n - norm(x, order_1) / norm(x, order_2)) / (sqrt_n - order_1);
|
||||
end
|
||||
@@ -0,0 +1,102 @@
|
||||
%FIND_LATEST_FILE find latest file in given directory and return path
|
||||
%
|
||||
% *optional input*
|
||||
% path... search path; default './'
|
||||
% file mask... limit results to a specific name or file
|
||||
% extension; default none
|
||||
% offset... take latest-offset; default 0
|
||||
%
|
||||
%
|
||||
% EXAMPLE:
|
||||
% out = find_latest_file;
|
||||
% out = find_latest_file('../analysis');
|
||||
% out = find_latest_file('../analysis', '*.h5');
|
||||
% out = find_latest_file('../analysis', '*recons*.h5');
|
||||
% out = find_latest_file('../analysis', {*recons*.h5, *recons*.mat});
|
||||
% out = find_latest_file('../analysis', '*.h5', -2);
|
||||
%
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ out ] = find_latest_file( varargin )
|
||||
|
||||
% input
|
||||
vars = [];
|
||||
|
||||
if nargin>0
|
||||
vars.path = varargin{1};
|
||||
else
|
||||
vars.path = './';
|
||||
vars.name = [];
|
||||
vars.offset = 0;
|
||||
end
|
||||
|
||||
if nargin>1
|
||||
vars.name = varargin{2};
|
||||
vars.offset = 0;
|
||||
end
|
||||
|
||||
if nargin>2
|
||||
vars.offset = varargin{3};
|
||||
end
|
||||
|
||||
|
||||
% make sure that directory exists
|
||||
if ~isdir(vars.path)
|
||||
error('Could not find directory %s', vars.path)
|
||||
end
|
||||
|
||||
|
||||
% add -name flag if needed
|
||||
if isempty(vars.name)
|
||||
sys_call = sprintf('find %s -type f', vars.path);
|
||||
else
|
||||
if iscell(vars.name)
|
||||
nme = ['''' strjoin(vars.name(:), ''' -o -name ''')];
|
||||
sys_call = sprintf('find %s -type f \\( -name %s'' \\)', vars.path, nme);
|
||||
else
|
||||
sys_call = sprintf('find %s -type f -name ''%s''', vars.path, vars.name);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% okay, let's go
|
||||
[~, out] = system([sys_call ' -printf ''%T@ %p\n'' | sort -n | tail ' num2str((abs(vars.offset)*(-1)-1)) '| cut -f2- -d" " | sed -n ''1p''']);
|
||||
|
||||
out = out(1:end-1);
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
%FIND_PACKAGE_REFS update references in <path> and its subfolders to
|
||||
%package structure in <base_path>.
|
||||
%
|
||||
% base_path... repository with new package structure
|
||||
% path... repository which needs to be updated
|
||||
%
|
||||
% *optional* given as name/value pair
|
||||
% extension... file extension; default '.m'
|
||||
% recursive... recursive behavior; default false
|
||||
% show_files... show file names, otherwise progressbar; default false
|
||||
% filename... change output file name and path; default
|
||||
% ./references.txt
|
||||
%
|
||||
% Example:
|
||||
% find_package_refs('./cSAXS_matlab_base', './cSAXS_matlab_ptycho')
|
||||
% find_package_refs('./cSAXS_matlab_base', './cSAXS_matlab_ptycho', 'recursive', false);
|
||||
%
|
||||
%
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 find_package_refs(base_path, path, varargin )
|
||||
|
||||
% check path
|
||||
if ~exist(path)
|
||||
error('Could not find %s', path)
|
||||
end
|
||||
if ~exist(base_path)
|
||||
error('Could not find %s', base_path)
|
||||
end
|
||||
|
||||
% set default values
|
||||
extension = '.m';
|
||||
recursive = false;
|
||||
show_files = true;
|
||||
filename_with_path = '../references.txt';
|
||||
|
||||
% parse the variable input arguments vararg = cell(0,0);
|
||||
if ~isempty(varargin)
|
||||
for ind = 1:2:length(varargin)
|
||||
name = varargin{ind};
|
||||
value = varargin{ind+1};
|
||||
switch lower(name)
|
||||
case 'extension'
|
||||
extension = value;
|
||||
case 'recursive'
|
||||
recursive = value;
|
||||
case 'show_files'
|
||||
show_files = value;
|
||||
case 'filename'
|
||||
filename_with_path = value;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% avoid overwriting files
|
||||
if exist(filename_with_path,'file')
|
||||
disp(['File ' filename_with_path ' exists,' ])
|
||||
userans = input(['Do you want to overwrite (y/N)? '],'s');
|
||||
if strcmpi(userans,'y')
|
||||
disp(['Saving to ' filename_with_path]);
|
||||
else
|
||||
disp(['Did not save ' filename_with_path])
|
||||
return
|
||||
end
|
||||
else
|
||||
display(['Saving to ' filename_with_path]);
|
||||
end
|
||||
|
||||
|
||||
fileID = fopen(filename_with_path,'w');
|
||||
|
||||
file_list = [];
|
||||
|
||||
|
||||
|
||||
|
||||
% get the target file list
|
||||
if recursive
|
||||
[~, target_fl] = system(['find ' path ' -name "*' extension '"']);
|
||||
target_fl = strsplit(target_fl, '\n');
|
||||
else
|
||||
[target_fl_temp] = dir([path '/*' extension]);
|
||||
for ii=1:length(target_fl_temp)
|
||||
target_fl{ii} = [path '/' target_fl_temp(ii).name];
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
% get the package file list
|
||||
[~, base_fl] = system(['find ' base_path ' -name "*' extension '"']);
|
||||
base_fl = strsplit(base_fl, '\n');
|
||||
for ii=1:length(base_fl)
|
||||
pckg_name = {};
|
||||
substr = strsplit(base_fl{ii}, '/');
|
||||
fn = substr{end};
|
||||
if isempty(fn)
|
||||
continue
|
||||
else
|
||||
% get the updated package name
|
||||
for jj=1:length(substr)
|
||||
try
|
||||
if strcmp(substr{jj}(1), '+')
|
||||
pckg_name{end+1} = substr{jj}(2:end);
|
||||
|
||||
end
|
||||
catch
|
||||
continue
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
pckg_name_full = strjoin(pckg_name, '.');
|
||||
|
||||
if show_files
|
||||
fprintf('-- Updating references to file %s.\n', fn);
|
||||
end
|
||||
|
||||
% call external function and update reference
|
||||
for kk=1:length(target_fl)
|
||||
if ~isempty(target_fl{kk})
|
||||
temp_fn = strsplit(target_fl{kk}, '/');
|
||||
temp_fn = temp_fn{end};
|
||||
if ~isfield(file_list, temp_fn(1:end-length(extension)))
|
||||
file_list.(temp_fn(1:end-length(extension))).pckgs = [];
|
||||
file_list.(temp_fn(1:end-length(extension))).files = [];
|
||||
file_list.(temp_fn(1:end-length(extension))).subfunctions = [];
|
||||
end
|
||||
|
||||
[~, cnt] = system(['grep -n ' fn(1:end-length(extension)) ' ' target_fl{kk} '| wc -l']);
|
||||
count = str2double(cnt);
|
||||
|
||||
if strcmp(fn, temp_fn) && count<=1
|
||||
fprintf('Skipping %s\n', fn)
|
||||
continue
|
||||
elseif count >=1
|
||||
[~, cnt] = system(['grep -n ''^function'' ' target_fl{kk} '| wc -l']);
|
||||
count = str2double(cnt) -1;
|
||||
file_list.(temp_fn(1:end-length(extension))).pckgs{end+1} = pckg_name_full;
|
||||
file_list.(temp_fn(1:end-length(extension))).files{end+1} = [pckg_name_full '.' fn(1:end-length(extension))];
|
||||
file_list.(temp_fn(1:end-length(extension))).subfunctions = (count>0)*count;
|
||||
end
|
||||
end
|
||||
end
|
||||
if ~show_files
|
||||
utils.progressbar(ii, length(base_fl))
|
||||
end
|
||||
end
|
||||
|
||||
fn = fieldnames(file_list);
|
||||
for ii=1:length(fn)
|
||||
if ~isempty(unique(file_list.(fn{ii}).pckgs(:)))
|
||||
fprintf(fileID, [fn{ii} '\n']);
|
||||
fprintf(fileID, [strjoin(unique(file_list.(fn{ii}).pckgs(:)), '\t') '\n']);
|
||||
fprintf(fileID, [strjoin(unique(file_list.(fn{ii}).files(:)), '\t') '\n']);
|
||||
fprintf(fileID, ['Subfunctions: ' num2str(file_list.(fn{ii}).subfunctions)]);
|
||||
fprintf(fileID, ['\n\n']);
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
fclose(fileID);
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
% FIND_SHIFT_FAST_1D uses cross-correlation to find shift between 1D patterns o1 and
|
||||
% o2, if the patterns are 2D, perform the search along the axis `ax`
|
||||
%
|
||||
% shift = find_shift_fast_1D(o1, o2, ax, sigma)
|
||||
%
|
||||
% Inputs:
|
||||
% **o1 - aligned array 1D/2D (will be aligned along 1st axis)
|
||||
% **o2 - template for alignment 1D or 2D
|
||||
% **ax - perform search along this axis
|
||||
% *optional*
|
||||
% **sigma - filtering intensity [0-1 range], sigma <= 0 no filtering, recommended sigma < 0.05
|
||||
% **padding - pading [in pixels] the provided array by zeros, prevent circular boundary condition in FFT, default = 0
|
||||
% *returns*
|
||||
% ++shift - (vector) displacement of the 1D/2D arrays
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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
|
||||
%
|
||||
|
||||
|
||||
|
||||
function shift = find_shift_fast_1D(o1, o2, ax, sigma, padding)
|
||||
|
||||
if nargin < 3
|
||||
ax = 2;
|
||||
end
|
||||
if nargin < 4
|
||||
sigma = 0;
|
||||
end
|
||||
if nargin < 5
|
||||
padding = 0;
|
||||
else
|
||||
padding = ceil(padding/2)*2;
|
||||
end
|
||||
|
||||
max_shift = size(o1,ax)/3; % avoid too large corrections !!!
|
||||
|
||||
Ndims = ndims(o1);
|
||||
|
||||
if ax ~= 1
|
||||
error('FIXME: Not tested axis')
|
||||
end
|
||||
|
||||
%% symmetrize before spectral filtering !!
|
||||
o1 = cat(ax, o1, flipud(o1));
|
||||
o2 = cat(ax, o2, flipud(o2));
|
||||
Npix = size(o1);
|
||||
|
||||
shape = ones(1,Ndims);
|
||||
shape(ax) = Npix(ax);
|
||||
|
||||
if sigma > 0
|
||||
%% high pass filter
|
||||
o1 = fft(o1, [],ax);
|
||||
o2 = fft(o2, [],ax);
|
||||
x = reshape((-Npix(ax)/2+1:Npix(ax)/2)/Npix(ax), shape);
|
||||
spectral_filter = fftshift(exp(1./(-(x.^2)/(sigma^2))));
|
||||
spectral_filter(floor(end/2+[-3:3])) = 0; %% remove some strange artefacts
|
||||
o1 = bsxfun(@times, o1, spectral_filter);
|
||||
o2 = bsxfun(@times, o2, spectral_filter);
|
||||
o1 = ifft(o1, [],ax);
|
||||
o2 = ifft(o2, [],ax);
|
||||
|
||||
end
|
||||
|
||||
% remove symetrization !!
|
||||
o1 = o1(1:end/2,:);
|
||||
o2 = o2(1:end/2,:);
|
||||
o1 = padarray(o1, padding/2, 'both');
|
||||
o2 = padarray(o2, padding/2, 'both');
|
||||
|
||||
|
||||
Npix = size(o1);
|
||||
shape = ones(1,Ndims);
|
||||
shape(ax) = Npix(ax);
|
||||
|
||||
%% remove edge issues (after symetrized filtering )
|
||||
spatial_filter = reshape(tukeywin(prod(shape)), shape);
|
||||
o1 = bsxfun(@times, o1, spatial_filter);
|
||||
o2 = bsxfun(@times, o2, spatial_filter);
|
||||
|
||||
o1 = fft(o1, [],ax);
|
||||
o2 = fft(o2, [],ax);
|
||||
|
||||
%% cross-correlation
|
||||
xcorrmat = abs(ifft(o1.*conj(o2),[],ax));
|
||||
%% 1D fftshift
|
||||
xcorrmat = circshift(xcorrmat, floor(Npix(ax)/2), ax);
|
||||
if ax == 2; error('FIXME: Not tested axis'); end
|
||||
|
||||
% choose only optimim withing reduced range
|
||||
xcorrmat([1:ceil(end/2-max_shift), ceil(end/2+max_shift):end],:) = 0;
|
||||
|
||||
%% take only small region around maximum
|
||||
WIN = 10;
|
||||
kernel_size = [1,1];
|
||||
kernel_size(ax) = WIN;
|
||||
mask = conv2(single(bsxfun(@eq, xcorrmat, max(xcorrmat,[],ax))), ones(kernel_size), 'same');
|
||||
xcorrmat(~mask) = nan;
|
||||
xcorrmat = max(0, bsxfun(@minus, xcorrmat, min(xcorrmat,[],ax)));
|
||||
xcorrmat(~mask) = 0;
|
||||
xcorrmat = bsxfun(@times, xcorrmat, 1./max(xcorrmat,[],ax)).^4;
|
||||
|
||||
|
||||
%% find center of mass
|
||||
MASS = sum(xcorrmat,ax);
|
||||
grid = reshape(1:Npix(ax),shape);
|
||||
shift = sum(bsxfun(@times, xcorrmat, grid),ax) ./ MASS - floor(Npix(ax)/2)-1;
|
||||
|
||||
end
|
||||
@@ -0,0 +1,156 @@
|
||||
% FIND_SHIFT_FAST_2D uses crosscorelation to find shift between o1 nd
|
||||
% o2 patterns in 3D space
|
||||
%
|
||||
% shift = find_shift_fast_2D(o1, o2, sigma, apply_fft)
|
||||
%
|
||||
% Inputs:
|
||||
% **o1 - aligned array 2D or 3D, (for stack of images, alignment is done along 3rd axis)
|
||||
% **o2 - template for alignment 2D or 3D
|
||||
% **sigma - filtering intensity [0-1 range], sigma <= 0 no filtering, recommended sigma < 0.05
|
||||
% **apply_fft - if false, assume o1 and o2 to be already in fourier domain
|
||||
% *returns*
|
||||
% ++shift - displacement of the 2D volumes
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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
|
||||
%
|
||||
|
||||
|
||||
function shift = find_shift_fast_2D(o1, o2, sigma, apply_fft, method)
|
||||
|
||||
|
||||
import math.*
|
||||
|
||||
|
||||
if nargin < 4
|
||||
apply_fft = true;
|
||||
end
|
||||
if nargin < 3
|
||||
sigma = 0.01;
|
||||
end
|
||||
if nargin < 5
|
||||
method = 'full_range';
|
||||
end
|
||||
|
||||
if apply_fft
|
||||
|
||||
[nx, ny, ~] = size(o1);
|
||||
|
||||
% suppress edge effects of the registration procedure
|
||||
spatial_filter = tukeywin(nx,0.5) * tukeywin(ny,0.5)';
|
||||
|
||||
o1 = bsxfun(@times, o1, spatial_filter);
|
||||
o2 = bsxfun(@times, o2, spatial_filter);
|
||||
|
||||
o1 = fft2(o1);
|
||||
o2 = fft2(o2);
|
||||
end
|
||||
|
||||
[nx, ny, ~] = size(o1);
|
||||
|
||||
if sigma > 0
|
||||
% remove low frequencies
|
||||
[X,Y] = meshgrid( (-nx/2:nx/2-1)/nx, (-ny/2:ny/2-1)/ny);
|
||||
spectral_filter = fftshift(exp(1./(-(X.^2+Y.^2)/sigma^2)))';
|
||||
o1 = bsxfun(@times, o1, spectral_filter);
|
||||
o2 = bsxfun(@times, o2, spectral_filter);
|
||||
end
|
||||
|
||||
|
||||
% fast subpixel cross correlation
|
||||
xcorrmat = fftshift_2D(abs(ifft2(o1.*conj(o2))));
|
||||
|
||||
|
||||
% %% just for testing
|
||||
% subplot(3,1,1)
|
||||
% imagesc(abs(fft2(o1(:,:,1)))); axis off image; colormap bone
|
||||
% subplot(3,1,2)
|
||||
% imagesc(abs(fft2(o2(:,:,1)))); axis off image; colormap bone
|
||||
% subplot(3,1,3)
|
||||
% imagesc(xcorrmat(:,:,1)); axis off image; colormap bone
|
||||
% drawnow
|
||||
% pause(0.1)
|
||||
|
||||
switch method
|
||||
case 'full_range'
|
||||
%% take only small region around maximum
|
||||
WIN = 5;
|
||||
kernel_size = [WIN,WIN];
|
||||
% convolution may be quite slow ?
|
||||
mask = convn(single(bsxfun(@eq, xcorrmat, max2(xcorrmat))), ones(kernel_size,'single'), 'same');
|
||||
xcorrmat(~mask) = nan;
|
||||
xcorrmat = max(0, bsxfun(@minus, xcorrmat, min2(xcorrmat)));
|
||||
xcorrmat(~mask) = 0;
|
||||
xcorrmat = bsxfun(@times, xcorrmat, 1./max2(xcorrmat)).^2;
|
||||
|
||||
%% get CoM of the central peak only !!, assume a single peak
|
||||
xcorrmat = max(0, xcorrmat - 0.5).^2;
|
||||
[x,y] = find_center_fast(xcorrmat);
|
||||
shift = [x,y];
|
||||
|
||||
case 'limited_range'
|
||||
% second option: assume that the shifts are only small, it is faster
|
||||
mxcorr = mean(xcorrmat,3);
|
||||
[m,n] = find(mxcorr == max(mxcorr(:)));
|
||||
|
||||
MAX_SHIFT = 10; % +-10px search
|
||||
MAX_SHIFT_X = min(floor(nx/2-0.5),MAX_SHIFT);
|
||||
MAX_SHIFT_Y = min(floor(ny/2-0.5),MAX_SHIFT);
|
||||
|
||||
xrange = (-MAX_SHIFT_X:MAX_SHIFT_X);
|
||||
yrange = (-MAX_SHIFT_Y:MAX_SHIFT_Y);
|
||||
|
||||
idx = { m + xrange,n+yrange,':'};
|
||||
xcorrmat = xcorrmat(idx{:});
|
||||
MAX = max(max(xcorrmat));
|
||||
|
||||
xcorrmat = bsxfun(@times, xcorrmat, 1. / MAX);
|
||||
|
||||
%% get CoM of the central peak only !!, assume a single peak
|
||||
xcorrmat = max(0, xcorrmat - 0.5).^2;
|
||||
[x,y] = find_center_fast(xcorrmat);
|
||||
shift = [x,y]+[n,m]-floor([ny,nx]/2)-1;
|
||||
end
|
||||
|
||||
if any(isnan(gather(shift)))
|
||||
keyboard
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function [x,y,MASS] = find_center_fast(xcorrmat)
|
||||
MASS = squeeze(sum(sum(xcorrmat)));
|
||||
[N,M,~] = size(xcorrmat);
|
||||
x = squeeze(sum( bsxfun(@times, sum(xcorrmat,1), 1:M), 2)) ./ MASS - floor(M/2)-1;
|
||||
y = squeeze(sum(bsxfun(@times, sum(xcorrmat,2), (1:N)'),1)) ./ MASS - floor(N/2)-1;
|
||||
end
|
||||
@@ -0,0 +1,115 @@
|
||||
% FIND_SHIFT_FAST_3D uses crosscorelation to find shift between o1 nd
|
||||
% o2 patterns in 3D space
|
||||
%
|
||||
% shift = find_shift_fast_3D(o1, o2, sigma, apply_fft)
|
||||
%
|
||||
% Inputs:
|
||||
% **o1 - aligned array 3D - return only single shift vector [x,y,z]
|
||||
% **o2 - template for alignement 3D
|
||||
% **sigma - filtering intensity [0-1 range], sigma <= 0 no filtering, recommended sigma < 0.05
|
||||
% **apply_fft - if false, assume o1 and o2 to be already in fourier domain
|
||||
% *returns*
|
||||
% ++shift - displacement of the 3D volumes
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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
|
||||
%
|
||||
|
||||
|
||||
function shift = find_shift_fast_3D(o1, o2, sigma, apply_fft)
|
||||
|
||||
|
||||
import math.*
|
||||
|
||||
assert(ndims(o1) == 3, 'Inputs has to be 3D matrix')
|
||||
assert(ndims(o2) == 3, 'Inputs has to be 3D matrix')
|
||||
|
||||
if nargin < 4
|
||||
apply_fft = true;
|
||||
end
|
||||
if nargin < 3
|
||||
sigma = 0.01;
|
||||
end
|
||||
|
||||
|
||||
if apply_fft
|
||||
|
||||
[nx, ny, nz] = size(o1);
|
||||
|
||||
% suppress edge effects of the registration procedure
|
||||
spatial_filter = tukeywin(nx,0.5) * tukeywin(ny,0.5)' .* reshape(tukeywin(nz,0.5),1,1,[]);
|
||||
|
||||
o1 = bsxfun(@times, o1, spatial_filter);
|
||||
o2 = bsxfun(@times, o2, spatial_filter);
|
||||
|
||||
clear spatial_filter
|
||||
|
||||
o1 = fftn(o1);
|
||||
o2 = fftn(o2);
|
||||
|
||||
end
|
||||
|
||||
[nx, ny, ~] = size(o1);
|
||||
|
||||
if sigma > 0
|
||||
% remove low frequencies
|
||||
[X,Y,Z] = meshgrid( (-nx/2:nx/2-1)/nx, (-ny/2:ny/2-1)/ny, (-nz/2:nz/2-1)/nz);
|
||||
spectral_filter = fftshift(exp(1./(-(X.^2+Y.^2+Z.^2)/sigma^2)));
|
||||
o1 = bsxfun(@times, o1, spectral_filter);
|
||||
o2 = bsxfun(@times, o2, spectral_filter);
|
||||
clear spectral_filter
|
||||
end
|
||||
|
||||
|
||||
% fast subpixel cross correlation
|
||||
xcorrmat = fftshift(abs(ifftn(o1.*conj(o2))));
|
||||
|
||||
|
||||
%% take only small region around maximum
|
||||
|
||||
WIN = 5;
|
||||
kernel_size = [WIN,WIN,WIN];
|
||||
xcorrmat = xcorrmat / max(xcorrmat(:));
|
||||
xcorrmat = xcorrmat .* convn(xcorrmat == 1, ones(kernel_size,'single'), 'same');
|
||||
[x,y,z] = find_center_fast(xcorrmat.^2);
|
||||
shift = [x,y,z];
|
||||
|
||||
end
|
||||
|
||||
function [x,y,z] = find_center_fast(xcorrmat)
|
||||
MASS = squeeze(sum(xcorrmat(:)));
|
||||
[N,M,O] = size(xcorrmat);
|
||||
x = squeeze(sum(sum(sum(xcorrmat .* (1:M),1)))) ./ MASS - floor(M/2)-1;
|
||||
y = squeeze(sum(sum(sum(xcorrmat .* (1:N)',2)))) ./ MASS - floor(N/2)-1;
|
||||
z = squeeze(sum(sum(sum(xcorrmat .* reshape(1:O,1,1,[]),3) ))) ./ MASS - floor(O/2)-1;
|
||||
end
|
||||
@@ -0,0 +1,65 @@
|
||||
% function residues = findresidues(phase)
|
||||
% Receives phase in radians, returns map of residues
|
||||
% Manuel Guizar - Sept 27, 2011
|
||||
% R. M. Goldstein, H. A. Zebker and C. L. Werner, Radio Science 23, 713-720
|
||||
% (1988).
|
||||
% Inputs
|
||||
% phase Phase in radians
|
||||
% disp = 0, No feedback
|
||||
% = 1, Text feedback (additional computation)
|
||||
% = 2, Text and graphic display (additional computation)
|
||||
% Outputs
|
||||
% residues Map of residues, note they are valued +1 or -1
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 residues = findresidues(phase)
|
||||
|
||||
if ~isreal(phase)
|
||||
phase = angle(phase);
|
||||
end
|
||||
|
||||
residues = wrapToPi(phase(2:end,1:end-1,:) - phase(1:end-1,1:end-1,:));
|
||||
residues = residues + wrapToPi(phase(2:end,2:end,:) - phase(2:end,1:end-1,:));
|
||||
residues = residues + wrapToPi(phase(1:end-1,2:end,:) - phase(2:end,2:end,:));
|
||||
residues = residues + wrapToPi(phase(1:end-1,1:end-1,:) - phase(1:end-1,2:end,:));
|
||||
residues = residues/(2*pi);
|
||||
|
||||
end
|
||||
|
||||
function x = wrapToPi(x)
|
||||
x = mod(x+pi, 2*pi)-pi;
|
||||
end
|
||||
@@ -0,0 +1,193 @@
|
||||
% function [ out ] = focus_series_fit( scans, p )
|
||||
% Receives scan numbers and parameters as a structure p
|
||||
% Input:
|
||||
% scans
|
||||
% For SPEC variables
|
||||
% p.motor_name From SPEC
|
||||
% p.counter From SPEC
|
||||
% For sgalil position file
|
||||
% p.position_file Example '~/Data10/sgalil/S%05d.dat'
|
||||
% p.fast_axis_index (= 1 or 2) for x or y scan respectively
|
||||
% For mcs counter
|
||||
% p.mcs_file Example sprintf('~/Data10/mcs/S%02d000-%02d999/S%%05d/%s_%%05d.dat',floor(scans(ii)/1000),floor(scans(ii)/1000),beamline.identify_eaccount);
|
||||
% p.mcs_channel Channel number, e.g. = 3
|
||||
%
|
||||
% Optional
|
||||
% p.motor_units
|
||||
% p.plot
|
||||
% p.title_str
|
||||
% p.coarse_motor
|
||||
%
|
||||
% Output
|
||||
% out.fitout Parameters of quadratic fit
|
||||
% out.coarse_motor Coarse motor name is passed back
|
||||
% out.fwhm A vector with the fwhm for each scan
|
||||
% out.vertex The position of coarse motor with minimum fwhm from the quadratic fit
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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) 2018 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 [ out ] = focus_series_fit( scans, p )
|
||||
|
||||
|
||||
out = struct;
|
||||
|
||||
if isempty(scans)
|
||||
error('Scans input seems to be empty')
|
||||
end
|
||||
if ~isfield(p,'plot')
|
||||
p.plot = true;
|
||||
end
|
||||
if ~isfield(p,'title_str')
|
||||
p.title_str = '';
|
||||
end
|
||||
if ~isfield(p,'motor_units')
|
||||
p.motor_units = '';
|
||||
end
|
||||
if ~isfield(p,'coarse_motor')
|
||||
p.motor_units = '';
|
||||
end
|
||||
if ~isfield(p,'pausetime')
|
||||
p.pausetime = 0;
|
||||
end
|
||||
% mcs
|
||||
if ~isfield(p,'mcs_file')
|
||||
p.mcs_file = [];
|
||||
end
|
||||
if ~isfield(p,'mcs_channel')
|
||||
p.mcs_channel = [];
|
||||
end
|
||||
|
||||
% sgalil
|
||||
if ~isfield(p,'position_file')
|
||||
p.position_file = [];
|
||||
end
|
||||
if ~isfield(p,'fast_axis_index')
|
||||
p.fast_axis_index = 1;
|
||||
end
|
||||
|
||||
S_all=io.spec_read('~/Data10/','ScanNr',scans);
|
||||
width = scans*0;
|
||||
coarse_motor = scans*0;
|
||||
|
||||
for ii=1:length(scans)
|
||||
|
||||
if numel(S_all) == 1
|
||||
S{1} = S_all;
|
||||
else
|
||||
S = S_all;
|
||||
end
|
||||
|
||||
if isempty(p.mcs_file)
|
||||
y = getfield(S{ii},p.counter); %#ok<GFLD>
|
||||
y(1:end-1)=diff(y);
|
||||
y(end) = 0;
|
||||
y(end)=y(end-1);
|
||||
else
|
||||
data = io.image_read(sprintf(p.mcs_file,scans(ii),scans(ii)));
|
||||
y = squeeze(data.data(p.mcs_channel,1,:));
|
||||
y(1:end-1)=diff(y);
|
||||
y([end end+1]) = 0;
|
||||
end
|
||||
|
||||
if isempty(p.position_file)
|
||||
x = getfield(S{ii},p.motor_name); %#ok<GFLD>
|
||||
else
|
||||
data = io.image_read(sprintf(p.position_file,scans(ii)));
|
||||
x = data.data(p.fast_axis_index,:).';
|
||||
end
|
||||
|
||||
% General model Gauss1:
|
||||
% f(x) = a1*exp(-((x-b1)/c1)^2)
|
||||
% Coefficients (with 95% confidence bounds):
|
||||
% a1 = -2754 (-2839, -2669)
|
||||
% b1 = -84.29 (-84.29, -84.28)
|
||||
% c1 = 0.002197 (0.002118, 0.002276)
|
||||
|
||||
[yabsmax, ind_absmax] = max(abs(y));
|
||||
% p0.a1 = y(ind_absmax);
|
||||
% p0.b1 = x(ind_absmax);
|
||||
% p0.c1 = 1e-9;
|
||||
p0 = [y(ind_absmax) x(ind_absmax) 1e-3];
|
||||
|
||||
% f = fit(x,y,'gauss1');
|
||||
f = fit(x,y,'gauss1', 'StartPoint', p0 );
|
||||
|
||||
if p.plot
|
||||
figure(4)
|
||||
plot(f,x,y,'.-');
|
||||
title(p.title_str)
|
||||
xlabel(sprintf('%s %s',p.motor_name,p.motor_units))
|
||||
ylabel(p.counter)
|
||||
drawnow
|
||||
pause(p.pausetime)
|
||||
end
|
||||
|
||||
width(ii)=f.c1*2*sqrt(2*log(2))/sqrt(2);
|
||||
fprintf('S%05d, FWHM = %.2e %s\n',scans(ii),width(ii),p.motor_units)
|
||||
coarse_motor(ii)=getfield(S{ii},p.coarse_motor); %#ok<GFLD>
|
||||
end
|
||||
|
||||
figure(5)
|
||||
plot(coarse_motor,width,'-bo')
|
||||
title(p.title_str)
|
||||
xlabel(p.coarse_motor)
|
||||
ylabel(sprintf('FWHM %s',p.motor_units))
|
||||
|
||||
if numel(scans)>2
|
||||
|
||||
h = fit(coarse_motor.',width.','poly2');
|
||||
|
||||
figure(6)
|
||||
plot(h,coarse_motor,width);
|
||||
title(p.title_str)
|
||||
xlabel(p.coarse_motor)
|
||||
ylabel(sprintf('FWHM %s',p.motor_units))
|
||||
|
||||
vertex = -h.p2/(2*h.p1);
|
||||
fprintf('\n\nThe vertex of the parabola is at %s = %f\n\n',p.coarse_motor,vertex)
|
||||
|
||||
fprintf('Average FWHM = %.2e %s\n',mean(width),p.motor_units)
|
||||
fprintf('Minimum FWHM = %.2e %s\n',min(width),p.motor_units)
|
||||
fprintf('Maximum FWHM = %.2e %s\n',max(width),p.motor_units)
|
||||
|
||||
out.fitout = h;
|
||||
out.coarse_motor = coarse_motor;
|
||||
out.fwhm = width;
|
||||
out.vertex = vertex;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
% A script to analyze vertica and horizontal through focus scans to
|
||||
% determine the size and position of the horizontal and vertical focii
|
||||
|
||||
addpath ..
|
||||
close all
|
||||
clear
|
||||
%% vertical beam
|
||||
|
||||
scans = [797:806];
|
||||
|
||||
p.motor_name = 'py';
|
||||
p.title_str = 'Vertical beam';
|
||||
p.motor_units = '(microns)';
|
||||
p.counter = 'diode';
|
||||
p.pausetime = 0.5;
|
||||
p.coarse_motor = 'hz';
|
||||
|
||||
out_ver = utils.focus_series_fit(scans,p);
|
||||
|
||||
%% horizontal beam
|
||||
|
||||
scans = [650:660];%[183:193];%[505:514];% scans 108 to, 89 to
|
||||
|
||||
p.motor_name = 'px';
|
||||
p.title_str = 'Horizontal beam';
|
||||
p.motor_units = '(microns)';
|
||||
p.counter = 'diode';
|
||||
p.pausetime = 0.5;
|
||||
p.coarse_motor = 'hz';
|
||||
|
||||
out_hor = utils.focus_series_fit(scans,p);
|
||||
|
||||
%% plot both
|
||||
figure(7)
|
||||
plot(out_ver.fitout,'b',out_ver.coarse_motor,out_ver.fwhm,'bo');
|
||||
hold on
|
||||
plot(out_hor.fitout,'r',out_hor.coarse_motor,out_hor.fwhm,'ro');
|
||||
title(sprintf('beam focus, vertex (hor,ver) (%.1f, %.1f)',out_hor.vertex,out_ver.vertex))
|
||||
xlabel(p.coarse_motor)
|
||||
ylabel(sprintf('FWHM %s',p.motor_units))
|
||||
legend('vertical','fit','horizontal','fit')
|
||||
hold off
|
||||
fprintf('The vertical vertex of the parabola is at %s = %f\n',p.coarse_motor, out_ver.vertex);
|
||||
fprintf('The horizontal vertex of the parabola is at %s = %f\n',p.coarse_motor,out_hor.vertex);
|
||||
|
||||
%% Example for sgalil continuous scan
|
||||
|
||||
scans = [797:806];
|
||||
|
||||
p.position_file = '~/Data10/sgalil/S%05d.dat';
|
||||
p.fast_axis_index = 1; % = 1 or 2 for x and y scan respectively
|
||||
p.mcs_file = sprintf('~/Data10/mcs/S%02d000-%02d999/S%%05d/%s_%%05d.dat',floor(scans(1)/1000),floor(scans(1)/1000),beamline.identify_eaccount);
|
||||
p.mcs_channel = 3;
|
||||
p.title_str = 'Horizontal beam';
|
||||
p.motor_units = '(mm)';
|
||||
p.counter = 'diode';
|
||||
p.pausetime = 0.5;
|
||||
p.coarse_motor = 'samy';
|
||||
|
||||
out_ver = utils.focus_series_fit(scans,p);
|
||||
|
||||
%%
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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) 2018 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.
|
||||
@@ -0,0 +1,67 @@
|
||||
%%% Following a feature
|
||||
for ii = 1:numel(object)
|
||||
obj{ii} = angle(object{ii});
|
||||
end
|
||||
pixsize = p.dx_spec(1)*1e6; % Microns
|
||||
|
||||
%Inputs
|
||||
% obj Is a cell with different objects
|
||||
% pixsize Pixel size
|
||||
|
||||
% Create useful arrays
|
||||
for ii = 1:numel(object)
|
||||
axisx{ii} = ([1:size(obj{ii},2)]-floor(object_size(2)/2)+1)*pixsize;
|
||||
axisy{ii} = ([1:size(obj{ii},1)]-floor(object_size(1)/2)+1)*pixsize;
|
||||
xind {ii} = [1:size(obj{ii},2)];
|
||||
yind{ii} = [1:size(obj{ii},1)];
|
||||
end
|
||||
|
||||
|
||||
%% Feature characteristics
|
||||
f.sigma = 1.5; % Feature width in real units
|
||||
f.contrast = -1;
|
||||
|
||||
sigma_ind = f.sigma/pixsize; % Feature width in pixels
|
||||
|
||||
figure(1)
|
||||
% imagesc(axisx{1},axisy{1},obj{1});
|
||||
imagesc(obj{1});
|
||||
axis xy equal tight
|
||||
colormap bone
|
||||
xlabel('\mum')
|
||||
[xinp,yinp] = ginput(1);
|
||||
xinp = round(xinp);
|
||||
yinp = round(yinp);
|
||||
|
||||
x1 = xind{1}(abs(xind{1}-xinp)<2*sigma_ind);
|
||||
y1 = yind{1}(abs(yind{1}-yinp)<2*sigma_ind);
|
||||
x2 = x1;
|
||||
y2 = y1;
|
||||
|
||||
for ii = 1:3
|
||||
[X Y] = meshgrid(xind{ii},yind{ii});
|
||||
ref = f.contrast*exp(-((X-xinp).^2+(Y-yinp).^2)/(2*sigma_ind^2));
|
||||
x1 = xind{1}(abs(xind{1}-xinp)<2*sigma_ind);
|
||||
y1 = yind{1}(abs(yind{1}-yinp)<2*sigma_ind);
|
||||
x2 = x1;
|
||||
y2 = y1;
|
||||
[subim1, subim2, delta, deltafine, regionsout] = registersubimages_2(obj{1}, ref, x1, y1, x2, y2, 10, 1, 1);
|
||||
% delta is (y,x) correction
|
||||
xinp = xinp - delta(2);
|
||||
yinp = yinp - delta(1);
|
||||
xposobjind(ii) = xinp;
|
||||
yposobjind(ii) = yinp;
|
||||
end
|
||||
|
||||
%%
|
||||
ii = 3;
|
||||
figure(2)
|
||||
% imagesc(axisx{1},axisy{1},ref);
|
||||
% imagesc(ref);
|
||||
imagesc(obj{ii});
|
||||
axis xy equal tight
|
||||
colormap bone
|
||||
hold on;
|
||||
plot(xposobjind(ii),yposobjind(ii),'ow')
|
||||
hold off;
|
||||
xlabel('pixels')
|
||||
@@ -0,0 +1,209 @@
|
||||
% Call function without arguments for a detailed explanation of its use
|
||||
|
||||
% Filename: $RCSfile: fopen_until_exists.m,v $
|
||||
%
|
||||
% $Revision: 1.9 $ $Date: 2011/08/13 17:37:15 $
|
||||
% $Author: $
|
||||
% $Tag: $
|
||||
%
|
||||
% Description:
|
||||
% Open a file, in case of failure retry repeatedly if this has been
|
||||
% specified.
|
||||
%
|
||||
% Note:
|
||||
% Call without arguments for a brief help text.
|
||||
%
|
||||
% Dependencies:
|
||||
% none
|
||||
%
|
||||
%
|
||||
% history:
|
||||
%
|
||||
% September 5th 2009:
|
||||
% bug fix in the zero file length check
|
||||
%
|
||||
% August 28th 2008:
|
||||
% use dir rather than fopen to check for the file and check additionally
|
||||
% that it is not of length zero
|
||||
%
|
||||
% May 9th 2008: 1st version
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [fid,vararg_remain] = fopen_until_exists(filename,varargin)
|
||||
|
||||
% set default values for the variable input arguments and parse the named
|
||||
% parameters:
|
||||
|
||||
% If the file has not been found and if this value is greater than 0.0 than
|
||||
% sleep for the specified time in seconds and retry reading the file.
|
||||
% This is repeated until the file has been successfully read
|
||||
% (retry_read_max=0) or until the maximum number of iterations is exceeded
|
||||
% (retry_read_max>0).
|
||||
retry_read_sleep_sec = 0.0;
|
||||
retry_read_max = 0;
|
||||
retry_sleep_when_found_sec = 0.0;
|
||||
|
||||
% exit with error message if the file has not been found
|
||||
error_if_not_found = 1;
|
||||
|
||||
% display a message once in case opening failed
|
||||
message_if_not_found = 1;
|
||||
|
||||
if (nargin < 1)
|
||||
fprintf('Usage:\n');
|
||||
fprintf('[fid] = %s(filename [[,<name>,<value>],...]);\n',...
|
||||
mfilename);
|
||||
fprintf('filename name of the file to open\n');
|
||||
fprintf('The optional name value pairs are:\n');
|
||||
fprintf('''RetryReadSleep'',<seconds> if greater than zero retry opening after this time (default: 0.0)\n');
|
||||
fprintf('''RetryReadMax'',<0-...> maximum no. of retries, 0 for infinity (default: 0)\n');
|
||||
fprintf('''RetrySleepWhenFound'',<seconds> if greater than zero wait for this time after a retry succeeded (default: %.1f)\n', ...
|
||||
retry_sleep_when_found_sec);
|
||||
fprintf('''MessageIfNotFound'',<0-no,1-yes> display a mesage if not found, 1-yes is default\n');
|
||||
fprintf('''ErrorIfNotFound'',<0-no,1-yes> exit with an error if not found, default is 1-yes\n');
|
||||
fprintf('The file ID of the opened file is returned or -1 in case of failure.\n');
|
||||
error('Invalid number of input parameters.');
|
||||
end
|
||||
|
||||
% check minimum number of input arguments
|
||||
if (nargin < 1)
|
||||
display_help();
|
||||
error('At least the filename has to be specified as input parameter.');
|
||||
end
|
||||
|
||||
% accept cell array with name/value pairs as well
|
||||
no_of_in_arg = nargin;
|
||||
if (nargin == 2)
|
||||
if (isempty(varargin))
|
||||
% ignore empty cell array
|
||||
no_of_in_arg = no_of_in_arg -1;
|
||||
else
|
||||
if (iscell(varargin{1}))
|
||||
% use a filled one given as first and only variable parameter
|
||||
varargin = varargin{1};
|
||||
no_of_in_arg = 1 + length(varargin);
|
||||
end
|
||||
end
|
||||
end
|
||||
% check number of input arguments
|
||||
if (rem(no_of_in_arg,2) ~= 1)
|
||||
error('The optional parameters have to be specified as ''name'',''value'' pairs');
|
||||
end
|
||||
|
||||
|
||||
% parse the variable input arguments
|
||||
vararg_remain = cell(0,0);
|
||||
for ind = 1:2:length(varargin)
|
||||
name = varargin{ind};
|
||||
value = varargin{ind+1};
|
||||
switch name
|
||||
case 'RetryReadSleep'
|
||||
retry_read_sleep_sec = value;
|
||||
case 'RetryReadMax'
|
||||
retry_read_max = value;
|
||||
case 'RetrySleepWhenFound'
|
||||
retry_sleep_when_found_sec = value;
|
||||
case 'MessageIfNotFound'
|
||||
message_if_not_found = value;
|
||||
case 'ErrorIfNotFound'
|
||||
error_if_not_found = value;
|
||||
otherwise
|
||||
vararg_remain{end+1} = name;
|
||||
vararg_remain{end+1} = value;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% try to access the file entry
|
||||
file_non_empty = 0;
|
||||
dir_entry = dir(filename);
|
||||
|
||||
% if it has not been found or if it is empty
|
||||
if ((isempty(dir_entry)) || (size(dir_entry,1) == 0) || ...
|
||||
(dir_entry.bytes <= 0))
|
||||
if (message_if_not_found)
|
||||
if (isempty(dir_entry))
|
||||
fprintf('%s not found',filename);
|
||||
else
|
||||
fprintf('%s found but of zero length',filename);
|
||||
end
|
||||
end
|
||||
% retry, if this has been specified
|
||||
if (retry_read_sleep_sec > 0.0)
|
||||
if (message_if_not_found)
|
||||
fprintf(', retrying\n');
|
||||
end
|
||||
% repeat until found or the specified number of repeats has been
|
||||
% exceeded (zero repeats means repeat endlessly)
|
||||
retry_read_ct = retry_read_max;
|
||||
while ((~file_non_empty) && ...
|
||||
((retry_read_max <= 0) || (retry_read_ct > 0)))
|
||||
fprintf('Pausing %d seconds and retrying \n',retry_read_sleep_sec);
|
||||
pause(retry_read_sleep_sec);
|
||||
dir_entry = dir(filename);
|
||||
if ((~isempty(dir_entry)) && (dir_entry.bytes > 0))
|
||||
file_non_empty = 1;
|
||||
% workaround option for various problems,
|
||||
% not for permanent use
|
||||
if (retry_sleep_when_found_sec > 0)
|
||||
pause(retry_sleep_when_found_sec);
|
||||
end
|
||||
end
|
||||
retry_read_ct = retry_read_ct -1;
|
||||
end
|
||||
else
|
||||
fprintf('\n');
|
||||
end
|
||||
else
|
||||
file_non_empty = 1;
|
||||
end
|
||||
|
||||
% open the file for read access
|
||||
if (file_non_empty)
|
||||
fid = fopen(filename,'r');
|
||||
else
|
||||
fid = -1;
|
||||
end
|
||||
|
||||
% exit with an error message, if this has been specified and if the file
|
||||
% could not be opened
|
||||
if (fid < 0)
|
||||
if (error_if_not_found)
|
||||
ME = MException('fopen_until_exists:not_found', ...
|
||||
strjoin({'File', filename, 'does not exist'}));
|
||||
throwAsCaller(ME);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,419 @@
|
||||
% [resolution FSC T freq n stat] = fourier_shell_corr_3D_2(img1,img2,param, varargin)
|
||||
% Computes the Fourier shell correlation between img1 and img2. It can also
|
||||
% compute the threshold function T. Images can be complex-valued.
|
||||
% Can handle non-cube arrays but assumes the voxel is isotropic
|
||||
%
|
||||
% Inputs:
|
||||
% **img1, img2 Compared images
|
||||
% **param Structure containing parameters
|
||||
% *optional*:
|
||||
% **dispfsc = 1; Display results
|
||||
% **SNRt = 0.5 Power SNR for threshold, popular options:
|
||||
% SNRt = 0.5; 1 bit threshold for average
|
||||
% SNRt = 0.2071; 1/2 bit threshold for average
|
||||
% **thickring Normally the pixels get assigned to the closest integer pixel ring in Fourier domain.
|
||||
% With thickring the thickness of the rings is increased by
|
||||
% thickring, so each ring gets more pixels and more statistics
|
||||
% **auto_thickring do not calculate overlaps if thickring > 1 is used
|
||||
% **st_title optional extra title in the plot
|
||||
% **freq_thr =0.05 mimimal freq value above which the resolution is detected
|
||||
% **show_fourier_corr show 2D Fourier correlation
|
||||
% **mask bool array equal to false for ignored pixels of the fft space
|
||||
%
|
||||
% returns:
|
||||
% ++resolution [min, max] resolution estimated from FSC curve
|
||||
% ++FSC FSC curve values
|
||||
% ++T Threshold values
|
||||
% ++freq spatial frequencies
|
||||
% ++stat stat - structure containing other statistics such as
|
||||
% SSNR, area under FSC curve. average SNR, ....
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 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 this copyright should be retained and the authors
|
||||
% and institution should be acknowledged in written form. Additionally
|
||||
% you should cite the publication most relevant for the implementation
|
||||
% of this code, namely
|
||||
% Vila-Comamala et al. "Characterization of high-resolution diffractive
|
||||
% X-ray optics by ptychographic coherent diffractive imaging," Opt.
|
||||
% Express 19, 21333-21344 (2011).
|
||||
%
|
||||
% Note however that the most relevant citation for the theoretical
|
||||
% foundation of the FSC criteria we use here is
|
||||
% M. van Heela, and M. Schatzb, "Fourier shell correlation threshold
|
||||
% criteria," Journal of Structural Biology 151, 250-262 (2005).
|
||||
%
|
||||
% 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 [resolution FSC T freq n stat] = fourier_shell_corr_3D_2(img1,img2,param, varargin)
|
||||
import math.isint
|
||||
import utils.*
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%% PROCESS PARAMETERS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
fsc_tic = tic;
|
||||
if nargin < 3
|
||||
param = struct();
|
||||
end
|
||||
|
||||
parser = inputParser;
|
||||
parser.addParameter('dispfsc', true , @islogical )
|
||||
parser.addParameter('dispsnr', false , @islogical ) % show also signal to noise ratio
|
||||
|
||||
parser.addParameter('SNRt', 0.5 , @isnumeric )% SNRt = 0.2071 for 1/2 bit threshold for average of 2 images
|
||||
% SNRt = 0.5 for 1 bit threshold for average of 2 images
|
||||
parser.addParameter('thickring', 0 , @isnumeric ) % thick ring in Fourier domain
|
||||
parser.addParameter('auto_binning', false , @islogical ) % bin FRC before calculating rings, it makes calculations faster
|
||||
parser.addParameter('max_rings', 200 , @isnumeric ) % maximal number of rings if autobinning is used
|
||||
parser.addParameter('st_title', '' , @isstring ) % optional extra title
|
||||
parser.addParameter('freq_thr', 0.05 , @isnumeric ) % mimimal freq value where resolution is detected
|
||||
parser.addParameter('show_2D_fourier_corr', false , @islogical ) % instead of rings, show rather 2D distribution of the Fourier correlation
|
||||
parser.addParameter('pixel_size', [] ) % size of pixel in meters
|
||||
parser.addParameter('mask', [], @(x)(isnumeric(x) || islogical(x)) ) % array, equal to 0 for ignored pixels of the fft space and 1 for rest
|
||||
parser.addParameter('windowautopos', true, @islogical ) % automatically position plotted window
|
||||
parser.addParameter('xlabel_type', 'nyquist', @(x)ismember(lower(x), {'nyquist', 'resolution'})) % select X axis units
|
||||
parser.addParameter('figure_id', 100, @isint) % call figure(figure_id)
|
||||
parser.addParameter('clear_figure', false, @islogical) % clear figure before plotting
|
||||
parser.addParameter('out_fn', [], @isstr) % saving path for the image
|
||||
parser.addParameter('show_summary', true, @islogical) % show summary at the end
|
||||
|
||||
parser.parse(varargin{:})
|
||||
r = parser.Results;
|
||||
|
||||
% load all to the param structure
|
||||
for name = fieldnames(r)'
|
||||
if ~isfield(param, name{1}) % prefer values in param structure
|
||||
param.(name{1}) = r.(name{1});
|
||||
end
|
||||
end
|
||||
|
||||
if isempty(param.pixel_size)
|
||||
warning('Pixel size not specified. Please use param.pixel_size. \n');
|
||||
param.pixel_size = nan;
|
||||
end
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% Create an example
|
||||
% A = 3;
|
||||
% img1 = rand(100,100,100);
|
||||
% img2 = img1 + A*rand(100,100,100);
|
||||
% img1 = img1 + A*rand(100,100,100);
|
||||
% dispfsc = 1;
|
||||
% SNRt = 1/A^2;
|
||||
|
||||
if any(size(img1) ~= size(img2))
|
||||
error('Images must be the same size')
|
||||
end
|
||||
|
||||
|
||||
[ny,nx,nz] = size(img1);
|
||||
nmin = min(size(img1));
|
||||
|
||||
|
||||
utils.verbose(2,'Calculating FSC');
|
||||
|
||||
% remove masked values from consideration (i.e. for laminography)
|
||||
F1 = fftn(img1);
|
||||
F2 = fftn(img2);
|
||||
if ~isempty( param.mask)
|
||||
F1 = bsxfun(@times,F1 , param.mask+eps);
|
||||
F2 = bsxfun(@times,F2 , param.mask+eps);
|
||||
end
|
||||
F1cF2 = F1 .* conj(F2);
|
||||
F1 = abs(F1).^2;
|
||||
F2 = abs(F2).^2;
|
||||
|
||||
[ny,nx,nz] = size(img1);
|
||||
nmin = min(size(img1));
|
||||
|
||||
thickring = param.thickring;
|
||||
|
||||
if param.auto_binning
|
||||
% bin the correlation values to speed up the following calculations
|
||||
% find optimal binning to make the volumes roughly cubic
|
||||
bin = ceil(thickring/4) * floor(size(img1)/ nmin);
|
||||
% avoid too large number of rings
|
||||
bin = max(bin, floor(nmin ./ param.max_rings));
|
||||
|
||||
if any(bin > 1)
|
||||
utils.verbose(1,'Autobinning %ix%ix%i', bin)
|
||||
thickring = ceil(thickring / min(bin));
|
||||
% fftshift and crop the arrays to make their size dividable by binning number
|
||||
if ismatrix(img1); bin(3) = 1; end
|
||||
% force the binning to be centered
|
||||
subgrid = {fftshift(ceil(bin(1)/2):(floor(ny/bin(1))*bin(1)-floor(bin(1)/2)-1)), ...
|
||||
fftshift(ceil(bin(2)/2):(floor(nx/bin(2))*bin(2)-floor(bin(2)/2)-1)), ...
|
||||
fftshift(ceil(bin(3)/2):(floor(nz/bin(3))*bin(3)-floor(bin(3)/2)-1))};
|
||||
if ismatrix(img1); subgrid(3) = [] ; end
|
||||
% binning makes the shell / ring calculations much faster
|
||||
F1 = ifftshift(utils.binning_3D(F1(subgrid{:}), bin));
|
||||
F2 = ifftshift(utils.binning_3D(F2(subgrid{:}), bin));
|
||||
F1cF2 = ifftshift(utils.binning_3D(F1cF2(subgrid{:}), bin));
|
||||
end
|
||||
else
|
||||
bin = 1;
|
||||
end
|
||||
|
||||
|
||||
[ny,nx,nz] = size(F1);
|
||||
nmax = max([nx ny nz]);
|
||||
nmin = min(size(img1));
|
||||
|
||||
|
||||
% empirically tested that thickring should be >=3 along the smallest axis to avoid FRC undesampling
|
||||
thickring = max(thickring, ceil(nmax/nmin));
|
||||
|
||||
param.thickring = thickring;
|
||||
|
||||
rnyquist = floor(nmax/2);
|
||||
freq = [0:rnyquist];
|
||||
|
||||
x = ifftshift([-fix(nx/2):ceil(nx/2)-1])*floor(nmax/2)/floor(nx/2);
|
||||
y = ifftshift([-fix(ny/2):ceil(ny/2)-1])*floor(nmax/2)/floor(ny/2);
|
||||
if nz ~= 1
|
||||
z = ifftshift([-fix(nz/2):ceil(nz/2)-1])*floor(nmax/2)/floor(nz/2);
|
||||
else
|
||||
z = 0;
|
||||
end
|
||||
|
||||
% deal with asymmetric pixel size in case of 2D FRC
|
||||
if length(param.pixel_size) == 2
|
||||
if param.pixel_size(1) > param.pixel_size(2)
|
||||
y = y .* param.pixel_size(2) / param.pixel_size(1);
|
||||
else
|
||||
x = x .* param.pixel_size(1) / param.pixel_size(2);
|
||||
end
|
||||
param.pixel_size = min(param.pixel_size); % FSC will be now calculated up to the maximal radius given by the smallest pixel size
|
||||
end
|
||||
|
||||
|
||||
[X,Y,Z] = meshgrid(single(x),single(y),single(z));
|
||||
index = (sqrt(X.^2+Y.^2+Z.^2));
|
||||
|
||||
clear X Y Z
|
||||
|
||||
|
||||
Nr = length(freq);
|
||||
for ii = 1:Nr
|
||||
r = freq(ii);
|
||||
if utils.verbose>2
|
||||
progressbar(ii,Nr)
|
||||
end
|
||||
% calculate always thickring, min ring thickness is given by the smallest axis
|
||||
ind = index>=r-thickring/2 & index<=r+thickring/2 ;
|
||||
ind = find(ind); % find seems to be faster then indexing
|
||||
auxF1 = F1(ind);
|
||||
auxF2 = F2(ind);
|
||||
auxF1cF2 = F1cF2(ind);
|
||||
C(ii) = sum(auxF1cF2);
|
||||
C1(ii) = sum(auxF1);
|
||||
C2(ii) = sum(auxF2);
|
||||
n(ii) = numel(ind); % Number of points
|
||||
end
|
||||
|
||||
|
||||
FSC = abs(C)./(sqrt(C1.*C2));
|
||||
n = n*prod(bin); % account for larger number of elements in the binned voxels
|
||||
|
||||
T = ( param.SNRt + 2*sqrt(param.SNRt)./sqrt(n+eps) + 1./sqrt(n) )./...
|
||||
( param.SNRt + 2*sqrt(param.SNRt)./sqrt(n+eps) + 1 );
|
||||
|
||||
freq_fine = 0:1e-3:max(freq);
|
||||
freq_fine_normal = freq_fine/max(freq);
|
||||
|
||||
FSC_fine = max(0,interpn(freq, FSC, freq_fine, 'spline')); % spline, linear
|
||||
T_fine = interpn(freq, T, freq_fine, 'spline');
|
||||
|
||||
|
||||
idx_intersect = abs(FSC_fine-T_fine)<2e-4;
|
||||
intersect_array = FSC_fine(idx_intersect);
|
||||
range = freq_fine_normal(idx_intersect);
|
||||
if length(range)<1
|
||||
range = [0 1];
|
||||
intersect_array = [1 1];
|
||||
end
|
||||
|
||||
|
||||
%%%%%% CALCULATE STATISTICS %%%%%%%%%%%%%%
|
||||
pixel_nm = param.pixel_size*1e9; % nm
|
||||
|
||||
|
||||
range_start = range(find(range>param.freq_thr, 1, 'first'));
|
||||
if isempty(range_start)
|
||||
range_start = range(1);
|
||||
end
|
||||
|
||||
resolution = [pixel_nm/range_start, pixel_nm/range(end)];
|
||||
fsc_mean_1nm = mean(FSC)/pixel_nm;
|
||||
|
||||
% calculate SNR: Huang, Xiaojing, et al. "Signal-to-noise and radiation exposure considerations in conventional and diffraction x-ray microscopy." Optics express 17.16 (2009): 13541-13553.
|
||||
SSNR = 2 * FSC ./ (1-FSC); % spectral signal to noise ratio
|
||||
SNR_avg = nansum(SSNR .* freq) / sum(freq); % average SNR (should correspond to signal^2 / noise^2 )
|
||||
|
||||
st_title_full = sprintf('%s \n Pixel size %.2f nm\n FSC: thickring %d, intersect (%.3f, %.3f) \n Resolution (%.2f, %.2f) nm \n Area under FSC = %.3f, <FSC(1nm)> = %.3f SNR_avg=%.3f', ...
|
||||
param.st_title, pixel_nm, param.thickring, range_start, range(end), pixel_nm/range_start, pixel_nm/range(end), mean(FSC), fsc_mean_1nm, SNR_avg);
|
||||
|
||||
if param.show_summary
|
||||
utils.verbose(1,['== FSC report: ==' st_title_full])
|
||||
end
|
||||
|
||||
stat.fsc_mean = mean(FSC);
|
||||
stat.fsc_mean_1nm = fsc_mean_1nm;% Area in inverse nm
|
||||
stat.SNR_avg = SNR_avg;
|
||||
stat.FSC = FSC;
|
||||
stat.threshold = T;
|
||||
|
||||
|
||||
%%%%% PLOT FOURIER SHELL CORRELATION %%%%%%%%%%%%%%%%%
|
||||
|
||||
if param.dispfsc
|
||||
fontsize = 12; % font size
|
||||
plotting.smart_figure(param.figure_id);
|
||||
if param.dispsnr
|
||||
subplot(1,2,1);
|
||||
end
|
||||
|
||||
if param.clear_figure; cla ; end
|
||||
hold all
|
||||
plot(freq/freq(end), FSC, '-','linewidth',2);
|
||||
plot(freq/freq(end), T, 'r','linewidth',2);
|
||||
plot(range, intersect_array, 'go','markersize',6,'MarkerFaceColor','none','linewidth',2);
|
||||
grid on
|
||||
axis([0 1 0 1]);
|
||||
hold off
|
||||
switch param.SNRt
|
||||
case 0.2071 , legend('FSC','1/2 bit threshold');
|
||||
case 0.5, legend('FSC','1 bit threshold');
|
||||
otherwise , legend('FSC',['Threshold SNR = ' num2str(param.SNRt)]);
|
||||
end
|
||||
|
||||
set(gca,'fontweight','bold','fontsize',fontsize,'xtick',[0:0.1:1],'ytick',[0:0.1:1]);
|
||||
|
||||
switch lower(param.xlabel_type)
|
||||
case 'nyquist'
|
||||
xlabel('Spatial frequency/Nyquist')
|
||||
case 'resolution'
|
||||
xaxis = [0:0.1:1];
|
||||
ticks = 1./xaxis* param.pixel_size*1e9;
|
||||
for i = 1:length(ticks)
|
||||
order = floor(log10(ticks(i)))-1;
|
||||
tick = round(ticks(i)/10^order)*10^order;
|
||||
if isnan(tick)
|
||||
tick = [];
|
||||
end
|
||||
XTickLabel{i} = tick;
|
||||
end
|
||||
set(gca,'XTickLabel',XTickLabel);
|
||||
xlabel(gca, ['Half-period resolution [nm]'])
|
||||
end
|
||||
if param.windowautopos
|
||||
win_size = [800 600];
|
||||
screensize = get( groot, 'Screensize' );
|
||||
set(gcf,'Outerposition',[100 min(270,screensize(4)-win_size(2)) win_size]); %[left, bottom, width, height]
|
||||
end
|
||||
ylabel('Fourier shell correlation')
|
||||
title(st_title_full,'interpreter','none')
|
||||
end
|
||||
|
||||
|
||||
|
||||
%%%%% PLOT SIGNAL TO NOISE RATIO %%%%%%%%%%%%%%%%%
|
||||
%% only approximation of SNR, dont use in publications
|
||||
if param.dispsnr
|
||||
fontsize = 12; % font size
|
||||
if param.dispfsc
|
||||
subplot(1,2,2);
|
||||
else
|
||||
figure(param.figure_id);
|
||||
end
|
||||
if param.clear_figure; cla ; end
|
||||
|
||||
hold all
|
||||
plot(freq/freq(end), SSNR, '-','linewidth',2);
|
||||
grid on
|
||||
xlim([0 1]);
|
||||
set(gca, 'yscale', 'log')
|
||||
hold off
|
||||
|
||||
|
||||
set(gca,'fontweight','bold','fontsize',fontsize,'xtick',[0:0.1:1]);
|
||||
|
||||
switch lower(param.xlabel_type)
|
||||
case 'nyquist'
|
||||
xlabel('Spatial frequency/Nyquist')
|
||||
case 'resolution'
|
||||
xaxis = [0:0.1:1];
|
||||
ticks = 1./xaxis* param.pixel_size*1e9;
|
||||
for i = 1:length(ticks)
|
||||
order = floor(log10(ticks(i)))-1;
|
||||
tick = round(ticks(i)/10^order)*10^order;
|
||||
if isnan(tick)
|
||||
tick = [];
|
||||
end
|
||||
XTickLabel{i} = tick;
|
||||
end
|
||||
set(gca,'XTickLabel',XTickLabel);
|
||||
xlabel(gca, ['Half-period resolution [nm]'])
|
||||
end
|
||||
ylabel('Spectral signal to noise ratio')
|
||||
if ~(param.dispfsc)
|
||||
title(st_title_full,'interpreter','none')
|
||||
end
|
||||
end
|
||||
|
||||
if ~isempty(param.out_fn)
|
||||
utils.verbose(1,'saving %s',param.out_fn);
|
||||
print('-djpeg','-r300',param.out_fn);
|
||||
end
|
||||
|
||||
|
||||
|
||||
if utils.verbose>2
|
||||
toc(fsc_tic)
|
||||
end
|
||||
|
||||
if param.show_2D_fourier_corr && nz == 1
|
||||
%% show 2D fourier correlation
|
||||
C = F1.*conj(F2);
|
||||
C1 = abs(F1).^2;
|
||||
C2 = abs(F2).^2;
|
||||
Nwin = 40;
|
||||
kernel = gausswin(Nwin, 3*nmax/ny) .* gausswin(Nwin, 3*nmax/nx)';
|
||||
C = conv2(fftshift(C),kernel,'same');
|
||||
C1 = conv2(fftshift(C1),kernel,'same');
|
||||
C2 = conv2(fftshift(C2),kernel,'same');
|
||||
|
||||
figure(323)
|
||||
imagesc(abs(C) ./ sqrt(C1 .* C2))
|
||||
axis off square
|
||||
colorbar
|
||||
title('2D fourier correlation')
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,415 @@
|
||||
% [resolution FSC T freq n stat] = fourier_shell_corr_3D_2e(img1,img2,param, varargin)
|
||||
% Computes the Fourier shell correlation between img1 and img2. It can also
|
||||
% compute the threshold function T. Images can be complex-valued.
|
||||
% Can handle non-cube arrays but assumes the voxel is isotropic
|
||||
% Modified by YJ for electron ptychography
|
||||
%
|
||||
% Inputs:
|
||||
% **img1, img2 Compared images
|
||||
% **param Structure containing parameters
|
||||
% *optional*:
|
||||
% **dispfsc = 1; Display results
|
||||
% **SNRt = 0.5 Power SNR for threshold, popular options:
|
||||
% SNRt = 0.5; 1 bit threshold for average
|
||||
% SNRt = 0.2071; 1/2 bit threshold for average
|
||||
% **thickring Normally the pixels get assigned to the closest integer pixel ring in Fourier domain.
|
||||
% With thickring the thickness of the rings is increased by
|
||||
% thickring, so each ring gets more pixels and more statistics
|
||||
% **auto_thickring do not calculate overlaps if thickring > 1 is used
|
||||
% **st_title optional extra title in the plot
|
||||
% **freq_thr =0.05 mimimal freq value above which the resolution is detected
|
||||
% **show_fourier_corr show 2D Fourier correlation
|
||||
% **mask bool array equal to false for ignored pixels of the fft space
|
||||
%
|
||||
% returns:
|
||||
% ++resolution [min, max] resolution estimated from FSC curve
|
||||
% ++FSC FSC curve values
|
||||
% ++T Threshold values
|
||||
% ++freq spatial frequencies
|
||||
% ++stat stat - structure containing other statistics such as
|
||||
% SSNR, area under FSC curve. average SNR, ....
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 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 this copyright should be retained and the authors
|
||||
% and institution should be acknowledged in written form. Additionally
|
||||
% you should cite the publication most relevant for the implementation
|
||||
% of this code, namely
|
||||
% Vila-Comamala et al. "Characterization of high-resolution diffractive
|
||||
% X-ray optics by ptychographic coherent diffractive imaging," Opt.
|
||||
% Express 19, 21333-21344 (2011).
|
||||
%
|
||||
% Note however that the most relevant citation for the theoretical
|
||||
% foundation of the FSC criteria we use here is
|
||||
% M. van Heela, and M. Schatzb, "Fourier shell correlation threshold
|
||||
% criteria," Journal of Structural Biology 151, 250-262 (2005).
|
||||
%
|
||||
% 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 [resolution FSC T freq n stat] = fourier_shell_corr_3D_2e(img1,img2,param, varargin)
|
||||
import math.isint
|
||||
import utils.*
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%% PROCESS PARAMETERS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
fsc_tic = tic;
|
||||
if nargin < 3
|
||||
param = struct();
|
||||
end
|
||||
|
||||
parser = inputParser;
|
||||
parser.addParameter('dispfsc', true , @islogical )
|
||||
parser.addParameter('dispsnr', false , @islogical ) % show also signal to noise ratio
|
||||
|
||||
parser.addParameter('SNRt', 0.5 , @isnumeric )% SNRt = 0.2071 for 1/2 bit threshold for average of 2 images
|
||||
% SNRt = 0.5 for 1 bit threshold for average of 2 images
|
||||
parser.addParameter('thickring', 0 , @isnumeric ) % thick ring in Fourier domain
|
||||
parser.addParameter('auto_binning', false , @islogical ) % bin FRC before calculating rings, it makes calculations faster
|
||||
parser.addParameter('max_rings', 200 , @isnumeric ) % maximal number of rings if autobinning is used
|
||||
parser.addParameter('st_title', '' , @isstring ) % optional extra title
|
||||
parser.addParameter('freq_thr', 0.05 , @isnumeric ) % mimimal freq value where resolution is detected
|
||||
parser.addParameter('show_2D_fourier_corr', false , @islogical ) % instead of rings, show rather 2D distribution of the Fourier correlation
|
||||
parser.addParameter('pixel_size', [] ) % size of pixel in angstrom
|
||||
parser.addParameter('mask', [], @(x)(isnumeric(x) || islogical(x)) ) % array, equal to 0 for ignored pixels of the fft space and 1 for rest
|
||||
parser.addParameter('windowautopos', true, @islogical ) % automatically position plotted window
|
||||
parser.addParameter('xlabel_type', 'nyquist', @(x)ismember(lower(x), {'nyquist', 'resolution'})) % select X axis units
|
||||
parser.addParameter('figure_id', 100, @isint) % call figure(figure_id)
|
||||
parser.addParameter('clear_figure', false, @islogical) % clear figure before plotting
|
||||
parser.addParameter('out_fn', [], @isstr) % saving path for the image
|
||||
parser.addParameter('show_summary', true, @islogical) % show summary at the end
|
||||
|
||||
parser.parse(varargin{:})
|
||||
r = parser.Results;
|
||||
|
||||
% load all to the param structure
|
||||
for name = fieldnames(r)'
|
||||
if ~isfield(param, name{1}) % prefer values in param structure
|
||||
param.(name{1}) = r.(name{1});
|
||||
end
|
||||
end
|
||||
|
||||
if isempty(param.pixel_size)
|
||||
warning('Pixel size not specified. Please use param.pixel_size. \n');
|
||||
param.pixel_size = nan;
|
||||
end
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% Create an example
|
||||
% A = 3;
|
||||
% img1 = rand(100,100,100);
|
||||
% img2 = img1 + A*rand(100,100,100);
|
||||
% img1 = img1 + A*rand(100,100,100);
|
||||
% dispfsc = 1;
|
||||
% SNRt = 1/A^2;
|
||||
|
||||
if any(size(img1) ~= size(img2))
|
||||
error('Images must be the same size')
|
||||
end
|
||||
|
||||
|
||||
[ny,nx,nz] = size(img1);
|
||||
nmin = min(size(img1));
|
||||
|
||||
|
||||
utils.verbose(2,'Calculating FSC');
|
||||
|
||||
% remove masked values from consideration (i.e. for laminography)
|
||||
F1 = fftn(img1);
|
||||
F2 = fftn(img2);
|
||||
if ~isempty( param.mask)
|
||||
F1 = bsxfun(@times,F1 , param.mask+eps);
|
||||
F2 = bsxfun(@times,F2 , param.mask+eps);
|
||||
end
|
||||
F1cF2 = F1 .* conj(F2);
|
||||
F1 = abs(F1).^2;
|
||||
F2 = abs(F2).^2;
|
||||
|
||||
[ny,nx,nz] = size(img1);
|
||||
nmin = min(size(img1));
|
||||
|
||||
thickring = param.thickring;
|
||||
|
||||
if param.auto_binning
|
||||
% bin the correlation values to speed up the following calculations
|
||||
% find optimal binning to make the volumes roughly cubic
|
||||
bin = ceil(thickring/4) * floor(size(img1)/ nmin);
|
||||
% avoid too large number of rings
|
||||
bin = max(bin, floor(nmin ./ param.max_rings));
|
||||
|
||||
if any(bin > 1)
|
||||
utils.verbose(1,'Autobinning %ix%ix%i', bin)
|
||||
thickring = ceil(thickring / min(bin));
|
||||
% fftshift and crop the arrays to make their size dividable by binning number
|
||||
if ismatrix(img1); bin(3) = 1; end
|
||||
% force the binning to be centered
|
||||
subgrid = {fftshift(ceil(bin(1)/2):(floor(ny/bin(1))*bin(1)-floor(bin(1)/2)-1)), ...
|
||||
fftshift(ceil(bin(2)/2):(floor(nx/bin(2))*bin(2)-floor(bin(2)/2)-1)), ...
|
||||
fftshift(ceil(bin(3)/2):(floor(nz/bin(3))*bin(3)-floor(bin(3)/2)-1))};
|
||||
if ismatrix(img1); subgrid(3) = [] ; end
|
||||
% binning makes the shell / ring calculations much faster
|
||||
F1 = ifftshift(utils.binning_3D(F1(subgrid{:}), bin));
|
||||
F2 = ifftshift(utils.binning_3D(F2(subgrid{:}), bin));
|
||||
F1cF2 = ifftshift(utils.binning_3D(F1cF2(subgrid{:}), bin));
|
||||
end
|
||||
else
|
||||
bin = 1;
|
||||
end
|
||||
|
||||
|
||||
[ny,nx,nz] = size(F1);
|
||||
nmax = max([nx ny nz]);
|
||||
nmin = min(size(img1));
|
||||
|
||||
|
||||
% empirically tested that thickring should be >=3 along the smallest axis to avoid FRC undesampling
|
||||
thickring = max(thickring, ceil(nmax/nmin));
|
||||
|
||||
param.thickring = thickring;
|
||||
|
||||
rnyquist = floor(nmax/2);
|
||||
freq = [0:rnyquist];
|
||||
|
||||
x = ifftshift([-fix(nx/2):ceil(nx/2)-1])*floor(nmax/2)/floor(nx/2);
|
||||
y = ifftshift([-fix(ny/2):ceil(ny/2)-1])*floor(nmax/2)/floor(ny/2);
|
||||
if nz ~= 1
|
||||
z = ifftshift([-fix(nz/2):ceil(nz/2)-1])*floor(nmax/2)/floor(nz/2);
|
||||
else
|
||||
z = 0;
|
||||
end
|
||||
|
||||
% deal with asymmetric pixel size in case of 2D FRC
|
||||
if length(param.pixel_size) == 2
|
||||
if param.pixel_size(1) > param.pixel_size(2)
|
||||
y = y .* param.pixel_size(2) / param.pixel_size(1);
|
||||
else
|
||||
x = x .* param.pixel_size(1) / param.pixel_size(2);
|
||||
end
|
||||
param.pixel_size = min(param.pixel_size); % FSC will be now calculated up to the maximal radius given by the smallest pixel size
|
||||
end
|
||||
|
||||
|
||||
[X,Y,Z] = meshgrid(single(x),single(y),single(z));
|
||||
index = (sqrt(X.^2+Y.^2+Z.^2));
|
||||
|
||||
clear X Y Z
|
||||
|
||||
|
||||
Nr = length(freq);
|
||||
for ii = 1:Nr
|
||||
r = freq(ii);
|
||||
if utils.verbose>2
|
||||
progressbar(ii,Nr)
|
||||
end
|
||||
% calculate always thickring, min ring thickness is given by the smallest axis
|
||||
ind = index>=r-thickring/2 & index<=r+thickring/2 ;
|
||||
ind = find(ind); % find seems to be faster then indexing
|
||||
auxF1 = F1(ind);
|
||||
auxF2 = F2(ind);
|
||||
auxF1cF2 = F1cF2(ind);
|
||||
C(ii) = sum(auxF1cF2);
|
||||
C1(ii) = sum(auxF1);
|
||||
C2(ii) = sum(auxF2);
|
||||
n(ii) = numel(ind); % Number of points
|
||||
end
|
||||
|
||||
|
||||
FSC = abs(C)./(sqrt(C1.*C2));
|
||||
n = n*prod(bin); % account for larger number of elements in the binned voxels
|
||||
|
||||
T = ( param.SNRt + 2*sqrt(param.SNRt)./sqrt(n+eps) + 1./sqrt(n) )./...
|
||||
( param.SNRt + 2*sqrt(param.SNRt)./sqrt(n+eps) + 1 );
|
||||
|
||||
freq_fine = 0:1e-3:max(freq);
|
||||
freq_fine_normal = freq_fine/max(freq);
|
||||
|
||||
FSC_fine = max(0,interpn(freq, FSC, freq_fine, 'spline')); % spline, linear
|
||||
T_fine = interpn(freq, T, freq_fine, 'spline');
|
||||
|
||||
|
||||
idx_intersect = abs(FSC_fine-T_fine)<2e-4;
|
||||
intersect_array = FSC_fine(idx_intersect);
|
||||
range = freq_fine_normal(idx_intersect);
|
||||
if length(range)<1
|
||||
range = [0 1];
|
||||
intersect_array = [1 1];
|
||||
end
|
||||
|
||||
|
||||
%%%%%% CALCULATE STATISTICS %%%%%%%%%%%%%%
|
||||
pixel = param.pixel_size; % angstrom
|
||||
|
||||
|
||||
range_start = range(find(range>param.freq_thr, 1, 'first'));
|
||||
if isempty(range_start)
|
||||
range_start = range(1);
|
||||
end
|
||||
|
||||
resolution = [pixel/range_start, pixel/range(end)];
|
||||
fsc_mean = mean(FSC)/pixel;
|
||||
|
||||
% calculate SNR: Huang, Xiaojing, et al. "Signal-to-noise and radiation exposure considerations in conventional and diffraction x-ray microscopy." Optics express 17.16 (2009): 13541-13553.
|
||||
SSNR = 2 * FSC ./ (1-FSC); % spectral signal to noise ratio
|
||||
SNR_avg = nansum(SSNR .* freq) / sum(freq); % average SNR (should correspond to signal^2 / noise^2 )
|
||||
|
||||
st_title_full = sprintf('%s \n Pixel size %.3f A\n FSC: thickring %d, intersect (%.3f, %.3f) \n Resolution (%.3f, %.3f) A \n Area under FSC = %.3f, <FSC(A)> = %.3f SNR_avg=%.3f', ...
|
||||
param.st_title, pixel, param.thickring, range_start, range(end), pixel/range_start, pixel/range(end), mean(FSC), fsc_mean, SNR_avg);
|
||||
|
||||
if param.show_summary
|
||||
utils.verbose(1,['== FSC report: ==' st_title_full])
|
||||
end
|
||||
|
||||
stat.fsc_mean = mean(FSC);
|
||||
stat.fsc_mean_1A = fsc_mean;% Area in inverse angstrom
|
||||
stat.SNR_avg = SNR_avg;
|
||||
stat.FSC = FSC;
|
||||
stat.threshold = T;
|
||||
|
||||
|
||||
%%%%% PLOT FOURIER SHELL CORRELATION %%%%%%%%%%%%%%%%%
|
||||
|
||||
if param.dispfsc
|
||||
fontsize = 12; % font size
|
||||
plotting.smart_figure(param.figure_id);
|
||||
if param.dispsnr
|
||||
subplot(1,2,1);
|
||||
end
|
||||
|
||||
if param.clear_figure; cla ; end
|
||||
hold all
|
||||
plot(freq/freq(end), FSC, '-','linewidth',2);
|
||||
plot(freq/freq(end), T, 'r','linewidth',2);
|
||||
plot(range, intersect_array, 'go','markersize',6,'MarkerFaceColor','none','linewidth',2);
|
||||
grid on
|
||||
axis([0 1 0 1]);
|
||||
hold off
|
||||
switch param.SNRt
|
||||
case 0.2071 , legend('FSC','1/2 bit threshold');
|
||||
case 0.5, legend('FSC','1 bit threshold');
|
||||
otherwise , legend('FSC',['Threshold SNR = ' num2str(param.SNRt)]);
|
||||
end
|
||||
|
||||
set(gca,'fontweight','bold','fontsize',fontsize,'xtick',[0:0.1:1],'ytick',[0:0.1:1]);
|
||||
|
||||
switch lower(param.xlabel_type)
|
||||
case 'nyquist'
|
||||
xlabel('Spatial frequency/Nyquist')
|
||||
case 'resolution'
|
||||
xaxis = [0:0.1:1];
|
||||
ticks = 1./xaxis* param.pixel_size;
|
||||
for i = 1:length(ticks)
|
||||
order = floor(log10(ticks(i)))-1;
|
||||
tick = round(ticks(i)/10^order)*10^order;
|
||||
if isnan(tick)
|
||||
tick = [];
|
||||
end
|
||||
XTickLabel{i} = tick;
|
||||
end
|
||||
set(gca,'XTickLabel',XTickLabel);
|
||||
xlabel(gca, ['Half-period resolution [A]'])
|
||||
end
|
||||
if param.windowautopos
|
||||
win_size = [800 600];
|
||||
screensize = get( groot, 'Screensize' );
|
||||
set(gcf,'Outerposition',[100 min(270,screensize(4)-win_size(2)) win_size]); %[left, bottom, width, height]
|
||||
end
|
||||
ylabel('Fourier shell correlation')
|
||||
title(st_title_full,'interpreter','none')
|
||||
end
|
||||
|
||||
|
||||
|
||||
%%%%% PLOT SIGNAL TO NOISE RATIO %%%%%%%%%%%%%%%%%
|
||||
%% only approximation of SNR, dont use in publications
|
||||
if param.dispsnr
|
||||
fontsize = 12; % font size
|
||||
if param.dispfsc
|
||||
subplot(1,2,2);
|
||||
else
|
||||
figure(param.figure_id);
|
||||
end
|
||||
if param.clear_figure; cla ; end
|
||||
|
||||
hold all
|
||||
plot(freq/freq(end), SSNR, '-','linewidth',2);
|
||||
grid on
|
||||
xlim([0 1]);
|
||||
set(gca, 'yscale', 'log')
|
||||
hold off
|
||||
|
||||
set(gca,'fontweight','bold','fontsize',fontsize,'xtick',[0:0.1:1]);
|
||||
|
||||
switch lower(param.xlabel_type)
|
||||
case 'nyquist'
|
||||
xlabel('Spatial frequency/Nyquist')
|
||||
case 'resolution'
|
||||
xaxis = [0:0.1:1];
|
||||
ticks = 1./xaxis* param.pixel_size;
|
||||
for i = 1:length(ticks)
|
||||
order = floor(log10(ticks(i)))-1;
|
||||
tick = round(ticks(i)/10^order)*10^order;
|
||||
if isnan(tick)
|
||||
tick = [];
|
||||
end
|
||||
XTickLabel{i} = tick;
|
||||
end
|
||||
set(gca,'XTickLabel',XTickLabel);
|
||||
xlabel(gca, ['Half-period resolution [A]'])
|
||||
end
|
||||
ylabel('Spectral signal to noise ratio')
|
||||
if ~(param.dispfsc)
|
||||
title(st_title_full,'interpreter','none')
|
||||
end
|
||||
end
|
||||
|
||||
if ~isempty(param.out_fn)
|
||||
utils.verbose(1,'saving %s',param.out_fn);
|
||||
print('-djpeg','-r300',param.out_fn);
|
||||
end
|
||||
|
||||
if utils.verbose>2
|
||||
toc(fsc_tic)
|
||||
end
|
||||
|
||||
if param.show_2D_fourier_corr && nz == 1
|
||||
%% show 2D fourier correlation
|
||||
C = F1.*conj(F2);
|
||||
C1 = abs(F1).^2;
|
||||
C2 = abs(F2).^2;
|
||||
Nwin = 40;
|
||||
kernel = gausswin(Nwin, 3*nmax/ny) .* gausswin(Nwin, 3*nmax/nx)';
|
||||
C = conv2(fftshift(C),kernel,'same');
|
||||
C1 = conv2(fftshift(C1),kernel,'same');
|
||||
C2 = conv2(fftshift(C2),kernel,'same');
|
||||
|
||||
figure(323)
|
||||
imagesc(abs(C) ./ sqrt(C1 .* C2))
|
||||
axis off square
|
||||
colorbar
|
||||
title('2D fourier correlation')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
% fract_hanning(outputdim,unmodsize)
|
||||
% out = Square array containing a fractional separable Hanning window with
|
||||
% DC in upper left corner.
|
||||
% outputdim = size of the output array
|
||||
% unmodsize = Size of the central array containing no modulation.
|
||||
% Creates a square hanning window if unmodsize = 0 (or ommited), otherwise the output array
|
||||
% will contain an array of ones in the center and cosine modulation on the
|
||||
% edges, the array of ones will have DC in upper left corner.
|
||||
|
||||
% February 8, 2007
|
||||
|
||||
% Slight update on August 17, 2009
|
||||
% Added a warning
|
||||
|
||||
% Copyright (c) 2016, Manuel Guizar Sicairos, James R. Fienup, University of Rochester
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
% * Neither the name of the University of Rochester nor the names
|
||||
% of its contributors may be used to endorse or promote products derived
|
||||
% from this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function out = fract_hanning(outputdim,unmodsize);
|
||||
|
||||
if nargin > 2,
|
||||
error('Too many input arguments'),
|
||||
elseif nargin == 1,
|
||||
unmodsize = 0;
|
||||
end
|
||||
|
||||
if outputdim < unmodsize,
|
||||
error('Output dimension must be smaller or equal to size of unmodulated window'),
|
||||
end
|
||||
|
||||
if unmodsize<0,
|
||||
unmodsize = 0;
|
||||
warning('Specified unmodsize<0, setting unmodsize = 0')
|
||||
end
|
||||
|
||||
N = [0:outputdim-1];
|
||||
% N = ifftshift([-floor(outputdim/2):ceil(outputdim/2)-1]);
|
||||
% N = [-floor(outputdim/2):ceil(outputdim/2)-1];
|
||||
[Nc,Nr] = meshgrid(N,N);
|
||||
|
||||
if unmodsize == 0,
|
||||
out = (1+cos(2*pi*Nc/outputdim)).*(1+cos(2*pi*Nr/outputdim))/4;
|
||||
else
|
||||
% Columns modulation
|
||||
out = (1+cos(2*pi*(Nc- floor((unmodsize-1)/2) )/(outputdim+1-unmodsize)))/2;
|
||||
if floor((unmodsize-1)/2)>0,
|
||||
out(:,1:floor((unmodsize-1)/2)) = 1;
|
||||
end
|
||||
out(:,floor((unmodsize-1)/2) + outputdim+3-unmodsize:length(N)) = 1;
|
||||
% Row modulation
|
||||
out2 = (1+cos(2*pi*(Nr- floor((unmodsize-1)/2) )/(outputdim+1-unmodsize)))/2;
|
||||
if floor((unmodsize-1)/2)>0,
|
||||
out2(1:floor((unmodsize-1)/2),:) = 1;
|
||||
end
|
||||
out2(floor((unmodsize-1)/2) + outputdim+3-unmodsize:length(N),:) = 1;
|
||||
|
||||
out = out.*out2;
|
||||
end
|
||||
% out = ifftshift(out);
|
||||
% one-edge at Nc = floor((unmodsize-1)/2)
|
||||
% other-edge at Nc = floor((unmodsize-1)/2) + (outputdim+1-unmodsize)
|
||||
%%% FINISH UP THIS CODE TO DO THE LOW PASS RECONSTRUCTION
|
||||
|
||||
return;
|
||||
@@ -0,0 +1,70 @@
|
||||
% fract_hanning_pad(outputdim,filterdim,unmodsize)
|
||||
% out = Square array containing a fractional separable Hanning window with
|
||||
% DC in upper left corner.
|
||||
% outputdim = size of the output array
|
||||
% filterdim = size of filter (it will zero pad if filterdim<outputdim
|
||||
% unmodsize = Size of the central array containing no modulation.
|
||||
% Creates a square hanning window if unmodsize = 0 (or ommited), otherwise the output array
|
||||
% will contain an array of ones in the center and cosine modulation on the
|
||||
% edges, the array of ones will have DC in upper left corner.
|
||||
|
||||
% August 17, 2009
|
||||
|
||||
% Copyright (c) 2016, Manuel Guizar Sicairos, University of Rochester
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
% * Neither the name of the University of Rochester nor the names
|
||||
% of its contributors may be used to endorse or promote products derived
|
||||
% from this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function out = fract_hanning_pad(outputdim,filterdim,unmodsize);
|
||||
import utils.fract_hanning
|
||||
|
||||
if nargin > 3,
|
||||
error('Too many input arguments'),
|
||||
elseif nargin == 1,
|
||||
unmodsize = 0;
|
||||
filterdim = outputdim;
|
||||
end
|
||||
|
||||
if outputdim < unmodsize,
|
||||
error('Output dimension must be smaller or equal to size of unmodulated window'),
|
||||
end
|
||||
|
||||
if outputdim < filterdim,
|
||||
error('Filter cannot be larger than output size'),
|
||||
end
|
||||
|
||||
if unmodsize<0,
|
||||
unmodsize = 0;
|
||||
warning('Specified unmodsize<0, setting unmodsize = 0')
|
||||
end
|
||||
|
||||
out = zeros(outputdim);
|
||||
out(round(outputdim/2+1-filterdim/2):round(outputdim/2+1+filterdim/2-1),...
|
||||
round(outputdim/2+1-filterdim/2):round(outputdim/2+1+filterdim/2-1)) ...
|
||||
= fftshift(fract_hanning(filterdim,unmodsize));
|
||||
out = fftshift(out);
|
||||
|
||||
return;
|
||||
@@ -0,0 +1,34 @@
|
||||
% GET_APODIZATION_MASK calculate a 2D circular mask fot smoothing tomogram
|
||||
%
|
||||
% [circulo] = get_apodization_mask(tomogram, rad_apod, axial_apod, radial_smooth)
|
||||
%
|
||||
% Inputs:
|
||||
% **tomogram - volume to be apodized
|
||||
% **rad_apod - number of pixels to be zeroed from edge of the tomogram
|
||||
% **radial_smooth - smoothness of the apodization in pixels, default = Npix/10
|
||||
% **layer_dim
|
||||
% Outputs:
|
||||
% ++circulo -apodization mask
|
||||
% Written BY YJ based on apply_3D_apodization.m
|
||||
|
||||
function [circulo] = get_apodization_mask(Npix, rad_apod, radial_smooth )
|
||||
import utils.*
|
||||
Npix_y = Npix(1);
|
||||
Npix_x = Npix(2);
|
||||
|
||||
Npix = max(Npix_y,Npix_x);
|
||||
if nargin < 3
|
||||
radial_smooth = Npix/10;
|
||||
end
|
||||
|
||||
if ~isempty(rad_apod)
|
||||
xt = -Npix/2:Npix/2-1;
|
||||
[X,Y] = meshgrid(xt,xt);
|
||||
radial_smooth = max(radial_smooth,1); % prevent division by zero
|
||||
circulo= single(1-radtap(X,Y,radial_smooth,round(Npix/2-rad_apod-radial_smooth)));
|
||||
%size(X)
|
||||
if Npix_y~=Npix_x
|
||||
circulo= crop_pad( circulo, [Npix_y,Npix_x]);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,157 @@
|
||||
% GET_ATT_LENGTH returns attenuation length of a material for a given energy (range)
|
||||
% formula... chemical formula
|
||||
% energy... single value in keV or energy range in keV
|
||||
% (optional) dens... density, negative number for default values
|
||||
% (optional) ang... grazing angle (default 90)
|
||||
% (optional) npts... number of points
|
||||
% (optional) plot... set to 1 for plotting
|
||||
%
|
||||
% returns
|
||||
% att... (energy in keV, transmission)
|
||||
% req_density... density in g/cm^3
|
||||
%
|
||||
% examples:
|
||||
% get_att_length('Au', 8.7, -1, 45)
|
||||
% get_att_length('Pb', [11.2 24], 0.1, -1, 100)
|
||||
%
|
||||
% 03/2017
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ att, req_density ] = get_att_length( formula, energy, varargin )
|
||||
|
||||
% check density
|
||||
if nargin < 3
|
||||
dens = -1;
|
||||
else
|
||||
dens = varargin{1};
|
||||
end
|
||||
|
||||
% check angle
|
||||
if nargin < 4
|
||||
ang = 90;
|
||||
else
|
||||
ang = varargin{2};
|
||||
end
|
||||
|
||||
% check specified number of points
|
||||
if nargin < 5
|
||||
npts = 99;
|
||||
else
|
||||
npts = varargin{3}-1;
|
||||
end
|
||||
|
||||
% check if plotting is requested
|
||||
if nargin < 6
|
||||
plot_att = false;
|
||||
else
|
||||
plot_att = varargin{4};
|
||||
end
|
||||
|
||||
|
||||
% convert to keV
|
||||
energy = energy * 1000;
|
||||
|
||||
if size(energy) ==1
|
||||
emin = energy-1;
|
||||
emax = energy+1;
|
||||
npts = 2;
|
||||
req_range = false;
|
||||
elseif size(energy,2) == 2
|
||||
emin = energy(1);
|
||||
emax = energy(2);
|
||||
req_range = true;
|
||||
else
|
||||
error('Only one specific energy or an energy range is supported.')
|
||||
|
||||
end
|
||||
|
||||
% check the energy range
|
||||
if emin < 30 || emax > 30000
|
||||
error('Energies must be in the range 0.03 keV to 30 keV.')
|
||||
end
|
||||
|
||||
% request the data
|
||||
server = 'http://henke.lbl.gov/';
|
||||
req = sprintf('Material=Enter+Formula&Formula=%s&Density=%f&Scan=Energy&Min=%d&Max=%d&Npts=%d&Fixed=%f&Plot=Log&Output=Plot', formula, dens, emin, emax, npts, ang);
|
||||
data_req = webwrite('http://henke.lbl.gov/cgi-bin/atten.pl', req);
|
||||
|
||||
% find and read dat file
|
||||
f_pos = strfind(data_req, '/tmp');
|
||||
data_req = strsplit(data_req(f_pos(1):end), '.');
|
||||
data = webread([server data_req{1} '.dat']);
|
||||
|
||||
% split data by line breaks
|
||||
data = strsplit(data, '\n');
|
||||
|
||||
% extract density
|
||||
req_density = data{1};
|
||||
req_density = strsplit(req_density, '=');
|
||||
req_density = strsplit(req_density{2}, ' ');
|
||||
req_density = str2double(req_density{1});
|
||||
|
||||
|
||||
% output
|
||||
if npts==2 && ~req_range
|
||||
att = zeros(1,2);
|
||||
req_att = data{4};
|
||||
req_att = strsplit(req_att,' ');
|
||||
att(1,1) = str2double(req_att{2})/1000;
|
||||
att(1,2) = str2double(req_att{3});
|
||||
else
|
||||
att = zeros(npts+1,2);
|
||||
for i=1:npts+1
|
||||
req_att = data{i+2};
|
||||
req_att = strsplit(req_att,' ');
|
||||
att(i,1) = str2double(req_att{2})/1000;
|
||||
att(i,2) = str2double(req_att{3});
|
||||
end
|
||||
end
|
||||
|
||||
% plot attenuation
|
||||
if plot_att
|
||||
if ~req_range
|
||||
fprintf('Requested plot for a single point.')
|
||||
end
|
||||
figure(76);
|
||||
plot(att(:,1), att(:,2))
|
||||
ylabel('attenuation length')
|
||||
xlabel('energy in keV')
|
||||
grid on;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
% Call function without arguments for a detailed explanation of its use
|
||||
|
||||
% Filename: $RCSfile: get_beam_center.m,v $
|
||||
%
|
||||
% $Revision: 1.4 $ $Date: 2011/04/07 17:57:03 $
|
||||
% $Author: $
|
||||
% $Tag: $
|
||||
%
|
||||
% Description:
|
||||
% try to find the center of a radially symmetric SAXS pattern
|
||||
%
|
||||
% Note:
|
||||
% Call without arguments for a brief help text.
|
||||
%
|
||||
% Dependencies:
|
||||
% - image_read
|
||||
% - prep_integ_masks
|
||||
%
|
||||
% history:
|
||||
%
|
||||
% May 9th 2008: 1st documented version
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ center_xy ] = get_beam_center(filename,varargin)
|
||||
import io.image_read
|
||||
|
||||
% set default values for the variable input arguments:
|
||||
% beam center guess
|
||||
guess_x = 512;
|
||||
guess_y = 512;
|
||||
% +/- test range in pixels around the good guess
|
||||
test_x = 3;
|
||||
test_y = 3;
|
||||
% angular beam-stop region to exclude
|
||||
bs_angle_from = 0;
|
||||
bs_angle_to = 0;
|
||||
% integration range
|
||||
r_from = 50;
|
||||
r_step = 1;
|
||||
r_to = 60;
|
||||
% figure number for display
|
||||
fig_no = 230;
|
||||
% directory and filename with the valid pixel mask
|
||||
filename_valid_mask = '~/Data10/analysis/data/pilatus_valid_mask.mat';
|
||||
parallel_tasks_max = 256;
|
||||
|
||||
% check minimum number of input arguments
|
||||
if (nargin < 1)
|
||||
fprintf('Usage:\n');
|
||||
fprintf('[center_xy]=%s(filename [[,<name>,<value>] ...]);\n',mfilename)
|
||||
fprintf('The optional <name>,<value> pairs are:\n');
|
||||
fprintf('''GuessX'',<integer> good guess for the beam center in x\n');
|
||||
fprintf('''GuessY'',<integer> good guess for the beam center in y\n');
|
||||
fprintf('''TestX'',<integer> check +/- this many pixel around the good guess, default in x is %d\n',...
|
||||
test_x);
|
||||
fprintf('''TestY'',<integer> check +/- this many pixel around the good guess, default in y is %d\n',...
|
||||
test_y);
|
||||
fprintf('''BeamstopAngleFrom'',<float> exclude an angular region from the integration, default for the start value is %d\n',...
|
||||
bs_angle_from);
|
||||
fprintf('''BeamstopAngleTo'',<float> exclude an angular region from the integration, default for the end value is %d\n',...
|
||||
bs_angle_to);
|
||||
fprintf('''RadiusFrom'',<integer> radial integration start radius, default is %d\n',r_from);
|
||||
fprintf('''RadiusStep'',<integer> radial integration step size, default is %d\n',r_step);
|
||||
fprintf('''RadiusFrom'',<integer> radial integration end radius, default is %d\n',r_to);
|
||||
fprintf('''FilenameValidMask'',<path and filename> Matlab file with the valid pixel indices ind_valid,\n');
|
||||
fprintf(' default is %s\n',filename_valid_mask);
|
||||
fprintf('''FigNo'',<integer> number of the figure in which the result is displayed\n');
|
||||
fprintf('''ParTasksMax'',<integer> specify the maximum number of CPU cores to use, 1 to deactivate the use of parallel computing, default is %d\n',parallel_tasks_max);
|
||||
fprintf('\n');
|
||||
fprintf('Extending the test region will slow down the processing in an unbearable amount.\n');
|
||||
fprintf('Therefore the good guess should be really good and the test area kept at its default value.\n');
|
||||
fprintf('\n');
|
||||
fprintf('Example:\n');
|
||||
fprintf('[cen]=%s(''~/Data10/pilatus/image_silver_behenate_10sec.cbf'',''GuessX'',512,''GuessY'',512,''RadiusFrom'',50,''RadiusTo'',60);\n',...
|
||||
mfilename);
|
||||
error('At least the filename has to be specified as input parameter.');
|
||||
end
|
||||
|
||||
|
||||
% accept cell array with name/value pairs as well
|
||||
no_of_in_arg = nargin;
|
||||
if (nargin == 2)
|
||||
if (isempty(varargin))
|
||||
% ignore empty cell array
|
||||
no_of_in_arg = no_of_in_arg -1;
|
||||
else
|
||||
if (iscell(varargin{1}))
|
||||
% use a filled one given as first and only variable parameter
|
||||
varargin = varargin{1};
|
||||
no_of_in_arg = 1 + length(varargin);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% check number of input arguments
|
||||
if (rem(no_of_in_arg,2) ~= 1)
|
||||
error('The optional parameters have to be specified as ''name'',''value'' pairs');
|
||||
end
|
||||
|
||||
|
||||
% parse the variable input arguments
|
||||
vararg_remain = cell(0,0);
|
||||
for ind = 1:2:length(varargin)
|
||||
name = varargin{ind};
|
||||
value = varargin{ind+1};
|
||||
switch name
|
||||
case 'GuessX'
|
||||
guess_x = round(value);
|
||||
case 'GuessY'
|
||||
guess_y = round(value);
|
||||
case 'TestX'
|
||||
test_x = value;
|
||||
case 'TestY'
|
||||
test_y = value;
|
||||
case 'BeamstopAngleFrom'
|
||||
bs_angle_from = value;
|
||||
case 'BeamstopAngleTo'
|
||||
bs_angle_to = value;
|
||||
case 'RadiusFrom'
|
||||
r_from = value;
|
||||
case 'RadiusStep'
|
||||
r_step = value;
|
||||
case 'RadiusTo'
|
||||
r_to = value;
|
||||
case 'FilenameValidMask'
|
||||
filename_valid_mask = value;
|
||||
case 'FigNo'
|
||||
fig_no = value;
|
||||
case 'ParTasksMax'
|
||||
parallel_tasks_max = value;
|
||||
otherwise
|
||||
vararg_remain{end+1} = name; %#ok<AGROW>
|
||||
vararg_remain{end+1} = value; %#ok<AGROW>
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% load the calibration image
|
||||
fprintf('loading %s\n',filename);
|
||||
frame = image_read(filename,vararg_remain);
|
||||
|
||||
% plot the calibration image
|
||||
figure(fig_no);
|
||||
hold off;
|
||||
clf;
|
||||
frame_plot = double(frame.data(:,:,1));
|
||||
frame_plot(frame_plot < 1) = 1;
|
||||
% mark the good guess for the beam center
|
||||
frame_plot(guess_y,(guess_x-20):(guess_x+20)) = 1e6;
|
||||
frame_plot((guess_y-20):(guess_y+20),guess_x) = 1e6;
|
||||
imagesc(log10(frame_plot));
|
||||
axis xy;
|
||||
axis equal;
|
||||
axis tight
|
||||
colorbar;
|
||||
title([ 'beam center guess marked at (' num2str(guess_x,'%.0f') ...
|
||||
',' num2str(guess_y,'%.0f') ')' ]);
|
||||
set(gcf,'Name','beam center guess');
|
||||
drawnow;
|
||||
|
||||
% calculate the standard deviation along the integration circles for all
|
||||
% beam centers within the test range
|
||||
y = (guess_y-test_y):(guess_y+test_y);
|
||||
x = (guess_x-test_x):(guess_x+test_x);
|
||||
ind_x_max = length(x);
|
||||
ind_y_max = length(y);
|
||||
ind_total = ind_x_max * ind_y_max;
|
||||
std_val = zeros(ind_y_max,ind_x_max);
|
||||
arg_prep_integ_masks = cell(1,length(vararg_remain)+12);
|
||||
% arg_prep_integ_masks{ 1} = 'RadiusFrom';
|
||||
% arg_prep_integ_masks{ 2} = r_from;
|
||||
% arg_prep_integ_masks{ 3} = 'RadiusTo';
|
||||
% arg_prep_integ_masks{ 4} = r_to;
|
||||
% arg_prep_integ_masks{ 5} = 'RadiusStep';
|
||||
% arg_prep_integ_masks{ 6} = r_step;
|
||||
arg_prep_integ_masks{ 1} = 'NoOfRadii';
|
||||
arg_prep_integ_masks{ 2} = [r_from:r_step:r_to];
|
||||
arg_prep_integ_masks{ 3} = 'SaveData';
|
||||
arg_prep_integ_masks{ 4} = 0;
|
||||
arg_prep_integ_masks{ 5} = 'FilenameValidMask';
|
||||
arg_prep_integ_masks{6} = filename_valid_mask;
|
||||
arg_prep_integ_masks{7} = 'DisplayValidMask';
|
||||
arg_prep_integ_masks{8} = 0;
|
||||
arg_prep_integ_masks{9} = 'BeamstopAngleFrom';
|
||||
arg_prep_integ_masks{10} = bs_angle_from;
|
||||
arg_prep_integ_masks{11} = 'BeamstopAngleTo';
|
||||
arg_prep_integ_masks{12} = bs_angle_to;
|
||||
arg_prep_integ_masks(13:end) = vararg_remain;
|
||||
|
||||
% initialize parallel processing if this is enabled and not yet done
|
||||
if (parallel_tasks_max > 1)
|
||||
pool = gcp('nocreate');
|
||||
if isempty(pool) %MGS2015 If there is no current pool
|
||||
% create a scheduler object using the default configuration, which is a
|
||||
% local scheduler if nothing else has been installed
|
||||
scheduler = parcluster; %MGS2015
|
||||
|
||||
% adapt maximum number of tasks/workers, if necessary
|
||||
%cluster_size = get(scheduler,'ClusterSize');
|
||||
cluster_size = scheduler.NumWorkers; %MGS2015
|
||||
if (parallel_tasks_max > cluster_size)
|
||||
fprintf('Adapting the maximum number of tasks from %d to %d.\n',...
|
||||
parallel_tasks_max, cluster_size);
|
||||
parallel_tasks_max = cluster_size;
|
||||
end
|
||||
|
||||
% open a Matlab pool for simple parallel processing
|
||||
if (parallel_tasks_max > 1)
|
||||
%matlabpool('open',parallel_tasks_max);%MGS2015
|
||||
parpool(parallel_tasks_max);
|
||||
fprintf('Using parallel processing with %d tasks.\n', ...
|
||||
parallel_tasks_max);
|
||||
end
|
||||
else
|
||||
if (pool.NumWorkers < parallel_tasks_max)
|
||||
fprintf('%s: usage of up to %d CPUs in parallel has been specified but an already open matlabpool with %d workers has been found and will be used instead\n', ...
|
||||
mfilename, parallel_tasks_max, pool.NumWorkers);
|
||||
parallel_tasks_max = pool.NumWorkers;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% integrate the specified detector frame for each beam-center position and
|
||||
% calculate the standard deviation along the specified ring
|
||||
if (parallel_tasks_max > 1)
|
||||
% simple parallelization using parfor rather than for
|
||||
parfor (ind_y = 1:ind_y_max)
|
||||
std_val(ind_y,:) = integrate_one(ind_y,ind_x_max,ind_total,x,y,filename,arg_prep_integ_masks,frame);
|
||||
end
|
||||
else
|
||||
for (ind_y = 1:ind_y_max)
|
||||
std_val(ind_y,:) = integrate_one(ind_y,ind_x_max,ind_total,x,y,filename,arg_prep_integ_masks,frame);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% find the beam center of minimum standard deviation
|
||||
[min_y ind_y] = min(std_val);
|
||||
[min_x ind_x] = min(min_y);
|
||||
ind_y = ind_y(ind_x);
|
||||
cen_x_coarse = x(ind_x);
|
||||
cen_y_coarse = y(ind_y);
|
||||
|
||||
% interpolate center within three pixels
|
||||
cen_x = cen_x_coarse;
|
||||
if ((ind_x > 1) && (ind_x < size(std_val,2)))
|
||||
denom = std_val(ind_y, ind_x +1) - 2*std_val(ind_y,ind_x) + ...
|
||||
std_val(ind_y,ind_x -1);
|
||||
if (abs(denom) > 1e-6)
|
||||
cen_x = cen_x + 0.5 - ...
|
||||
(std_val(ind_y,ind_x+1)-std_val(ind_y,ind_x)) / denom;
|
||||
end
|
||||
end
|
||||
|
||||
cen_y = cen_y_coarse;
|
||||
if ((ind_y > 1) && (ind_y < size(std_val,1)))
|
||||
denom = std_val(ind_y +1, ind_x) - 2*std_val(ind_y,ind_x) + ...
|
||||
std_val(ind_y -1,ind_x);
|
||||
if (abs(denom) > 1e-6)
|
||||
cen_y = cen_y + 0.5 - ...
|
||||
(std_val(ind_y+1,ind_x)-std_val(ind_y,ind_x)) / denom;
|
||||
end
|
||||
end
|
||||
|
||||
% compile return argument
|
||||
center_xy = [ cen_x cen_y ];
|
||||
|
||||
% display the result
|
||||
fprintf('Minimum standard deviation position interpolated to (%.3f,%.3f)\n',...
|
||||
cen_x,cen_y);
|
||||
|
||||
% plot the standard deviation as a function of tested pixel coordinates
|
||||
figure(fig_no +1);
|
||||
surf(x,y,std_val);
|
||||
colorbar;
|
||||
title( ['standard deviation of the radial integration, center = (' ...
|
||||
num2str(cen_x,'%.1f') ', ' num2str(cen_y,'%.1f') ')' ] );
|
||||
xlabel('x [ pixel ]');
|
||||
ylabel('y [ pixel ]');
|
||||
set(gcf,'Name','standard deviation');
|
||||
|
||||
|
||||
% integrate the specified detector frame for each beam-center position and
|
||||
% calculate the standard deviation along the specified ring
|
||||
function [std_val] = integrate_one(ind_y,ind_x_max,ind_total,x,y,filename,arg_prep_integ_masks,frame)
|
||||
import beamline.prep_integ_masks
|
||||
std_val = zeros(1,ind_x_max);
|
||||
for (ind_x = 1:ind_x_max)
|
||||
fprintf('%3d / %3d\n',(ind_y-1)*ind_x_max + ind_x,ind_total);
|
||||
[ integ_masks ] = ...
|
||||
prep_integ_masks( filename, [x(ind_x) y(ind_y)], ...
|
||||
arg_prep_integ_masks);
|
||||
|
||||
ind_r_max = length(integ_masks.radius);
|
||||
|
||||
% sum standard deviation over circle segments
|
||||
norm_by = 0;
|
||||
for (ind_r = 1:ind_r_max)
|
||||
if (integ_masks.norm_sum(ind_r,1) > 0)
|
||||
std_val(ind_x) = std_val(ind_x) + ...
|
||||
std(double(frame.data(integ_masks.indices{ind_r,1}))) / ...
|
||||
integ_masks.norm_sum(ind_r,1);
|
||||
norm_by = norm_by +1;
|
||||
end
|
||||
end
|
||||
if (norm_by > 0)
|
||||
std_val(ind_x) = std_val(ind_x) / norm_by;
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,151 @@
|
||||
% GET_FIL_TRANS returns transmission of a solid for a given energy (range)
|
||||
% formula... chemical formula
|
||||
% energy... single value in keV or energy range in keV
|
||||
% thickness... thickness in micron
|
||||
% (optional) dens... density, negative number for default values
|
||||
% (optional) npts... number of points
|
||||
% (optional) plot... set to 1 for plotting
|
||||
%
|
||||
% returns
|
||||
% trans... (energy in keV, transmission)
|
||||
% req_density... density in g/cm^3
|
||||
%
|
||||
% examples:
|
||||
% get_fil_trans('Au', 8.7, 2)
|
||||
% get_fil_trans('Pb', [11.2 24], 0.1, -1, 100)
|
||||
%
|
||||
% 03/2017
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ trans, req_density ] = get_fil_trans( formula, energy, thickness, varargin )
|
||||
|
||||
% check density
|
||||
if nargin < 4
|
||||
dens = -1;
|
||||
else
|
||||
dens = varargin{1};
|
||||
end
|
||||
|
||||
% check specified number of points
|
||||
if nargin < 5
|
||||
npts = 99;
|
||||
else
|
||||
npts = varargin{2}-1;
|
||||
end
|
||||
|
||||
% check if plotting is requested
|
||||
if nargin < 6
|
||||
plot_trans = false;
|
||||
else
|
||||
plot_trans = varargin{3};
|
||||
end
|
||||
|
||||
|
||||
% convert to keV
|
||||
energy = energy * 1000;
|
||||
|
||||
if size(energy) ==1
|
||||
emin = energy-1;
|
||||
emax = energy+1;
|
||||
npts = 2;
|
||||
req_range = false;
|
||||
elseif size(energy,2) == 2
|
||||
emin = energy(1);
|
||||
emax = energy(2);
|
||||
req_range = true;
|
||||
else
|
||||
error('Only one specific energy or an energy range is supported.')
|
||||
|
||||
end
|
||||
|
||||
% check the energy range
|
||||
if emin < 30 || emax > 30000
|
||||
error('Energies must be in the range 0.03 keV to 30 keV.')
|
||||
end
|
||||
|
||||
% request the data
|
||||
server = 'http://henke.lbl.gov/';
|
||||
req = sprintf('Material=Enter+Formula&Formula=%s&Density=%f&Thickness=%f&Scan=Energy&Min=%d&Max=%d&Npts=%d&Plot=Linear&Output=Plot', formula, dens, thickness, emin, emax, npts);
|
||||
data_req = webwrite('http://henke.lbl.gov/cgi-bin/filter.pl', req);
|
||||
|
||||
% find and read dat file
|
||||
f_pos = strfind(data_req, '/tmp');
|
||||
data_req = strsplit(data_req(f_pos(1):end), '.');
|
||||
data = webread([server data_req{1} '.dat']);
|
||||
|
||||
% split data by line breaks
|
||||
data = strsplit(data, '\n');
|
||||
|
||||
% extract density
|
||||
req_density = data{1};
|
||||
req_density = strsplit(req_density, '=');
|
||||
req_density = strsplit(req_density{2}, ' ');
|
||||
req_density = str2double(req_density{1});
|
||||
|
||||
%keyboard
|
||||
|
||||
% output
|
||||
if npts==2 && ~req_range
|
||||
trans = zeros(1,2);
|
||||
req_trans = data{4};
|
||||
req_trans = strsplit(req_trans,' ');
|
||||
trans(1,1) = str2double(req_trans{2})/1000;
|
||||
trans(1,2) = str2double(req_trans{3});
|
||||
else
|
||||
trans = zeros(npts+1,2);
|
||||
for i=1:npts+1
|
||||
req_trans = data{i+2};
|
||||
req_trans = strsplit(req_trans,' ');
|
||||
trans(i,1) = str2double(req_trans{2})/1000;
|
||||
trans(i,2) = str2double(req_trans{3});
|
||||
end
|
||||
end
|
||||
|
||||
% plot transmission
|
||||
if plot_trans
|
||||
if ~req_range
|
||||
fprintf('Requested plot for a single point.')
|
||||
end
|
||||
figure(76);
|
||||
plot(trans(:,1), trans(:,2))
|
||||
ylabel('transmission')
|
||||
xlabel('energy in keV')
|
||||
grid on;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
% GET_FROM_3D_PROJECTION add one small 3D block into large 3D array
|
||||
%
|
||||
% small_array = get_from_3D_projection(small_array,full_array, positions_offset, indices)
|
||||
%
|
||||
% Inputs:
|
||||
% **full_array - array from which the small_array will loaded
|
||||
% **small_array - empty array for storing the data
|
||||
% **positions_offset - [Nangles x 2] offset from (1,1) coordinate in pixels
|
||||
% for each slice , if provide only [1x2] vector, assume the same
|
||||
% offset for each slice
|
||||
% **indices - add only to selected sliced of the full_array
|
||||
% *optional*
|
||||
% **use_MEX - (use_MEX==true) use fast mex code
|
||||
% *returns*
|
||||
% ++small_array or none, results were writted !directly! to the input
|
||||
% array small_array, there is not need to take any output if MEX
|
||||
% function add_to_3D_projection was used
|
||||
%
|
||||
% Compilation from Matlab:
|
||||
% mex -R2018a 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" get_from_3D_projection_mex.cpp
|
||||
% Usage from Matlab:
|
||||
%
|
||||
% full_array = (randn(1000, 1000, 1, 'single'));
|
||||
% small_array = (ones(500, 500, 100, 'single'));
|
||||
%
|
||||
% positions_offset = int32([1:100; 1:100])';
|
||||
% indices = int32([1:100]); % indices are starting from 1 !!
|
||||
% tic; get_from_3D_projection_mex(small_array,full_array,positions_offset,indices); toc
|
||||
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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
|
||||
%
|
||||
|
||||
|
||||
|
||||
function small_array = get_from_3D_projection(small_array, full_array, positions_offset, indices, use_MEX)
|
||||
|
||||
Np_f = size(full_array);
|
||||
Np_s = size(small_array);
|
||||
|
||||
if nargin < 4
|
||||
indices = 1:Np_f(3);
|
||||
end
|
||||
if nargin < 5
|
||||
use_MEX = true;
|
||||
end
|
||||
if size(positions_offset,1)==1
|
||||
positions_offset = repmat(positions_offset, size(small_array,3), 1);
|
||||
end
|
||||
positions_offset = int32(positions_offset);
|
||||
indices= int32(indices);
|
||||
|
||||
if use_MEX && ~isa(full_array, 'gpuArray') && ~verLessThan('matlab', '9.4') && ~islogical(small_array) % logical arrays not yet implemented
|
||||
%% run fast MEX-based code if possible
|
||||
try
|
||||
get_from_3D_projection_mex(small_array,full_array, positions_offset, indices)
|
||||
catch err
|
||||
% recompile the scripts if needed
|
||||
if any(strcmp(err.identifier, { 'MATLAB:UndefinedFunction','MATLAB:mex:ErrInvalidMEXFile'}))
|
||||
utils.verbose(0, 'Recompilation of MEX functions ... ')
|
||||
path = replace(mfilename('fullpath'), mfilename, '');
|
||||
mex('-R2018a','-O', 'CFLAGS="\$CFLAGS -fopenmp"', '-O','LDFLAGS="\$LDFLAGS -fopenmp"',[path,'private/get_from_3D_projection_mex.cpp'], '-output', [path, 'private/get_from_3D_projection_mex'])
|
||||
get_from_3D_projection_mex(small_array,full_array, positions_offset, indices)
|
||||
else
|
||||
rethrow(err)
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
%% simple matlab based version that may be too slow
|
||||
for ii = 1:size(positions_offset,1)
|
||||
jj = min(indices(ii),size(full_array,3));
|
||||
for i = 1:2
|
||||
% limit to the region inside full_array
|
||||
ind_f{i} = positions_offset(ii,i)+int32(1:Np_s(i));
|
||||
ind_f{i} = max(1,1+positions_offset(ii,i)):min(positions_offset(ii,i)+Np_s(i),Np_f(i));
|
||||
% adjust size of the small matrix to correspond
|
||||
ind_s{i} = ((ind_f{i}(1)-positions_offset(ii,i))):(ind_f{i}(end)-positions_offset(ii,i));
|
||||
end
|
||||
small_array(ind_s{:},ii) = full_array(ind_f{:},jj) ;
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,170 @@
|
||||
% GET_GAS_TRANS returns transmission of a solid for a given energy (range)
|
||||
% formula... chemical formula
|
||||
% energy... single value in keV or energy range in keV
|
||||
% thickness... thickness in cm
|
||||
% (optional) press... pressure in Torr (default 30)
|
||||
% (optional) tempr... temperature in Kelvin (default 295)
|
||||
% (optional) npts... number of points
|
||||
% (optional) plot... set to 1 for plotting
|
||||
%
|
||||
% returns
|
||||
% trans... (energy in keV, transmission)
|
||||
% req_press... pressure
|
||||
%
|
||||
% examples:
|
||||
% get_gas_trans('Air', 8.7, 2)
|
||||
% get_gas_trans('CO2', [11.2 24], 20, 30, 100)
|
||||
%
|
||||
% 03/2017
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ trans, req_press ] = get_gas_trans( formula, energy, thickness, varargin )
|
||||
|
||||
% check pressure
|
||||
if nargin < 4
|
||||
press = 30;
|
||||
else
|
||||
press = varargin{1};
|
||||
end
|
||||
|
||||
% check temperature
|
||||
if nargin < 5
|
||||
tempr = 295;
|
||||
else
|
||||
tempr = varargin{2};
|
||||
end
|
||||
|
||||
% check specified number of points
|
||||
if nargin < 6
|
||||
npts = 99;
|
||||
else
|
||||
npts = varargin{3}-1;
|
||||
end
|
||||
|
||||
% check if plotting is requested
|
||||
if nargin < 7
|
||||
plot_trans = false;
|
||||
else
|
||||
plot_trans = varargin{4};
|
||||
end
|
||||
|
||||
% default compounds
|
||||
switch lower(formula)
|
||||
case lower('Air')
|
||||
formula = 'N1.562O.42C.0003Ar.0094';
|
||||
case lower('Methane')
|
||||
formula = 'C1H4';
|
||||
case lower('P-10')
|
||||
formula = 'Ar.9C.1H.4';
|
||||
case lower('Propane')
|
||||
formula = 'C3H8';
|
||||
end
|
||||
|
||||
% convert to keV
|
||||
energy = energy * 1000;
|
||||
|
||||
if size(energy) ==1
|
||||
emin = energy-1;
|
||||
emax = energy+1;
|
||||
npts = 2;
|
||||
req_range = false;
|
||||
elseif size(energy,2) == 2
|
||||
emin = energy(1);
|
||||
emax = energy(2);
|
||||
req_range = true;
|
||||
else
|
||||
error('Only one specific energy or an energy range is supported.')
|
||||
|
||||
end
|
||||
|
||||
% check the energy range
|
||||
if emin < 30 || emax > 30000
|
||||
error('Energies must be in the range 0.03 keV to 30 keV.')
|
||||
end
|
||||
|
||||
% request the data
|
||||
server = 'http://henke.lbl.gov/';
|
||||
req = sprintf('Material=Enter+Formula&Formula=%s&Press=%f&Temp=%f&Path=%f&Scan=Energy&Min=%d&Max=%d&Npts=%d&Plot=Linear&Output=Plot', formula, press, tempr, thickness, emin, emax, npts);
|
||||
data_req = webwrite('http://henke.lbl.gov/cgi-bin/gastrn.pl', req);
|
||||
|
||||
% find and read dat file
|
||||
f_pos = strfind(data_req, '/tmp');
|
||||
data_req = strsplit(data_req(f_pos(1):end), '.');
|
||||
data = webread([server data_req{1} '.dat']);
|
||||
|
||||
% split data by line breaks
|
||||
data = strsplit(data, '\n');
|
||||
|
||||
% extract density
|
||||
req_press = data{1};
|
||||
req_press = strsplit(req_press, '=');
|
||||
req_press = strsplit(req_press{2}, ' ');
|
||||
req_press = str2double(req_press{1});
|
||||
|
||||
%keyboard
|
||||
|
||||
% output
|
||||
if npts==2 && ~req_range
|
||||
trans = zeros(1,2);
|
||||
req_trans = data{4};
|
||||
req_trans = strsplit(req_trans,' ');
|
||||
trans(1,1) = str2double(req_trans{2})/1000;
|
||||
trans(1,2) = str2double(req_trans{3});
|
||||
else
|
||||
trans = zeros(npts+1,2);
|
||||
for i=1:npts+1
|
||||
req_trans = data{i+2};
|
||||
req_trans = strsplit(req_trans,' ');
|
||||
trans(i,1) = str2double(req_trans{2})/1000;
|
||||
trans(i,2) = str2double(req_trans{3});
|
||||
end
|
||||
end
|
||||
|
||||
% plot transmission
|
||||
if plot_trans
|
||||
if ~req_range
|
||||
fprintf('Requested plot for a single point.')
|
||||
end
|
||||
figure(76);
|
||||
plot(trans(:,1), trans(:,2))
|
||||
ylabel('transmission')
|
||||
xlabel('energy in keV')
|
||||
grid on;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
% get_grid returns coordinate system for input shape ish and pixel size px
|
||||
%
|
||||
% Example:
|
||||
% [g1,g2] = get_grid(512, 29e-9);
|
||||
% returns an fft-shifted coordinate system of size 512x512 with a pixel size of 29 nm
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [gx,gy] = get_grid(ish, px)
|
||||
|
||||
if length(ish) == 1
|
||||
sh = [ish ish];
|
||||
elseif length(ish) == 2
|
||||
sh = ish;
|
||||
else
|
||||
error('Input shape has to be 1D or 2D')
|
||||
end
|
||||
|
||||
if length(px) == 1
|
||||
dx = [px px];
|
||||
elseif length(ish) ==2
|
||||
dx = px;
|
||||
else
|
||||
error('Pixel size has to be 1D or 2D')
|
||||
end
|
||||
|
||||
x = fftshift(-sh(2)/2:floor((sh(2)-1)/2))*dx(2);
|
||||
y = fftshift(-sh(1)/2:floor((sh(1)-1)/2))*dx(1);
|
||||
|
||||
[gx,gy] = meshgrid(x,y);
|
||||
|
||||
end
|
||||
@@ -0,0 +1,120 @@
|
||||
% Call function without arguments for instructions on how to use it
|
||||
|
||||
% Filename: $RCSfile: get_hdr_val.m,v $
|
||||
%
|
||||
% $Revision: 1.3 $ $Date: 2008/08/28 18:47:31 $
|
||||
% $Author: $
|
||||
% $Tag: $
|
||||
%
|
||||
% Description:
|
||||
% Find text signature in a bunch of cell strings from a file header and
|
||||
% return the following value in the specified format. Example:
|
||||
% no_of_bin_bytes = get_hdr_val(header,'X-Binary-Size:','%f',1);
|
||||
% The last parameter specifies whether the macro should exit with an error
|
||||
% message if the text signature has not been found.
|
||||
%
|
||||
% Note:
|
||||
% Call without arguments for a brief help text.
|
||||
%
|
||||
% Dependencies:
|
||||
% none
|
||||
%
|
||||
%
|
||||
% history:
|
||||
%
|
||||
% May 7th 2008:
|
||||
% add number of input argument check and brief help text
|
||||
%
|
||||
% April 25th 2008: 1st version
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [outval,line_number,err] = get_hdr_val(header,signature,format,...
|
||||
exit_if_not_found)
|
||||
|
||||
% initialize output arguments
|
||||
outval = 0;
|
||||
line_number = 0;
|
||||
err = 0;
|
||||
|
||||
if (nargin ~= 4)
|
||||
fprintf('Usage:\n');
|
||||
fprintf('[value,line_number,error]=%s(header,signature,format,exit_if_not_found);\n',...
|
||||
mfilename);
|
||||
fprintf('header cell array with text lines as returned by cbfread or ebfread\n');
|
||||
fprintf('signature string to be searched for in the header\n');
|
||||
fprintf('format printf-like format specifier for the interpretation of the value that follows the signature\n');
|
||||
fprintf('exit_if_not_found exit with an error in case either the signature or the value have not been found\n');
|
||||
error('Wrong number of input arguments.\n');
|
||||
end
|
||||
|
||||
% search for the signature string
|
||||
pos_found = strfind(header,signature);
|
||||
|
||||
% for sscanf the percentage sign has a special meaning
|
||||
signature_sscanf = strrep(signature,'%','%%');
|
||||
|
||||
% loop over the search results for all header lines
|
||||
for (ind=1:length(pos_found))
|
||||
% if the signature string has been found in this line
|
||||
if (length(pos_found{ind}) > 0)
|
||||
% get the following value in the specified format
|
||||
[outval,count] = sscanf(header{ind}(pos_found{ind}:end),...
|
||||
[signature_sscanf format]);
|
||||
% return an error if the signature and value combination has not
|
||||
% been found (i.e., the format specification did not match)
|
||||
if (count < 1)
|
||||
outval = 0;
|
||||
err = 1;
|
||||
else
|
||||
% return the first occurrence if more than one has been found
|
||||
if (count > 1)
|
||||
outval = outval(1);
|
||||
end
|
||||
% return the line number
|
||||
line_number = ind;
|
||||
return;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% no occurrence found
|
||||
err = 1;
|
||||
if (exit_if_not_found)
|
||||
error(['no header line with signature ''' signature ''' and format ' ...
|
||||
format ' found']);
|
||||
end
|
||||
|
||||
return;
|
||||
@@ -0,0 +1,123 @@
|
||||
% GET_INTEGRATION_MATRIX Generate sparse integration matrix that sums up
|
||||
% values according to the provided integration mask
|
||||
%
|
||||
%
|
||||
% int_matrix = get_integration_matrix(mask)
|
||||
%
|
||||
% Inputs:
|
||||
% **mask - 2D integer array, 0 = ignored regions, 1:max(mask) are different sectors that will be summed separatelly
|
||||
% Outputs:
|
||||
% ++int_matrix - 2D sparse matrix
|
||||
%
|
||||
%
|
||||
%%%%%%%%%%%%%%%%%%%%% HOW TO USE %%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% % create some data
|
||||
% img = single(imread('cameraman.tif'));
|
||||
% img = repmat(img, 1,1,10); % just add there 3rd dimension
|
||||
% Np = size(img);
|
||||
%
|
||||
% %% define parameters of the integration matrix
|
||||
% Nrad = 20;
|
||||
% Nsec = 30;
|
||||
% center_pos = Np/2-30;
|
||||
%
|
||||
%
|
||||
% %% generate radial and sector masks, needs to be modified if center != Np/2
|
||||
% [mask, radial_mask, sector_mask] = get_radial_integration_mask(Np, Nrad, Nsec, center_pos);
|
||||
%
|
||||
% %% check the generated sector mask
|
||||
% figure(1)
|
||||
% imagesc(mask); axis off image
|
||||
% title('Radial & Angular sectors')
|
||||
% colormap(hsv)
|
||||
% drawnow
|
||||
%
|
||||
% % generate the integration 2D sparse matrix
|
||||
% T = get_integration_matrix(mask);
|
||||
%
|
||||
%
|
||||
% %% perform sparse matrix based integration
|
||||
% tic
|
||||
% img_sum = single(reshape((T*reshape(double(img), prod(Np(1:2)), [])), Nrad,Nsec, []));
|
||||
% toc
|
||||
%
|
||||
% %% perform matlab based integration for comparison
|
||||
% tic
|
||||
% img_sum_0 = zeros(Nrad,Nsec, size(img,3));
|
||||
% for nz = 1:size(img,3)
|
||||
% im = img(:,:,nz);
|
||||
% for i = 1:Nrad
|
||||
% m = radial_mask == i;
|
||||
% for j = 1:Nsec
|
||||
% img_sum_0(i,j,nz) = sum(im( m & sector_mask == j ));
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
% toc
|
||||
%
|
||||
%
|
||||
% % show the first frame to check that the methods are identical
|
||||
% figure
|
||||
% subplot(1,2,1)
|
||||
% imagesc(img_sum_0(:,:,1)); axis image
|
||||
% title('Matlab')
|
||||
% subplot(1,2,2)
|
||||
% imagesc(img_sum(:,:,1)); axis image
|
||||
% title('Sparse matrix')
|
||||
|
||||
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 int_matrix = get_integration_matrix(mask)
|
||||
N = max(mask(:));
|
||||
Np = size(mask);
|
||||
int_matrix = zeros(prod(Np),2);
|
||||
ind_start = 1;
|
||||
for id = 1 : max(mask(:))
|
||||
[i,j] = find(mask == id);
|
||||
ind_end = ind_start + length(i)-1;
|
||||
int_matrix(ind_start:ind_end,:) = [id*ones(length(i),1),i+(j-1)*Np(1)];
|
||||
ind_start = ind_end + 1;
|
||||
end
|
||||
% convert to sparse matrix
|
||||
int_matrix = sparse(int_matrix(1:ind_end,1),int_matrix(1:ind_end,2),ones(ind_end,1), N, prod(Np));
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
% bool = get_option(p, option_name, default)
|
||||
% return option value if option exists and is not empty or false, otherwise
|
||||
% return default
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 bool = get_option(p, option_name, default)
|
||||
|
||||
if nargin > 2
|
||||
bool = default;
|
||||
else
|
||||
bool = false;
|
||||
end
|
||||
if isfield(p, option_name)
|
||||
val = p.(option_name);
|
||||
if isempty(val)
|
||||
bool = false;
|
||||
elseif (isnumeric(val) || islogical(val)) && isscalar(val) && val == false
|
||||
bool = false;
|
||||
else
|
||||
bool = p.(option_name);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,106 @@
|
||||
% GET_RADIAL_INTEGRATION_MASK create 2D integer array that serves as a
|
||||
% template for get_integration_matrix for radial integration
|
||||
%
|
||||
%
|
||||
% [radial_integration_mask, radial_mask, sector_mask] = get_radial_integration_mask(Np, Nrad, Nsec, center_pos)
|
||||
%
|
||||
% Inputs:
|
||||
% **Np - size of the integrated frames
|
||||
% **Nrad - number of radial rings
|
||||
% **Nsec - number of angular sectors
|
||||
% **center_pos - position of center in pixels, e.g. Np/2 for well centered dataset
|
||||
% Outputs:
|
||||
% ++radial_integration_mask - 2D integer array integration mask
|
||||
% ++radial_mask - 2D integer array integration mask of only radial rings
|
||||
% ++sector_mask - 2D integer array integration mask of only angular sectors
|
||||
%
|
||||
%
|
||||
%%%%%%%%%%%%%%%%%%%%% HOW TO USE %%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% % create some data
|
||||
% img = single(imread('cameraman.tif'));
|
||||
% img = repmat(img, 1,1,10); % just add there 3rd dimension
|
||||
% Np = size(img);
|
||||
%
|
||||
% %% define parameters of the integration matrix
|
||||
% Nrad = 20;
|
||||
% Nsec = 30;
|
||||
% center_pos = Np/2-30;
|
||||
%
|
||||
%
|
||||
% %% generate radial and sector masks, needs to be modified if center != Np/2
|
||||
% [mask, radial_mask, sector_mask] = get_radial_integration_mask(Np, Nrad, Nsec, center_pos);
|
||||
%
|
||||
% %% check the generated sector mask
|
||||
% figure(1)
|
||||
% imagesc(mask); axis off image
|
||||
% title('Radial & Angular sectors')
|
||||
% colormap(hsv)
|
||||
% drawnow
|
||||
%
|
||||
% % generate the integration 2D sparse matrix
|
||||
% T = get_integration_matrix(mask);
|
||||
%
|
||||
%
|
||||
% %% perform sparse matrix based integration
|
||||
% tic
|
||||
% img_sum = single(reshape((T*reshape(double(img), prod(Np(1:2)), [])), Nrad,Nsec, []));
|
||||
% toc
|
||||
%
|
||||
% %% perform matlab based integration for comparison
|
||||
% tic
|
||||
% img_sum_0 = zeros(Nrad,Nsec, size(img,3));
|
||||
% for nz = 1:size(img,3)
|
||||
% im = img(:,:,nz);
|
||||
% for i = 1:Nrad
|
||||
% m = radial_mask == i;
|
||||
% for j = 1:Nsec
|
||||
% img_sum_0(i,j,nz) = sum(im( m & sector_mask == j ));
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
% toc
|
||||
%
|
||||
%
|
||||
% % show the first frame to check that the methods are identical
|
||||
% figure
|
||||
% subplot(1,2,1)
|
||||
% imagesc(img_sum_0(:,:,1)); axis image
|
||||
% title('Matlab')
|
||||
% subplot(1,2,2)
|
||||
% imagesc(img_sum(:,:,1)); axis image
|
||||
% title('Sparse matrix')
|
||||
|
||||
|
||||
|
||||
function [radial_integration_mask, radial_mask, sector_mask] = get_radial_integration_mask(Np, Nrad, Nsec, center_pos)
|
||||
% generate 2D integration masks - radial + sectors
|
||||
|
||||
offset = center_pos - Np/2;
|
||||
xgrid = (-floor(Np(2)/2)+1:floor(Np(2)/2))+offset(2);
|
||||
ygrid = (-floor(Np(1)/2)+1:floor(Np(1)/2))+offset(1);
|
||||
|
||||
[X,Y] = meshgrid(xgrid, ygrid);
|
||||
R = sqrt(X.^2 + Y.^2);
|
||||
Phi = atan2(X,Y);
|
||||
|
||||
% calculate array corresponding to rings
|
||||
r_all = linspace(0, max(Np(1:2))/2, Nrad+1);
|
||||
radial_mask = zeros(Np(1:2));
|
||||
for i = 1:Nrad
|
||||
radial_mask(R >= r_all(i) & R < r_all(i+1)) = i;
|
||||
end
|
||||
|
||||
% calculate array corresponding to sectors
|
||||
sec_all = linspace(-pi,pi,Nsec+1);
|
||||
sector_mask = zeros(Np(1:2));
|
||||
for i = 1:Nsec
|
||||
sector_mask(Phi >= sec_all(i) & Phi < sec_all(i+1)) = i;
|
||||
end
|
||||
|
||||
|
||||
% generate joined integration mask
|
||||
radial_integration_mask = double(radial_mask + (sector_mask-1) .* Nrad);
|
||||
radial_integration_mask(radial_mask ==0 | sector_mask == 0) = 0;
|
||||
|
||||
end
|
||||
@@ -0,0 +1,154 @@
|
||||
% GET_REF_INDEX returns refractive index for the specified chemical formula at a given energy (range)
|
||||
% formula... chemical formula
|
||||
% energy... single value in keV or energy range in keV
|
||||
% (optional) dens... density, negative number for default value
|
||||
% (optional) npts... number of points
|
||||
% (optional) plot... set to 1 for plotting the refractive index
|
||||
%
|
||||
% returns
|
||||
% ref... (energy in keV, delta, beta)
|
||||
% req_density... density in g/cm^3
|
||||
%
|
||||
% examples:
|
||||
% get_ref_index('Au', 8.7)
|
||||
% get_ref_index('Pb', [11.2 24], -1, 100)
|
||||
%
|
||||
% 03/2017
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ ref, req_density ] = get_ref_index( formula, energy, varargin )
|
||||
|
||||
% check density
|
||||
if nargin < 3
|
||||
dens = -1;
|
||||
else
|
||||
dens = varargin{1};
|
||||
end
|
||||
|
||||
% check specified number of points
|
||||
if nargin < 4
|
||||
npts = 99;
|
||||
else
|
||||
npts = varargin{2}-1;
|
||||
end
|
||||
|
||||
% check if plotting is requested
|
||||
if nargin < 5
|
||||
plot_ref = false;
|
||||
else
|
||||
plot_ref = varargin{3};
|
||||
end
|
||||
|
||||
% convert to keV
|
||||
energy = energy * 1000;
|
||||
|
||||
if size(energy) ==1
|
||||
emin = energy;
|
||||
emax = energy;
|
||||
npts = 1;
|
||||
req_range = false;
|
||||
elseif size(energy,2) == 2
|
||||
emin = energy(1);
|
||||
emax = energy(2);
|
||||
req_range = true;
|
||||
else
|
||||
error('Only one specific energy or an energy range is supported.')
|
||||
|
||||
end
|
||||
|
||||
% check the energy range
|
||||
if emin < 30 || emax > 30000
|
||||
error('Energies must be in the range 0.03 keV to 30 keV.')
|
||||
end
|
||||
|
||||
|
||||
% request the data
|
||||
server = 'http://henke.lbl.gov/';
|
||||
req = sprintf('Material=Enter+Formula&Formula=%s&Density=%f&Scan=Energy&Min=%d&Max=%d&Npts=%d&Output=Text+File', formula, dens, emin, emax, npts);
|
||||
data_req = webwrite([server 'cgi-bin/getdb.pl'], req);
|
||||
%keyboard
|
||||
% find and read dat file
|
||||
f_pos = strfind(data_req, '/tmp');
|
||||
data_req = strsplit(data_req(f_pos(1):end), '.');
|
||||
data = webread([server data_req{1} '.dat']);
|
||||
|
||||
% split data by line breaks
|
||||
data = strsplit(data, '\n');
|
||||
|
||||
% extract density
|
||||
req_density = data{1};
|
||||
req_density = strsplit(req_density, '=');
|
||||
req_density = str2double(req_density{2});
|
||||
|
||||
|
||||
% output
|
||||
if npts==1 && ~req_range
|
||||
ref = zeros(1,3);
|
||||
req_ref = data{3};
|
||||
req_ref = strsplit(req_ref,' ');
|
||||
ref(1,1) = str2double(req_ref{2})/1000;
|
||||
ref(1,2) = str2double(req_ref{3});
|
||||
ref(1,3) = str2double(req_ref{4});
|
||||
else
|
||||
ref = zeros(npts+1,3);
|
||||
for i=1:npts+1
|
||||
req_ref = data{i+2};
|
||||
req_ref = strsplit(req_ref,' ');
|
||||
ref(i,1) = str2double(req_ref{2})/1000;
|
||||
ref(i,2) = str2double(req_ref{3});
|
||||
ref(i,3) = str2double(req_ref{4});
|
||||
end
|
||||
end
|
||||
|
||||
% plot refractive index
|
||||
if plot_ref
|
||||
if ~req_range
|
||||
fprintf('Requested plot for a single point.')
|
||||
end
|
||||
figure(76);
|
||||
hold on;
|
||||
plot(ref(:,1), ref(:,2))
|
||||
plot(ref(:,1), ref(:,3))
|
||||
ylabel('refractive index')
|
||||
xlabel('energy in keV')
|
||||
legend('delta', 'beta')
|
||||
grid on;
|
||||
hold off;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
% GET_ROTATION_MATRIX_3D generate 3D rotation matrix of size 3x3xn
|
||||
%
|
||||
% rot_3D = get_rotation_matrix_3D(chi, psi, theta)
|
||||
%
|
||||
% Inputs:
|
||||
% chi, psi, theta - rotation angles in degrees , vector or scalar
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 processindg was carried out
|
||||
% usindg 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 rot_3D = get_rotation_matrix_3D(chi, psi, theta)
|
||||
|
||||
if numel(chi) ~= numel(psi) || numel(psi) ~= numel(theta)
|
||||
error('Input sizes are not indentical')
|
||||
end
|
||||
|
||||
N = numel(chi);
|
||||
rot_3D = zeros(3,3,N);
|
||||
|
||||
for ii = 1:N
|
||||
Rx = [ 1, 0, 0 ;
|
||||
0, cosd(chi(ii)), -sind(chi(ii));
|
||||
0, sind(chi(ii)), cosd(chi(ii))];
|
||||
|
||||
Ry = [ cosd(psi(ii)), 0, sind(psi(ii)) ;
|
||||
0, 1, 0;
|
||||
-sind(psi(ii)), 0, cosd(psi(ii))];
|
||||
|
||||
Rz = [ cosd(theta(ii)), -sind(theta(ii)), 0 ;
|
||||
sind(theta(ii)), cosd(theta(ii)), 0;
|
||||
0, 0, 1];
|
||||
|
||||
rot_3D(:,:,ii) = Rx*Ry*Rz;
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,70 @@
|
||||
%GET_UNIT_LENGTH returns the SI unit for a given length
|
||||
% [unit,val] = get_length_unit(val)
|
||||
% Assumes that val is given in [m].
|
||||
%
|
||||
% **val... length
|
||||
%
|
||||
% returns:
|
||||
% ++ unit SI unit string
|
||||
% ++ val input value converted to SI unit
|
||||
%
|
||||
% EXAMPLE:
|
||||
% [unit, val] = get_unit_length(2e-3);
|
||||
% unit
|
||||
% 'mm'
|
||||
% val
|
||||
% '2'
|
||||
%
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [unit,val] = get_unit_length(val)
|
||||
|
||||
units = {'m', 'mm', 'um', 'nm', 'pm', 'fm', 'am'};
|
||||
|
||||
scl = 0;
|
||||
while true
|
||||
if abs(val)*1e3^(scl)>=1 || scl==length(units)-1
|
||||
val = val*1e3^(scl);
|
||||
unit = units{scl+1};
|
||||
break;
|
||||
else
|
||||
scl = scl+1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% GoldsteinUnwrap2D implements 2D Goldstein branch cut phase unwrapping algorithm.
|
||||
%
|
||||
% References::
|
||||
% 1. R. M. Goldstein, H. A. Zebken, and C. L. Werner, �Satellite radar interferometry:
|
||||
% Two-dimensional phase unwrapping,� Radio Sci., vol. 23, no. 4, pp. 713�720, 1988.
|
||||
% 2. D. C. Ghiglia and M. D. Pritt, Two-Dimensional Phase Unwrapping:
|
||||
% Theory, Algorithms and Software. New York: Wiley-Interscience, 1998.
|
||||
%
|
||||
% Inputs: 1. Complex image in .mat double format
|
||||
% 2. Binary mask (optional)
|
||||
% Outputs: 1. Unwrapped phase image
|
||||
% 2. Phase quality map
|
||||
%
|
||||
% This code can easily be extended for 3D phase unwrapping.
|
||||
% Posted by Bruce Spottiswoode on 22 December 2008
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% Copyright (c) 2008, Bruce Spottiswoode
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
% * Neither the name of the University of Cape Town nor the names
|
||||
% of its contributors may be used to endorse or promote products derived
|
||||
% from this software without specific prior written permission.
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
function [unph] = goldstein_unwrap2D(a, max_box_radius)
|
||||
|
||||
|
||||
|
||||
IM=a;
|
||||
IM_mask=ones(size(IM)); %Mask (if applicable)
|
||||
|
||||
IM_mag=abs(IM); %Magnitude image
|
||||
IM_phase=angle(IM); %Phase image
|
||||
|
||||
% Unwrap
|
||||
residue_charge=PhaseResidues(IM_phase, IM_mask); %Calculate phase residues
|
||||
branch_cuts=BranchCuts(residue_charge, max_box_radius, IM_mask); %Place branch cuts
|
||||
[IM_unwrapped, rowref, colref]=FloodFill(IM_phase, branch_cuts, IM_mask); %Flood fill phase unwrapping
|
||||
|
||||
unph=IM_unwrapped;
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
% Implementation of Goldstein unwrap algorithm based on location of
|
||||
% residues and introduction of branchcuts.
|
||||
% R. M. Goldstein, H. A. Zebker and C. L. Werner, Radio Science 23, 713-720
|
||||
% (1988).
|
||||
% Inputs
|
||||
% fase Phase in radians, wrapped between (-pi,pi)
|
||||
% disp (optional) = 1 to show progress (will slow down code)
|
||||
% will also display the branch cuts
|
||||
% start (optional) [y,x] position to start unwrapping. Typically faster
|
||||
% at the center of the array
|
||||
% Outputs
|
||||
% faserecon Unwrapped phase ( = fase where phase could not be unwrapped)
|
||||
% shadow = 1 where phase could not be unwrapped
|
||||
% 31 August, 2010 - Acknowledge if used
|
||||
|
||||
% Modified 20 Sept 2010 - Find a safe area to unwrap around the first point
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [faserecon shadow] = goldsteinunwrap2(fase,disp,start)
|
||||
|
||||
|
||||
display('Unwrapping with Goldstein algorithm')
|
||||
[nr nc] = size(fase);
|
||||
if nargin < 2
|
||||
disp = 0;
|
||||
end
|
||||
if nargin <3
|
||||
nrstart = round(nr/2);
|
||||
ncstart = round(nc/2);
|
||||
else
|
||||
nrstart = start(1);
|
||||
ncstart = start(2);
|
||||
end
|
||||
|
||||
residues = wrapToPi(fase(2:end,1:end-1) - fase(1:end-1,1:end-1));
|
||||
residues = residues + wrapToPi(fase(2:end,2:end) - fase(2:end,1:end-1));
|
||||
residues = residues + wrapToPi(fase(1:end-1,2:end) - fase(2:end,2:end));
|
||||
residues = residues + wrapToPi(fase(1:end-1,1:end-1) - fase(1:end-1,2:end));
|
||||
residues = residues/(2*pi);
|
||||
%%% Find residues
|
||||
[posr,posc] = find(round(residues)==1);
|
||||
respos = [posr posc ones(length(posr),1)];
|
||||
[posr,posc] = find(round(residues)==-1);
|
||||
resneg = [posr posc -ones(length(posr),1)];
|
||||
%[posr,posc] = find(round(residues)~=0);
|
||||
%res = [posr posc];
|
||||
%res = [respos;resneg];
|
||||
nres = length(respos(:,1))+length(resneg(:,1));
|
||||
display(['Found ' num2str(nres) ' residues'])
|
||||
|
||||
if nres == 0,
|
||||
faserecon = unwrap(unwrap(fase')');
|
||||
shadow = faserecon*0;
|
||||
return;
|
||||
end
|
||||
|
||||
%%% Find minimum length walls
|
||||
%currentwall = residues*0;
|
||||
currentwall = zeros(nr+2,nc+2);
|
||||
%currentwallcharge = 0;
|
||||
%wallsegdone = 0;
|
||||
|
||||
%currentwall(res(1,1)+1,res(1,2)+1) = 1;
|
||||
|
||||
|
||||
for ii = 1:min(length(respos(:,1)),length(resneg(:,1))),
|
||||
dist = (respos(1,1) - resneg(:,1)).^2 + (respos(1,2)-resneg(:,2)).^2;
|
||||
ind = find(dist == min(dist),1,'first');
|
||||
if sqrt(dist(ind)) < min(nc,nr)/4,%/4
|
||||
|
||||
currentwall( respos(1,1)+1,min(respos(1,2),resneg(ind,2))+1 : max(respos(1,2),resneg(ind,2))+1 ) = 1;
|
||||
currentwall(min(resneg(ind,1),respos(1,1))+1:max(resneg(ind,1),respos(1,1))+1,resneg(ind,2)+1) = 1;
|
||||
|
||||
respos = respos(2:end,:); % Remove from respos
|
||||
resaux = resneg(1:ind-1,:);
|
||||
resaux = [resaux;resneg(ind+1:end,:)];
|
||||
resneg = resaux;
|
||||
else % Wall too long between them, send to window edge
|
||||
% for respos
|
||||
distedges = [nr-respos(1,1) respos(1,1) nc-respos(1,2) respos(1,2)]; %upper, lower, right, left
|
||||
switch min(distedges)
|
||||
case distedges(1) %upper
|
||||
currentwall(respos(1,1)+1:nr+2, respos(1,2)+1 ) = 1;
|
||||
case distedges(2) %lower
|
||||
currentwall(1:respos(1,1)+1, respos(1,2)+1) = 1;
|
||||
case distedges(3); %right
|
||||
currentwall(respos(1,1)+1, respos(1,2)+1:nc+2) = 1;
|
||||
case distedges(4); %left
|
||||
currentwall(respos(1,1)+1, 1:respos(1,2)+1) = 1;
|
||||
end
|
||||
|
||||
% for resneg
|
||||
distedges = [nr-resneg(ind,1) resneg(ind,1) nc-resneg(ind,2) resneg(ind,2)]; %upper, lower, right, left
|
||||
switch min(distedges)
|
||||
case distedges(1) %upper
|
||||
currentwall(resneg(ind,1)+1:nr+2, resneg(ind,2)+1 ) = 1;
|
||||
case distedges(2) %lower
|
||||
currentwall(1:resneg(ind,1)+1, resneg(ind,2)+1) = 1;
|
||||
case distedges(3); %right
|
||||
currentwall(resneg(ind,1)+1, resneg(ind,2)+1:nc+2) = 1;
|
||||
case distedges(4); %left
|
||||
currentwall(resneg(ind,1)+1, 1:resneg(ind,2)+1) = 1;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
% else
|
||||
% error('Need to implement for unbalanced charge residues')
|
||||
% end
|
||||
|
||||
|
||||
% Branch cuts for unpaired residues
|
||||
res = [respos; resneg];
|
||||
display([num2str(length(res(:,1))) ' unpaired residues'])
|
||||
for ii = 1:length(res(:,1)),
|
||||
distedges = [nr-res(1,1) res(1,1) nc-res(1,2) res(1,2)]; %upper, lower, right, left
|
||||
switch min(distedges)
|
||||
case distedges(1) %upper
|
||||
currentwall(res(1,1)+1:nr+2, res(1,2)+1 ) = 1;
|
||||
case distedges(2) %lower
|
||||
currentwall(1:res(1,1)+1, res(1,2)+1) = 1;
|
||||
case distedges(3); %right
|
||||
currentwall(res(1,1)+1, res(1,2)+1:nc+2) = 1;
|
||||
case distedges(4); %left
|
||||
currentwall(res(1,1)+1, 1:res(1,2)+1) = 1;
|
||||
end
|
||||
res = res(2:end,:);
|
||||
end
|
||||
if disp == 1,
|
||||
figure(4);
|
||||
imagesc(currentwall);
|
||||
colorbar
|
||||
axis xy
|
||||
title('Branch cuts')
|
||||
colormap gray
|
||||
drawnow
|
||||
end
|
||||
|
||||
%% Safe unwrap from start position (this could be made faster)
|
||||
% Only defined the maximum square, could be made faster by defining a
|
||||
% rectangle for example
|
||||
[wallposy wallposx] = find(currentwall == 1); % finds wall positions
|
||||
%distnearest = (wallposy-nrstart).^2+(wallposx-ncstart).^2;
|
||||
%distnearest = abs(wallposy-nrstart)+abs(wallposx-ncstart);
|
||||
distnearest = max(abs(wallposy-nrstart),abs(wallposx-ncstart));
|
||||
indi = find(distnearest == min(distnearest),1);
|
||||
longi = min(distnearest)-2;
|
||||
%longi = min([longi nrstart-1 ncstart-1 nc-ncstart-1 nr-nrstart-1]);
|
||||
|
||||
% figure(100);
|
||||
% plot(wallposx,wallposy,'o');
|
||||
% hold on,
|
||||
% plot(ncstart,nrstart,'or'),
|
||||
% plot([-longi longi]+ncstart,[-longi -longi]+nrstart,'-r');
|
||||
% plot([-longi longi]+ncstart,[longi longi]+nrstart,'-r');
|
||||
% plot([-longi -longi]+ncstart,[longi -longi]+nrstart,'-r');
|
||||
% plot([longi longi]+ncstart,[longi -longi]+nrstart,'-r');
|
||||
% hold off,
|
||||
%%
|
||||
|
||||
|
||||
faserecon = fase*0;
|
||||
shadow = faserecon+1; % not unwrapped yet
|
||||
|
||||
% faserecon(nrstart,ncstart) = fase(nrstart,ncstart);
|
||||
% shadow(nrstart,ncstart) = 0;
|
||||
% counter = 0;
|
||||
|
||||
% faserecon(nrstart+[-longi:longi],ncstart+[-longi:longi]) ...
|
||||
% = unwrap(unwrap( fase(nrstart+[-longi:longi],ncstart+[-longi:longi])')');
|
||||
% shadow(nrstart+[-longi:longi],ncstart+[-longi:longi]) = 0;
|
||||
|
||||
xmask = [max(1,ncstart-longi):min(nc,ncstart+longi)];
|
||||
ymask = [max(1,nrstart-longi):min(nr,nrstart+longi)];
|
||||
faserecon(ymask,xmask) = unwrap(unwrap( fase(ymask,xmask)')');
|
||||
shadow(ymask,xmask) = 0;
|
||||
|
||||
|
||||
|
||||
counter = 0;
|
||||
|
||||
|
||||
% Start unwrapping
|
||||
maxiter = 2*max(nr,nc);
|
||||
wallvert = currentwall(1:end-1,:)¤twall(2:end,:); % prevents horizontal integration
|
||||
%wallvert = [zeros(1,nc-1);wallvert;zeros(1,nc-1)];
|
||||
wallhor = currentwall(:,1:end-1)¤twall(:,2:end); % prevents horizontal integration
|
||||
%wallhor = [zeros(nr-1,1) wallhor zeros(nr-1,1)];
|
||||
|
||||
|
||||
while (counter <maxiter)&&(max(shadow(:))==1);
|
||||
shadowprev = shadow;
|
||||
%%%%% Step right
|
||||
%newrec = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == 1;
|
||||
newrec = [false(nr,1) shadow(:,2:end)¬(shadow(:,1:end-1))];
|
||||
%prev = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == -1;
|
||||
% Block forbiden paths here
|
||||
newrec(:,2:end) = newrec(:,2:end)&(1-wallvert(1:end-1,2:end-2));
|
||||
deltafase = [zeros(nr,1) fase(:,2:end)-faserecon(:,1:end-1)].*newrec;
|
||||
%faserecon = faserecon + (fase - round(deltafase/(2*pi))*2*pi).*newrec;
|
||||
faserecon(newrec) = fase(newrec) - round(deltafase(newrec)/(2*pi))*2*pi;
|
||||
shadow(newrec) = 0;
|
||||
|
||||
%%%%% Step left
|
||||
%newrec = [shadow(:,1:end-1)-shadow(:,2:end) zeros(nr,1)] == 1;
|
||||
newrec = [shadow(:,1:end-1)¬(shadow(:,2:end)) false(nr,1)];
|
||||
%prev = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == -1;
|
||||
% Block forbiden paths here
|
||||
newrec(:,1:end-1) = newrec(:,1:end-1)&(1-wallvert(1:end-1,2:end-2));
|
||||
deltafase = [fase(:,1:end-1)-faserecon(:,2:end) zeros(nr,1)].*newrec;
|
||||
%faserecon = faserecon + (fase - round(deltafase/(2*pi))*2*pi).*newrec;
|
||||
faserecon(newrec) = fase(newrec) - round(deltafase(newrec)/(2*pi))*2*pi;
|
||||
shadow(newrec) = 0;
|
||||
|
||||
%%%%% Step up (positive y)
|
||||
%newrec = [zeros(1,nc) ; shadow(2:end,:)-shadow(1:end-1,:)] == 1;
|
||||
newrec = [false(1,nc) ; shadow(2:end,:)¬(shadow(1:end-1,:))];
|
||||
%prev = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == -1;
|
||||
% Block forbiden paths here
|
||||
newrec(2:end,:) = newrec(2:end,:)&(1-wallhor(2:end-2,1:end-1));
|
||||
deltafase = [zeros(1,nc) ; fase(2:end,:)-faserecon(1:end-1,:)].*newrec;
|
||||
%faserecon = faserecon + (fase - round(deltafase/(2*pi))*2*pi).*newrec;
|
||||
faserecon(newrec) = fase(newrec) - round(deltafase(newrec)/(2*pi))*2*pi;
|
||||
shadow(newrec) = 0;
|
||||
|
||||
%%%%% Step down (negative y)
|
||||
%newrec = [shadow(1:end-1,:)-shadow(2:end,:) ; zeros(1,nc)] == 1;
|
||||
newrec = [shadow(1:end-1,:)¬(shadow(2:end,:)) ; false(1,nc)];% Logical input does not seeem to help with computing time
|
||||
%prev = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == -1;
|
||||
% Block forbiden paths here
|
||||
newrec(1:end-1,:) = newrec(1:end-1,:)&(1-wallhor(2:end-2,1:end-1));
|
||||
deltafase = [fase(1:end-1,:)-faserecon(2:end,:) ; zeros(1,nc)].*newrec;
|
||||
%faserecon = faserecon + (fase - round(deltafase/(2*pi))*2*pi).*newrec;
|
||||
faserecon(newrec) = fase(newrec) - round(deltafase(newrec)/(2*pi))*2*pi;
|
||||
shadow(newrec) = 0;
|
||||
|
||||
counter = counter+1;
|
||||
|
||||
if any(not(shadow(:)==shadowprev(:))) == 0,
|
||||
warning('Not all points are accessible for integration')
|
||||
faserecon(shadow==1) = fase(shadow==1);
|
||||
break;
|
||||
end
|
||||
|
||||
|
||||
if disp == 1,
|
||||
figure(5);
|
||||
imagesc(faserecon);
|
||||
colorbar
|
||||
axis xy
|
||||
title('Reconstructed phase')
|
||||
colormap jet
|
||||
drawnow;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if counter == maxiter,
|
||||
warning('Maximum number of iterations exceeded for unwrapping. Increase maxiter.'),
|
||||
end
|
||||
@@ -0,0 +1,118 @@
|
||||
% Identify the current system to set useful default parameter values in
|
||||
% default_parameter_value.m.
|
||||
% A modified version of both macros at the beginning of the Matlab search
|
||||
% path may be used to define local standard parameters.
|
||||
|
||||
% Filename: $RCSfile: identify_system.m,v $
|
||||
%
|
||||
% $Revision: 1.3 $ $Date: 2010/07/22 15:08:21 $
|
||||
% $Author: $
|
||||
% $Tag: $
|
||||
%
|
||||
% Description:
|
||||
% Identify the current system to set useful default parameter values in
|
||||
% default_parameter_value.m.
|
||||
% A modified version of both macros at the beginning of the Matlab search
|
||||
% path may be used to define local standard parameters.
|
||||
%
|
||||
% Note:
|
||||
% none
|
||||
%
|
||||
% Dependencies:
|
||||
% none
|
||||
%
|
||||
%
|
||||
% history:
|
||||
%
|
||||
% June 2nd 2009:
|
||||
% buffer current system ID for later calls to speed up execution
|
||||
%
|
||||
% April 16th, 2009: 1st version
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [return_system_id_str return_other_system_flags] = identify_system()
|
||||
|
||||
persistent system_id_str;
|
||||
persistent parallel_computing_toolbox_available;
|
||||
|
||||
if (isempty(system_id_str))
|
||||
% default value
|
||||
system_id_str = 'other';
|
||||
|
||||
if (isunix)
|
||||
% check for a known network name of the PC Matlab is running on
|
||||
[status,hostname] = unix('hostname');
|
||||
if (status == 0)
|
||||
hostname = sscanf(hostname,'%s');
|
||||
if length(hostname)>4 && strcmp(hostname(1:5),'x12sa')
|
||||
system_id_str = 'X12SA';
|
||||
else
|
||||
switch hostname
|
||||
case {'pc6024', 'pc5369'}
|
||||
system_id_str = 'DPC lab';
|
||||
case {'mpc1054'}
|
||||
system_id_str = 'mDPC lab';
|
||||
case {'pc5211', 'mpc1144', 'mpc1145'}
|
||||
system_id_str = 'cSAXS-mobile';
|
||||
case {'lccxs01', 'lccxs02', 'mpc1208'}
|
||||
system_id_str = 'CXS compute node';
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
% neither Linux nor Mac
|
||||
system_id_str = 'Windows';
|
||||
end
|
||||
end
|
||||
|
||||
% check for the parallel computing toolbox being available
|
||||
if (isempty(parallel_computing_toolbox_available))
|
||||
parallel_computing_toolbox_available = false;
|
||||
|
||||
versions = ver;
|
||||
for line = 1:length(versions)
|
||||
if strfind(versions(line).Name, 'Parallel Computing Toolbox')
|
||||
parallel_computing_toolbox_available = true;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% compile return values
|
||||
|
||||
return_system_id_str = system_id_str;
|
||||
|
||||
return_other_system_flags.parallel_computing_toolbox_available = parallel_computing_toolbox_available;
|
||||
@@ -0,0 +1,61 @@
|
||||
% IMCROP_OUTLIERS find the largest region of Mask and remove other
|
||||
% the nonconnectd regions
|
||||
%
|
||||
% mask_new = imcrop_outliers(mask, number_of_objects)
|
||||
%
|
||||
% Inputs:
|
||||
% **mask binary 2D mask to be parsed
|
||||
% **number_of_objects number of largest objects to be kept, default = 1
|
||||
%
|
||||
% returns:
|
||||
% ++mask_new mask after removing all smaller nonconnected objects
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 mask_new = imcrop_outliers(mask, number_of_objects)
|
||||
if nargin == 1
|
||||
number_of_objects = 1;
|
||||
end
|
||||
|
||||
L0 = double(labelmatrix(bwconncomp(mask)));
|
||||
[m,n] = hist(L0(L0>0),unique(L0(L0>0)));
|
||||
[~,ind] = sort(m);
|
||||
|
||||
mask_new = ismember(L0, n(ind(max(1,end - number_of_objects+1):end)));
|
||||
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
% AFFINE_DEFORM_FFT apply accurate affine deformation on image
|
||||
% use only for minor corrections !!
|
||||
%
|
||||
% img = affine_deform_fft(img, affine_matrix, shift)
|
||||
%
|
||||
% Inputs:
|
||||
% **img - 2D or stack of 2D images
|
||||
% **affine_matrix - 2x2xN affine matrix
|
||||
% **shift - Nx2 vector of shifts to be applied
|
||||
% *returns*:
|
||||
% ++img - deformed image
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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. |
|
||||
%| |f
|
||||
%| 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 img = imdeform_affine_fft(img, affine_matrix, shift)
|
||||
import utils.*
|
||||
if nargin < 3
|
||||
shift = [];
|
||||
end
|
||||
if ~isempty(shift)
|
||||
img = imshift_fft(img, shift);
|
||||
end
|
||||
if ~isempty(affine_matrix)
|
||||
if size(affine_matrix,3)>1
|
||||
for i=1:size(affine_matrix,3)
|
||||
[scale, asymmetry, rotation, shear] = math.decompose_affine_matrix(double(gather(affine_matrix(:,:,i))));
|
||||
if any(abs(scale(:)-1) > 1e-5)
|
||||
img(:,:,i) = imrescale_frft(img(:,:,i), scale, scale.*asymmetry);
|
||||
end
|
||||
if any(abs(shear(:)) > 1e-5)
|
||||
img(:,:,i) = imshear_fft(img(:,:,i),shear,1);
|
||||
end
|
||||
if any(abs(rotation(:))> 1e-5)
|
||||
img(:,:,i) = imrotate_ax_fft(img(:,:,i),rotation,3);
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
[scale, asymmetry, rotation, shear] = math.decompose_affine_matrix(double(gather(affine_matrix)));
|
||||
if any(abs(scale(:)-1) > 1e-5)
|
||||
img = imrescale_frft(img, scale, scale.*asymmetry);
|
||||
end
|
||||
if any(abs(shear(:)) > 1e-5)
|
||||
img = imshear_fft(img,shear,1);
|
||||
end
|
||||
if any(abs(rotation(:))> 1e-5)
|
||||
img = imrotate_ax_fft(img,rotation,3);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,100 @@
|
||||
% IMGAUSSFILT2_FFT apply gaussian smoothing along all three dimensions
|
||||
% faster than matlab version
|
||||
%
|
||||
% A = imgaussfilt2_fft(A,sigma)
|
||||
%
|
||||
% Inputs:
|
||||
% **A 3D volume to be smoothed
|
||||
% **sigma gaussian smoothing constant
|
||||
% **split 3x1 int vector to split the volume and save memory
|
||||
% *returns*:
|
||||
% ++A smoothed volume
|
||||
|
||||
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 A = imgaussfilt2_fft(A,sigma, split)
|
||||
% gaussian blurring along first 2 dimension
|
||||
import math.*
|
||||
if isscalar(sigma) && sigma == 0
|
||||
return
|
||||
end
|
||||
if nargin < 3
|
||||
split = 1;
|
||||
end
|
||||
|
||||
isReal = isreal(A);
|
||||
|
||||
Npx = size(A);
|
||||
|
||||
A = fft2_partial(A, split);
|
||||
|
||||
for dim=1:2
|
||||
if isscalar(sigma)
|
||||
grid = single((-Npx(dim)/2:Npx(dim)/2-1));
|
||||
ker = exp(-grid.^2/ sigma^2)';
|
||||
elseif isvector(sigma)
|
||||
% use user given kernel , assume splitable 1D kernel
|
||||
ker = zeros(Npx(dim),1,'like', A);
|
||||
Ns = length(sigma);
|
||||
ker(ceil(Npx(dim)/2)+[-floor(Ns/2):ceil(Ns/2)-1]) = sigma;
|
||||
else
|
||||
error('N-dim kernel not implemented')
|
||||
end
|
||||
ker = ker / sum(ker);
|
||||
ker = fft(ker,[],1);
|
||||
|
||||
ker_shape = ones(1,2);
|
||||
ker_shape(dim) = Npx(dim);
|
||||
B = reshape(ker,ker_shape);
|
||||
if isa(A, 'gpuArray'); B = gpuArray(B); end
|
||||
A = A.*B;
|
||||
end
|
||||
clear B
|
||||
|
||||
A = ifft2_partial(A, split);
|
||||
|
||||
if isReal
|
||||
A = real(A);
|
||||
end
|
||||
|
||||
% Im not sure why, but the output needs to be fftshifted
|
||||
A = fftshift_2D(A);
|
||||
|
||||
end
|
||||
@@ -0,0 +1,76 @@
|
||||
% IMGAUSSFILT3_CONV apply gaussian smoothing along all three dimensions using convolution,
|
||||
% faster than matlab alternative
|
||||
%
|
||||
%
|
||||
% A = imgaussfilt3_conv(A,sigma)
|
||||
%
|
||||
% Inputs:
|
||||
% **A 3D volume to be smoothed
|
||||
% **sigma gaussian smoothing constant, scalar or use vector for anizotropic kernel smoothing
|
||||
% returns:
|
||||
% ++A smoothed volume
|
||||
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 X = imgaussfilt3_conv(X, filter_size)
|
||||
%% faster equivalent to the imgaussfilt3 in matlab
|
||||
|
||||
shape_0 = {[], 1,1};
|
||||
for ax = 1:3
|
||||
if filter_size(min(end,ax)) == 0
|
||||
continue
|
||||
end
|
||||
if ax == 1 || filter_size(min(end,ax-1)) ~= filter_size(min(end,ax))
|
||||
ker = get_kernel(filter_size(min(end,ax)) , class(X));
|
||||
end
|
||||
shape = circshift(shape_0, ax-1);
|
||||
X = convn(X, reshape(ker,shape{:}), 'same');
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ker = get_kernel(filter_size, class)
|
||||
|
||||
grid = (-ceil(2*filter_size):ceil(2*filter_size)) / filter_size;
|
||||
ker = exp(-grid.^2);
|
||||
ker = ker / sum(ker);
|
||||
if isa(class, 'gpuArray')
|
||||
ker = gpuArray(single(ker));
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,101 @@
|
||||
% IMGAUSSFILT3_FFT apply isotropic gaussian smoothing along all three
|
||||
% dimensions, faster than matlab alternative
|
||||
%
|
||||
% A = imgaussfilt3_fft(A,sigma, split)
|
||||
%
|
||||
% Inputs:
|
||||
% **A 3D volume to be smoothed
|
||||
% **sigma gaussian smoothing constant
|
||||
% **split 3x1 int vector to split the volume and save memory
|
||||
% *returns*:
|
||||
% ++A filtered volume
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 A = imgaussfilt3_fft(A,sigma, split)
|
||||
% gaussian blurring in 3D
|
||||
import math.*
|
||||
|
||||
if sigma == 0
|
||||
return
|
||||
end
|
||||
if nargin < 3
|
||||
split = 1;
|
||||
end
|
||||
|
||||
Npx = size(A);
|
||||
isReal = isreal(A);
|
||||
|
||||
A = fftn_partial(A, split);
|
||||
|
||||
for dim=1:3
|
||||
grid = single((-Npx(dim)/2:Npx(dim)/2-1));
|
||||
ker = exp(-grid.^2/ sigma^2)';
|
||||
ker = ker / sum(ker);
|
||||
ker = fft(ker,[],1);
|
||||
|
||||
ker_shape = ones(1,3);
|
||||
ker_shape(dim) = Npx(dim);
|
||||
B{dim} = reshape(ker,ker_shape);
|
||||
end
|
||||
if isa(A, 'gpuArray')
|
||||
A = arrayfun(@prod3,A,B{:});
|
||||
else
|
||||
A = prod3(A,B{:});
|
||||
end
|
||||
|
||||
|
||||
A = ifftn_partial(A, split);
|
||||
if isReal
|
||||
A = real(A);
|
||||
end
|
||||
|
||||
% Im not sure why, but the output needs to be fftshifted
|
||||
|
||||
for dim = 1:3
|
||||
m = size(A, dim);
|
||||
p = ceil(m/2);
|
||||
idx{dim} = [p+1:m 1:p];
|
||||
end
|
||||
|
||||
% Use comma-separated list syntax for N-D indexing.
|
||||
A = A(idx{:});
|
||||
|
||||
end
|
||||
|
||||
function A = prod3(A,k1,k2,k3)
|
||||
A = A .* k1 .* k2 .* k3;
|
||||
end
|
||||
@@ -0,0 +1,83 @@
|
||||
% IMRESCALE_FFT subpixel precision rescaling based on multiplication by a
|
||||
% matrix of fourier transformation, fast only for small arrays
|
||||
% Inputs:
|
||||
% **img - 2D or stack of 2D images
|
||||
% **scale - scaling factor
|
||||
% *returns*:
|
||||
% ++img - 2D or stack of 2D images scaled by factor scale
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img_rescale = imrescale_fft(img, scale)
|
||||
|
||||
if scale == 1 || isnan(scale)
|
||||
img_rescale = img;
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
N = size(img);
|
||||
|
||||
for i = 1:2
|
||||
if N(1) ~= N(2) || i == 1
|
||||
ind_x = real(zeros(N(i),1, 'like', img));
|
||||
ind_x(:) = (0:N(i)-1)/N(i)-0.5;
|
||||
grid = ind_x*ind_x';
|
||||
grid = -2i*pi*N(i)/scale*grid;
|
||||
W{i} = exp(grid)'/N(i); % matrix of fourier transformation
|
||||
else
|
||||
W{2} = W{1};
|
||||
end
|
||||
end
|
||||
|
||||
fimg = fftshift(fft2(fftshift(img)));
|
||||
|
||||
if size(img,3) > 1
|
||||
fimg2 = W{1}*reshape(fimg,N(1),[]);
|
||||
fimg2 = reshape(fimg2, N(1),N(2),[]);
|
||||
fimg2 = permute(fimg2, [2,1,3]);
|
||||
fimg2 = reshape(fimg2, N(2),[]);
|
||||
img_rescale = (W{1}*fimg2); % rescale and fft back
|
||||
img_rescale = reshape(img_rescale, N(2),N(1),[]);
|
||||
img_rescale = permute(img_rescale, [2,1,3]);
|
||||
else
|
||||
fimg2 = W{1}*fimg;
|
||||
img_rescale = (W{2}*fimg2.').';
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
% IMRESCALE_FRFT subpixel accurate image rescaling based on fractional fourier
|
||||
% transformation (FRFT)
|
||||
%
|
||||
% img = imrescale_frft(img, scale_x, scale_y, scale_z)
|
||||
%
|
||||
% Inputs:
|
||||
% **img 2D or stack of 2D images
|
||||
% **scale_x - horizontal scaling factor
|
||||
% *optional*
|
||||
% **scale_y - vertical scaling factor, if not provided scale_x is used
|
||||
% **scale_z - 3rd axis scaling factor, if not provided, no scaling is
|
||||
% used along 3rd axis
|
||||
% *returns*:
|
||||
% ++img 2D or stack of 2D images scaled by factors scale_x, (scale_y)
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [img, win] = imrescale_frft(img, scale_x, scale_y, scale_z)
|
||||
|
||||
isReal = isreal(img);
|
||||
win = [];
|
||||
if ~isvector(scale_x) && ~isscalar(scale_x)
|
||||
error('Inputs scaling is expected as scalar or vector')
|
||||
end
|
||||
if nargin < 3 && (size(img,1)==size(img,2))
|
||||
% 2d version is faster only for many stacked pictures
|
||||
if scale_x > 1
|
||||
win = get_window(img, scale_x, 1) .* get_window(img, scale_x, 2);
|
||||
img = img .* win;
|
||||
end
|
||||
%size(img)
|
||||
img = math.fftshift_2D(ifft2(math.fftshift_2D(FRFT_2D(img,scale_x))));
|
||||
else
|
||||
if nargin < 3
|
||||
scale_y = scale_x;
|
||||
end
|
||||
if any(scale_y ~= 1)
|
||||
img = math.fftshift_2D(ifft(math.fftshift_2D(FRFT_1D(img,scale_y))));
|
||||
end
|
||||
if any(scale_x ~= 1)
|
||||
img = permute(img,[2,1,3]);
|
||||
img = math.fftshift_2D(ifft(math.fftshift_2D(FRFT_1D(img,scale_x))));
|
||||
img = permute(img,[2,1,3]);
|
||||
end
|
||||
if nargin > 3
|
||||
if any(scale_z ~= 1)
|
||||
img = permute(img,[3,2,1]);
|
||||
img = math.fftshift_2D(ifft(math.fftshift_2D(FRFT_1D(img,scale_z))));
|
||||
img = permute(img,[3,2,1]);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if isReal
|
||||
img = real(img);
|
||||
end
|
||||
end
|
||||
|
||||
function win = get_window(img, scale, ax)
|
||||
% apodize window for img to prevent periodic boundary errors
|
||||
win = ones(ceil(size(img,ax)/scale/2)*2,class(img));
|
||||
win = utils.crop_pad(win, [size(img,ax),1]);
|
||||
win = shiftdim(win, 1-ax);
|
||||
end
|
||||
|
||||
function X=FRFT_1D(X,alpha)
|
||||
% 1D fractional fourier transformation
|
||||
% See A. Averbuch, "Fast and Accurate Polar Fourier Transform"
|
||||
|
||||
%% it works as magnification lens Claus, D., & Rodenburg, J. M. (2015). Pixel size adjustment in coherent diffractive imaging within the Rayleigh–Sommerfeld regime
|
||||
|
||||
%% test plot(abs(fftshift(ifft((FRFT_1D(x,scale))))))
|
||||
|
||||
N = size(X,1);
|
||||
grid = fftshift(-N:N-1)';
|
||||
|
||||
preFactor = reshape(exp(1i*pi*grid*alpha(:)'),2*N,1,[]); % perform shift
|
||||
Factor= reshape(exp(-1i*pi*grid.^2/N * alpha(:)'),2*N,1,[]); % propagation / scaling
|
||||
X=[X; zeros(size(X), class(X))]; % add oversampling
|
||||
X= bsxfun(@times, X, Factor .* preFactor);
|
||||
|
||||
% avoid duplication of XX
|
||||
X=fft(X);
|
||||
X = bsxfun(@times, X,fft(conj(Factor)));
|
||||
X=ifft(X);
|
||||
|
||||
X=bsxfun(@times, X,reshape(Factor .* preFactor,2*N,1,[]));
|
||||
X=X(1:N,:,:);
|
||||
%% remove phase offset
|
||||
X = bsxfun(@times, X , reshape(exp(-1i*pi*N*alpha/2),1,1,[]));
|
||||
end
|
||||
|
||||
function X=FRFT_2D(X,alpha)
|
||||
% 2D fractional fourier transformation
|
||||
% See A. Averbuch, "Fast and Accurate Polar Fourier Transform"
|
||||
|
||||
%% it maybe works as magification lens Claus, D., & Rodenburg, J. M. (2015). Pixel size adjustment in coherent diffractive imaging within the Rayleigh–Sommerfeld regime
|
||||
|
||||
alpha = reshape(alpha,1,1,[]);
|
||||
|
||||
N = size(X,1);
|
||||
grid = (fftshift(-N:N-1)') * ones(1, 'like', X);
|
||||
|
||||
[Xg,Yg] = meshgrid(grid(1:N), grid(1:N));
|
||||
preFactor = exp((1i*pi.*alpha)*(-N/2+(Xg+Yg) - (1/N)*(Xg.^2+Yg.^2))); % perform shift after FFT
|
||||
|
||||
[Xg,Yg] = meshgrid(grid, grid);
|
||||
Factor=exp((1i*pi/N(1))*(Xg.^2+Yg.^2) .* alpha); % propagation / scaling
|
||||
Factor = fft2(Factor);
|
||||
|
||||
X= X .* preFactor;
|
||||
|
||||
if length(size(X))==4 %%added by YJ to present errors when using variable probe
|
||||
x_tilde = zeros(2*N, 2*N, size(X,3), size(X,4), 'like', X);
|
||||
% upsample the X array
|
||||
x_tilde(1:N, 1:N,:,:) = X;
|
||||
|
||||
X=fft2(x_tilde);
|
||||
|
||||
X = X .* Factor;
|
||||
|
||||
X=ifft2( X );
|
||||
|
||||
X=X(1:N,1:N,:,:);
|
||||
|
||||
else %%length(size(X))==3
|
||||
|
||||
x_tilde = zeros(2*N, 2*N, size(X,3), 'like', X);
|
||||
% upsample the X array
|
||||
x_tilde(1:N, 1:N,:) = X;
|
||||
|
||||
X=fft2(x_tilde);
|
||||
|
||||
X = X .* Factor;
|
||||
|
||||
X=ifft2( X );
|
||||
|
||||
X=X(1:N,1:N,:);
|
||||
end
|
||||
|
||||
X=X.* preFactor;
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
% FUNCTION img_stack = imrotate_ax(img_stack, angle, ax, val, method)
|
||||
% bilinear rotate stack of images along given axis
|
||||
|
||||
% IMROTATE_AX bilinear rotate stack of images along given axis
|
||||
% img_stack = imrotate_fft(img, theta, axis,ax=3 val=0, method='bilinear')
|
||||
%
|
||||
% Inputs:
|
||||
% **img - stacked array of images to be rotated
|
||||
% **theta - rotation angle
|
||||
% **axis - rotation axis
|
||||
% *optional*
|
||||
% **val - fill missing values by this number
|
||||
% **method- interpolation method
|
||||
% *returns*:
|
||||
% ++img - rotated image
|
||||
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img_stack = imrotate_ax(img_stack, angle, ax, val, method)
|
||||
if nargin < 4
|
||||
val = 0;
|
||||
end
|
||||
if nargin < 3
|
||||
ax = 3;
|
||||
end
|
||||
if nargin < 5
|
||||
method = 'bilinear';
|
||||
end
|
||||
|
||||
%% bilinear rotation along given axis
|
||||
N = size(img_stack,ax);
|
||||
|
||||
if ~isa(img_stack, 'gpuArray')
|
||||
%% for CPU based rotation process the inputs slice by slice
|
||||
ind = {':',':',':'};
|
||||
for ii = 1:N
|
||||
if utils.verbose > 0; utils.progressbar(ii,N); end
|
||||
ind{ax} = ii;
|
||||
|
||||
auxslice = squeeze(img_stack(ind{:}));
|
||||
if any(size(auxslice) ~= N)
|
||||
% pad in case of asymmetric input
|
||||
auxslice_pad = padarray( auxslice , [N N], val); % val is the background
|
||||
auxslice_pad = imrotate(auxslice_pad,angle,method,'crop');
|
||||
auxslice = auxslice_pad(N+1:end-N, N+1:end-N);
|
||||
else
|
||||
auxslice = imrotate(auxslice,angle,method,'crop');
|
||||
end
|
||||
img_stack(ind{:}) = auxslice;
|
||||
end
|
||||
else
|
||||
%% for GPU call directly the internal code for 2D interpolation and process the image block in one step
|
||||
|
||||
if ax == 1
|
||||
img_stack = permute(img_stack, [3,2,1]); angle = - angle;
|
||||
elseif ax == 2
|
||||
img_stack = permute(img_stack, [1,3,2]);
|
||||
end
|
||||
|
||||
outputSize = size(img_stack);
|
||||
if isreal(img_stack)
|
||||
img_stack = images.internal.gpu.imrotate(img_stack, angle, method, outputSize);
|
||||
else
|
||||
img_stack = complex(images.internal.gpu.imrotate(real(img_stack), angle, method, outputSize),...
|
||||
images.internal.gpu.imrotate(imag(img_stack), angle, method, outputSize));
|
||||
end
|
||||
|
||||
if ax == 1
|
||||
img_stack = permute(img_stack, [3,2,1]);
|
||||
elseif ax == 2
|
||||
img_stack = permute(img_stack, [1,3,2]);
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,119 @@
|
||||
% IMROTATE_AX_FFT fft-based image rotation for a stack of images along given axis
|
||||
% based on "Fast Fourier method for the accurate rotation of sampled images", Optic Communications, 1997
|
||||
% img_stack = imrotate_ax_fft(img, theta, ax)
|
||||
%
|
||||
% Inputs:
|
||||
% **img - stacked array of images to be rotated
|
||||
% **theta - rotation angle
|
||||
% *optional*
|
||||
% **axis - rotation axis (default=3)
|
||||
% returns:
|
||||
% ++img - rotated image
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img = imrotate_ax_fft(img, theta, axis)
|
||||
if all(theta == 0) || isempty(img); return ; end
|
||||
|
||||
if nargin < 3
|
||||
axis = 3;
|
||||
end
|
||||
|
||||
isReal = isreal(img);
|
||||
|
||||
if axis == 1
|
||||
img = permute(img, [3,2,1]); theta = - theta;
|
||||
elseif axis == 2
|
||||
img = permute(img, [1,3,2]);
|
||||
end
|
||||
|
||||
angle_90_offset = round(theta/90);
|
||||
|
||||
if angle_90_offset ~= 0
|
||||
img = rot90(img, angle_90_offset);
|
||||
theta = theta - 90*angle_90_offset;
|
||||
end
|
||||
|
||||
if theta == 0; return ; end
|
||||
|
||||
|
||||
[M, N, ~] = size(img);
|
||||
|
||||
% make possible to rotate each slice with different angle
|
||||
theta = reshape(theta,1,1,[]) * ones(1,'like',img); % move to GPU if needed
|
||||
xgrid = (ifftshift(-fix(M/2):ceil(M/2)-1)'/M);
|
||||
ygrid = (ifftshift(-fix(N/2):ceil(N/2)-1) /N);
|
||||
Mgrid = (1:M)'-floor(M/2)-0.5; % the 0.5px offset is important to make the rotation equivalent to matlab imrotate
|
||||
Ngrid = (1:N) -floor(N/2)-0.5;
|
||||
|
||||
if isa(theta, 'gpuArray')
|
||||
[M1, M2] = arrayfun(@aux_fun, theta, xgrid, ygrid, Mgrid, Ngrid);
|
||||
else
|
||||
[M1, M2] = aux_fun(theta, xgrid, ygrid, Mgrid, Ngrid);
|
||||
end
|
||||
|
||||
|
||||
% rotate images by a combination of shears
|
||||
img=ifft(fft(img,[],2).*M1,[],2);
|
||||
img=ifft(fft(img,[],1).*M2,[],1);
|
||||
img=ifft(fft(img,[],2).*M1,[],2);
|
||||
|
||||
if isReal
|
||||
img = real(img);
|
||||
end
|
||||
|
||||
if axis == 1
|
||||
img = permute(img, [3,2,1]);
|
||||
elseif axis == 2
|
||||
img = permute(img, [1,3,2]);
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
% auxiliarly function to be used for GPU kernel merging
|
||||
function [M1, M2] = aux_fun(theta, xgrid, ygrid, Mgrid, Ngrid)
|
||||
|
||||
|
||||
% based on "Fast Fourier method for the accurate rotation of sampled images", Optic Communications, 1997
|
||||
Nx = -sind(theta) .* xgrid;
|
||||
Ny = tand(theta/2).* ygrid;
|
||||
|
||||
M1 = exp(-2i*pi*Mgrid.*Ny);
|
||||
M2 = exp(-2i*pi*Ngrid.*Nx);
|
||||
|
||||
end
|
||||
@@ -0,0 +1,81 @@
|
||||
% IMSHEAR_FFT fft-based image shearing function for a stack of images along given axis
|
||||
%
|
||||
% img_stack = imshear_fft(img_stack, theta, shear_axis)
|
||||
%
|
||||
% Inputs:
|
||||
% **img_stack - stack of 2D images
|
||||
% **theta - shear angle, scalar
|
||||
% **shear_axis - image axis along which the image will be shared
|
||||
% *returns*:
|
||||
% ++img - shreared image
|
||||
%
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img = imshear_fft(img, theta, shear_axis)
|
||||
|
||||
if theta == 0; return ; end
|
||||
|
||||
assert(any(shear_axis == [1,2]), 'Shear axis has to be 1 or 2' )
|
||||
|
||||
isReal = isreal(img);
|
||||
|
||||
if abs(theta) > 45
|
||||
error('Out of valid angle range [-45,45], use rot90 to get into the valid range')
|
||||
end
|
||||
|
||||
[M, N, ~] = size(img);
|
||||
theta = reshape(theta,1,1,[]); % allow different theta for each slice
|
||||
|
||||
Nx = -sind(theta) .* ifftshift(-fix(M/2):ceil(M/2)-1)/M;
|
||||
Ny = tand(theta/2).* ifftshift(-fix(N/2):ceil(N/2)-1)/N;
|
||||
Mgrid = 2i*pi*((1:M)'-floor(M/2)) * ones(1,'like',img);
|
||||
Ngrid = 2i*pi*((1:N)'-floor(N/2)) * ones(1,'like',img);
|
||||
|
||||
% rotate images by a combination of shears
|
||||
switch shear_axis
|
||||
case 1, img=ifft(fft(img,[],2).*exp(-Mgrid.*Ny), [],2);
|
||||
case 2, img=ifft(fft(img,[],1).*exp( Ngrid.*Nx)',[],1);
|
||||
otherwise
|
||||
error('Shear axis has to be 1 or 2')
|
||||
end
|
||||
|
||||
if isReal
|
||||
img = real(img);
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,73 @@
|
||||
% IMSHIFT_CIRC_AX will apply integer shift that can be different
|
||||
% for each frame along axis AX. The shift is applied with !! periodic
|
||||
% boundary !!.
|
||||
%
|
||||
% img_out = imshift_circ_ax(img, shift, ax)
|
||||
%
|
||||
% Inputs:
|
||||
% **img - stack of images
|
||||
% **shift - horizontal / vertical shift in pixels , N*2 vector
|
||||
% **ax - axis along which the stacked images will be shifted
|
||||
% *returns*:
|
||||
% ++img - shifted image
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img_out = imshift_circ_ax(img, shift, ax)
|
||||
|
||||
shift = round(shift);
|
||||
|
||||
if all(shift == 0)
|
||||
img_out=img;
|
||||
return
|
||||
end
|
||||
|
||||
Npix = size(img);
|
||||
|
||||
img_out = img;
|
||||
|
||||
|
||||
ind = {':',':',':'}; % assume max 3 dim
|
||||
ax_0 = 1+mod(ax,ndims(img)); % fixed axis
|
||||
for i = 1:Npix(ax_0)
|
||||
ind{ax_0} = i;
|
||||
img_out(ind{:}) = circshift(img(ind{:}), shift(i), ax);
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
% IMSHIFT_FAST shift of stack of images by given number of
|
||||
% pixels and if needed crop / pad image to fit into Npix_new
|
||||
%
|
||||
% img_new=imshift_fast(img_0, x,y, Npix_new=[], type='linear', default_val=0)
|
||||
%
|
||||
% Inputs:
|
||||
% **img_0 - stack of images
|
||||
% **x,y - horizontal / vertical shift in pixels (scalars)
|
||||
% **Npix_new - empty/missing => keep original size, 2x1 vector => embed new image into given frame size
|
||||
% **type - linear / nearest neighbor interpolation , (missing/empty => linear)
|
||||
% **default_val - default value to fill empty regions created after the image shift
|
||||
% returns:
|
||||
% ++ img_new - shifted image padded to Npix_new
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img_new=imshift_fast(img_0, x,y, Npix_new, type, default_val)
|
||||
|
||||
|
||||
if nargin < 4 || isempty(Npix_new)
|
||||
Npix_new = size(img_0);
|
||||
end
|
||||
Npix_new = Npix_new(1:2);
|
||||
if nargin < 5
|
||||
type = 'linear';
|
||||
end
|
||||
if nargin < 6
|
||||
default_val = 0;
|
||||
end
|
||||
if length(x) > 1 || length(y) > 1
|
||||
error('Only scalar position shifts are accepted')
|
||||
end
|
||||
|
||||
[Nx, Ny, Nimgs] = size(img_0);
|
||||
|
||||
|
||||
if x==0 && y == 0 && all([Nx,Ny] == Npix_new)
|
||||
%% no change is needed, return original image
|
||||
img_new = img_0;
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
pos = -[x,y];
|
||||
if strcmp(type, 'linear') && any(round([x,y]) ~= [x,y]) && ~isa(img_0, 'logical')
|
||||
shift = make_shift(pos - round(pos));
|
||||
|
||||
Npix_tmp = size(img_0);
|
||||
Npix_tmp(1:2) = Npix_tmp(1:2) + 2;
|
||||
img_tmp = zeros(Npix_tmp, 'like', img_0 );
|
||||
for i = 1:Nimgs
|
||||
img_tmp(:,:,i) = conv2(img_0(:,:,i), shift, 'full');
|
||||
end
|
||||
img_0 = img_tmp;
|
||||
end
|
||||
Npix = [Nx,Ny];
|
||||
|
||||
[oROI, pROI] = find_ROI( pos ,Npix_new, Npix );
|
||||
|
||||
|
||||
if all(x==0) && all(y == 0) && all(Npix_new < Npix)
|
||||
img_new = img_0(pROI{:},:);
|
||||
else
|
||||
if all(abs(pos) <= 1) && all( Npix_new == Npix)
|
||||
img_new = img_0; % for tiny shift reuse the original array
|
||||
else
|
||||
img_new = ones([Npix_new,Nimgs], 'like', img_0 )*default_val;
|
||||
end
|
||||
img_new(oROI{:}, :) = img_0(pROI{:}, :);
|
||||
end
|
||||
end
|
||||
|
||||
function [oROI, pROI, oROI_, pROI_] = find_ROI( position, Nobj_new, Nobj_0 )
|
||||
|
||||
oROI = cell(2,1);
|
||||
pROI = cell(2,1);
|
||||
|
||||
pos = round(position([2,1]));
|
||||
%% correction for odd size of the Nobj_new
|
||||
pos = pos - mod(Nobj_0-Nobj_new,2) .* (Nobj_new > Nobj_0);
|
||||
oROI_ = zeros(2);
|
||||
pROI_ = zeros(2);
|
||||
for dim = 1:2
|
||||
range_0 = round(pos(dim) + [1,Nobj_0(dim)] - Nobj_0(dim)/2 + Nobj_new(dim)/2);
|
||||
oROI_(dim,:) = min(max(1,range_0), Nobj_new(dim));
|
||||
l = oROI_(dim,2) - oROI_(dim,1) +1;
|
||||
p1 = min(Nobj_0(dim), Nobj_0(dim) - (range_0(2) - Nobj_new(dim)));
|
||||
pROI_(dim,1) = p1 - l+1;
|
||||
pROI_(dim,2) = p1;
|
||||
if pROI_(dim,1) < pROI_(dim,2)
|
||||
pROI{dim} = pROI_(dim,1):pROI_(dim,2);
|
||||
else
|
||||
pROI{dim} = [];
|
||||
end
|
||||
if oROI_(dim,1) < oROI_(dim,2)
|
||||
oROI{dim} = oROI_(dim,1):oROI_(dim,2);
|
||||
else
|
||||
oROI{dim} = [];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function shift_mat = make_shift(shift)
|
||||
|
||||
x = shift(2); % correction on pixel position
|
||||
y = shift(1);
|
||||
N = max(1, ceil(abs([x,y])));
|
||||
x = x+N(1);
|
||||
y = y+N(2);
|
||||
dx = x-floor(x);
|
||||
dy = y-floor(y);
|
||||
|
||||
|
||||
w(1) = dx * dy;
|
||||
w(2) = (1-dx) * dy;
|
||||
w(3) = dx * (1-dy);
|
||||
w(4) = (1-dx) * (1-dy);
|
||||
|
||||
ix = 1+floor(x);
|
||||
iy = 1+floor(y);
|
||||
|
||||
shift_mat = zeros(2*N+1);
|
||||
shift_mat(ix, iy) = w(4);
|
||||
shift_mat(ix+1, iy) = w(3);
|
||||
shift_mat(ix, iy+1) = w(2);
|
||||
shift_mat(ix+1, iy+1) = w(1);
|
||||
end
|
||||
@@ -0,0 +1,114 @@
|
||||
% IMSHIFT_FFT will apply shift with subpixel accuracy that can be different for each frame.
|
||||
%
|
||||
% img = imshift_fft(img, x,y, apply_fft = true, weights = [])
|
||||
%
|
||||
% Inputs:
|
||||
% **img - input image stack, can be complex valued
|
||||
% **x, y - shifts in number of pixels
|
||||
% **apply_fft , if false, then images will be assumed to be in fourier space
|
||||
% **weights - 0<W<=1 apply importance weighting to avoid noise in low reliability regions
|
||||
% returns:
|
||||
% ++img - shifted image stack
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img = imshift_fft(img, x,y, apply_fft, weights)
|
||||
|
||||
|
||||
if nargin < 3
|
||||
y = x(:,2); % x can be either Nx1 or Nx2 vector
|
||||
x = x(:,1);
|
||||
end
|
||||
if nargin < 4
|
||||
apply_fft = true; % if false, assume that img is already fft transformed
|
||||
end
|
||||
if nargin < 5
|
||||
weights = []; % weights prevents amplitifaction of noise in low reliability regions
|
||||
end
|
||||
if ~isempty(weights) && ~isscalar(weights)
|
||||
eps_ = 1e2*eps(ones(1,'like',img));
|
||||
weights = max(eps_, weights); % avoid dividing by zero
|
||||
end
|
||||
|
||||
if all(x==0) && all(y==0)
|
||||
return
|
||||
end
|
||||
|
||||
if ~isempty(weights) && ~isscalar(weights) && apply_fft
|
||||
img = img .* weights;
|
||||
end
|
||||
|
||||
if all(x==0) % shift only along one axis -> faster
|
||||
img = utils.imshift_fft_ax(img, y,1, apply_fft);
|
||||
elseif all(y==0)
|
||||
img = utils.imshift_fft_ax(img, x,2, apply_fft);
|
||||
else
|
||||
%% 2D FFT SHIFTING
|
||||
real_img = isreal(img);
|
||||
Np = size(img);
|
||||
|
||||
|
||||
if apply_fft
|
||||
img = math.fft2_partial(img);
|
||||
end
|
||||
|
||||
xgrid = ifftshift(-fix(Np(2)/2):ceil(Np(2)/2)-1)/Np(2);
|
||||
X = reshape((x(:)*xgrid)',1,Np(2),[]);
|
||||
X = exp((-2i*pi)*X);
|
||||
img = bsxfun(@times, img,X);
|
||||
ygrid = ifftshift(-fix(Np(1)/2):ceil(Np(1)/2)-1)/Np(1);
|
||||
Y = reshape((y(:)*ygrid)',Np(1),1,[]);
|
||||
Y = exp((-2i*pi)*Y);
|
||||
img = bsxfun(@times, img,Y);
|
||||
|
||||
if apply_fft
|
||||
img = math.ifft2_partial(img);
|
||||
end
|
||||
if real_img
|
||||
img = real(img);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if ~isempty(weights) && ~isscalar(weights) && apply_fft
|
||||
weights = utils.imshift_fft(weights, x,y); %% weights needs to be shifted as well
|
||||
img = img ./ weights;
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,105 @@
|
||||
% IMSHIFT_FFT_AX will apply subpixel shift that can be different for each
|
||||
% frame along one dimension only
|
||||
% If apply_fft == false, then images will be assumed to be in fourier space
|
||||
%
|
||||
% Inputs:
|
||||
% **img - inputs ndim array to be shifted along ax-th dimension
|
||||
% **ax - axis along which the array will be shifted
|
||||
% **shift - Nx1 vector of shifts, positive direction is up
|
||||
% **apply_fft = false - if the img is already after fft, default is false
|
||||
% *returns*:
|
||||
% ++img - shifted image / volume
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img = imshift_fft_ax(img, shift, ax, apply_fft)
|
||||
|
||||
|
||||
if nargin < 4
|
||||
apply_fft = true;
|
||||
end
|
||||
if all(shift == 0)
|
||||
return
|
||||
end
|
||||
|
||||
isReal = isreal(img);
|
||||
|
||||
Npix = size(img);
|
||||
|
||||
if ndims(img) == 3
|
||||
Np = [1,1,Npix(3)];
|
||||
else
|
||||
Np = Npix;
|
||||
Np(ax) = 1;
|
||||
end
|
||||
|
||||
Ng = ones(1,3);
|
||||
if ax > ndims(img)
|
||||
Npix(ax) = 1;
|
||||
end
|
||||
|
||||
Ng(ax) = Npix(ax);
|
||||
|
||||
|
||||
|
||||
|
||||
if isscalar(shift)
|
||||
shift = shift .* ones(Np);
|
||||
end
|
||||
|
||||
grid = ifftshift(-fix(Npix(ax)/2):ceil(Npix(ax)/2)-1)/Npix(ax);
|
||||
|
||||
X = bsxfun(@times, reshape(shift,Np), reshape(grid,Ng));
|
||||
X = exp((-2i*pi)*X);
|
||||
|
||||
|
||||
if apply_fft
|
||||
img = math.fft_partial(img, ax, 1+mod(ax, ndims(img)) );
|
||||
end
|
||||
|
||||
img = bsxfun(@times, img,X);
|
||||
|
||||
if apply_fft
|
||||
img = math.ifft_partial(img, ax, 1+mod(ax, ndims(img)) );
|
||||
end
|
||||
|
||||
if isReal
|
||||
img = real(img);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
% IMSHIFT_LINEAR will apply shift that can be different for
|
||||
% each frame.
|
||||
% + compared to imshift_fft, it does not have periodic boundary
|
||||
% + it is based on linear interpolation, so it can be run fast on GPU
|
||||
% + integer shift is equivalent to imshift_fft (up to the boundary condition)
|
||||
% - it needs for-loop for each frame -> it gets slow on GPU for
|
||||
% shifting my small images. In that case imshift_fft can be faster.
|
||||
%
|
||||
% img = imshift_linear(img, x,y, method)
|
||||
%
|
||||
% Inputs:
|
||||
% **img input image / stack of images
|
||||
% **x applied shift or vector of shifts for each frame
|
||||
% **y applied shift or vector of shifts for each frame
|
||||
% **method choose interpolation method: nearest, {linear}, cubic , circ
|
||||
%
|
||||
% *returns*:
|
||||
% ++img shifted image / stack of images
|
||||
%
|
||||
% see also: utils.imshift_fast, utils.imshift_fft
|
||||
|
||||
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img = imshift_linear(img, x,y, method)
|
||||
|
||||
|
||||
if nargin < 3
|
||||
y = x(:,2);
|
||||
x = x(:,1);
|
||||
end
|
||||
if nargin < 4
|
||||
method = 'linear';
|
||||
end
|
||||
|
||||
if all(x==0) && all(y==0)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
real_img = isreal(img);
|
||||
[Nx, Ny,Nlayers] = size(img);
|
||||
|
||||
if isscalar(x)
|
||||
x = ones(Nlayers,1) * x;
|
||||
end
|
||||
if isscalar(y)
|
||||
y = ones(Nlayers,1) * y;
|
||||
end
|
||||
|
||||
if strcmpi(method, 'circ')
|
||||
% perform fast shift with circular boundary condition
|
||||
X = 1:Nx;
|
||||
Y = 1:Ny;
|
||||
for ii = 1:Nlayers
|
||||
img(:,:,ii) = img(circshift(X,round(y(ii))), ...
|
||||
circshift(Y,round(x(ii))),ii);
|
||||
end
|
||||
else
|
||||
|
||||
for ii = 1:Nlayers
|
||||
%x(ii)
|
||||
%y(ii)
|
||||
img(:,:,ii) = interp2(single(img(:,:,ii)), single(-x(ii)+(1:Ny)),single(-y(ii)+(1:Nx)'), method,0);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,109 @@
|
||||
% IMSHIFT_LINEAR_AX will apply shift that can be different for
|
||||
% each frame along axis ax
|
||||
% + compared to imshift_fft, it does not have periodic boundary
|
||||
% + it is based on linear interpolation, so it can be run fast on GPU
|
||||
% + integer shift is equivalent to imshift_fft (up to the boundary condition)
|
||||
% - it needs for-loop for each frame -> it gets slow on GPU for
|
||||
% shifting my small images. In that case imshift_fft can be faster.
|
||||
%
|
||||
% img = imshift_linear(img, x,y, method)
|
||||
%
|
||||
% Inputs:
|
||||
% **img input image / stack of images
|
||||
% **shift applied shift or vector of shifts for each frame
|
||||
% **ax axis along which the shift will be performed
|
||||
% **method choose interpolation method: nearest, {linear}, cubic , circ
|
||||
% **extrap_val filling value for the missing regions after interpolation (default=nan)
|
||||
%
|
||||
% returns:
|
||||
% ++img shifted image / stack of images
|
||||
%
|
||||
% see also: utils.imshift_fast, utils.imshift_fft
|
||||
|
||||
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img_out = imshift_linear_ax(img, shift, ax, method, extrap_val)
|
||||
|
||||
|
||||
if nargin < 4
|
||||
method = 'linear';
|
||||
end
|
||||
if nargin < 5
|
||||
extrap_val = nan;
|
||||
end
|
||||
|
||||
if all(shift == 0)
|
||||
img_out=img;
|
||||
return
|
||||
end
|
||||
|
||||
Npix = size(img);
|
||||
|
||||
img = single(img);
|
||||
|
||||
img = shiftdim(img, ax-1);
|
||||
|
||||
img_out = img;
|
||||
|
||||
|
||||
ind = {':',':',':'}; % assume max 3 dim
|
||||
ax_0 = 1+mod(ax,ndims(img)); % fixed axis
|
||||
|
||||
if strcmpi(method, 'circ')
|
||||
% apply NN shift with circular condition
|
||||
for i = 1:Npix(ax_0)
|
||||
ind{ax_0} = i;
|
||||
img_out(ind{:}) = circshift(img(ind{:}), round(shift(i)), ax);
|
||||
end
|
||||
else
|
||||
|
||||
for ii = 1:Npix(ax_0)
|
||||
ind{ax_0} = ii;
|
||||
img_out(ind{:}) = interp1(1:size(img,1), img(ind{:}), -shift(ii)+(1:size(img,1)), method, extrap_val);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
img_out = shiftdim(img_out, ax-1);
|
||||
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,69 @@
|
||||
% INTERP3_GPU - fast texture-based GPU based interpolation method for 3D deformation
|
||||
% input array is deformated gived X,Y,Z deformation vector fields
|
||||
%
|
||||
% array = interp3_gpu(array, DVF_X, DVF_Y, DVF_Z)
|
||||
%
|
||||
% Inputs:
|
||||
% **array volume to be deformed
|
||||
% **DVF_X deformation field in X direction
|
||||
% **DVF_Y deformation field in Y direction
|
||||
% **DVF_Z deformation field in Z direction
|
||||
% Outputs:
|
||||
% ++array deformed volume
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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) 2018 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 array = interp3_gpu(array, DVF_X, DVF_Y, DVF_Z)
|
||||
|
||||
|
||||
% apply 3D deformation using GPU textures
|
||||
try
|
||||
array = interp3_gpu(array, DVF_X, DVF_Y, DVF_Z);
|
||||
catch err
|
||||
if strcmpi(err.identifier, 'MATLAB:mex:ErrInvalidMEXFile')
|
||||
% recompile the MEX code
|
||||
path = replace(mfilename('fullpath'), mfilename, '');
|
||||
mexcuda('-output', fullfile(path,'private/interp3_gpu_ker'), fullfile(path, 'private/interp3_gpu_ker.cu'))
|
||||
array = interp3_gpu(array, DVF_X, DVF_Y, DVF_Z);
|
||||
else
|
||||
rethrow(err)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,69 @@
|
||||
% INTERPOLATEFT Computes 2D interpolated image using Fourier transform, i.e. dirichlet
|
||||
% interpolation. Computes the FT and then adjusts the size by zero padding
|
||||
% or cropping then it computes the IFT. A real valued input may have
|
||||
% residual imaginary components, which is given by numerical precision of
|
||||
% the FT and IFT.
|
||||
%
|
||||
% imout = interpolateFT(im,outsize,ax)
|
||||
%
|
||||
% Inputs:
|
||||
% **im - Input complex array
|
||||
% **outsize - Output size of array [N pixels]
|
||||
% **ax - index of axis along which interpolation is done
|
||||
%
|
||||
% *returns*:
|
||||
% ++imout - Output complex image
|
||||
%
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ imout ] = interpolateFT(im,outsize)
|
||||
import math.fftshift_2D
|
||||
import math.ifftshift_2D
|
||||
import utils.crop_pad
|
||||
|
||||
|
||||
Nout = outsize;
|
||||
Nin = size(im);
|
||||
|
||||
imFT = fftshift_2D(fft2(im));
|
||||
|
||||
imout = crop_pad(imFT, outsize);
|
||||
|
||||
imout = ifft2(ifftshift_2D(imout))*(Nout(1)*Nout(2)/(Nin(1)*Nin(2)));
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
% INTERPOLATEFT_3D Computes 3D interpolated image using Fourier transform, i.e. dirichlet
|
||||
% interpolation. Computes the FT and then adjusts the size by zero padding
|
||||
% or cropping then it computes the IFT. A real valued input may have
|
||||
% residual imaginary components, which is given by numerical precision of
|
||||
% the FT and IFT.
|
||||
%
|
||||
% imout = interpolateFT_3D(im,outsize, fourier_mask)
|
||||
%
|
||||
% Inputs
|
||||
% **im - Input real/complex 3D volume
|
||||
% **outsize - Output size of array [ny nx nz]
|
||||
% **fourier_mask - if provided, apply mask in fourier space. ifftn( mask * fftn(im))
|
||||
% *returns*
|
||||
% ++imout - Output real/complex volume
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ imout ] = interpolateFT_3D(im,outsize, fourier_mask)
|
||||
|
||||
Nout = outsize;
|
||||
Nin = size(im);
|
||||
|
||||
if all(Nout == Nin) && nargin < 3
|
||||
imout = im;
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
imFT = fftshift(fftn(im));
|
||||
|
||||
imout = utils.crop_pad_3D(imFT, outsize);
|
||||
|
||||
if nargin > 2
|
||||
% if provided, apply fourier mask, NOT FFTSHIFTED !!
|
||||
imout = imout .* fourier_mask;
|
||||
end
|
||||
|
||||
imout = ifftn(ifftshift(imout))*(Nout(1)*Nout(2)*Nout(3)/(Nin(1)*Nin(2)*Nin(3)));
|
||||
|
||||
if isreal(im)
|
||||
imout = real(imout);
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
% INTERPOLATEFT_AX Computes interpolated array using 1D Fourier transform, i.e. dirichlet
|
||||
% interpolation along single axis. Computes the FT and then adjusts the size by zero padding
|
||||
% or cropping then it computes the IFT. A real valued input may have
|
||||
% residual imaginary components, which is given by numerical precision of
|
||||
% the FT and IFT.
|
||||
%
|
||||
% imout = interpolateFT_ax(im,outsize,ax, use_fft)
|
||||
%
|
||||
% Inputs:
|
||||
% **im - Input complex array
|
||||
% **outsize - Output size of array [N pixels]
|
||||
% **ax - index of axis along which interpolation is done
|
||||
% *optional*
|
||||
% **use_fft - if false, assume that im is already fft-transformed, default = true
|
||||
%
|
||||
% Outputs:
|
||||
% ++imout - Output complex image
|
||||
%
|
||||
% Example:
|
||||
% x = randn(10,20,30);
|
||||
% x_int = utils.interpolateFT_ax(x, 10, 3) % downsample to 10 pixels along 3rd axis
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ imout ] = interpolateFT_ax(im,outsize,ax, use_fft)
|
||||
|
||||
Nin = size(im);
|
||||
if ax > ndims(im)
|
||||
Nin(ax) = 1;
|
||||
end
|
||||
if nargin < 4
|
||||
use_fft = true;
|
||||
end
|
||||
|
||||
Nout = Nin;
|
||||
Nout(ax) = outsize;
|
||||
|
||||
if use_fft
|
||||
imFT = fft(im,[],ax);
|
||||
else
|
||||
imFT = im;
|
||||
end
|
||||
|
||||
centerin = floor(Nin(ax)/2)+1;
|
||||
centerout = floor(Nout(ax)/2)+1;
|
||||
|
||||
center_diff = centerout - centerin;
|
||||
|
||||
|
||||
grid_in = fftshift(1:Nin(ax));
|
||||
grid_in = grid_in(max(-center_diff+1,1):min(-center_diff+Nout(ax),Nin(ax)));
|
||||
grid_in = {grid_in,':',':',':'};
|
||||
grid_in = circshift( grid_in, ax-1);
|
||||
|
||||
grid_out = [max(ceil(Nout(ax)/2)+1,Nout(ax) - centerin+2):Nout(ax), ...
|
||||
1:min(centerin-1, ceil(Nout(ax)/2))];
|
||||
grid_out = {grid_out,':',':',':'};
|
||||
grid_out = circshift( grid_out, ax-1);
|
||||
|
||||
|
||||
|
||||
if Nout(ax) > Nin(ax)
|
||||
% perform multiplication to keep average values,
|
||||
% multiply the smaller array to save time
|
||||
imFT = imFT*(Nout(ax)/(Nin(ax)));
|
||||
end
|
||||
|
||||
imout = zeros(Nout,'like',im);
|
||||
imout(grid_out{:}) = imFT(grid_in{:});
|
||||
|
||||
|
||||
if use_fft
|
||||
imout = ifft(imout,[],ax);
|
||||
end
|
||||
|
||||
if Nout(ax) < Nin(ax)
|
||||
% perform multiplication to keep average values,
|
||||
% multiply the smaller array to save time
|
||||
imout = imout*(Nout(ax)/(Nin(ax)));
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,93 @@
|
||||
% INTERPOLATEFT_CENTERED Perform FT interpolation of provided stack of images using FFT so that
|
||||
% the center of mass is not modified after the resolution change
|
||||
% This function is critical for subpixel accurate up/down sampling
|
||||
%
|
||||
% imout = interpolateFT_centered(im,downsample,interp_sign)
|
||||
%
|
||||
% Inputs:
|
||||
% **im - Input complex 2D array or stacked 3D array
|
||||
% **Npix_new - (2x1 vector) Size of the interpolated array
|
||||
% **interp_sign - +1 or -1, sign that adds extra 1px shift. +1 is needed
|
||||
% if interpolation is used to downsample phase gradient which is used for
|
||||
% unwrapping, otherwise use -1
|
||||
% *returns*:
|
||||
% ++imout - Output complex image
|
||||
%
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ img ] = interpolateFT_centered(img,Np_new, interp_sign)
|
||||
import utils.*
|
||||
import math.*
|
||||
|
||||
Np = size(img);
|
||||
Np_new = 2+Np_new;
|
||||
isReal = isreal(img);
|
||||
|
||||
scale = prod((Np_new-2)) / prod(Np(1:2));
|
||||
downsample = ceil(sqrt(1/scale));
|
||||
|
||||
if isa(img, 'gpuArray')
|
||||
scale = Garray(scale);
|
||||
end
|
||||
% apply the padding to account for boundary issues
|
||||
img = padarray(img, double([downsample,downsample]), 'symmetric' ,'both');
|
||||
|
||||
% go to the fourier space
|
||||
img = fft2(img);
|
||||
|
||||
% apply +/-0.5 px shift
|
||||
img = imshift_fft(img, interp_sign*-0.5, interp_sign*-0.5, false);
|
||||
|
||||
% crop in the Fourier space (can be speeded up similarly to example in utils.interpolateFT_ax )
|
||||
img = ifftshift_2D(crop_pad(fftshift_2D(img), Np_new));
|
||||
|
||||
% apply -/+0.5 px shift in the cropped space
|
||||
img = imshift_fft(img, interp_sign*0.5, interp_sign*0.5, false);
|
||||
|
||||
% return to the real space
|
||||
img = ifft2(img);
|
||||
|
||||
% scale to keep the average constant
|
||||
img = img*scale;
|
||||
|
||||
% remove the padding
|
||||
img = img(2:end-1, 2:end-1,:);
|
||||
|
||||
if isReal
|
||||
img = real(img); % preserve complexity
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,69 @@
|
||||
% INTERPOLATE_LINEAR rescaling based on interp2, faster than utils.interpolateFT,
|
||||
% works also with GPU
|
||||
% Note: for small arrays processed on GPU, utils.interpolateFT can be
|
||||
% faster due to lower overhead (no for-loop)
|
||||
%
|
||||
% img = interpolate_linear(img, scale, method)
|
||||
%
|
||||
% Inputs:
|
||||
% **img - 2D or stack of 2D images
|
||||
% **scale - scaling factor
|
||||
% **method - linear (default), cubic, nearest
|
||||
% *returns*:
|
||||
% ++img_out - 2D or stack of 2D images scaled by factor scale
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 img_out = interpolate_linear(img, sizeOut, method)
|
||||
|
||||
[Nx, Ny,Nlayers] = size(img);
|
||||
|
||||
if all([Nx,Ny] == sizeOut(1:2))
|
||||
img_out = img;
|
||||
return
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
method = 'linear';
|
||||
end
|
||||
|
||||
img_out = zeros([sizeOut(1:2), Nlayers],'like',img);
|
||||
for ii = 1:Nlayers
|
||||
img_out(:,:,ii) = interp2(img(:,:,ii), linspace(1,Ny,sizeOut(2)),linspace(1,Nx,sizeOut(1))', method);
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
function [mask] = make_circular_mask(N, radius)
|
||||
%Make a circular mask. Made by YJ
|
||||
% N: size of image
|
||||
% radius: radius
|
||||
if length(N)==1
|
||||
x = linspace(-floor(N/2),ceil(N/2)-1,N);
|
||||
y = linspace(-floor(N/2),ceil(N/2)-1,N);
|
||||
else
|
||||
x = linspace(-floor(N(2)/2),ceil(N(2)/2)-1,N(2));
|
||||
y = linspace(-floor(N(1)/2),ceil(N(1)/2)-1,N(1));
|
||||
end
|
||||
[Y, X] = meshgrid(x,y);
|
||||
S = sqrt(X.^2+Y.^2);
|
||||
|
||||
mask = S <= radius;
|
||||
end
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
% MTIMES_STACK Extension of @mtimes function for stacked images and GPU
|
||||
%
|
||||
% C = mtimes_stack(A,B)
|
||||
% returns the propagated wavefield
|
||||
% Inputs:
|
||||
% **A first matrix
|
||||
% **B second matrix
|
||||
% *returns*
|
||||
% ++C product matrix
|
||||
%
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 C = mtimes_stack(A,B)
|
||||
|
||||
if isa(A, 'gpuArray') || isa(B, 'gpuArray')
|
||||
C = pagefun(@mtimes, A,B);
|
||||
return
|
||||
end
|
||||
|
||||
% CPU code
|
||||
if ismatrix(A) && ismatrix(B)
|
||||
C = mtimes(A,B);
|
||||
elseif ismatrix(A) && ndims(B) == 3
|
||||
Np = size(B);
|
||||
C = reshape(A*reshape(B,Np(1),[]), Np);
|
||||
elseif ndims(A) == 3 && ismatrix(B)
|
||||
Np = size(A);
|
||||
fdims = 1:ndims(A);
|
||||
fdims(1:2) = [2,1];
|
||||
C = permute(reshape(B*reshape(permute(A,fdims),Np(2),[]),Np(fdims)),fdims);
|
||||
else
|
||||
C = zeros(size(A,1), size(B,2), size(B,3), 'like', A);
|
||||
for ii = 1:size(B,3)
|
||||
C(:,:,ii) = A(:,:,ii) * B(:,:,ii);
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
classdef onCleanup < handle
|
||||
%ONCLEANUP - modified MATLAB class
|
||||
%
|
||||
% EXAMPLES:
|
||||
% %% cleanup function with no arguments %%
|
||||
% 1.) define cleanup routine:
|
||||
% function cleanexit()
|
||||
% fprintf('Reconstruction stopped!')
|
||||
% end
|
||||
%
|
||||
% 2.) get instance of onCleanup:
|
||||
% finishup = utils.onCleanup(@() cleanexit());
|
||||
%
|
||||
% %% cleanup function with one or more arguments
|
||||
% 1.) define cleanup routine:
|
||||
% function cleanexit(p)
|
||||
% if ~p.getReport.completed
|
||||
% fprintf('Reconstruction stopped!')
|
||||
% end
|
||||
% end
|
||||
%
|
||||
% 2.) get instance of onCleanup:
|
||||
% finishup = utils.onCleanup(p, @(x) cleanexit(x));
|
||||
%
|
||||
% 3.) if needed, update parameters that are passed to your cleanup
|
||||
% function:
|
||||
% finishup.update(p);
|
||||
%
|
||||
%
|
||||
%
|
||||
%
|
||||
%onCleanup - Specify cleanup work to be done on function completion.
|
||||
% C = onCleanup(S), when called in function F, specifies any cleanup tasks
|
||||
% that need to be performed when F completes. S is a handle to a function
|
||||
% that performs necessary cleanup work when F exits (e.g., closing files that
|
||||
% have been opened by F). S will be called whether F exits normally or
|
||||
% because of an error.
|
||||
%
|
||||
% onCleanup is a MATLAB class and C = onCleanup(S) constructs an instance C of
|
||||
% that class. Whenever an object of this class is explicitly or implicitly
|
||||
% cleared from the workspace, it runs the cleanup function, S. Objects that
|
||||
% are local variables in a function are implicitly cleared at the termination
|
||||
% of that function.
|
||||
%
|
||||
% Example 1: Use onCleanup to close a file.
|
||||
%
|
||||
% function fileOpenSafely(fileName)
|
||||
% fid = fopen(fileName, 'w');
|
||||
% c = onCleanup(@()fclose(fid));
|
||||
%
|
||||
% functionThatMayError(fid);
|
||||
% end % c will execute fclose(fid) here
|
||||
%
|
||||
%
|
||||
% Example 2: Use onCleanup to restore the current directory.
|
||||
%
|
||||
% function changeDirectorySafely(fileName)
|
||||
% currentDir = pwd;
|
||||
% c = onCleanup(@()cd(currentDir));
|
||||
%
|
||||
% functionThatMayError;
|
||||
% end % c will execute cd(currentDir) here
|
||||
%
|
||||
% See also: CLEAR, CLEARVARS
|
||||
|
||||
% Copyright 2007-2012 The MathWorks, Inc.
|
||||
|
||||
properties(SetAccess = 'public', GetAccess = 'public', Transient)
|
||||
task = @nop;
|
||||
prop = [];
|
||||
end
|
||||
|
||||
methods
|
||||
function h = onCleanup(functionHandle, varargin)
|
||||
% onCleanup - Create a ONCLEANUP object
|
||||
% C = ONCLEANUP(FUNC) creates C, a ONCLEANUP object. There is no need to
|
||||
% further interact with the variable, C. It will execute FUNC at the time it
|
||||
% is cleared.
|
||||
%
|
||||
% See also: CLEAR, ONCLEANUP
|
||||
if ~isempty(varargin)
|
||||
h.prop = varargin;
|
||||
end
|
||||
h.task = functionHandle;
|
||||
end
|
||||
|
||||
function update(h, varargin)
|
||||
h.prop = varargin;
|
||||
end
|
||||
|
||||
function delete(h)
|
||||
% DELETE - Delete a ONCLEANUP object.
|
||||
% DELETE does not need to be called directly, as it is called when the
|
||||
% ONCLEANUP object is cleared. DELETE is implicitly called for all ONCLEANUP
|
||||
% objects that are local variables in a function that terminates.
|
||||
%
|
||||
% See also: CLEAR, ONCLEANUP, ONCLEANUP/ONCLEANUP
|
||||
if ~isempty(h.prop)
|
||||
h.task(h.prop{:});
|
||||
else
|
||||
h.task();
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function nop
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
% pad_2D pads a 2D array (in both direction). It's based on Matlab's padarray function
|
||||
% Inputs:
|
||||
% **img input image
|
||||
% **outsize size of final image
|
||||
% *optional:*
|
||||
% **padval value to fill padded regions
|
||||
% returns:
|
||||
% ++imout cropped image
|
||||
% Written by YJ
|
||||
|
||||
function [ imout ] = pad_2D( img, outsize, padval)
|
||||
|
||||
Nin = size(img);
|
||||
Nout = outsize(1:2);
|
||||
|
||||
if Nout(1)<Nin(1) || Nout(2)<Nin(2)
|
||||
disp(size(img))
|
||||
error('Output size is smaller than input image!')
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
padval = 0;
|
||||
end
|
||||
|
||||
pad_pre = [0,0];
|
||||
pad_post = [0,0];
|
||||
%calculate how much to pad
|
||||
if mod(Nin(1),2)==0 %if input image size is even
|
||||
pad_post(1) = ceil((Nout(1)-Nin(1))/2);
|
||||
pad_pre(1) = floor((Nout(1)-Nin(1))/2);
|
||||
else %odd
|
||||
pad_post(1) = floor((Nout(1)-Nin(1))/2);
|
||||
pad_pre(1) = ceil((Nout(1)-Nin(1))/2);
|
||||
end
|
||||
|
||||
if mod(Nin(2),2)==0 %if input image size is even
|
||||
pad_post(2) = ceil((Nout(2)-Nin(2))/2);
|
||||
pad_pre(2) = floor((Nout(2)-Nin(2))/2);
|
||||
else %odd
|
||||
pad_post(2) = floor((Nout(2)-Nin(2))/2);
|
||||
pad_pre(2) = ceil((Nout(2)-Nin(2))/2);
|
||||
end
|
||||
|
||||
%imout = padarray(img, [(Nout(1)-Nin(1))/2, (Nout(2)-Nin(2))/2],padval);
|
||||
|
||||
|
||||
imout = padarray(img, pad_pre,padval,'pre');
|
||||
imout = padarray(imout, pad_post,padval,'post');
|
||||
|
||||
if ~isreal(img)
|
||||
imout = complex(imout);
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,111 @@
|
||||
%%PARAM_PROTECT_FIELD
|
||||
% param_protect_field(param)... check for protected field; returns
|
||||
% boolean
|
||||
%
|
||||
% accepts struct or string as input
|
||||
%
|
||||
% param_protect_field()... return protected fields
|
||||
%
|
||||
% param_protect_field(param, 'p')... add param to protected fields
|
||||
%
|
||||
% param_protect_field(param, 'r')... remove param from protected fields
|
||||
%
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [varout] = param_protect_field(varargin)
|
||||
|
||||
persistent prot_field
|
||||
|
||||
if nargin == 0
|
||||
if isempty(prot_field)
|
||||
varout = [];
|
||||
elseif isempty(fieldnames(prot_field))
|
||||
varout = [];
|
||||
else
|
||||
varout = fieldnames(prot_field);
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if nargin == 1
|
||||
|
||||
if isstruct(varargin{1})
|
||||
fn = fieldnames(varargin{1});
|
||||
for ii=1:length(fn)
|
||||
varout{ii} = isfield(prot_field, fn{ii});
|
||||
end
|
||||
elseif ischar(varargin{1})
|
||||
varout{1} = isfield(prot_field,varargin{1});
|
||||
end
|
||||
|
||||
elseif nargin == 2
|
||||
|
||||
if strcmp(varargin{2},'p')
|
||||
% protect fields
|
||||
prot_field.(varargin{1}) = true;
|
||||
|
||||
elseif strcmp(varargin{2}, 'r')
|
||||
% remove protected fields
|
||||
if isstruct(varargin{1})
|
||||
fn = fieldnames(varargin{1});
|
||||
for ii=1:length(fn)
|
||||
try
|
||||
prot_field = rmfield(prot_field,fn{ii});
|
||||
catch
|
||||
fprintf('Could not find protected field %s\n', fn{ii});
|
||||
end
|
||||
end
|
||||
|
||||
elseif ischar(varargin{1})
|
||||
try
|
||||
prot_field = rmfield(prot_field,varargin{1});
|
||||
catch
|
||||
fprintf('Could not find protected field %s\n', varargin{1});
|
||||
end
|
||||
end
|
||||
else
|
||||
error('Unknown second argument %s. Please use ''p'' to protect and ''r'' to remove %s from protected fields.', varargin{2}, varargin{1})
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if isempty(prot_field)
|
||||
varout = [];
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
%PEAKFINDER Noise tolerant fast peak finding algorithm
|
||||
% INPUTS:
|
||||
% x0 - A real vector from the maxima will be found (required)
|
||||
% sel - The amount above surrounding data for a peak to be
|
||||
% identified (default = (max(x0)-min(x0))/4). Larger values mean
|
||||
% the algorithm is more selective in finding peaks.
|
||||
% thresh - A threshold value which peaks must be larger than to be
|
||||
% maxima or smaller than to be minima.
|
||||
% extrema - 1 if maxima are desired, -1 if minima are desired
|
||||
% (default = maxima, 1)
|
||||
% OUTPUTS:
|
||||
% peakLoc - The indicies of the identified peaks in x0
|
||||
% peakMag - The magnitude of the identified peaks
|
||||
%
|
||||
% [peakLoc] = peakfinder(x0) returns the indicies of local maxima that
|
||||
% are at least 1/4 the range of the data above surrounding data.
|
||||
%
|
||||
% [peakLoc] = peakfinder(x0,sel) returns the indicies of local maxima
|
||||
% that are at least sel above surrounding data.
|
||||
%
|
||||
% [peakLoc] = peakfinder(x0,sel,thresh) returns the indicies of local
|
||||
% maxima that are at least sel above surrounding data and larger
|
||||
% (smaller) than thresh if you are finding maxima (minima).
|
||||
%
|
||||
% [peakLoc] = peakfinder(x0,sel,thresh,extrema) returns the maxima of the
|
||||
% data if extrema > 0 and the minima of the data if extrema < 0
|
||||
%
|
||||
% [peakLoc, peakMag] = peakfinder(x0,...) returns the indicies of the
|
||||
% local maxima as well as the magnitudes of those maxima
|
||||
%
|
||||
% If called with no output the identified maxima will be plotted along
|
||||
% with the input data.
|
||||
%
|
||||
% Note: If repeated values are found the first is identified as the peak
|
||||
%
|
||||
% Ex:
|
||||
% t = 0:.0001:10;
|
||||
% x = 12*sin(10*2*pi*t)-3*sin(.1*2*pi*t)+randn(1,numel(t));
|
||||
% x(1250:1255) = max(x);
|
||||
% peakfinder(x)
|
||||
%
|
||||
% Copyright Nathanael C. Yoder 2011 (nyoder@gmail.com)
|
||||
|
||||
% Copyright (c) 2011, Nathanael C. Yoder
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function varargout = peakfinder(x0, sel, thresh, extrema)
|
||||
|
||||
% Perform error checking and set defaults if not passed in
|
||||
error(nargchk(1,4,nargin,'struct'));
|
||||
error(nargoutchk(0,2,nargout,'struct'));
|
||||
|
||||
s = size(x0);
|
||||
flipData = s(1) < s(2);
|
||||
len0 = numel(x0);
|
||||
if len0 ~= s(1) && len0 ~= s(2)
|
||||
error('PEAKFINDER:Input','The input data must be a vector')
|
||||
elseif isempty(x0)
|
||||
varargout = {[],[]};
|
||||
return;
|
||||
end
|
||||
if ~isreal(x0)
|
||||
warning('PEAKFINDER:NotReal','Absolute value of data will be used')
|
||||
x0 = abs(x0);
|
||||
end
|
||||
|
||||
if nargin < 2 || isempty(sel)
|
||||
sel = (max(x0)-min(x0))/4;
|
||||
elseif ~isnumeric(sel) || ~isreal(sel)
|
||||
sel = (max(x0)-min(x0))/4;
|
||||
warning('PEAKFINDER:InvalidSel',...
|
||||
'The selectivity must be a real scalar. A selectivity of %.4g will be used',sel)
|
||||
elseif numel(sel) > 1
|
||||
warning('PEAKFINDER:InvalidSel',...
|
||||
'The selectivity must be a scalar. The first selectivity value in the vector will be used.')
|
||||
sel = sel(1);
|
||||
end
|
||||
|
||||
if nargin < 3 || isempty(thresh)
|
||||
thresh = [];
|
||||
elseif ~isnumeric(thresh) || ~isreal(thresh)
|
||||
thresh = [];
|
||||
warning('PEAKFINDER:InvalidThreshold',...
|
||||
'The threshold must be a real scalar. No threshold will be used.')
|
||||
elseif numel(thresh) > 1
|
||||
thresh = thresh(1);
|
||||
warning('PEAKFINDER:InvalidThreshold',...
|
||||
'The threshold must be a scalar. The first threshold value in the vector will be used.')
|
||||
end
|
||||
|
||||
if nargin < 4 || isempty(extrema)
|
||||
extrema = 1;
|
||||
else
|
||||
extrema = sign(extrema(1)); % Should only be 1 or -1 but make sure
|
||||
if extrema == 0
|
||||
error('PEAKFINDER:ZeroMaxima','Either 1 (for maxima) or -1 (for minima) must be input for extrema');
|
||||
end
|
||||
end
|
||||
|
||||
x0 = extrema*x0(:); % Make it so we are finding maxima regardless
|
||||
thresh = thresh*extrema; % Adjust threshold according to extrema.
|
||||
dx0 = diff(x0); % Find derivative
|
||||
dx0(dx0 == 0) = -eps; % This is so we find the first of repeated values
|
||||
ind = find(dx0(1:end-1).*dx0(2:end) < 0)+1; % Find where the derivative changes sign
|
||||
|
||||
% Include endpoints in potential peaks and valleys
|
||||
x = [x0(1);x0(ind);x0(end)];
|
||||
ind = [1;ind;len0];
|
||||
|
||||
% x only has the peaks, valleys, and endpoints
|
||||
len = numel(x);
|
||||
minMag = min(x);
|
||||
|
||||
|
||||
if len > 2 % Function with peaks and valleys
|
||||
|
||||
% Set initial parameters for loop
|
||||
tempMag = minMag;
|
||||
foundPeak = false;
|
||||
leftMin = minMag;
|
||||
|
||||
% Deal with first point a little differently since tacked it on
|
||||
% Calculate the sign of the derivative since we taked the first point
|
||||
% on it does not neccessarily alternate like the rest.
|
||||
signDx = sign(diff(x(1:3)));
|
||||
if signDx(1) <= 0 % The first point is larger or equal to the second
|
||||
ii = 0;
|
||||
if signDx(1) == signDx(2) % Want alternating signs
|
||||
x(2) = [];
|
||||
ind(2) = [];
|
||||
len = len-1;
|
||||
end
|
||||
else % First point is smaller than the second
|
||||
ii = 1;
|
||||
if signDx(1) == signDx(2) % Want alternating signs
|
||||
x(1) = [];
|
||||
ind(1) = [];
|
||||
len = len-1;
|
||||
end
|
||||
end
|
||||
|
||||
% Preallocate max number of maxima
|
||||
maxPeaks = ceil(len/2);
|
||||
peakLoc = zeros(maxPeaks,1);
|
||||
peakMag = zeros(maxPeaks,1);
|
||||
cInd = 1;
|
||||
% Loop through extrema which should be peaks and then valleys
|
||||
while ii < len
|
||||
ii = ii+1; % This is a peak
|
||||
% Reset peak finding if we had a peak and the next peak is bigger
|
||||
% than the last or the left min was small enough to reset.
|
||||
if foundPeak
|
||||
tempMag = minMag;
|
||||
foundPeak = false;
|
||||
end
|
||||
|
||||
% Make sure we don't iterate past the length of our vector
|
||||
if ii == len
|
||||
break; % We assign the last point differently out of the loop
|
||||
end
|
||||
|
||||
% Found new peak that was lager than temp mag and selectivity larger
|
||||
% than the minimum to its left.
|
||||
if x(ii) > tempMag && x(ii) > leftMin + sel
|
||||
tempLoc = ii;
|
||||
tempMag = x(ii);
|
||||
end
|
||||
|
||||
ii = ii+1; % Move onto the valley
|
||||
% Come down at least sel from peak
|
||||
if ~foundPeak && tempMag > sel + x(ii)
|
||||
foundPeak = true; % We have found a peak
|
||||
leftMin = x(ii);
|
||||
peakLoc(cInd) = tempLoc; % Add peak to index
|
||||
peakMag(cInd) = tempMag;
|
||||
cInd = cInd+1;
|
||||
elseif x(ii) < leftMin % New left minima
|
||||
leftMin = x(ii);
|
||||
end
|
||||
end
|
||||
|
||||
% Check end point
|
||||
if x(end) > tempMag && x(end) > leftMin + sel
|
||||
peakLoc(cInd) = len;
|
||||
peakMag(cInd) = x(end);
|
||||
cInd = cInd + 1;
|
||||
elseif ~foundPeak && tempMag > minMag % Check if we still need to add the last point
|
||||
peakLoc(cInd) = tempLoc;
|
||||
peakMag(cInd) = tempMag;
|
||||
cInd = cInd + 1;
|
||||
end
|
||||
|
||||
% Create output
|
||||
peakInds = ind(peakLoc(1:cInd-1));
|
||||
peakMags = peakMag(1:cInd-1);
|
||||
else % This is a monotone function where an endpoint is the only peak
|
||||
[peakMags,xInd] = max(x);
|
||||
if peakMags > minMag + sel
|
||||
peakInds = ind(xInd);
|
||||
else
|
||||
peakMags = [];
|
||||
peakInds = [];
|
||||
end
|
||||
end
|
||||
|
||||
% Apply threshold value. Since always finding maxima it will always be
|
||||
% larger than the thresh.
|
||||
if ~isempty(thresh)
|
||||
m = peakMags>thresh;
|
||||
peakInds = peakInds(m);
|
||||
peakMags = peakMags(m);
|
||||
end
|
||||
|
||||
|
||||
|
||||
% Rotate data if needed
|
||||
if flipData
|
||||
peakMags = peakMags.';
|
||||
peakInds = peakInds.';
|
||||
end
|
||||
|
||||
|
||||
|
||||
% Change sign of data if was finding minima
|
||||
if extrema < 0
|
||||
peakMags = -peakMags;
|
||||
x0 = -x0;
|
||||
end
|
||||
% Plot if no output desired
|
||||
if nargout == 0
|
||||
if isempty(peakInds)
|
||||
disp('No significant peaks found')
|
||||
else
|
||||
figure;
|
||||
plot(1:len0,x0,'.-',peakInds,peakMags,'ro','linewidth',2);
|
||||
end
|
||||
else
|
||||
varargout = {peakInds,peakMags};
|
||||
end
|
||||
@@ -0,0 +1,65 @@
|
||||
% Call function without arguments for instructions on how to use it
|
||||
|
||||
% Filename: $RCSfile: pixel_to_q.m,v $
|
||||
%
|
||||
% $Revision: 1.1 $ $Date: 2008/06/10 17:05:14 $
|
||||
% $Author: $
|
||||
% $Tag: $
|
||||
%
|
||||
% Description:
|
||||
% calculated momentum transfer q in inverse Angstroem from pixel numbers
|
||||
% relative to the beam center
|
||||
%
|
||||
% Dependencies:
|
||||
% none
|
||||
%
|
||||
% history:
|
||||
%
|
||||
% June 9th 2008: 1st documented version
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ q_A ] = pixel_to_q( pixel, pixel_size_mm, det_dist_mm, E_keV )
|
||||
|
||||
if (nargin ~= 4)
|
||||
fprintf('Usage:\n');
|
||||
fprintf('[ q_A ] = %s( pixel, pixel_size_mm, det_dist_mm, E_keV );\n',...
|
||||
mfilename);
|
||||
error('Wrong number of parameters, 4 expected, %d found',nargin);
|
||||
end
|
||||
|
||||
lambda_A = 12.39852 / E_keV;
|
||||
|
||||
q_A = 4*pi * sin( atan(pixel*pixel_size_mm/det_dist_mm) /2) / lambda_A;
|
||||
@@ -0,0 +1,174 @@
|
||||
% [PSD, freq] = power_spectral_density(img, varargin)
|
||||
% Computes the power spectral density of the provided 3D image.
|
||||
% Can handle non-cube arrays but assumes the voxel is isotropic
|
||||
%
|
||||
% Inputs:
|
||||
% img input image (2D or 3D)
|
||||
%
|
||||
% Parameters:
|
||||
% thickring Normally the pixels get assigned to the closest integer pixel ring in Fourier domain.
|
||||
% With thickring the thickness of the rings is increased by
|
||||
% thickring, so each ring gets more pixels and more statistics
|
||||
% auto_binning apply binning if dimensions are significanlty different along each axis
|
||||
% mask bool array equal to false for ignored pixels of the fft space
|
||||
%
|
||||
% Outputs:
|
||||
% PSD PSD curve values
|
||||
% freq normalized spatial frequencies to 1
|
||||
%
|
||||
% Example of use:
|
||||
% img = randn(512,512,512);
|
||||
% utils.power_spectral_density(img, 'thickring', 3);
|
||||
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [PSD, freq] = power_spectral_density(img, air, varargin)
|
||||
import math.isint
|
||||
import utils.*
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%% PROCESS PARAMETERS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
parser = inputParser;
|
||||
parser.addParameter('thickring', 3 , @isnumeric ) % thick ring in Fourier domain
|
||||
parser.addParameter('auto_binning', true , @islogical ) % bin FRC before calculating rings, it makes calculations faster
|
||||
parser.addParameter('max_rings', 200 , @isnumeric ) % maximal number of rings if autobinning is used
|
||||
parser.addParameter('mask', true, @islogical ) % bool array, equal to false for ignored pixels of the fft space
|
||||
parser.addParameter('windowautopos', true, @islogical ) % automatically position plotted window
|
||||
parser.addParameter('figure_id', 101, @isint) % call figure(figure_id)
|
||||
|
||||
|
||||
parser.parse(varargin{:})
|
||||
param = parser.Results;
|
||||
|
||||
|
||||
disp('Calculating PSD');
|
||||
|
||||
% remove masked values from consideration (i.e. for laminography)
|
||||
Fimg = abs(bsxfun(@times,fftn(img) , param.mask+eps)).^2;
|
||||
|
||||
[ny,nx,nz] = size(img);
|
||||
nmin = min(size(img));
|
||||
|
||||
% avoid edge artefacts
|
||||
img = img .* tukeywin(size(img,1),0.5) .* tukeywin(size(img,2),0.5)' .* reshape(tukeywin(size(img,3),0.5),1,1,[]);
|
||||
|
||||
|
||||
thickring = param.thickring;
|
||||
|
||||
if param.auto_binning
|
||||
% bin the correlation values to speed up the following calculations
|
||||
% find optimal binning to make the volumes roughly cubic
|
||||
bin = ceil(thickring/4) * floor(size(img)/ nmin);
|
||||
% avoid too large number of rings
|
||||
bin = max(bin, floor(nmin ./ param.max_rings));
|
||||
|
||||
if any(bin > 1)
|
||||
fprintf('Autobinning %ix%ix%i \n', bin)
|
||||
thickring = ceil(thickring / min(bin));
|
||||
% fftshift and crop the arrays to make their size dividable by binning number
|
||||
if ismatrix(img); bin(3) = 1; end
|
||||
% force the binning to be centered
|
||||
subgrid = {fftshift(ceil(bin(1)/2):(floor(ny/bin(1))*bin(1)-floor(bin(1)/2)-1)), ...
|
||||
fftshift(ceil(bin(2)/2):(floor(nx/bin(2))*bin(2)-floor(bin(2)/2)-1)), ...
|
||||
fftshift(ceil(bin(3)/2):(floor(nz/bin(3))*bin(3)-floor(bin(3)/2)-1))};
|
||||
if ismatrix(img); subgrid(3) = [] ; end
|
||||
% binning makes the shell / ring calculations much faster
|
||||
Fimg = ifftshift(utils.binning_3D(Fimg(subgrid{:}), bin));
|
||||
end
|
||||
else
|
||||
bin = 1;
|
||||
end
|
||||
|
||||
|
||||
[ny,nx,nz] = size(Fimg);
|
||||
nmax = max([nx ny nz]);
|
||||
nmin = min(size(img));
|
||||
|
||||
|
||||
% empirically tested that thickring should be >=3 along the smallest axis to avoid FRC undesampling
|
||||
thickring = max(thickring, ceil(nmax/nmin));
|
||||
|
||||
param.thickring = thickring;
|
||||
|
||||
rnyquist = floor(nmax/2);
|
||||
freq = [0:rnyquist];
|
||||
|
||||
x = ifftshift([-fix(nx/2):ceil(nx/2)-1])*floor(nmax/2)/floor(nx/2);
|
||||
y = ifftshift([-fix(ny/2):ceil(ny/2)-1])*floor(nmax/2)/floor(ny/2);
|
||||
if nz ~= 1
|
||||
z = ifftshift([-fix(nz/2):ceil(nz/2)-1])*floor(nmax/2)/floor(nz/2);
|
||||
else
|
||||
z = 0;
|
||||
end
|
||||
[X,Y,Z] = meshgrid(single(x),single(y),single(z));
|
||||
index = (sqrt(X.^2+Y.^2+Z.^2));
|
||||
|
||||
clear X Y Z
|
||||
|
||||
|
||||
Nr = length(freq);
|
||||
for ii = 1:Nr
|
||||
r = freq(ii);
|
||||
progressbar(ii,Nr)
|
||||
% calculate always thickring, min ring thickness is given by the smallest axis
|
||||
ind = index>=r-thickring/2 & index<=r+thickring/2 ;
|
||||
ind = find(ind); % find seems to be faster then indexing
|
||||
auxFimg = Fimg(ind);
|
||||
C(ii) = sum(auxFimg);
|
||||
n(ii) = numel(ind); % Number of points
|
||||
end
|
||||
|
||||
n = n*prod(bin); % account for larger number of elements in the binned voxels
|
||||
|
||||
PSD = abs(C) ./ n;
|
||||
freq = freq/freq(end);
|
||||
|
||||
figure(param.figure_id)
|
||||
hold all
|
||||
plot(freq, PSD)
|
||||
hold off
|
||||
set(gca, 'yscale', 'log')
|
||||
ylabel('Power spectral density')
|
||||
xlabel('Spatial frequency/Nyquist')
|
||||
grid on
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
*
|
||||
*-----------------------------------------------------------------------*
|
||||
| |
|
||||
| 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.
|
||||
|
||||
|
||||
* Compilation from Matlab:
|
||||
mex -R2018a 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" add_to_3D_projection_mex.cpp
|
||||
*
|
||||
* Usage from Matlab:
|
||||
|
||||
full_array = (zeros(1000, 1000, 1, 'single'));
|
||||
small_array = (ones(500, 500, 100, 'single'));
|
||||
|
||||
positions = int32([1:100; 1:100])';
|
||||
indices = int32([1:100]); % indices are starting from 1 !!
|
||||
add_values = true; % (DEFAULT)
|
||||
add_to_3D_projection_mex(small_array,full_array,positions, indices,add_values);
|
||||
|
||||
* Matlab version: add_to_3D_projection(full_array, small_array, positions)
|
||||
*
|
||||
*
|
||||
*
|
||||
* results are directly added to full_array, add_values == false => rewrite original values
|
||||
*
|
||||
* This code in matlab:
|
||||
*
|
||||
N_f = size(full_array);
|
||||
N_s = size(small_array);
|
||||
for ii = 1:N_f(3)
|
||||
for i = 1:2
|
||||
ind_f{i} = max(1, 1+positions(ii,i)):min(N_f(i),positions(ii,i)+N_s(i));
|
||||
ind_s{i} = ((ind_f{i}(1)-positions(ii,i))):(ind_f{i}(end)-positions(ii,i));
|
||||
end
|
||||
full_array(ind_f{:},ii) = full_array(ind_f{:},ii) + small_array(ind_s{:},ii);
|
||||
end
|
||||
*
|
||||
*/
|
||||
|
||||
#include "matlab_overload.h"
|
||||
#include "mex.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <omp.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define THREADS 16
|
||||
#define CHUNK 10
|
||||
|
||||
template <typename dtype, bool add_atomic, bool add_values>
|
||||
void inner_loop(dtype * array_full, dtype const * array_small, const mwSize pos_x0, const mwSize pos_y0, const mwSize pos_zs, const mwSize pos_zf, const mwSize Ns_x, const mwSize Ns_y, const mwSize Nf_x, const mwSize Nf_y)
|
||||
{
|
||||
|
||||
mwSize id, col, row, pos_y, pos_x, id_small, id_large, idc_small, idc_large;
|
||||
|
||||
#pragma omp parallel for schedule(static) num_threads(THREADS) private(col, row, pos_x, pos_y, id_small, id_large, idc_small, idc_large)
|
||||
for (col = (pos_x0>=0 ? 0 : -pos_x0) ; col < Ns_x; col++) {
|
||||
pos_x = col + pos_x0;
|
||||
idc_small = col*Ns_y + Ns_y*Ns_x*pos_zs;
|
||||
idc_large = pos_x*Nf_y + Nf_y*Nf_x*pos_zf;
|
||||
|
||||
if (pos_x >= Nf_x )
|
||||
continue;
|
||||
for (row = (pos_y0 >= 0 ? 0 : -pos_y0) ; row < Ns_y; row++) {
|
||||
pos_y = row + pos_y0;
|
||||
if (pos_y >= Nf_y )
|
||||
continue;
|
||||
|
||||
// skip positions that are out of the matrix
|
||||
id_small = row + idc_small;
|
||||
id_large = pos_y + idc_large;
|
||||
|
||||
if (add_atomic && add_values)
|
||||
//Add values to the already provided ones
|
||||
AddData_atomic(array_full[id_large], array_small[id_small]);
|
||||
else if (add_values)
|
||||
// rewrite original values
|
||||
AddData(array_full[id_large], array_small[id_small]);
|
||||
else
|
||||
// rewrite original values
|
||||
SetData(array_full[id_large], array_small[id_small]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename dtype>
|
||||
void add_to_projection(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
|
||||
|
||||
dtype * array_full;
|
||||
dtype const * array_small;
|
||||
|
||||
GetData(prhs[1], array_full);
|
||||
GetData(prhs[0], array_small);
|
||||
|
||||
// check if values should be added or overwritten
|
||||
bool const add_values = nrhs < 5 || mxGetScalar(prhs[4]); // if true, x += y, if false x = y;
|
||||
bool const add_atomic = nrhs < 6 || mxGetScalar(prhs[5]); // if true, correclty deal with overlap between the positions, but it is slow
|
||||
|
||||
mxInt32 const *indices = mxGetInt32s(prhs[3]);
|
||||
mxInt32 const *positions = mxGetInt32s(prhs[2]);
|
||||
|
||||
/* Get dimension of probe and object / small + large array */
|
||||
mwSize const *fdims = mxGetDimensions(prhs[1]);
|
||||
mwSize const Nf_y = fdims[0];
|
||||
mwSize const Nf_x = fdims[1];
|
||||
mwSize const Nf_z = (mxGetNumberOfDimensions(prhs[1]) == 3 ? fdims[2] : 1);
|
||||
|
||||
mwSize const *sdims = mxGetDimensions(prhs[0]);
|
||||
mwSize const Ns_y = sdims[0];
|
||||
mwSize const Ns_x = sdims[1];
|
||||
mwSize const Ns_z = (mxGetNumberOfDimensions(prhs[0]) == 3 ? sdims[2] : 1);
|
||||
|
||||
mwSize const Nid = mxGetNumberOfElements(prhs[3]);
|
||||
mwSize const Npos = mxGetM(prhs[2]);
|
||||
|
||||
if(Npos != Ns_z && Ns_z > 1 )
|
||||
mexErrMsgIdAndTxt("MexError:tomo","The 3rd dim of 1st input argument must be equal to length of positions.");
|
||||
|
||||
if(Nid != Ns_z && Ns_z > 1)
|
||||
mexErrMsgIdAndTxt("MexError:tomo","The 3rd dim of 1st input argument must be equal to length of indices.");
|
||||
|
||||
mwSize id, pos_zs,pos_zf, col, row, pos_y, pos_x, pos_x0, pos_y0 ;
|
||||
mwSize id_small, id_large, idc_small, idc_large;
|
||||
bool out_of_range = false;
|
||||
|
||||
for (id = 0; id < Nid; id++) {
|
||||
if (Nf_z == 1)
|
||||
pos_zf = 0;
|
||||
else
|
||||
pos_zf = indices[id]-1; // distribute the small_array only to defined sliced in the full_array
|
||||
|
||||
if (pos_zf >= Nf_z)
|
||||
{
|
||||
out_of_range = true;
|
||||
continue;
|
||||
}
|
||||
pos_zs = (id < Ns_z ? id : Ns_z-1); // min(id, Nf_z)
|
||||
|
||||
|
||||
pos_x0 = positions[id+Nid];
|
||||
pos_y0 = positions[id];
|
||||
|
||||
if (add_values && add_atomic)
|
||||
inner_loop<dtype,true,true>(array_full, array_small, pos_x0, pos_y0, pos_zs, pos_zf, Ns_x, Ns_y, Nf_x, Nf_y);
|
||||
else if (add_values)
|
||||
inner_loop<dtype,false,true>(array_full, array_small, pos_x0, pos_y0, pos_zs, pos_zf, Ns_x, Ns_y, Nf_x, Nf_y);
|
||||
else
|
||||
inner_loop<dtype,false,false>(array_full, array_small, pos_x0, pos_y0, pos_zs, pos_zf, Ns_x, Ns_y, Nf_x, Nf_y);
|
||||
|
||||
}
|
||||
if (out_of_range)
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Indices are out of range for provided inputs");
|
||||
|
||||
}
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
|
||||
#if MX_HAS_INTERLEAVED_COMPLEX == 0
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Only Matlab R2018a and newer is supported");
|
||||
#endif
|
||||
|
||||
/* Check for proper number of arguments. */
|
||||
if (nrhs <4 || nrhs > 6)
|
||||
mexErrMsgTxt("4-6 input arguments required: add_to_3D_projection_mex(small_array,full_array,positions, indices, add_values=true, add_atomic=true)");
|
||||
else if (nlhs != 0)
|
||||
mexErrMsgTxt("No output argument has to be specified.");
|
||||
|
||||
/* Input must be of type single / uint32 / uint16. */
|
||||
if ( !(mxIsDouble(prhs[0]) || mxIsSingle(prhs[0]) || mxIsUint32(prhs[0]) || mxIsUint16(prhs[0]) || mxIsLogical(prhs[0]) || mxIsUint8(prhs[0]) ) ) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Class of input 1 is not double/single/uint8/uint16/uint32");
|
||||
}
|
||||
if ( (mxGetClassID(prhs[0]) != mxGetClassID (prhs[1])) ) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs arrays are not the same type");
|
||||
}
|
||||
/* Input must be of type int32. */
|
||||
for (int i=2; i<4; i++) {
|
||||
if (mxIsInt32(prhs[i]) != 1) {
|
||||
printf("Input %d is not integer\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
if ((nrhs == 5) && (mxIsLogical(prhs[4]) != 1)) {
|
||||
printf("Input 5 is not logical\n");
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs must be of correct type.");
|
||||
}
|
||||
|
||||
|
||||
if(mxIsComplex(prhs[0]) != mxIsComplex(prhs[1])) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Complexity of the inputs has to be the same");
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ((mxGetNumberOfDimensions(prhs[0]) > 3) || (mxGetNumberOfDimensions(prhs[0]) < 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[1]) > 3) || (mxGetNumberOfDimensions(prhs[1]) < 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[2]) != 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[3]) != 2))
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Wrong number of dimensions in inputs");
|
||||
|
||||
|
||||
if(mxGetN(prhs[2]) != 2 )
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Positions are expected as Nx2 matrix");
|
||||
|
||||
if (mxIsComplex(prhs[0]))
|
||||
switch (mxGetClassID(prhs[0]))
|
||||
{
|
||||
case mxDOUBLE_CLASS: add_to_projection<mxComplexDouble>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxSINGLE_CLASS: add_to_projection<mxComplexSingle>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT32_CLASS: add_to_projection<mxComplexUint32>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT16_CLASS: add_to_projection<mxComplexUint16>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT8_CLASS: add_to_projection<mxComplexUint8>(nlhs, plhs, nrhs, prhs); break;
|
||||
}
|
||||
else
|
||||
switch (mxGetClassID(prhs[0]))
|
||||
{
|
||||
case mxDOUBLE_CLASS: add_to_projection<mxDouble>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxSINGLE_CLASS: add_to_projection<mxSingle>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT32_CLASS: add_to_projection<mxUint32>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT16_CLASS: add_to_projection<mxUint16>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT8_CLASS: add_to_projection<mxUint8>(nlhs, plhs, nrhs, prhs); break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
*
|
||||
**-----------------------------------------------------------------------*
|
||||
| |
|
||||
| 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
|
||||
|
||||
|
||||
|
||||
*
|
||||
Compilation from Matlab:
|
||||
mex -R2018a 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" get_from_3D_projection_mex.cpp
|
||||
|
||||
% Usage from Matlab:
|
||||
full_array = (randn(1000, 1000, 1, 'single'));
|
||||
small_array = (ones(500, 500, 100, 'single'));
|
||||
|
||||
positions = int32([1:100; 1:100])';
|
||||
indices = int32([1:100]); % indices are starting from 1 !!
|
||||
tic; get_from_3D_projection_mex(small_array,full_array,positions,indices); toc
|
||||
|
||||
This code in matlab:
|
||||
full_array = randn(100,100,200, 'single');
|
||||
small_array = zeros(50,50,50, 'single');
|
||||
positions = ones(200,2, 'int32');
|
||||
indices = int32(1:50);
|
||||
|
||||
Npix = size(full_array);
|
||||
small_array = zeros(dimensions, 'single');
|
||||
for jj = 1:length(indices)
|
||||
ii = indices(jj)
|
||||
for i = 1:2
|
||||
% limit to the region inside full_array
|
||||
ind_f{i} = max(1,1+positions(ii,i)):min(positions(ii,i)+dimensions(i),Npix(i));
|
||||
% adjust size of the small matrix to correspond
|
||||
ind_s{i} = ((ind_f{i}(1)-positions(ii,i))):(ind_f{i}(end)-positions(ii,i));
|
||||
end
|
||||
small_array(ind_s{:},jj) = full_array(ind_f{:},ii) ;
|
||||
end
|
||||
*/
|
||||
|
||||
#include "matlab_overload.h"
|
||||
#include "mex.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <omp.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
#define THREADS 12
|
||||
#define CHUNK 20
|
||||
|
||||
|
||||
|
||||
template <typename dtype>
|
||||
void inner_loop(dtype const * array_full, dtype * array_small, const mwSize pos_x0, const mwSize pos_y0, const mwSize pos_zs, const mwSize pos_zf, const mwSize Ns_x, const mwSize Ns_y, const mwSize Nf_x, const mwSize Nf_y)
|
||||
{
|
||||
|
||||
mwSize id, col, row, pos_y, pos_x, id_small, id_large, idc_small, idc_large;
|
||||
|
||||
#pragma omp parallel for schedule(static) num_threads(THREADS) private(col, row, pos_x, pos_y, id_small, id_large, idc_small, idc_large)
|
||||
for (col = (pos_x0>=0 ? 0 : -pos_x0) ; col < Ns_x; col++) {
|
||||
pos_x = col + pos_x0;
|
||||
idc_small = col*Ns_y + Ns_y*Ns_x*pos_zs;
|
||||
idc_large = pos_x*Nf_y + Nf_y*Nf_x*pos_zf;
|
||||
|
||||
if (pos_x >= Nf_x )
|
||||
continue;
|
||||
|
||||
|
||||
for (row = (pos_y0 >= 0 ? 0 : -pos_y0) ; row < Ns_y; row++) {
|
||||
pos_y = row + pos_y0;
|
||||
if (pos_y >= Nf_y )
|
||||
continue;
|
||||
|
||||
//skip positions that are out of the matrix
|
||||
id_small = row + idc_small;
|
||||
id_large = pos_y + idc_large;
|
||||
|
||||
//rewrite original values
|
||||
SetData(array_small[id_small], array_full[id_large]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename dtype>
|
||||
void get_from_projection(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
dtype const * array_full;
|
||||
dtype * array_small;
|
||||
|
||||
GetData(prhs[1], array_full);
|
||||
GetData(prhs[0], array_small);
|
||||
|
||||
// check if values should be added or overwritten
|
||||
bool const add_values = !((nrhs == 5) && ( !mxGetScalar(prhs[4]) ));
|
||||
|
||||
mxInt32 const *indices = mxGetInt32s(prhs[3]);
|
||||
mxInt32 const *positions = mxGetInt32s(prhs[2]);
|
||||
|
||||
/* Get dimension of probe and object / small + large array */
|
||||
mwSize const *fdims = mxGetDimensions(prhs[1]);
|
||||
mwSize const Nf_y = fdims[0];
|
||||
mwSize const Nf_x = fdims[1];
|
||||
mwSize const Nf_z = (mxGetNumberOfDimensions(prhs[1]) == 3 ? fdims[2] : 1);
|
||||
|
||||
mwSize const *sdims = mxGetDimensions(prhs[0]);
|
||||
mwSize const Ns_y = sdims[0];
|
||||
mwSize const Ns_x = sdims[1];
|
||||
mwSize const Ns_z = (mxGetNumberOfDimensions(prhs[0]) == 3 ? sdims[2] : 1);
|
||||
|
||||
mwSize const Nid = mxGetNumberOfElements(prhs[3]);
|
||||
mwSize const Npos = mxGetM(prhs[2]);
|
||||
|
||||
if(Npos != Ns_z )
|
||||
mexErrMsgIdAndTxt("MexError:tomo","The 3rd dim of 1st input argument must be equal to length of positions.");
|
||||
|
||||
if(Nid != Ns_z)
|
||||
mexErrMsgIdAndTxt("MexError:tomo","The 3rd dim of 1st input argument must be equal to length of indices.");
|
||||
|
||||
mwSize id, pos_zs,pos_zf, col, row, pos_y, pos_x, pos_x0, pos_y0, idc_small, idc_large;
|
||||
mwSize id_small, id_large;
|
||||
bool out_of_range = false;
|
||||
|
||||
// #pragma omp parallel for schedule(dynamic) num_threads(THREADS) private(col, row, pos_x, pos_y, pos_x0, pos_y0, id_small, id_large, pos_zs,pos_zf,id, idc_small, idc_large)
|
||||
for (id = 0; id < Nid; id++) {
|
||||
if (Nf_z == 1)
|
||||
pos_zf = 0;
|
||||
else
|
||||
pos_zf = indices[id]-1; // distribute the small_array only to defined sliced in the full_array
|
||||
|
||||
if (pos_zf > Nf_z)
|
||||
{
|
||||
out_of_range = true;
|
||||
continue;
|
||||
}
|
||||
pos_zs = (id < Ns_z ? id : Ns_z); // min(id, Nf_z)
|
||||
|
||||
|
||||
pos_x0 = positions[id+Nid];
|
||||
pos_y0 = positions[id];
|
||||
|
||||
inner_loop<dtype>(array_full, array_small, pos_x0, pos_y0, pos_zs, pos_zf, Ns_x, Ns_y, Nf_x, Nf_y);
|
||||
|
||||
}
|
||||
if (out_of_range)
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Indices are out of range for provided inputs");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
#if MX_HAS_INTERLEAVED_COMPLEX == 0
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Only Matlab R2018a and newer is supported");
|
||||
#endif
|
||||
|
||||
/* Check for proper number of arguments. */
|
||||
if (nrhs <4 || nrhs > 5)
|
||||
mexErrMsgTxt("4-5 input arguments required: add_to_3D_projection_mex(small_array,full_array,positions, indices, add_values)");
|
||||
else if (nlhs != 0)
|
||||
mexErrMsgTxt("No output argument has to be specified.");
|
||||
|
||||
/* Input must be of type double / single / uint32 / uint16. */
|
||||
if ( !(mxIsDouble(prhs[0]) || mxIsSingle(prhs[0]) || mxIsUint32(prhs[0]) || mxIsUint16(prhs[0]) || mxIsLogical(prhs[0]) || mxIsUint8(prhs[0]) ) ) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Class of input 1 is not double/single/uint8/uint16/uint32");
|
||||
}
|
||||
if ( (mxGetClassID(prhs[0]) != mxGetClassID (prhs[1])) ) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs arrays are not the same type");
|
||||
}
|
||||
/* Input must be of type int32. */
|
||||
for (int i=2; i<4; i++) {
|
||||
if (mxIsInt32(prhs[i]) != 1) {
|
||||
printf("Input %d is not integer\n",i+1);
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Inputs must be of correct type.");
|
||||
}
|
||||
}
|
||||
|
||||
if(mxIsComplex(prhs[0]) != mxIsComplex(prhs[1])) {
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Complexity of the inputs has to be the same");
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ((mxGetNumberOfDimensions(prhs[0]) > 3) || (mxGetNumberOfDimensions(prhs[0]) < 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[1]) > 3) || (mxGetNumberOfDimensions(prhs[1]) < 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[2]) != 2) ||
|
||||
(mxGetNumberOfDimensions(prhs[3]) != 2))
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Wrong number of dimensions in inputs");
|
||||
|
||||
if(mxGetN(prhs[2]) != 2 )
|
||||
mexErrMsgIdAndTxt("MexError:tomo","Positions are expected as Nx2 matrix");
|
||||
|
||||
if (mxIsComplex(prhs[0]))
|
||||
switch (mxGetClassID(prhs[0]))
|
||||
{
|
||||
case mxDOUBLE_CLASS: get_from_projection<mxComplexDouble>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxSINGLE_CLASS: get_from_projection<mxComplexSingle>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT32_CLASS: get_from_projection<mxComplexUint32>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT16_CLASS: get_from_projection<mxComplexUint16>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT8_CLASS: get_from_projection<mxComplexUint8>(nlhs, plhs, nrhs, prhs); break;
|
||||
}
|
||||
else
|
||||
switch (mxGetClassID(prhs[0]))
|
||||
{
|
||||
case mxDOUBLE_CLASS: get_from_projection<mxDouble>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxSINGLE_CLASS: get_from_projection<mxSingle>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT32_CLASS: get_from_projection<mxUint32>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT16_CLASS: get_from_projection<mxUint16>(nlhs, plhs, nrhs, prhs); break;
|
||||
case mxUINT8_CLASS: get_from_projection<mxUint8>(nlhs, plhs, nrhs, prhs); break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef INTERP3_GPU_tex_HPP
|
||||
#define INTERP3_GPU_tex_HPP
|
||||
|
||||
#include "tmwtypes.h"
|
||||
#include "mex.h"
|
||||
#include "gpu/mxGPUArray.h"
|
||||
|
||||
// interp3_gpu.m - fast texture based GPU based interpolation method for 3D deformation
|
||||
//
|
||||
// RECOMPILE: mexcuda -output interp3_gpu_mex interp3_gpu_ker.cu interp3_gpu_mex.cpp
|
||||
//
|
||||
// %*-----------------------------------------------------------------------*
|
||||
// %| |
|
||||
// %| 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) 2018 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.
|
||||
|
||||
|
||||
|
||||
|
||||
int checkLastError(char * msg);
|
||||
|
||||
void interp3_init( float * Img, const mxGPUArray * Img_0, const mxGPUArray *X, const mxGPUArray *Y, const mxGPUArray *Z, const unsigned int M, const unsigned int N, const unsigned int O);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
|
||||
// interp3_gpu.m - fast texture based GPU based interpolation method for 3D deformation
|
||||
//
|
||||
// RECOMPILE: mexcuda -output interp3_gpu_mex interp3_gpu_ker.cu interp3_gpu_mex.cpp
|
||||
//
|
||||
// %*-----------------------------------------------------------------------*
|
||||
// %| |
|
||||
// %| 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) 2018 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.
|
||||
|
||||
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cuda_runtime_api.h>
|
||||
#include "interp3_gpu.hpp"
|
||||
#include <cuda.h>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include "mex.h"
|
||||
#include "gpu/mxGPUArray.h"
|
||||
|
||||
#define MAX(x,y) (x>y?x:y);
|
||||
#define MIN(x,y) (x<y?x:y);
|
||||
#define ABS(x) (x>0?x:-x);
|
||||
#define INF (1023);
|
||||
|
||||
typedef const unsigned int cuint;
|
||||
typedef const int cint;
|
||||
|
||||
typedef texture<float, 3, cudaReadModeElementType> texture3D;
|
||||
|
||||
static texture3D ImgTexture, X_tex, Y_tex, Z_tex;
|
||||
|
||||
// splitting volume on smaller blocks to prevent GPU crashes
|
||||
static cuint g_blockX = 256;
|
||||
static cuint g_blockY = 256;
|
||||
static cuint g_blockZ = 256;
|
||||
|
||||
|
||||
cudaArray* allocateVolumeArray( cuint X, cuint Y, cuint Z)
|
||||
{
|
||||
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
|
||||
cudaArray* cuArray;
|
||||
cudaExtent extent;
|
||||
extent.width = X;
|
||||
extent.height = Y;
|
||||
extent.depth = Z;
|
||||
cudaError err = cudaMalloc3DArray(&cuArray, &channelDesc, extent);
|
||||
if (err != cudaSuccess) {
|
||||
mexPrintf ("Failed to allocate %dx%dx%d GPU array\n",X,Y,Z);
|
||||
return 0;
|
||||
}
|
||||
return cuArray;
|
||||
}
|
||||
|
||||
static bool bindVolumeDataTexture(const cudaArray* array, texture3D & Texture, bool normalized)
|
||||
{
|
||||
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
|
||||
Texture.addressMode[0] = cudaAddressModeClamp;
|
||||
Texture.addressMode[1] = cudaAddressModeClamp;
|
||||
Texture.addressMode[2] = cudaAddressModeClamp;
|
||||
Texture.filterMode = cudaFilterModeLinear; //cudaFilterModePoint
|
||||
Texture.normalized = normalized;
|
||||
|
||||
cudaError err = cudaBindTextureToArray(Texture, array, channelDesc);
|
||||
checkLastError("cudaBindTextureToArray ");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool transferVolumeToArray(const mxGPUArray * m_img, cudaArray *& array)
|
||||
{
|
||||
|
||||
mwSize const * dimensions = mxGPUGetDimensions(m_img);
|
||||
mwSize Ndim = mxGPUGetNumberOfDimensions(m_img);
|
||||
int M = (int)dimensions[0];
|
||||
int N = (int)dimensions[1];
|
||||
int O = Ndim > 2 ? (int)dimensions[2] : 1;
|
||||
|
||||
// get the values into float array
|
||||
const float * img =(const float *)mxGPUGetDataReadOnly(m_img);
|
||||
|
||||
array = allocateVolumeArray(M,N,O);
|
||||
if (array == 0)
|
||||
return false;
|
||||
|
||||
if (M * sizeof(float) > 2048) {
|
||||
mexPrintf("Volume is too large to be transfered to GPU array");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* make volume array (no copying) */
|
||||
cudaPitchedPtr volume;
|
||||
volume.ptr = (float *)img;
|
||||
volume.pitch = M * sizeof(float);
|
||||
volume.xsize = M;
|
||||
volume.ysize = N;
|
||||
|
||||
cudaExtent extent;
|
||||
extent.width = M;
|
||||
extent.height = N;
|
||||
extent.depth = O;
|
||||
|
||||
cudaMemcpy3DParms p;
|
||||
cudaPos zp = { 0, 0, 0 };
|
||||
p.srcArray = 0;
|
||||
p.srcPos = zp;
|
||||
p.srcPtr = volume;
|
||||
p.dstArray = array;
|
||||
p.dstPtr.ptr = 0;
|
||||
p.dstPtr.pitch = 0;
|
||||
p.dstPtr.xsize = 0;
|
||||
p.dstPtr.ysize = 0;
|
||||
p.dstPos = zp;
|
||||
p.extent = extent;
|
||||
p.kind = cudaMemcpyDeviceToDevice;
|
||||
|
||||
cudaError err = cudaMemcpy3D(&p);
|
||||
|
||||
if (!checkLastError("transferVolumeToArray cudaMemcpy3D"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int checkLastError(char * msg)
|
||||
{
|
||||
cudaError_t cudaStatus = cudaGetLastError();
|
||||
if (cudaStatus != cudaSuccess) {
|
||||
char err[512];
|
||||
sprintf(err, "interp3 variation failed \n %s: %s. \n", msg, cudaGetErrorString(cudaStatus));
|
||||
mexErrMsgTxt(err);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
bool cudaTextForceKernelsCompletion()
|
||||
{
|
||||
cudaError_t returnedCudaError = cudaThreadSynchronize();
|
||||
if (returnedCudaError != cudaSuccess) {
|
||||
fprintf(stderr, "Failed to force completion of cuda kernels: %d: %s. \n ", returnedCudaError, cudaGetErrorString(returnedCudaError));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* TEXTURE TRILINEAR INTERPOLATION
|
||||
**/
|
||||
|
||||
|
||||
__global__ void kernel_interp3(float * p, cuint N, cuint M, cuint O,
|
||||
cuint Xstart, cuint Ystart, cuint Zstart) {
|
||||
|
||||
// Location in a 3D matrix
|
||||
mwSize m = Xstart+ blockIdx.x * blockDim.x + threadIdx.x;
|
||||
mwSize n = Ystart+ blockIdx.y * blockDim.y + threadIdx.y;
|
||||
mwSize o = Zstart+ blockIdx.z * blockDim.z + threadIdx.z;
|
||||
|
||||
if (m < M & n < N & o < O)
|
||||
{
|
||||
float xs, ys, zs; // shifted coordinates
|
||||
float mn, nn, on; // normalized coordinates
|
||||
mn = (float)(m)/M;
|
||||
nn = (float)(n)/N;
|
||||
on = (float)(o)/O;
|
||||
// mn = (m+0.5f);
|
||||
// nn = (n+0.5f);
|
||||
// on = (o+0.5f);
|
||||
// load deformed coordinates
|
||||
xs = m+0.5f - tex3D(X_tex,mn, nn, on);
|
||||
ys = n+0.5f - tex3D(Y_tex,mn, nn, on);
|
||||
zs = o+0.5f - tex3D(Z_tex,mn, nn, on);
|
||||
// get trilinear interplation
|
||||
bool outsiders = (xs > 0) & (ys > 0) & (zs > 0) &
|
||||
(xs < M) & (ys < N) & (zs < O);
|
||||
float p_val = (outsiders ? tex3D(ImgTexture,xs,ys,zs) : 0);
|
||||
// write the interpolation to the output
|
||||
p[(n)*N+(m)+(o)*M*N] = p_val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Host function called by MEX gateway.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
void interp3_init( float * p, const mxGPUArray * p0, const mxGPUArray *m_X, const mxGPUArray *m_Y, const mxGPUArray *m_Z, cuint M, cuint N, cuint O)
|
||||
{
|
||||
if (M*N*O*4 > 1024e6) {
|
||||
mexPrintf("Image size exceeded 1024MB, textures in interp3 will fail\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* move image to the texture array */
|
||||
cudaArray* cuArray, *cuArrayX, *cuArrayY, *cuArrayZ;
|
||||
checkLastError("after allocateVolumeArray");
|
||||
transferVolumeToArray(p0, cuArray);
|
||||
checkLastError("after transferVolumeToArray\n \n ");
|
||||
bindVolumeDataTexture(cuArray, ImgTexture, false);
|
||||
|
||||
/* move X deformation to the texture array */
|
||||
checkLastError("after allocateVolumeArray");
|
||||
transferVolumeToArray(m_X, cuArrayX);
|
||||
checkLastError("after transferVolumeToArray\n \n ");
|
||||
bindVolumeDataTexture(cuArrayX, X_tex, true);
|
||||
|
||||
/* move Y deformation to the texture array */
|
||||
checkLastError("after allocateVolumeArray");
|
||||
transferVolumeToArray(m_Y, cuArrayY);
|
||||
checkLastError("after transferVolumeToArray\n \n ");
|
||||
bindVolumeDataTexture(cuArrayY, Y_tex, true);
|
||||
|
||||
/* move Z deformation to the texture array */
|
||||
checkLastError("after allocateVolumeArray");
|
||||
transferVolumeToArray(m_Z, cuArrayZ);
|
||||
checkLastError("after transferVolumeToArray\n \n ");
|
||||
bindVolumeDataTexture(cuArrayZ, Z_tex, true);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// *************** 3-dim case ***************
|
||||
// Choose a reasonably sized number of threads in each dimension for the block.
|
||||
int const threadsPerBlockEachDim = 10; // MAX THREAD is 1024 ~ 10*10*10 for 3D
|
||||
dim3 const dimThread(threadsPerBlockEachDim, threadsPerBlockEachDim, threadsPerBlockEachDim);
|
||||
//mexPrintf("Thread %i %i %i \n ", dimThread.x, dimThread.y, dimThread.z);
|
||||
// Compute the thread block and grid sizes based on the board dimensions.
|
||||
int const blocksPerGrid_M = (g_blockX + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
int const blocksPerGrid_N = (g_blockY + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
int const blocksPerGrid_O = (g_blockZ + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
|
||||
dim3 dimBlock(blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
|
||||
//mexPrintf("Block %i %i %i \n ", blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
|
||||
|
||||
std::list<cudaStream_t> streams;
|
||||
|
||||
for ( int blockXstart=0; blockXstart < M; blockXstart += g_blockX)
|
||||
for ( int blockYstart=0; blockYstart < N; blockYstart += g_blockY)
|
||||
for ( int blockZstart=0; blockZstart < O; blockZstart += g_blockZ)
|
||||
{
|
||||
cudaStream_t stream;
|
||||
cudaStreamCreate(&stream);
|
||||
streams.push_back(stream);
|
||||
kernel_interp3<<<dimBlock, dimThread, 0, stream>>>
|
||||
(p,M,N,O, blockXstart,blockYstart,blockZstart);
|
||||
}
|
||||
|
||||
checkLastError("after kernel");
|
||||
cudaThreadSynchronize();
|
||||
for (std::list<cudaStream_t>::iterator iter = streams.begin(); iter != streams.end(); ++iter)
|
||||
cudaStreamDestroy(*iter);
|
||||
|
||||
streams.clear();
|
||||
|
||||
|
||||
|
||||
// clear memory , unbind textures
|
||||
|
||||
cudaTextForceKernelsCompletion();
|
||||
|
||||
cudaFreeArray(cuArray);
|
||||
cudaFreeArray(cuArrayX);
|
||||
cudaFreeArray(cuArrayY);
|
||||
cudaFreeArray(cuArrayZ);
|
||||
|
||||
checkLastError("after cudaFreeArray");
|
||||
cudaUnbindTexture(ImgTexture);
|
||||
cudaUnbindTexture(X_tex);
|
||||
cudaUnbindTexture(Y_tex);
|
||||
cudaUnbindTexture(Z_tex);
|
||||
checkLastError("cudaUnbindTexture");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "mex.h"
|
||||
#include "gpu/mxGPUArray.h"
|
||||
#include "interp3_gpu.hpp"
|
||||
|
||||
// interp3_gpu.m - fast texture based GPU based interpolation method for 3D deformation
|
||||
//
|
||||
// RECOMPILE: mexcuda -output interp3_gpu_mex interp3_gpu_ker.cu interp3_gpu_mex.cpp
|
||||
//
|
||||
// %*-----------------------------------------------------------------------*
|
||||
// %| |
|
||||
// %| 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) 2018 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.
|
||||
|
||||
|
||||
/**
|
||||
* MEX gateway
|
||||
*/
|
||||
void mexFunction(int nlhs , mxArray *plhs[],
|
||||
int nrhs, mxArray const *prhs[])
|
||||
{
|
||||
char const * const errId = "parallel:gpu:interp3_gpu:InvalidInput";
|
||||
char const * const errMsg = "Invalid input to MEX file.";
|
||||
|
||||
// Initialize the MathWorks GPU API.
|
||||
mxInitGPU();
|
||||
|
||||
if (nrhs!=4) {
|
||||
mexPrintf("Wrong number of inputs\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
|
||||
|
||||
const mxGPUArray * m_Img_orig = mxGPUCreateFromMxArray(prhs[0]);
|
||||
if ((mxGPUGetClassID(m_Img_orig) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("wrong input m_Img_orig\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const float * p_Img_orig = (const float *)mxGPUGetDataReadOnly(m_Img_orig);
|
||||
|
||||
|
||||
const mxGPUArray * m_X = mxGPUCreateFromMxArray(prhs[1]);
|
||||
const mxGPUArray * m_Y = mxGPUCreateFromMxArray(prhs[2]);
|
||||
const mxGPUArray * m_Z = mxGPUCreateFromMxArray(prhs[3]);
|
||||
if ((mxGPUGetClassID(m_X) != mxSINGLE_CLASS) |
|
||||
(mxGPUGetClassID(m_Y) != mxSINGLE_CLASS) |
|
||||
(mxGPUGetClassID(m_Z) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("wrong input X,Y,Z\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
|
||||
mwSize const * dimensions = mxGPUGetDimensions(m_Img_orig);
|
||||
mwSize Ndim = mxGPUGetNumberOfDimensions(m_Img_orig);
|
||||
int M = (int)dimensions[0];
|
||||
int N = (int)dimensions[1];
|
||||
int O = Ndim > 2 ? (int)dimensions[2] : 1;
|
||||
|
||||
mxGPUArray * m_Img_out = mxGPUCreateGPUArray(Ndim,
|
||||
dimensions,
|
||||
mxSINGLE_CLASS,
|
||||
mxREAL,
|
||||
MX_GPU_INITIALIZE_VALUES);
|
||||
float * p_Img_out = (float *)mxGPUGetData(m_Img_out);
|
||||
|
||||
checkLastError("Before kernel run");
|
||||
|
||||
// mexcuda -output interp3_gpu_mex interp3_gpu_ker.cu interp3_gpu_mex.cpp
|
||||
|
||||
interp3_init( p_Img_out,m_Img_orig, m_X, m_Y, m_Z, M, N, O);
|
||||
|
||||
checkLastError("Before after run");
|
||||
|
||||
plhs[0] = mxGPUCreateMxArrayOnGPU(m_Img_out);
|
||||
|
||||
mxGPUDestroyGPUArray(m_Img_out);
|
||||
mxGPUDestroyGPUArray(m_Img_orig);
|
||||
mxGPUDestroyGPUArray(m_X);
|
||||
mxGPUDestroyGPUArray(m_Y);
|
||||
mxGPUDestroyGPUArray(m_Z);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
|
||||
|
||||
#ifndef _MATLAB_OVERLOAD
|
||||
#define _MATLAB_OVERLOAD
|
||||
|
||||
#include "mex.h"
|
||||
|
||||
|
||||
// overload the GetData function for each of the possible data type + select the correct matlab get function
|
||||
inline void GetData(const mxArray *in, const mxComplexDouble *& out) { out = mxGetComplexDoubles(in); return; };
|
||||
inline void GetData(const mxArray *in, const mxComplexSingle *& out) { out = mxGetComplexSingles(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxComplexUint32 *& out) { out = mxGetComplexUint32s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxComplexUint16 *& out) { out = mxGetComplexUint16s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxComplexUint8 *& out) { out = mxGetComplexUint8s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxDouble *& out) { out = mxGetDoubles(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxSingle *& out) { out = mxGetSingles(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxUint32 *& out) { out = mxGetUint32s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxUint16 *& out) { out = mxGetUint16s(in); return;};
|
||||
inline void GetData(const mxArray *in, const mxUint8 *& out) { out = mxGetUint8s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexDouble *& out) { out = mxGetComplexDoubles(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexSingle *& out) { out = mxGetComplexSingles(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexUint32 *& out) { out = mxGetComplexUint32s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexUint16 *& out) { out = mxGetComplexUint16s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxComplexUint8 *& out) { out = mxGetComplexUint8s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxDouble *& out) { out = mxGetDoubles(in); return;};
|
||||
inline void GetData(const mxArray *in, mxSingle *& out) { out = mxGetSingles(in); return;};
|
||||
inline void GetData(const mxArray *in, mxUint32 *& out) { out = mxGetUint32s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxUint16 *& out) { out = mxGetUint16s(in); return;};
|
||||
inline void GetData(const mxArray *in, mxUint8 *& out) { out = mxGetUint8s(in); return;};
|
||||
|
||||
inline void AddData_atomic( mxDouble &out, const mxDouble &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxSingle &out, const mxSingle &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxUint32 &out, const mxUint32 &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxUint16 &out, const mxUint16 &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxUint8 &out, const mxUint8 &in) {
|
||||
#pragma omp atomic
|
||||
out += in; };
|
||||
inline void AddData_atomic( mxComplexDouble &out, const mxComplexDouble &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
inline void AddData_atomic( mxComplexSingle &out, const mxComplexSingle &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
inline void AddData_atomic( mxComplexUint32 &out, const mxComplexUint32 &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
inline void AddData_atomic( mxComplexUint16 &out, const mxComplexUint16 &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
inline void AddData_atomic( mxComplexUint8 &out, const mxComplexUint8 &in) {
|
||||
#pragma omp atomic update
|
||||
out.real += in.real;
|
||||
#pragma omp atomic update
|
||||
out.imag += in.imag;};
|
||||
|
||||
inline void AddData( mxDouble &out, const mxDouble &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxSingle &out, const mxSingle &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxUint32 &out, const mxUint32 &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxUint16 &out, const mxUint16 &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxUint8 &out, const mxUint8 &in) {
|
||||
out += in; };
|
||||
inline void AddData( mxComplexDouble &out, const mxComplexDouble &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
inline void AddData( mxComplexSingle &out, const mxComplexSingle &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
inline void AddData( mxComplexUint32 &out, const mxComplexUint32 &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
inline void AddData( mxComplexUint16 &out, const mxComplexUint16 &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
inline void AddData( mxComplexUint8 &out, const mxComplexUint8 &in) {
|
||||
out.real += in.real;
|
||||
out.imag += in.imag;};
|
||||
|
||||
inline void SetData( mxDouble &out, const mxDouble &in) { out = in; };
|
||||
inline void SetData( mxSingle &out, const mxSingle &in) { out = in; };
|
||||
inline void SetData( mxUint32 &out, const mxUint32 &in) { out = in; };
|
||||
inline void SetData( mxUint16 &out, const mxUint16 &in) { out = in; };
|
||||
inline void SetData( mxUint8 &out, const mxUint8 &in) { out = in; };
|
||||
inline void SetData( mxComplexDouble &out, const mxComplexDouble &in) { out.real = in.real; out.imag = in.imag; };
|
||||
inline void SetData( mxComplexSingle &out, const mxComplexSingle &in) { out.real = in.real; out.imag = in.imag; };
|
||||
inline void SetData( mxComplexUint32 &out, const mxComplexUint32 &in) { out.real = in.real; out.imag = in.imag; };
|
||||
inline void SetData( mxComplexUint16 &out, const mxComplexUint16 &in) { out.real = in.real; out.imag = in.imag; };
|
||||
inline void SetData( mxComplexUint8 &out, const mxComplexUint8 &in) { out.real = in.real; out.imag = in.imag; };
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
% progressbar - display a progress bar
|
||||
%
|
||||
% progressbar(n,N,w);
|
||||
%
|
||||
% displays the progress of n out of N.
|
||||
% n should start at 1.
|
||||
% w is the width of the bar (default w=20).
|
||||
%
|
||||
|
||||
% Copyright (c) 2010, Gabriel Peyre
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function progressbar(n,N,w)
|
||||
|
||||
if nargin<3
|
||||
w = 20;
|
||||
end
|
||||
|
||||
% progress char
|
||||
cprog = '.';
|
||||
cprog1 = '*';
|
||||
% begining char
|
||||
cbeg = '[';
|
||||
% ending char
|
||||
cend = ']';
|
||||
|
||||
p = min( floor(n/N*(w+1)), w);
|
||||
|
||||
global pprev;
|
||||
if isempty(pprev)
|
||||
pprev = -1;
|
||||
end
|
||||
|
||||
if not(p==pprev)
|
||||
ps = repmat(cprog, [1 w]);
|
||||
ps(1:p) = cprog1;
|
||||
ps = [cbeg ps cend];
|
||||
if n>1
|
||||
% clear previous string
|
||||
fprintf( repmat('\b', [1 length(ps)]) );
|
||||
end
|
||||
fprintf(ps);
|
||||
end
|
||||
pprev = p;
|
||||
if n==N
|
||||
fprintf('\n');
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,90 @@
|
||||
%PROP2FOCUS propagate img to focus
|
||||
% prop2focus uses 'phase detection autofocus' to find the focus
|
||||
%
|
||||
% img... complex-valued object
|
||||
% lam... wavelength
|
||||
% dx... pixel size
|
||||
%
|
||||
% optional parameters
|
||||
% d_start... initial guess of propagation distance to focus
|
||||
% fov... crop to fov and apodize edges
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 [ d, img_prop ] = prop2focus(img, lam, dx, varargin)
|
||||
import utils.*
|
||||
|
||||
img_sz = size(img);
|
||||
|
||||
% defaults
|
||||
fov = img_sz(1)*0.6;
|
||||
d_start = 0;
|
||||
|
||||
% parse the variable input arguments vararg = cell(0,0);
|
||||
for ind = 1:2:length(varargin)
|
||||
name = varargin{ind};
|
||||
value = varargin{ind+1};
|
||||
switch lower(name)
|
||||
case 'd_start'
|
||||
d_start = value;
|
||||
case 'fov'
|
||||
fov = value;
|
||||
otherwise
|
||||
error('Unknown parameter %s', name)
|
||||
end
|
||||
end
|
||||
|
||||
% prepare fov mask with apodization
|
||||
fov_mask = fftshift(fract_hanning_pad(img_sz, round(fov*1.2), round(fov)));
|
||||
img = img.*fov_mask;
|
||||
|
||||
|
||||
% create masks for autofocus
|
||||
mask = fract_hanning_pad(img_sz,round(img_sz(1)/5),round(img_sz(1)/5*0.9));
|
||||
|
||||
mask1 = abs(shiftpp2(fftshift(mask),round(img_sz(1)/20),0));
|
||||
mask2 = abs(shiftpp2(fftshift(mask),-round(img_sz(1)/20),0));
|
||||
|
||||
|
||||
% minimize difference between the 2 images
|
||||
fun = @(d)sum(sum(abs(abs(fft2(ifftshift(fftshift(fft2(prop_free_nf(img,lam,d,dx))).*mask2)))-(abs(fft2(ifftshift(fftshift(fft2(prop_free_nf(img,lam,d,dx))).*mask1)))))));
|
||||
|
||||
d = fminsearch(fun,d_start);
|
||||
|
||||
% propagate to focus
|
||||
img_prop = prop_free_nf(img, lam, d, dx);
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,103 @@
|
||||
% PROP_FREE_FF Far field propagation
|
||||
%
|
||||
% PROP_FREE_FF(WIN, LAMBDA, Z, PIXSIZE) returns the propagated wavefield
|
||||
% WIN by a distance Z, using wavelength LAMBDA. PIXSIZE is the dimension
|
||||
% of one pixel.
|
||||
%
|
||||
% PROP_FREE_FF(WIN, LAMBDA, Z) is the same as above, assuming PIXSIZE=1
|
||||
% (that is, Z and LAMBDA are expressed in pixel units).
|
||||
%
|
||||
% In this implementation, the output wave pixel size becomes
|
||||
% Z*LAMBDA/(N*PIXSIZE) (where N is the linear dimension of the array).
|
||||
|
||||
|
||||
|
||||
% Academic License Agreement
|
||||
%
|
||||
% Source Code
|
||||
%
|
||||
% Introduction
|
||||
% • This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
|
||||
% will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
|
||||
% ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
|
||||
%
|
||||
% Terms and Conditions of the LICENSE
|
||||
% 1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
|
||||
% hereinafter set out and until termination of this license as set forth below.
|
||||
% 2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
|
||||
% or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
|
||||
% LICENSEE’s responsibility to ensure its proper use and the correctness of the results.”
|
||||
% 3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
||||
% A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
|
||||
% HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
|
||||
% OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
|
||||
% 4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
|
||||
% "IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
|
||||
% license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
|
||||
% profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
|
||||
% in the commercial use, application or exploitation of works similar to the PROGRAM.
|
||||
% 5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
|
||||
% another computing language:
|
||||
% "Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
|
||||
% Scherrer Institut, Switzerland."
|
||||
%
|
||||
% Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
|
||||
% P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379–382 (2008).
|
||||
% (doi: 10.1126/science.1158573),
|
||||
% for maximum likelihood:
|
||||
% P. Thibault and M. Guizar-Sicairos, Maximum-likelihood refinement for coherent diffractive imaging, New J. Phys. 14, 063004 (2012).
|
||||
% (doi: 10.1088/1367-2630/14/6/063004),
|
||||
% for mixed coherent modes:
|
||||
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 68–71 (2013). (doi: 10.1038/nature11806),
|
||||
% and/or for multislice:
|
||||
% E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 29089–29108 (2016).
|
||||
% (doi: 10.1364/OE.24.029089).
|
||||
% 6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
|
||||
% names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
|
||||
% 7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
|
||||
% agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
|
||||
% make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
|
||||
% © All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
|
||||
% 8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
|
||||
% 9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
|
||||
% to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
|
||||
% in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
|
||||
% in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
|
||||
% 10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
|
||||
% the courts of Zürich, Switzerland.
|
||||
|
||||
function wout = prop_free_ff(win, lambda, z, pixsize)
|
||||
|
||||
import math.*
|
||||
|
||||
if ndims(win) < 2
|
||||
error('Input wavefield should be at least 2-dimensional array!')
|
||||
end
|
||||
|
||||
sz = size(win);
|
||||
|
||||
if sz(1) ~= sz(2)
|
||||
error('Only implemented for square arrays...')
|
||||
end
|
||||
|
||||
N = sz(1);
|
||||
|
||||
if nargin > 3
|
||||
z = z / pixsize(1);
|
||||
lambda = lambda / pixsize(1);
|
||||
end
|
||||
|
||||
% Evaluate if aliasing could be a problem
|
||||
|
||||
if N*sqrt(2.) > abs(z)*lambda
|
||||
utils.verbose(0,'Warning: there could be some aliasing issues...');
|
||||
utils.verbose(0,'(you could try a near field method)');
|
||||
end
|
||||
|
||||
[x,y] = meshgrid(-N/2:floor((N-1)/2),-N/2:floor((N-1)/2));
|
||||
r2 = x.^2 + y.^2;
|
||||
|
||||
wout = -1i * exp(1i * pi * lambda * z * r2 /N^2) .* ifftshift_2D(fft2(fftshift_2D(win .* exp(1i * pi * r2 / (lambda*z)))));
|
||||
%wout = fftshift(fft2(fftshift(win .* exp(1i * pi * r2 / (lambda*z)))));
|
||||
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user