function declare_properties(varargin)
% Declare properties of a function.
% declare_properties('Property',value,'Property',value, ...)
%
% declare_properties must be a top-level statement in the function (like persistent) that must come
% before arg_define. The function must use varargin in its argument list.
%
% This construct can be used to declare any key-value properties for a function which can later be
% retrieved using arg_report('properties',@myfunction). BCILAB looks for certain properties in
% plugin functions (e.g., filters, dataset_editing, machine_learning), to support improved
% integration of these functions into the GUI and the evaluation system.
%
% In:
%   Options...: list of name-value pairs.
%
%               Ordering hints applicable for filters (respected by flt_pipeline) are the following:
%                'depends': expresses that some other filter(s) *must* have been called before running
%                           the filter whose properties are being declared (this is usually due to some
%                           required meta-data that is supplied by that other filter)
%                'cannot_follow': expresses that the filter being declared cannot follow after some
%                                 other filter(s) (this is usually due to destructive
%                                 editing performed by those other filters)
%                'cannot_precede': expresses that the filter being declared cannot precede some
%                                  other filter(s)
%                'follows': expresses that the filter being declared *prefers* to follow some
%                           other filter(s) (this is usually for numeric or efficiency reasons)
%                'precedes': expresses that the filter being declared *prefers* to precede some
%                           other filter(s) (this is usually for numeric or efficiency reasons)
%
%               Optional properties respected by the evaluation system (for improved usability):
%                'independent_channels': specify that this filter does not transfer information
%                                        across channels (e.g. channel selection, FIR filter)
%                                        (allows the online system to auto-infer which data channels
%                                        are actually required by a given BCI model)
%                'independent_trials': specify that this filter does transfer information
%                                      across second-length or larger time scales (on the order of
%                                      the duration of a trial or larger); this determines whether
%                                      the filter will be called repeatedly for each partition of the
%                                      data in a cross-validation and other offline analyses
%
%               Further optional properties include:
%                'name': specify the GUI/human-readable name of this function (auto-determined if
%                        left unspecified)
%                'experimental': whether the function implementation is experimental or otherwise
%                                in "prototype" stage
%                'deprecated': whether the function is deprecated
%
% Examples:
%   function myfunction(...,varargin)
%
%   % declare a property called 'name', and assign the string 'MyFunction' to it, and another
%   % property called 'price', with some value attached
%   declare_properties('name','MyFunction','price',1999)
%
%   % in a signal processing function, declare the name of the function as it should appear in the
%   % GUI panel (default is the name of the file without the flt_ / set_ prefix)
%   declare_properties('name','MyFilter')
%
%   % in a signal processing function, declare that the filter depends on two other (previously applied)
%   % filters (here: flt_ica and set_fit_dipoles)
%   declare_properties('depends',{'flt_ica','set_flt_dipoles'});
%
%   % in a signal processing function, declare a hint that the filter typically follows some other
%   % filter in the pipeline (if that other filter was enabled; here: flt_resample)
%   declare_properties('follows','flt_resample');
%
%   % in a signal processing function, declare a hint that the filter typically precedes some other
%   % filters in the pipeline (if that other filter was enabled; here: flt_iir and flt_fir)
%   declare_properties('precedes',{'flt_iir','flt_fir'});
%
%   % in a signal processing function, declare the constraint that the filter cannot follow some other
%   % filter
%   declare_properties('cannot_follow','set_makepos');
%
%   % in a signal processing function, declare the constraint that the filter cannot follow some other
%   % filter
%   declare_properties('cannot_precede','set_makepos');
%
%   % in a signal processing function, declare that the contents of each output channel produced
%   % by the filter depend only on the contents of the corresponding input channel (i.e. there is not
%   % cross-mixing of channels (default is false)
%   declare_properties('independent_channels',true);
%
%   % in a signal processing function, declare that the contents of each output trial depend not
%   % only on data of the respective input trial, but perhaps on other trials, as well (i.e., there is
%   % cross-mixing over time at trial granularity); the effect of this is that the respective filter
%   % will be executed once per cross-validation fold
%   declare_properties('independent_trials',false);
%
% See also:
%   arg_report
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2010-11-02

% Copyright (C) Christian Kothe, SCCN, 2010, christian@sccn.ucsd.edu
%
% 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

caller_args = evalin('caller','varargin');
if length(caller_args)>1 && isequal(caller_args(end-1:end),{'__arg_report__','properties'})
    % properties are being requested via arg_report; return them as a struct
    caller = hlp_getcaller();

    % collect properties as name-value pairs
    if ~iscellstr(varargin(1:2:end))
        error('The given arguments must be name-value pairs.'); end
    nvps = reshape([{'depends',{},'cannot_follow',{},'cannot_precede',{},'follows',{},'precedes',{},'independent_channels',[], ...
        'independent_trials',[],'name',caller,'deprecated',false,'experimental',false} varargin],2,[]);
    % find the indices of the last assignment for each name and convert them to a struct
    [s,inds] = sort(nvps(1,:)); inds(strcmp(s(1:end-1),s(2:end))) = [];
    properties = cell2struct(nvps(2,inds),nvps(1,inds),2);

    if isempty(properties.independent_trials) && (strncmp(caller,'flt_',4) || strncmp(caller,'set_',4))
        properties.independent_trials = false;
        % warn about this omission: in practice, this means that this filter and all that come after it
        % in a pipeline will be recomputed for every partition of the data during (nested) cross-validation
        % (perhaps 10x or 100x as often as necessary)
        disp_once('Note: The function "%s" does not declare the property independent_trials; assuming that it is false. This may be a conservative assumption that can have massive performance cost during offline processing. Consider declaring the property explicitly in the declare_properties() clause.',caller);
    end

    if isempty(properties.independent_channels) && (strncmp(caller,'flt_',4) || strncmp(caller,'set_',4))
        properties.independent_channels = false;
        % warn about this omission: in practice, this often means that BCILAB has to assume that a given
        % model requires all channels that were present in the source data set -- even if it selects
        % only a subset somewhere in its filter pipeline (e.g., excluding peripheral measures). If such
        % channels are not available in an online stream, the model will fail to work, perhaps
        % unneccessarily.
        disp_once('Note: The function "%s" does not declare the property independent_channels; assuming that it is false. This may be a conservative assumption that can make it unnecessariy difficult to set up online processing. Consider declaring the property explicitly in the declare_properties() clause.',caller);
    end

    % report them
    arg_issuereport(properties);
end


% Compile sharedmatrix mex file.
%
% Copyright (c) 2010,2011 Joshua V Dillon
% All rights reserved. (See file header for details.)

fprintf('Compiling sharedmatrix mex files...\n');

numbits=computer;numbits=str2num(numbits(end-1:end))

if numbits==64
	% For 64-bit machines:
	mex -largeArrayDims -O -v sharedmatrix.c
else
	% For 32-bit machines:
	mex -O -v sharedmatrix.c
end

fprintf('Done.\n');

% --- Miscellaneous Comments ------------------------------------------------

% Valgrind doesn't seem to work here.
% matlab -nodesktop -nojvm -nosplash -r "x=rand(3,4);sharedmatrix('clone',12345,x);quit" -D"valgrind --error-limit=no --tool=memcheck -v --log-file=valgrind.log --leak-check=full --track-origins=yes"

% mex -largeArrayDims -O -v CFLAGS='$CFLAGS -Wall -Werror -ansi -DDEBUG -D_XOPEN_SOURCE -fPIC' sharedmatrix.c

% --- Possibly useful notes. ------------------------------------------------

% --- Note 1 ---

% If you have trouble compiling in Matlab (GLIB error) try prefixing the matlab
% command with a LD_PRELOAD, ie,
% $ LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 matlab

% --- Note 2 ---

% http://morganbye.net/blog/2011/05/matlab-ubuntu-1104
%
% MATLAB with Ubuntu 11.04
%
% Under the new Ubuntu 11.04 (Natty Narwhal), when you try and run MATLAB
% you'll get the following error
%
%     /matlab/bin/util/oscheck.sh: 605: /lib64/libc.so.6: not found
%
% To resolve this problem, go to a terminal window (Alt + F2 from anywhere) and
% type:
%
% For 64 bit:
%     sudo ln -s /lib64/x86_64-linux-gnu/libc-2.13.so /lib64/libc.so.6
%
% For 32 bit:
%     sudo ln -s /lib/i386-linux-gnu/libc-2.13.so /lib/libc.so.6
%
% This should restore the missing library that was uninstalled during the
% Ubuntu update process.


classdef MetaDataTagsClass  < matlab.mixin.Copyable

    % SNIRF-spec class properties
    properties
        tags
    end

    % Non-SNIRF class properties
    properties (Access = private)
        filename
        fileformat
    end

    methods

        % -------------------------------------------------------
        function obj = MetaDataTagsClass(varargin)
            % Set class properties not part of the SNIRF format
            obj.fileformat = 'hdf5';

            obj.tags.SubjectID = 'default';
            obj.tags.MeasurementDate = datestr(now,29);
            obj.tags.MeasurementTime = datestr(now,'hh:mm:ss');
            obj.tags.LengthUnit = 'mm';
            obj.tags.TimeUnit = 'unknown';
            obj.tags.FrequencyUnit = 'unknown';
            obj.tags.AppName  = 'snirf-homer3';
            obj.tags.SnirfDraft = '3';

            if nargin==1
                obj.filename = varargin{1};
                obj.Load();
            end
        end

        % -------------------------------------------------------
        function err = LoadHdf5(obj, fileobj, location)
            err = 0;

            % Arg 1
            if ~exist('fileobj','var') || (ischar(fileobj) && ~exist(fileobj,'file'))
                fileobj = '';
            end

            % Arg 2
            if ~exist('location', 'var') || isempty(location)
                location = '/nirs/metaDataTags';
            elseif location(1)~='/'
                location = ['/',location];
            end

            % Error checking
            if ~isempty(fileobj) && ischar(fileobj)
                obj.filename = fileobj;
            elseif isempty(fileobj)
                fileobj = obj.filename;
            end
            if isempty(fileobj)
               err = -1;
               return;
            end

            %%%%%%%%%%%% Ready to load from file

            try
                % Reset tags
                obj.tags = struct();

                % Open group
                [gid, fid] = HDF5_GroupOpen(fileobj, location);

                metaDataStruct = h5loadgroup(gid);
                tags = fieldnames(metaDataStruct); %#ok<*PROPLC>
                for ii=1:length(tags)
                    eval(sprintf('obj.tags.%s = metaDataStruct.%s;', tags{ii}, tags{ii}));
                end

                HDF5_GroupClose(fileobj, gid, fid);

                % Detect old or invalid metadatatag data
                assert(obj.IsValid());

            catch

                err = -1;

            end

        end

        % -------------------------------------------------------
        function SaveHdf5(obj, fileobj, location) %#ok<*INUSD>
            % Arg 1
            if ~exist('fileobj', 'var') || isempty(fileobj)
                error('Unable to save file. No file name given.')
            end

            % Arg 2
            if ~exist('location', 'var') || isempty(location)
                location = '/nirs/metaDataTags';
            elseif location(1)~='/'
                location = ['/',location];
            end

            if ~exist(fileobj, 'file')
                fid = H5F.create(fileobj, 'H5F_ACC_TRUNC', 'H5P_DEFAULT', 'H5P_DEFAULT');
                H5F.close(fid);
            end
            props = propnames(obj.tags);
            for ii=1:length(props)
                eval(sprintf('hdf5write_safe(fileobj, [location, ''/%s''], obj.tags.%s);', props{ii}, props{ii}));
            end
        end

        % -------------------------------------------------------
        function b = IsValid(obj)
            b = false;

            % Use latest required fields to determine if we're loading old
            % metaDataTag format version of SNIRF spec
            if ~isproperty(obj.tags, 'FrequencyUnit')
                return;
            end

            b = true;
        end

        % -------------------------------------------------------
        function B = eq(obj, obj2)
            B = false;
            props1 = propnames(obj.tags);
            props2 = propnames(obj2.tags);
            for ii=1:length(props1)
                if ~isproperty(obj2.tags, props1{ii})
                    return;
                end
                if eval(sprintf('~strcmp(obj.tags.%s, obj2.tags.%s)', props1{ii}, props1{ii}))
                    return;
                end
            end
            for ii=1:length(props2)
                if ~isproperty(obj.tags, props2{ii})
                    return;
                end
                if eval(sprintf('~strcmp(obj.tags.%s, obj2.tags.%s)', props2{ii}, props2{ii}))
                    return;
                end
            end
            B = true;
        end

        % -------------------------------------------------------
        function Add(obj, key, value)
            key(key==' ') = '';
            eval(sprintf('obj.tags.%s = value', key));
        end

        % ----------------------------------------------------------------------------------
        function tags = Get(obj)
            fields = propnames(obj.tags);
            tags = repmat(struct('key','','value',[]),length(fields),1);
            for ii=1:length(fields)
                eval(sprintf('tags(ii).key = ''%s'';', fields{ii}));
                eval(sprintf('tags(ii).value = obj.tags.%s;', fields{ii}));
            end
        end

        % ----------------------------------------------------------------------------------
        function nbytes = MemoryRequired(obj)
            nbytes = 0;
            fields = propnames(obj.tags);
            for ii=1:length(fields)
                nbytes = nbytes + eval(sprintf('sizeof(obj.tags.%s)', fields{ii}));
            end
        end

    end
end


function [linecolors, linestyles, linewidths] = SetDataPlotLineStyles(handles, iCh)
global maingui

datatype    = GetDatatype(handles);
ml          = GetMeasurementList(handles);

linecolorsAvailable  = maingui.axesData.SDPairColors;
linestylesAvailable  = {'-',':','-.','--'};
linewidthsAvailable   = [1.5, 2.0, 1.5, 1.5, 1.5];

linecolors  = zeros(length(iCh), 3);
linestyles  = cell(1, length(iCh));
linewidths  = zeros(1, length(iCh));

for ii = 1:length(iCh)

    if datatype == maingui.buttonVals.RAW   ||   datatype == maingui.buttonVals.OD
        iSD = GetSelectedSDPairIndex(ml(iCh(ii),1), ml(iCh(ii),2));
        linecolors(ii, :)  = linecolorsAvailable(iSD, :);
        linestyles{ii}     = linestylesAvailable{ml(iCh(ii),4)};
        linewidths(ii)     = linewidthsAvailable(ml(iCh(ii),4));

    elseif datatype == maingui.buttonVals.CONC

        iHb = ml(iCh(ii),4);
        iSD = GetSelectedSDPairIndex(ml(iCh(ii),1), ml(iCh(ii),2));
        linecolors(ii, :)  = linecolorsAvailable(iSD, :);
        linestyles{ii}     = linestylesAvailable{iHb};
        linewidths(ii)     = linewidthsAvailable(iHb);

    elseif datatype == maingui.buttonVals.OD_HRF

        iSD = GetSelectedSDPairIndex(ml(iCh(ii),1), ml(iCh(ii),2));
        linecolors(ii, :)  = linecolorsAvailable(iSD, :);
        linestyles{ii}     = linestylesAvailable{ml(iCh(ii),4)};
        linewidths(ii)     = linewidthsAvailable(ml(iCh(ii),4));

    elseif datatype == maingui.buttonVals.CONC_HRF

        iHb = ml(iCh(ii),4);
        iSD = GetSelectedSDPairIndex(ml(iCh(ii),1), ml(iCh(ii),2));
        linecolors(ii, :)  = linecolorsAvailable(iSD, :);
        linestyles{ii}     = linestylesAvailable{iHb};
        linewidths(ii)     = linewidthsAvailable(iHb);

    end

end

% --------------------------------------------------------------------------
function iHb = HbLabel2Index(label)
hbTypes     = {'hbo','hbr','hbt'};
iHb = [];
for jj = 1:length(hbTypes)
    if ~includes(lower(label), lower(hbTypes{jj}))
        continue;
    end
    iHb = jj;
    break;
end


function [vectorResult] = niftiCreateComplementString(vectorString)
%
%Take the complement of the vectorString input. So, if we receive AIR, we
%want to return ASR. That is, take the complement of each input with
%respect to the "correct" RPS format.

vectorResult = vectorString;

searchStringMap = containers.Map;

searchStringMap('L') = 'R';
searchStringMap('A') = 'P';
searchStringMap('I') = 'S';

for i = 1:numel(vectorResult)
    if searchStringMap.isKey(vectorResult(i))
        %We need to flip it!
        vectorResult(i) = searchStringMap(vectorResult(i));
    end %if
end %for

return


function v = ksvdver(history)
%KSVDVER K-SVD toolbox version information.
%  KSVDVER displays the current KSVD toolbox version information.
%
%  KSVDVER('history') also displays history information about the previous
%  versions of the KSVD toolbox and their change logs.
%
%  V = KSVDVER returns the version number of the current KSVD toolbox, and
%  does not display any information.

%  Ron Rubinstein
%  Computer Science Department
%  Technion, Haifa 32000 Israel
%  ronrubin@cs
%
%  October 2009

ver = 13;

if (nargout>0)
  if (nargin>0)
    error('Invalid number of parameters.');
  end
  v = ver;

else

  if (nargin==0 || (nargin==1 && strcmpi(history,'history')))

    disp(' ');
    disp('---------------------------------');
    printf('    KSVD Toolbox version %d       ',ver);
    disp('---------------------------------');
    disp(' ');

  else
    error('Unknown parameters.');
  end

  if (nargin>0)

    %% changes only displayed since first public release %%

%     disp(' ');
%     disp('KSVD Toolbox version 1, 24.10.07');
%     disp('---------------------------------');
%     disp(' ');
%     disp('Initial release.');
%     disp(' ');
%     disp(' ');
%     disp(' ');
%
%     disp('KSVD Toolbox version 2, 13.12.07');
%     disp('---------------------------------');
%     disp(' ');
%     disp('Features:');
%     disp(' ');
%     disp('  1. KSVD: support for sparsity and error based coding.');
%     disp('  2. New OMPDENOISE function for generic OMP-based denoising.');
%     disp('  3. ''memusage'' parameter introduced for controlling memory usage.');
%     disp(' ');
%     disp('Bug fixes:');
%     disp(' ');
%     disp('  1. KSVD: when initializing the dictionary with a set of signals, ');
%     disp('     only selects non-zero ones.');
%     disp('  2. KSVD: only negates atoms with first element negative, instead of');
%     disp('     multiplying each atom by its sign (which nullified atoms whose');
%     disp('     first element was zero).');
%     disp('  3. KSVD: tracks training signals used to replace unused atoms, so');
%     disp('     the same one is not used twice.');
%     disp(' ');
%     disp('Internal changes:');
%     disp('  1. Eliminated the use of function cleardict in KSVD, following bugfix (3).');
%     disp(' ');
%     disp(' ');
%     disp(' ');
%
%     disp('KSVD Toolbox version 3, 16.01.08');
%     disp('---------------------------------');
%     disp(' ');
%     disp('Features:');
%     disp(' ');
%     disp('  1. Option for specifying a list of initial signals for the dictionary using');
%     disp('     the parameter initdict.')
%     disp('  2. Changed error computation from Frobenius norm to MSE.');
%     disp('  3. Added the VERBOSE parameter for controlling printed output.');
%     disp('  4. Added the muthresh parameter to KSVD.');
%     disp('  5. Added parameter maxval to OMPDENOISE and KSVDDENOISE.');
%     disp(' ');
%     disp('Internal changes:');
%     disp(' ');
%     disp('  1. Added the sparsecode method for cleaner code.');
%     disp('  2. Re-introduced the use of function cleardict.');
%     disp(' ');
%     disp('Bug fixes:');
%     disp(' ');
%     disp('  1. Function cleardict now checks correlation between atoms in absolute value.');
%     disp(' ');
%     disp(' ');
%     disp(' ');
%
%     disp('KSVD Toolbox version 4, 27.01.08');
%     disp('---------------------------------');
%     disp(' ');
%     disp('Features:');
%     disp(' ');
%     disp('  1. Added functions OMPDENOISE2 and OMPDENOISE3 for faster denoising of');
%     disp('     2-D and 3-D signals.');
%     disp('  2. Added gain and lambda parameters to OMPDENOISE and KSVDDENOISE.');
%     disp(' ');
%     disp(' ');
%     disp(' ');
%
%     disp('KSVD Toolbox version 5, 03.02.08');
%     disp('---------------------------------');
%     disp(' ');
%     disp('Features:');
%     disp(' ');
%     disp('  1. KSVD: atom update is now in random order rather than sequential.');
%     disp('  2. KSVD: improved error computation: error is now computed after the');
%     disp('     dictionary update step, eliminating the need for an additional sparse');
%     disp('     coding step at the end of the algorithm for error computation.');
%     disp('     Computed error is now RMSE for sparsity-based minimization, and average');
%     disp('     atom count for error-based minimization.');
%     disp('  3. KSVD: cleardict now replaces every atom not used by at least 4 training');
%     disp('     signals. Atoms already replaced in the dictionary update step are');
%     disp('     excluded from this criterion.');
%     disp('  4. Added the ''exact'' parameter to KSVD/KSVDDENOISE, to allow using the exact');
%     disp('     SVD solution rather than the default quicker approximation method.');
%     disp('  5. Changed behavior of VERBOSE=3 mode in KSVD, and added VERBOSE=4 mode.');
%     disp('  6. VERBOSE in OMPDENOISE/2/3 now prints a message every VERBOSE seconds,');
%     disp('     not every VERBOSE blocks.');
%     disp('  7. OMPDENOISE: faster computation of the matrix cnt (a counter matrix');
%     disp('     containing the number of blocks covering each sample in the signal.');
%     disp('  8. KSVDDENOISE: new default values for gain and lambda.');
%     disp('  9. KSVDDENOISE: reverts to function OMPDENOISE when memusage is ''low''');
%     disp(' 10. Set a limit on the number of atoms used to code each block in OMPDENOISE');
%     disp('     and KSVDDENOISE. Added the maxatoms parameter to control this limit.');
%     disp(' 11. Improved documentation.');
%     disp(' 12. Added the KSVDVER function.');
%     disp(' ');
%     disp('Internal changes:');
%     disp(' ');
%     disp('  1. Support for the new call syntax of OMP Toolbox v6.');
%     disp('  2. OMPDENOISE3 now computes the matrix cnt using much less memory. Instead');
%     disp('     of allocating three matrices the size of the input signal, it only');
%     disp('     allocates one such matrix.');
%     disp(' ');
%     disp('Bug fixes:');
%     disp(' ');
%     disp('  1. OMPDENOISE2/3 now compute the matrix cnt correctly.');
%     disp(' ');
%     disp(' ');
%     disp(' ');
%
%     disp('KSVD Toolbox version 6, 14.02.08');
%     disp('---------------------------------');
%     disp(' ');
%     disp('Features:');
%     disp(' ');
%     disp('  1. New stepsize parameter in OMPDENOISE/2/3 and KSVDDENOISE.');
%     disp('  2. ''blocksize'' parameter in OMPDENOISE/2/3 and KSVDDENOISE can now be a scalar.');
%     disp('  3. Added the Contents.m file.');
%     disp('  4. Revised VERBOSE settings in KSVDDENOISE, and slightly improved display format');
%     disp('     in KSVD.');
%     disp(' ');
%     disp('Bug fixes:');
%     disp(' ');
%     disp('  1. OMPDENOISE/2/3: fixed a bug in the computation of the matrix cnt when');
%     disp('     the signal is not square.');
%     disp(' ');
%     disp(' ');
%     disp(' ');
%
%     disp('KSVD Toolbox version 7, 18.04.08');
%     disp('---------------------------------');
%     disp(' ');
%     disp('Features:');
%     disp(' ');
%     disp('  1. OMPDENOISE now prints the estimated remaining time.');
%     disp('  2. New ''msgdelta'' parameter in KSVD and KSVDDENOISE for printing');
%     disp('     periodic status updates.');
%     disp(' ');
%     disp('Internal changes:');
%     disp(' ');
%     disp('  1. Compatible with OMP Toolbox v7.');
%     disp(' ');
%     disp(' ');
%     disp(' ');

    disp(' ');
    disp(' ');
    disp('KSVD Toolbox version 7, 18.04.08');
    disp('---------------------------------');
    disp(' ');
    disp('First public release.');
    disp(' ');
    disp(' ');
    disp(' ');

    disp('KSVD Toolbox version 8, 29.05.08');
    disp('---------------------------------');
    disp(' ');
    disp('Features:');
    disp(' ');
    disp('  1. Added ''sigma'' and ''noisemode'' parameters to OMPDENOISE and KSVDDENOISE.');
    disp('  2. Added the overcomplete DCT dictionary as an optional initial dictionary');
    disp('     in KSVDDENOISE, by setting the initdict parameter to the string ''odct''.');
    disp('  3. Improved default gain and lambda parameters in OMPDENOISE.');
    disp(' ');
    disp('Bug fixes:');
    disp(' ');
    disp('  1. KSVDDENOISE: corrected a bug which caused incorrect gain and lambda');
    disp('     parameters to be sent to OMPDENOISE in some cases.');
    disp(' ');
    disp('Internal changes:');
    disp(' ');
    disp('  1. When replacing an unused atom, the search for an example with maximal');
    disp('     error is limited to a fixed number of signals.');
    disp('  2. Improved implementation of KSVDVER.');
    disp('  3. Uses the TIMER package for time estimation.');
    disp(' ');
    disp(' ');
    disp(' ');

    disp('KSVD Toolbox version 9, 30.11.08');
    disp('---------------------------------');
    disp(' ');
    disp('Features:');
    disp(' ');
    disp('  1. OMPDENOISE and KSVDDENOISE can now return the average number of');
    disp('     non-zeros in the denoised block representations.');
    disp(' ');
    disp('Bug fixes:');
    disp(' ');
    disp('  1. Corrected an error when parameter MSGDELTA was not specified.');
    disp(' ');
    disp('Internal changes:');
    disp(' ');
    disp('  1. The COUNTCOVER function counts the number of times a pixel in a');
    disp('     multi-dimensional signal is covered by overlapping blocks.');
    disp('  2. Function CLEARDICT now computes the error norm in blocks to reduce');
    disp('     memory consumption.');
    disp(' ');
    disp(' ');
    disp(' ');

    disp('KSVD Toolbox version 10, 21.05.09');
    disp('----------------------------------');
    disp(' ');
    disp('Features:');
    disp(' ');
    disp('  1. Source code for supporting C functions now available for compilation');
    disp('     on any Matlab platform.');
    disp('  2. Added KSVDDEMO and KSVDDENOISEDEMO.');
    disp('  3. Improved performance of OMPDENOISE2, OMPDENOISE3 and KSVD.');
    disp('  4. New SHOWDICT function for displaying a dictionary of image patches.');
    disp('  5. KSVD: improved VERBOSE/MSGDELTA parameter syntax.');
    disp('  6. KSVD: messages are now displayed by default.');
    disp('  7. KSVD: only one of the parameters dictsize/initdict needs to be specified.');
    disp('  8. KSVD: eliminated the data saving option.');
    disp('  9. OMPDENOISE: messages are now displayed by default.');
    disp(' 10. KSVDDENOISE: simplified MSGDELTA parameter.');
    disp(' 11. KSVDDENOISE: default initial dictionary is now overcomplete DCT.');
    disp(' 12. KSVDDENOISE: parameter initdict can be the string ''data'' to indicate');
    disp('     initialization from training examples.');
    disp(' ');
    disp(' ');
    disp(' ');

    disp('KSVD Toolbox version 11, 03.08.09');
    disp('----------------------------------');
    disp(' ');
    disp('Features:');
    disp(' ');
    disp('  1. Added OMPDENOISE1 for fast OMP denoising of 1-D signals.');
    disp('  2. Added support for 1-D signals in KSVDDENOISE.');
    disp(' ');
    disp('Bug fixes:');
    disp(' ');
    disp('  1. Corrected a bug in OMPDENOISE/2/3 when memusage is low.');
    disp(' ');
    disp('Internal changes:');
    disp(' ');
    disp('  1. KSVD: only compute sum(data.*data) when memusage is high.');
    disp(' ');
    disp(' ');
    disp(' ');

    disp('KSVD Toolbox version 12, 24.08.09');
    disp('----------------------------------');
    disp(' ');
    disp('Features:');
    disp(' ');
    disp('  1. KSVD: significantly faster atom update computation via optimized');
    disp('     sparse-matrix code.');
    disp('  2. KSVD: reduced memory consumption by computing one column of G');
    disp('     at a time when clearing the dictionary, and using block processing');
    disp('     to compute representation error.');
    disp(' ');
    disp('Internal changes:');
    disp(' ');
    disp('  1. KSVD: when replacing an atom in cleardict, the search for an example');
    disp('     with maximal error is limited to a fixed number of signals.');
    disp('  2. KSVDDENOISEDEMO: memusage is set to ''high'' for faster performance.');
    disp(' ');
    disp(' ');
    disp(' ');

    disp('KSVD Toolbox version 13, 18.10.09');
    disp('----------------------------------');
    disp(' ');
    disp('Features:');
    disp(' ');
    disp('  1. KSVDDENOISE: reduced memory consumption by employing block processing');
    disp('     to remove the DC channel from training examples.');
    disp('  2. OMPDENOISE1/2/3: significantly faster operation using new IM2COLSTEP and');
    disp('     COL2IMSTEP MEX functions.');
    disp('  3. OMPDENOISE/1/2/3: dictionary normalization is verified only once, eliminating');
    disp('     redundant computations.');
    disp('  4. KSVDDENOISE: ''low'' memory usage now uses the faster OMPDENOISE1/2/3');
    disp('     functions, and does not revert to OMPDENOISE.');
    disp(' ');
    disp('Internal changes:');
    disp(' ');
    disp('  1. KSVD: cleardict never replaces an atom if it was already replaced by');
    disp('     optimize_atom in the same iteration.');
    disp(' ');
    disp('Bug fixes:');
    disp(' ');
    disp('  1. OMPDENOISE1: progress messages now display the correct block number.');
    disp('  2. KSVD: cleardict considers all training examples to replace an unused atom,');
    disp('     rather than only a fixed number. This eliminates a rare bug introduced in v12');
    disp('     in which the fixed number of examples could be insufficient.');
    disp(' ');
    disp(' ');

   end
end


function [blockInfo] = PL2ReadNextDataBlock(blockInfo)
% PL2ReadNextDataBlock(blockInfo): read next data block, return block info
%
% example:
%
% blockInfo = PL2ReadFirstDataBlock(filename)
% while blockInfo.Type > 0
%    % process data from the block
%    % ...
%    % read the next data block
%    blockInfo = internalPL2ReadNextDataBlock(blockInfo);
% end
%
%
% INPUT:
%   blockInfo - a structure returned from PL2ReadFirstDataBlock or PL2ReadNextDataBlock
%
% OUTPUT:
%   blockInfo - information about the data block
%
%   blockInfo.Type - type of data block
%                    0 - not a data block, did not find data in the file
%                    1 - spike data type
%                    2 - analog data type
%                    3 - digital event data type
%                    4 - start/stop event data type
%   blockInfo.Source - block source
%   blockInfo.Channel - block channel inside source
%   if blockInfo.Type is 1 (spike), SpikeData structure is filled
%       blockInfo.SpikeData.WaveLength - number of samples in each waveform
%       blockInfo.SpikeData.NumSpikes - number of spikes
%       blockInfo.SpikeData.Timestamps  - spike timestamps in seconds
%       blockInfo.SpikeData.Units - spike units
%       blockInfo.SpikeData.Waveforms - spike waveforms in milliVolts
%   if blockInfo.Type is 2 (analog), AnalogData structure is filled
%       blockInfo.AnalogData.NumSamples - number of analog samples
%       blockInfo.AnalogData.Timestamp - timestamps of the first sample (in seconds)
%       blockInfo.AnalogData.Values - sample values in milliVolts
%   if blockInfo.Type is 3 (event), EventData structure is filled
%       blockInfo.EventData.NumEvents - number of events
%       blockInfo.EventData.Timestamps - event timestamps in seconds
%       blockInfo.EventData.Values - event values
%   if blockInfo.Type is 4 (start/stop event), StartStopEventData structure is filled
%       blockInfo.StartStopEventData.NumEvents - number of events
%       blockInfo.StartStopEventData.Timestamps - event timestamps in seconds
%       blockInfo.StartStopEventData.Values - event values

blockInfo = internalPL2ReadNExtDataBlock(blockInfo);

end


%% freeBoundaryPatch
% Below is a demonstration of the features of the |freeBoundaryPatch| function

%%
clear; close all; clc;

%% Syntax
% |[indFree]=freeBoundaryPatch(F);|

%% Description
% UNDOCUMENTED
%% Examples
%
%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% 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/>.


function newROI = dtiMergeROIs(roi1,roi2)
%
%   newROI = dtiMergeROIs(roi1,roi2)
%
% Author: RFD, BW
% Purpose:
%  Merge ROIs
%
%Example:
% handles = guidata(gcf); roi1 = handles.rois(1); roi2 = handles.rois(2);
% newROI = dtiMergeROIs(roi1,roi2);
% handles = dtiAddROI(newROI,handles,1);
% guidata(gcf,handles);
% dtiRefresh ... or something

newROI = roi1;
newROI.name = sprintf('%s_%s',roi1.name,roi2.name);

newROI.coords = unique(vertcat(roi1.coords,roi2.coords),'rows');

return;


function fmri_EccBias_GLMcontrasts

% EccBias scans processing code
%
% USER IMPORTANT!!!: Before running this script, make sure that all EccBias
% scans have the correct annotation fields and scan groups (are grouped
% correctly). Otherwise, fmri_EccBias_checkDataTypesForGLM will fail.
%
% 1. Set GLM parameters for all scans
% 2. Check EccBias localizer experiments for:
%    a. Datatype and scan numbers
%    b. Record parfiles
%    c. Make sure scan groupings are correct
% 3. Run GLM for EccBias experiments
% 4. Run contrasts for the EccBias experiments
%
% Calls the functions:
% * fmri_EccBias_setGLMparams (subfunction)
% * fmri_EccBias_checkDataTypesForGLM
% * fmri_EccBias_computeContrasts
%
%
% AL 09/17/08
% Modified 06/18/2008: there are calls to er_setParams and saveSessions all
% over the place, which results in the params for the MotionComp_RefScan1
% being changed for the worse. I'm not sure how to efficiently prevent this
% from happening, so instead, I let it happen, and just fix the ANNOTATION
% and PARFILE fields at the end, since accuracy here is important.
%
% Code taken from fmri_FFA_motionCompFix

clear all

% Set directory and subject list
% Alternatively: subs = {'sess1','sess2','sess3',...};
if ispc
   fmriDir = 'W:\projects\Kids\fmri\eccbias_faces_places\';
else
   fmriDir = '/biac1/kgs/projects/Kids/fmri/eccbias_faces_places/';
end
cd(fmriDir); s=dir('*0*'); subs={s.name};

% Start a log text file to document successes and failures in preprocessing
dateAndTime=datestr(now); dateAndTime(12)='_'; dateAndTime(15)='h';dateAndTime(18)='m';
logDir=fullfile(fmriDir,'logs');
if ~isdir(logDir), mkdir(logDir), end;
logFile = fullfile(fmriDir,'logs',['EccBias_Log_' dateAndTime '.txt']);
fid=fopen(logFile,'w');
[junk,logFileName]=fileparts(logFile);
scriptName = 'fmri_EccBias_GLMcontrasts.m';
startTime = clock;

% 1. Set GLM parameters
params=fmri_EccBias_setGLMparams(fid,logFileName,scriptName); % Subfunction within this script

for ii=1:length(subs)

    % Get rid of all mrVista globals in workspace. Put this at the top,
    % just in case we break from the rest of the loop.
    clear dataTYPES mrSESSION vANATOMYPATH HOMEDIR hI newDt newScan

    thisDir = fullfile(fmriDir,subs{ii}); cd(thisDir);
    fprintf(fid,'\n ------------------------------------------ \n');
    fprintf(fid,'Processing %s\n\n',thisDir);
    fprintf('Processing %s\n\n',thisDir);

    %% Check if the subject already has been processed by script (and thus
    %% should not be re-entered to this script). If they do, skip to the
    %% next subject by using CONTINUE.
    load mrSESSION.mat
    theglm=find(strcmp({dataTYPES.name},'GLMs'));
     if ~isempty(theglm)
        checkScans=length(dataTYPES(theglm).eventAnalysisParams);
        alreadyDone=[];
        for xx=1:checkScans
            tmp=(strfind(lower(dataTYPES(theglm).eventAnalysisParams(xx).annotation),'eccbias'));
            alreadyDone=[alreadyDone tmp];
        end
        if(~isempty(alreadyDone))
            fprintf(fid,'Error: Subject already processed (has GLM with ''Eccbias'' in annotation field), skipping... \n\n');
            fprintf('Error: Subject already processed (has GLM with ''Eccbias'' in annotation field), skipping... \n\n');
            continue
        end
    end

    %% 2a/b/c. Find datatype number for MotionComp_RefScan1, find scan
    %% numbers for EccBias localizer scans, record parfiles for these scans and
    %% make sure scan groupings are correct. If everything checks out,
    %% proceed with GLM. If not, SKIP THIS SUBJECT.
    [go,s1,s2]=fmri_Eccbias_checkDataTypesForGLM(fid,dataTYPES);

    % If there was a problem in step 3, skip GLM and proceed to next
    % subject
    if go==0
        continue

    %% 3. Otherwise, run GLM (to debug: fid=1)
    elseif go==1
        try
            % Initialize a hidden view of the 'inplane' data (like invoking
            % mrVista without a GUI, dataTYPES/etc in workspace)
            hI = initHiddenInplane(s1.mc, s1.scan);
            params.parfiles={s1.parfile, s2.parfile};
            er_setParams(hI, params); % write params as eventAnalysisParams fields
            tic; [hI, ecc_scan] = applyGlm(hI,s1.mc,s1.scangroup,params);
            time=toc;
            fprintf(fid,'GLM COMPLETED -- dt %d, scan %d. Time: %d m %2.2f s \n\n',...
                hI.curDataType,ecc_scan,floor(time/60),mod(time,60));
            fprintf('GLM COMPLETED -- dt %d, scan %d. Time: %d m %2.2f s \n\n',...
                hI.curDataType,ecc_scan,floor(time/60),mod(time,60));
            glmOK=1;
        catch
            fprintf(fid,'FAILURE TO SUCCESSFULLY RUN GLM \n');
            fprintf('FAILURE TO SUCCESSFULLY RUN GLM \n');
            theerror=lasterror;
            fprintf(fid,'%s \n\n',theerror.message);
            fprintf('%s \n\n',theerror.message);
            glmOK=0;
        end

        %% 4. Compute contrast maps
        if glmOK

            try
                fmri_EccBias_computeContrasts(hI, ecc_scan)
                fprintf(fid,'Computed contrasts using fmri_EccBias_computeContrasts \n');
                fprintf('Computed contrasts using fmri_EccBias_computeContrasts \n');
            catch
                fprintf(fid,'FAILURE TO SUCCESSFULLY COMPUTE CONTRASTS \n');
                fprintf('FAILURE TO SUCCESSFULLY COMPUTE CONTRASTS \n');
                theerror=lasterror;
                fprintf(fid,'%s \n\n',theerror.message);
                fprintf('%s \n\n',theerror.message);

            end
        end
    end

    % Fix the annotation and parfile fields for the MotionComp_RefScan
    % dataTYPE, since these are undesirably changed (collateral damage).
    dataTYPES(s1.mc).eventAnalysisParams(s1.scan).annotation='EccBias_run1';
    dataTYPES(s2.mc).eventAnalysisParams(s2.scan).annotation='EccBias_run2';

    par1=dataTYPES(s1.mc).scanParams(s1.scan).parfile;
    par2=dataTYPES(s2.mc).scanParams(s2.scan).parfile;

    dataTYPES(s1.mc).eventAnalysisParams(s1.scan).parfiles=par1;
    dataTYPES(s2.mc).eventAnalysisParams(s2.scan).parfiles=par2;
    save(fullfile(thisDir,'mrSESSION.mat'),'mrSESSION','dataTYPES', '-append');
    clear par1 par2

end

totalTime=etime(clock,startTime);

fprintf(fid,'\n ------------------------------------------ \n');
fprintf(fid,'Total running time for script: %f minutes \n',totalTime/60);
fprintf('Total running time for script: %f minutes \n',totalTime/60);

fclose(fid); % close out the log file

return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function params=fmri_EccBias_setGLMparams(fid,logFileName,scriptName)

% Set GLM parameters: We set the PARAMS struct fields to the values on the
% wiki, which are further explained there. Also we print the values to the
% log. http://vpnl.stanford.edu/internal/wiki/index.php/ROIanalysis#GLMs

fprintf(fid,'\n ------------------------------------------ \n');
fprintf(fid,'\n GLM PARAMETERS \n');
fprintf(fid,' ------------------------------------------ \n');

params=er_defaultParams % Initialize param struct with defaults
p.al='params.alpha=0.0500'; eval(p.al); fprintf(fid,'%s \n',p.al);
p.at='params.ampType=''betas'''; eval(p.at); fprintf(fid,'%s \n',p.at);
p.an='params.annotation=''Eccbias Runs 1&2'''; eval(p.an); fprintf(fid,'%s \n',p.an);
p.ap='params.assignParfiles=0'; eval(p.ap); fprintf(fid,'%s \n',p.ap);
p.bp='params.bslPeriod=[-6 -5 -4 -3 -2 -1 0]'; eval(p.bp); fprintf(fid,'%s \n',p.bp);
p.dt='params.detrend=1'; eval(p.dt); fprintf(fid,'%s \n',p.dt);
p.df='params.detrendFrames=20;'; eval(p.df); fprintf(fid,'%s \n',p.df);
p.ea='params.eventAnalysis=1'; eval(p.ea); fprintf(fid,'%s \n',p.ea);
p.eb='params.eventsPerBlock=6'; eval(p.eb); fprintf(fid,'%s \n',p.eb);
p.fp='params.framePeriod=2'; eval(p.fp); fprintf(fid,'%s \n',p.fp);
p.gt='params.glmHRF=3'; eval(p.gt); fprintf(fid,'%s \n',p.gt);
p.gp='params.glmHRF_params=[6 16 1 1 6 0 24]'; eval(p.gp); fprintf(fid,'%s \n',p.gp);
p.gw='params.glmWhiten=0'; eval(p.gw); fprintf(fid,'%s \n',p.gw); % temporal autocorrelation
p.ic='params.inhomoCorrect=1'; eval(p.ic); fprintf(fid,'%s \n',p.ic);
p.lp='params.lowPassFilter=0'; eval(p.lp); fprintf(fid,'%s \n',p.lp);
p.nb='params.normBsl=1'; eval(p.nb); fprintf(fid,'%s \n',p.nb);
p.od='params.onsetDelta=0'; eval(p.od); fprintf(fid,'%s \n',p.od);
p.pf='params.parfiles='''''; eval(p.pf); fprintf(fid,'%s \n',p.pf); % fill in after checkDataTypes...
p.pp='params.peakPeriod=[4 5 6 7 8 9 10 11 12 13 14]'; eval(p.pp); fprintf(fid,'%s \n',p.pp);
p.sh='params.setHRFParams=0'; eval(p.sh); fprintf(fid,'%s \n',p.sh);
p.sc='params.snrConds=1'; eval(p.sc); fprintf(fid,'%s \n',p.sc);
p.tn='params.temporalNormalization=0'; eval(p.tn); fprintf(fid,'%s \n',p.tn);
p.tw='params.timeWindow=[-6:1:24]'; eval(p.tw); fprintf(fid,'%s \n',p.tw);
p.log=['params.logFile=''' logFileName '''']; eval(p.log); fprintf(fid,'%s \n',p.log)
p.script=['params.scriptName=''' scriptName '''']; eval(p.script); fprintf(fid,'%s \n',p.script)


function value=moxunit_fieldtrip_util_parse_dependency(line)
% parse WALLTIME property in FieldTrip test
%
% value=moxunit_fieldtrip_util_parse_walltime(line)
%
% Input:
%   line                string which represents one or more alphanumeric
%                       strings
%
% Output:
%   value               cell string with the strings in line separated by
%                       white space
%
% #   For MOxUnit_fieldtrip's copyright information and license terms,   #
% #   see the COPYING file distributed with MOxUnit_fieldtrip.           #

    if ~ischar(line)
        error('input must be numeric');
    end

    value=regexp(line,'(\w+)','match');


%{
    Copyright (C) Cambridge Electronic Design Limited 2014
    Author: James Thompson
    Web: www.ced.co.uk email: james@ced.co.uk, softhelp@ced.co.uk

    This file is part of CEDS64ML, a MATLAB interface to the SON64 library.

    CEDS64ML 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.

    CEDS64ML 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 CEDS64ML.  If not, see <http://www.gnu.org/licenses/>.
%}

function [ iOk, sUnitsOut ] = CEDS64ChanUnits( fhand, iChan, sUnitsIn )
%CEDS64CHANUNITS Gets and sets channels units
%   [ iOk {, sUnitsOut} ] = CEDS64ChanUnits( fhand, iChan{, sUnitsIn} )
%   Input
%   fhand - An integer handle to an open file
%   iChan - A channel number
%   sUnitsIn - (Optional) A string conatining the new units
%   Output
%   iOk - 0 if the units were set correctly otherwise a negative error code.
%   sUnitsOut - A string containing the old units

if (nargin == 2 || nargin == 3) % always get the old units
    %step 1 find out how big the comment is
    dummystring = blanks(1);
    [iSize] = calllib('ceds64int', 'S64GetChanUnits', fhand, iChan, dummystring, -1);
    %step 2 create a string buffer of the correct size
    stringptr = blanks(iSize+1);
    [iOk, sUnitsOut] = calllib('ceds64int', 'S64GetChanUnits', fhand, iChan, stringptr, 0);
else
    iOk = -22;
end

% has there been an error?
if iOk < 0
    return;
end

% if not set the new units if we're given some
if (nargin == 3)
    iOk = calllib('ceds64int', 'S64SetChanUnits', fhand, iChan, sUnitsIn);
end
end


function [inputMovie] = addDroppedFramesToMovie(inputMovie,droppedFrames,varargin)
	% Fixes movie by adding dropped frames with the mean of the movie (to reduce impact on cell extraction algorithms).
	% Biafra Ahanonu
	% started: 2016.10.04 [20:31:15]
	% inputs
		% inputMovie - matrix dims are [X Y t] - where t = number of time points
		% path to inscopix file or list of dropped frames
	% outputs
		% inputMovie with dropped frames added back in.

	[inputMovie] = ciapkg.video.addDroppedFramesToMovie(inputMovie,droppedFrames,'passArgs', varargin);
end


%kkasc2val 'Import ASCII Data File to Value Segment'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros kasc2val.pane file
%
% Parameters:
% InputFile: i1 'ASCII Input File', required: 'ASCII input data file containing new data segment'
% InputFile: i2 'Data Object Input', optional: 'data object input to insert the new segment into'
% Integer: so 'Start Offset ', default: 0: 'starting point in ASCII file to start importing at'
% Integer: sf 'Skip Factor ', default: 0: 'number of points in ASCII file to skip between reads'
% Integer: wsize ' ', default: 1: 'width size must be > 0'
% Integer: hsize ' ', default: 1: 'height size must be > 0'
% Integer: dsize ' ', default: 1: 'depth size must be > 0'
% Integer: tsize ' ', default: 1: 'time size must be > 0'
% Integer: esize ' ', default: 1: 'elements size must be > 0'
% OutputFile: o 'Output Object', required: 'output data object'
%
% Example: o = kkasc2val({i1, i2}, {'i1','';'i2','';'so',0;'sf',0;'wsize',1;'hsize',1;'dsize',1;'tsize',1;'esize',1;'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% kasc2val - Import ASCII Data File to Value Segment
%
%  DESCRIPTION
% This routine will import an ASCII data file and insert it into a data
% object if it is specified.  If there is no source object to insert the
% new segment into, the data object specified as the output file will be
% created.  The new segment will be inserted into this data object in the
% value segment.  If a source object was specified, then all of its
% data segments and the global object attributes will be copied to the
% destination.
% The index order is specified by setting the -windex, -hindex, -dindex,
% -tindex and -eindex flags.  They can not be set to the same value.
% The start offset is the point to start importing in the
% ASCII data.  All points before this one are ignored.
% The skip factor is the number of points to skip in the ASCII
% data between reads.  If the size of the new segment's lowest
% index is 40 and the skip factor is 5, then this routine will
% read in 40 points skip 5 and read in 40 more, etc. until the
% entire ASCII file read in.
% Complex values in ASCII are represented by number pairs, surrounded
% by parenthesis and separated by a comma.  For example, (8, 3) represents
% the complex number 8+3i.
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
% kasc2mask, kasc2loc, kasc2time, kasc2map, kimportasc
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kkasc2val(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,..] = kkasc2val(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i1', '__input';'i2', '__input';'so', 0;'sf', 0;'wsize', 1;'hsize', 1;'dsize', 1;'tsize', 1;'esize', 1;'o', '__output'};
maxval={0,1,1,1,2,2,2,2,2,0};
minval={0,1,1,1,2,2,2,2,2,0};
istoggle=[0,1,1,1,1,1,1,1,1,0];
was_set=istoggle * 0;
paramtype={'InputFile','InputFile','Integer','Integer','Integer','Integer','Integer','Integer','Integer','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 'kasc2val"  '],Inputs,narglist);


function OUT = mpower(varargin)

% overloaded power for GRIDobj
%
% Note that there is no matrix power defined for GRIDobj. Thus
% mpower overloads element-by-element powers (power).

funname = 'power';
narginchk(2,2)
OUT = builtincaller(funname,varargin{:});


function images = experiment_get_dataset(varargin)
% images = experiment_get_dataset(varargin) - Collect all the images
%   from one of more datasets
% Eg: images = experiment_get_dataset('stock') - to get the stock images
% Use any subset of
%  'copydays', 'stock', 'imnet', 'imnet-lite', 'imnet-nogreen', 'imnet-large', 'hoggle'

if nargin == 0
  subsets = {'stock', 'imnet', 'hoggle'} ;
else
  subsets = varargin ;
end

images = {} ;
for i=1:numel(subsets)

  switch subsets{i}

    case 'copydays'
      % copydays dataset
      tmp = dir('/users/aravindh/work/datasets/copydays/*.jpg') ;
      copydays = cellfun(@(x) fullfile('/users/aravindh/work/datasets/copydays/', x), {tmp(:).name}, 'uniform', false);
      images = horzcat(images, copydays) ;

    case 'stock'
      % stock images
      tmp = vertcat(...
        dir('data/stock_images/*.jpg'), ...
        dir('data/stock_images/*.png')) ;
      stock = cellfun(@(x) fullfile('data/stock_images', x), {tmp(~[tmp.isdir]).name}, 'uniform', false);
      images = horzcat(images, stock) ;

    case 'imnet'
      % image net images. This is a large scale experiment.
      tmp = dir('data/imagenet12-val/*.JPEG') ;
      imnet = cellfun(@(x) fullfile('data/imagenet12-val/', x), {tmp(1:100).name}, 'uniform', false);
      imnet_large = cellfun(@(x) fullfile('data/imagenet12-val/', x), {tmp(101:500).name}, 'uniform', false);
      images = horzcat(images, imnet) ;

    case 'imnet-lite'
      % image net images tiny subset
      tmp = dir('data/imagenet12-val/*.JPEG') ;
      imnet = cellfun(@(x) fullfile('data/imagenet12-val/', x), {tmp(1:100).name}, 'uniform', false);
      imnet_large = cellfun(@(x) fullfile('data/imagenet12-val/', x), {tmp(101:500).name}, 'uniform', false);
      images = horzcat(images, imnet([13 24 43 70])) ;% [1 2 5 8 17 18 30 34 48 56]

    case 'imnet-nogreen'
      % image net images which are not green. To see if the greenish output
      % is a property of the prior or the network.
      tmp = dir('data/imagenet12-val/ILSVRC2012_val_000000*.JPEG') ;
      imnet = cellfun(@(x) fullfile('data/imagenet12-val/', x), {tmp(1:99).name}, 'uniform', false);
      images = horzcat(images, imnet( [1 2 5 17 18 30 34 48 56 70] ));

    case 'imnet-large'
      % image net images
      tmp = dir('data/imagenet12-val/*.JPEG') ;
      imnet_large = cellfun(@(x) fullfile('data/imagenet12-val/', x), {tmp(101:500).name}, 'uniform', false);
      images = horzcat(images, imnet_large);

    case 'hoggle'
      % hoggle images
      hoggle{1} = 'data/hoggle/hoggle-orig-1.jpg' ;
      hoggle{2} = 'data/hoggle/hoggle-orig-2.jpg' ;
      images = horzcat(images, hoggle) ;

  end
end


%PLANESTRAIN Plane strain physics mode.

% Copyright 2013-2022 Precise Simulation, Ltd.


function r = strgsub(s, re, replacement)
%STRGSUB Replaces all substrings matching a specified pattern
%
%   r = strgsub(s, re, newstring);
%       replaces all substrings in s that match the regular expression
%       re by the newstring.
%
%   r = strgsub(s, re, translatef);
%       translates all substrings in s that match the regular expression
%       re using the function translatef, which should be a function
%       handle.
%
%   Examples
%   --------
%       % replaces all occurrences of a particular string by a new one
%       r = strgsub('It is in year 1998 and year 2004', 'year', 'yr');
%       r <- 'It is in yr 1998 and yr 2004'
%
%       % replaces all substrings matching a pattern by a fixed string
%       r = strgsub('It is in year 1998 and year 2004', '\d+', '####');
%       r <- 'It is in year #### and year ####'
%
%       % squeezes consecutive spaces to one space
%       r = strgsub('A  b    c      d', '\s+', ' ');
%       r <- 'A b c d'
%
%       % Capitalize each word
%       r = strgsub('you and me', '\w+', @(x) [upper(x(1)), x(2:end)]);
%       r <- 'You And Me'
%
%       % increment each number occurred in a string by one
%       r = strgsub('10:20 34:562', '\d+', @(x) int2str(str2double(x)+1));
%       r <- '11:21 35:563'
%

%   History
%   -------
%       - Created by Dahua Lin, on Oct 9, 2008
%

%% parse and verify input arguments

assert(ischar(s) && ndims(s) == 2 && size(s,1) <= 1, ...
    'strgsub:invalidarg', ...
    'The first input argument should be a char string.');

assert(ischar(re) && ndims(re) == 2 && size(re,1) == 1 && ~isempty(re), ...
    'strgsub:invalidarg', ...
    'The regular expression should be a non-empty char string.');

if ischar(replacement)
    s2 = replacement;
    assert(ischar(s2) && ndims(s2) == 2 && size(s2,1) <= 1, ...
        'strgsub:invalidarg', ...
        'The size of the string of replacement is illegal.');
    direct_replace = true;

elseif isa(replacement, 'function_handle')
    tf = replacement;
    direct_replace = false;

else
    error('strgsub:invalidarg', ...
        'replacement should be either a string or a function handle.');
end

%% main

if direct_replace
    [sp, ep] = regexp(s, re, 'start', 'end');

    if ~isempty(sp)
        r = do_replace(s, sp, ep, s2);
    else
        r = s;
    end
else
    [sp, ep, ms] = regexp(s, re, 'start', 'end', 'match');

    if ~isempty(sp)
        s2 = cell(size(ms));
        for i = 1 : numel(s2)
            s2{i} = tf(ms{i});
        end
        r = do_replace(s, sp, ep, s2);
    else
        r = s;
    end
end

%% The core replace function

function r = do_replace(s, sp, ep, s2)

nr = numel(sp);
if ischar(s2)
    s2 = repmat({s2}, [1, nr]);
end

s1 = cell(1, nr + 1);
p = 1;
for i = 1 : nr
    if p < sp(i)
        s1{i} = s(p:sp(i)-1);
    end
    p = ep(i)+1;
end
if p <= length(s)
    s1{nr+1} = s(p:end);
end

ss = cell(1, 2*nr+1);
ss(1:2:end) = s1;
ss(2:2:end) = s2;

r = [ss{:}];
if isempty(r)
    r = '';
end


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