function spm_progress_bar(action,varargin)
% Display a 'Progress Bar' in the 'Interactive' window
% FORMAT spm_progress_bar('Init',height,xlabel,ylabel,flgs)
% Initialise the bar in the 'Interactive' window.
% If flgs contains a 't', then use tex interpreter for labels.
%
% FORMAT spm_progress_bar('Set',value)
% Set the height of the bar itself.
%
% FORMAT spm_progress_bar('Set','xlabel',xlabel)
% FORMAT spm_progress_bar('Set','ylabel',ylabel)
% Set the progress bar labels.
%
% FORMAT spm_progress_bar('Set','height',height)
% Set the height of the progress bar.
%
% FORMAT spm_progress_bar('Clear')
% Clear the 'Interactive' window.
%__________________________________________________________________________
% Copyright (C) 1996-2015 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_progress_bar.m 6383 2015-03-19 17:20:41Z guillaume $

persistent pbar;

if ~nargin, action = 'Init'; end

switch lower(action)

    % Initialise
    %======================================================================
    case 'init'
        Finter = spm_figure('FindWin','Interactive');
        if isempty(Finter), pbar = []; return; end
        if nargin > 1, arg1 = varargin{1}; else arg1 = 1;           end
        if nargin > 2, arg2 = varargin{2}; else arg2 = 'Computing'; end
        if nargin > 3, arg3 = varargin{3}; else arg3 = '';          end
        if nargin > 4, arg4 = varargin{4}; else arg4 = ' ';         end
        if any(arg4 == 't'), interp = 'tex'; else interp = 'none';  end
        pb = struct('pointer',get(Finter,'Pointer'),...
                    'name',   get(Finter,'Name'),...
                    'buffer', get(Finter,'DoubleBuffer'));
        spm_progress_bar('Clear');
        set(Finter,'Pointer','watch');
        set(Finter,'Name',pb.name);
        set(Finter,'DoubleBuffer','on'); % no effect since R2013a
        if ischar(arg2), arg2 = repmat({arg2},1,numel(arg1)); end
        if ischar(arg3), arg3 = repmat({arg3},1,numel(arg1)); end

        for i=1:numel(arg1)
            %-
            pb.ax(i) = axes(...
                'Position', [((i/(numel(arg1)+1))-0.05) 0.2 0.05 0.6],...
                'XTick',    [],...
                'Xlim',     [0 1],...
                'Ylim',     [0 max([arg1(i) eps])],...
                'Box',      'on',...
                'Parent',   Finter);
            try, set(pb.ax(i),'ClippingStyle','rectangle'); end

            %-XLabel
            lab = get(pb.ax(i),'Xlabel');
            if numel(arg2) < i, arg2{i} = ''; end
            set(lab,'string',arg2{i},'FontSize',10,'Interpreter',interp);

            %-YLabel
            lab = get(pb.ax(i),'Ylabel');
            if numel(arg3) < i, arg3{i} = ''; end
            set(lab,'string',arg3{i},'FontSize',10,'Interpreter',interp);

            %-Title
            pb.t(i) = get(pb.ax(i),'Title');
            set(pb.t(i),'string','0% Complete','Interpreter',interp);

            %-Began...
            t = clock;
            if numel(arg1) == 1, opts = {};
            else opts = {'Rotation',90,'HorizontalAlignment','center'}; end
            str = sprintf('Began %2.0f:%02.0f:%02.0f',t(4),t(5),t(6));
            pb.b(i) = text(2,arg1(i)/2,0,str,...
                'FontSize',10,...
                'Parent',pb.ax(i),...
                opts{:});

            %-Progress bar
            pb.l(i) = line(...
                'Xdata',     [0.5 0.5],...
                'Ydata',     [0 0],...
                'LineWidth', 8,...
                'Color',     [1 0 0],...
                'Parent',    pb.ax(i));
        end

        pbar = pb;
        drawnow;

    % Set
    %======================================================================
    case 'set'
        if isempty(pbar) || ~all(ishandle(pbar.l)), pbar = []; return; end
        if nargin == 1, value = 0; else value = varargin{1}; end

        if ischar(value)
            if nargin == 2, str = ''; else str = varargin{2}; end
            if nargin == 3, p   = 1;  else p   = varargin{3}; end
            switch lower(value)
                case {'xlabel','ylabel'}
                    set(get(pbar.ax(p),value),'String',str);
                case 'height'
                    t = clock;
                    bstr = sprintf('Began %2.0f:%02.0f:%02.0f',t(4),t(5),t(6));
                    set(pbar.b(p),'String',bstr);
                    set(pbar.ax(p),'YLim',[0 max([str eps])]);
                otherwise
                    error('Unknown action.');
            end
        else
            if nargin == 2, p = 1; else p = varargin{2}; end
            set(pbar.l(p),'Ydata',[0 value]);
            lim = get(pbar.ax(p),'Ylim');lim=lim(2);
            set(pbar.t(p),'string',sprintf('%.0f%% Complete',100*value/lim));
        end
        try, drawnow limitrate; catch, drawnow; end

    % Clear
    %======================================================================
    case 'clear'
        Finter = spm_figure('FindWin','Interactive');
        if isempty(Finter), pbar = []; return; end
        spm_figure('Clear',Finter);
        if isstruct(pbar)
            set(Finter,'Pointer',     pbar.pointer);
            set(Finter,'Name',        pbar.name);
            set(Finter,'DoubleBuffer',pbar.buffer);
        end
        pbar = [];
        drawnow;

    % Error
    %======================================================================
    otherwise
        error('Unknown action string');
end


function [dat] = read_neuralynx_sdma(dataset, begsample, endsample, chanindx);

% READ_NEURALYNX_SDMA read specified channels and samples from a Neuralynx splitted DMA dataset
%
% Use as
%    [hdr] = read_neuralynx_sdma(dataset)
%    [dat] = read_neuralynx_sdma(dataset, begsample, endsample, chanindx)
%
% The splitted DMA dataset is not a formal Neuralynx format, but at
% the FCDC we use it in conjunction with SPIKEDOWNSAMPLE. The dataset
% directory contains files, one for each channel, each containing a
% 8-byte header followed by the binary values for all samples. Commonly
% the binary values are represented as int32, but it is possible to use
% int16 or other numeric representations. The 8-byte header specifies the
% numeric representation and the bitshift that should be applied (in case
% of integer representations).
%
% This function returns the electrophysiological data in AD units
% and not in uV. You should look up the details of the headstage and
% the Neuralynx amplifier and scale the values accordingly.

% Copyright (C) 2006-2008, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id: read_neuralynx_sdma.m 945 2010-04-21 17:41:20Z roboos $

needhdr = (nargin==1);
needdat = (nargin>=2);

if ~isdir(dataset)
  error('dataset should be a directory');
end

% determine the content of the dataset directory
dirlist = dir(dataset);

% determine the correspondence between files and channels
label         = cell(length(dirlist),1);
filesel       = zeros(length(dirlist),1);
headerfile    = [];
[pd, nd, xd]  = fileparts(dataset);
for i=1:length(dirlist)
  [pf, nf, x1] = fileparts(dirlist(i).name);
  [pf, nf, x2] = fileparts(nf);
  % compare the name of the channel with the name of the dataset and look at the file extention
  % the file should be called "dataset/dataset.chanlabel" or "dataset/dataset.chanlabel.bin"
  if strcmp(nf, nd) && ~isempty(x1)
    if ~isempty(x2)
      label{i}   = x2(2:end);
      filesel(i) = 1;
    elseif strcmp(x1, '.txt')
      % this is not a proper channel, but an ascii file with header info
      label{i}   = [];
      filesel(i) = 0;
      headerfile = fullfile(dataset, dirlist(i).name);
    else
      label{i}   = x1(2:end);
      filesel(i) = 1;
    end
  else
    label{i}   = [];
    filesel(i) = 0;
  end
end
label = label(filesel==1);
bytes = cell2mat({dirlist(filesel==1).bytes}); % number of bytes in each file
filelist = {dirlist(filesel==1).name};         % filename excluding the path
clear dirlist filesel pd nd xd

for i=1:length(filelist)
  % include the full path in the filename
  filelist{i} = fullfile(dataset, filelist{i});
end

