function varargout = read_meas_prot(filename, varargin)
%READ_MEAS_PROT  read pulse sequence protocol from VB13A- and VB15A-style "meas.dat"
%
% YAPS = read_meas_prot(filename)

% jonathan polimeni <jonp@padkeemao.nmr.mgh.harvard.edu>, 2007/jan/03
% $Id: read_meas_prot.m,v 1.1 2008/05/21 19:01:01 greve Exp $
%**************************************************************************%

  VERSION = '$Revision: 1.1 $';
  if ( nargin == 0 ), help(mfilename); return; end;

  header = '';
  if ( nargin >= 2 ),
    if ( ~isstruct(varargin{1}) ),
      header = varargin{1};
    end;
  end;

  %------------------------------------------------------------------------%
  % error checking

  if ( ~exist(filename, 'file') ),
    error('file [%s] does not exist', filename);
  end;

  VERBOSE = 0;

  %------------------------------------------------------------------------%

  if ( isempty(header) ),
    [fp, errstr] = fopen(filename, 'r', 'l');
    if ( fp == -1 ),
      error(errstr);
    end;

    % determine size (in bytes) of ascii header files stored in the 'meas.dat'
    % format (i.e., "Config_.evp", "Dicom_.evp", etc) to skip over them all.
    % [note: this works for VB11A also---the first integer is 32, which is
    % the number of bytes to skip at the beginning!]
    data_start = fread(fp, 1, 'uint32');

    header_files = fread(fp, 1, 'uint32');

    % read header into one string for parsing
    header = fscanf(fp, '%c', data_start-24);

    fclose(fp);

  end;

  %------------------------------------------------------------------------%
  % ICE parameters from Config_.evp

  param_list = {
      ... %%% k-space sample counts  (no "RawSeg" for some reason)
      'RawCol','RawLin','RawCha','RawSet','RawEco','RawPhs','RawRep', ...
      'RawPar','RawSlc','RawIda','RawIdb','RawIdc','RawIdd','RawIde','RawAve', ...
      ... %%%
      ... %%% iPAT / parallel imaging acquisition parameters
      'NAFLin','NAFPar','NFirstLin','NFirstPar', ...
      'NRefLin','NRefPar','NFirstRefLin','NFirstRefPar', ...
      ... %%%
      ... %%% effective k-space dimensions
      'NColMeas','NLinMeas','NChaMeas','NSetMeas','NEcoMeas','NPhsMeas','NRepMeas','NSegMeas', ...
      'NParMeas','NSlcMeas','NIdaMeas','NIdbMeas','NIdcMeas','NIddMeas','NIdeMeas','NAveMeas', ...
      ... %%%
      ... %%% final image dimensions
      'NImageLins','NImageCols','NImagePar'};

  Config_evp = cell2struct(cell(length(param_list),1), param_list, 1);
  Config_evp_values = [];

  for ind = 1:length(param_list),
    param = param_list{ind};

    %%%%%%% MATCH TYPE #0: integer dimension size, e.g., <ParamLong."RawCol">  { 256  }
    match = regexp(header, ['<Param\w+\."(?<param>' param ')">\s*{\s*(?<value>[-]*\d*)\s*}'], 'names');

    % check if no match is found
    if ( isempty(match) ),
      if ( VERBOSE ),
        warning('SIEMENS:IO:versioning', 'missing protocol parameter "%s"---check sequence', param);
      end;
      continue;
    end;

    % consider only first match
    match = match(1);

    % empty means value for this parameter dimension = 0
    if ( isempty(match.value) ),
      match.value = '0';
    end;

    % save out struct and numerical array
    param_values(ind) = str2num(match.value);

    %%%-------------------------------%
    %%% SPECIAL CASES: "NFirstLin", "NFirstPar", "NFirstRefLin", "NFirstRefPar" (0-based indices needing conversion to 1-based)
    if ( regexp(param, '^NFirst') ),
      param_values(ind) = param_values(ind) + 1;
    end;

    Config_evp = setfield(Config_evp, param_list{ind}, param_values(ind));

  end;  %% FOR

  %  %%%-------------------------------%
  %  %%% SPECIAL CASES: "NFirstRefLin", "NFirstRefPar"
  %  if ( Config_evp.NFirstRefLin == 0 ),
  %    Config_evp.NRefLin = 0;
  %  end;
  %  if ( Config_evp.NFirstRefPar == 0 ),
  %    Config_evp.NRefPar = 0;
  %  end;

  %========================================================================%
  %------------------------------------------------------------------------%
  %========================================================================%
  % IDEA parameters from YAPS, a.k.a., ASCCONV (contained in meas.asc)

  %  TODO: determine phase encoding or readout direction, and polarities,
  %  to convert reconstructed matrix into proper viewing position

  %------------------------------------------------------------------------%
  % anastasia's list

  %  p.SequenceFileName      = 'tSequenceFileName';
  %  p.ProtocolName          = 'tProtocolName';
  %  p.FlipAngleDegree       = 'adFlipAngleDegree';
  %  p.TxFrequency           = 'sTXSPEC.lFrequency';
  %  p.BaseResolution        = 'sKSpace.lBaseResolution';
  %  p.PhaseEncodingLines    = 'sKSpace.lPhaseEncodingLines';
  %  p.FourierRows           = 'iNoOfFourierLines';
  %  p.FourierColumns        = 'iNoOfFourierColumns';
  %  p.NumChannels           = 'iMaxNoOfRxChannels';
  %  p.PhaseResolution       = 'sKSpace.dPhaseResolution';
  %  p.Partitions            = 'sKSpace.lPartitions';
  %  p.TR                    = 'alTR\[[0-9]*\]';
  %  p.TI                    = 'alTI\[[0-9]*\]';
  %  p.TE                    = 'alTE\[[0-9]*\]';
  %  p.SliceArraySize        = 'sSliceArray.lSize';
  %  p.SlicePositionSag      = 'sSliceArray.asSlice\[[0-9]*\].sPosition.dSag';
  %  p.SlicePositionCor      = 'sSliceArray.asSlice\[[0-9]*\].sPosition.dCor';
  %  p.SlicePositionTra      = 'sSliceArray.asSlice\[[0-9]*\].sPosition.dTra';
  %  p.SliceNormalSag        = 'sSliceArray.asSlice\[[0-9]*\].sNormal.dSag';
  %  p.SliceNormalCor        = 'sSliceArray.asSlice\[[0-9]*\].sNormal.dCor';
  %  p.SliceNormalTra        = 'sSliceArray.asSlice\[[0-9]*\].sNormal.dTra';
  %  p.Thickness             = 'sSliceArray.asSlice\[[0-9]*\].dThickness';
  %  p.PhaseFOV              = 'sSliceArray.asSlice\[[0-9]*\].dPhaseFOV';
  %  p.ReadoutFOV            = 'sSliceArray.asSlice\[[0-9]*\].dReadoutFOV';
  %  p.InPlaneRot            = 'sSliceArray.asSlice\[[0-9]*\].dInPlaneRot';
  %  p.DiffDirections        = 'sDiffusion.lDiffDirections';
  %  p.bValue                = 'sDiffusion.alBValue\[1\]';
  %  p.b0Repetitions         = 'sWiPMemBlock.alFree\[8\]';
  %  p.Repetitions           = 'lRepetitions';

  % dwelltime = The base resolution and the effective dwelltime are specified without oversampling
  % (true number of samples = base_resolution * oversampling,
  % real dwelltime = effective dwelltime/oversampling).

  % duration of the ADC (columns * dwelltime)

  % YAPS.lRampTime, YAPS.lFlatTime, YAPS.lADCDuration, YAPS.lRampMode

  [YAPS, param_list] = read_meas_prot__struct;

  param_values = zeros(length(param_list),1);

  % scan through header for each of the protocol parameter values
  for ind = 1:length(param_list),
    param = param_list{ind};

    %%%-------------------------------%
    %%% SPECIAL CASE:

    if ( strcmp(param, 'sCoilElementID_tElement') ),

      match = regexp(header, ['asCoilSelectMeas\S*(?<param>lRxChannelConnected)\s*=\s*(?<value>\d*\.?x?\d*)'], 'names');
      channel_val = str2double({match.value});
      [channel_unique, channel_index] = unique(channel_val);

      match = regexp(header, ['asCoilSelectMeas\S*(?<param>tElement)\s*=\s*"(?<string>\S*)"'], 'names');

      YAPS = setfield(YAPS, 'sCoilElementID_tElement', {match(channel_index).string});
      continue;

    end;

    %%%-------------------------------%
    %%% SPECIAL CASE: slice array params, "dPhaseFOV", "dReadoutFOV"

    if ( strcmp(param, 'dPhaseFOV') || strcmp(param, 'dReadoutFOV') ),
      param = strcat('asSlice\S*', param);
    end;

    %%%-------------------------------%

    % exploit MATLAB regexp machinery to pull out parameter/value pairs

    %%%%%%% MATCH TYPE #1: string parameter, e.g.,  tSequenceFileName                        = "%SiemensSeq%\gre"
    match = regexp(header, ['\W(?<param>' param ')\s*=\s*"(?<string>\S*)"'], 'names');
    if ( ~isempty(match) ),
      % consider only first match
      match = match(1);

      % set string value
      YAPS = setfield(YAPS, regexprep(param_list{ind}, '\.', '_'), match.string);
      continue;
    end;

    %%%%%%% MATCH TYPE #2: numerical parameter but single element, e.g., iMaxNoOfRxChannels                       = 9
    match = regexp(header, ['\W(?<param>' param ')\s*=\s*(?<value>(-*)\d*\.?x?\w*)'], 'names', 'once');

    if ( isempty(match) ),

      %%%%%%% MATCH TYPE #3: numerical parameter array, possibly negative, e.g., sRXSPEC.alDwellTime[0]                   = 6500
      match = regexp(header, ['\W(?<param>' param ')\[(?<index>\d*)\]\s*=\s*(?<value>(-*)\d*\.?\d*)'], 'names');

      if ( ~isempty(match) ),

        %%%-------------------------------%
        %%% SPECIAL CASE: "alRegridMode"

        % the "alRegridMode" parameter consists of an array of values indicating
        % which basic waveform components comprise the readout waveform. the
        % presence of a fifth component (i.e., "alRegridMode[4]") indicates a
        % sinusoidal waveform. the parameter value itself is irrelevant here.
        if ( strcmp(param, 'alRegridMode') ),
          sinusoid_gradient_waveform_flag = 0;
          for im = 1:length(match),
            if ( match(im).index == 4 ),
              % sinusoidal waveform found!
              % save out struct and numerical array
              sinusoid_gradient_waveform_flag = 1;
            end;
          end;
          if ( sinusoid_gradient_waveform_flag == 1 ),
            param_values(ind) = 4;  % 'REGRID_SINUSOIDAL'
          else,
            param_values(ind) = 2;  % 'REGRID_TRAPEZOIDAL'
          end;
          YAPS = setfield(YAPS, param_list{ind}, param_values(ind));
          continue;
        end;

        %%%-------------------------------%

        indices = str2num([match.index].');
        values = [];

        for ii = 1:length(match),
          % empty means value for this parameter = 0
          if ( isempty(match(ii).value) ),
            match(ii).value = '0';
          end;
          values(str2num(match(ii).index)+1) = str2num(match(ii).value);
        end;

        YAPS = setfield(YAPS, regexprep(param_list{ind}, '\.', '_'), values);
        continue;

      end;

    end;

    % check if still no match is found
    if ( isempty(match) ),
      if ( VERBOSE ),
        warning('SIEMENS:IO:versioning', 'missing protocol parameter "%s"---check sequence', param);
      end;

      if ( regexp(param, '^fl.*') )
	YAPS = setfield(YAPS, regexprep(param_list{ind}, '\.', '_'), 0.0);
      end;

      continue;
    end;

    %========================================================================%
    %========================================================================%
    % consider only first match
    match = match(1);

    % empty means value for this parameter = 0
    if ( isempty(match.value) ),
      match.value = '0';
    end;

    % convert hex entries to decimal
    if ( regexp(match.value, '^0x\d*') ),
      match.value = num2str(hex2dec( regexprep(match.value, '^0x', '') ));
    end;

    %%%-------------------------------%
    %%% ENUMERATED TYPE: "ucPhasePartialFourier" and "ucSlicePartialFourier"
    if ( strcmp(param, 'ucPhasePartialFourier') || strcmp(param, 'ucSlicePartialFourier') ),

      % "enum PartialFourierFactor" snarfed from <n4/pkg/MrServers/MrProtSrv/MrProt/SeqDefines.h>
      switch str2num(match.value),
       case hex2dec('01'),  % PF_HALF = 0x01
        match.value = '4/8';
       case hex2dec('02'),  % PF_5_8  = 0x02
        match.value = '5/8';
       case hex2dec('04'),  % PF_6_8  = 0x04
        match.value = '6/8';
       case hex2dec('08'),  % PF_7_8  = 0x08
        match.value = '7/8';
       case hex2dec('10'),  % PF_OFF  = 0x10
        match.value = '8/8';
       otherwise,
        warning(sprintf('unrecognized mode for "%s":  [ %d ]', param, match.value));
      end;

    end;

    %%%-------------------------------%
    %%% ENUMERATED TYPE: "ucMultiSliceMode"

    if ( strcmp(param, 'ucMultiSliceMode') ),
      % "enum MultiSliceMode" snarfed from <n4/pkg/MrServers/MrProtSrv/MrProt/SeqDefines.h>
      switch str2num(match.value),
       case hex2dec('01'),  % MSM_SEQUENTIAL  = 0x01
        match.value = 'MSM_SEQUENTIAL';
       case hex2dec('02'),  % MSM_INTERLEAVED = 0x02
        match.value = 'MSM_INTERLEAVED';
       case hex2dec('04'),  % MSM_SINGLESHOT  = 0x04
        match.value = 'MSM_SINGLESHOT';
       otherwise,
        warning(sprintf('unrecognized mode for "%s":  [ %d ]', param, match.value));
      end;

      YAPS = setfield(YAPS, regexprep(param_list{ind}, '\.', '_'), match.value);
      continue;
    end;

    %%%-------------------------------%
    %%% ENUMERATED TYPE: "ucPATMode"
    if ( strcmp(param, 'ucPATMode') ),

      % "enum PATSelMode" snarfed from <n4/pkg/MrServers/MrProtSrv/MrProt/SeqDefines.h>
      switch str2num(match.value),
       case hex2dec('01'),
        match.value = 'PAT_MODE_NONE';
       case hex2dec('02'),
        match.value = 'PAT_MODE_GRAPPA';
       case hex2dec('04'),
        match.value = 'PAT_MODE_SENSE';
       case hex2dec('08'),
        match.value = 'PAT_MODE_2D';
       otherwise,
        warning(sprintf('unrecognized mode for "%s":  [ %d ]', param, match.value));
      end;

      YAPS = setfield(YAPS, regexprep(param_list{ind}, '\.', '_'), match.value);
      continue;
    end;

    %%%-------------------------------%
    %%% ENUMERATED TYPE: "ucRefScanMode"
    if ( strcmp(param, 'ucRefScanMode') ),

      % "enum PATRefScanMode" snarfed from <n4/pkg/MrServers/MrProtSrv/MrProt/SeqDefines.h>
      switch str2num(match.value),
       case hex2dec('01'),
        match.value = 'PAT_REF_SCAN_UNDEFINED';      % e.g. if no PAT is selected
       case hex2dec('02'),
        match.value = 'PAT_REF_SCAN_INPLACE';        % sequence supplies inplace reference lines
       case hex2dec('04'),
        match.value = 'PAT_REF_SCAN_EXTRA';          % sequence supplies extra reference lines
       case hex2dec('08'),
        match.value = 'PAT_REF_SCAN_PRESCAN';        % sequence does not supply reference lines, the data must have been acquired with a previous measurement
       case hex2dec('10'),
        match.value = 'PAT_REF_SCAN_INTRINSIC_AVE';  % The sequence contains intrinsic ref.lines due to sharing e.g. in the averages dimension
       case hex2dec('20'),
        match.value = 'PAT_REF_SCAN_INTRINSIC_REP';  % The sequence contains intrinsic ref.lines due to sharing e.g. in the repetition or phases dimension (i.e., TSENSE)
       case hex2dec('40'),
        match.value = 'PAT_REF_SCAN_INTRINSIC_PHS';  % The sequence contains intrinsic ref.lines due to sharing e.g. in the repetition or phases dimension (i.e., TSENSE)
       case hex2dec('80'),
        match.value = 'PAT_REF_SCAN_INPLACE_LET';    % A single (L)ong (E)cho (T)rain acquires reference lines and imaging lines
       otherwise,
        warning(sprintf('unrecognized mode for "%s":  [ %d ]', param, match.value));
      end;

      YAPS = setfield(YAPS, regexprep(param_list{ind}, '\.', '_'), match.value);
      continue;
    end;

    %------------------------------------------------------------------------%

    % save out struct and numerical array
    param_values(ind) = str2num(match.value);
    YAPS = setfield(YAPS, regexprep(param_list{ind}, '\.', '_'), param_values(ind));

  end;  %% FOR

  %------------------------------------------------------------------------%
  %------------------------------------------------------------------------%
  %%% post-processing

  if ( ~strncmp(YAPS.ulVersion, '0x', 2) ),
    YAPS.ulVersion = lower(['0x' dec2hex(YAPS.ulVersion)]);
  end;

  switch YAPS.ulVersion,
   case '0xbee332',
    YAPS.ulVersion = [YAPS.ulVersion, ':  "N4_VA25A_LATEST_20040724"'];
   case '0x1421cf5',
    YAPS.ulVersion = [YAPS.ulVersion, ':  "N4_VB11D_LATEST_20040724"'];
   case '0x1452a3b',
    YAPS.ulVersion = [YAPS.ulVersion, ':  "N4_VB13A_LATEST_20060607"'];
   case '0x1483779',
    YAPS.ulVersion = [YAPS.ulVersion, ':  "N4_VB15A_LATEST_20070519"'];
   otherwise,
    disp(sprintf('==> [%s]: version string "%s" not on record!', mfilename, ...
                 YAPS.ulVersion));
  end;

  %%%-------------------------------%
  %%% SPECIAL CASE: "alTE"

  YAPS.alTE = YAPS.alTE(1:YAPS.lContrasts);

  %%%-------------------------------%
  %%% SPECIAL CASE: regrid parameters (only a pain in VB15)

  if ( isempty(YAPS.alRegridMode) ),

    param_list = {'alRegridRampupTime', 'alRegridRampdownTime', ...
                  'alRegridFlattopTime', 'alRegridDelaySamplesTime', ...
                  'alRegridMode', 'aflRegridADCDuration'};

    for ind = 1:length(param_list),
      param = param_list{ind};

      match = regexp(header, ['<Param\w+\."(?<param>' param ')">\s*{\s*(?<value>[\d ]*)\s*}'], 'names');

      % SPECIAL CASE (within a special case): pesky 'Precision' string for "aflRegridADCDuration"
      if ( isempty(match) ),
        match = regexp(header, ['<Param\w+\."(?<param>' param ')">\s*{\s*<Precision>[ \d]*\s*(?<value>[\d \.]*)\s*}'], 'names');
      end;

      match.value = str2num(match.value);
      YAPS = setfield(YAPS, param_list{ind}, match.value(1));

    end;

  end;

  %%%-------------------------------%
  %%% ENUMERATED TYPE: "alRegridMode"

  switch YAPS.alRegridMode,
    % "enum RegriddingMode" snarfed from <n4/pkg/MrServers/MrProtSrv/MrProt/SeqDefines.h>

   case hex2dec('01'),
    YAPS.ucRegridMode = 'REGRID_NONE';
   case hex2dec('02'),
    YAPS.ucRegridMode = 'REGRID_TRAPEZOIDAL';
   case hex2dec('04'),
    YAPS.ucRegridMode = 'REGRID_SINUSOIDAL';
   otherwise,
    warning(sprintf('unrecognized mode for "%s":  [ %d ]', 'alRegridMode', YAPS.alRegridMode));
  end;

  %%%-------------------------------%
  %%% SPECIAL CASE: flBandwidthPerPixelPhaseEncode and iEffectiveEpiEchoSpacing (only present in VB15)

  param_list = {'flBandwidthPerPixelPhaseEncode', 'iEffectiveEpiEchoSpacing'};

  for ind = 1:length(param_list),
    param = param_list{ind};

    match = regexp(header, ['<Param\w+\."(?<param>' param ')">\s*{\s*(?<value>[\d.?\d]*)\s*}'], 'names');

    if ( isempty(match) ),
      continue;
    end;

    match.value = str2num(match.value);

    if ( isempty(match.value) ),
      match.value = 0;
    end;

    YAPS = setfield(YAPS, param_list{ind}, match.value(1));

  end;

  %%%-------------------------------%
  %%% SPECIAL CASE: sSliceArray

  param_list = {'sPosition.dSag', 'sPosition.dCor', 'sPosition.dTra', ...
                  'sNormal.dSag',   'sNormal.dCor',   'sNormal.dTra', ...
                'dThickness', 'dPhaseFOV', 'dReadoutFOV', 'InPlaneRot'};

  % empty sub-struct for slice array
  asSlice = cell2struct(cell(length(param_list),1), regexprep(param_list, '\.', '_'), 1);

  for slc = 1:YAPS.sSliceArray_lSize,

    % assign new empty sub-struct for each slice
    YAPS.sSliceArray(slc) = asSlice;

    for ind = 1:length(param_list),

    param = param_list{ind};
    param = regexprep(param, '\.', '\\.');

    match = regexp(header, ['sSliceArray\.asSlice\[' num2str(slc-1) '\]\.(?<param>' param ')\s*=\s*(?<value>(-*)\d*\.?x?\w*)'], 'names');

    % check if no match is found (e.g., only one of three possible normals will be represented, so empty match is common)
    if ( isempty(match) ),
      match(1).value = '0';
    end;

    % consider only first match
    match = match(1);

    YAPS.sSliceArray(slc) = setfield(YAPS.sSliceArray(slc), regexprep(param_list{ind}, '\.', '_'), str2num(match.value));
    end;
  end;

  %------------------------------------------------------------------------%

  if ( nargout > 0 ),
    varargout{1} = YAPS;
    varargout{2} = Config_evp;
    varargout{3} = header;
  end;

  return;

  %************************************************************************%
  %%% $Source: /space/repo/1/dev/dev/matlab/read_meas_prot.m,v $
  %%% Local Variables:
  %%% mode: Matlab
  %%% fill-column: 76
  %%% comment-column: 0
  %%% End:


function varargout = icatb_read_gzip_nii(fileIn, varargin)
%% Read data from gzip nifti file (*.nii.gz) directly using GZIPInputstream.
%
% Inputs:
%
% 1. fileIn - Nifti gzip file name
% 2. varargin - Variable arguments passed in pairs
%
%   a. read_hdr_only - Optional argument. By default, both header and data information is returned. If set to 1, only necessary fields in header
%   are returned (slices and timeNo variables are ignored).
%   b. slices - Axial slice/slices. You could enter row vector of slices. By
%   default, all slices are loaded.
%   c. timepoints - Timepoints of interest. By default, all timepoints are
%   returned.
%   d.mask - Mask of interest. Specify full file path or use boolean mask
%   or indices.
%   e. use_spm -  Gzip files are un-zipped and spm volume functions are used to read nifti
%   files
%   f. buffer_size - Default buffer size is set to 2^14 bytes (memory efficient) when reading
%   using GZIPInputstream. Max buffer size you could specify is 2^31-1.
%
% Outputs:
% [hdr, V] - if read_hdr_only == 1. hdr is header and V is spm volume
% structure.
% [data, hdr, V] if read_hdr_only == 0. Data is 4D array (x,y,z,t) or 2D
% array (x*y*z, t) if mask is specified, hdr is header and V os spm volume structure.
%
%

NIFTI_GZ = 0;

GZIPINFO.isLargeFile = 1;
GZIPINFO.buffer_size = 2^14;

%% Parse inputs
read_hdr_only = 0;
buffer_size = 2^14;
isLargeFile = 0;
try
    buffer_size = GZIPINFO.buffer_size;
catch
end

try
    isLargeFile = GZIPINFO.isLargeFile;
catch
end

isSPMRead = NIFTI_GZ;
if (isempty(isSPMRead))
    isSPMRead = 0;
end
slices = [];
timeNo = [];

for n = 1:2:length(varargin)
    if (strcmpi(varargin{n}, 'read_hdr_only'))
        read_hdr_only = varargin{n + 1};
    elseif (strcmpi(varargin{n}, 'slices'))
        slices = varargin{n + 1};
    elseif (strcmpi(varargin{n}, 'timepoints') || strcmpi(varargin{n}, 'time'))
        timeNo = varargin{n + 1};
    elseif (strcmpi(varargin{n}, 'mask'))
        mask = varargin{n + 1};
    elseif (strcmpi(varargin{n}, 'use_spm'))
        isSPMRead = varargin{n + 1};
    elseif (strcmpi(varargin{n}, 'buffer_size'))
        buffer_size = varargin{n + 1};
    end
end

if (nargout > 3)
    error('Max number of output arguments can be returned is 3');
end

if (read_hdr_only)
    if (nargout > 2)
        error('Max number of output arguments can be returned is 2 with read header only');
    end
end

if (~usejava('jvm'))
    error('Requires jvm to read gzip nifti (*.nii.gz) file');
end

jar_p = fileparts(which('icatb_read_gzip_nii.m'));

if (~isdeployed)
    javaaddpath(fullfile(jar_p, 'icatb_gz.jar'));
end

import icatb_gz.*;

if (~isSPMRead)
    try
        zclass = icatb_gz.read_gzip();
    catch
        isSPMRead = 1;
    end
end

nBytesToRead = 348;
doSwapBytes = 0;

%% Use GZIPInputstream
if (read_hdr_only)
    fid  = java.io.FileInputStream(fileIn);
    zid  = java.util.zip.GZIPInputStream(fid);
    if (nargout == 1)
        zid.skip(40);
        if (~isSPMRead)
            inByteArray = zclass.read(zid, 16);
        else
            inByteArray = readInitialBytes(zid, 16);
        end
    else
        if (~isSPMRead)
            inByteArray = zclass.read(zid, nBytesToRead);
        else
            inByteArray = readInitialBytes(zid, nBytesToRead);
        end
    end
    try
        zid.close();
        fid.close();
    catch
    end
    hdr = read_hdr(inByteArray);
    if (nargout > 1)
        gzV = getVol(fileIn, hdr);
    end

else

    if (~isSPMRead)
        [inByteArray, hdr, doSwapBytes] = readGzip(fileIn, buffer_size, isLargeFile);
        gzV = getVol(fileIn, hdr);
    else
        % Uncompress file and read header
        [hdr, orig_gzfn, gzV, XYZ] = getSpmVol(fileIn, timeNo);
    end

end

if (read_hdr_only)

    varargout{1} = hdr;
    if (nargout == 2)
        varargout{2} = gzV;
    end

    return;

end

dims = hdr.dim(2:5);

if (~exist('slices', 'var') || isempty(slices))
    slices = 1:dims(3);
end

if (~exist('timeNo', 'var') || isempty(timeNo))
    timeNo = 1:dims(4);
end

byteA = double(hdr.bitpix / 8);

convertDataTo2D = 1;

%% Mask
if (exist('mask', 'var') && ~isempty(mask))
    if (ischar(mask))
        mask = spm_read_vols(spm_vol(mask));
        mask(isfinite(mask)==0) = 0;
    end
    if (numel(mask) ~= prod(dims(1:3)))
        maskF = zeros(dims(1:3));
        maskF(mask) = 1;
    else
        maskF = mask;
    end
    maskF = reshape(maskF, dims(1:3));
else
    convertDataTo2D = 0;
    maskF = (ones(dims(1:3)) ~= 0);
end

mask_inds = find(maskF(:, :, slices) ~= 0);

if (~convertDataTo2D)
    data = zeros(dims(1), dims(2), length(slices), length(timeNo));
else
    data = zeros(length(mask_inds), length(timeNo));
end

for t = 1:length(timeNo)
    endT = 0;
    for z = 1:length(slices)
        startT = endT  + 1;

        if (~isSPMRead)

            if (convertDataTo2D)
                mInds = find(maskF(:, :, slices(z)) ~= 0);
            end

            position =  double(byteA*((timeNo(t)-1)*prod(dims(1:3)) + (slices(z)-1)*prod(dims(1:2)))) + double(hdr.vox_offset);

            tmp = inByteArray(position + 1: position + dims(1)*dims(2)*byteA);

            if (~convertDataTo2D)
                if (~doSwapBytes)
                    tmp = double(typecast(tmp, hdr.precision));
                else
                    tmp = double(swapbytes(typecast(tmp, hdr.precision)));
                end
                tmpDat = reshape(tmp, [dims(1), dims(2)]);
            else
                if (~doSwapBytes)
                    tmpDat = double(typecast(tmp, hdr.precision));
                else
                    tmpDat = double(swapbytes(typecast(tmp, hdr.precision)));
                end
                tmpDat = tmpDat(mInds);
            end

            endT = endT + length(tmpDat);

        else

            mInds = find(maskF(:, :, slices(z)) ~= 0);
            tmpa = squeeze(XYZ(1, :, :, slices(z)));
            tmpb = squeeze(XYZ(2, :, :, slices(z)));
            tmpa = tmpa(mInds);
            tmpb = tmpb(mInds);
            tmpDat = [];
            if (~isempty(mInds))
                tmpDat = spm_sample_vol(gzV(t), tmpa, tmpb, slices(z)*ones(size(mInds)), 0);
            end
            endT = endT + length(tmpDat);
            if (~convertDataTo2D)
                tmpDat = reshape(tmpDat, dims(1), dims(2));
            end

        end

        clear tmp;

        if (~convertDataTo2D)
            data(:, :, z, t) = tmpDat;
        else
            data(startT:endT, t) = tmpDat;
        end

    end

end

if (~isSPMRead)
    if (hdr.scl_slope ~=0)
        data = data*hdr.scl_slope + hdr.scl_inter;
    end
end

data (isfinite(data) == 0) = 0;

varargout{1} = data;
varargout{2} = hdr;

if (nargout == 3)
    varargout{3} = gzV(1);
end

if (exist('orig_gzfn', 'var'))
    doCleanUpFiles(orig_gzfn);
end

function [hdr, doSwapBytes] = read_hdr(inByteArray)
%% Read header

doSwapBytes = 0;
corr_types = {'uint8', 'int16', 'int32', 'single', 'double', 'int8', 'uint16', 'uint32'};
codes   = [2, 4, 8, 16, 64, 256, 512, 768];

% necessary fields
if (length(inByteArray) == 16)
    dim = typecast(inByteArray, 'int16');
    if (dim(1) < 1 || dim(1) > 7)
        doSwapBytes = 1;
        dim = swapbytes(typecast(inByteArray, 'int16'));
    end
    hdr.dim = dim(:)';
    return;
end

chk = typecast(inByteArray(41:56), 'int16');
if (chk(1) < 1 || chk(1) > 7)
    doSwapBytes = 1;
end

fieldsIn  = {   'dim',    'int16',  (41:56);
    'datatype',           'int16',  (71:72);
    'bitpix',             'int16',  (73:74);
    'vox_offset',         'single', (109:112);
    'pixdim',             'single', (77:108);
    'scl_slope',          'single', (113:116);
    'scl_inter',          'single', (117:120);
    'qform_code',         'int16',  (253:254);
    'sform_code',         'int16',  (255:256);
    'quatern_b',          'single', (257:260);
    'quatern_c',          'single', (261:264);
    'quatern_d',          'single', (265:268);
    'qoffset_x',          'single', (269:272);
    'qoffset_y',          'single', (273:276);
    'qoffset_z',          'single', (277:280);
    'sizeof_hdr',         'int32',  (1:4);
    'data_type',          'char',   (5:14);
    'db_name',            'char',   (15:32);
    'extents',            'int32',  (33:36);
    'session_error',      'int16',  (37:38);
    'regular',            'char',   (39:39);
    'dim_info',           'uint8',   (40:40);
    'intent_p1',          'single', (57:60);
    'intent_p2',          'single', (61:64);
    'intent_p3',          'single', (65:68);
    'intent_code',        'int16',  (69:70);
    'slice_start',        'int16',  (75:76);
    'slice_end',          'int16',  (121:122);
    'slice_code',         'uint8',   (123:123);
    'xyzt_units',         'uint8',   (124:124);
    'cal_max',            'single', (125:128);
    'cal_min',            'single', (129:132);
    'slice_duration',     'single', (133:136);
    'toffset',            'single', (137:140);
    'glmax',              'single', (141:144);
    'glmin',              'single', (145:148);
    'descrip',            'char',   (149:228);
    'aux_file',           'char',   (229:252);
    'srow_x',             'single', (281:296);
    'srow_y',             'single', (297:312);
    'srow_z',             'single', (313:328);
    'intent_name',        'char',   (329:344);
    'magic',              'char',   (345:348)};

for nF = 1:size(fieldsIn, 1)
    if (strcmpi(fieldsIn{nF, 2}, 'char'))
        tmp = char(inByteArray(fieldsIn{nF, 3}));
        if (size(tmp, 1) > 1)
            tmp = tmp';
        end
    else
        if (~doSwapBytes)
            tmp = typecast(inByteArray(fieldsIn{nF, 3}), fieldsIn{nF, 2});
        else
            tmp = swapbytes(typecast(inByteArray(fieldsIn{nF, 3}), fieldsIn{nF, 2}));
        end
    end
    if (isnumeric(tmp))
        tmp = double(tmp(:)');
    end
    hdr.(fieldsIn{nF, 1}) = tmp;
end

hdr.dim = hdr.dim(:)';
hdr.pixdim = hdr.pixdim(:)';

hdr.precision = [];
chk = find(codes == hdr.datatype);
if (~isempty(chk))
    hdr.precision = corr_types{chk};
end

if isempty(hdr.precision)
    error('Unknown data type');
end

function [inByteArray, hdr, doSwapBytes] = readGzip(fileIn, buffer_size, isLargeFile)
%% Read large data in chunks
%

import icatb_gz.*;
zclass = icatb_gz.read_gzip();
hdrSize = 348;

tmpFileInfo = dir(fileIn);
tmpGBytes = tmpFileInfo(1).bytes/1024/1024/1024;

% if (tmpGBytes > 0.5)
%     isLargeFile = 1;
% end

if (isLargeFile)

    fid  = java.io.FileInputStream(fileIn);
    zid  = java.util.zip.GZIPInputStream(fid);

    try

        hdrBytes = zclass.read(zid, hdrSize);

        [hdr, doSwapBytes] = read_hdr(typecast(hdrBytes, 'uint8'));

        voxel_offset = hdr.vox_offset;
        bytesA = hdr.bitpix/8;
        byte_array_size = voxel_offset + prod(hdr.dim(2:5))*bytesA;
        inByteArray = zeros(byte_array_size, 1, 'int8');
        inByteArray(1:hdrSize) = hdrBytes;
        zid.close();
        fid.close();

        fid  = java.io.FileInputStream(fileIn);
        zid  = java.util.zip.GZIPInputStream(fid);
        zid.skip(voxel_offset);
        count = voxel_offset;
        while 1

            count = count + 1;

            tmp = zclass.read(zid, buffer_size);

            len = length(tmp);

            if (len == 0)
                break;
            end

            endCount = count + len - 1;
            inByteArray(count:endCount) = tmp;
            count = endCount;

        end

        inByteArray = typecast(inByteArray, 'uint8');

        zid.close();
        fid.close();

    catch

        zid.close();
        fid.close();

    end

else

    inByteArray = zclass.read(fileIn, buffer_size);
    inByteArray = typecast(inByteArray, 'uint8');
    [hdr, doSwapBytes] = read_hdr(inByteArray);

end

function V = getVol(fname, hdr)
%% Create spm volume structure from header

fname_i = fname;
[pathstr, fn, extn] = fileparts(fname);

extn = strrep(lower(extn), '.gz', '');
fname = fullfile(pathstr, [fn, extn]);

mat = decode_qform0(hdr);

V   = struct('fname', fname,...
    'dim',   hdr.dim(2:4),...
    'dt',   [hdr.datatype, 0],...
    'pinfo', [hdr.scl_slope hdr.scl_inter hdr.vox_offset]',...
    'mat',   mat,...
    'n',     1,...
    'descrip', 'NIFTI');

h = nifti;
h.mat = V.mat;
h.mat0 = V.mat;
fp  = fopen(fname_i, 'r', 'native');
[~,~,mach] = fopen(fp);
fclose(fp);
dat = file_array(V.fname, hdr.dim(2:5),[hdr.datatype, strfind(mach,'be')], hdr.vox_offset, hdr.scl_slope, hdr.scl_inter);
h.dat = dat;
h.diminfo.slice = 3;
h.diminfo.slice_time.code = hdr.slice_code;
h.diminfo.slice_time.start = hdr.slice_start+1;
h.diminfo.slice_time.end = hdr.slice_end+1;
h.timing.toffset = hdr.toffset;
h.timing.tspace = hdr.pixdim(5);
matcodes = {'UNKNOWN', 'Scanner', 'Aligned', 'Talairach', 'MNI152'};
h.mat_intent = matcodes{hdr.sform_code+1};
h.mat0_intent = matcodes{hdr.qform_code+1};
V.private = h;

function M = decode_qform0(hdr)
% Decode qform info from NIFTI-1 headers.
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id: decode_qform0.m 3131 2009-05-18 15:54:10Z guillaume $

dim    = double(hdr.dim);
pixdim = double(hdr.pixdim);
if ~isfield(hdr,'magic') || hdr.qform_code <= 0,
    flp = spm_flip_analyze_images;
    %disp('------------------------------------------------------');
    %disp('The images are in a form whereby it is not possible to');
    %disp('tell the left and right sides of the brain apart.');
    %if flp,
    %    disp('They are assumed to be stored left-handed.');
    %else
    %    disp('They are assumed to be stored right-handed.');
    %end;
    %disp('------------------------------------------------------');

    %R     = eye(4);
    n      = min(dim(1),3);
    vox    = [pixdim(2:(n+1)) ones(1,3-n)];

    if ~isfield(hdr,'origin') || ~any(hdr.origin(1:3)),
        origin = (dim(2:4)+1)/2;
    else
        origin = double(hdr.origin(1:3));
    end;
    off     = -vox.*origin;
    M       = [vox(1) 0 0 off(1) ; 0 vox(2) 0 off(2) ; 0 0 vox(3) off(3) ; 0 0 0 1];

    % Stuff for default orientations
    if flp, M = diag([-1 1 1 1])*M; end;
else

    % Rotations from quaternions
    R = Q2M(double([hdr.quatern_b hdr.quatern_c hdr.quatern_d]));

    % Translations
    T = [eye(4,3) double([hdr.qoffset_x hdr.qoffset_y hdr.qoffset_z 1]')];

    % Zooms.  Note that flips are derived from the first
    % element of pixdim, which is normally unused.
    n = min(dim(1),3);
    Z = [pixdim(2:(n+1)) ones(1,4-n)];
    Z(Z<0) = 1;
    if pixdim(1)<0, Z(3) = -Z(3); end;
    Z = diag(Z);

    M = T*R*Z;

    % Convert from first voxel at [1,1,1]
    % to first voxel at [0,0,0]
    M = M * [eye(4,3) [-1 -1 -1 1]'];
end;
return;

function M = Q2M(Q)
% Generate a rotation matrix from a quaternion xi+yj+zk+w,
% where Q = [x y z], and w = 1-x^2-y^2-z^2.
% See: http://skal.planet-d.net/demo/matrixfaq.htm
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id: Q2M.m 1143 2008-02-07 19:33:33Z spm $

Q = Q(1:3); % Assume rigid body
w = sqrt(1 - sum(Q.^2));
x = Q(1); y = Q(2); z = Q(3);
if w<1e-7,
    w = 1/sqrt(x*x+y*y+z*z);
    x = x*w;
    y = y*w;
    z = z*w;
    w = 0;
end;
xx = x*x; yy = y*y; zz = z*z; ww = w*w;
xy = x*y; xz = x*z; xw = x*w;
yz = y*z; yw = y*w; zw = z*w;
M = [...
    (xx-yy-zz+ww)      2*(xy-zw)      2*(xz+yw) 0
    2*(xy+zw) (-xx+yy-zz+ww)      2*(yz-xw) 0
    2*(xz-yw)      2*(yz+xw) (-xx-yy+zz+ww) 0
    0              0              0  1];
return;

function varargout = getSpmVol(fileIn, timeNo)
%% Unzip file and read info
%

gzfn = gunzip (fileIn, tempdir);
orig_gzfn = char(gzfn);

if (nargout > 2)
    gzfn = rename_4d_file(orig_gzfn);
    if (~exist('timeNo', 'var') || isempty(timeNo))
        timeNo = (1:size(gzfn, 1));
    end
    gzV = spm_vol(deblank(gzfn(timeNo, :)));
    hdr = gzV(1).private.hdr;

    hdr.dim = double(hdr.dim);

else

    hdr = icatb_read_hdr(deblank(orig_gzfn));
    hdr.dim = double(hdr.dime.dim);

end

varargout{1} = hdr;
varargout{2} = orig_gzfn;

if (nargout >= 3)
    varargout{3} = gzV;
end

if (nargout == 4)
    XYZ = icatb_get_voxel_coords(gzV(1).dim(1:3));
    XYZ = reshape(XYZ, [3, gzV(1).dim(1:3)]);
    varargout{4} = XYZ;
end

function doCleanUpFiles(orig_gzfn)

try
    for nF = 1:size(orig_gzfn, 1)
        delete(deblank(orig_gzfn(nF, :)));
    end
catch
end

function inByteArray = readInitialBytes(zid, nBytesToRead)
%% Use read method in matlab
%

if (isfinite(nBytesToRead))
    inByteArray = zeros(nBytesToRead, 1, 'uint8');
else
    inByteArray = [];
    inByteArray = uint8(inByteArray);
end

count = 0;
tmp = 0;
while ((tmp ~= -1) && (count < nBytesToRead))
    count = count + 1;
    tmp = uint8(read(zid));
    inByteArray(count) = tmp;
end

function [hdr,otherendian] = icatb_read_hdr(fname)
% Read (SPM customised) Analyze header
% fname       - .hdr filename
% hdr         - structure containing Analyze header
% otherendian - byte swapping necessary flag
%_______________________________________________________________________
% Copyright (C) 2005 Wellcome Department of Imaging Neuroscience

% John Ashburner
% $Id: spm_read_hdr.m 112 2005-05-04 18:20:52Z john $

otherendian = 0;
fname = deblank(fname);
if (strcmpi(fname(end-2:end), '.gz'))
    hdr = icatb_read_gzip_nii(fname, 'read_hdr_only', 1);
    return;
end

fid         = fopen(fname,'r','native');
%otherendian = 0;
if (fid > 0)
    dime = read_dime(fid);
    if dime.dim(1)<0 | dime.dim(1)>15, % Appears to be other-endian
        % Re-open other-endian
        fclose(fid);
        if spm_platform('bigend'), fid = fopen(fname,'r','ieee-le');
        else,                      fid = fopen(fname,'r','ieee-be'); end;
        otherendian = 1;
        dime = read_dime(fid);
    end;
    %hk       = read_hk(fid);
    %hist     = read_hist(fid);
    %hdr.hk   = hk;
    hdr.dime = dime;
    %hdr.hist = hist;

    % SPM specific bit - unused
    %if hdr.hk.sizeof_hdr > 348,
    %	spmf = read_spmf(fid,dime.dim(5));
    %	if ~isempty(spmf),
    %		hdr.spmf = spmf;
    %	end;
    %end;

    fclose(fid);
else,
    hdr = [];
    otherendian = NaN;
    %error(['Problem opening header file (' fopen(fid) ').']);
end;
return;
%_______________________________________________________________________
%_______________________________________________________________________
function hk = read_hk(fid)
% read (struct) header_key
%-----------------------------------------------------------------------
fseek(fid,0,'bof');
hk.sizeof_hdr 		= fread(fid,1,'int32');
hk.data_type  		= mysetstr(fread(fid,10,'uchar'))';
hk.db_name    		= mysetstr(fread(fid,18,'uchar'))';
hk.extents    		= fread(fid,1,'int32');
hk.session_error	= fread(fid,1,'int16');
hk.regular			= mysetstr(fread(fid,1,'uchar'))';
hk.hkey_un0			= mysetstr(fread(fid,1,'uchar'))';
if isempty(hk.hkey_un0), error(['Problem reading "hk" of header file (' fopen(fid) ').']); end;
return;
%_______________________________________________________________________
%_______________________________________________________________________
function dime = read_dime(fid)
% read (struct) image_dimension
%-----------------------------------------------------------------------
fseek(fid,40,'bof');
dime.dim		= fread(fid,8,'int16')';
%dime.vox_units	= mysetstr(fread(fid,4,'uchar'))';
%dime.cal_units	= mysetstr(fread(fid,8,'uchar'))';
%dime.unused1	= fread(fid,1,'int16');
%dime.datatype	= fread(fid,1,'int16');
%dime.bitpix		= fread(fid,1,'int16');
%dime.dim_un0	= fread(fid,1,'int16');
%dime.pixdim		= fread(fid,8,'float')';
%dime.vox_offset	= fread(fid,1,'float');
%dime.funused1	= fread(fid,1,'float');
%dime.funused2	= fread(fid,1,'float');
%dime.funused3	= fread(fid,1,'float');
%dime.cal_max	= fread(fid,1,'float');
%dime.cal_min	= fread(fid,1,'float');
%dime.compressed	= fread(fid,1,'int32');
%dime.verified	= fread(fid,1,'int32');
dime.glmax		= fread(fid,1,'int32');
dime.glmin		= fread(fid,1,'int32');
if isempty(dime.glmin), error(['Problem reading "dime" of header file (' fopen(fid) ').']); end;
return;
%_______________________________________________________________________
%_______________________________________________________________________
function hist = read_hist(fid)
% read (struct) data_history
%-----------------------------------------------------------------------
fseek(fid,148,'bof');
hist.descrip	= mysetstr(fread(fid,80,'uchar'))';
hist.aux_file	= mysetstr(fread(fid,24,'uchar'))';
hist.orient		= fread(fid,1,'uchar');
hist.origin		= fread(fid,5,'int16')';
hist.generated	= mysetstr(fread(fid,10,'uchar'))';
hist.scannum	= mysetstr(fread(fid,10,'uchar'))';
hist.patient_id	= mysetstr(fread(fid,10,'uchar'))';
hist.exp_date	= mysetstr(fread(fid,10,'uchar'))';
hist.exp_time	= mysetstr(fread(fid,10,'uchar'))';
hist.hist_un0	= mysetstr(fread(fid,3,'uchar'))';
hist.views		= fread(fid,1,'int32');
hist.vols_added	= fread(fid,1,'int32');
hist.start_field= fread(fid,1,'int32');
hist.field_skip	= fread(fid,1,'int32');
hist.omax		= fread(fid,1,'int32');
hist.omin		= fread(fid,1,'int32');
hist.smax		= fread(fid,1,'int32');
hist.smin		= fread(fid,1,'int32');
if isempty(hist.smin), error(['Problem reading "hist" of header file (' fopen(fid) ').']); end;
return;
%_______________________________________________________________________
%_______________________________________________________________________
function spmf = read_spmf(fid,n)
% Read SPM specific fields
% This bit may be used in the future for extending the Analyze header.

fseek(fid,348,'bof');
mgc = fread(fid,1,'int32');    % Magic number
if mgc ~= 20020417, spmf = []; return; end;

for j=1:n,
    spmf(j).mat    = fread(fid,16,'double'); % Orientation information
    spmf(j).unused = fread(fid,384,'uchar'); % Extra unused stuff
    if length(spmf(j).unused)<384,
        error(['Problem reading "spmf" of header file (' fopen(fid) ').']);
    end;
    spmf(j).mat = reshape(spmf(j).mat,[4 4]);
end;
return;
%_______________________________________________________________________
%_______________________________________________________________________
function out = mysetstr(in)
tmp = find(in == 0);
tmp = min([min(tmp) length(in)]);
out = setstr([in(1:tmp)' zeros(1,length(in)-(tmp))])';
return;
%_______________________________________________________________________
%_______________________________________________________________________

function files = rename_4d_file(files, fileNumber)
%For nifti and analyze files rename the files by adding a number at the
%end

if ~exist('fileNumber', 'var')
    fileNumber = [];
end

if ~isempty(files)

    % Do pattern match to check IMG or NII files
    files = cellstr(files);

    % MATCH IMG OR NII
    checkNII = regexpi(files, '\.nii$|\.gz$');
    checkIMG = regexpi(files, '\.img$');

    good_inds1 = icatb_good_cells(checkNII);
    good_inds2 = icatb_good_cells(checkIMG);

    % Get good cells
    good_inds = (good_inds1 | good_inds2);
    good_inds = find(good_inds ~= 0);

    clear good_inds1 good_inds2 checkNII checkIMG;

    % If IMG or NII files exist check the headers of the image files
    if ~isempty(good_inds)
        imFiles = files(good_inds);
        if (~isempty(fileNumber)) && (length(fileNumber) == 1) && (fileNumber == 1)
            imFiles = strcat(imFiles, ',1');
            files(good_inds) = imFiles;
        else
            % Loop over img or nii files
            for nIm = 1:length(imFiles)
                currentFile = imFiles{nIm};

                try
                    numFiles = getDims(currentFile);
                catch
                    numFiles = 1;
                end

                if (isempty(fileNumber))
                    tempFileNum = (1:numFiles);
                else
                    tempFileNum = fileNumber;
                end

                tempFileNum(tempFileNum > numFiles) = [];

                if ~isempty(tempFileNum)
                    tempFiles = [repmat(currentFile, length(tempFileNum), 1), repmat(',', length(tempFileNum), 1), numberToString(tempFileNum(:))];
                else
                    tempFiles = '';
                end
                files{good_inds(nIm)} = tempFiles;
            end
            % End loop over img or nii files
            files = cellstr(char(files));
            ind = icatb_good_cells(files);
            files = files(ind);
        end
    end
    % End for checking IMG or NII files

    if ~isempty(files)
        files = char(files);
    end

end

function str = numberToString(nums)
% number to string. pad space after the number

try
    str = arrayfun(@num2str, nums, 'uniformoutput', false);
catch
    str = cell(length(nums), 1);
    for n = 1:length(nums)
        str{n} = num2str(nums(n));
    end
end

str = char(str);

function tp = getDims(currentFile)

if (~strcmpi(currentFile(end-2:end),'.gz'))
    ni = nifti(currentFile);
    tp = ni.dat.dim(4);
else
    ni = icatb_read_hdr(currentFile);
    tp = ni.dim(5);
end

function ind = icatb_good_cells(mycell)
%% Find good cells

if ~iscell(mycell)
    mycell = {mycell};
end

ind = cellfun('isempty', mycell);

% Good cells
ind = (ind == 0);

% Convert ind to row vector
ind = ind(:)';

function xyz = icatb_get_voxel_coords(dims)
%% Get voxel coords
%

xdim = dims(1);
ydim = dims(2);
zdim = dims(3);

[xords, yords] = ndgrid(1:xdim, 1:ydim);
xords = xords(:)'; yords = yords(:)';
CrPl    = 1:zdim;
zords   = CrPl(:)*ones(1,xdim*ydim);
xyz   = [repmat(xords,1,numel(CrPl)); ...
    repmat(yords,1,numel(CrPl)); ...
    reshape(zords',1,[])];


function out = oselect(ob, y)
% recall that imask/omask and idim/odim are swapped on ctranspose
out = fatrix2_select(ob.omask, ob.odim, y);


function varargout=lpcaa2ao(varargin)
%
% For calling details please see v_lpcaa2ao.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_lpcaa2ao.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: lpcaa2ao.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_lpcaa2ao(varargin{:});
else
    v_lpcaa2ao(varargin{:});
end


function setup()
    %  setup allows the user to setup the earthquake datafile, overlaying faults, mainshocks

    % turned into function by Celso G Reyes 2017

    report_this_filefun();
    ZG=ZmapGlobal.Data;
    % make the interface
    %

    if ~exist('ZG.bin_dur', 'var')
        ZG.bin_dur = days(14);
    end

    % This is the info window text
    %
    ttlStr='ZMAP Data Import                               ';
    hlpStr1= ...
        ['                                                '
        'For fast and easy data access ZMAP uses the     '
        'internal matlab data format (*.mat) data files).'
        'Earthquakes catalogs as well as additional      '
        'information must first be loaded as and ASCII   '
        'file. Once this data is saved as a matlab *.mat '
        'file it can be reloaded directly into ZMAP.     '
        '                                                '
        'Several Data types can be integrated:           '
        ' EARTHQUAKE CATALOGS: You will need to supply   '
        ' formated ASCII file (e.g hypoellispe format) or'
        ' an ASCII files with the following information  '
        ' in columns sperated by at least one blanck:    '
        '                                                '
        '  lon lat year month day mag depth hour min     '
        '                                                '
        'Example: (California)                           '
        '-116.86 34.35 86 03 27 4.2 15.0 10 25           '
        'Please note the minus sign for W longitudes!    '
        'You chose the magnitude that you would like to  '
        'work with. Zmap works with decimales (0-100) in '
        'the minute position, not with degrees (0-60)!   '];
    hlpStr2= ...
        ['COASTLINE DATA: ZMAP will plot coastlines and/or'
        'state borders on maps. You need to supply an    '
        'ascii datafile with columns seperated by at     '
        'least one blanck:                               '
        'lon  lat  (e.g. -116.86  34.34)                 '
        'A "lift pen" command can be initiade by the line'
        'Inf  Inf (Therefore you avoid connecting islands'
        ' etc.)                                          '
        '                                                '
        'FAULTS DATA: Faults data is imported in the same'
        'way as coastlines.                              '
        'SYMBOLS: Two type of symbols can be displayed on'
        'the seismicity maps: (1) Epicenters of large    '
        'earthquakes as + signs and (2) main faults as   '
        'thick lines. The input format is identical to   '
        'the above - note that you can seperate multiple '
        'main faults by "Inf Inf".                       ' ];
    hlpStr3= ...
        ['The Clear button will remove existing data      '
        'or overlay symbols.                             '
        '                                                ' ];
    % Find out if figure already exists
    %
    loda=findobj('Type','Figure','-and','Name','Import Data into ZMAP');

    % Set up the setup window Enviroment
    %
    if isempty(loda)
        loda = figure_w_normalized_uicontrolunits( ...
            'Name','Import Data into ZMAP',...
            'NumberTitle','off', ...
            'NextPlot','new', ...
            'Visible','off', ...
            'Position',[ (ZG.fipo(3:4) - [500 400]) (ZG.map_len - [100 100]) ]);

        te = text(0.1,0.99,'Load all the available data as ASCII files.\newlinePress <Save> to save the new catalog \newlineafter you have loaded all ASCII files!');
        set(te,'FontSize',ZG.fontsz.m);

        te1 = text(0.40,0.80,'Data ') ;
        set(te1,'FontSize',ZG.fontsz.m,'Color','r','FontWeight','bold')

        te2 = text(0.25,0.58,'Overlay Symbols') ;
        set(te2,'FontSize',ZG.fontsz.m,'Color','r','FontWeight','bold');

        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.01 .65 .30 .08 ],...
            'Units','normalized',...
            'callback',@loaddb_callback,...
            'String','EQ Datafile');

        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.35 .65 .35 .08 ],...
            'Units','normalized',...
            'callback',@loaddb_focal_callback,...
            'String','EQ Datafile (+focal)');

        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.80 .65 .15 .08 ],...
            'Units','normalized',...
            'callback',@clearevents_callback,...
            'String','Clear ');

        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.25 .45 .45 .08 ],...
            'Units','normalized',...
            'callback',@loadmainshocks_callback,...
            'String','Mainshocks ');
        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.75 .45 .15 .08 ],...
            'Units','normalized',...
            'callback',@clearmainshocks_callback,...
            'String','Clear ');

        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.25 .35 .45 .08 ],...
            'Units','normalized',...
            'callback',@loadfaults_callback,...
            'String','Faults ');
        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.75 .35 .15 .08 ],...
            'Units','normalized',...
            'callback',@clearfaults_callback,...
            'String','Clear ');

        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.25 .25 .45 .08 ],...
            'Units','normalized',...
            'callback',@load_mainrupt_callback,...
            'String','Mainrupture');
        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.75 .25 .15 .08 ],...
            'Units','normalized',...
            'callback',@clear_mainrupt_callback,...
            'String','Clear ');

        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.25 .15 .45 .08 ],...
            'Units','normalized',...
            'callback',@loadcoast_callback,...
            'String','Coastline/Borders');
        uicontrol('BackGroundColor',[0.8 0.8 0.8]','Style','Pushbutton',...
            'Position',[.75 .15 .15 .08 ],...
            'Units','normalized',...
            'callback',@clearcoast_callback,...
            'String','Clear ');

        uicontrol('Style','Pushbutton',...
            'Position',[.75 .03 .15 .08 ],...
            'Units','normalized', 'Callback', @close_callback,'String','Cancel');

        uicontrol('Style','Pushbutton',...
            'Position',[.05 .03 .25 .08 ],...
            'Units','normalized',...
            'callback',@save_callback,...
            'String','Save as *.mat');

        uicontrol('Style','Pushbutton',...
            'Position',[.45 .03 .15 .08 ],...
            'Units','normalized',...
            'callback',@info_callback,...
            'String','Info');

        watchoff

    end   %if figure exist
    figure(loda)
    set(gca,'box','off',...
        'SortMethod','childorder','TickDir','out','FontWeight','bold',...
        'visible','off','FontSize',ZG.fontsz.m,'Linewidth',1.2)

    set(loda,'Visible','on');

    function loaddb_callback(mysrc,myevt)
        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        dataimpo('noini',1);
    end

    function loaddb_focal_callback(mysrc,myevt)
        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        loadasci('focal','of');
    end

    function clearevents_callback(mysrc,myevt)
        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        a = [];
        zmap_update_displays();
    end

    function loadmainshocks_callback(mysrc,myevt)
        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        loadasci('mainshock','of');
    end

    function clearmainshocks_callback(mysrc,myevt)
        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        main  = [];
        zmap_update_displays();
    end

    function loadfaults_callback(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        loadasci('faults','of');
    end

    function clearfaults_callback(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        faults  = [];
        zmap_update_displays();
    end

    function load_mainrupt_callback(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        loadasci('mainfaults','of');
    end

    function clear_mainrupt_callback(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        mainfault  = [];
        zmap_update_displays();
    end

    function loadcoast_callback(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        loadasci('coastline','of');
    end

    function clearcoast_callback(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        coastline  = [];
        zmap_update_displays();
    end

    function close_callback(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        close;
    end

    function save_callback(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        msg.infodisp('  ','Save Data');

        [file1,path1] = uiputfile(fullfile(ZmapGlobal.Data.Directories.data, '*.mat'), 'Filename?');
        save(fullfile(path1, file1),'a','faults','mainfault','coastline','main','infstri');
        close(loda);
        zmap_update_displays();

    end

    function info_callback(mysrc,myevt)

        callback_tracker(mysrc,myevt,mfilename('fullpath'));
        zmaphelp(ttlStr,hlpStr1,hlpStr2,hlpStr3);
    end

end


function errstring = consistent(ds, type)

% CONSISTENT   Check ReBEL data structures for consistentency.
%
%   errstring = consistent(ds, type) checks a data structure DS of supposed TYPE for consistency.
%
%     See also
%     GSSM, GENINFDS
%
%   Copyright (c) Oregon Health & Science University (2006)
%
%   This file is part of the ReBEL Toolkit. The ReBEL Toolkit is available free for
%   academic use only (see included license file) and can be obtained from
%   http://choosh.csee.ogi.edu/rebel/.  Businesses wishing to obtain a copy of the
%   software should contact rebel@csee.ogi.edu for commercial licensing information.
%
%   See LICENSE (which should be part of the main toolkit distribution) for more
%   detail.

%===============================================================================================

if (nargin~=2)
  error('Not enough input arguments!');
end

if ~ischar(type)
  error('Type argument should be a string.');
end

% Assume that all is OK as default
errhead = ['  [ consistent(' inputname(1) ',''' type ''') ]   '];

errstring = '';

if ~isstruct(ds)
  errstring = [errhead inputname(1) ' is not a data structure.'];
  return
end

switch (type)

%===============================================================================================================================
%== General State Space Model Data Structure (GSSM)
%===============================================================================================================================
case 'gssm'

  %-- Check existence of required data structure fields
  mf = checkstructfields(ds,'type','tag','statedim','obsdim','paramdim','U1dim','U2dim','Vdim','Ndim','pNoise','oNoise','params','ffun','hfun','setparams');
  if ~isempty(mf), errstring = [errhead ' Data structure does not contain the following fields : ' mf]; return; end

  %-- Check type field
  if ~ischar(ds.type) | ~stringmatch(ds.type,'gssm')
      errstring = [errhead  ' Data structure is not of type ''' type ''' or the type field is not a string'];
      return;
  end

%===============================================================================================================================
%== Inference Data Structure (InferenceDS)
%===============================================================================================================================
case 'InferenceDS'

  %-- Check existence of required data structure fields
  mf = checkstructfields(ds,'type','inftype','statedim','obsdim','U1dim','U2dim','Vdim','Ndim', ...
                            'ffun','hfun','innovation','stateAngleCompIdxVec','obsAngleCompIdxVec');
  if ~isempty(mf), errstring = [errhead ' Data structure does not contain the following fields : ' mf]; return; end

  %-- Check type field
  if (~ischar(ds.type) | ~stringmatch(ds.type,'InferenceDS'))
    errstring = [errhead  ' Data structure is not of type ''' type ''' or the type field is not a string.'];
    return;
  end

  %-- Check inference type field
  if ~stringmatch(ds.inftype,{'state','parameter','joint'})
    errstring = [errhead  ' Inference type ''' type ''' unknown.'];
    return;
  end

%===============================================================================================================================
%== Noise Source Data Structure (NoiseDS)
%===============================================================================================================================
case 'NoiseDS'

  %-- Check existence of required data structure fields
  mf = checkstructfields(ds,'type','ns_type','tag','dim','sample','likelihood');
  if ~isempty(mf), errstring = [errhead ' Data structure does not contain the following fields : ' mf]; return; end

  %-- Check type field
  if (~ischar(ds.type) | ~stringmatch(ds.type,'NoiseDS'))
    errstring = [errhead  ' Data structure is not of type ''' type ''' or the type field is not a string.'];
    return;
  end

%===============================================================================================================================
otherwise
  errstring = [errhead 'Data structure type ' type ' not supported.'];
end

return


function [CODE, Declarations, NewVars] = ParseTmpFile(FILENAME,Result_Name)

%This function is designed to read the output of ccode.m back into matlab
%and parse it into a more useful format. It assumes a very specific format
%for the file, and assumes that the last line is a result, and
%automatically assigns it Result_Num.

%Figure out what to call things
persistent Result_Var_Num
persistent Local_Var_Num

%Initialize the persistent variables
if isempty(Result_Var_Num), Result_Var_Num=0; end
if isempty(Local_Var_Num), Local_Var_Num=2; end

%What should local variables be called?
BaseName = 'tmp';

%Check what the result name should be
if nargin == 1
    Result_Name = ['Result_' num2str(Result_Var_Num)];
    Result_Var_Num = Result_Var_Num + 1;  %Increment the number
end

% First, open the file and count the number of lines
fid = fopen(FILENAME);
N_Lines = 0;
while 1
    tline = fgetl(fid);
    if ~ischar(tline), break, end
    N_Lines = N_Lines + 1;
%     disp(tline)
end
% disp(N_Lines)
fclose(fid);

%Next, initialize the outputs;
CODE = cell(N_Lines,1);
Variables = cell(N_Lines,1);
Declarations = cell(2,1);
Declarations{1} = 'double  ';  %initialize the declarations for the tmp variables
Declarations{2} = 'double  ';  %initialize the declaration for the results

%Now, do the useful things:
fid = fopen(FILENAME);
for i=1:N_Lines
    tline = fgetl(fid);
    %Figure out what to name things:
    if i==N_Lines
        %This is the last line of the file -> it stores the result
        VarName = Result_Name;
        index = strfind(tline,'=');  %Search for the equal sign
        CODE{i} = [VarName ' = ' tline((index+1):end)];
        Declarations{2} = [Declarations{2} VarName];   %declare the result
    else
        %This is a regular line, so get the name from the file
        index = strfind(tline,'=');  %Search for the equal sign
        VarName = tline(1:(index-1)); %Get the first part of the string
        VarName = VarName(~isspace(VarName));  %Remove the spaces
        CODE{i} = tline;
        if i==1
            %Then first line, don't need the comma
            Declarations{1} = [Declarations{1}  VarName ];
        else
        Declarations{1} = [Declarations{1} ', ' VarName];   %Add it to the tmp pile
        end
    end

    Variables{i} = VarName;
end

Declarations{1} = [Declarations{1} ';'];
Declarations{2} = [Declarations{2} ';'];

fclose(fid);  %Close the file

%% Rename local variables
% This function will be called multiple times, and the output stored in a
% single file for all function calls. Thus, if the same variable names are
% used (such as t2,t3,t4...) then they will cause a compile error. To fix
% this, the function uses a persistent variable to continue increasing the
% local variable ID numbers.

NewVars = Variables;   %Store the new variable names here
for i=1:(length(Variables)-1)
    NewVars{i} = [BaseName num2str(Local_Var_Num)];  %Create the new name
    Local_Var_Num = Local_Var_Num + 1;   %Increment the counter
end

%Now do a find and replace operation on all of the functions:
for i=1:length(CODE)
    for j = 1:length(NewVars)
        CODE{i} = strrep(CODE{i},Variables{j},NewVars{j});
    end
end

for i = 1:length(Declarations)
    for j = 1:length(NewVars)
        Declarations{i} = strrep(Declarations{i},Variables{j},NewVars{j});
    end
end

end


%kkclipout 'Clip Data Values Outside of the Specified Range'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros kclipout.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'Input file'
% OutputFile: o ' Output ', required: 'output file'
%
% Example: o = kkclipout(i, {'i','';'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% kclipout - Clip Data Values Outside of the Specified Range
%
%  DESCRIPTION
% The "Clip Outside" operator (kclipout) performs clipping on the Input
% data object (i) outside of the range defined by the specified Lower and Upper
% Cutoff Values (lc, uc).
% All data values in the Input object that are LESS THAN the Lower Cutoff
% are set to the Lower Cutoff in the resulting Output object, unless the
% alternate "Lower Cutoff Output Value" (fval) is explicitly provided.  If
% this value is provided, clipped data are set to that value instead of the
% Lower Cutoff.  Likewise, data values GREATER THAN the Upper Cutoff are set
% to the Upper Cutoff, unless the alternate "Upper Cutoff Output Value" is
% explicitly provided.  All other data remain the same.
%
% The following histogram defines the clipping operation.
% .KS
%
% \f(CW
%                                 |<-A->|<-B->|<-C->|
%                                 |     | :   | .   |
%                                 |    .:.:.  .:::  |
%                                 |:. .::::::.::::: |
%                                 |::::::::::::::::.|
%                                 ------|-----|------
%                                      lc     uc
%
%         A:  if value <  lc                  output = lc or fval
%         B:  if value >= lc AND value <= uc  output = input
% 	C:  if value >  uc                  output = uc or tval
% "
%
% .KE
% P "Data Type" 5
% .cI $DATAMANIP/repos/shared/man/sections/value_type_1input
%
%  "Map Data" 5
% .cI $DATAMANIP/repos/shared/man/sections/map_1input
%
%  "Validity Mask" 5
% .cI $DATAMANIP/repos/shared/man/sections/mask_1input
%
%  "Explicit Location and Time Data" 5
% .cI $DATAMANIP/repos/shared/man/sections/loc_and_time_1input
%
%  "Failure Modes"
% .cI $DATAMANIP/repos/shared/man/sections/fail_1input
%
% Executing "Clip Outside" runs the program \fIkclip\fP with the -thresh
% option set to FALSE (-thresh 0).
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
% DATAMANIP::kclipabove, DATAMANIP::kclipbelow, DATAMANIP::kclipin,
% DATAMANIP::kmegaclip, DATAMANIP::kclip
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kkclipout(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,..] = kkclipout(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'o', '__output'};
maxval={0,0};
minval={0,0};
istoggle=[0,0];
was_set=istoggle * 0;
paramtype={'InputFile','OutputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; 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(1,1);
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
[varargout{:}]=callKhoros([w 'kclip"  -thresh'],Inputs,narglist);


function SaveAsNIfTI(data, target, output)

% function SaveAsNIfTI(data, nifti)
%
% Input:
%
% data: the data array to be saved to disk
%
% target: the NIfTI object specifying the target volume specification
%
% output: the filename for the output NIfTI file
%

% following the example in
% http://niftilib.sourceforge.net/mat_api_html/README.txt
%
% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
%

dat = file_array;
dat.fname = output;
dat.dim = target.dim;
dat.dtype = 'FLOAT64-LE';
dat.offset = ceil(348/8)*8;

N = nifti;
N.dat = dat;
N.mat = target.mat;
N.mat_intent = target.mat_intent;
N.mat0 = target.mat0;
N.mat0_intent = target.mat0_intent;

create(N);

N.dat(:,:,:,:) = data;


function msfun_simiam_ui(block)

% Copyright (C) 2013, Georgia Tech Research Corporation
% see the LICENSE file included with this software

%%
%% The setup method is used to set up the basic attributes of the
%% S-function such as ports, parameters, etc. Do not add any other
%% calls to the main body of the function.
%%
app = [];
setup(block);

 %endfunction

%% Function: setup ===================================================
%% Abstract:
%%   Set up the basic characteristics of the S-function block such as:
%%   - Input ports
%%   - Output ports
%%   - Dialog parameters
%%   - Options
%%
%%   Required         : Yes
%%   C-Mex counterpart: mdlInitializeSizes
%%
function setup(block)

% Register number of ports
block.NumInputPorts  = 0;
block.NumOutputPorts = 0;

% Set up the states
block.NumContStates = 0;
% block.NumDworks = 0;

% Register parameters
block.NumDialogPrms     = 0;

% Register sample times
%  [0 offset]            : Continuous sample time
%  [positive_num offset] : Discrete sample time
%
%  [-1, 0]               : Inherited sample time
%  [-2, 0]               : Variable sample time
block.SampleTimes = [0.033 0];

% Specify the block simStateCompliance. The allowed values are:
%    'UnknownSimState', < The default setting; warn and assume DefaultSimState
%    'DefaultSimState', < Same sim state as a built-in block
%    'HasNoSimState',   < No sim state
%    'CustomSimState',  < Has GetSimState and SetSimState methods
%    'DisallowSimState' < Error out when saving or restoring the model sim state
block.SimStateCompliance = 'DefaultSimState';

%% -----------------------------------------------------------------
%% The MATLAB S-function uses an internal registry for all
%% block methods. You should register all relevant methods
%% (optional and required) as illustrated below. You may choose
%% any suitable name for the methods and implement these methods
%% as local functions within the same file. See comments
%% provided for each function for more information.
%% -----------------------------------------------------------------

block.RegBlockMethod('InitializeConditions', @InitializeConditions);
block.RegBlockMethod('Start', @Start);
block.RegBlockMethod('Outputs', @Outputs);     % Required
block.RegBlockMethod('Update', @Update);
block.RegBlockMethod('Derivatives', @Derivatives);
block.RegBlockMethod('Terminate', @Terminate); % Required

end %end setup

%%
%% InitializeConditions:
%%   Functionality    : Called at the start of simulation and if it is
%%                      present in an enabled subsystem configured to reset
%%                      states, it will be called when the enabled subsystem
%%                      restarts execution to reset the states.
%%   Required         : No
%%   C-MEX counterpart: mdlInitializeConditions
%%
function InitializeConditions(block)

end %end InitializeConditions

%%
%% Start:
%%   Functionality    : Called once at start of model execution. If you
%%                      have states that should be initialized once, this
%%                      is the place to do it.
%%   Required         : No
%%   C-MEX counterpart: mdlStart
%%
function Start(block)

root_path = fullfile(fileparts(mfilename('fullpath')), '../');
addpath(genpath(root_path));
root_path

app = simiam.ui.AppWindow(root_path, true);
app.load_ui();

% store info in custom data;
customData = containers.Map('UniformValues', false);
simulator = app.simulator_;
customData('simulatorHandle') = simulator;
set(block.BlockHandle, 'UserData', customData, 'UserDataPersistent', 'off');

end %endfunction

%%
%% Outputs:
%%   Functionality    : Called to generate block outputs in
%%                      simulation step
%%   Required         : Yes
%%   C-MEX counterpart: mdlOutputs
%%
function Outputs(block)

end %end Outputs

%%
%% Update:
%%   Functionality    : Called to update discrete states
%%                      during simulation step
%%   Required         : No
%%   C-MEX counterpart: mdlUpdate
%%
function Update(block)

customData = get(block.BlockHandle, 'UserData');
simulator = customData('simulatorHandle');

if(~app.is_state_crashed_)
    simulator.step([],[]);
else
    error('Collision detected!');
end

end %end Update

%%
%% Derivatives:
%%   Functionality    : Called to update derivatives of
%%                      continuous states during simulation step
%%   Required         : No
%%   C-MEX counterpart: mdlDerivatives
%%
function Derivatives(block)

end %end Derivatives

%%
%% Terminate:
%%   Functionality    : Called at the end of simulation for cleanup
%%   Required         : Yes
%%   C-MEX counterpart: mdlTerminate
%%
function Terminate(block)

end %end Terminate

end


% loadeep_avg() - Load EEProbe average data (*.avr).
%
% Usage:
%   >> [EEG] = loadeep_avg(file);
%
% Inputs:
%            filename    - name of EEProbe averaged file, including extension (*.avr)
%
% Outputs:
%   [EEG]                - data structure holding EEG information and other
%                          relevant information.
%
% Author: Maarten-Jan Hoeve, ANT Software, Enschede, The Netherlands, 8 October 2003
%
% See also: eeglab(), pop_loadeep_avg()
%

%123456789012345678901234567890123456789012345678901234567890123456789012

% Copyright (C) 2003 Maarten-Jan Hoeve, m.hoeve@ieee.org
%
% This program 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 2 of the License, or
% (at your option) any later version.
%
% This program 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 this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

% $Log: loadeep_avg.m,v $
% Revision 1.3  2005/07/21 10:12:51  mvelde
% updated information
%
% Revision 1.2  2005/06/08 08:16:37  mvelde
% converted files to unix format
%
% Revision 1.1  2004/11/26 13:22:22  jwiskerke
% Added eeglab to cvs.
%
% Revision 1.3  2003/10/24 13:34:40  Maarten-Jan Hoeve
% Added GNU Licence and updated revision history
%
% Revision 1.1.1.2  2003/10/17 09:55:20  mvelde
% updated: consistent copyrights, arguments/data labels, fixed some typos
%
% Advanced Neuro Technology (ANT) BV, The Netherlands, www.ant-neuro.com / info@ant-neuro.com
%

function r=loadeep_avg(file)

if nargin < 1
	help loadeep;
	return;
end;

% defaults
if ~any(file=='.'), file=[file '.avr']; end
[datdir,name,ext]=fileparts(file);
disp(['Loading file ' file ' ...'])

eeg=read_eep_avr(file);

r.filename=file;
r.totsamples=eeg.npnt;
r.nchannels=eeg.nchan;
r.rate=eeg.rate;

% Create struct for holding channel labels
for i=1:r.nchannels
    chanlocs(i).labels=char(eeg.label(i));
    chanlocs(i).theta=0;
    chanlocs(i).radius=0;
    chanlocs(i).X=0;
    chanlocs(i).Y=0;
    chanlocs(i).Z=0;
    chanlocs(i).sph_theta=0;
    chanlocs(i).sph_phi=0;
    chanlocs(i).sph_radius=0;
end
r.chanlocs=chanlocs;

r.nsmpl=eeg.npnt;
r.time=eeg.time;
r.dat=eeg.data;
r.nsweeps=eeg.nsweeps;     %number of trials averaged
r.xmin=eeg.xmin;
r.xmax=eeg.xmax;
r.variance=eeg.variance;   % variance (nchan x npnt)
r.condlab=eeg.condlab;     % string with condition label
r.condcol=eeg.condcol;     % string with color code for condition
r.trialc=eeg.trialc;       % total number of trial in original data
r.rejtrialc=eeg.rejtrialc; % number of rejected trials


function [] = tapas_display_table(summaries, figname)
%% Display a figure with the summaries.
%
% Input
%       summaries       -- Table with the summaries.
%       figname         -- Optional. String with the name for the figure.
%
% Output
%

% aponteeduardo@gmail.com
% copyright (C) 2019
%

n = 1;

n = n + 1;
if nargin < n
    figname = 'Table';
end

figure('name', figname);
uitable('Data', summaries{:, :}, ...
    'ColumnName', summaries.Properties.VariableNames,...
    'RowName', summaries.Properties.RowNames, ...
    'Units', 'Normalized', ...
    'Position',[0, 0, 1, 1]);

end


% Prepare testing data to quicken testing
init;

model = exp_params.model;

% Get test image path
im_dir = [VOC07PATH 'JPEGImages/'];
fid = fopen([VOC07PATH 'ImageSets/Main/test.txt']);
test_imgs = textscan(fid, '%s');
test_imgs = test_imgs{1};
num_test = size(test_imgs, 1);

% Network to use
caffe_params.model = exp_params.model;
caffe_params.model_file = exp_params.model_file;
caffe_params.def_file = exp_params.def_file;
caffe_params.device = exp_params.device;

% Load bounding boxes
load('data/SelectiveSearchVOC2007test.mat');
bbox = boxes(:);

% Initialization
max_img = 10;             % maximum number of images in the .mat file
tests = cell(1);
counter = 1;
file_counter = 1;

for ii=1:num_test
    disp(['Image: ' num2str(ii) '/' num2str(num_test)]);
    im_path = [im_dir test_imgs{ii} '.jpg'];
    im = imread(im_path);

    %boxes = selective_search(im, 'single');
    index = find(strcmp(images, test_imgs{ii}));
    boxes = bbox{index};
    num_boxes = size(boxes, 1);
    disp(['Number of boxes ' num2str(num_boxes)]);

    tic
    test = cell(num_boxes, 1);
    for jj=1:num_boxes
        box = boxes(jj, :);
        region = im(box(1):box(3), box(2):box(4), :);
        rep = extract_caffe_feature(region, caffe_params);

        test{jj} = struct;
        test{jj}.feature = mean(rep, 2);
        test{jj}.bbox = box;
    end
    tests{counter} = test;
    counter = counter + 1;
    toc

    if counter > max_img
        disp(['Save to file']);
        save(['data/' model '/test_' num2str(file_counter) '.mat'], 'tests', '-v7.3');
        counter = 1;
        file_counter = file_counter + 1;
        clear tests; tests = cell(max_img, 1);
    end
end

save(['data/' model '/test_' num2str(file_counter) '.mat'], 'tests', '-v7.3');


function print_png(outfile)
%PRINT_PNG stores a figure as png file
%
%   Usage: print_png(outfile)
%
%   Input parameters:
%       outfile     - file name to store the figure
%
%   See also: plot_sound_field, print_png

%*****************************************************************************
% The MIT License (MIT)                                                      *
%                                                                            *
% Copyright (c) 2010-2019 SFS Toolbox Developers                             *
%                                                                            *
% Permission is hereby granted,  free of charge,  to any person  obtaining a *
% copy of this software and associated documentation files (the "Software"), *
% to deal in the Software without  restriction, including without limitation *
% the rights  to use, copy, modify, merge,  publish, distribute, sublicense, *
% and/or  sell copies of  the Software,  and to permit  persons to whom  the *
% Software is furnished to do so, subject to the following conditions:       *
%                                                                            *
% The above copyright notice and this permission notice shall be included in *
% all copies or substantial portions of the Software.                        *
%                                                                            *
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
% IMPLIED, INCLUDING BUT  NOT LIMITED TO THE  WARRANTIES OF MERCHANTABILITY, *
% FITNESS  FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL *
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
% LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT  OR OTHERWISE, ARISING *
% FROM,  OUT OF  OR IN  CONNECTION  WITH THE  SOFTWARE OR  THE USE  OR OTHER *
% DEALINGS IN THE SOFTWARE.                                                  *
%                                                                            *
% The SFS Toolbox  allows to simulate and  investigate sound field synthesis *
% methods like wave field synthesis or higher order ambisonics.              *
%                                                                            *
% https://sfs.readthedocs.io                            sfstoolbox@gmail.com *
%*****************************************************************************

%% ===== Checking of input parameter =====================================
nargmin = 1;
nargmax = 1;
narginchk(nargmin,nargmax);

%% ===== Main ============================================================
% Font type
set_font_type('Arial');
pause(0.2);
print('-r150','-opengl','-dpng',outfile);
pause(0.2);
close;


% Author: Guosheng Lin (guosheng.lin@gmail.com)
% example code for multi-scale predictions, fusion and accuracy evaluation

function demo_predict_mscale_nyud()

rng('shuffle');

addpath('./my_utils');
dir_matConvNet='../libs/matconvnet/matlab';
run(fullfile(dir_matConvNet, 'vl_setupnn.m'));

run_config=[];
ds_config=[];

run_config.use_gpu=true;
% run_config.use_gpu=false;
run_config.gpu_idx=1;

%-------------------------------------------------------------------------------------------------------------------------
% settings for using trained model:

ds_name_subfix='nyud';

% result dir:
result_name=['result_' datestr(now, 'YYYYmmDDHHMMSS') '_predict_custom_data'];
result_dir=fullfile('../cache_data', ['test_examples_' ds_name_subfix], result_name);

% using a trained model:
run_config.trained_model_path='../model_trained/refinenet_res101_nyud.mat'; % resnet101 based refinenet
% run_config.trained_model_path='../model_trained/refinenet_res152_nyud.mat'; % resnet152 based refinenet

% provide class_info for the trained model:
ds_config.class_info=gen_class_info_nyud();

% control the size of input images to avoid excessively small or large images
run_config.input_img_short_edge_min=450;
run_config.input_img_short_edge_max=800;
%-------------------------------------------------------------------------------------------------------------------------

% specify the folder that contains testing images:
img_data_dir='../datasets/example_imgs_nyud';

% providing ground-truth mask folder for evaluation, or set to empty if not available
% if the folder of ground-truth masks are provided (an example is shown below),
% this code will perform evaluation after multi-scale prediction and fusion.
gt_mask_dir=[];

%-------------------------------------------------------------------------------------------------------------------------
% settings for accuracy evaluation after multi-scale prediction and fusion:
% the following example specifies images for testing and the ground-truth masks for evaluation:

% Notes: for the evaluation purpose, the image folder should only contain testing images, excluding any training images:
% Notes: the ground-truth masks should follow the class label definition in the variable specified above: 'ds_config.class_info'

% uncomment the following lines to enable accuracy evaluation, should replace by your folders:

% img_data_dir='../datasets/nyudv2/images_testonly';
% gt_mask_dir='../datasets/nyudv2/gt_testonly';
%-------------------------------------------------------------------------------------------------------------------------

%-------------------------------------------------------------------------------------------------------------------------
% settings for multi-scale prediction, you can consider 3 scales or 5 scales:

prediction_scales=[0.4 0.6 0.8 1 1.2]; % 5 scales
% prediction_scales=[0.6 0.8 1]; % 3 scales
% prediction_scales=[0.8]; % or only use 1 scale
%-------------------------------------------------------------------------------------------------------------------------

ds_config.img_data_dir=img_data_dir;
result_evaluate_param=[];
result_evaluate_param.gt_mask_dir=gt_mask_dir;
ds_config.result_evaluate_param=result_evaluate_param;

run_config.prediction_scales=prediction_scales;
run_config.model_name=result_name;
run_config.root_cache_dir=result_dir;

do_predict_and_evaluate(run_config, ds_config);

end

function do_predict_and_evaluate(run_config, ds_config)

run_config.gen_net_opts_fn=@gen_net_opts_model_type1;

run_config.run_evaonly=true;
ds_config.use_custom_data=true;
ds_config.use_dummy_gt=true;
run_config.use_dummy_gt=ds_config.use_dummy_gt;

ds_config.ds_name='tmp_data';
mkdir_notexist(run_config.root_cache_dir);

diary_dir=run_config.root_cache_dir;
mkdir_notexist(diary_dir);
diary(fullfile(diary_dir, 'output.txt'));
diary on

run_dir_name=fileparts(mfilename('fullpath'));
[~, run_dir_name]=fileparts(run_dir_name);
run_config.run_dir_name=run_dir_name;
run_config.run_file_name=mfilename();

ds_info=gen_dataset_info(ds_config);
my_diary_flush();

if run_config.use_gpu
	gpu_num=gpuDeviceCount;
	if gpu_num>=1
		gpuDevice(run_config.gpu_idx);
    else
        error('no gpu found!');
	end
end

train_opts=run_config.gen_net_opts_fn(run_config, ds_info.class_info);

imdb=my_gen_imdb(train_opts, ds_info);
data_norm_info=[];
data_norm_info.image_mean=128;
imdb.ref.data_norm_info=data_norm_info;

[net_config, net_exp_info]=prepare_running_model(train_opts);

prediction_scales=run_config.prediction_scales;
scale_num=length(prediction_scales);
predict_result_dirs=cell(scale_num, 1);

for s_idx=1:scale_num

	one_scale=prediction_scales(s_idx);
	one_result_dir=fullfile(run_config.root_cache_dir, sprintf('predict_result_%d', s_idx));
	predict_result_dirs{s_idx}=one_result_dir;

	fprintf('\n\n--------------------------------------------------\n\n');
	fprintf('conduct prediction using image scale: %1.2f  (current scale / total scales: %d/%d) \n', one_scale, s_idx, scale_num);

	train_opts.root_cache_dir=one_result_dir;
	train_opts.input_img_scale=one_scale;
	train_opts.eva_param=update_eva_param_mscale(train_opts.eva_param, train_opts);

	my_net_tool(train_opts, imdb, net_config, net_exp_info);

	fprintf('\n\n--------------------------------------------------\n\n');
	disp('results are saved in:');
	disp(train_opts.root_cache_dir);

	my_diary_flush();

end

if length(predict_result_dirs)>1

    fprintf('\n\n--------------------------------------------------\n\n');
    disp('fusing multiscale predictions');

    fuse_param=[];
    fuse_param.predict_result_dirs=predict_result_dirs;
    fuse_param.fuse_result_dir=fullfile(run_config.root_cache_dir, 'predict_result_final_fused');
    fuse_param.cache_fused_score_map=true;
    fuse_multiscale_results(fuse_param, ds_config.class_info);

    fprintf('\n\n--------------------------------------------------\n\n');
    disp('final fused results are saved in:');
    disp(fuse_param.fuse_result_dir);

    my_diary_flush();

    final_prediction_dir=fuse_param.fuse_result_dir;

else

    final_prediction_dir=predict_result_dirs{1};
end

% evaluate the final fused result, if ground-truth is provided
result_evaluate_param=ds_config.result_evaluate_param;
if ~isempty(result_evaluate_param) && ~isempty(result_evaluate_param.gt_mask_dir)
	result_evaluate_param.predict_result_dir=fullfile(final_prediction_dir, 'predict_result_mask');
	fprintf('\n\n--------------------------------------------------\n\n');
	disp('perform evaluation of the predicted masks');
	result_info=evaluate_predict_results(result_evaluate_param, ds_config.class_info);
    disp_evaluate_result(result_info, ds_config.class_info);

    eva_result_cached_file=fullfile(final_prediction_dir, 'eva_result_info.mat');
    fprintf('saving evaluation result to: %s\n', eva_result_cached_file);
    save(eva_result_cached_file, 'result_info');
end

my_diary_flush();
diary off

end


function y=chk_param(val,name,varargin)

% y=chk_param(val,name,varargin)
%
% Check that 'val' satisfies all the requirements given in 'varargin'.
% If any of the requirements are not met, the parameter's 'name' is printed
% along with information on which requirement failed.
%
% Example usage:
%   error(chk_param(speed,'speed','>',0,'<=',100));
% The above will throw an error if speed is <=0 or >100. Otherwise,
% nothing will be printed.
%
% Supported parameter checks are:
%   'string'
%   TBD

% Copyright 2012 Evrytania LLC (http://www.evrytania.com)
%
% Written by James Peroulas <james@evrytania.com>
%
% This program 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.
%
% This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.

global CHK_PARAM_BYPASS
if (CHK_PARAM_BYPASS==1)
  y=[];
  return
end

failed=0;
t=1;
while (t<=length(varargin))
  switch lower(varargin{t})
    case 'scalar'
      if (~isscalar(val)) failed=1; break; end
    case 'vector'
      if (~isvector(val)) failed=1; break; end
    case 'horizontal'
      if (size(val,1)~=1) failed=1; break; end
    case 'vertical'
      if (size(val,2)~=1) failed=1; break; end
    case 'string'
      if (~ischar(val)) failed=1; break; end
    case 'numeric'
      if (~isnumeric(val)) failed=1; break; end
    case 'struct'
      if (~isstruct(val)) failed=1; break; end
    case 'real'
      if (~isreal(val)) failed=1; break; end
    case '>'
      t=t+1;
      if (t>length(varargin)) error('> requires an argument'); end
      if (~all(val(:)>varargin{t})) failed=1; break; end
    case '<'
      t=t+1;
      if (t>length(varargin)) error('< requires an argument'); end
      if (~all(val(:)<varargin{t})) failed=1; break; end
    case '<='
      t=t+1;
      if (t>length(varargin)) error('<= requires an argument'); end
      if (~all(val(:)<=varargin{t})) failed=1; break; end
    case '>='
      t=t+1;
      if (t>length(varargin)) error('>= requires an argument'); end
      if (~all(val(:)>=varargin{t})) failed=1; break; end
    case 'rows>'
      t=t+1;
      if (t>length(varargin)) error('rows> requires an argument'); end
      if (size(val,1)<=varargin{t}) failed=1; break; end
    case 'rows<'
      t=t+1;
      if (t>length(varargin)) error('rows< requires an argument'); end
      if (size(val,1)>=varargin{t}) failed=1; break; end
    case 'rows<='
      t=t+1;
      if (t>length(varargin)) error('rows<= requires an argument'); end
      if (size(val,1)>varargin{t}) failed=1; break; end
    case 'rows>='
      t=t+1;
      if (t>length(varargin)) error('rows>= requires an argument'); end
      if (size(val,1)<varargin{t}) failed=1; break; end
    case 'rows=='
      t=t+1;
      if (t>length(varargin)) error('rows>= requires an argument'); end
      if (size(val,1)~=varargin{t}) failed=1; break; end
    case 'cols>'
      t=t+1;
      if (t>length(varargin)) error('cols> requires an argument'); end
      if (size(val,2)<=varargin{t}) failed=1; break; end
    case 'cols<'
      t=t+1;
      if (t>length(varargin)) error('cols< requires an argument'); end
      if (size(val,2)>=varargin{t}) failed=1; break; end
    case 'cols<='
      t=t+1;
      if (t>length(varargin)) error('cols<= requires an argument'); end
      if (size(val,2)>varargin{t}) failed=1; break; end
    case 'cols>='
      t=t+1;
      if (t>length(varargin)) error('cols>= requires an argument'); end
      if (size(val,2)<varargin{t}) failed=1; break; end
    case 'cols=='
      t=t+1;
      if (t>length(varargin)) error('cols== requires an argument'); end
      if (size(val,2)~=varargin{t}) failed=1; break; end
    case 'length>'
      t=t+1;
      if (t>length(varargin)) error('length> requires an argument'); end
      if (length(val)<=varargin{t}) failed=1; break; end
    case 'length<'
      t=t+1;
      if (t>length(varargin)) error('length< requires an argument'); end
      if (length(val)>=varargin{t}) failed=1; break; end
    case 'length<='
      t=t+1;
      if (t>length(varargin)) error('length<= requires an argument'); end
      if (length(val)>varargin{t}) failed=1; break; end
    case 'length>='
      t=t+1;
      if (t>length(varargin)) error('length>= requires an argument'); end
      if (length(val)<varargin{t}) failed=1; break; end
    case 'length=='
      t=t+1;
      if (t>length(varargin)) error('length== requires an argument'); end
      if (length(val)~=varargin{t}) failed=1; break; end
    case 'integer'
      if (any(val(:)~=floor(val(:)))) failed=1; break; end
    otherwise
      if (ischar(varargin{t}))
        error(sprintf('Unrecognized requirement passed to chk_param: %s',varargin{t}));
      else
        error(sprintf('Unrecognized requirement passed to chk_param index %i',t));
      end
  end
  t=t+1;
end

if (failed)
  y=['parameter ''' name ''' must satisfy the following requirements:'];
  for t=1:length(varargin)
    if (t~=1)
      y=[y ', '];
    else
      y=[y ' '];
    end
    if (ischar(varargin{t}))
      y=[y varargin{t}];
    else
      y=[y num2str(varargin{t})];
    end
  end
else
  y=[];
end


num_pes: 256
l1_size_cstr: 100
l2_size_cstr: 3000
noc_bw_cstr: 1000
offchip_bw_cstr: 50