initial commit

This commit is contained in:
2026-08-07 15:56:42 +09:00
commit 91ad25aca9
1012 changed files with 159314 additions and 0 deletions
+68
View File
@@ -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
+69
View File
@@ -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
+123
View File
@@ -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
+159
View File
@@ -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
+44
View File
@@ -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
+215
View File
@@ -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
+91
View File
@@ -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
+79
View File
@@ -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
+110
View File
@@ -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
+74
View File
@@ -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
+144
View File
@@ -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
+34
View File
@@ -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
+25
View File
@@ -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
+45
View File
@@ -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
+17
View File
@@ -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
+17
View File
@@ -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
+50
View File
@@ -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
+216
View File
@@ -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
+180
View File
@@ -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
+181
View File
@@ -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
+60
View File
@@ -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
+53
View File
@@ -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
+91
View File
@@ -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
+325
View File
@@ -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
+223
View File
@@ -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
+211
View File
@@ -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
View File
@@ -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
+122
View File
@@ -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;
+192
View File
@@ -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
+103
View File
@@ -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
+102
View File
@@ -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
+200
View File
@@ -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
+140
View File
@@ -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
+156
View File
@@ -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
+115
View File
@@ -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
+65
View File
@@ -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
+193
View File
@@ -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
+96
View File
@@ -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.
+67
View File
@@ -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')
+209
View File
@@ -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
+419
View File
@@ -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
+415
View File
@@ -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
+88
View File
@@ -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;
+70
View File
@@ -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;
+34
View File
@@ -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
+157
View File
@@ -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
+342
View File
@@ -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
+151
View File
@@ -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
+117
View File
@@ -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
+170
View File
@@ -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
+64
View File
@@ -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
+120
View File
@@ -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;
+123
View File
@@ -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
+56
View File
@@ -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
+106
View File
@@ -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
+154
View File
@@ -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
+70
View File
@@ -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
+70
View File
@@ -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
+68
View File
@@ -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. 713720, 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
+293
View File
@@ -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,:)&currentwall(2:end,:); % prevents horizontal integration
%wallvert = [zeros(1,nc-1);wallvert;zeros(1,nc-1)];
wallhor = currentwall(:,1:end-1)&currentwall(:,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)&not(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)&not(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,:)&not(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,:)&not(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
+118
View File
@@ -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;
+61
View File
@@ -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
+86
View File
@@ -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
+100
View File
@@ -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
+76
View File
@@ -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
+101
View File
@@ -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
+83
View File
@@ -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
+178
View File
@@ -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 RayleighSommerfeld 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 RayleighSommerfeld 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
+111
View File
@@ -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
+119
View File
@@ -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
+81
View File
@@ -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
+73
View File
@@ -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
+162
View File
@@ -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
+114
View File
@@ -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
+105
View File
@@ -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
+109
View File
@@ -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
+109
View File
@@ -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
+69
View File
@@ -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
+69
View File
@@ -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)));
+80
View File
@@ -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
+118
View File
@@ -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
+93
View File
@@ -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
+69
View File
@@ -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
+17
View File
@@ -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
+73
View File
@@ -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
+107
View File
@@ -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
+54
View File
@@ -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
+111
View File
@@ -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
+261
View File
@@ -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
+65
View File
@@ -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;
+174
View File
@@ -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
+260
View File
@@ -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;
}
+55
View File
@@ -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
+315
View File
@@ -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");
}
+112
View File
@@ -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);
}
+110
View File
@@ -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
+70
View File
@@ -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
+90
View File
@@ -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
+103
View File
@@ -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
% LICENSEEs 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, 379382 (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, 6871 (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, 2908929108 (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