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
+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