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
+414
View File
@@ -0,0 +1,414 @@
% Call function without arguments for instructions on how to use it
% Filename: $RCSfile: tune_valid_mask.m,v $
%
% $Revision: 1.5 $ $Date: 2012/09/02 15:13:40 $
% $Author: bunk $
% $Tag: $
%
% Description:
% remove outlyers of intensity that deviates from the azimuthal integration
% from the valid pixel mask
%
% Note:
% Call without arguments for a brief help text.
%
% Dependencies:
% - image_read
%
% history:
%
% May 21st 2010, Oliver Bunk:
% 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 [valid_mask] = tune_valid_mask(data_dir, varargin)
import beamline.radial_integ
import io.image_read
import plotting.display_valid_mask
import utils.find_files
% set default values for the variable input arguments:
% directory with the integrated data files
indir_integ_data = '~/Data10/analysis/radial_integration/';
% filename of the integrated data, empty to determine it from the raw data
% file name
filename_integ_data = [];
% use all cbf files
filename_mask = '*.cbf';
% filename for loading and saving the valid pixel mask
filename_valid_mask = '~/Data10/analysis/data/pilatus_valid_mask.mat';
% integration masks
filename_integ_masks = '~/Data10/analysis/data/pilatus_integration_masks.mat';
% size of the median filter that is use to smooth the data for identifying
% outlyers
median_size = 11;
% first pixel to start at
radius_from = 20;
% last pixel to check
radius_to = 0;
% only intensities above this threshold are considered for being hot
threshold_hot = 5;
% this value times the standard deviation of the intensity is used as hot pixel
% threshold
threshold_median = 3.0;
% save the updated mask
save_data = 0;
% display result in this figure
fig_no = 201;
% matching files to use
point_range = [];
% check minimum number of input arguments
if (nargin < 1)
fprintf('\nUsage:\n');
fprintf('[valid_mask]=%s(data_dir [[,<name>,<value>]...]);\n',mfilename);
fprintf('Remove outlyers from the valid pixel mask by comparing azimuthally integrated data\n');
fprintf('against the same data median filtered and rejecting pixels with a deviation\n');
fprintf('in intensity specified in multiples of the standard deviation.\n');
fprintf('\n');
fprintf('The optional <name>,<value> pairs are:\n');
fprintf('''FilenameMask'',<file specifier> specify the files to be used from the data directory, empty string for all, default is ''%s''\n',...
filename_mask);
fprintf('''PointRange'',<vector or []> matching files to use, default is [] for all files\n');
fprintf('''IndirIntegData'',<filename.mat> directory with the azimuthally integrated data, default is %s\n',...
indir_integ_data);
fprintf('''FilenameIntegData'',<filename.mat> filename for the azimuthally integrated data, empty to determine the name\n');
fprintf(' from the first raw data file name, default is ''%s''\n',...
filename_integ_data);
fprintf('''FilenameIntegMasks'',<filename> Matlab file containing the integration masks, default is ''%s''\n',filename_integ_masks);
fprintf('''RadiusFrom'',<integer> no. of the pixel to start with, default is %.0f\n',radius_from);
fprintf('''RadiusTo'',<integer> no. of the last pixel to check, default is %.0f\n',radius_to);
fprintf('''MedianSize'',<integer> size of the median filter in pixels, default is %.0f\n',...
median_size);
fprintf('''ThresholdHot'',<float> pixels above this value are considered for being hot, default is %d\n',...
threshold_hot);
fprintf('''ThresholdMedian'',<float> pixels outside the range (I+/-threshold_median*sqrt(I))\n');
fprintf(' of the median filtered data are considered to be hot,\n');
fprintf(' default is %.1f\n',...
threshold_median);
fprintf('''SaveData'',<0-no,1-yes> save the valid pixel mask, default is %d\n',save_data);
fprintf('''FilenameValidMask'',<path and filename> Matlab file with the valid pixel indices,\n');
fprintf(' default is %s\n',filename_valid_mask);
fprintf('''FigNo'',<integer> number of the figure in which the result is displayed, default is %d\n',...
fig_no);
fprintf('\n');
fprintf('Examples:\n');
fprintf('[valid_mask]=%s(''~/Data10/pilatus/S05000-05999/S05715/e12612_1_05715_00000_00000.cbf'');\n',...
mfilename);
fprintf('[valid_mask]=%s(''~/Data10/pilatus/S05000-05999/S05715/*.cbf'');\n',...
mfilename);
error('At least the filename of the raw data 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 = 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 'FilenameIntegMasks'
filename_integ_masks = value;
case 'FilenameMask'
filename_mask = value;
case 'PointRange'
point_range = value;
case 'IndirIntegData'
indir_integ_data = value;
case 'FilenameIntegData'
filename_integ_data = value;
case 'RadiusFrom',
radius_from = round(value);
case 'RadiusTo',
radius_to = round(value);
case 'MedianSize'
median_size = round(value);
case 'ThresholdMedian'
threshold_median = value;
case 'ThresholdHot'
threshold_hot = value;
case 'FilenameValidMask'
filename_valid_mask = value;
case 'SaveData'
save_data = value;
case 'FigNo'
fig_no = value;
otherwise
vararg_remain{end+1} = name; %#ok<AGROW>
vararg_remain{end+1} = value; %#ok<AGROW>
end
end
vararg_remain{end+1} = 'UnhandledParError';
vararg_remain{end+1} = 0;
vararg_remain{end+1} = 'DisplayFilename';
vararg_remain{end+1} = 0;
% set some default values for the plot window
set(0, 'DefaultAxesfontsize', 12);
set(0, 'DefaultAxeslinewidth', 1, 'DefaultAxesfontsize', 12);
set(0, 'DefaultLinelinewidth', 1);
% get all matching filenames
if (data_dir(end) ~= '/')
data_dir(end+1) = '/';
end
[data_dir,fnames,vararg_remain] = ...
find_files( [ data_dir filename_mask ], vararg_remain );
if (length(fnames) < 1)
error('No matching files found for %s%s.\n',data_dir,filename_mask);
end
% load the current valid pixel mask in variable valid_mask
fprintf('loading the existing valid mask %s\n',filename_valid_mask);
load(filename_valid_mask);
framesize = valid_mask.framesize(1) * valid_mask.framesize(2);
% load the integration masks in variable integ_masks
fprintf('Loading the integration masks from %s\n',filename_integ_masks);
load(filename_integ_masks);
no_of_radii = length(integ_masks.radius);
if ((radius_to < radius_from) || (radius_to > no_of_radii))
radius_to = no_of_radii;
end
% process the frames
ind_hot = [];
ind_dark = [];
integ_data = [];
fprintf('data directory is %s\n',data_dir);
if (isempty(point_range))
point_range = 1:length(fnames);
else
ind = find(point_range <= length(fnames));
if (length(point_range) ~= length(ind))
fprintf('Warning, %d value(s) from the specified point range are out of the range [1,%.0f] and not used.\n',...
length(point_range)-length(ind),length(fnames));
point_range = point_range(ind);
end
end
for (point_ind=1:length(point_range))
f_ind = point_range(point_ind);
% read the raw data
fprintf('%3d/%3d: reading %s%s\n',f_ind,length(point_range),...
data_dir,fnames(f_ind).name);
filename_raw = [data_dir fnames(f_ind).name ];
[frame] = image_read(filename_raw,vararg_remain);
% check that the files have identical dimensions
if ((size(frame.data,1) ~= valid_mask.framesize(1)) || ...
(size(frame.data,2) ~= valid_mask.framesize(2)))
error('The valid pixel mask has %d x %d pixels, this frame has %d x %d pixels',...
valid_mask.framesize(1),valid_mask.framesize(2),...
size(frame.data,1),size(frame.data,2));
end
% read the radially integrated data
if (isempty(integ_data))
% determine filename for the integrated data from the first raw
% data filename
if (isempty(filename_integ_data))
[pathstr, filename_integ_data] = fileparts(fnames(f_ind).name);
filename_integ_data = [ filename_integ_data '_integ.mat' ]; %#ok<AGROW>
end
filename_integ_data = fullfile(indir_integ_data,filename_integ_data);
fprintf('Loading the integrated intensities from %s\n',...
filename_integ_data);
integ_data = load(filename_integ_data);
% take the median of all segments with positive intensities, i.e.,
% skip negative intensities
I_all_prev = integ_data.I_all;
no_of_segments = size(I_all_prev,2);
no_of_points = size(I_all_prev,3);
I_all = zeros(no_of_radii,no_of_points);
I_std = zeros(no_of_radii,no_of_points);
if (no_of_segments > 1)
fprintf('Using the median of %d segments.\n',no_of_segments);
end
for (ind1=1:no_of_radii)
for (ind3=1:no_of_points)
no_of_el = 0;
I_use = zeros(1,no_of_segments);
ind_I_use = zeros(1,no_of_segments);
for (ind2=1:no_of_segments)
if (I_all_prev(ind1,ind2,ind3) >= 0)
no_of_el = no_of_el +1;
I_use(no_of_el) = I_all_prev(ind1,ind2,ind3);
ind_I_use(no_of_el) = ind2;
end
end
if (no_of_el > 1)
[I_sorted,ind_sorted] = sort(I_use(1:no_of_el));
ind_median = round(0.5*no_of_el);
I_all(ind1,ind3) = I_sorted(ind_median);
% get the standard deviation of this intensity
I_std(ind1,ind3) = integ_data.I_std(ind1,ind_I_use(ind_sorted(ind_median)),ind3);
end
end
end
% print this information once rather than for each file
fprintf('Checking radii from %d to %d.\n',radius_from,radius_to);
end
% get the index to the integrated data
ind = 1;
ind_max = length(integ_data.filenames_all);
while ((ind <= ind_max) && ...
(isempty(strfind(integ_data.filenames_all{ind},fnames(f_ind).name))))
ind = ind +1;
end
if (ind > ind_max)
error('Could not find integrated data for raw data file %s in %s.',...
filename_raw,filename_integ_data);
end
data_integ = squeeze(I_all(:,ind));
data_integ_std = squeeze(I_std(:,ind));
% median filtered data for comparison
data_integ_med = medfilt1(data_integ,median_size,size(data_integ,1),1);
% figure(fig_no+2);
% hold off;
% clf;
% semilogy(data_integ);
% hold all;
% semilogy(data_integ_med);
% semilogy(data_integ_med+data_integ_std*threshold_median);
% semilogy(data_integ_med-data_integ_std*threshold_median);
frame_cmp = ones(valid_mask.framesize) -2;
frame_cmp_std = zeros(valid_mask.framesize);
for (ind_r = radius_from:radius_to)
for (ind_seg = 1:no_of_segments)
if (integ_masks.norm_sum(ind_r,ind_seg) > 0)
frame_cmp(integ_masks.indices{ind_r,ind_seg}) = ...
data_integ_med(ind_r);
frame_cmp_std(integ_masks.indices{ind_r,ind_seg}) = ...
data_integ_std(ind_r);
end
end
end
%
ind_dark = union(ind_dark, ...
find((frame.data >= 0) & ...
(frame_cmp >= 0) & ...
(frame.data < frame_cmp - threshold_median*frame_cmp_std)));
% only consider pixels of sufficient intensity for being hot
ind_hot = union(ind_hot, ...
find((frame.data > threshold_hot) & ...
(frame_cmp >= 0) & ...
(frame.data > frame_cmp + threshold_median*frame_cmp_std)));
end
% calculate the complementary masks of the valid pixels
valid_mask.indices = intersect(valid_mask.indices,...
setdiff(1:framesize,union(ind_dark,ind_hot)));
fprintf('In total %d dark and %d hot pixels found.\n',...
length(ind_dark),length(ind_hot));
fprintf('%d valid pixels remain.\n',length(valid_mask.indices));
if (save_data)
% create a backup of the mask
if (exist(filename_valid_mask,'file'))
filename_mask_backup = [ filename_valid_mask '.bak' ];
fprintf('Copying the current mask %s to %s\n',filename_valid_mask,...
filename_mask_backup);
copyfile(filename_valid_mask,filename_mask_backup);
end
% save the masks
fprintf('Saving valid_mask to %s\n',filename_valid_mask);
save(filename_valid_mask,'valid_mask');
% plot new valid pixel mask
display_valid_mask('FilenameValidMask',filename_valid_mask,...
'NoHelp',1,'FigNo',fig_no);
else
fprintf('The updated valid pixel mask is NOT saved.\n');
end
% plot the additional invalid pixels
figure(fig_no+1);
% mark the valid pixels as 1, leave the invalid at 0
frame = zeros(valid_mask.framesize);
frame(valid_mask.indices) = 1;
frame(ind_dark) = -10;
frame(ind_hot) = 10;
imagesc(frame);
caxis([-10 10]);
axis xy;
axis equal;
axis tight;
colorbar;
title_str = ['valid pixels, ' ...
num2str(length(ind_dark)+length(ind_hot),'%d') ...
' update(s) marked with intensity -10/10'];
title(title_str);
set(gcf,'Name','valid pixels, updates marked');