% there is a preferred ordering, which corresponds with the channel order in the non-splitted DMA file
preferred = {
  'stx'
  'pid'
  'siz'
  'tsh'
  'tsl'
  'cpu'
  'ttl'
  'x01'
  'x02'
  'x03'
  'x04'
  'x05'
  'x06'
  'x07'
  'x08'
  'x09'
  'x10'
  'csc001'
  'csc002'
  'csc003'
  'csc004'
  'csc005'
  'csc006'
  'csc007'
  'csc008'
  'csc009'
  'csc010'
  'csc011'
  'csc012'
  'csc013'
  'csc014'
  'csc015'
  'csc016'
  'csc017'
  'csc018'
  'csc019'
  'csc020'
  'csc021'
  'csc022'
  'csc023'
  'csc024'
  'csc025'
  'csc026'
  'csc027'
  'csc028'
  'csc029'
  'csc030'
  'csc031'
  'csc032'
  'csc033'
  'csc034'
  'csc035'
  'csc036'
  'csc037'
  'csc038'
  'csc039'
  'csc040'
  'csc041'
  'csc042'
  'csc043'
  'csc044'
  'csc045'
  'csc046'
  'csc047'
  'csc048'
  'csc049'
  'csc050'
  'csc051'
  'csc052'
  'csc053'
  'csc054'
  'csc055'
  'csc056'
  'csc057'
  'csc058'
  'csc059'
  'csc060'
  'csc061'
  'csc062'
  'csc063'
  'csc064'
  'csc065'
  'csc066'
  'csc067'
  'csc068'
  'csc069'
  'csc070'
  'csc071'
  'csc072'
  'csc073'
  'csc074'
  'csc075'
  'csc076'
  'csc077'
  'csc078'
  'csc079'
  'csc080'
  'csc081'
  'csc082'
  'csc083'
  'csc084'
  'csc085'
  'csc086'
  'csc087'
  'csc088'
  'csc089'
  'csc090'
  'csc091'
  'csc092'
  'csc093'
  'csc094'
  'csc095'
  'csc096'
  'csc097'
  'csc098'
  'csc099'
  'csc100'
  'csc101'
  'csc102'
  'csc103'
  'csc104'
  'csc105'
  'csc106'
  'csc107'
  'csc108'
  'csc109'
  'csc110'
  'csc111'
  'csc112'
  'csc113'
  'csc114'
  'csc115'
  'csc116'
  'csc117'
  'csc118'
  'csc119'
  'csc120'
  'csc121'
  'csc122'
  'csc123'
  'csc124'
  'csc125'
  'csc126'
  'csc127'
  'csc128'
  'csc129'
  'csc130'
  'csc131'
  'csc132'
  'csc133'
  'csc134'
  'csc135'
  'csc136'
  'csc137'
  'csc138'
  'csc139'
  'csc140'
  'csc141'
  'csc142'
  'csc143'
  'csc144'
  'csc145'
  'csc146'
  'csc147'
  'csc148'
  'csc149'
  'csc150'
  'csc151'
  'csc152'
  'csc153'
  'csc154'
  'csc155'
  'csc156'
  'csc157'
  'csc158'
  'csc159'
  'csc160'
  'csc161'
  'csc162'
  'csc163'
  'csc164'
  'csc165'
  'csc166'
  'csc167'
  'csc168'
  'csc169'
  'csc170'
  'csc171'
  'csc172'
  'csc173'
  'csc174'
  'csc175'
  'csc176'
  'csc177'
  'csc178'
  'csc179'
  'csc180'
  'csc181'
  'csc182'
  'csc183'
  'csc184'
  'csc185'
  'csc186'
  'csc187'
  'csc188'
  'csc189'
  'csc190'
  'csc191'
  'csc192'
  'csc193'
  'csc194'
  'csc195'
  'csc196'
  'csc197'
  'csc198'
  'csc199'
  'csc200'
  'csc201'
  'csc202'
  'csc203'
  'csc204'
  'csc205'
  'csc206'
  'csc207'
  'csc208'
  'csc209'
  'csc210'
  'csc211'
  'csc212'
  'csc213'
  'csc214'
  'csc215'
  'csc216'
  'csc217'
  'csc218'
  'csc219'
  'csc220'
  'csc221'
  'csc222'
  'csc223'
  'csc224'
  'csc225'
  'csc226'
  'csc227'
  'csc228'
  'csc229'
  'csc230'
  'csc231'
  'csc232'
  'csc233'
  'csc234'
  'csc235'
  'csc236'
  'csc237'
  'csc238'
  'csc239'
  'csc240'
  'csc241'
  'csc242'
  'csc243'
  'csc244'
  'csc245'
  'csc246'
  'csc247'
  'csc248'
  'csc249'
  'csc250'
  'csc251'
  'csc252'
  'csc253'
  'csc254'
  'csc255'
  'csc256'
  'crc'
  };

[sel1, sel2] = match_str(preferred, label);
if length(sel2)==length(label)
  % all reorder the labels/files
  label = label(sel2);
  bytes = bytes(sel2);
  filelist = filelist(sel2);
else
  % not all files in this SDMA dataset could be accounted for in the
  % preference list, hence do not attempt to apply the preferred ordering
end

if needhdr
  % construct a general header for the complete dataset
  if ~isempty(headerfile)
    orig             = neuralynx_getheader(headerfile);
    hdr.Fs           = orig.SamplingFrequency;
    hdr.nSamples     = [];        % see below
    hdr.nSamplesPre  = 0;         % number of pre-trigger samples in each trial
    hdr.nTrials      = 1;         % number of trials
    hdr.label        = label;
    hdr.nChans       = length(label);
    hdr.orig.dataset = orig;       % keep the header details
  else
    % some parts of the header have to be hardcoded, since the splitted dataset does not contain all header information
    hdr.Fs           = 32556;     % sampling frequency
    hdr.nSamples     = [];        % see below
    hdr.nSamplesPre  = 0;         % number of pre-trigger samples in each trial
    hdr.nTrials      = 1;         % number of trials
    hdr.label        = label;
    hdr.nChans       = length(label);
  end

  % read the header of each individual file, i.e. for each variable
  clear orig
  for i=1:length(filelist)
    orig(i) = read_neuralynx_bin(filelist{i});
  end

  % determine the number of samples for each channel
  nsamples = cell2mat({orig.nSamples});
  if any(nsamples~=nsamples(1))
    error('different number of samples over channels are not supported');
  else
    hdr.nSamples = nsamples(1);
  end

  % determine the sampling frequency for each channel
  fsample = cell2mat({orig.Fs});
  if any(diff(fsample))
    error('different sampling rates over channels are not supported');
  elseif any(fsample~=hdr.Fs)
    error('inconsistent sampling rates');
  end

  % determine the first and last timestamp, by reading them from the timestamp channels
  tslfile = filelist{find(strcmp('tsl', label))};
  tshfile = filelist{find(strcmp('tsh', label))};
  beg_tsl = read_neuralynx_bin(tslfile, 1, 1);
  beg_tsh = read_neuralynx_bin(tshfile, 1, 1);
  end_tsl = read_neuralynx_bin(tslfile, hdr.nSamples, hdr.nSamples);
  end_tsh = read_neuralynx_bin(tshfile, hdr.nSamples, hdr.nSamples);
  hdr.FirstTimeStamp = timestamp_neuralynx(beg_tsl, beg_tsh);
  hdr.LastTimeStamp  = timestamp_neuralynx(end_tsl, end_tsh);
  hdr.TimeStampPerSample = double(hdr.LastTimeStamp-hdr.FirstTimeStamp)./(hdr.nSamples-1);  % this should be double, since it can be fractional

  % also remember the original header details
  hdr.orig.chan = orig;

  % only return the header information
  dat = hdr;

else
  % allocate memory for all data
  dat = zeros(length(chanindx), endsample-begsample+1);

  % read all channels, one small chunk at at time, and write it to seperate files
  for i=1:length(chanindx)
    j = chanindx(i);
    dat(i,:) = double(read_neuralynx_bin(filelist{j}, begsample, endsample));
  end
end


function [strctident,signreslabels]=loadcorrelres(strctident,endo,names,startdate,enddate,lags,n,IRFt,favar,pref)

signreslabels=strctident.signreslabels;
signreslabels_shocksindex=strctident.signreslabels_shocksindex;

if strctident.CorrelInstrument=="" && strctident.CorrelShock=="" %if  CorrelInstrument CorrelShock are empty then skip this part completly
    strctident.checkCorrelInstrumentShock=0; %there is nothing to check
    strctident.hbartext_CorrelInstrumentShock='';
