%kImpRaw 'imports a raw data file and bins it '
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros ImpRaw.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'First Input data object'
% Integer: sizex 'SizeX', default: 256: 'x dimension of the data'
% Integer: binx 'BinX', default: 1: 'number of pixels to bin along x (if below 0 it is extracted, above 0 summed)'
% Toggle: bt 'Byte Type', default: 0: 'True: Is bytes; False: Is Short'
% Integer: sizey 'SizeY', default: 256: 'y dimension of the data'
% Integer: biny 'BinY', default: 1: 'number of pixels to bin along y (if below 0 it is extracted, above 0 summed)'
% Integer: sizez 'SizeZ', default: 10: 'z dimension of the data'
% Integer: binz 'BinZ', default: 1: 'number of pixels to bin along z (if below 0 it is extracted, above 0 summed)'
% Integer: sizet 'SizeT', default: 1: 'time dimension of the data'
% Integer: sizee 'SizeE', default: 1: 'element dimension of the data'
% Integer: offset 'offset', default: 0: 'Offset in bytes'
% OutputFile: o 'Output', required: 'Resulting output data object'
%
% Example: o = kImpRaw(i, {'i','';'sizex',256;'binx',1;'bt',0;'sizey',256;'biny',1;'sizez',10;'binz',1;'sizet',1;'sizee',1;'offset',0;'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% ImpRaw - imports a raw data file and bins it
%
%  DESCRIPTION
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kImpRaw(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,..] = kImpRaw(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'sizex', 256;'binx', 1;'bt', 0;'sizey', 256;'biny', 1;'sizez', 10;'binz', 1;'sizet', 1;'sizee', 1;'offset', 0;'o', '__output'};
maxval={0,0,0,0,0,0,0,0,0,0,0,0};
minval={0,0,0,0,0,0,0,0,0,0,0,0};
istoggle=[0,0,0,1,0,0,0,0,0,0,0,0];
was_set=istoggle * 0;
paramtype={'InputFile','Integer','Integer','Toggle','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 'impraw"  -k'],Inputs,narglist);


function [taskReport, essentialRxns, taskStructure, essentialFluxes]=checkTasks(model,inputFile,printOutput,printOnlyFailed,getEssential,taskStructure)
% checkTasks
%   Performs a set of simulations as defined in a task file.
%
%   Input:
%   model           a model structure
%   inputFile       a task list in Excel format. See the function
%                   parseTaskList for details (opt if taskStructure is
%                   supplied)
%   printOutput     true if the results of the test should be displayed
%                   (opt, default true)
%   printOnlyFailed true if only tasks that failed should be displayed
%                   (opt, default false)
%   getEssential    true if the essential reactions should be calculated for
%                   all the tasks. This option is used with runINIT (opt,
%                   default false)
%   taskStructure   structure with the tasks, as from parseTaskList. If
%                   this is supplied then inputFile is ignored (opt)
%
%
%   Output:
%   taskReport          structure with the results
%       id              cell array with the id of the task
%       description     cell array with the description of the task
%       ok              boolean array with true if the task was successful
%   essentialRxns       MxN matrix with the essential reactions (M) for each
%                       task (N). An element is true if the corresponding
%                       reaction is essential in the corresponding task.
%                       Failed tasks and SHOULD FAIL tasks are ignored.
%                       This is used by the INIT algorithm (if tasks
%                       are supplied). If getEssential=false then
%                       essentialRxns=false(nRxns,nTasks)
%   taskStructure       structure with the tasks, as from parseTaskList
%   essentialFluxes     The fluxes of the essential rxns - same structure as essentialRxns
%
%
%   This function is used for defining a set of tasks for a model to
%   perform. The tasks are defined by defining constraints on the model,
%   and if the problem is feasible, then the task is considered successful.
%   In general, each row can contain one constraint on uptakes, one
%   constraint on outputs, one new equation, and one change of reaction
%   bounds. If more bounds are needed to define the task, then several rows
%   can be used for each task.
%
%   Usage: [taskReport, essentialReactions, taskStructure]=checkTasks(model,inputFile,...
%           printOutput,printOnlyFailed,getEssential,taskStructure)

if nargin<3 || isempty(printOutput)
    printOutput=true;
end
if nargin<4 || isempty(printOnlyFailed)
    printOnlyFailed=false;
end
if nargin<5 || isempty(getEssential)
    getEssential=false;
end

%Prepare the input model a little
model.b=zeros(numel(model.mets),2);

modelMets=upper(strcat(model.metNames,'[',model.comps(model.metComps),']'));
if ~isfield(model,'unconstrained')
    EM='Exchange metabolites should normally not be removed from the model when using checkTasks. Inputs and outputs are defined in the task file instead. Use importModel(file,false) to import a model with exchange metabolites remaining';
    dispEM(EM,false);
end

%Parse the task file
if nargin<6
    taskStructure=parseTaskList(inputFile);
end

essentialRxns=false(numel(model.rxns),numel(taskStructure));
essentialFluxes = NaN(numel(model.rxns),numel(taskStructure));

tModel=model;
taskReport=[];
for i=1:numel(taskStructure)
    taskReport.id{i,1}=taskStructure(i).id;
    taskReport.description{i,1}=taskStructure(i).description;
    %Set the inputs
    if ~isempty(taskStructure(i).inputs)
        [I, J]=ismember(upper(taskStructure(i).inputs),modelMets);
        J=J(I); %Only keep the ones with matches
        K=ismember(upper(taskStructure(i).inputs),'ALLMETS');
        L=~cellfun('isempty',strfind(upper(taskStructure(i).inputs),'ALLMETSIN'));
        %Check that all metabolites are either real metabolites or
        %ALLMETS/ALLMETSIN
        if ~all(I|K|L)
            fprintf(['ERROR: Could not find all inputs in "[' taskStructure(i).id '] ' taskStructure(i).description '"\n']);
            taskReport.ok(i,1)=false;
            tModel=model;
            continue;
        end
        if numel(J)~=numel(unique(J))
            EM=['The constraints on some input(s) in "[' taskStructure(i).id '] ' taskStructure(i).description '" are defined more than one time'];
            dispEM(EM);
        end
        %If all metabolites should be added
        if any(K)
            %Check if ALLMETS is the first metabolite. Otherwise print a
            %warning since it will write over any other constraints that
            %are set
            if K(1)==0
                EM=['ALLMETS is used as an input in "[' taskStructure(i).id '] ' taskStructure(i).description '" but it it not the first metabolite in the list. Constraints defined for the metabolites before it will be over-written'];
                dispEM(EM,false);
            end
            %Use the first match of ALLMETS. There should only be one, but
            %still..
            tModel.b(:,1)=taskStructure(i).UBin(find(K,1))*-1;
        end
        %If metabolites in a specific compartment should be used
        if any(L)
            L=find(L);
            for j=1:numel(L)
                %The compartment defined
                compartment=upper(taskStructure(i).inputs{L(j)}(11:end-1));
                %Check if it exists in the model
                C=find(ismember(upper(model.comps),compartment));
                if any(C)
                    %Match to metabolites
                    tModel.b(model.metComps==C,1)=taskStructure(i).UBin(L(j))*-1;
                else
                    EM=['The compartment defined for ALLMETSIN in "[' taskStructure(i).id '] ' taskStructure(i).description '" does not exist'];
                    dispEM(EM);
                end
            end
        end
        %Then add the normal constraints
        if any(J)
            tModel.b(J,1)=taskStructure(i).UBin(I)*-1;
            tModel.b(J,2)=taskStructure(i).LBin(I)*-1;
        end
    end
    %Set the outputs
    if ~isempty(taskStructure(i).outputs)
        [I, J]=ismember(upper(taskStructure(i).outputs),modelMets);
        J=J(I); %Only keep the ones with matches
        K=ismember(upper(taskStructure(i).outputs),'ALLMETS');
        L=~cellfun('isempty',strfind(upper(taskStructure(i).outputs),'ALLMETSIN'));
        %Check that all metabolites are either real metabolites or
        %ALLMETS/ALLMETSIN
        if ~all(I|K|L)
            fprintf(['ERROR: Could not find all outputs in "[' taskStructure(i).id '] ' taskStructure(i).description '"\n']);
            taskReport.ok(i,1)=false;
            tModel=model;
            continue;
        end
        if numel(J)~=numel(unique(J))
            EM=['The constraints on some output(s) in "[' taskStructure(i).id '] ' taskStructure(i).description '" are defined more than one time'];
            dispEM(EM);
        end
        %If all metabolites should be added
        if any(K)
            %Check if ALLMETS is the first metabolite. Otherwise print a
            %warning since it will write over any other constraints that
            %are set
            if K(1)==0
                EM=['ALLMETS is used as an output in "[' taskStructure(i).id '] ' taskStructure(i).description '" but it it not the first metabolite in the list. Constraints defined for the metabolites before it will be over-written'];
                dispEM(EM,false);
            end
            %Use the first match of ALLMETS. There should only be one, but
            %still..
            tModel.b(:,2)=taskStructure(i).UBout(find(K,1));
        end
        %If metabolites in a specific compartment should be used
        if any(L)
            L=find(L);
            for j=1:numel(L)
                %The compartment defined
                compartment=upper(taskStructure(i).outputs{L(j)}(11:end-1));
                %Check if it exists in the model
                C=find(ismember(upper(model.comps),compartment));
                if any(C)
                    %Match to metabolites
                    tModel.b(model.metComps==C,2)=taskStructure(i).UBout(L(j));
                else
                    EM=['The compartment defined for ALLMETSIN in "[' taskStructure(i).id '] ' taskStructure(i).description '" does not exist'];
                    dispEM(EM);
                end
            end
        end
        %Then add the normal constraints
        if any(J)
            %Verify that IN and OUT bounds are consistent. Cannot require
            %that a metabolite is simultaneously input AND output at some
            %nonzero flux.
            I = find(I);  % otherwise indexing becomes confusing
            nonzero_LBin = tModel.b(J,2) < 0;
            nonzero_LBout = taskStructure(i).LBout(I) > 0;
            if any(nonzero_LBin & nonzero_LBout)
                EM=['The IN LB and OUT LB in "[' taskStructure(i).id '] ' taskStructure(i).description '" cannot be nonzero for the same metabolite'];
                dispEM(EM);
            end
            tModel.b(J(nonzero_LBout),1)=taskStructure(i).LBout(I(nonzero_LBout));
            tModel.b(J,2)=taskStructure(i).UBout(I);
        end
    end
    %Add new rxns
    if ~isempty(taskStructure(i).equations)
        rxn.equations=taskStructure(i).equations;
        rxn.lb=taskStructure(i).LBequ;
        rxn.ub=taskStructure(i).UBequ;
        rxn.rxns=strcat({'TEMPORARY_'},num2str((1:numel(taskStructure(i).equations))'));
        %Allow for new metabolites to be added. This is because it should
        %be possible to add, say, a whole new pathway
        tModel=addRxns(tModel,rxn,3,[],true);
    end
    %Add changed bounds
    if ~isempty(taskStructure(i).changed)
        tModel=setParam(tModel,'lb',taskStructure(i).changed,taskStructure(i).LBrxn);
        tModel=setParam(tModel,'ub',taskStructure(i).changed,taskStructure(i).UBrxn);
    end

    %Solve and print
    sol=solveLP(tModel);
    if ~isempty(sol.x)
        %assign the fluxes
        essentialFluxes(:,i) = sol.x(1:numel(model.rxns));

        if ~taskStructure(i).shouldFail
            taskReport.ok(i,1)=true;
            if printOnlyFailed==false && printOutput==true
                fprintf(['PASS: [' taskStructure(i).id '] ' taskStructure(i).description '\n']);
            end
            %Calculate the essential reactions
            if getEssential==true
                [~, taskEssential]=getEssentialRxns(tModel);
                %This is because there could be more reactions in tModel
                %than in model
                essentialRxns(taskEssential(taskEssential<=numel(model.rxns)),i)=true;
            end
        else
            taskReport.ok(i,1)=false;
            if printOutput==true
                fprintf(['PASS (should fail): [' taskStructure(i).id '] ' taskStructure(i).description '\n']);
            end
        end
    else
        if ~taskStructure(i).shouldFail
            taskReport.ok(i,1)=false;
            if printOutput==true
                fprintf(['FAIL: [' taskStructure(i).id '] ' taskStructure(i).description '\n']);
            end
        else
            taskReport.ok(i,1)=true;
            if printOnlyFailed==false && printOutput==true
                fprintf(['FAIL (should fail): [' taskStructure(i).id '] ' taskStructure(i).description '\n']);
            end
        end
    end
    if taskStructure(i).printFluxes && ~isempty(sol.x)
        sol=solveLP(tModel,1);
        if ~isempty(sol.x)
            printFluxes(tModel,sol.x,false,10^-6,[],'%rxnID (%eqn):%flux\n');
            fprintf('\n');
        end
    end
    tModel=model;
end
end


classdef My_copy_layer < dagnn.ElementWise
  properties
  end

  methods
    function outputs = forward(obj, inputs, params)
        outputs = inputs ;
    end

    function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
        derInputs = derOutputs ;
        derParams = {} ;
    end

    % ---------------------------------------------------------------------
    function obj = DropOut(varargin)
      obj.load(varargin{:}) ;
    end

    function obj = reset(obj)
      reset@dagnn.ElementWise(obj) ;
    end

  end

end


function [ y, ierror ] = y_check_common ( y )

%*****************************************************************************80
%
%% Y_CHECK_COMMON checks a Common year.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 March 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input/output, integer Y, the year, which must not be 0.
%
%    Output, integer IERROR, is 0 if Y is legal, and 1 otherwise.
%
  if ( y ~= 0 )
    ierror = 0;
  else
    ierror = 1;
  end

  return
end


function index = findNameInList(list, name)
%
%
%        index = findNameInList(list, name)
%
%
%       Input:
%           -list: a list of name; i.e. a result of dir call
%           -name: a string
%
%       Output:
%           -index: the index where name is found in list. It is set to -1
%           if not found.
%
%     Copyright (C) 2015  Francesco Banterle
%
%     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/>.
%

index = -1;

for i=1:n
    if(strcmp(name, list(i).name) == 1)
        index = i;
    end
end

end


function [selectionImage, selectionIndexArray, unusedVarargin] = select(this, varargin)
% Prototype for select-method of n-dimensional image data using dimInfo
%
%   Y = MrImage()
%   selectionImage = Y.select('type', 'index'/'label', 'invert', true/false, ...
%              'removeDims', true/false
%               'dimLabel1', arrayIndicesDim1/samplingPointsDim1, ...,
%               ...
%              'dimLabelK', arrayIndicesDimK/samplingPointsDimK, ...)
%
%
% This is a method of class MrImage.
%
% NOTE: Y.select([]) returns a COPY of the current object Y.
%
%   PropertyName/Value pairs
%   General parameters
%   'type'      'index' (default) or 'label'
%               defines how selection elements should be
%               interpreted as array indices or sampling points
%   'invert'    true or false (default)
%               if true, selection is inverted and given arrayIndices are
%               excluded from returned selection, based on
%               dimInfo-information about whole array
%   'removeDims' true or false (default)
%               if true, singleton dimensions (1 or less dimensions) will be removed
%
% OUT
%   selectionIndexArray     indexArray of selected samples in original
%                           dimInfo
%   selectionImage          dimInfo of specified selection, derived as
%                           subset from dimInfo
%   unusedVarargin          if specified, returns all input arguments that
%                           did not match a dimLabel/Value pair of dimInfo
%                           Note: If this output is omitted, select returns
%                           an error for every unknown dimension requested
%
% EXAMPLE
%   select
%
%   See also MrImage MrDimInfo.select

% Author:   Lars Kasper
% Created:  2016-01-31
% Copyright (C) 2016 Institute for Biomedical Engineering
%                    University of Zurich and ETH Zurich
%
% This file is part of the TAPAS UniQC Toolbox, which is released
% under the terms of the GNU General Public License (GPL), version 3.
% You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version).
% For further details, see the file COPYING or
%  <http://www.gnu.org/licenses/>.

returnUnusedVarargin = nargout >=3;
% extract removeDims info
defaults.removeDims = 0;
[args, argsSelect] = tapas_uniqc_propval(varargin, defaults);
tapas_uniqc_strip_fields(args);

if returnUnusedVarargin
    [selectionDimInfo, selectionIndexArray, unusedVarargin] = ...
        this.dimInfo.select(argsSelect{:});
else
    % be strict about wrong varargin, return error for unused select dims
    [selectionDimInfo, selectionIndexArray] = ...
        this.dimInfo.select(argsSelect{:});
end

selectionImage = this.copyobj;
selectionImage.data = selectionImage.data(selectionIndexArray{:});
selectionImage.dimInfo = selectionDimInfo.copyobj();

if removeDims
    selectionImage = selectionImage.remove_dims();
end


function c = subsasgn(c,s,b)
%SUBSASGN     Implements subscripted assignments for long numbers
%
%   example   c(2:3) = b
%

% written  12/30/98     S.M. Rump
% modified 11/11/99     S.M. Rump  precb<=precc
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
% modified 08/26/12     S.M. Rump  global variables removed
%

  INTLAB_LONG_ERROR = getappdata(0,'INTLAB_LONG_ERROR');

  if length(s)>1
    error('multiple indexing for long assignment not allowed')
  end

  if strcmp(s.type,'()')     % assignment c(i) = b
    if isempty(b)
      c.sign(s(1).subs{:}) = [];
      c.exponent(s(1).subs{:}) = [];
      c.mantissa(s(1).subs{:},:) = [];
      if INTLAB_LONG_ERROR
        c.error.mant(s(1).subs{:}) = [];
        c.error.exp(s(1).subs{:}) = [];
      end
      return
    else
      if isa(b,'double')
        b = long(b);
      end
    end
    if isempty(c)
      c.sign = [];
      c.exponent = [];
      c.mantissa = [];
      c.error.mant = [];
      c.error.exp = [];
      c = class(c,'long');
    end
    c.sign(s(1).subs{:},1) = b.sign;
    c.exponent(s(1).subs{:},1) = b.exponent;
    precb = size(b.mantissa,2);
    precc = size(c.mantissa,2);
    if precb<=precc
      c.mantissa(s(1).subs{:},precb+1:end) = 0;
      c.mantissa(s(1).subs{:},1:precb) = b.mantissa;
    else
      c.mantissa(end,precb) = 0;
      c.mantissa(s(1).subs{:},:) = b.mantissa;
    end
    if INTLAB_LONG_ERROR
      c.error.mant(s(1).subs{:},1) = b.error.mant;
      c.error.exp(s(1).subs{:},1) = b.error.exp;
    end
  else
    error('invalid call of subsasgn')
  end


% //This software is licensed under the BSD 3 Clause license: http://opensource.org/licenses/BSD-3-Clause
%
%
% //Copyright (c) 2013, University of Oxford
% //All rights reserved.
%
% //Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
%
% //Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
% //Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
% //Neither the name of the University of Oxford nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
% //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%
%   The method implemented in this file has been patented by their original
%   authors. Commercial use of this code is thus strongly not
%   recocomended.
%
% //Authors: 	Gari D Clifford -
% //            Roberta Colloca -
% //			Julien Oster	-

function [BC,PC,sZ] = BPcount( sZ )

% BPcount counts the number of non empty bins (BC) in the matrix Z and
% the number of {dRR(i),dRR(i-1)} in the same region (PC) and deletes
% the counted points from the matrix Z

%bdc is the BIN diagonal count: number of non empty bins contained in
%the i-th diagonal of Z
bdc=0;
BC=0;
%pdc is the POINTS diagonal count: number of {dRR(i),dRR(i-1)} contained in
%the i-th diagonal of Z
pdc=0;
PC=0;

for i=-2:2
     bdc=sum(diag(sZ,i)~=0);
     pdc=sum(diag(sZ,i));
     BC=BC+bdc;
     PC=PC+pdc;
     sZ=sZ-diag(diag(sZ,i),i);
 end

end


function timelock = fttimelock(this, chanind, timeind, trialind, freqind)
% Method for converting meeg object to Fieldtrip timelock/freq struct
% FORMAT timelock = fttimelock(this, chanind, timeind, trialind, freqind)
%
% The method support both time and TF data and outputs different variants
% of timelock or freq FT struct depending on the dataset type and requested
% data dimensions.
% _______________________________________________________________________
% Copyright (C) 2008-2012 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak
% $Id: fttimelock.m 6158 2014-09-09 12:23:49Z vladimir $

if ~islinked(this)
    error('There is no data linked to the object');
end

if nargin < 2 || ~isnumeric(chanind)
    chanind = 1:nchannels(this);
end

if nargin < 3 || ~isnumeric(timeind)
    timeind = 1:nsamples(this);
end

if nargin < 4 || ~isnumeric(trialind)
    trialind = 1:ntrials(this);
end

if strncmpi(transformtype(this),'TF',2) && ...
        (nargin < 5 || isempty(freqind))
     freqind = 1:nfrequencies(this);
end

timelock             = [];
timelock.label       = chanlabels(this, chanind)';

if isequal(transformtype(this), 'time')
   if isequal(type(this), 'continuous')
            error('For continuous data use ftraw method');
   end

   if isequal(type(this), 'single') || length(trialind)>1
       timelock.dimord  = 'rpt_chan_time';
       timelock.trial   =  permute(subsref(this, substruct('()', {chanind, timeind, trialind})), [3 1 2]);
   else
       timelock.dimord  = 'chan_time';
       timelock.avg     =  spm_squeeze(subsref(this, substruct('()', {chanind, timeind, trialind})), 3);
   end

   timelock.time       = time(this, timeind);

elseif strncmpi(transformtype(this),'TF',2)
    if length(timeind)>1
        if isequal(type(this), 'single') || length(trialind)>1
            timelock.dimord    = 'rpt_chan_freq_time';
            timelock.powspctrm = permute(subsref(this, substruct('()', {chanind, freqind, timeind, trialind})), [4 1 2 3]);
        else
            timelock.dimord     = 'chan_freq_time';
            timelock.powspctrm  =  spm_squeeze(subsref(this, substruct('()', {chanind, freqind, timeind, trialind})), 3);
        end

        timelock.time       = time(this, timeind);
    else
        if isequal(type(this), 'single') || length(trialind)>1
            timelock.dimord    = 'rpt_chan_freq';
            timelock.powspctrm = spm_squeeze(permute(subsref(this, substruct('()', {chanind, freqind, timeind, trialind})), [4 1 2 3]), 4);
        else
            timelock.dimord     = 'chan_freq';
            timelock.powspctrm  =  spm_squeeze(subsref(this, substruct('()', {chanind, freqind, timeind, trialind})), [3 4]);
        end
    end

    timelock.freq      = frequencies(this, freqind);
else
    error('Unknown transform type.');
end

if length(trialind)>1

    clist      =  condlist(this);
    condlabels = conditions(this, trialind);
    timelock.trialinfo = 0*trialind;

    for k = 1:numel(clist)
        fprintf('mapping condition label "%s" to condition code %d\n', clist{k}, k);
        sel = strcmp(clist{k}, condlabels);
        timelock.trialinfo(sel) = k;
    end

end

if ~isempty(sensors(this, 'MEG'))
    timelock.grad = sensors(this, 'MEG');
end

if ~isempty(sensors(this, 'EEG'))
    timelock.elec = sensors(this, 'EEG');
end


function mprob = convBonmin(prob,opts,warn)
%CONVBONMIN Convert OPTI problem to BONMIN Mixed Integer Nonlinear problem
%
%   mprob = convBonmin(prob,opts)

%   Copyright (C) 2011 Jonathan Currie (I2C2)

%COMPATIBLE CPLEX VERSION
CPLEXVER = '12.5.0.0';

%Ensure all args passed
if(nargin < 2)
    error('You must supply both the problem + options');
end
if(~isstruct(prob) || ~isstruct(opts))
    error('Both prob + opts must be structures!');
end

%Ensure we have defaults for bonmin
if(isempty(opts.solverOpts))
    opts.solverOpts = bonminset;
end

%First convert to IPOPT problem (used as the internal relaxed solver)
mprob = convIpopt(prob,opts);
%Remove options from IPOPT structure we don't need
mprob.options.ipopt = rmfield(mprob.options.ipopt,'max_cpu_time'); %don't want this set in the local solver
mprob.options.ipopt = rmfield(mprob.options.ipopt,'print_level'); %don't want this set in the local solver
%Remove options already at OPTI default (appears BONMIN sets some internally different from docs)
mprob.options.ipopt = optiRemoveDefaults(mprob.options.ipopt,ipoptset('bonmin'));

%Set BONMIN options
mprob.options.bonmin = bonminset(opts.solverOpts,'noIpopt'); %this will remove ipopt options from the bonminset structure
%Remove options set elsewhere
mprob.options.bonmin = rmfield(mprob.options.bonmin,'var_lin');
mprob.options.bonmin = rmfield(mprob.options.bonmin,'cons_lin');
%Remove options already at OPTI default (appears BONMIN sets some internally different from docs)
mprob.options.bonmin = optiRemoveDefaults(mprob.options.bonmin,bonminset());

%If user has specified Cplex, ensure we can load it
if(isfield(mprob.options.bonmin,'milp_solver') && strcmpi(mprob.options.bonmin.milp_solver,'cplex'))
    try
        %Forces to load Cplex on current platform (x86 or x64) if MATLAB interface present
        c = Cplex; %#ok<NASGU>
    catch %#ok<CTCH>
       %nothing to do
    end
    try
        %The following will fail with a "cannot load module" if it cannot find correct version of Cplex DLL on user's PC
        v = bonminCplex(); %#ok<NASGU>
    catch %#ok<CTCH>
        if(warn)
            optiwarn('opti:bonmin_Cplex','Could not load BONMIN with CPLEX - ensure CPLEX (v%s) is installed and licensed on your PC. Using CBC for now.',CPLEXVER);
        end
        mprob.options.bonmin = rmfield(mprob.options.bonmin,'milp_solver');
    end
end

%Convert OPTISET options to equivalent BONMIN ones
mprob.options.bonmin.node_limit = opts.maxnodes;
mprob.options.bonmin.time_limit = opts.maxtime;
mprob.options.bonmin.integer_tolerance = opts.tolint;

%Set Display Level
if(strcmpi(opts.display,'iter'))
    mprob.options.display = 1;
else
    mprob.options.display = 0;
end

%Setup Integer Vars
mprob.options.var_type = prob.int.ind; %uses -1, 0, 1 format
%Setup Nonlinear Vars
if(isempty(opts.solverOpts.var_lin) || any(isnan(opts.solverOpts.var_lin)))
    mprob.options.var_lin = zeros(prob.sizes.ndec,1); %for now assuming all nonlinear
else
    varlin = opts.solverOpts.var_lin;
    if(length(varlin) ~= prob.sizes.ndec)
        error('The decision variable linearity vector is the wrong size! Expected %d x 1',prob.sizes.ndec);
    else
        mprob.options.var_lin = varlin;
    end
end
%Setup Nonlinear Constraints Linearity
if(prob.sizes.nrow) %bug fix when bonmin solves with double-sided linear row constraints
    nlincon = prob.sizes.nrow;
else
    nlincon = prob.sizes.nineq + prob.sizes.neq;
end
if(prob.sizes.nnlrow) %bug fix when bonmin solves with double-sided nonlinear row constraints
    nnlcon = prob.sizes.nnlrow + prob.sizes.nqc;
else
    nnlcon = prob.sizes.nnlineq + prob.sizes.nnleq + prob.sizes.nqc;
end
if(isempty(opts.solverOpts.cons_lin) || any(isnan(opts.solverOpts.cons_lin)))
   mprob.options.cons_lin = [zeros(nnlcon,1); ones(nlincon,1)]; %augment both kinds
else
    conslin = opts.solverOpts.cons_lin;
    if(length(conslin) ~= (nlincon+nnlcon))
        error('The constraint linearity vector is the wrong size! Expected %d x 1',nlincon+nnlcon);
    else
        mprob.options.cons_lin = conslin;
    end
end


classdef TestFeatureDetector
    %TestFeatureDetector

    properties (Constant)
        im = fullfile(mexopencv.root(),'test','tsukuba_l.png');
        kfields = {'pt', 'size', 'angle', 'response', 'octave', 'class_id'};
        detectors = { ...
            ... % features2d (opencv)
            'AgastFeatureDetector', 'FastFeatureDetector', ...
            'GFTTDetector', 'SimpleBlobDetector', 'MSER', ...
            'BRISK', 'ORB', 'KAZE', 'AKAZE', ...
            ... % xfeatures2d (opencv_contrib)
            'SIFT', 'SURF', 'StarDetector', 'MSDDetector', ...
            'HarrisLaplaceFeatureDetector'
        };
    end

    methods (Static)
        function test_detect_img
            img = cv.imread(TestFeatureDetector.im, ...
                'Grayscale',true, 'ReduceScale',2);
            for i=1:numel(TestFeatureDetector.detectors)
                try
                    obj = cv.FeatureDetector(TestFeatureDetector.detectors{i});
                catch ME
                    %TODO: check if opencv_contrib/xfeatures2d is available
                    %error('mexopencv:testskip', 'contrib');
                    continue;
                end
                typename = obj.typeid();

                kpts = obj.detect(img);
                validateattributes(kpts, {'struct'}, {'vector'});
                assert(all(ismember(TestFeatureDetector.kfields, ...
                    fieldnames(kpts))));
            end
        end

        function test_detect_imgset
            img = cv.imread(TestFeatureDetector.im, ...
                'Grayscale',true, 'ReduceScale',2);
            imgs = {img, img};
            for i=1:numel(TestFeatureDetector.detectors)
                try
                    obj = cv.FeatureDetector(TestFeatureDetector.detectors{i});
                catch ME
                    %TODO: check if opencv_contrib/xfeatures2d is available
                    %error('mexopencv:testskip', 'contrib');
                    continue;
                end

                kpts = obj.detect(imgs);
                validateattributes(kpts, {'cell'}, ...
                    {'vector', 'numel',numel(imgs)});
                cellfun(@(kpt) validateattributes(kpt, ...
                    {'struct'}, {'vector'}), kpts);
                cellfun(@(kpt) assert(all(ismember(...
                    TestFeatureDetector.kfields, fieldnames(kpt)))), kpts);
            end
        end

        function test_detect_mask
            img = imread(TestFeatureDetector.im);
            mask = zeros(size(img), 'uint8');
            mask(:,1:end/2) = 255;  % only search left half of the image

            for i=1:numel(TestFeatureDetector.detectors)
                try
                    obj = cv.FeatureDetector(TestFeatureDetector.detectors{i});
                catch ME
                    %TODO: check if opencv_contrib/xfeatures2d is available
                    %error('mexopencv:testskip', 'contrib');
                    continue;
                end

                kpts = obj.detect(img, 'Mask',mask);
                validateattributes(kpts, {'struct'}, {'vector'});
                assert(all(ismember(TestFeatureDetector.kfields, ...
                    fieldnames(kpts))));
                xy = cat(1, kpts.pt);
                assert(all(xy(:,1) <= ceil(size(img,2)/2)));
            end
        end
    end

end


function y = base64encode(x, eol)
%BASE64ENCODE Perform base64 encoding on a string.
%
%   BASE64ENCODE(STR, EOL) encode the given string STR.  EOL is the line ending
%   sequence to use; it is optional and defaults to '\n' (ASCII decimal 10).
%   The returned encoded string is broken into lines of no more than 76
%   characters each, and each line will end with EOL unless it is empty.  Let
%   EOL be empty if you do not want the encoded string broken into lines.
%
%   STR and EOL don't have to be strings (i.e., char arrays).  The only
%   requirement is that they are vectors containing values in the range 0-255.
%
%   This function may be used to encode strings into the Base64 encoding
%   specified in RFC 2045 - MIME (Multipurpose Internet Mail Extensions).  The
%   Base64 encoding is designed to represent arbitrary sequences of octets in a
%   form that need not be humanly readable.  A 65-character subset
%   ([A-Za-z0-9+/=]) of US-ASCII is used, enabling 6 bits to be represented per
%   printable character.
%
%   Examples
%   --------
%
%   If you want to encode a large file, you should encode it in chunks that are
%   a multiple of 57 bytes.  This ensures that the base64 lines line up and
%   that you do not end up with padding in the middle.  57 bytes of data fills
%   one complete base64 line (76 == 57*4/3):
%
%   If ifid and ofid are two file identifiers opened for reading and writing,
%   respectively, then you can base64 encode the data with
%
%      while ~feof(ifid)
%         fwrite(ofid, base64encode(fread(ifid, 60*57)));
%      end
%
%   or, if you have enough memory,
%
%      fwrite(ofid, base64encode(fread(ifid)));
%
%   See also BASE64DECODE.

%   Author:      Peter John Acklam
%   Time-stamp:  2004-02-03 21:36:56 +0100
%   E-mail:      pjacklam@online.no
%   URL:         http://home.online.no/~pjacklam

   % check number of input arguments
   error(nargchk(1, 2, nargin));

   % make sure we have the EOL value
   if nargin < 2
      eol = sprintf('\n');
   else
      if sum(size(eol) > 1) > 1
         error('EOL must be a vector.');
      end
      if any(eol(:) > 255)
         error('EOL can not contain values larger than 255.');
      end
   end

   if sum(size(x) > 1) > 1
      error('STR must be a vector.');
   end

   x   = uint8(x);
   eol = uint8(eol);

   ndbytes = length(x);                 % number of decoded bytes
   nchunks = ceil(ndbytes / 3);         % number of chunks/groups
   nebytes = 4 * nchunks;               % number of encoded bytes

   % add padding if necessary, to make the length of x a multiple of 3
   if rem(ndbytes, 3)
      x(end+1 : 3*nchunks) = 0;
   end

   x = reshape(x, [3, nchunks]);        % reshape the data
   y = repmat(uint8(0), 4, nchunks);    % for the encoded data

   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % Split up every 3 bytes into 4 pieces
   %
   %    aaaaaabb bbbbcccc ccdddddd
   %
   % to form
   %
   %    00aaaaaa 00bbbbbb 00cccccc 00dddddd
   %
   y(1,:) = bitshift(x(1,:), -2);                  % 6 highest bits of x(1,:)

   y(2,:) = bitshift(bitand(x(1,:), 3), 4);        % 2 lowest bits of x(1,:)
   y(2,:) = bitor(y(2,:), bitshift(x(2,:), -4));   % 4 highest bits of x(2,:)

   y(3,:) = bitshift(bitand(x(2,:), 15), 2);       % 4 lowest bits of x(2,:)
   y(3,:) = bitor(y(3,:), bitshift(x(3,:), -6));   % 2 highest bits of x(3,:)

   y(4,:) = bitand(x(3,:), 63);                    % 6 lowest bits of x(3,:)

   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % Now perform the following mapping
   %
   %   0  - 25  ->  A-Z
   %   26 - 51  ->  a-z
   %   52 - 61  ->  0-9
   %   62       ->  +
   %   63       ->  /
   %
   % We could use a mapping vector like
   %
   %   ['A':'Z', 'a':'z', '0':'9', '+/']
   %
   % but that would require an index vector of class double.
   %
   z = repmat(uint8(0), size(y));
   i =           y <= 25;  z(i) = 'A'      + double(y(i));
   i = 26 <= y & y <= 51;  z(i) = 'a' - 26 + double(y(i));
   i = 52 <= y & y <= 61;  z(i) = '0' - 52 + double(y(i));
   i =           y == 62;  z(i) = '+';
   i =           y == 63;  z(i) = '/';
   y = z;

   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   % Add padding if necessary.
   %
   npbytes = 3 * nchunks - ndbytes;     % number of padding bytes
   if npbytes
      y(end-npbytes+1 : end) = '=';     % '=' is used for padding
   end

   if isempty(eol)

      % reshape to a row vector
      y = reshape(y, [1, nebytes]);

   else

      nlines = ceil(nebytes / 76);      % number of lines
      neolbytes = length(eol);          % number of bytes in eol string

      % pad data so it becomes a multiple of 76 elements
      y(nebytes + 1 : 76 * nlines) = 0;
      y = reshape(y, 76, nlines);

      % insert eol strings
      eol = eol(:);
      y(end + 1 : end + neolbytes, :) = eol(:, ones(1, nlines));

      % remove padding, but keep the last eol string
      m = nebytes + neolbytes * (nlines - 1);
      n = (76+neolbytes)*nlines - neolbytes;
      y(m+1 : n) = '';

      % extract and reshape to row vector
      y = reshape(y, 1, m+neolbytes);

   end

   % output is a character array
   y = char(y);


function val = get_params(CPD, name)
% GET_PARAMS Get the parameters (fields) for a tabular_CPD object
% val = get_params(CPD, name)
%
% The following fields can be accessed
%
% cpt       - the CPT
%
% e.g., CPT = get_params(CPD, 'cpt')

switch name
 case 'cpt',      val = CPD.CPT;
 case 'tree',     val = CPD.tree;
 otherwise,
  error(['invalid argument name ' name]);
end


function x = r8mat_read_bin ( input_filename, m, n )

%*****************************************************************************80
%
%% R8MAT_READ_BIN reads an R8MAT from a binary file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 August 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the input filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of data items.
%
%    Output, real X(M,N), the data.
%
  input_unit = fopen ( input_filename, 'rb' );

  x = fread ( input_unit, [ m, n ], 'double' );

  fclose ( input_unit );

  return
end


function objNew = copy(obj)
% COPY Create an indipendent copy of a point cloud object.
% ------------------------------------------------------------------------------
% DESCRIPTION/NOTES
% The pointCloud class is a subclass of the handle class, i.e. it is NOT a value
% class. More informations about the difference between handle and value classes
% can be found in [1]. To create an indipendent copy of a point cloud object,
% this method can be used.
% ------------------------------------------------------------------------------
% OUTPUT
% 1 [objNew]
%   Copy of point cloud object.
% ------------------------------------------------------------------------------
% EXAMPLES
% 1 Copy an object and select a subset of points in the new object.
%   pcOrig = pointCloud('Lion.xyz');
%   pcCopy = pcOrig.copy;
%   % Attention: if instead of the previous line 'pcCopy = pcOrig;' is used,
%   % pcOrig and pcCopy share the same object, i.e. they are NOT indipendent.
%   pcOrig.select('RandomSampling', 10); % select a subset of points in pcOrig
%   pcOrig.info; % in pcOrig only a subset of points is selected
%   pcCopy.info; % in pcCopy still all points are selected
% ------------------------------------------------------------------------------
% REFERENCES
% [1] % https://de.mathworks.com/help/matlab/matlab_oop/comparing-handle-and-value-classes.html
% ------------------------------------------------------------------------------
% philipp.glira@gmail.com
% ------------------------------------------------------------------------------

% Reference: https://de.mathworks.com/matlabcentral/newsreader/view_thread/257925

% Start ------------------------------------------------------------------------

procHierarchy = {'POINTCLOUD' 'COPY'};
msg('S', procHierarchy);
msg('I', procHierarchy, sprintf('Point cloud label = ''%s''', obj.label));

% Copy -------------------------------------------------------------------------

% Deactivate logging
originalLogLevel = msg('O', 'GetLogLevel');
msg('O', 'SetLogLevel', 'off');

% Instantiate new object of the same class
objNew = feval(class(obj), obj.X);

% Copy all non-hidden properties
p = properties(obj);
for i = 1:length(p)
    if ~any(strcmp(p{i}, {'cog' 'lim' 'noPoints'}))
        objNew.(p{i}) = obj.(p{i});
    end
end

% Reactivate logging
msg('O', 'SetLogLevel', originalLogLevel);

% End --------------------------------------------------------------------------

msg('E', procHierarchy);

end


%INVSIG The inverse sigmoid of a dataset


function match(audio_file, gyro_rec, gyro_fs)
    % gyro_fs - Gyro sampling frequency

    % plot_spectrums(gyro_rec, GYRO_FS);

    [audio_samples, audio_fs] = audioread(audio_file);
    [gyro_timestamps, gyro_samples] = read_samples_file(gyro_rec);

    match_samples(audio_samples, audio_fs, gyro_samples, gyro_fs);
end


%--- help for set_simulation_initial_conditions ---
%
%  Set the initial conditions for forecasting, simulation and irfs
%
%  ::
%
%    Initcond=set_simulation_initial_conditions(obj)
%
%  Args:
%
%     obj (rise | dsge | svar | rfvar): model object
%
%  Returns:
%     :
%
%     - **Initcond** [struct]: Initial conditions for simulation
%
%  Note:
%
%     - if future values of endogenous are found, they are discarded the
%       variables are not explicitly declared as conditioning endogenous
%       variables.
%
%     - if either endogenous or exogenous variables are declared as
%       conditioning variables, we automatically have a conditional forecasting
%       exercise.
%
%     - if no variable is declared as conditioning, we have a simulation
%       exercise, in which case, there is a burn-in period.
%
%     - Initialization is always done at the steady state and the declared
%       endogenous variables merely override the steady state values. This means
%       that if a variable is not found in the database, it is initialized at its
%       steady state.
%
%  Example:
%
%  See also:
%


f{1}=dir('*.m')
f{2}=dir('visim/*.m')

fid=fopen('segymat-functions.xml','w');

fprintf(fid,'<sect1 id=\"%s\"><title>%s</title>\n','reference','M-file Reference');
for ff=1:length(f)

     for i=1:length(f{ff})
     [p,name,ext]=fileparts(f{ff}(i).name);
     disp(name)
     h=help(name);

     fprintf(fid,'<sect2 id=\"%s\"><title>%s</title>\n',['_',name],name);
     fprintf(fid,'<para><programlisting><![CDATA[%s]]></programlisting></para>\n',h);
     fprintf(fid,'</sect2>\n\n');

     end

end
fprintf(fid,'</sect1>');

fclose(fid);


function [net, stats] = cnn_train(net, imdb, getBatch, varargin)
%CNN_TRAIN  An example implementation of SGD for training CNNs
%    CNN_TRAIN() is an example learner implementing stochastic
%    gradient descent with momentum to train a CNN. It can be used
%    with different datasets and tasks by providing a suitable
%    getBatch function.
%
%    The function automatically restarts after each training epoch by
%    checkpointing.
%
%    The function supports training on CPU or on one or more GPUs
%    (specify the list of GPU IDs in the `gpus` option).

% Copyright (C) 2014-16 Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

opts.expDir = fullfile('data','exp') ;
opts.continue = true ;
opts.batchSize = 256 ;
opts.numSubBatches = 1 ;
opts.train = [] ;
opts.val = [] ;
opts.gpus = [] ;
opts.prefetch = false ;
opts.numEpochs = 300 ;
opts.learningRate = 0.001 ;
opts.weightDecay = 0.0005 ;
opts.momentum = 0.9 ;
opts.saveMomentum = true ;
opts.nesterovUpdate = false ;
opts.randomSeed = 0 ;
opts.memoryMapFile = fullfile(tempdir, 'matconvnet.bin') ;
opts.profile = false ;
opts.parameterServer.method = 'mmap' ;
opts.parameterServer.prefix = 'mcn' ;

opts.conserveMemory = true ;
opts.backPropDepth = +inf ;
opts.sync = false ;
opts.cudnn = true ;
opts.errorFunction = 'multiclass' ;
opts.errorLabels = {} ;
opts.plotDiagnostics = false ;
opts.plotStatistics = true;
opts = vl_argparse(opts, varargin) ;

if ~exist(opts.expDir, 'dir'), mkdir(opts.expDir) ; end
if isempty(opts.train), opts.train = find(imdb.images.set==1) ; end
if isempty(opts.val), opts.val = find(imdb.images.set==2) ; end
if isnan(opts.train), opts.train = [] ; end
if isnan(opts.val), opts.val = [] ; end

% -------------------------------------------------------------------------
%                                                            Initialization
% -------------------------------------------------------------------------

net = vl_simplenn_tidy(net); % fill in some eventually missing values
net.layers{end-1}.precious = 1; % do not remove predictions, used for error
vl_simplenn_display(net, 'batchSize', opts.batchSize) ;

evaluateMode = isempty(opts.train) ;
if ~evaluateMode
  for i=1:numel(net.layers)
    J = numel(net.layers{i}.weights) ;
    if ~isfield(net.layers{i}, 'learningRate')
      net.layers{i}.learningRate = ones(1, J) ;
    end
    if ~isfield(net.layers{i}, 'weightDecay')
      net.layers{i}.weightDecay = ones(1, J) ;
    end
  end
end

% setup error calculation function
hasError = true ;
if isstr(opts.errorFunction)
  switch opts.errorFunction
    case 'none'
      opts.errorFunction = @error_none ;
      hasError = false ;
    case 'multiclass'
      opts.errorFunction = @error_multiclass ;
      if isempty(opts.errorLabels), opts.errorLabels = {'top1err', 'top5err'} ; end
    case 'binary'
      opts.errorFunction = @error_binary ;
      if isempty(opts.errorLabels), opts.errorLabels = {'binerr'} ; end
    otherwise
      error('Unknown error function ''%s''.', opts.errorFunction) ;
  end
end

state.getBatch = getBatch ;
stats = [] ;

% -------------------------------------------------------------------------
%                                                        Train and validate
% -------------------------------------------------------------------------

modelPath = @(ep) fullfile(opts.expDir, sprintf('net-epoch-%d.mat', ep));
modelFigPath = fullfile(opts.expDir, 'net-train.pdf') ;

start = opts.continue * findLastCheckpoint(opts.expDir) ;
if start >= 1
  fprintf('%s: resuming by loading epoch %d\n', mfilename, start) ;
  [net, state, stats] = loadState(modelPath(start)) ;
else
  state = [] ;
end

for epoch=start+1:opts.numEpochs

  % Set the random seed based on the epoch and opts.randomSeed.
  % This is important for reproducibility, including when training
  % is restarted from a checkpoint.

  rng(epoch + opts.randomSeed) ;
  prepareGPUs(opts, epoch == start+1) ;

  % Train for one epoch.
  params = opts ;
  params.epoch = epoch ;
  params.learningRate = opts.learningRate(min(epoch, numel(opts.learningRate))) ;
  params.train = opts.train(randperm(numel(opts.train))) ; % shuffle
  params.val = opts.val(randperm(numel(opts.val))) ;
  params.imdb = imdb ;
  params.getBatch = getBatch ;

  if numel(params.gpus) <= 1
    [net, state] = processEpoch(net, state, params, 'train') ;
    [net, state] = processEpoch(net, state, params, 'val') ;
    if ~evaluateMode
      saveState(modelPath(epoch), net, state) ;
    end
    lastStats = state.stats ;
  else
    spmd
      [net, state] = processEpoch(net, state, params, 'train') ;
      [net, state] = processEpoch(net, state, params, 'val') ;
      if labindex == 1 && ~evaluateMode
        saveState(modelPath(epoch), net, state) ;
      end
      lastStats = state.stats ;
    end
    lastStats = accumulateStats(lastStats) ;
  end

  stats.train(epoch) = lastStats.train ;
  stats.val(epoch) = lastStats.val ;
  clear lastStats ;
  saveStats(modelPath(epoch), stats) ;

  if params.plotStatistics
    switchFigure(1) ; clf ;
    plots = setdiff(...
      cat(2,...
      fieldnames(stats.train)', ...
      fieldnames(stats.val)'), {'num', 'time'}) ;
    for p = plots
      p = char(p) ;
      values = zeros(0, epoch) ;
      leg = {} ;
      for f = {'train', 'val'}
        f = char(f) ;
        if isfield(stats.(f), p)
          tmp = [stats.(f).(p)] ;
          values(end+1,:) = tmp(1,:)' ;
          leg{end+1} = f ;
        end
      end
      subplot(1,numel(plots),find(strcmp(p,plots))) ;
      plot(1:epoch, values','o-') ;
      xlabel('epoch') ;
      title(p) ;
      legend(leg{:}) ;
      grid on ;
    end
    drawnow ;
    print(1, modelFigPath, '-dpdf') ;
  end
end

% With multiple GPUs, return one copy
if isa(net, 'Composite'), net = net{1} ; end

% -------------------------------------------------------------------------
function err = error_multiclass(params, labels, res)
% -------------------------------------------------------------------------
predictions = gather(res(end-1).x) ;
[~,predictions] = sort(predictions, 3, 'descend') ;

% be resilient to badly formatted labels
if numel(labels) == size(predictions, 4)
  labels = reshape(labels,1,1,1,[]) ;
end

% skip null labels
mass = single(labels(:,:,1,:) > 0) ;
if size(labels,3) == 2
  % if there is a second channel in labels, used it as weights
  mass = mass .* labels(:,:,2,:) ;
  labels(:,:,2,:) = [] ;
end

m = min(5, size(predictions,3)) ;

error = ~bsxfun(@eq, predictions, labels) ;
err(1,1) = sum(sum(sum(mass .* error(:,:,1,:)))) ;
err(2,1) = sum(sum(sum(mass .* min(error(:,:,1:m,:),[],3)))) ;

% -------------------------------------------------------------------------
function err = error_binary(params, labels, res)
% -------------------------------------------------------------------------
predictions = gather(res(end-1).x) ;
error = bsxfun(@times, predictions, labels) < 0 ;
err = sum(error(:)) ;

% -------------------------------------------------------------------------
function err = error_none(params, labels, res)
% -------------------------------------------------------------------------
err = zeros(0,1) ;

% -------------------------------------------------------------------------
function [net, state] = processEpoch(net, state, params, mode)
% -------------------------------------------------------------------------
% Note that net is not strictly needed as an output argument as net
% is a handle class. However, this fixes some aliasing issue in the
% spmd caller.

% initialize with momentum 0
if isempty(state) || isempty(state.momentum)
  for i = 1:numel(net.layers)
    for j = 1:numel(net.layers{i}.weights)
      state.momentum{i}{j} = 0 ;
    end
  end
end

% move CNN  to GPU as needed
numGpus = numel(params.gpus) ;
if numGpus >= 1
  net = vl_simplenn_move(net, 'gpu') ;
  for i = 1:numel(state.momentum)
    for j = 1:numel(state.momentum{i})
      state.momentum{i}{j} = gpuArray(state.momentum{i}{j}) ;
    end
  end
end
if numGpus > 1
  parserv = ParameterServer(params.parameterServer) ;
  vl_simplenn_start_parserv(net, parserv) ;
else
  parserv = [] ;
end

% profile
if params.profile
  if numGpus <= 1
    profile clear ;
    profile on ;
  else
    mpiprofile reset ;
    mpiprofile on ;
  end
end

subset = params.(mode) ;
num = 0 ;
stats.num = 0 ; % return something even if subset = []
stats.time = 0 ;
adjustTime = 0 ;
res = [] ;
error = [] ;

start = tic ;
for t=1:params.batchSize:numel(subset)
  fprintf('%s: epoch %02d: %3d/%3d:', mode, params.epoch, ...
          fix((t-1)/params.batchSize)+1, ceil(numel(subset)/params.batchSize)) ;
  batchSize = min(params.batchSize, numel(subset) - t + 1) ;

  for s=1:params.numSubBatches
    % get this image batch and prefetch the next
    batchStart = t + (labindex-1) + (s-1) * numlabs ;
    batchEnd = min(t+params.batchSize-1, numel(subset)) ;
    batch = subset(batchStart : params.numSubBatches * numlabs : batchEnd) ;
    num = num + numel(batch) ;
    if numel(batch) == 0, continue ; end

    [im, labels] = params.getBatch(params.imdb, batch) ;

    if params.prefetch
      if s == params.numSubBatches
        batchStart = t + (labindex-1) + params.batchSize ;
        batchEnd = min(t+2*params.batchSize-1, numel(subset)) ;
      else
        batchStart = batchStart + numlabs ;
      end
      nextBatch = subset(batchStart : params.numSubBatches * numlabs : batchEnd) ;
      params.getBatch(params.imdb, nextBatch) ;
    end

    if numGpus >= 1
      im = gpuArray(im) ;
    end

    if strcmp(mode, 'train')
      dzdy = 1 ;
      evalMode = 'normal' ;
    else
      dzdy = [] ;
      evalMode = 'test' ;
    end
    net.layers{end}.class = labels ;
    res = vl_simplenn(net, im, dzdy, res, ...
                      'accumulate', s ~= 1, ...
                      'mode', evalMode, ...
                      'conserveMemory', params.conserveMemory, ...
                      'backPropDepth', params.backPropDepth, ...
                      'sync', params.sync, ...
                      'cudnn', params.cudnn, ...
                      'parameterServer', parserv, ...
                      'holdOn', s < params.numSubBatches) ;

    % accumulate errors
    error = sum([error, [...
      sum(double(gather(res(end).x))) ;
      reshape(params.errorFunction(params, labels, res),[],1) ; ]],2) ;
  end

  % accumulate gradient
  if strcmp(mode, 'train')
    if ~isempty(parserv), parserv.sync() ; end
    [net, res, state] = accumulateGradients(net, res, state, params, batchSize, parserv) ;
  end

  % get statistics
  time = toc(start) + adjustTime ;
  batchTime = time - stats.time ;
  stats = extractStats(net, params, error / num) ;
  stats.num = num ;
  stats.time = time ;
  currentSpeed = batchSize / batchTime ;
  averageSpeed = (t + batchSize - 1) / time ;
  if t == 3*params.batchSize + 1
    % compensate for the first three iterations, which are outliers
    adjustTime = 4*batchTime - time ;
    stats.time = time + adjustTime ;
  end

  fprintf(' %.1f (%.1f) Hz', averageSpeed, currentSpeed) ;
  for f = setdiff(fieldnames(stats)', {'num', 'time'})
    f = char(f) ;
    fprintf(' %s: %.3f', f, stats.(f)) ;
  end
  fprintf('\n') ;

  % collect diagnostic statistics
  if strcmp(mode, 'train') && params.plotDiagnostics
    switchFigure(2) ; clf ;
    diagn = [res.stats] ;
    diagnvar = horzcat(diagn.variation) ;
    diagnpow = horzcat(diagn.power) ;
    subplot(2,2,1) ; barh(diagnvar) ;
    set(gca,'TickLabelInterpreter', 'none', ...
      'YTick', 1:numel(diagnvar), ...
      'YTickLabel',horzcat(diagn.label), ...
      'YDir', 'reverse', ...
      'XScale', 'log', ...
      'XLim', [1e-5 1], ...
      'XTick', 10.^(-5:1)) ;
    grid on ;
    subplot(2,2,2) ; barh(sqrt(diagnpow)) ;
    set(gca,'TickLabelInterpreter', 'none', ...
      'YTick', 1:numel(diagnpow), ...
      'YTickLabel',{diagn.powerLabel}, ...
      'YDir', 'reverse', ...
      'XScale', 'log', ...
      'XLim', [1e-5 1e5], ...
      'XTick', 10.^(-5:5)) ;
    grid on ;
    subplot(2,2,3); plot(squeeze(res(end-1).x)) ;
    drawnow ;
  end
end

% Save back to state.
state.stats.(mode) = stats ;
if params.profile
  if numGpus <= 1
    state.prof.(mode) = profile('info') ;
    profile off ;
  else
    state.prof.(mode) = mpiprofile('info');
    mpiprofile off ;
  end
end
if ~params.saveMomentum
  state.momentum = [] ;
else
  for i = 1:numel(state.momentum)
    for j = 1:numel(state.momentum{i})
      state.momentum{i}{j} = gather(state.momentum{i}{j}) ;
    end
  end
end

net = vl_simplenn_move(net, 'cpu') ;

% -------------------------------------------------------------------------
function [net, res, state] = accumulateGradients(net, res, state, params, batchSize, parserv)
% -------------------------------------------------------------------------
numGpus = numel(params.gpus) ;
otherGpus = setdiff(1:numGpus, labindex) ;

for l=numel(net.layers):-1:1
  for j=numel(res(l).dzdw):-1:1

    if ~isempty(parserv)
      tag = sprintf('l%d_%d',l,j) ;
      parDer = parserv.pull(tag) ;
    else
      parDer = res(l).dzdw{j}  ;
    end

    if j == 3 && strcmp(net.layers{l}.type, 'bnorm')
      % special case for learning bnorm moments
      thisLR = net.layers{l}.learningRate(j) ;
      net.layers{l}.weights{j} = vl_taccum(...
        1 - thisLR, ...
        net.layers{l}.weights{j}, ...
        thisLR / batchSize, ...
        parDer) ;
    else
      % Standard gradient training.
      thisDecay = params.weightDecay * net.layers{l}.weightDecay(j) ;
      thisLR = params.learningRate * net.layers{l}.learningRate(j) ;

      if thisLR>0 || thisDecay>0
        % Normalize gradient and incorporate weight decay.
        parDer = vl_taccum(1/batchSize, parDer, ...
                           thisDecay, net.layers{l}.weights{j}) ;

        % Update momentum.
        state.momentum{l}{j} = vl_taccum(...
          params.momentum, state.momentum{l}{j}, ...
          -1, parDer) ;

        % Nesterov update (aka one step ahead).
        if params.nesterovUpdate
          delta = vl_taccum(...
            params.momentum, state.momentum{l}{j}, ...
            -1, parDer) ;
        else
          delta = state.momentum{l}{j} ;
        end

        % Update parameters.
        net.layers{l}.weights{j} = vl_taccum(...
          1, net.layers{l}.weights{j}, ...
          thisLR, delta) ;
      end
    end

    % if requested, collect some useful stats for debugging
    if params.plotDiagnostics
      variation = [] ;
      label = '' ;
      switch net.layers{l}.type
        case {'conv','convt'}
          variation = thisLR * mean(abs(state.momentum{l}{j}(:))) ;
          power = mean(res(l+1).x(:).^2) ;
          if j == 1 % fiters
            base = mean(net.layers{l}.weights{j}(:).^2) ;
            label = 'filters' ;
          else % biases
            base = sqrt(power) ;%mean(abs(res(l+1).x(:))) ;
            label = 'biases' ;
          end
          variation = variation / base ;
          label = sprintf('%s_%s', net.layers{l}.name, label) ;
      end
      res(l).stats.variation(j) = variation ;
      res(l).stats.power = power ;
      res(l).stats.powerLabel = net.layers{l}.name ;
      res(l).stats.label{j} = label ;
    end
  end
end

% -------------------------------------------------------------------------
function stats = accumulateStats(stats_)
% -------------------------------------------------------------------------

for s = {'train', 'val'}
  s = char(s) ;
  total = 0 ;

  % initialize stats stucture with same fields and same order as
  % stats_{1}
  stats__ = stats_{1} ;
  names = fieldnames(stats__.(s))' ;
  values = zeros(1, numel(names)) ;
  fields = cat(1, names, num2cell(values)) ;
  stats.(s) = struct(fields{:}) ;

  for g = 1:numel(stats_)
    stats__ = stats_{g} ;
    num__ = stats__.(s).num ;
    total = total + num__ ;

    for f = setdiff(fieldnames(stats__.(s))', 'num')
      f = char(f) ;
      stats.(s).(f) = stats.(s).(f) + stats__.(s).(f) * num__ ;

      if g == numel(stats_)
        stats.(s).(f) = stats.(s).(f) / total ;
      end
    end
  end
  stats.(s).num = total ;
end

% -------------------------------------------------------------------------
function stats = extractStats(net, params, errors)
% -------------------------------------------------------------------------
stats.objective = errors(1) ;
for i = 1:numel(params.errorLabels)
  stats.(params.errorLabels{i}) = errors(i+1) ;
end

% -------------------------------------------------------------------------
function saveState(fileName, net, state)
% -------------------------------------------------------------------------
save(fileName, 'net', 'state') ;

% -------------------------------------------------------------------------
function saveStats(fileName, stats)
% -------------------------------------------------------------------------
if exist(fileName)
  save(fileName, 'stats', '-append') ;
else
  save(fileName, 'stats') ;
end

% -------------------------------------------------------------------------
function [net, state, stats] = loadState(fileName)
% -------------------------------------------------------------------------
load(fileName, 'net', 'state', 'stats') ;
net = vl_simplenn_tidy(net) ;
if isempty(whos('stats'))
  error('Epoch ''%s'' was only partially saved. Delete this file and try again.', ...
        fileName) ;
end

% -------------------------------------------------------------------------
function epoch = findLastCheckpoint(modelDir)
% -------------------------------------------------------------------------
list = dir(fullfile(modelDir, 'net-epoch-*.mat')) ;
tokens = regexp({list.name}, 'net-epoch-([\d]+).mat', 'tokens') ;
epoch = cellfun(@(x) sscanf(x{1}{1}, '%d'), tokens) ;
epoch = max([epoch 0]) ;

% -------------------------------------------------------------------------
function switchFigure(n)
% -------------------------------------------------------------------------
if get(0,'CurrentFigure') ~= n
  try
    set(0,'CurrentFigure',n) ;
  catch
    figure(n) ;
  end
end

% -------------------------------------------------------------------------
function clearMex()
% -------------------------------------------------------------------------
%clear vl_tmove vl_imreadjpeg ;
disp('Clearing mex files') ;
clear mex ;
clear vl_tmove vl_imreadjpeg ;

% -------------------------------------------------------------------------
function prepareGPUs(params, cold)
% -------------------------------------------------------------------------
numGpus = numel(params.gpus) ;
if numGpus > 1
  % check parallel pool integrity as it could have timed out
  pool = gcp('nocreate') ;
  if ~isempty(pool) && pool.NumWorkers ~= numGpus
    delete(pool) ;
  end
  pool = gcp('nocreate') ;
  if isempty(pool)
    parpool('local', numGpus) ;
    cold = true ;
  end
end
if numGpus >= 1 && cold
  fprintf('%s: resetting GPU\n', mfilename) ;
  clearMex() ;
  if numGpus == 1
    disp(gpuDevice(params.gpus)) ;
  else
    spmd
      clearMex() ;
      disp(gpuDevice(params.gpus(labindex))) ;
    end
  end
end


% UMD_SRC Creates a source for the UMD Texture dataset
%
% Usage
%    src = UMD_SRC(directory)
%
% Input
%    directory: The directory containing the UMD Texture dataset.
%
% Output
%    src: The UMD source.
%

function src = umd_src(directory)
	if (nargin<1)
		directory = '/Users/laurentsifre/TooBigForDropbox/Databases/umd';
	end
	src = create_src(directory, @uiuc_extract_objects_fun);
end

function [objects, classes] = uiuc_extract_objects_fun(file)
	objects.u1 = [1, 1];
	objects.u2 = [960, 1280];
	path_str = fileparts(file);
	path_parts = regexp(path_str, filesep, 'split');
	classes = {path_parts{end}};
end


% function output = test_add_overlay(input)
% Test image overlay creation and plotting of 3D-RGB-image via montage
%
%   output = test_add_overlay(input)
%
% IN
%
% OUT
%
% EXAMPLE
%   test_add_overlay
%
%   See also tapas_uniqc_add_overlay

% Author:   Saskia Bollmann & Lars Kasper
% Created:  2014-11-25
% Copyright (C) 2014 Institute for Biomedical Engineering
%                    University of Zurich and ETH Zurich
%
% This file is part of the TAPAS UniQC Toolbox, which is released
% under the terms of the GNU General Public Licence (GPL), version 3.
% You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version).
% For further details, see the file COPYING or
%  <http://www.gnu.org/licenses/>.

clear;
close all;
clc;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Load example data
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

pathExamples    = tapas_uniqc_get_path('examples');
fileTest        = fullfile(pathExamples, 'nifti', 'rest', 'meanfmri.nii');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Create Example overlay
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

X               = MrImage(fileTest);
edgeX           = edge(X);

imageMatrix     = X.data;
overlayMatrix   = edgeX.data;

rgbMatrix       = tapas_uniqc_add_overlay(imageMatrix, overlayMatrix, 'jet');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Plot resulting overlay via montage
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

X.plot('overlayImages', edgeX)

stringTitle = 'imageMatrix';
figure('Name', stringTitle);
montage(permute(imageMatrix, [1 2 4 3]), 'DisplayRange', []);
title(tapas_uniqc_str2label(stringTitle));

stringTitle = 'overlayMatrix';
figure('Name', stringTitle);
montage(permute(overlayMatrix, [1 2 4 3]), 'DisplayRange', []);
title(tapas_uniqc_str2label(stringTitle));
colormap hot;

stringTitle = 'test_add_overlay Montage Image';
figure('Name', stringTitle);
montage(rgbMatrix, 'DisplayRange', []);
title(tapas_uniqc_str2label(stringTitle));


function test_pull360

% MEM 2gb
% WALLTIME 00:10:00
% DEPENDENCY

mri				= ft_read_mri('single_subj_T1_1mm.nii', 'datatype', 'nifti');
mri.transform	= [-1,0,0,95.7;0,1,0,-122.5;0,0,1,-132.5;0,0,0,1]; % this will require intervention by getinside in ft_prepare_headmodels

cfg                         = [];
cfg.mri                     = mri;
cfg.sourcemodel.resolution         = 10;       % in mm
cfg.sourcemodel.unit               = 'mm';
ft_prepare_sourcemodel(cfg);


function draw_API = defaultCircle(h_group)
%
%       DRAW_API.setColor
%       DRAW_API.updateView
%       DRAW_API.getBoundingBox
%

  % initialize variables needing function scope
  bounding_box = [];
  %h_axes = iptancestor(h_group,'axes');

  % The line objects should have a width of one screen pixel.
  line_width = ceil(getPointsPerScreenPixel);
  h_circle  = rectangle(...
                        'Curvature', [1,1],...
                        'LineWidth', line_width,...
                        'faceColor', 'none',...
                        'Hittest', 'off',...
                        'Parent', h_group);
  h_patch   = patch('FaceColor', 'none', 'EdgeColor', 'none', ...
                    'HitTest', 'off', ...
                    'Parent', h_group);

  draw_API.setColor         = @setColor;
  draw_API.updateView       = @updateView;
  draw_API.getBoundingBox   = @getBoundingBox;

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function pos = getBoundingBox
    pos = bounding_box;
  end
  %--------------------------------------------------------------------------

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function updateView(cen, r)

    if ~ishandle(h_group)
        return;
    end

    new_pos = [cen(1) - r, cen(2) - r, r+r, r+r];
    if ( ~isequal(new_pos, get(h_circle, 'Position')) )
      set(h_circle, 'Position', new_pos);
      xx = [...
        new_pos(1),...
        new_pos(1),new_pos(1)+new_pos(3),new_pos(1)+new_pos(3),...
        new_pos(1)];
      yy = [...
        new_pos(2),...
        new_pos(2)+new_pos(4),new_pos(2)+new_pos(4),new_pos(2),...
        new_pos(2)];
      set(h_patch, 'XData', xx, 'YData', yy);
    end

    bounding_box = new_pos;

  end
  %--------------------------------------------------------------------------

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function setColor(c)
    if ishandle(h_circle)
      set(h_circle, 'EdgeColor', c);
    end

  end
  %--------------------------------------------------------------------------

end

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% function setXYDataIfChanged(h, x, y)
% % Set XData and YData of HG object h to x and y if they are different.  h
% % must be a valid HG handle to an object having XData and YData properties.
% % No validation is performed.
%
%   if ~isequal(get(h, 'XData'), x) || ~isequal(get(h, 'YData'), y)
%     set(h, 'XData', x, 'YData', y);
%   end
% end
% %--------------------------------------------------------------------------


function plotPendulumCart(t,x,param)

Cart_Width = 0.2;
Cart_Height = 0.1;
Limits = param.axis;

Cart = x(1:2);
Bob = x(3:4);

if param.clearFigure    %THEN RUNNING ANIMATION
    clf;
    hold on;

    %Plot Cart
    x = Cart(1) - 0.5*Cart_Width;
    y = -0.5*Cart_Height;
    w = Cart_Width;
    h = Cart_Height;
    h = rectangle('Position',[x,y,w,h],'LineWidth',4,'Curvature',[0.3,0.3]);
    set(h,'EdgeColor',[0.1,0.8,0.1])

    %Plot Pendulum
    Rod_X = [Cart(1), Bob(1)];
    Rod_Y = [Cart(2), Bob(2)];
    plot(Rod_X,Rod_Y,'k-','LineWidth',4)

    %Plot Bob
    plot(Bob(1),Bob(2),'k.','MarkerSize',50)

    %Plot Rails
    plot([Limits(1) Limits(2)],-0.5*Cart_Height*[1,1],'k-','LineWidth',2)

    %Title
    title(['Simulation Time: ' num2str(t) ' s'])

    %These commands keep the window from automatically rescaling in funny ways.
    axis(Limits);
    axis('equal');
    axis manual;
    axis off;

else    %THEN RUNNING STOP ACTION

    hold on;

    %Plot Cart
    x = Cart(1) - 0.5*Cart_Width;
    y = -0.5*Cart_Height;
    w = Cart_Width;
    h = Cart_Height;
    rectangle('Position',[x,y,w,h],'LineWidth',2);

    %Plot Pendulum
    Rod_X = [Cart(1), Bob(1)];
    Rod_Y = [Cart(2), Bob(2)];
    plot(Rod_X,Rod_Y,'k-','LineWidth',2)

    %Plot Bob and hinge
    plot(Bob(1),Bob(2),'k.','MarkerSize',30)
    plot(Cart(1),Cart(2),'k.','MarkerSize',30)

    %Plot Rails
    plot([Limits(1) Limits(2)],-0.5*Cart_Height*[1,1],'k-','LineWidth',2)

    %Plot trace of the Bob's path:
    plot(param.Bob(1,:),param.Bob(2,:),'k:','LineWidth',1)

    %These commands keep the window from automatically rescaling in funny ways.
    axis(Limits);
    axis('equal');
    axis manual;
    axis off;

end
end


function OUT = test_pattern_on_kragel_2018_n270_data(varargin)
%
% test a multivariate signature pattern stored in an fmri_data object on Kragel et al. 2018 datasets, N = 270
%
% -   requires kragel_2018_nat_neurosci_270_subjects_test_images.mat
%     if not found, will attempt to download from Neurovault using
%     retrieve_neurovault_collection(). See load_image_set('kragel18_alldata')
%
% -   Dataset is from Kragel et al. 2018, Nature Neuroscience.
%     Uses load_image_set to load it:
%     test_images = load_image_set('kragel18_alldata', 'noverbose');
%
% -   If not found, load_image_set uses the utility retrieve_neurovault_collection
%     to pull the images from Neurovault.org if you don't have them.
%     [files_on_disk, url_on_neurovault, mycollection, myimages] = retrieve_neurovault_collection(504);
%     image_obj = fmri_data(files_on_disk);
%     It also adds meta-data to label the images.
%
% :Usage:
% ::
%
%     [list outputs here] = test_pattern_on_kragel_2018_n270_data(obj)
%
% For objects: Type methods(object_name) for a list of special commands
%              Type help object_name.method_name for help on specific
%              methods.
%
% ..
%     Author and copyright information:
%
%     Copyright (C) 2019 Tor Wager
%
%     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/>.
% ..
%
% :Inputs:
%
%   **obj:**
%        An fmri_data object storing a single image of multivariate pattern weights
%
% :Optional Inputs:
%   **'noverbose':**
%        Turn off verbose output
%
%   **'noplots':**
%       Turn off plots
%
%   **'threshold_type'
%       Followed by keyphrase, e.g., 'Optimal balanced error rate'
%       Default is 'Optimal overall accuracy'
%
%
% :Outputs:
%
%   **OUT:**
%        A structure with a summary table of sensivity, specificity, PPV,
%        and effect size for each classification (pain vs. other, cog
%        control vs. other, negative emotion vs. other.
%        Also includes roc_plot output for all three classifications, with
%        more stats and function handles.
%
%
% :Examples:
% ::
%
%    % give examples of code here
%    param1 = abc();
%    param2 = xyz();
%    [out1,out2] = func_call(param1, param2)
%
% :References:
%   CITATION(s) HERE
%
% :See also:
%   - list other functions related to this one, and alternatives*
%

% ..
%    Programmers' notes:
%    List dates and changes here, and author of changes
% ..

% ----------------------------------------------------------------------
% Defaults
% ----------------------------------------------------------------------
% Must define ALL inputs here. All these can be changed by passing in arguments.

obj = [];
num_cols = 18;      % this is for the test dataset
doverbose = true;
doplot = true;
fontsize = 14;
threshold_type = 'Optimal balanced error rate'; % 'Optimal overall accuracy'; %

colors = [repmat({[1 .2 0]}, 1, 6) repmat({[.4 .5 .2]}, 1, 6) repmat({[.1 0 .9]}, 1, 6)];

sim_string = 'cosine_similarity';  % or 'dotproduct' or 'correlation'
weight_string = 'none';  % or 'weighted'

canlab_parse_inputs_subfcn();

% ----------------------------------------------------------------------
% Display helper functions: Called by later scripts
% ----------------------------------------------------------------------

dashes = '----------------------------------------------';
printstr = @(dashes) disp(dashes);
printhdr = @(str) fprintf('%s\n%s\n%s\n', dashes, str, dashes);

disp('Process: test_pattern_on_kragel_2018_n270_data');
printstr(dashes)

disp(' ');

% ----------------------------------------------------------------------
% Load and prep test data
% ----------------------------------------------------------------------
test_images = load_image_set('kragel18_alldata', 'noverbose');

test_images.Y = test_images.metadata_table.Studynumber;

% vector_data = apply_mask(test_images, obj, 'pattern_expression', sim_string);
vector_data = apply_mask(test_images, obj, 'pattern_expression', sim_string,weight_string); %weight by overall cosine similarity

for s = 1:length(test_images.additional_info)
    pattern_response{s} = vector_data(test_images.Y==s);
end

% clear exp
% labels = test_images.additional_info;
labels = format_strings_for_legend(test_images.additional_info);

% ----------------------------------------------------------------------
% ROC and stats
% ----------------------------------------------------------------------

% [ispain, iscog, isemo] = deal(false(270, 1));
%
% ispain(1:6*15) = true;
% iscog(6*15 + 1 : (12*15)) = true;
% isemo(12*15+1:18*15) = true;

ispain = strcmp(test_images.metadata_table.Domain, 'Pain');
iscog = strcmp(test_images.metadata_table.Domain, 'Cog_control');
isemo = strcmp(test_images.metadata_table.Domain, 'Neg_Emotion');

wh_isnan=isnan(vector_data);
vector_data=vector_data(~wh_isnan);

ispain=ispain(~wh_isnan);
iscog=iscog(~wh_isnan);
isemo=isemo(~wh_isnan);

% Boostrap confidence intervals for effect size
fprintf('Bootstrapping CIs\n')

bci_pain = bootci(5000, @cohens_d_2sample, vector_data, ispain);

bci_cog = bootci(5000, @cohens_d_2sample, vector_data, iscog);

bci_emo = bootci(5000, @cohens_d_2sample, vector_data, isemo);

% ----------------------------------------------------------------------
% ROC calculation and classification output
% ----------------------------------------------------------------------

printhdr('Pattern classification results')
disp('Applied pattern to test data from 18 studies, n = 270 participants')
disp('From Kragel et al. 2018, Nature Neuroscience')
disp(' ')

disp('Classification of pain vs. other')

roc_pain = roc_plot(vector_data,ispain, 'noplot', 'threshold_type', threshold_type);

fprintf('Threshold for cosine_sim = %3.4f, Cohen''s d(pain vs no) = %3.2f, Bootstrapped CI is [%3.2f %3.2f]\n', ...
    roc_pain.class_threshold, cohens_d_2sample(vector_data, ispain), bci_pain(1), bci_pain(2));

disp(' ')

disp('Classification of cognitive control vs. other')

roc_cog = roc_plot(vector_data,iscog, 'noplot', 'threshold_type', threshold_type);

fprintf('Threshold for cosine_sim = %3.4f, Cohen''s d(cog vs no) = %3.2f, Bootstrapped CI is [%3.2f %3.2f]\n', ...
    roc_cog.class_threshold, cohens_d_2sample(vector_data, iscog), bci_cog(1), bci_cog(2));

disp(' ')

disp('Classification of emotion vs. other')

roc_emo = roc_plot(vector_data,isemo, 'noplot', 'threshold_type', threshold_type);

fprintf('Threshold for cosine_sim = %3.4f, Cohen''s d(emo vs no) = %3.2f, Bootstrapped CI is [%3.2f %3.2f]\n', ...
    roc_emo.class_threshold, cohens_d_2sample(vector_data, isemo), bci_emo(1), bci_emo(2));
disp(' ')

% ----------------------------------------------------------------------
% Output table
% ----------------------------------------------------------------------

tabledata(1, :) = [roc_pain.class_threshold cohens_d_2sample(vector_data, ispain) roc_pain.sensitivity roc_pain.specificity roc_pain.PPV ];
tabledata(2, :) = [roc_cog.class_threshold cohens_d_2sample(vector_data, iscog) roc_cog.sensitivity roc_cog.specificity roc_cog.PPV ];
tabledata(3, :) = [roc_emo.class_threshold cohens_d_2sample(vector_data, isemo) roc_emo.sensitivity roc_emo.specificity roc_emo.PPV ];

T = array2table(tabledata, 'VariableNames', {'Cos_Sim_Thresh' 'Cohens_d' 'Sensitivity' 'Specificity' 'PPV'}, 'RowNames', {'Pain' 'Cog Control' 'Neg Emotion'});

disp(T);

OUT.summary_table = T;
OUT.roc_pain = roc_pain;
OUT.roc_cog = roc_cog;
OUT.roc_emo = roc_emo;

% ----------------------------------------------------------------------
% Plot
% ----------------------------------------------------------------------
if doplot

    create_figure('plot', 1, 3);

    clear hh

    subplot(1,3,3)

    roc = roc_plot(vector_data,ispain, 'threshold_type', threshold_type, 'nooutput');
    set(roc.line_handle, 'Color', 'r');
    hh(1) = roc.line_handle(2);

    roc = roc_plot(vector_data,iscog, 'threshold_type', threshold_type, 'nooutput');
    set(roc.line_handle, 'Color', 'g');
    hh(2) = roc.line_handle(2);

    roc = roc_plot(vector_data,isemo, 'threshold_type', threshold_type, 'nooutput');
    set(roc.line_handle, 'Color', 'b');
    hh(3) = roc.line_handle(2);

    set(gca,'fontsize', fontsize)
    legend(hh, {'Pain vs Other' 'Cog vs. Other' 'Emo vs. Other'});

    printhdr('Stats for individual studies')

    subplot(1,3,1:2)

    set(gca, 'FontSize', fontsize);
    barplot_columns(pattern_response,'names',labels,'colors',colors,'nofig');
    ylabel 'Pattern Response (Cosine Similarity)'
    hold on;

    if roc_pain.accuracy_p < .05
        plot([0 19],[roc_pain.class_threshold roc_pain.class_threshold],'r--')
    end

    if roc_cog.accuracy_p < .05
        plot([0 19],[roc_cog.class_threshold roc_cog.class_threshold],'g--')
    end

    if roc_emo.accuracy_p < .05
        plot([0 19],[roc_emo.class_threshold roc_emo.class_threshold],'b--')
    end

else
    % no plot, but print stats

    printhdr('Stats for individual studies')
    barplot_columns(pattern_response,'names',labels, 'colors',colors, 'skipallplots');

end % plot

% ----------------------------------------------------------------------
% ----------------------------------------------------------------------
% Nested functions
% ----------------------------------------------------------------------
% ----------------------------------------------------------------------

    function canlab_parse_inputs_subfcn()
        % INPUT PARSER: This is a nested function.
        % It modifies variables in the calling workspace directly.
        % It validates inputs.
        % It uses inputParser, but also allows for special keywords that change
        % variables, which are not handled by inputParser.

        % ----------------------------------------------------------------------
        % Parse inputs
        % ----------------------------------------------------------------------
        p = inputParser;

        % Validation functions - customized for each type of input
        % ----------------------------------------------------------------------

        valfcn_scalar = @(x) validateattributes(x, {'numeric'}, {'nonempty', 'scalar'});
        valfcn_number = @(x) validateattributes(x, {'numeric'}, {'nonempty'}); % scalar or vector
        valfcn_cell = @(x) validateattributes(x, {'cell'}, {'nonempty'}, {'numel'}, num_cols);

        valfcn_image_vector = @(x) isa(x, 'image_vector');

        % Required inputs
        % ----------------------------------------------------------------------
        p.addRequired('obj', valfcn_image_vector);

        % Optional inputs - key-value pairs
        % ----------------------------------------------------------------------
        % Pattern: keyword, value, validation function handle

        p.addParameter('fontsize', fontsize);
        p.addParameter('colors', colors);
        p.addParameter('sim_string', sim_string);
        p.addParameter('weight_string',weight_string);
        p.addParameter('threshold_type', threshold_type);

        % Optional inputs - Logical flags and keywords
        % ----------------------------------------------------------------------
        % Identify and remove these before parsing, because they do not follow name-value pair pattern
        wh = strcmp(varargin, 'noverbose');
        if any(wh), doverbose = false; varargin(wh) = []; end

        wh = strcmp(varargin, 'noplots');
        if any(wh), doplot = false; varargin(wh) = []; end

        wh = strcmp(varargin, 'noplot');
        if any(wh), doplot = false; varargin(wh) = []; end

        % Parse inputs and distribute out to variable names in workspace
        % ----------------------------------------------------------------------
        p.parse(varargin{:});

        IN = p.Results;
        fn = fieldnames(IN);

        for i = 1:length(fn)
            str = sprintf('%s = IN.(''%s'');', fn{i}, fn{i});
            eval(str)
        end

    end  % Parse subfunction

end % main function


    %% Regional Channel Selection
    % 5 Region
    channel_f=epoch.x(:,1:7,:);
    channel_o=epoch.x(:,28:32,:);
    channel_p=epoch.x(:,23:27,:);
    channel_c=epoch.x(:,[8:11,13:15,18:21],:);
    channel_t=epoch.x(:,[12,16:17,22],:);

    % 5 Region + Vertical
    channel_f1=epoch.x(:,[1,3:4],:);
    channel_f2=epoch.x(:,[2,6:7],:);
    channel_f3=epoch.x(:,5,:);
    channel_o1=epoch.x(:,29,:);
    channel_o2=epoch.x(:,31,:);
    channel_o3=epoch.x(:,30,:);
    channel_p1=epoch.x(:,[18:19,23:24,28],:);
    channel_p2=epoch.x(:,[20:21,26:27,32],:);
    channel_p3=epoch.x(:,25,:);
    channel_c1=epoch.x(:,[8:9,13],:);
    channel_c2=epoch.x(:,[10:11,15],:);
    channel_c3=epoch.x(:,14,:);
    channel_t1=epoch.x(:,[12,17],:);
    channel_t2=epoch.x(:,[16,22],:);


classdef EMObject < handle
	% EMObject is the combination of Shape and Material.

	properties (SetAccess = immutable)
		shape
		material
	end

	methods
		function this = EMObject(shape, material)
			if nargin ~= 0
				chkarg(istypesizeof(shape, 'Shape', [1 0]), '"shape" should be row vector with Shape as elements.');
				chkarg(istypesizeof(material, 'Material'), ...
					'"material" should be instance of Material.');

				n = length(shape);
				this(n) = EMObject;
				for i = 1:n
					this(i).material = material;
					this(i).shape = shape(i);
				end
			end
		end

		% A function assigning eps and mu could have been a member function of
		% EMObject, but there are too many subpixel smoothing schemes for eps and
		% mu.  Suppoting all those schemes would make EMObject very heavyweight. A
		% decision of taking out those schemes from EMObject was made to leave
		% EMObject lightweight.
	end
end


clear all;

[X,Y,Z] = peaks(100);
X = single(X);
Y = single(Y);
Z = single(Z);
Z_index = uint8((Z - min(Z(:))) * (255 / (max(Z(:)) - min(Z(:)))));
Z_color = uint8(ind2rgb(Z_index, hsv(256)*256));
Z_color_multiframe = reshape([Z_color(:)*0.2 Z_color(:)*0.6 Z_color(:)], 100, 100, 3, 3);
Z_color_noisy = uint8(single(Z_color) + rand(100, 100, 3).*50);

% 8-bit, grayscale image
saveastiff(uint8(Z_index), 'Z_uint8.tif');

% Lossless LZW compression
options.comp = 'lzw';
saveastiff(uint8(Z_index), 'Z_uint8_LZW.tif', options);
options.comp = 'no';

% Ask a question if the file is already exist
options.ask = true;
saveastiff(uint8(Z_index), 'Z_uint8_LZW.tif', options);
options.ask = false;

% Allow message printing.
options.message = true;
saveastiff(uint8(Z_index), 'Z_uint8_LZW.tif', options);
options.message = false;

% 16-bit, grayscale image
saveastiff(uint16(Z_index), 'Z_uint16.tif');

% 32-bit single, grayscale image
saveastiff(Z, 'Z_single.tif');

% RGB color image
options.color = true;
saveastiff(Z_color, 'Z_rgb.tif', options);
options.color = false;

% Save each R, G and B chanels of the color image, separately.
saveastiff(Z_color, 'Z_rgb_channel.tif');

% Save the multi-frame RGB color image
options.color = true;
saveastiff(Z_color_multiframe, 'Z_rgb_multiframe.tif', options);
options.color = false;

% Save the noise-added RGB color image
options.color = true;
saveastiff(Z_color_noisy, 'Z_rgb_noisy.tif', options);
options.color = false;

% 32-bit single, 50x50x50 volume data
saveastiff(single(rand(50, 50, 50)), 'volume_50x50x50.tif');

% Append option is ignored if path dose not exist.
options.append = true;
saveastiff(Z_index, 'Z_uint8_append.tif', options);
options.append = false;

% You can append any type of image to an existing tiff file.
options.append = true;
saveastiff(Z, 'complex_frame.tif');
saveastiff(single(rand(10, 10, 3)), 'complex_frame.tif', options);
options.color = true;
saveastiff(Z_color_multiframe, 'complex_frame.tif', options);
options.color = false;
options.append = false;

% Load multiframe tiff
multiframe = loadtiff('volume_50x50x50.tif');
complexframe = loadtiff('complex_frame.tif');


function dat = read_spike6mat_data(filename, varargin)

% read_spike6mat_data() - read Matlab files exported from Spike 6
%
% Usage:
%   >> header = read_spike6mat_data(filename, varargin);
%
% Inputs:
%   filename - [string] file name
%
% Optional inputs:
%   'begsample'      first sample to read
%   'endsample'      last sample to read
%   'chanindx'  -    list with channel indices to read
%   'header'    - FILEIO structure header
%
% Outputs:
%   dat    - data over the specified range
% _______________________________________________________________________
% Copyright (C) 2008 Institute of Neurology, UCL
% Vladimir Litvak

if nargin < 1
    help read_spike6mat_data;
    return;
end;

header    = keyval('header',     varargin);
begsample = keyval('begsample',  varargin);
endsample = keyval('endsample',  varargin);
chanindx  = keyval('chanindx',   varargin);

if isempty(header)
    header = read_spike6mat_header(filename);
end

if isempty(begsample), begsample = 1; end;
if isempty(endsample), endsample = header.nSamples; end;

try
    vars = struct2cell(load(filename));
catch
    error('File not found or wrong format.');
end

if isempty(chanindx)
    chanindx = 1:numel(vars);
end

dat = zeros(length(chanindx), endsample-begsample+1);

for i = 1:length(chanindx)
    dat(i, :) = vars{chanindx(i)}.values(begsample:endsample);
end


%{
MIT License

Copyright (c) 2018 ZjxRS

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.
%}
% This is lifted from https://github.com/ZjxRS/ImageProcess/tree/master/Matlab/ENVI_ReadAndWrite

function D=envidataread(datafile,info)
%ENVIDATAREAD Reads data of ENVI image file according to ENVI image file header information.
%D=ENVIDATAREAD(DATAFILE,INFO) provides image data (D).
%D will be in whatever number format (double, int, etc.) as in the ENVI
%file.

%Original version by Ian Howat, Ohio State Universtiy, ihowat@gmail.com
%Thanks to Yushin Ahn and Ray Jung
%Heavily modified by Felix Totir.
%

if nargin < 2
    error('You must specify the information about data (output of envihdrread)');
end

%-improved- assert(info.header_offset==0,'Non-zero header offset not supported');

%% Set binary format parameters
switch info.byte_order
    case {0}
        machine = 'ieee-le';
    case {1}
        machine = 'ieee-be';
    otherwise
        machine = 'n';
end

iscx=false; %if it is complex
switch info.data_type
    case {1}
        format = 'uint8';
    case {2}
        format= 'int16';
    case{3}
        format= 'int32';
    case {4}
        format= 'float';
    case {5}
        format= 'double';
    case {6}
        iscx=true;
        format= 'float';
    case {9}
        iscx=true;
        format= 'double';
    case {12}
        format= 'uint16';
    case {13}
        format= 'uint32';
    case {14}
        format= 'int64';
    case {15}
        format= 'uint64';
    otherwise
        error(['File type number: ',num2str(dtype),' not supported']);
end

% *** BSQ Format ***
% [Band 1]
% R1: C1, C2, C3, ...
% R2: C1, C2, C3, ...
%  ...
% RN: C1, C2, C3, ...
%
% [Band 2]
%  ...
% [Band N]

% *** BIL Format ***
% [Row 1]
% B1: C1, C2, C3, ...
% B2: C1, C2, C3, ...
%
%  ...
% [Row N]

% *** BIP Format ***
% Row 1
% C1: B1 B2 B3, ...
% C2: B1 B2 B3, ...
% ...
% Row N

n = info.lines*info.samples*info.bands;

fid=fopen(datafile,'r');
fread(fid,info.header_offset,'uint8',0,machine); %we skip the header
if ~iscx
    if strcmp(info.file_type, 'ENVI Classification')
        D = fread(fid,n,'uint8',0,machine);
    else
        D = fread(fid,n,format,0,machine); %alternatively, multibandreader (matlab function) might be used
    end
else
    D = fread(fid,2*n,format,0,machine); %alternatively, multibandreader (matlab function) might be used
    D = complex(D(1:2:end),D(2:2:end));
end
fclose(fid);

switch lower(info.interleave)
    case {'bsq'}
        D = reshape(D,[info.samples,info.lines,info.bands]);
        D = permute(D,[2,1,3]);
    case {'bil'}
        D = reshape(D,[info.samples,info.bands,info.lines]);
        D = permute(D,[3,1,2]);
    case {'bip'}
        D = reshape(D,[info.bands,info.samples,info.lines]);
        D=permute(D,[3,2,1]);
end