% function [varargout] = spec_read(specDatFile, varargin) % call 'spec_read()' for further help % % please reports bugs, problems, suggestions for improvements to: % CXS group % % the case of duplicate scannumbers in the spec file, and how to % address them remains to be implemented %*-----------------------------------------------------------------------* %|                                                                       | %|  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 [varargout] = spec_read(specDatFile, varargin) import io.* import utils.find_files % check minimum number of input arguments if(~isunix) error(['The function ''spec_read'' relies on various system calls,\n' ... ' currently available only on UNIX-like systems\n']); end if (nargin<1) spec_help(mfilename); error('At least the spec data 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 % here the default parameters scannr = -1; output_arg = {'meta','motor','counter'}; unhandled_par_error = 1; force_cell = 0; % other parameters burstn0 = 1; mexpn0 = 1; creader = 1; orchestraPath = []; specReadOptions = []; % parse the variable input arguments vararg = cell(0,0); for jj = 1:2:length(varargin) name = varargin{jj}; value = varargin{jj+1}; switch name case 'ScanNr' if (~all(value==round(value)) || any(value==0)) error('The value of ''%s'' needs to be a (vector of) integer(s) not equal to zero', name) end scannr = value; case 'Burst' if (~all(value==round(value)) || any(value<=0)) error('The value of ''%s'' needs to be a positive integer', name) end burstn0 = max(1,value); mexpn0 = 1; case 'MultExp' if (~all(value==round(value)) || any(value<=0)) error('The value of ''%s'' needs to be a positive integer', name) end burstn0 = 1; mexpn0 = max(1,value); case 'OutPut' output_arg = set_TextFlag(output_arg,value); case 'PilatusMask' pilatusMask = value; output_arg = set_TextFlag(output_arg,'+pilatus'); case 'PilatusDir' pilatusDir0 = value; output_arg = set_TextFlag(output_arg,'+pilatus'); case 'Cell' force_cell = value; case 'CReader' creader = value; case 'Orchestra' orchestraPath = value; case 'UnhandledParError' unhandled_par_error = value; otherwise vararg{end+1} = name; %#ok vararg{end+1} = value; %#ok end end specDatFile = beamline.find_specDatFile(specDatFile); if creader try if ~isempty(orchestraPath) specReadOptions = [specReadOptions ' --orchestra ' orchestraPath]; end sysCall = [ fullfile(fileparts(mfilename('fullpath')), './spec_reader/spec_reader') ' -s ' specDatFile ' --scanNr ' strjoin(arrayfun(@(x) num2str(x),scannr,'UniformOutput',false),',') specReadOptions]; [stat, out] = system(sysCall); if stat error(['Fast spec reader failed: ' strtrim(out)]) end res = jsondecode([ out ]); if length(res)==1 varargout{1} = res; else varargout{1} = num2cell(res)'; end catch ME if creader warning('Fast spec reader failed.') disp(ME) creader = 0; end end end if ~creader % reading the spec file for the scans if ~exist(specDatFile, 'file') error('Spec file was not found in %s', specDatFile) end [scans,scanline] = spec_readscan(specDatFile, scannr); % reading the spec file for configuration information [motorc,motorline] = spec_readconfig(specDatFile); motorn = cell(size(scannr)); for jj=1:numel(scans) motorn{jj} = motorc{find(motorline0) for ii=1:numel(counters) scan_structure.(counters{ii}) = data(:,ii); end end end if (any(strcmp(output_arg,'pilatus'))) if (burstn0>1) burstn = burstn0; elseif (isfield(scan_structure,'burstn')) burstn = max(ones(size(scan_structure.burstn)),scan_structure.burstn); else burstn = burstn0; end if (mexpn0>1) mexpn = mexpn0; elseif (isfield(scan_structure,'mexpn')) mexpn = max(ones(size(scan_structure.burstn)),scan_structure.mexpn); else mexpn = mexpn0; end if (numel(burstn)==1 && numel(mexpn)==1) % these pseudo motors shouldn't be scanned and are % therefore presumably constant Pilatus = cell(size(data,1),1); scanInd = [transpose(floor((0:size(data,1)-1)/mexpn)), ... transpose(mod(0:size(data,1)-1,mexpn))]; for ii=1:size(data,1) if (burstn<=1) indices = all(ones(size(pilatusName))'*scanInd(ii,:)==pilatusInd,2); else indices = all(ones(size(pilatusName))'*scanInd(ii,1)==pilatusInd(:,1),2); end Pilatus{ii} = {pilatusName(indices).name}; if (numel(indices) error('Not all named parameters have been handled.'); end if (numel(varargout{1})==1 && ~force_cell) varargout{1} = varargout{1}{1}; end varargout{2} = vararg; return end end %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [varargout] = spec_readscan(specDatFile, scannr) import io.* import utils.* % check minimum number of input arguments if (nargin<2) spec_read_help(mfilename); error('usage ''spec_readscan(specDatFile, scannr)'''); end cmd = sprintf('grep -n ''#S '' %s', specDatFile); [~,sysout] = system(cmd); arrout = regexp(sysout,'[:\n]','split'); arrout = arrout(~cellfun(@isempty,arrout)); arrout = transpose(reshape(arrout,2,[])); [s1,~] = size(arrout); if (any(scannr>0)) tmp = regexp(arrout(:,2),' +','split'); scanID = zeros(size(tmp)); for ii=1:numel(tmp) scanID(ii) = str2double(tmp{ii}{2}); end end % creating a look up table where the scans begin and end lineI = zeros(size(scannr)); scans = cell(size(scannr)); for ii=1:numel(scannr) if (scannr(ii)<0) if (-scannr(ii)>size(arrout,1)) error('There does not seem to be sufficiently many scans in ''%s''', ... specDatFile); end tmp = regexp(arrout(end+scannr(ii)+1,:),' +','split'); lineI(ii) = str2double(tmp{1}); if (scannr(ii) < -1) tmp = regexp(arrout(end+scannr(ii)+2,:),' +','split'); lineF = str2double(tmp{1})-1; else cmd = sprintf('wc -l %s', specDatFile); [~,sysout] = system(cmd); lineF = str2double(regexp(sysout,'[0-9]+ ','match')); end scannr(ii) = str2double(tmp{2}(2)); else tmp = find((scannr(ii)==scanID),1,'last'); try verbose(2,'reading ''%s''',arrout{tmp,2}); catch fprintf('reading ''%s''\n',arrout{tmp,2}); end if (isempty(tmp)) fprintf('Do not find scan #S %d in ''%s''.\n', ... scannr(ii),specDatFile); continue end lineI(ii) = str2double(arrout(tmp,1)); if (tmp