else
    % however if we have no sign, relmagn FEVD restrictions at all, but we have correl restrictions then generate them
    if strctident.signres==0 && strctident.zerores==0 && strctident.magnres==0 && strctident.favar_signres==0 && strctident.favar_zerores==0 && strctident.favar_magnres==0 && strctident.relmagnres==0 && strctident.favar_relmagnres==0 && strctident.FEVDres==0 && strctident.favar_FEVDres==0
        % loop over endogenous (columns)
        for ii=1:n
            % give the generic name 'shock ii'
            if IRFt==6 && ii==1 % special case for the IV shock in IRFt==6
                signreslabels{ii,1}=strcat('IV Shock (',strctident.Instrument,')');
                signreslabels_shocksindex=[signreslabels_shocksindex; ii];
            else
                signreslabels{ii,1}=['shock ' num2str(ii)];
                if strctident.signrestableempty(ii)==0 % restrictions, however no label is found, count this column
                    signreslabels_shocksindex=[signreslabels_shocksindex; ii];
                end
            end
        end
        % save the shock index to later determine the number of identified shocks
        strctident.signreslabels_shocksindex=unique(signreslabels_shocksindex);
        strctident.signreslabels_shocks=signreslabels(strctident.signreslabels_shocksindex);
        strctident.signreslabels=signreslabels;
        strctident.periods=[0;0]; % also provide some periods here to generate irfs
    end

    % check if we have IV correlation restrictions
    [IVcorrel,txtcorrel]=xlsread(pref.excelFile,'IV');
    checkCorrelInstrument_index=ismember(txtcorrel(1,2:end),strctident.CorrelInstrument);
    checkCorrelShock_index=ismember(strctident.signreslabels,strctident.CorrelShock); %%%%% evt. change to strcmp loop

    %% we might have a correl shock only (no other restrictions), identify
    if sum(checkCorrelShock_index)==0
        % load the data from Excel
        % sign restrictions values
        if strctident.signres==1
            [~,~,strngs1]=xlsread(pref.excelFile,'sign res values');
        elseif strctident.relmagnres==1
            [~,~,strngs1]=xlsread(pref.excelFile,'relmagn res values');
        elseif strctident.FEVDres==1
            [~,~,strngs1]=xlsread(pref.excelFile,'FEVD res values');
        else
            [~,~,strngs1]=xlsread(pref.excelFile,'sign res values');
        end
        % replace NaN entries by blanks
        strngs1(cellfun(@(x) any(isnan(x)),strngs1))={[]};
        % convert all numeric entries into strings
        strngs1(cellfun(@isnumeric,strngs1))=cellfun(@num2str,strngs1(cellfun(@isnumeric,strngs1)),'UniformOutput',0);
        % identify the non-empty entries (pairs of rows and columns), changed the
        % routine here
        % empty strngs1 columns and rows, to make sure empty rows (with empty strings) are dismissed
        for ii=1:size(strngs1,1) %rows
            strngs1emptyrows(ii,1)=isempty(cat(2,strngs1{ii,:}));
        end
        strngs1emptyrows_index=find(strngs1emptyrows==0);

        for ii=1:size(strngs1,2) %columns
            strngs1emptycolumns(1,ii)=isempty(cat(2,strngs1{:,ii}));
        end
        strngs1emptycolumns_index=find(strngs1emptycolumns==0);
        %
        strngs1=strngs1(strngs1emptyrows_index,strngs1emptycolumns_index);

        [nerows1,neclmns1]=find(~cellfun('isempty',strngs1));
        % count the number of such entries
        neentries1=size(nerows1,1);
        % all these entries contrain strings: fix them to correct potential user formatting errors
        % loop over entries (value table)
        for ii=1:neentries1
            strngs1{nerows1(ii,1),neclmns1(ii,1)}=bear.utils.fixstring(strngs1{nerows1(ii,1),neclmns1(ii,1)});
        end

        % loop over endogenous variables
        for ii=1:n
            % for each variable, there should be two entries in the table corresponding to its name
            % one is the column lable, the other is the row label
            [r,c]=find(strcmp(strngs1,endo{ii,1}));
            % if it is not possible to find two entries, return an error
            if size(r,1)<2
                message=['Endogenous variable ' endo{ii,1} ' cannot be found in both rows and columns of the table. Please verify that the ''sign res values'' sheet of the Excel data file is properly filled.'];
                msgbox(message,'Sign restriction error');
                error('programme termination: sign restriction error');
            end
            % otherwise, the greatest number in r corresponds to the row of the column labels: record it
            rows(ii,1)=max(r);
            % the greatest number in c corresponds to the column of the row labels: record it
            clmns(ii,1)=max(c);
        end

        % find the shock, %%here a user specified label is provided in  the res
        % sheets in the excel file
        [r2,c2]=find(strcmp(strngs1,strctident.CorrelShock));

        if ~isempty(r2)==1 && ~isempty(c2)==1
            c2index=find(c2==clmns);
            signreslabels{c2index,1}=strctident.CorrelShock;
            signreslabels_shocksindex=[signreslabels_shocksindex;c2index];

            %save in structure
            strctident.signreslabels=signreslabels;
            strctident.signreslabels_shocksindex=sort(signreslabels_shocksindex);

            %again, check if we have IV correlation restrictions
            [IVcorrel,txtcorrel]=xlsread(pref.excelFile,'IV');
            checkCorrelInstrument_index=ismember(txtcorrel(1,2:end),strctident.CorrelInstrument);
            checkCorrelShock_index=ismember(strctident.signreslabels,strctident.CorrelShock); %%%%% evt. change to strcmp loop
        elseif isempty(r2)==1 && isempty(c2)==1
            % do nothing in this case
        end

    end
    % check for correlation restrictions
    % when there is no shock with an extra instrument
    if sum(checkCorrelShock_index)==0 && sum(checkCorrelInstrument_index)==0
        strctident.checkCorrelInstrumentShock=0; %there is nothing to check
        strctident.hbartext_CorrelInstrumentShock='';
        % warning if we found a CorrelShock only
    elseif sum(checkCorrelShock_index)~=0 && sum(checkCorrelInstrument_index)==0
        strctident.checkCorrelInstrumentShock=0;
        strctident.hbartext_CorrelInstrumentShock='';
        message=['Found CorrelShock ' strctident.CorrelShock ', but CorrelInstrument ' strctident.CorrelInstrument ' cannot be found in the "IV" excel sheet. Correlation restrictions are ignored.'];
        msgbox(message,'Correlation restriction warning');
        % warning if we found a CorrelShock only
    elseif sum(checkCorrelShock_index)==0 && sum(checkCorrelInstrument_index)~=0 && strcmp(strctident.CorrelShock,'CorrelShock')==0
        strctident.checkCorrelInstrumentShock=0;
        strctident.hbartext_CorrelInstrumentShock='';
        message=['Found CorrelInstrument ' strctident.CorrelInstrument ', but CorrelShock ' strctident.CorrelShock ' cannot be found. Correlation restrictions are ignored.'];
        msgbox(message,'Correlation restriction warning');
        % we found a CorrelInstrument and a CorrelShock
    elseif sum(checkCorrelInstrument_index)~=0 && sum(checkCorrelShock_index)~=0 | strcmp(strctident.CorrelShock,'CorrelShock')==1
        % find index for the Shock with correlation restriction, %%here no
        % label is provided in the res sheets in the excel file
        strctident.CorrelShock_index=find(checkCorrelShock_index); %save index
        strctident.checkCorrelInstrumentShock=1;
        Index = strcmp(txtcorrel(1,:),strctident.CorrelInstrument);           %find the instrument in the IV sheet
        IVnum = find(Index==1, 1, 'first')-1;
        IVcorrel = IVcorrel(:, IVnum);
        IVcorrel = IVcorrel(~isnan(IVcorrel));
        txtcorrel = txtcorrel(2:length(IVcorrel)+1,1);              % drop IV names from txt
        date = names(2:end,1);                                   %get the datevector of the VAR
        startlocationY_in_Y=find(strcmp(date,startdate));        %location of sample startdate in Y datevector
        endlocationY_in_Y=find(strcmp(date,enddate));            %location of sample enddate in Y datevector
        date = date(startlocationY_in_Y+lags:endlocationY_in_Y,:);  %cut datevector of Y such that it corresponds to the time dates used in the VAR
        strctident.OverlapIVcorrelinY = ismember(date,txtcorrel);           %Use this to cut EPS
        strctident.OverlapYinIVcorrel = ismember(txtcorrel,date);           %Use this to cut IV
        strctident.IVcorrel = IVcorrel(strctident.OverlapYinIVcorrel,:);               %cut all the entries from IV that are not in the sample
        strctident.hbartext_CorrelInstrumentShock='correlation, ';

        % check for empty other res shocks and non-empty correl res shocks
        correlshocktest=0;
        for ii=1:size(strctident.signreslabels,1)
            if correlshocktest==1
                break
            end
            if strctident.signrestableempty(ii,1)==1 && strctident.favar_signrestableempty(ii,1)==1 && strctident.relmagnrestableempty(ii,1)==1 && strctident.favar_relmagnrestableempty(ii,1)==1 && strctident.FEVDrestableempty(ii,1)==1 && strctident.favar_FEVDrestableempty(ii,1)==1 && checkCorrelShock_index(ii,1)==0 && strcmp(strctident.CorrelShock,'CorrelShock')==1
                % add them to the list of identified shocks in this case
                strctident.signreslabels{ii,1}=['CorrelShock (' strctident.CorrelInstrument ')'];    % or generate a label
                strctident.signreslabels_shocksindex=[strctident.signreslabels_shocksindex; ii]; % add it in the shocksindex
                checkCorrelShock_index(ii,1)=1;
                correlshocktest=1;
            end
        end

        % update the output in strctident
        strctident.signreslabels_shocks=strctident.signreslabels(strctident.signreslabels_shocksindex);
        signreslabels=strctident.signreslabels;
        strctident.CorrelShock_index=find(checkCorrelShock_index);

        %finally check if there are sign restrictions on the shock of interest. If
        %not we can use the flipped entry of the rotation matrix aswell
        if ~isempty(strctident.CorrelShock)
            if isempty(strctident.Scell{1,strctident.CorrelShock_index})
                strctident.FlipCorrel=1;
            else
                strctident.FlipCorrel=0;
            end
        end
    end
end

if favar.FAVAR==1
    % check here if the shocks of interest actually exist
    if favar.IRF.npltXshck > size(strctident.signreslabels_shocks,1)
        % error if no shock to plot is found, otherwise code crashes at a later stage
        message=['Error: Shock(s) (' favar.IRFplotXshock ') cannot be found.'];
        error('bear:loadcorrelres:ShockNotFound',message)
    end
end


