mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 19:39:08 +09:00
initial commit
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
% TESTING SCRIPT for ASTRA wrappers
|
||||
% This script will run some basic features in the ASTRA wrapper code
|
||||
% ie reconstruciton , splitting on GPU, splitting between multiple workers
|
||||
% compare results with expected values to detect inconsistencies
|
||||
% recompile commands
|
||||
% (Linux, GCC 4.8.5) mexcuda -outdir private ASTRA_GPU_wrapper/ASTRA_GPU_wrapper.cu ASTRA_GPU_wrapper/util3d.cu ASTRA_GPU_wrapper/par3d_fp.cu ASTRA_GPU_wrapper/par3d_bp.cu
|
||||
% (Windows) mexcuda -outdir private ASTRA_GPU_wrapper\ASTRA_GPU_wrapper.cu ASTRA_GPU_wrapper\util3d.cu ASTRA_GPU_wrapper\par3d_fp.cu ASTRA_GPU_wrapper\par3d_bp.cu
|
||||
|
||||
cd(fullfile( fileparts(mfilename('fullpath')), '..'))
|
||||
addpath('tests')
|
||||
addpath('utils')
|
||||
addpath('./')
|
||||
addpath(find_base_package)
|
||||
utils.verbose(0)
|
||||
|
||||
utils.verbose(0,'Creating data for ASTRA wrapper tests')
|
||||
if ~exist('GPU_id', 'var'); GPU_id = [1]; end
|
||||
gpuDevice(GPU_id);
|
||||
|
||||
% volume settings
|
||||
Npix_vol = [300, 300, 200] ;
|
||||
Nangles = 400;
|
||||
Npix_proj = [400, 400];
|
||||
|
||||
% create "data"
|
||||
angles = linspace(0, 180, Nangles);
|
||||
lamino_angle = 60; % 90 deg is normal tomo
|
||||
tilt_angle = 10; % rotation in plane of the projection
|
||||
CoR_offset = [20,10]; % offset of the center of rotation
|
||||
pixel_scale = [1,1] ; % relative scale of the pixels
|
||||
volData = ones(Npix_vol, 'single');
|
||||
|
||||
% generate geometry
|
||||
[cfg, vectors] = astra.ASTRA_initialize(Npix_vol, Npix_proj, angles, lamino_angle, tilt_angle, pixel_scale,Npix_proj/2+CoR_offset);
|
||||
% find optimal split, for small volumes below 600^3 no split is needed
|
||||
split = astra.ASTRA_find_optimal_split(cfg);
|
||||
|
||||
% generate projections
|
||||
projData = astra.Ax_partial(volData, cfg, vectors, split);
|
||||
|
||||
% plot the projections
|
||||
figure
|
||||
plotting.imagesc3D(projData, 'init_frame', 50); axis off image; colormap bone
|
||||
title('Volume projection')
|
||||
drawnow
|
||||
|
||||
% do backprojection projections !!! not FBP !!!
|
||||
backprojData = astra.Atx_partial(projData, cfg, vectors, split);
|
||||
|
||||
utils.verbose(0,'Simple ASTRA wrapper tested')
|
||||
%% =============== tests simple "on GPU" splitting ============
|
||||
split = [2,2,2,2];
|
||||
|
||||
% generate projections
|
||||
projData_split = astra.Ax_partial(volData, cfg, vectors, split);
|
||||
|
||||
err = norm(projData(:) - projData_split(:)) / norm(projData(:));
|
||||
% plotting.imagesc3D(projData - projData_split); colorbar; axis off image; colormap bone
|
||||
assert(err < 1e-5, "Splitted projections solver is not fully consistent with the unsplitted one")
|
||||
|
||||
|
||||
% do backprojection projections !!! not FBP !!!
|
||||
backprojData_split = astra.Atx_partial(projData, cfg, vectors, split);
|
||||
err = norm(backprojData(:) - backprojData_split(:)) / norm(backprojData(:));
|
||||
assert(err < 1e-6, "Splitted backprojections solver is not fully consistent with the unsplitted one")
|
||||
|
||||
|
||||
utils.verbose(0,'On GPU splitting tested')
|
||||
%% =============== tests additional splitting for tomography ============
|
||||
|
||||
split = [2,2,2,1];
|
||||
projData_split = tomo.Ax_sup_partial(volData, cfg, vectors, split);
|
||||
err = norm(projData(:) - projData_split(:)) / norm(projData(:));
|
||||
if err > 1e-5
|
||||
figure
|
||||
plotting.imagesc3D(projData - projData_split); colorbar; axis off image; colormap bone
|
||||
title('Projection data difference')
|
||||
drawnow
|
||||
end
|
||||
if err > 1e-3
|
||||
error("Sup-splitted projections solver is not fully consistent with the unsplitted one")
|
||||
elseif err > 1e-5
|
||||
warning("Sup-splitted projections solver is not fully consistent with the unsplitted one, most likely only subpixel errors are present")
|
||||
end
|
||||
|
||||
|
||||
|
||||
backprojData_split = tomo.Atx_sup_partial(projData, cfg, vectors, split);
|
||||
err = norm(backprojData(:) - backprojData_split(:)) / norm(backprojData(:));
|
||||
if err > 1e-5
|
||||
figure
|
||||
plotting.imagesc_tomo(backprojData - backprojData_split); colorbar; axis off image; colormap bone
|
||||
title('Backprojection data difference')
|
||||
drawnow
|
||||
end
|
||||
if err > 1e-3
|
||||
error("Sup-splitted backprojections solver is not fully consistent with the unsplitted one")
|
||||
elseif err > 1e-5
|
||||
warning("Sup-splitted backprojections solver is not fully consistent with the unsplitted one, most likely only subpixel errors are present")
|
||||
end
|
||||
|
||||
utils.verbose(0,'Extra splitting tested')
|
||||
|
||||
%% =============== tests multiGPU solvers ============
|
||||
|
||||
utils.verbose(0,'Testing multiGPU solver')
|
||||
|
||||
c = parcluster('local');
|
||||
if exist('local_cluster_jobs', 'dir')
|
||||
rmdir('local_cluster_jobs', 's') % delete folder with jobs (prevent accumulation )
|
||||
end
|
||||
mkdir('local_cluster_jobs') % recreate the folder
|
||||
c.JobStorageLocation = ['local_cluster_jobs'];
|
||||
|
||||
|
||||
GPU = [1:gpuDeviceCount];
|
||||
split = [2,2,2,2];
|
||||
projData_split = tomo.Ax_sup_partial(volData, cfg, vectors, split, 'GPU', GPU);
|
||||
err = norm(projData(:) - projData_split(:)) / norm(projData(:));
|
||||
% plotting.imagesc3D(projData - projData_split); colorbar; axis off image; colormap bone
|
||||
assert(err < 1e-5, "Sup-splitted projections solver is not fully consistent with the unsplitted one")
|
||||
|
||||
|
||||
backprojData_split = tomo.Atx_sup_partial(projData, cfg, vectors, split, 'GPU', GPU);
|
||||
err = norm(backprojData(:) - backprojData_split(:)) / norm(backprojData(:));
|
||||
assert(err < 1e-6, "Sup-splitted backprojections solver is not fully consistent with the unsplitted one")
|
||||
|
||||
utils.verbose(0,'Multi GPU solver tested')
|
||||
rmdir('local_cluster_jobs', 's') % delete folder with jobs (prevent accumulation )
|
||||
|
||||
utils.verbose(0,'==== All ASTRA wrapper tests passed ===== ')
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| Except where otherwise noted, this work is licensed under a |
|
||||
%| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
%| International (CC BY-NC-SA 4.0) license. |
|
||||
%| |
|
||||
%| Copyright (c) 2018 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
%| |
|
||||
%| Author: CXS group, PSI |
|
||||
%*-----------------------------------------------------------------------*
|
||||
% You may use this code with the following provisions:
|
||||
%
|
||||
% If the code is fully or partially redistributed, or rewritten in another
|
||||
% computing language this notice should be included in the redistribution.
|
||||
%
|
||||
% If this code, or subfunctions or parts of it, is used for research in a
|
||||
% publication or if it is fully or partially rewritten for another
|
||||
% computing language the authors and institution should be acknowledged
|
||||
% in written form in the publication: “Data processing was carried out
|
||||
% using the “cSAXS matlab package” developed by the CXS group,
|
||||
% Paul Scherrer Institut, Switzerland.”
|
||||
% Variations on the latter text can be incorporated upon discussion with
|
||||
% the CXS group if needed to more specifically reflect the use of the package
|
||||
% for the published work.
|
||||
%
|
||||
% A publication that focuses on describing features, or parameters, that
|
||||
% are already existing in the code should be first discussed with the
|
||||
% authors.
|
||||
%
|
||||
% This code and subroutines are part of a continuous development, they
|
||||
% are provided “as they are” without guarantees or liability on part
|
||||
% of PSI or the authors. It is the user responsibility to ensure its
|
||||
% proper use and the correctness of the results.
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
% DEBUG returns current debug level, if nothing was set, returns 0
|
||||
%
|
||||
% out = debug(varargin)
|
||||
% Inputs:
|
||||
% **debug_level - debugging level, if nothing was set, returns 0
|
||||
% returns:
|
||||
% ++debug_level - last set debug level
|
||||
%
|
||||
% USE:
|
||||
% set debug level :
|
||||
% debug(debug_level)
|
||||
% get debug level :
|
||||
% level = debug()
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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 = debug(varargin)
|
||||
|
||||
persistent debug_level
|
||||
|
||||
if nargin > 0
|
||||
debug_level = varargin{1};
|
||||
end
|
||||
|
||||
if isempty(debug_level)
|
||||
debug_level = 0; % no debugging
|
||||
end
|
||||
if nargout > 0
|
||||
out = debug_level;
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,53 @@
|
||||
clear; close all; clc
|
||||
addpath('utils')
|
||||
addpath(find_base_package())
|
||||
utils.verbose(struct('prefix', 'run_tests'))
|
||||
|
||||
%% SELECTED TESTS TO BE RUN
|
||||
test_astra = true; % run tests of ASTRA projectiors in +astra and multiGPU astra wrappers in +tomo, check that they all provide consistent results
|
||||
test_mex_function = true; % test MEX functions used by tomo.block_fun, tomo.Ax_sup_partial, tomo.Axt_sup_partial
|
||||
test_simulated_data = true; % test uses synthetic data to run all templates under well controlled conditions
|
||||
test_real_data = true; % test uses real data to run all templates under real experimental conditions
|
||||
|
||||
%% SELECT BASIC PARAMETERS
|
||||
GPU_id = 1;
|
||||
base_path = './'; % path to store temporal data
|
||||
|
||||
|
||||
gpuDevice(GPU_id);
|
||||
utils.report_GPU_usage
|
||||
pause(1)
|
||||
|
||||
%% TEST ASTRA WRAPPER
|
||||
% This script will run some basic features in the +astra/ ASTRA wrapper code
|
||||
% ie reconstruciton , splitting on GPU, splitting between multiple workers
|
||||
% compare results with expected values to detect inconsistencies
|
||||
if test_astra
|
||||
utils.verbose(struct('prefix', 'Test ASTRA'))
|
||||
run('tests/astra_wrappers_tests.m')
|
||||
end
|
||||
%% TEST MEX FUNCTION
|
||||
% the MEX functions in +utils/private use OpenMP to accelerate memory transfer from
|
||||
% large array into small sub array and back
|
||||
if test_mex_function
|
||||
utils.verbose(struct('prefix', 'Test MEX'))
|
||||
run('tests/test_MEX_functions.m')
|
||||
end
|
||||
clearvars -except GPU_id base_path test_real_data test_simulated_data
|
||||
|
||||
|
||||
%% TEMPLATE FOR AUTOMATIC TOMOGRAPHY CODE TESTS
|
||||
% test uses synthetic data to run all templates under well controlled
|
||||
% conditions, use setting if you want to add noise or other difficulties to
|
||||
% be tested during alignment
|
||||
if test_simulated_data
|
||||
utils.verbose(struct('prefix', 'Test simulated data'))
|
||||
run('tests/test_tomo_simulated_data.m')
|
||||
end
|
||||
clearvars -except GPU_id base_path test_real_data
|
||||
|
||||
if test_real_data
|
||||
utils.verbose(struct('prefix', 'Test real data'))
|
||||
run('tests/test_tomo_real_data.m')
|
||||
end
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
%% simple script to test performace of the MEX accelerated functions
|
||||
% utils.get_from_3D_projection and utils.add_to_3D_projection
|
||||
% the MEX functions use OpenMP to accelerate memory transfer from
|
||||
% large array into small sub array and back
|
||||
%
|
||||
% Matlab equivalent is :
|
||||
% small_array = full_array(1:Npix_small(1),1:Npix_small(2),1:Npix_small(3));
|
||||
% full_array(1:Npix_small(1),1:Npix_small(2),1:Npix_small(3)) = full_array(1:Npix_small(1),1:Npix_small(2),1:Npix_small(3)) + small_array;
|
||||
|
||||
|
||||
cd(fullfile( fileparts(mfilename('fullpath')), '..'))
|
||||
addpath('tests')
|
||||
addpath('utils')
|
||||
addpath('./')
|
||||
addpath(find_base_package)
|
||||
utils.verbose(0)
|
||||
|
||||
%% if needed, recompile the mex functions manually
|
||||
% cd cSAXS_matlab_base/+utils/private
|
||||
% if verLessThan('matlab', '9.4')
|
||||
% mex -largeArrayDims 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" get_from_3D_projection.cpp
|
||||
% mex -largeArrayDims 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" add_to_3D_projection.cpp
|
||||
% else
|
||||
% mex -R2018a 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" get_from_3D_projection_mex.cpp
|
||||
% mex -R2018a 'CFLAGS="\$CFLAGS -fopenmp"' LDFLAGS="\$LDFLAGS -fopenmp" add_to_3D_projection_mex.cpp
|
||||
% end
|
||||
|
||||
Npix_full = [600,600,600];
|
||||
Npix_small = [400,400,400];
|
||||
|
||||
utils.verbose(0,'--- get_from_3D_projection')
|
||||
full_array = randn(Npix_full, 'single')+1i;
|
||||
small_array = ones(Npix_small, 'like', single(1i));
|
||||
positions = (10*rand(Npix_small(3),2));
|
||||
indices = ([1:Npix_small(3)]); % indices start from 1
|
||||
|
||||
%% get 3D stack array "small_array" from 3D stack array "full_array" given the offsets "positions" and layers "indices"
|
||||
utils.verbose(0,'Speed test MEX')
|
||||
for ii = 1:3
|
||||
tic; utils.get_from_3D_projection(small_array,full_array,positions,indices); toc
|
||||
end
|
||||
|
||||
assert(norm(small_array(:)-reshape(utils.get_from_3D_projection(small_array,full_array,positions,indices, false),[],1))==0, 'get_from_3D_projection MEX function does not provide exact results')
|
||||
|
||||
|
||||
utils.verbose(0,'Speed test Matlab')
|
||||
for ii = 1:3
|
||||
tic; small_array = full_array(1:Npix_small(1),1:Npix_small(2),1:Npix_small(3)); toc
|
||||
end
|
||||
|
||||
%% add 3D stack array "small_array" into 3D stack array "full_array" given the offsets "positions" and layers "indices"
|
||||
utils.verbose(0,'--- add_to_3D_projection')
|
||||
full_array = zeros(Npix_full, 'like', single(1i));
|
||||
small_array = ones(Npix_small, 'like', single(1i));
|
||||
positions = (10*rand(Npix_small(3),2));
|
||||
indices = ([1:Npix_small(3)]); % indices are starting from 1 !!
|
||||
add_values = true;
|
||||
utils.verbose(0,'=== add values atomic')
|
||||
utils.verbose(0,'Speed test MEX')
|
||||
for ii = 1:3
|
||||
tic; utils.add_to_3D_projection(small_array,full_array,positions, indices,add_values, true);toc
|
||||
end
|
||||
|
||||
assert(norm(full_array(:)-reshape(utils.add_to_3D_projection(3*small_array,zeros(Npix_full, 'like', single(1i)),positions, indices,add_values,true,false),[],1))==0, 'add_to_3D_projection MEX function does not provide exact results')
|
||||
|
||||
utils.verbose(0,'Speed test Matlab')
|
||||
tic; full_array(1:Npix_small(1),1:Npix_small(2),1:Npix_small(3)) = full_array(1:Npix_small(1),1:Npix_small(2),1:Npix_small(3)) + small_array; toc
|
||||
|
||||
|
||||
%% set 3D stack array "small_array" into 3D stack array "full_array" given the offsets "positions" and layers "indices"
|
||||
utils.verbose(0,'=== add values nonatomic')
|
||||
add_values = true;
|
||||
utils.verbose(0,'Speed test MEX')
|
||||
full_array = zeros(Npix_full, 'like', single(1i));
|
||||
for ii = 1:3
|
||||
tic; utils.add_to_3D_projection(small_array,full_array,positions, indices,add_values, false);toc
|
||||
end
|
||||
assert(norm(full_array(:)-reshape(utils.add_to_3D_projection(3*small_array,zeros(Npix_full, 'like', single(1i)),positions, indices,add_values,false,false),[],1))==0, 'add_to_3D_projection MEX function does not provide exact results')
|
||||
|
||||
|
||||
utils.verbose(0,'Speed test Matlab')
|
||||
tic; full_array(1:Npix_small(1),1:Npix_small(2),1:Npix_small(3)) = full_array(1:Npix_small(1),1:Npix_small(2),1:Npix_small(3)) + small_array; toc
|
||||
%% set 3D stack array "small_array" into 3D stack array "full_array" given the offsets "positions" and layers "indices"
|
||||
utils.verbose(0,'=== set values')
|
||||
add_values = false;
|
||||
utils.verbose(0,'Speed test MEX')
|
||||
full_array = zeros(Npix_full, 'like', single(1i));
|
||||
for ii = 1:3
|
||||
tic; utils.add_to_3D_projection(small_array,full_array,positions, indices,add_values);toc
|
||||
end
|
||||
assert(norm(full_array(:)-reshape(utils.add_to_3D_projection(small_array,zeros(Npix_full, 'like', single(1i)),positions, indices,add_values,false,false),[],1))==0, 'add_to_3D_projection MEX function does not provide exact results')
|
||||
|
||||
utils.verbose(0,'Speed test Matlab')
|
||||
tic; full_array(1:Npix_small(1),1:Npix_small(2),1:Npix_small(3)) = small_array; 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) 2018 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
%| |
|
||||
%| Author: CXS group, PSI |
|
||||
%*-----------------------------------------------------------------------*
|
||||
% You may use this code with the following provisions:
|
||||
%
|
||||
% If the code is fully or partially redistributed, or rewritten in another
|
||||
% computing language this notice should be included in the redistribution.
|
||||
%
|
||||
% If this code, or subfunctions or parts of it, is used for research in a
|
||||
% publication or if it is fully or partially rewritten for another
|
||||
% computing language the authors and institution should be acknowledged
|
||||
% in written form in the publication: “Data processing was carried out
|
||||
% using the “cSAXS matlab package” developed by the CXS group,
|
||||
% Paul Scherrer Institut, Switzerland.”
|
||||
% Variations on the latter text can be incorporated upon discussion with
|
||||
% the CXS group if needed to more specifically reflect the use of the package
|
||||
% for the published work.
|
||||
%
|
||||
% A publication that focuses on describing features, or parameters, that
|
||||
% are already existing in the code should be first discussed with the
|
||||
% authors.
|
||||
%
|
||||
% This code and subroutines are part of a continuous development, they
|
||||
% are provided “as they are” without guarantees or liability on part
|
||||
% of PSI or the authors. It is the user responsibility to ensure its
|
||||
% proper use and the correctness of the results.
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
%% TEMPLATE FOR AUTOMATIC TOMOGRAPHY CODE TESTS
|
||||
% perform tests on measured dataset stored in /das/work/p16/p16812/
|
||||
|
||||
cd(fullfile( fileparts(mfilename('fullpath')), '..'))
|
||||
addpath('tests')
|
||||
addpath('utils')
|
||||
addpath('./')
|
||||
addpath(find_base_package)
|
||||
clearvars -except par0 tested_templates scratch_path GPU_id base_path test_simulated_data test_real_data base_path
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% Edit this section %%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
datasets = 1:5; % 1-nature chip, 2-FFC particle, 3-retina, 4-local tomo, 5-lamni chip
|
||||
|
||||
verbose_level = -1; % -1 = keep very quiet the reconstructions
|
||||
|
||||
scratch_path = '/das/work/p16/p16812/'; % path to the cSAXS scratch p-folder where are saved the test datasets
|
||||
|
||||
|
||||
if ~exist('GPU_id', 'var'); GPU_id = [1]; end
|
||||
if ~exist('base_path', 'var'); base_path = '../'; end
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
|
||||
utils.verbose(verbose_level)
|
||||
setenv('TMP',[base_path,'/tmp']) % TEMP for matlab scripts
|
||||
|
||||
utils.verbose(-1, '=== Searching for data in %s ====', scratch_path)
|
||||
|
||||
for dataset = datasets
|
||||
|
||||
par0 = struct();
|
||||
par0.GPU_list = GPU_id;
|
||||
|
||||
switch dataset
|
||||
case 1
|
||||
%% Nature chip 2016
|
||||
% test: large projections, phase residua/errors from sharp transitions
|
||||
tested_templates ={'template_tomo_recons'} ;
|
||||
par0.tomo_id = [];
|
||||
par0.scanstomo = [2718:3925];
|
||||
par0.fileprefix='online_'; % string at the beginning of the filename, related to reconstruction name
|
||||
par0.filesuffix = '_600x600_wrap_1_c'; % string searched at the end of the data filenames, No need to add _c or _recons, it will look for it
|
||||
par0.file_extension = 'mat';
|
||||
par0.analysis_path = fullfile(scratch_path, 'data/e16622_tomo_nature_chip_2016/analysis/');
|
||||
par0.surface_calib_file = [];
|
||||
par0.omnyposfile = fullfile(scratch_path, 'data/e16622_tomo_nature_chip_2016/specES1/scan_positions/scan_%05d.dat'); %Filename pattern for Orchestra interferometer position files
|
||||
par0.OMNY_angle_file = fullfile(scratch_path, 'data/e16622_tomo_nature_chip_2016/specES1/dat-files/tomography_scannumbers.txt'); % Filename with angles
|
||||
par0.max_residua_limit = inf; % limit used to determine which projection have failed
|
||||
|
||||
case 2
|
||||
%% johanness FCC catalyst
|
||||
% test: large projections, low freq. errors, periodic artefacts, vertically asymmetric sample
|
||||
tested_templates ={'template_tomo_recons'} ;
|
||||
par0.tomo_id = [];
|
||||
par0.scanstomo = [500:1349];
|
||||
par0.fileprefix='offline_'; % string at the beginning of the filename, related to reconstruction name
|
||||
par0.filesuffix = '500x500_run_1_recons'; % string searched at the end of the data filenames, No need to add _c or _recons, it will look for it
|
||||
par0.file_extension = 'mat';
|
||||
par0.analysis_path = fullfile(scratch_path, 'data/e16410_tomo_FCC_particle/analysis/');
|
||||
par0.surface_calib_file = [];
|
||||
par0.omnyposfile = fullfile(scratch_path, 'data/e16410_tomo_FCC_particle/specES1/scan_positions/scan_%05d.dat'); %Filename pattern for Orchestra interferometer position files
|
||||
par0.OMNY_angle_file = fullfile(scratch_path, 'data/e16410_tomo_FCC_particle/specES1/dat-files/tomography_scannumbers.txt'); % Filename with angles
|
||||
% solve in lower resolution
|
||||
par0.downsample_projections = 1;
|
||||
|
||||
case 3
|
||||
%% retina from OMNY
|
||||
% test: large projections, low freq. errors, huge phase jumps
|
||||
tested_templates ={'template_tomo_recons'} ;
|
||||
par0.tomo_id = [];
|
||||
par0.scanstomo = [1925:2384];
|
||||
par0.fileprefix='online_wrap_'; % string at the beginning of the filename, related to reconstruction name
|
||||
par0.filesuffix = '_452x452_run_1_c'; % string searched at the end of the data filenames, No need to add _c or _recons, it will look for it
|
||||
par0.file_extension = 'mat';
|
||||
par0.analysis_path = fullfile(scratch_path, 'data/e15634_retina_2015_OMNY/analysis/');
|
||||
par0.surface_calib_file = [];
|
||||
par0.omnyposfile = fullfile(scratch_path, 'data/e15634_retina_2015_OMNY/specES1/omny_recontruct/scan_%05d.dat'); %Filename pattern for Orchestra interferometer position files
|
||||
par0.OMNY_angle_file = fullfile(scratch_path, 'data/e15634_retina_2015_OMNY/specES1/dat-files/omny_scannumbers.txt'); % Filename with angles
|
||||
par0.downsample_projections = 1; % downsample projections by factor of 2^x, set 0 to do nothing and 1,2,.. for different levels of projection binning
|
||||
par0.auto_alignment = false;
|
||||
par0.get_auto_calibration = false;
|
||||
|
||||
case 4
|
||||
%% local tomo dataset !! THIS TEST TAKES ~1 HOUR and requires 200GB of RAM !!
|
||||
tested_templates ={'template_tomo_interior'} ;
|
||||
par0.tomo_id = []; % [68:74]; % Either scan numbers or tomo_id can be given, but not both, if not provided leave tomo_id=[]
|
||||
par0.scanstomo = 1700:7690;
|
||||
par0.lowres_tomo_path =fullfile(scratch_path, 'data/e17312_localtomo_FCC_particle/tomogram_delta_S00089_to_S01525_ram-lak_freqscl_1.00.mat');
|
||||
|
||||
% IO loading
|
||||
par0.fileprefix=''; % string at the beginning of the filename, related to reconstruction name
|
||||
par0.filesuffix = '_recons'; % string searched at the end of the data filenames, No need to add _c or _recons, it will look for it
|
||||
par0.file_extension = 'h5';
|
||||
par0.downsample_projections = 0; % downsample projections by factor of 2^x, set 0 to do nothing and 1,2,.. for different levels of projection binning
|
||||
par0.analysis_path = fullfile(scratch_path, 'data/e17312_localtomo_FCC_particle/analysis/');
|
||||
|
||||
par0.clip_amplitude_quantile = 0.95; % clip amplitudes in the loaded projections that are exceeding given quantile, if par0.clip_amplitude_quantile == 1, do nothing
|
||||
par0.max_residua_limit = 100; % limit used to determine which projection have failed
|
||||
par0.surface_calib_file = [];
|
||||
par0.omnyposfile = fullfile(scratch_path, 'data/e17312_localtomo_FCC_particle/specES1/scan_positions/scan_%05d.dat'); %Filename pattern for Orchestra interferometer position files
|
||||
par0.OMNY_angle_file = fullfile(scratch_path, 'data/e17312_localtomo_FCC_particle/specES1/dat-files/tomography_scannumbers.txt'); % Filename with angles
|
||||
|
||||
% Other
|
||||
par0.save_memory = false; % try to limit use of RAM
|
||||
par0.inplace_processing = par0.save_memory; % process object_stack using inplace operations to save memory
|
||||
par0.fp16_precision = true; % use 16-bit precision to store the complex-valued projections
|
||||
par0.cache_stack_object = par0.save_memory; % store stack_object to disk when no needed
|
||||
|
||||
|
||||
case 5
|
||||
%% lamni chip dataset !! THIS TEST TAKES SEVERAL HOURS and requires full RAM !!
|
||||
tested_templates ={'template_tomo_recons_lamino'} ;
|
||||
% par0.scanstomo = [984:1850]; %2326]; % smaller angular range
|
||||
par0.scanstomo = [984:3717]; % full angular range
|
||||
par0.tomo_id = []; % Either scan numbers or tomo_id can be given, but not both, if not provided leave tomo_id=[]
|
||||
|
||||
% IO loading
|
||||
par0.fileprefix=''; % string at the beginning of the filename, related to reconstruction name
|
||||
par0.filesuffix = 'test_1'; %% string searched at the end of the data filenames, No need to add _c or _recons, it will look for it
|
||||
par0.file_extension = 'h5';
|
||||
par0.downsample_projections = 0; % downsample projections by factor of 2^x, set 0 to do nothing and 1,2,.. for different levels of projection binning
|
||||
par0.analysis_path = fullfile(scratch_path, 'data/e17299_lamni_chip_dataset_2018/analysis/');
|
||||
|
||||
par0.clip_amplitude_quantile = 0.95; % clip amplitudes in the loaded projections that are exceeding given quantile, if par0.clip_amplitude_quantile == 1, do nothing
|
||||
par0.max_residua_limit = 100; % limit used to determine which projection have failed
|
||||
par0.surface_calib_file = [];
|
||||
par0.omnyposfile = fullfile(scratch_path, 'data/e17299_lamni_chip_dataset_2018/specES1/scan_positions/scan_%05d.dat'); %Filename pattern for Orchestra interferometer position files
|
||||
par0.OMNY_angle_file = fullfile(scratch_path, 'data/e17299_lamni_chip_dataset_2018/specES1/dat-files/tomography_scannumbers.txt'); % Filename with angles
|
||||
|
||||
% Other
|
||||
par0.save_memory = true; % try to limit use of RAM
|
||||
par0.inplace_processing = par0.save_memory; % process object_stack using inplace operations to save memory
|
||||
par0.fp16_precision = par0.save_memory; % use 16-bit precision to store the complex-valued projections
|
||||
par0.cache_stack_object = par0.save_memory; % store stack_object to disk when no needed
|
||||
otherwise
|
||||
error('Missing dataset')
|
||||
end
|
||||
|
||||
|
||||
|
||||
for tested_template = tested_templates
|
||||
clearvars -except par0 tested_template tested_templates scratch_path GPU_id base_path test_simulated_data test_real_data base_path
|
||||
|
||||
utils.verbose(struct('prefix', 'init'))
|
||||
|
||||
%% test stage 0: load basic configuration parameters
|
||||
utils.verbose(-1,'====================================================')
|
||||
utils.verbose(-1,'===== Testing template "%s" ============', tested_template{1})
|
||||
utils.verbose(-1,'====================================================')
|
||||
|
||||
% set debugging info level and marks
|
||||
debug(1)
|
||||
warning('off', 'MATLAB:mpath:nameNonexistentOrNotADirectory')
|
||||
warning('off', 'MATLAB:dispatcher:pathWarning')
|
||||
|
||||
run(tested_template{1})
|
||||
|
||||
for item = fieldnames(par0)'
|
||||
par.(item{1}) = par0.(item{1});
|
||||
end
|
||||
|
||||
|
||||
%% test stage 1: load test data and continue with the remplate
|
||||
utils.verbose(-1,'Running template')
|
||||
|
||||
debug(3)
|
||||
utils.verbose(struct('prefix', 'template'))
|
||||
run(tested_template{1})
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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.
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
%% TEMPLATE FOR AUTOMATIC TOMOGRAPHY CODE TESTS
|
||||
% test uses synthetic data to run all templates under well controlled
|
||||
% conditions, use setting if you want to add noise or other difficulties to
|
||||
% be tested during alignment
|
||||
cd(fullfile( fileparts(mfilename('fullpath')), '..'))
|
||||
addpath('tests')
|
||||
addpath('utils')
|
||||
addpath('./')
|
||||
addpath(find_base_package)
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% Edit this section %%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
tested_templates = 1:3; % IDs of the tested templates
|
||||
|
||||
templates_list ={ 'template_tomo_recons', ...
|
||||
'template_tomo_recons_lamino', ...
|
||||
'template_tomo_nonrigid', ...
|
||||
'template_tomo_recons_deprecated'...
|
||||
};
|
||||
|
||||
|
||||
verbose_level = -1; % -1 = keep very quiet the reconstructions
|
||||
|
||||
% artificial data settings
|
||||
Npix_vol = [200,200,200] ;
|
||||
undersampling = 1; % level of undersampling compared to Crowther criterion
|
||||
noise_level = 0; % relative noise level with respect to the maximal phase value in the projections
|
||||
N_subtomos = 4;
|
||||
add_residual_layer = false; % add a thin metal-like layer to test behaviour with residua
|
||||
Nangles = ceil(pi/2*Npix_vol(1)) / undersampling;
|
||||
Nangles = ceil(Nangles/N_subtomos)*N_subtomos; % make splitable for 4 subtomos
|
||||
asize = ceil(Npix_vol(1:2) / 10); % size of the simulated probe
|
||||
|
||||
if ~exist('GPU_id', 'var'); GPU_id = [1]; end
|
||||
if ~exist('base_path', 'var'); base_path = '../'; end
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
|
||||
assert(all(GPU_id <= gpuDeviceCount), 'Select valid GPU id in GPU_id')
|
||||
|
||||
utils.verbose(verbose_level)
|
||||
setenv('TMP',[base_path,'/tmp']) % TEMP for matlab scripts
|
||||
|
||||
|
||||
|
||||
%% MAKE A PHANTOM
|
||||
utils.verbose(-1,'Creating phantom')
|
||||
rng default
|
||||
volData = randn(Npix_vol - asize(1), 'single');
|
||||
volData = (0.5+0.5*(utils.imgaussfilt3_fft(volData, 3) > 0)) .* ...
|
||||
(utils.imgaussfilt3_fft(volData, 10) > 0);
|
||||
volData = utils.imgaussfilt3_conv(volData, 0.6); % prevent too sharp edges
|
||||
|
||||
if add_residual_layer
|
||||
% add kind of metalic layer to test robustness of the codes
|
||||
[X,Y,Z] = meshgrid(-Npix_vol(1)/2:Npix_vol(1)/2-1,-Npix_vol(2)/2:Npix_vol(2)/2-1,-Npix_vol(3)/2:Npix_vol(3)/2-1);
|
||||
layer = abs(0.1*X + 0.5*Y+0.2*Z + 50*utils.imgaussfilt3_fft(randn(Npix_vol, 'single'),10) )<0.5;
|
||||
volData = volData + 10*utils.crop_pad_3D(layer, size(volData));
|
||||
end
|
||||
volData = utils.apply_3D_apodization(volData, 0, Npix_vol(1)/5, 1);
|
||||
volData = utils.crop_pad_3D(volData, Npix_vol);
|
||||
|
||||
for tested_template = templates_list(tested_templates)
|
||||
utils.verbose(struct('prefix', 'init'))
|
||||
|
||||
%% test stage 0: load basic configuration parameters
|
||||
utils.verbose(-1,'Loading template "%s"', tested_template{1})
|
||||
if strcmpi(tested_template{1}, 'template_tomo_nonrigid')
|
||||
%nonrigid tomo has data generation already included in the template
|
||||
debug(1)
|
||||
run(tested_template{1})
|
||||
else
|
||||
par = struct();
|
||||
par.lamino_angle = 90; % default setting
|
||||
|
||||
% set debugging info level and marks
|
||||
debug(1)
|
||||
warning('off', 'MATLAB:mpath:nameNonexistentOrNotADirectory')
|
||||
warning('off', 'MATLAB:dispatcher:pathWarning')
|
||||
|
||||
run(tested_template{1})
|
||||
|
||||
utils.verbose(-1,'Creating data')
|
||||
|
||||
% create "data"
|
||||
if ~par.is_laminography
|
||||
theta = pi+linspace(0, 180*(1-1/Nangles), Nangles);
|
||||
else
|
||||
Nangles = Nangles * 2;
|
||||
theta = pi+linspace(0, 360*(1-1/Nangles), Nangles);
|
||||
end
|
||||
|
||||
% create "N_subtomos" subtomos
|
||||
theta = reshape(reshape(theta, N_subtomos,[])',1,[]);
|
||||
par.subtomos = reshape(ones(Nangles/N_subtomos,N_subtomos).*[1:N_subtomos],1,[]);
|
||||
|
||||
% Add noise and offsets to the measured positions to make the
|
||||
% alignment more difficult
|
||||
position_errors = (0.1*randn(Nangles,2) + 0.1*sind(3*theta')) * Npix_vol(3);
|
||||
|
||||
asize = asize + ceil(max(asize, max(abs(position_errors)))/32)*32; % avoid the sample going out of FOV
|
||||
par.asize = asize;
|
||||
|
||||
if par.lamino_angle == 90
|
||||
Npix_proj = [Npix_vol(3), ceil(sqrt(2)*Npix_vol(1))]+asize;
|
||||
max_sample_height = inf;
|
||||
else
|
||||
Npix_proj = ceil(sqrt(2)*Npix_vol([3,1]) .* [cosd(par.lamino_angle), 1] )+asize;
|
||||
max_sample_height = 5e-6 ;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
% provide other parameters required by the template
|
||||
par.factor = 1;
|
||||
par.factor_edensity = 1;
|
||||
par.pixel_size = 50e-9;
|
||||
par.scans_string = '';
|
||||
par.output_folder = '???'; % some nonexistent folder, in default the template should not write any data during debug mode
|
||||
obj_interf_pos_x = 0;
|
||||
obj_interf_pos_y = 0;
|
||||
delta_stack_prealign = [] ;
|
||||
par.tilt_angle = 0;
|
||||
par.skewness_angle = 0;
|
||||
par.lambda = 0.2e-9;
|
||||
par.scanstomo = 1:Nangles;
|
||||
par.air_gap = [5,5];
|
||||
par.GPU_list = GPU_id;
|
||||
par.nresidua_per_frame = 0;
|
||||
|
||||
% generate geometry
|
||||
Npix_vol(3) = min(Npix_vol(3),ceil(max_sample_height / par.pixel_size)-1);
|
||||
|
||||
CoR = Npix_proj/2 + position_errors;
|
||||
[cfg, vectors] = astra.ASTRA_initialize(Npix_vol, Npix_proj, theta, par.lamino_angle, 'rotation_center', CoR);
|
||||
% find optimal split, for small volumes below 600^3 no split is needed
|
||||
split = astra.ASTRA_find_optimal_split(cfg);
|
||||
par.illum_sum = ones(Npix_proj);
|
||||
|
||||
|
||||
% generate complex projections
|
||||
stack_object = tomo.Ax_sup_partial(utils.crop_pad_3D(volData, Npix_vol), cfg, vectors, split);
|
||||
stack_object = stack_object / math.sp_quantile(stack_object, 0.99, 10);
|
||||
if noise_level>0; stack_object = stack_object + noise_level * randn(size(stack_object)); end
|
||||
stack_object = exp(-0.1*stack_object - 4i*stack_object);
|
||||
|
||||
object = stack_object(:,:,1);
|
||||
|
||||
|
||||
if strcmpi(tested_template, 'template_tomo_recons_lamino')
|
||||
% create errors in global geometry -> test automatic refinement
|
||||
par.tilt_angle = -0.5;
|
||||
par.skewness_angle = 0.5;
|
||||
else
|
||||
par.tilt_angle = 0;
|
||||
par.skewness_angle = 0;
|
||||
end
|
||||
|
||||
|
||||
%% test stage 1: load test data and continue with the remplate
|
||||
utils.verbose(-1,'Loading template "%s"', tested_template{1})
|
||||
|
||||
debug(2)
|
||||
utils.verbose(struct('prefix', 'template'))
|
||||
run(tested_template{1})
|
||||
|
||||
|
||||
% check results of the geometry refinement provided by tests
|
||||
if strcmpi(tested_template, 'template_tomo_recons_lamino')
|
||||
assert(abs(par.tilt_angle) < 0.1 && abs(par.skewness_angle) < 0.1, 'Geometry refinement in laminography did not work well')
|
||||
end
|
||||
end
|
||||
clearvars -except par tested_templates Nangles volData Npix_vol asize N_subtomos GPU_id noise_level test_astra test_mex_function test_simulated_data test_real_data base_path
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| 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.
|
||||
|
||||
Reference in New Issue
Block a user