%LOAD_PREPARED_DATA Load prepared data file and convert it into the default Matlab %structure % % filename path and filename of the h5 file % % *optional* % return_intensity return intensity or magnitude; default false (= return magnitude) % scan select scan, either integer or array % enum return only selected frames % return_fftshifted return results fftshifted, default == true % % *returns*: % fmag fourier magnitudes of the measured data, ie fftshift(sqrt(data)) % fmask mask of the fourier magnitudes, 1 for bad pixels, 0 for other % pos scanning positions (Npos x 2 array) % max_power maximal intesity (max(sum(sum(fmag,1),2),[],3) / numel(fmag(:,:,1));) % scanindexrange indices corresponding to each of the scans % max_sum something stored in h5_data.measurement.(['n' num2str(ii-1)]).Attributes.max_sum; % % Examples: % [fmag, fmask, ~] = load_prepared_data('~/Data10/analysis/S00668/S00668_S00669_data_400x400.h5'); % [fmag, fmask, pos] = load_prepared_data('~/Data10/analysis/S00668/S00668_S00669_data_400x400.h5'); % % % load intensities % [I, ~, ~] = load_prepared_data('~/Data10/analysis/S00668/S00668_S00669_data_400x400.h5', true); % % % load data from second scan % [fmag, fmask, pos] = load_prepared_data('~/Data10/analysis/S00668/S00668_S00669_data_400x400.h5', false, 2); % % % load data from scan 1 and 3 % [fmag, fmask, pos] = load_prepared_data('~/Data10/analysis/S00668/S00668_S00669_data_400x400.h5', false, [1 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 [ fmag, fmask, pos, max_power, scanindexrange, max_sum ] = load_prepared_data( filename, return_intensity, enum, return_fftshifted ) import io.HDF.hdf5_load if nargin < 2 return_intensity = false; % return intensity as measured by detector end if nargin < 3 enum = []; % return only selected frames end if nargin < 4 return_fftshifted = true; % return data fftshifted, !! DEFAULT == true !! end if ~exist(filename, 'file'); error('Cannot load %s', filename); end %% compatility to load also old matlab datasets [~,~,ext]=fileparts(filename); if strcmpi(ext, '.mat') d = load(filename); fmag = d.data; fmask = d.fmask; if ~return_intensity % normalize to provide similar data as in h5-mex max_power = max(sum(sum(fmag,1),2),[],3) / numel(fmag(:,:,1)); renorm = sqrt(1/max_power); fmag = sqrt(fmag)*renorm; end if return_fftshifted fmag = math.fftshift_2D(fmag); fmask = math.fftshift_2D(fmask); end return end %% load h5 file recon = false; inf = h5info(filename); for ii=1:numel(inf.Groups) if strcmpi(inf.Groups(ii).Name, '/reconstruction') recon = true; end end if recon h5_data = hdf5_load(filename, '/measurement/data', '-a'); else h5_data = hdf5_load(filename, '-a'); end if isfield(h5_data, 'reconstruction') h5_data = h5_data.measurement.data; end %% check hdf5 data verion (python or mex data prep?) if isfield(h5_data, 'measurements') h5_version = 'mex'; else h5_version = 'LibDetXR'; end switch h5_version case 'mex' warning('Outdated data format.') asize = size(h5_data.measurements.measurement_0.diff_pat.Value); fn = fieldnames(h5_data.measurements); numpts = length(fn)-1; fmag = zeros(asize(1), asize(2), numpts); fmask = ones(asize(1), asize(2), numpts); pos = zeros(numpts, 2); if isempty(enum) enum = 1:length(fieldnames(h5_data.detectors))-1; end for ii=enum fmaskdet{ii} = zeros(asize(1),asize(2)); modules = transpose(h5_data.detectors.(['detector_' num2str(ii-1)]).modules.Value); numrows = modules(:,1); numcols = modules(:,2); indbeginmody = modules(:,3)+1; indbeginmodx = modules(:,4)+1; indendmody = numrows + indbeginmody -1; indendmodx = numcols + indbeginmodx -1; nummody = length(indbeginmody); nummodx = length(indbeginmodx); for kk = 1:nummody for jj = 1:nummodx fmaskdet{ii}(indbeginmody(kk):indendmody(kk),indbeginmodx(jj):indendmodx(jj))=1; end end end scanindexrange = ones([2 length(enum)]); cid=1; for ii=1:numpts cf =['measurement_' num2str(ii-1)]; det = h5_data.measurements.(cf).Attributes.detector; if any(enum==det+1) if ii>scanindexrange(2,det+1) scanindexrange(2,det+1) = ii; end fmag(:,:,cid) = transpose(h5_data.measurements.(cf).diff_pat.Value); if isfield(h5_data.measurements.(cf), 'bad_pixels') bp_temp = h5_data.measurements.(cf).bad_pixels.Value; else bp_temp = []; end pos(cid, :) = h5_data.measurements.(cf).Attributes.position; fmask(:,:,cid) = fmaskdet{det+1}; if ~isempty(bp_temp) for kk=1:size(bp_temp,2) fmask(bp_temp(1,kk)+1,bp_temp(2,kk)+1,cid) = 0; end end cid = cid + 1; end end fmag = fmag(:,:,1:cid-1); fmask = fmask(:,:,1:cid-1); pos = pos(1:cid-1,:); % attr = hdf5_load(filename, '/measurements/','-sa'); max_power = h5_data.measurements.Attributes.max_power; fmask = logical(fmask); if return_intensity renorm = sqrt(1/max_power); fmag = (fmag/renorm).^2; end scanindexrange = scanindexrange'; for ii=2:length(enum) scanindexrange(ii,1) = scanindexrange(ii-1,2)+1; end case 'LibDetXR' %% get data dims fmag_dim(1) = 0; fmag_dim(2) = 1; if isempty(enum) enum = 1:length(fieldnames(h5_data.measurement))-1; end for ii=enum fmag_temp{ii} = h5_data.measurement.(['n' num2str(ii-1)]).data.Value; fmag_dim(ii+2) = size(fmag_temp{ii},3); end asize = size(fmag_temp{enum(1)}); if asize(1) ~= asize(2) error('Loading of asymmetric prepated datasets not supported, use p.force_preparation_data=true') end fmag = zeros(asize(1), asize(2), sum(fmag_dim)-1, 'single'); fmask = ones(asize(1), asize(2), sum(fmag_dim)-1, 'logical'); pos = zeros(sum(fmag_dim)-1, 2); max_sum = zeros(length(enum), 1); %% load modules to prepare fmask and load everything into containers if isempty(enum) enum = 1:length(fieldnames(h5_data.detector)); end for ii=enum % get modules for mask fmaskdet{ii} = zeros(asize(1),asize(2), 'logical'); modules = transpose(h5_data.detector.(['n' num2str(ii-1)]).modules.Value); numrows = modules(:,1); numcols = modules(:,2); indbeginmody = modules(:,3)+1; indbeginmodx = modules(:,4)+1; indendmody = numrows + indbeginmody -1; indendmodx = numcols + indbeginmodx -1; nummody = length(indbeginmody); nummodx = length(indbeginmodx); for kk = 1:nummody for jj = 1:nummodx fmaskdet{ii}(indbeginmody(kk):indendmody(kk),indbeginmodx(jj):indendmodx(jj))=1; end end temp_range = sum(fmag_dim(1:ii+1)):sum(fmag_dim(1:ii+2))-1; fmask(:,:,temp_range) = repmat(fmaskdet{ii},[1,1,fmag_dim(ii+2)]); % get bad pixels if isfield(h5_data.detector.(['n' num2str(ii-1)]), 'bad_pixels') bp = h5_data.detector.(['n' num2str(ii-1)]).bad_pixels.Value; for kk=1:size(bp,2) fmask(bp(1,kk)+1,bp(2,kk)+1,temp_range) = 0; end else if isfield(h5_data.measurement.(['n' num2str(ii-1)]), 'bad_pixels') bp = h5_data.measurement.(['n' num2str(ii-1)]).bad_pixels.Value; bpi = h5_data.measurement.(['n' num2str(ii-1)]).bad_pixels_index.Value; assert(length(bpi)==length(temp_range), 'Number of frames does not match the number of bad pixel datasets.') offset = 1; for kk=1:length(bpi) for jj=offset:bpi(kk) fmask(bp(1,jj)+1, bp(2,jj)+1, temp_range(kk)) = 0; end offset = bpi(kk); end end end fmag(:,:,temp_range) = permute(fmag_temp{ii}, [2 1 3]); pos_temp = h5_data.measurement.(['n' num2str(ii-1)]).positions.Value; pos(temp_range,1) = pos_temp(1,:); pos(temp_range,2) = pos_temp(2,:); max_sum(enum) = h5_data.measurement.(['n' num2str(ii-1)]).Attributes.max_sum; end % normalize to provide similar data as in h5-mex max_power = max(sum(sum(fmag,1),2),[],3) / numel(fmag(:,:,1)); renorm = sqrt(1/max_power); if ~return_intensity fmag = sqrt(fmag)*renorm; end fmask = logical(fmask); scanindexrange = zeros(numel(enum),2); scanindexrange(1,:) = fmag_dim(2:3); for ii=2:numel(enum) scanindexrange(ii,1) = scanindexrange(ii-1,2)+1; scanindexrange(ii,2) = scanindexrange(ii-1,2)+fmag_dim(ii+2); end otherwise error('Unknown HDF5 data structure!') end if ~return_fftshifted % return data as seen by detector, fmag = math.ifftshift_2D(fmag); fmask = math.ifftshift_2D(fmask); end end