%kcxinspector 'Interactively inspects results of classification '
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros cxinspector.pane file
%
% Parameters:
% InputFile: iorig 'Input Original Image', required: 'Input Original Image'
% InputFile: iclass 'Input Classified Image', required: 'Input Classified Image'
% InputFile: idist 'Input Probabilities', optional: 'input distances (probabilities) file'
% InputFile: icsf 'Class Specification File', required: 'input class specification file'
%
% Example: kcxinspector({iorig, iclass, idist, icsf}, {'iorig','';'iclass','';'idist','';'icsf',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% cxinspector - Interactively inspects results of classification
%
%  DESCRIPTION
% Inspector (cxinspector xvroutine) allows the user to interactively inspect the results for a classification using the classifiers in the Classify Toolbox. It can be used to verify pixels in the image for classification errors and results. The user can click on pixels on the classified result to see its original values and classification results.
% This xvroutine expects as inputs the original image [-iorig], the classified result [-iclass], and the Class Specification File for that classification task [-icsf], which will be used to get the classes' labels.
% Optionally the Inspector xvroutine can use the output for the Output Probabilities that most classifiers can create which are related with the discriminant functions for that classifier. If these values are presented as input for the parameter [-idist], their values will be presented in the output window.
% The xvroutine will have a workspace for display of images that can display either the original image or the classification result. When the mouse is clicked on the workspace, a small text report will be output'd on the Output Window (which is shown when the Output button is pressed) with basic information about the classifier, the position where the user clicked the mouse, the original input data at that position and the classification result for that pixel.
% There is a Image Display button which will bring a panel where the user can set whether the original image or the classification result will be displayed, whether the routine will use a private colormap for display and if the images are multiband (i.e. images with depth and/or time > 1) which band will be displayed.
%
%
%
%  EXAMPLES
% All examples for the Classify toolbox are listed on the Classify Toolbox Manual. For an example of this routine, please see the Classify:workspaces:MINDIST example workspace.
%
%  "SEE ALSO"
% cthematicmap, Class Specification File format in the Classify Toolbox Manual.
%
%  RESTRICTIONS
% Expect the parameter [-icsf] to point to a valid Class Specification file, and the parameters [-iclass] to be a result of classification with one of the classifiers in this toolbox.
%
%  REFERENCES
% All references for the Classify toolbox are listed on the Classify Toolbox Manual.
%
%  COPYRIGHT
% Copyright (C) 1997 Rafael Santos. Khoros (C) Khoral Research, Inc.
%

function varargout = kcxinspector(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kcxinspector(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'iorig', '__input';'iclass', '__input';'idist', '__input';'icsf', '__input'};
maxval={0,0,1,0};
minval={0,0,1,0};
istoggle=[0,0,1,0];
was_set=istoggle * 0;
paramtype={'InputFile','InputFile','InputFile','InputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=0; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(0);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
callKhoros([w 'cxinspector"  '],Inputs,narglist);


function video2pic( videoFile, outputPath, picFormat )
%VIDEO2PIC converts viedo frames into pictures.
%   This function uses mmreader to read videos. Thus video format supported
%   by system can be converted to pictures. Output file name follows the
%   format: VideoName_FrameNumber.PicSuffix.
%
%   VIDEO2PIC input parameters interactively.
%   VIDEO2PIC( VIDEOFILE, OUTPUTPATH, PICFORMAT ) runs as a
%   function.
%
%   videoFile: full path of video to convert.
%   outputPath: pictures will be saved under outputPath/videoname/.
%   picFormat: check 'help imwrite'
%
%	Shiquan Wang @ CASIA
%	sqwang@nlpr.ia.ac.cn
%   http://www.cbsr.ia.ac.cn/users/sqwang/
%	revised on 2009/10/19

%% Initialization
if nargin < 1
    videoFile = input('Input full video path:', 's');
    outputPath = input('Input video output path[Default is under the video path]:', 's');
    if isempty(outputPath)
        outputPath = videoFile(1, 1:find(videoFile=='\', 1, 'last')-1);
    end
    picFormat = input('Input output pic format[JPG by default]:');
    if isempty(picFormat)
        picFormat = 'JPG';
    end
end

%% Main part
videoObject = mmreader(videoFile);
numFrames = get(videoObject, 'numberOfFrames');
fileName = get(videoObject, 'Name');
% bitsPerPix = get(videoObject, 'BitsPerPixel');
% H = get(videoObject, 'Height');
% W = get(videoObject, 'Width');
% bytesPerFrame = bitsPerPix*H*W/8;
outputPath = fullfile(outputPath, fileName(1, 1:find(fileName=='.', 1, 'last')-1));
numOrder = max(4, size(int2str(numFrames), 2));
mkdir(outputPath);

indexFrame = [1 1];
frameLimit = 100; % This can be set a larger value with enough memory.
while indexFrame(1, 1) <= numFrames
%     memorynow = memory;
%     memoryMax = memorynow.MaxPossibleArrayBytes;
%     frameLimit = floor(memoryMax/bytesPerFrame*0.8);
    indexFrame(1, 2) = min(numFrames, indexFrame(1, 1) + frameLimit);
    frameAll = read(videoObject, indexFrame);

    for i = indexFrame(1, 1):1:indexFrame(1, 2)    %save frames to pic
        imgFrame = frameAll(:,:,:,i - indexFrame(1, 1) + 1);
        saveFormat = strcat('%s\\%s_%0', int2str(numOrder), 'd.%s');
        picName = sprintf(saveFormat, outputPath, fileName, i, picFormat);
        imwrite(imgFrame, picName);
        disp(picName); % This output can be turned off.
    end
    indexFrame(1, 1) = indexFrame(1, 2) + 1;
end

end


classdef ProcResultClass < handle

    properties
        dod;
        dc;
        dodAvg;
        dcAvg;
        dodAvgStd;
        dcAvgStd;
        dodSum2;
        dcSum2;
        tHRF;
        nTrials;
        ch;
        grpAvgPass;
        misc;
    end

    properties (Access=private)
        filename
        logger
    end

    methods

        % ---------------------------------------------------------------------------
        function obj = ProcResultClass()
            global logger

            obj.logger = InitLogger(logger);

            obj.Initialize();
            obj.filename = '';
        end

        % ---------------------------------------------------------------------------
        function Initialize(obj)
            obj.dod = [];
            obj.dc = [];
            obj.dodAvg = [];
            obj.dcAvg = [];
            obj.dodAvgStd = [];
            obj.dcAvgStd = [];
            obj.dodSum2 = [];
            obj.dcSum2 = [];
            obj.tHRF = [];
            obj.nTrials = {};
            obj.grpAvgPass = [];
            obj.misc = [];
        end

        % ---------------------------------------------------------------------------
        function tHRF_common = GeneratetHRFCommon(obj, tHRF_common)
            nDataBlks = obj.GetDataBlocksNum();
            if isempty(tHRF_common)
                tHRF_common = cell(nDataBlks,1);
            end

            % Find smallest tHRF among the runs. We should make this the common one.
            for iBlk = 1:nDataBlks
                if isempty(tHRF_common{iBlk})
                    tHRF_common{iBlk} = obj.GetTHRF(iBlk);
                elseif length(obj.GetTHRF(iBlk)) < length(tHRF_common{iBlk})
                    tHRF_common{iBlk} = obj.GetTHRF(iBlk);
                end
            end
        end

        % ---------------------------------------------------------------------------
        function SettHRFCommon(obj, tHRF_common, name, type)
            for iBlk = 1:length(tHRF_common)
                if size(tHRF_common{iBlk},2)<size(tHRF_common{iBlk},1)
                    tHRF_common{iBlk} = tHRF_common{iBlk}';
                end
                t = obj.GetTHRF(iBlk);
                if isempty(t)
                    return;
                end
                n = length(tHRF_common{iBlk});
                m = length(t);
                d = n-m;
                if d<0
                    fprintf('WARNING: tHRF for %s %s is larger than the common tHRF.\n',type, name);
                    if ~isempty(obj.dodAvg)
                        if isa(obj.dodAvg, 'DataClass')
                            obj.dodAvg(iBlk).TruncateTpts(abs(d));
                        else
                            obj.dodAvg(n+1:m,:,:) = [];
                        end
                    end
                    if ~isempty(obj.dodAvgStd)
                        if isa(obj.dodAvgStd, 'DataClass')
                            obj.dodAvgStd(iBlk).TruncateTpts(abs(d));
                        else
                            obj.dodAvgStd(n+1:m,:,:) = [];
                        end
                    end
                    if ~isempty(obj.dodSum2)
                        if isa(obj.dodSum2, 'DataClass')
                            obj.dodSum2(iBlk).TruncateTpts(abs(d));
                        else
                            obj.dodSum2(n+1:m,:,:) = [];
                        end
                    end
                    if ~isempty(obj.dcAvg)
                        if isa(obj.dcAvg, 'DataClass')
                            obj.dcAvg(iBlk).TruncateTpts(abs(d));
                        else
                            obj.dcAvg(n+1:m,:,:,:) = [];
                        end
                    end
                    if ~isempty(obj.dcAvgStd)
                        if isa(obj.dcAvgStd, 'DataClass')
                            obj.dcAvgStd(iBlk).TruncateTpts(abs(d));
                        else
                            obj.dcAvgStd(n+1:m,:,:,:) = [];
                        end
                    end
                    if ~isempty(obj.dcSum2)
                        if isa(obj.dcSum2, 'DataClass')
                            obj.dcSum2(iBlk).TruncateTpts(abs(d));
                        else
                            obj.dcSum2(n+1:m,:,:,:) = [];
                        end
                    end
                end
                obj.tHRF = tHRF_common{iBlk};
            end
        end

        % ----------------------------------------------------------------------------------
        function var = GetVar(obj, varname, iBlk)
            var = [];
            if exist('iBlk','var') && isempty(iBlk)
                iBlk=1;
            end
            if isproperty(obj, varname)
                eval(sprintf('var = obj.%s;', varname));
            elseif isproperty(obj.misc, varname)
                eval(sprintf('var = obj.misc.%s;', varname));
            end
            if ~isempty(var) && exist('iBlk','var')
                if iscell(var)
                    var = var{iBlk};
                else
                    var = var(iBlk);
                end
            end
        end

    end

    methods

        % ----------------------------------------------------------------------------------
        function filename = SetFilename(obj, filename)
            if nargin==1
                filename = '';
                return;
            end
            if isempty(filename)
                return;
            end

            % It is important that this function can assume that the
            % filename path + '.mat' exists
            [pname, fname] = fileparts(filename);
            pname = filesepStandard(pname);
            if ispathvalid([pname, fname, '.mat'])
                obj.filename = [pname, fname, '.mat'];
            elseif ispathvalid([pname, fname, '/', fname, '.mat'])
                obj.filename = [pname, fname, '/', fname, '.mat'];
            else
                obj.filename = '';
            end
            filename = obj.filename;
        end

        % ----------------------------------------------------------------------------------
        function SetInactiveChannelData(obj)
            if isa(obj.dc, 'DataClass')
                obj.dc.SetInactiveChannelData();
            end
            if isa(obj.dod, 'DataClass')
                obj.dod.SetInactiveChannelData();
            end
            if isa(obj.dcAvg, 'DataClass')
                obj.dcAvg.SetInactiveChannelData();
            end
            if isa(obj.dodAvg, 'DataClass')
                obj.dodAvg.SetInactiveChannelData();
            end
            if isa(obj.dcAvgStd, 'DataClass')
                obj.dcAvgStd.SetInactiveChannelData();
            end
            if isa(obj.dodAvgStd, 'DataClass')
                obj.dodAvgStd.SetInactiveChannelData();
            end
        end

        % ----------------------------------------------------------------------------------
        function Save(obj, vars, filename, options)
            % options possible values:
            %    freememory
            %    keepinmemory

            if ~exist('options', 'var') || isempty(options)
                options = 'keepinmemory';
            end

            obj.SetFilename(filename);

            output = obj; %#ok<NASGU>
            props = propnames(vars);
            for ii=1:length(props)
                if eval( sprintf('isproperty(output, ''%s'');', props{ii}) )
                    eval( sprintf('output.%s = vars.%s;', props{ii}, props{ii}) );
                else
                    eval( sprintf('output.misc.%s = vars.%s;', props{ii}, props{ii}) );
                end
            end

            obj.SetInactiveChannelData();

            % If file name is not an empty string, save results to file and  ree memory
            % to save memory space
            if isempty(obj.filename)
                return;
            end

            % If saving this data for the first time folder might have to be created under
            % the processd data output folder, depending on the group folder folder structure
            pname = fileparts(obj.filename);
            if ~isempty(pname)
                if ~ispathvalid(pname)
                    mkdir(pname)
                end
            end

            try
                obj.logger.Write(sprintf('Saving derived data output: %s', obj.filename));
            	save(obj.filename, '-mat', 'output');
            catch
                if ~ispathvalid(obj.filename)
                    msg = sprintf('ERROR: Was not able to save processed data - %s not found.', obj.filename);
                    MessageBox(msg);
                    obj.logger.Write(msg);
                    return;
                end
            end

            % Free memory for this object
            if ~isempty(findstr('freememory', options)) %#ok<FSTR>
                obj.FreeMemory();
            end
        end

        % ----------------------------------------------------------------------------------
        function SaveInit(obj, pathname, filename)
            if isempty(filename)
                return
            end
            if ispathvalid([filesepStandard(pathname), filename, '.mat'])
                return
            end
            if ~ispathvalid(pathname)
                mkdir(pathname)
            end
            output = ProcResultClass();

            obj.logger.Write(sprintf('Initializing empty derived data output file:   %s', [filesepStandard(pathname), filename, '.mat']));
            save([filesepStandard(pathname), filename, '.mat'], '-mat', 'output');
        end

        % ----------------------------------------------------------------------------------
        function err = Load(obj, filename)
            err = 0;
            obj.SetFilename(filename);
            if isempty(obj.filename)
                return;
            end

            % If object is not empty it means we already have loaded data. No
            % need to waste time loading it from file.
%             if ~obj.IsEmpty()
%                 return;
%             end

            % Error check file
            if ~ispathvalid(obj.filename,'file')
                return
            end

            % If file name is not an empty string, load proc stream output from file
            load(obj.filename, '-mat');

            % Error check output
            if ~exist('output','var')
                return
            end
            if ~isa(output,'ProcResultClass')
                return
            end
            obj.Copy(output);
        end

        % ----------------------------------------------------------------------------------
        function FreeMemory(obj, filename)
            if ~exist('filename','var')
                filename = '';
            end

            % If file name is not passed and is not already set within this
            % object it means we are not saving output to seperate files
            % and therefore not freeing memory for the processed output.
            % Therefore we simply return to avoid re-initialzing the object
            if isempty(obj.filename) && isempty(filename)
                return;
            end

            if ~ispathvalid([filename, '.mat'], 'file')
                return
            end

            % Free memory for this object
            obj.Initialize();
        end

        % ----------------------------------------------------------------------------------
        function Reset(obj, filename)
            obj.Initialize();

            obj.SetFilename(filename);
            if isempty(obj.filename)
                return;
            end

            % Check that data file associated with this processing element exists
            if ispathvalid(obj.filename, 'file')
                % Delete file containing the actual datas
                delete(obj.filename);
            end

            % Check that exported data file associated with this processing element exists
            [pname, fname] = fileparts(obj.filename);
            if ispathvalid([pname, '/', fname, '_HRF.txt'], 'file')
                delete([pname, '/', fname, '_HRF.txt']);
            end
        end

        % ----------------------------------------------------------------------------------
        function Flush(obj)
            obj.Initialize();
        end

        % ----------------------------------------------------------------------------------
        function Print(obj, indent)
            if ~exist('indent', 'var')
                indent = 6;
            end
            fprintf('%sOutput:\n', blanks(indent));
        end

    end

    methods

        % ----------------------------------------------------------------------------------
        function [keys, values] = GetAllData(obj)
            % Returns names and references to all non-empty DataClass objects available as
            % properties of the ProcResultClass instance or of the misc list
            props = properties(obj);
            keys = {};
            values = {};
            for i = 1:length(props)
                val = eval(sprintf('obj.%s', props{i}));
                if isa(val, 'DataClass')
                    if ~isempty(val.dataTimeSeries) && ~isempty(val.time) && ~isempty(val.measurementList)
                        keys{end + 1} = props{i}; %#ok<AGROW>
                        values{end + 1} = val; %#ok<AGROW>
                    end
                end
            end
            try
                miscnames = fields(obj.misc);
            catch
                return
            end
            for i = 1:length(miscnames)
                val = eval(sprintf('obj.misc.%s', miscnames{i}));
                if isa(val, 'DataClass')
                    if ~isempty(val.dataTimeSeries) && ~isempty(val.time) && ~isempty(val.measurementList)
                        keys{end + 1} = miscnames{i}; %#ok<AGROW>
                        values{end + 1} = val; %#ok<AGROW>
                    end
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function SetTHRF(obj, t)
            obj.tHRF = t;
        end

        % ----------------------------------------------------------------------------------
        function t = GetTHRF(obj, iBlk)
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk = 1;
            end

            if ~isempty(obj.dcAvg) && isa(obj.dcAvg, 'DataClass')
                t = obj.dcAvg(iBlk).GetT;
            elseif ~isempty(obj.dodAvg) && isa(obj.dodAvg, 'DataClass')
                t = obj.dodAvg(iBlk).GetT;
            else
                t = obj.tHRF;
            end
        end

        % ----------------------------------------------------------------------------------
        function SetDodAvg(obj, val)
            obj.dodAvg = val;
        end

        % ----------------------------------------------------------------------------------
        function SetDcAvg(obj, val)
            obj.dcAvg = val;
        end

        % ----------------------------------------------------------------------------------
        function SetDodAvgStd(obj, val)
            obj.dodAvgStd = val;
        end

        % ----------------------------------------------------------------------------------
        function SetDcAvgStd(obj, val)
            obj.dcAvgStd = val;
        end

        % ----------------------------------------------------------------------------------
        function SetDodSum2(obj, val)
            obj.dodSum2 = val;
        end

        % ----------------------------------------------------------------------------------
        function SetDcSum2(obj, val)
            obj.dcSum2 = val;
        end

        % ----------------------------------------------------------------------------------
        function SetDod(obj, val)
            obj.dod = val;
        end

        % ----------------------------------------------------------------------------------
        function SetDc(obj, val)
            obj.dc = val;
        end

        % ----------------------------------------------------------------------------------
        function yavg = GetDodAvg(obj, type, condition, iBlk) %#ok<*INUSL>
            yavg = [];

            % Check type argument
            if ~exist('type','var') || isempty(type)
                type = 'dodAvg';
            end
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk = 1; %#ok<NASGU>
            end

            if ~ischar(type)
                return;
            end

            % Get data matrix
            if isa(eval(sprintf('obj.%s', type)), 'DataClass')
                if isempty(eval(sprintf('obj.%s', type)))
                    return;
                end
                yavg = eval(sprintf('obj.%s(iBlk).GetDataTimeSeries(''reshape'')', type));
            else
                yavg = eval(sprintf('obj.%s', type));
            end

            % Get condition
            if ~exist('condition','var')
                condition = 1:size(yavg,3);
            end
            if isempty(condition)
                yavg = [];
            end
            if isempty(yavg)
                return;
            end
            if max(condition)>size(yavg,3)
                yavg = [];
                return;
            end
            if all(isnan(yavg(:,:,condition)))
                yavg = [];
                return;
            end
            yavg = yavg(:,:,condition);
        end

        % ----------------------------------------------------------------------------------
        function yavg = GetDcAvg(obj, type, condition, iBlk)
            yavg = [];

            % Check type argument
            if ~exist('type','var') || isempty(type)
                type = 'dcAvg';
            end
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk = 1; %#ok<NASGU>
            end

            if ~ischar(type)
                return;
            end

            % Get data matrix
            if isa(eval(sprintf('obj.%s', type)), 'DataClass')
                if isempty(eval(sprintf('obj.%s', type)))
                    return;
                end
                yavg = eval(sprintf('obj.%s(iBlk).GetDataTimeSeries(''reshape'')', type));
            else
                yavg = eval(sprintf('obj.%s', type));
            end

            % Get condition
            if ~exist('condition','var')
                condition = 1:size(yavg,4);
            end
            if isempty(condition)
                yavg = [];
            end
            if isempty(yavg)
                return;
            end
            if max(condition)>size(yavg,4)
                yavg = [];
                return;
            end
            if all(isnan(yavg(:,:,:,condition)))
                yavg = [];
                return;
            end
            yavg = yavg(:,:,:,condition);
        end

        % ----------------------------------------------------------------------------------
        function y = GetDataTimeCourse(obj, type, iBlk)
            y = [];
            options = ''; %#ok<NASGU>

            % Check type argument
            if ~exist('type','var') || isempty(type)
                type = 'dcAvg';
            end
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk = 1; %#ok<NASGU>
            end

            if ~ischar(type)
                return;
            end

            if isa(eval(sprintf('obj.%s', type)), 'DataClass')
                if isempty(eval(sprintf('obj.%s', type)))
                    return;
                end
                if strcmp(type, 'dc') || strcmp(type, 'dcAvg') || strcmp(type, 'dodAvg')
                    options = 'reshape'; %#ok<NASGU>
                end
                y = eval(sprintf('obj.%s(iBlk).GetDataTimeSeries(options)', type));
            else
                y = eval(sprintf('obj.%s', type));
            end
        end

        % ----------------------------------------------------------------------------------
        function SetNtrials(obj, val)
            obj.nTrials = val;
        end

        % ----------------------------------------------------------------------------------
        function nTrials = GetNtrials(obj, iBlk)
            nTrials = {};
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk = 1;
            end
            if isempty(obj.nTrials)
                return;
            end
            if iscell(obj.nTrials)
                nTrials = obj.nTrials{iBlk};
            else
                nTrials = obj.nTrials;
            end
        end

        % ----------------------------------------------------------------------------------
        function s = GetStims(obj, t)
            if nargin==1
                t = [];
            end
            s = obj.GetVar('s');
            if isempty(s)
                if isempty(obj.dod) || ~isa(obj.dod, 'DataClass')
                    return;
                end
                stim = obj.GetVar('stim');
                if isempty(stim)
                    return;
                end
                snirf = SnirfClass(obj.dod, stim);
                s = snirf.GetStims(t);
            end
        end

        % ----------------------------------------------------------------------------------
        function val = GetTincAuto(obj, iBlk)
            val = {};
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk=1;
            end
            if isproperty(obj.misc, 'tIncAuto')
                if iscell(obj.misc.tIncAuto)
                    val = obj.misc.tIncAuto{iBlk};
                else
                    val = obj.misc.tIncAuto;
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function val = GetTincAutoCh(obj, iBlk)
            val = {};
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk=1;
            end
            if isproperty(obj.misc, 'tIncAutoCh')
                if iscell(obj.misc.tIncAutoCh)
                    val = obj.misc.tIncAutoCh{iBlk};
                else
                    val = obj.misc.tIncAutoCh;
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function mlActAuto = GetMeasListActAuto(obj, iBlk)
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk=1;
            end
            mlActAutoAll = obj.GetVar('mlActAuto');
            mlActAuto = mlActAutoAll{iBlk};
        end

        % ----------------------------------------------------------------------------------
        function n = GetDataBlocksNum(obj)
            n = 0;

            if ~isempty(obj.dcAvg)
                if isnumeric(obj.dcAvg)
                    n = 1;
                else
                    n = length(obj.dcAvg);
                end
            elseif ~isempty(obj.dodAvg)
                if isnumeric(obj.dodAvg)
                    n = 1;
                else
                    n = length(obj.dodAvg);
                end
            elseif ~isempty(obj.dc)
                if isnumeric(obj.dc)
                    n = 1;
                else
                    n = length(obj.dc);
                end
            elseif ~isempty(obj.dod)
                if isnumeric(obj.dod)
                    n = 1;
                else
                    n = length(obj.dod);
                end
            end
        end

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    methods

        % ----------------------------------------------------------------------------------
        function Copy(obj, obj2, filename)

            if ~isa(obj, 'ProcResultClass')
                return;
            end
            if ~exist('filename', 'var')
                filename = '';
            end
            obj.SetFilename(filename);

            % If file name is set and exists then free memory for output
            % as a place holder for loading data from file when needed
            if ~isempty(filename) && exist(obj.filename, 'file')

                obj.FreeMemory(filename);

            % Else copy obj2 to obj
            elseif isempty(filename)

	            obj.dod = obj2.dod;
	            obj.dc = obj2.dc;
	            obj.dodAvg = obj2.dodAvg;
	            obj.dcAvg = obj2.dcAvg;
	            obj.dodAvgStd = obj2.dodAvgStd;
	            obj.dcAvgStd = obj2.dcAvgStd;
	            obj.dodSum2 = obj2.dodSum2;
	            obj.dcSum2 = obj2.dcSum2;
	            obj.tHRF = obj2.tHRF;
	            if iscell(obj2.nTrials)
	                obj.nTrials = obj2.nTrials;
	            else
	                obj.nTrials = {obj2.nTrials};
	            end
	            obj.ch = obj2.ch;
	            obj.misc = obj2.misc;
            end
        end

        % ----------------------------------------------------------------------------------
        function b = IsEmpty(obj)
            b = false;
            if isempty(obj)
                b = true;
                return
            end
            if ~isempty(obj.dod)
                return
            end
            if ~isempty(obj.dc)
                return
            end
            if ~isempty(obj.dodAvg)
                return
            end
            if ~isempty(obj.dcAvg)
                return
            end
            if ~isempty(obj.dodAvgStd)
                return
            end
            if ~isempty(obj.dcAvgStd)
                return
            end
            if ~isempty(obj.dodSum2)
                return
            end
            if ~isempty(obj.dcSum2)
                return
            end
            if ~isempty(obj.tHRF)
                return
            end
            if ~isempty(obj.nTrials)
                return
            end
            if ~isempty(obj.grpAvgPass)
                return
            end
            if ~isempty(obj.misc)
                return
            end
            b = true;
        end

        % ----------------------------------------------------------------------------------
        function n = GetNumChForOneCondition(obj, iBlk)
            n = 0;
            if nargin<2
                iBlk = 1;
            end
            if isa(obj.dcAvg, 'DataClass')
                n = length(obj.dcAvg(iBlk).GetMeasurementListIdxs(1));
            end
        end

        % ----------------------------------------------------------------------------------
        function nbytes = MemoryRequired(obj)
            fields = properties(obj);
            nbytes = zeros(length(fields),1);
            for ii = 1:length(fields)
                fieldstr = sprintf('obj.%s', fields{ii});
                if ~isempty(fieldstr)
                    if isa(eval(fieldstr), 'DataClass')
                        nbytes(ii) =  eval(sprintf('%s.MemoryRequired();', fieldstr));
                    else
                        nbytes(ii) =  eval(sprintf('sizeof(%s);', fieldstr));
                    end
                end
            end
            nbytes = sum(nbytes);
        end

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Export related methods
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    methods

        % ----------------------------------------------------------------------------------
        function [tblcells, maxwidth] = GenerateTableCellsHeader_MeanHRF(obj, iBlk)
            if nargin<5
                iBlk = 1;
            end
            tblcells = TableCell.empty();
            maxwidth = length('HRF HbX,999,999');
            if isa(obj.dcAvg, 'DataClass')
                measList = obj.dcAvg(iBlk).measurementList;
                measListIdxs = obj.dcAvg(iBlk).GetMeasurementListIdxs(1);
                for iCh = measListIdxs
                    tblcells(1,iCh) = TableCell(sprintf('%s,%d,%d', measList(iCh).dataTypeLabel, measList(iCh).sourceIndex, measList(iCh).detectorIndex), maxwidth);
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function tblcells = GenerateTableCells_MeanHRF_Alt(obj, name, CondNames, trange, width, iBlk)
            if ~exist('trange','var') || isempty(trange) || all(trange==0)
                trange = [obj.tHRF(1), obj.tHRF(end)];
            end
            if ~exist('width','var') || isempty(width)
                width = 12;
            end
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk = 1;
            end
            tblcells = TableCell.empty();
            if isa(obj.dcAvg, 'DataClass')
                dataTimeSeries = obj.dcAvg(iBlk).GetDataTimeSeries('');
                h = waitbar_improved(0, sprintf('Generating table cells for export ... 0%% complete.'));
                % Data rows
                for iCond = 1:length(CondNames)
                    waitbar_improved(iCond/length(CondNames), h, sprintf('Generating table cells for export ... %d%% complete.', uint32(100 * iCond/length(CondNames))));
                    measListIdxs = obj.dcAvg(iBlk).GetMeasurementListIdxs(iCond);
                    for iCh = measListIdxs
                        iT = (obj.dcAvg.time >= trange(1)) & (obj.dcAvg.time <= trange(2));
                        meanData = mean(dataTimeSeries(iT,iCh));
                        if isnan(meanData)
                            cname  = 'N/A';
                        else
                            cname = sprintf('%s%0.5e', blanks(meanData>=0), meanData);
                        end
                        tblcells(iCond, mod(iCh-1, length(measListIdxs))+1) = TableCell(cname, width);
                    end
                end
                close(h);
            end
        end

        % ----------------------------------------------------------------------------------
        function tblcells = GenerateTableCells_HRF(obj, CondNames, iBlk)
            tblcells = [];

            if ~isa(obj.dcAvg, 'DataClass')
                return
            end
            if isempty(obj.dcAvg)
                return
            end
            if obj.dcAvg.IsEmpty()
                return
            end

            if nargin<3
                iBlk = 1;
            end

            tblcells = TableCell.empty();

            dataTimeSeries  = obj.dcAvg(iBlk).GetDataTimeSeries();
            time            = obj.dcAvg(iBlk).GetTime();
            measList        = obj.dcAvg(iBlk).measurementList;

            %%%% Row 1: Header row containing stim condition names
            tblcells(2,1) = TableCell('', 12);      % Make space for time column
            for iCh = 1:length(measList)
                tblcells(1,iCh+1) = TableCell(sprintf('%s', CondNames{measList(iCh).dataTypeIndex}), 12);
            end

            %%%% Row 2: Header row containing time label followed by Hb types with source,detector indices
            tblcells(2,1) = TableCell('time', 12);
            for iCh = 1:length(measList)
                tblcells(2,iCh+1) = TableCell(sprintf('%s,%d,%d', measList(iCh).dataTypeLabel, measList(iCh).sourceIndex, measList(iCh).detectorIndex), 12);
            end

            %%%% Rows 3 and greater are time points and data for all channels
            h = waitbar_improved(0, sprintf('Generating table cells for export ... 0%% complete.'));
            for t = 1:size(dataTimeSeries,1)
                if mod(t,100)==0
                    waitbar_improved(t/size(dataTimeSeries,1), h, sprintf('Generating table cells for export ... %d%% complete.', uint32(100 * t/size(dataTimeSeries,1))));
                end

                % time
                cname = sprintf('%s%0.3f', blanks(time(t)>=0), time(t));
                tblcells(t+2,1) = TableCell(cname, 12);

                % data
                for iCh = 1:length(measList)
                    if isnan(dataTimeSeries(t,iCh))
                        cname  = 'NaN';
                    else
                        cname = sprintf('%s%0.5e', blanks(dataTimeSeries(t,iCh)>=0), dataTimeSeries(t,iCh));
                    end
                    tblcells(t+2,iCh+1) = TableCell(cname, 12);
                end
            end
            close(h);
        end

        % ----------------------------------------------------------------------------------
        function tblcells = GenerateTableCells_MeanHRF(obj, name, CondNames, trange, iBlk)
            tblcells = [];

            if ~isa(obj.dcAvg, 'DataClass')
                return
            end
            if isempty(obj.dcAvg)
                return
            end
            if obj.dcAvg.IsEmpty()
                return
            end

            if nargin<3
                iBlk = 1;
            end

            tblcells = TableCell.empty();

            dataTimeSeries  = obj.dcAvg(iBlk).GetDataTimeSeries();
            time            = obj.dcAvg(iBlk).GetTime();
            measList        = obj.dcAvg(iBlk).measurementList;

            %%%% Row 1: Header row containing stim condition names
            tblcells(2,1) = TableCell('', 12);      % Make space for time column
            for iCh = 1:length(measList)
                tblcells(1,iCh+1) = TableCell(sprintf('%s', CondNames{measList(iCh).dataTypeIndex}), 12);
            end

            %%%% Row 2: Header row containing processing element label followed by Hb types with source,detector indices
            tblcells(2,1) = TableCell(sprintf('Name'), 12);
            for iCh = 1:length(measList)
                tblcells(2,iCh+1) = TableCell(sprintf('%s,%d,%d', measList(iCh).dataTypeLabel, measList(iCh).sourceIndex, measList(iCh).detectorIndex), 12);
            end

            %%%% Row 3: processing element name followed by mean HRF data for all channels
            h = waitbar_improved(0, sprintf('Generating table cells for export ... 0%% complete.'));

            % Name of processing element
            tblcells(3,1) = TableCell(name, 12);

            % Mean HRF data
            for iCh = 1:length(measList)
                iT = (time >= trange(1)) & (time <= trange(2));
                if isnan(dataTimeSeries(iT,iCh))
                    cname  = 'NaN';
                else
                    cname = sprintf('%s%0.5e', blanks(mean(dataTimeSeries(iT,iCh)) >= 0), mean(dataTimeSeries(iT,iCh)));
                end
                tblcells(3,iCh+1) = TableCell(cname, 12);
            end
            close(h);
        end

        % ----------------------------------------------------------------------------------
        function tbl = ExportHRF(obj, filename, CondNames, iBlk)
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk = 1;
            end

            % Generate table cells
            tblcells = obj.GenerateTableCells_HRF(CondNames, iBlk);

            [p, f] = fileparts(obj.SetFilename(filename));
            filename = [filesepStandard(p, 'nameonly:dir'), f];

            % Create table export data to file
            tbl = ExportTable(filename, 'HRF', tblcells);
        end

        % ----------------------------------------------------------------------------------
        function filename = ExportHRF_GetFilename(obj, filename)
            [p, f] = fileparts(obj.SetFilename(filename));
            filename = [filesepStandard(p, 'nameonly:dir'), f];

            % Create table export data to file
            tbl = ExportTable(filename, 'HRF');
            filename = tbl.GetFilenameFull();
        end

        % ----------------------------------------------------------------------------------
        function tbl = ExportMeanHRF(obj, filename, CondNames, trange, iBlk)
            if ~exist('iBlk','var') || isempty(iBlk)
                iBlk = 1;
            end

            [p, f] = fileparts(obj.SetFilename(filename));
            filename = [filesepStandard(p, 'nameonly:dir'), f];

            % Generate table cells
            tblcells = obj.GenerateTableCells_MeanHRF(f, CondNames, trange, iBlk);

            % Create table export data to file
            tbl = ExportTable(filename, 'HRF Mean', tblcells);
        end

        % ----------------------------------------------------------------------------------
        function tbl = ExportMeanHRF_Alt(obj, filename, tblcells)
            [p, f] = fileparts(obj.SetFilename(filename));
            filename = [filesepStandard(p, 'nameonly:dir'), f];

            % Create table export data to file
            tbl = ExportTable(filename, 'HRF mean', tblcells);
        end

    end

end


function [grRules,rxnGeneMat,indexes2check] = standardizeGrRules(model,embedded)
% standardizeGrRules
%   Standardizes gene-rxn rules in a model according to the following
%       - No overall containing brackets
%       - Just enzyme complexes are enclosed into brackets
%       - ' and ' & ' or ' strings are strictly set to lowercases
%
%   A rxnGeneMat matrix consistent with the standardized grRules is created.
%
%   model        a model structure
%   embedded     true if this function is called inside of another
%                RAVEN function (opt, default false)
%
%   grRules      [nRxns x 1] cell array with the standardized grRules
%   rxnGeneMat   [nRxns x nGenes]Sparse matrix consitent with the
%                standardized grRules
%
%   If this function is going to be used in a model reconstruction or
%   modification pipeline it is recommended to run this function just
%   at the beginning of the process.
%
%   Usage: [grRules,rxnGeneMat,indexes2check]=standardizeGrRules(model,embedded)

%Preallocate fields
n          = length(model.rxns);
[g,~]      = size(model.genes);
rxnGeneMat = sparse(n,g);
grRules    = cell(n,1);
genes      = model.genes;
if nargin<2
    embedded = false;
end

if isfield(model,'grRules')
    originalGrRules=model.grRules;
    originalGrRules=grRulesPreparation(originalGrRules);
    %Search for potential logical errors in the grRules field
    indexes2check = findPotentialErrors(originalGrRules,embedded,model);

    for i=1:length(originalGrRules)
        originalSTR = originalGrRules{i};
        grRules{i,:}  = originalSTR;
        %Non-empty grRules are splitted in all their different isoenzymes
        genesSets   = getSimpleGeneSets(originalSTR);
        rxnGeneMat  = modifyRxnGeneMat(genesSets,genes,rxnGeneMat,i);
        %standardize the non-conflicting grRules
        if ~ismember(i,indexes2check)
            newSTR = [];
            if ~isempty(genesSets)
                %For each simple genes set in the rule
                for j=1:length(genesSets)
                    simpleSet  = genesSets{j};
                    %Enclose simpleSet in brackets
                    if length(genesSets)>1
                        if ~isempty(strfind(simpleSet,' and '))
                            simpleSet = horzcat('(',simpleSet,')');
                        end
                    end
                    %Separate genesSets in the substring (in case of
                    %isoenzymes)
                    if j<length(genesSets)
                        newSTR = [newSTR, simpleSet, ' or '];
                        %Add the last simpleSet
                    else
                        newSTR = [newSTR, simpleSet];
                    end
                end
                %Update grRule
                grRules{i} = char(newSTR);
            end
        end
    end
end

end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Function that gets a cell array with all the simple geneSets in a given
%grRule string
function genesSets = getSimpleGeneSets(originalSTR)
genesSets  = [];
%If gene rule is not empty split in all its different isoenzymes
if ~isempty(originalSTR)
    originalSTR = strtrim(originalSTR);
    %Remove all brackets
    originalSTR = strrep(originalSTR,'(','');
    originalSTR = strrep(originalSTR,')','');
    %Split all the different genesSets
    genesSets  = transpose(strsplit(originalSTR,' or '));
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Function that gets a cell array of simple genes sets (single genes or
%enzyme complexes) associated with the i-th reaction and modifies the
%correspondent row in the rxnGeneMat accordingly.
function rxnGeneMat = modifyRxnGeneMat(genesSets,modelGenes,rxnGeneMat,i)

if ~isempty(genesSets)
    for j=1:length(genesSets)
        simpleSet  = genesSets{j};
        %        rxnGeneMat = modifyRxnGeneMat(simpleSet,model.genes,rxnGeneMat,i);
        %Get individual genes
        STR   = strrep(simpleSet,') and (',' and ');
        genes = strsplit(STR,' ');
        for k=1:length(genes)
            if ~strcmpi(genes(k),' and ')
                %Get gene index
                genePos = find(strcmpi(modelGenes,genes(k)));
                if ~isempty(genePos)
                    rxnGeneMat(i,genePos) = 1;
                    %else
                    %In this case the gene should be added to the
                    %genes field (and to all of its dependencies)
                end
            end
        end
    end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Function that gets the model field grRules and returns the indexes of the
%rules in which the pattern ") and (" is present.
function indexes2check = findPotentialErrors(grRules,embedded,model)
indxs_l       = find(~cellfun(@isempty,strfind(grRules,') and (')));
indxs_l_L     = find(~cellfun(@isempty,strfind(grRules,') and')));
indxs_l_R     = find(~cellfun(@isempty,strfind(grRules,'and (')));
indexes2check = vertcat(indxs_l,indxs_l_L,indxs_l_R);
indexes2check = unique(indexes2check);

if ~isempty(indexes2check)

    if embedded
        EM = 'Potentially problematic ") AND (" in the grRules for reaction(s): ';
        dispEM(EM,false,model.rxns(indexes2check),true)
    else
        STR = 'Potentially problematic ") AND (", ") AND" or "AND ("relat';
        STR = [STR,'ionships found in\n\n'];
        for i=1:length(indexes2check)
            index = indexes2check(i);
            STR = [STR '  - grRule #' model.rxns{index} ': ' grRules{index} '\n'];
        end
        STR = [STR,'\n This kind of relationships should only be present '];
        STR = [STR,'in  reactions catalysed by complexes of isoenzymes e'];
        STR = [STR,'.g.\n\n  - (G1 or G2) and (G3 or G4)\n\n For these c'];
        STR = [STR,'ases modify the grRules manually, writing all the po'];
        STR = [STR,'ssible combinations e.g.\n\n  - (G1 and G3) or (G1 a'];
        STR = [STR,'nd G4) or (G2 and G3) or (G2 and G4)\n\n For other c'];
        STR = [STR,'ases modify the correspondent grRules avoiding:\n\n '];
        STR = [STR,' 1) Overall container brackets, e.g.\n        "(G1 a'];
        STR = [STR,'nd G2)" should be "G1 and G2"\n\n  2) Single unit en'];
        STR = [STR,'zymes enclosed into brackets, e.g.\n        "(G1)" s'];
        STR = [STR,'hould be "G1"\n\n  3) The use of uppercases for logi'];
        STR = [STR,'cal operators, e.g.\n        "G1 OR G2" should be "G'];
        STR = [STR,'1 or G2"\n\n  4) Unbalanced brackets, e.g.\n        '];
        STR = [STR,'"((G1 and G2) or G3" should be "(G1 and G2) or G3"\n'];
        warning(sprintf(STR))
    end
end
end

function grRules = grRulesPreparation(grRules)
%Remove unnecessary blanks
grRules=strrep(grRules,'  ',' ');
grRules=strrep(grRules,'( ','(');
grRules=strrep(grRules,' )',')');
% Make sure that AND and OR strings are in lowercase
grRules=strrep(grRules,' AND ',' and ');
grRules=strrep(grRules,' OR ',' or ');
end


function varargout = adjustIntensityRangeGui(varargin)
% ADJUSTINTENSITYRANGEGUI M-file for adjustIntensityRangeGui.fig
%      ADJUSTINTENSITYRANGEGUI, by itself, creates a new ADJUSTINTENSITYRANGEGUI or raises the existing
%      singleton*.
%
%      H = ADJUSTINTENSITYRANGEGUI returns the handle to a new ADJUSTINTENSITYRANGEGUI or the handle to
%      the existing singleton*.
%
%      ADJUSTINTENSITYRANGEGUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in ADJUSTINTENSITYRANGEGUI.M with the given input arguments.
%
%      ADJUSTINTENSITYRANGEGUI('Property','Value',...) creates a new ADJUSTINTENSITYRANGEGUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before adjustIntensityRangeGui_OpeningFunction gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to adjustIntensityRangeGui_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help adjustIntensityRangeGui

% Last Modified by GUIDE v2.5 11-Aug-2004 09:30:47

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @adjustIntensityRangeGui_OpeningFcn, ...
                   'gui_OutputFcn',  @adjustIntensityRangeGui_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin & isstr(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
%--------------------------------------------------------
% --- Executes just before adjustIntensityRangeGui is made visible.
%--------------------------------------------------------
function adjustIntensityRangeGui_OpeningFcn(hObject, eventdata, handles, varargin)

% Choose default command line output for adjustIntensityRangeGui
handles.output = hObject;

hMainGui = getappdata(0,'hMainGui');
intensityParam = getappdata(hMainGui,'intensityParam');
set(handles.lowerEdit,'String',num2str(intensityParam.lowerLimit));
set(handles.upperEdit,'String',num2str(intensityParam.upperLimit));
handles.intensityParam = intensityParam;

% Set the slider's value and step size
handax=findobj(hMainGui,'tag','axes1');
cimg = getimage(handax);
cmin = intensityParam.minIntensity;
cmax = intensityParam.maxIntensity;
rng = cmax-cmin;

if cmax == 0
    cmin = 0; cmax = 1;
    step_size = 1;
elseif cmax <= 1
    step_size = double(rng/256);
else
    step_size = 1/double(rng-1);
end
set(handles.lowerSlider,'Min',cmin,'Max',cmax,...
    'Value', intensityParam.lowerLimit,'SliderStep',[step_size step_size]);
set(handles.upperSlider,'Min',cmin,'Max',cmax,...
    'Value',intensityParam.upperLimit,'SliderStep',[step_size step_size]);
set(handles.upperEdit,'String',num2str(intensityParam.upperLimit));
set(handles.lowerEdit,'String',num2str(intensityParam.lowerLimit));

guidata(hObject, handles);

%--------------------------------------------------------
% --- Outputs from this function are returned to the command line.
%--------------------------------------------------------
function varargout = adjustIntensityRangeGui_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;

%--------------------------------------------------------
% --- Executes during object creation, after setting all properties.
%--------------------------------------------------------
function lowerSlider_CreateFcn(hObject, eventdata, handles)
usewhitebg = 1;
if usewhitebg
    set(hObject,'BackgroundColor',[.9 .9 .9]);
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end
% --- Executes on slider movement.
%--------------------------------------------------------
function lowerSlider_Callback(hObject, eventdata, handles)
lwLimit= round(get(hObject,'Value'));
upLimit = round(get(handles.upperSlider,'Value'));
if lwLimit<upLimit
    set(handles.lowerEdit,'String',num2str(lwLimit));
    hMainGui = getappdata(0,'hMainGui');
    handax=findobj(hMainGui,'tag','axes1');
    ll = get(handax,'Clim');
    set(handax,'Clim',[lwLimit ll(2)]);
    handles.intensityParam.lowerLimit = lwLimit;
else
    errordlg('Lower limit cannot be larger than the upper');
end
guidata(hObject, handles);

%--------------------------------------------------------
% --- Executes during object creation, after setting all properties.
function upperSlider_CreateFcn(hObject, eventdata, handles)
usewhitebg = 1;
if usewhitebg
    set(hObject,'BackgroundColor',[.9 .9 .9]);
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end
%--------------------------------------------------------
% --- Executes on slider movement.
%--------------------------------------------------------
function upperSlider_Callback(hObject, eventdata, handles)
upLimit= round(get(hObject,'Value'));
lwLimit = round(get(handles.lowerSlider,'Value'));
if lwLimit < upLimit
    set(handles.upperEdit,'String',num2str(upLimit));
    hMainGui = getappdata(0,'hMainGui');
    handax=findobj(hMainGui,'tag','axes1');
    ll = get(handax,'Clim');
    set(handax,'Clim',[ll(1) upLimit]);
    handles.intensityParam.upperLimit = upLimit;
else
    errordlg('Lower limit cannot be larger than upper limit');
end
guidata(hObject, handles);
%--------------------------------------------------------
% --- Executes on button press in pushbuttonApply.
%--------------------------------------------------------
function pushbuttonApply_Callback(hObject, eventdata, handles)
hMainGui = getappdata(0,'hMainGui');
setappdata(hMainGui,'intensityParam',handles.intensityParam);
% getappdata(hMainGui,'intensityParam')
if ishandle(handles.figure1),
    close(handles.figure1);
end
%--------------------------------------------------------
% --- Executes during object creation, after setting all properties.
%--------------------------------------------------------
function lowerEdit_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end
%--------------------------------------------------------
%--------------------------------------------------------
function lowerEdit_Callback(hObject, eventdata, handles)
strg = get(hObject,'String');
lwLimit =str2num(strg);
upLimit = get(handles.upperSlider,'Value');
maxLimit = get(handles.lowerSlider,'Max');
if lwLimit <= maxLimit
    if lwLimit < upLimit
        set(handles.lowerSlider,'Value',lwLimit);
        hMainGui = getappdata(0,'hMainGui');
        handax=findobj(hMainGui,'tag','axes1');
        ll = get(handax,'Clim');
        set(handax,'CLim',[lwLimit ll(2)]);
        handles.intensityParam.lowerLimit = lwLimit;
    else
        errordlg('Lower limit cannot be larger than upper limit');
    end
else
    errordlg('Larger than maximum limit');
end
guidata(hObject, handles);
%--------------------------------------------------------
% --- Executes during object creation, after setting all properties.
%--------------------------------------------------------
function upperEdit_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end
%--------------------------------------------------------
%--------------------------------------------------------
function upperEdit_Callback(hObject, eventdata, handles)
strg = get(hObject,'String');
upLimit =str2num(strg);
lwLimit = get(handles.lowerSlider,'Value');
maxLimit = get(handles.lowerSlider,'Max');
if upLimit <=maxLimit
    if upLimit > lwLimit
        set(handles.upperSlider,'Value',upLimit);
        hMainGui = getappdata(0,'hMainGui');
        handax=findobj(hMainGui,'tag','axes1');
        ll = get(handax,'CLim');
        set(handax,'CLim',[ll(1) upLimit]);
        handles.intensityParam.upperLimit = upLimit;
    else
        errordlg('Lower limit cannot be larger than the upper');
    end
else
    errordlg('Larger than maximum limit');
end
guidata(hObject, handles);

%--------------------------------------------------------
% --- Executes on button press in pushbuttonCancel.
function pushbuttonCancel_Callback(hObject, eventdata, handles)
close(handles.figure1);


function ok = write_hdr_raw(fname,hdr,be)
% Write a NIFTI-1 .hdr file.
% FORMAT ok = write_hdr_raw(fname,hdr,be)
% fname - filename of image
% hdr   - a structure containing hdr info
% be    - whether big-endian or not
% ok    - status (1=good, 0=bad)
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id$

[pth,nam,ext] = fileparts(fname);
if isempty(pth), pth = pwd; end

if isfield(hdr,'magic')
    org = niftistruc;
    switch deblank(hdr.magic)
    case {'ni1'}
        hname = fullfile(pth,[nam '.hdr']);
    case {'n+1'}
        hname = fullfile(pth,[nam '.nii']);
    otherwise
        error('Bad header.');
    end;
else
    org   = mayostruc;
    hname = fullfile(pth,[nam '.hdr']);
end;

if nargin >=3
    if be, mach = 'ieee-be';
    else   mach = 'ieee-le';
    end;
else       mach = 'native';
end;

ok = true;
if spm_existfile(hname),
    fp = fopen(hname,'r+',mach);
else
    fp = fopen(hname,'w+',mach);
end
if fp == -1,
    ok = false;
    return;
end

for i=1:length(org)
    if isfield(hdr,org(i).label),
        dat = hdr.(org(i).label);
        if length(dat) ~= org(i).len,
            if length(dat)< org(i).len,
                dat = [dat(:) ; zeros(org(i).len-length(dat),1)];
            else
                dat = dat(1:org(i).len);
            end;
        end;
    else
        dat = org(i).def;
    end;
    % fprintf('%s=\n',org(i).label)
    % disp(dat)
    len = fwrite(fp,dat,org(i).dtype.prec);
    if len ~= org(i).len,
        ok = false;
    end;
end;
fclose(fp);
if ~ok,
     fprintf('There was a problem writing to the header of\n');
     fprintf('"%s"\n', fname);
end;
return;