function data_num = p02_data_num ( )

%*****************************************************************************80
%
%% P02_DATA_NUM returns the dimension of the data vector for problem 2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 August 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, integer DATA_NUM, the dimension of the data vector.
%
  data_num = 11;

  return
end


%kktan 'Compute Tangent or Arc Tangent Function'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros ktan.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'Input data object'
% OutputFile: o 'Output', required: 'Resulting output data object'
% Toggle: tan 'Tangent', default: 0: 'Calculate tangent of input'
% Toggle: atan 'Arc Tangent', default: 0: 'Calculate arc tangent of input'
%
% Example: o = kktan(i, {'i','';'o','';'tan',0;'atan',0})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% ktan - Compute Tangent or Arc Tangent Function
%
%  DESCRIPTION
% The "Tan & ArcTan" operator returns the tangent, or arc tangent, value
% of each data point in the input data object, \fBInput".  The forward or
% inverse trigonometric operation is specified by selecting the \fBTangent" or
% \fBArc Tangent" option on the user interface.
%
% Executing "Tan & ArcTan" runs the program \fIkarith1\fP
% with the -tan or -atan flag.
%
%  "\fBData Type"" 5
% .cI $DATAMANIP/repos/shared/man/sections/value_type_1input
%
%  "\fBMap Data"" 5
% .cI $DATAMANIP/repos/shared/man/sections/map_1input
%
%  "\fBValidity Mask"" 5
% .cI $DATAMANIP/repos/shared/man/sections/mask_1input
%
%  "\fBExplicit Location and Time Data"" 5
% .cI $DATAMANIP/repos/shared/man/sections/loc_and_time_1input
%
%  "\fBFailure Modes""
% .cI $DATAMANIP/repos/shared/man/sections/fail_1input
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
% DATAMANIP::karith1
%
%  RESTRICTIONS
% Operations on complex data are not supported at this time.
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kktan(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,..] = kktan(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'o', '__output';'tan', 0;'atan', 0};
maxval={0,0,0,0};
minval={0,0,0,0};
istoggle=[0,0,1,1];
was_set=istoggle * 0;
paramtype={'InputFile','OutputFile','Toggle','Toggle'};
% 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 'karith1"  '],Inputs,narglist);


function [Ycon,ln] = concatenate_files(files,filename,output_type)

% concatenate a list of files into a single file
% INPUTS
% files:        list of a files as a struct array. Name of each file is in files(i).name
% filename:     output filename
% type:         output type ('mat' array loaded in RAM (default), 'hdf5' and 'tif' are currently supported)

% OUTPUTS
% Ycon:         concantenated file as an array if output_type == 'mat'
% ln:           length of each file (in frames)

if ~exist('output_type','var')
    output_type = 'mat';
end

if ~exist('filename','var') || isempty(filename)
    filename = ['concatenated_file.',output_type];
end

numFiles = length(files);
ln = zeros(numFiles,1);

Y1 = read_file(fullfile(files(1).folder, files(1).name));
sizY = size(Y1);
T1 = sizY(end);
data_type = class(Y1);
nd = max(ndims(Y1)-1,2);
sizY = sizY(1:nd);

switch lower(output_type)
    case 'mat'
        Ycon = cast([],data_type); %zeros([sizY,T1],data_type);
    case {'hdf5','h5'}
        Ycon = filename;
        h5create(filename,'/mov',[sizY,Inf],'Chunksize',[sizY,1],'Datatype',data_type);
    case {'tif','tiff'}
        Ycon = filename;
        opts_tiff.append = true;
        opts_tiff.big = true;
    otherwise
        error('This filetype is currently not supported')
end

for i = 1:numFiles
    Y_temp = read_file(fullfile(files(i).folder, files(i).name)); %cat(nd+1,Ycon,Y_temp);
    ln(i) = size(Y_temp,ndims(Y_temp));

    switch lower(output_type)
        case 'mat'
            Ycon = cat(nd+1,Ycon,Y_temp);
        case {'hdf5','h5'}
            h5write(filename,'/mov',Y_temp,[ones(1,nd),sum(ln(1:i-1))+1],size(Y_temp));
        case {'tif','tiff'}
            saveastiff(cast(Y_temp,data_type),filename,opts_tiff);
    end
end


function varargout = randsample(varargin)
% - Produces a column, like Matlab does (instead of Octave, which produces a row), when the first input is a scalar
% - Allows first input to be char. It is then treated as the population to sample from (not as a number)
if ischar(varargin{1})
    varargout{1} = varargin{1}(randsample(numel(varargin{1}), varargin{2:end}));
else
    varargout{1} = builtin('randsample', varargin{:});
    if numel(varargin{1})==1
        varargout{1} = varargout{1}(:);
    end
end
end


function root_num = p16_root_num ( )

%*****************************************************************************80
%
%% P16_ROOT_NUM returns the number of known roots for problem 16.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 May 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, integer ROOT_NUM, the number of known roots.
%
  root_num = 0;

  return
end


%
%
%  Setup_Nesta
%
%  sets up the path for Nesta
%
%
%
% Written by: Jerome Bobin, Caltech
% Email: bobin@acm.caltech.edu
% Created: May 2009
%
% NESTA NESTA Version 1.1
%   See also NESTA

% This adds a relative path, so it only works
% when you're in the NESTA directory

%addpath RecPF_v1.1/solver/
%addpath Misc/

% This adds an absolute path, so it works
% when the user is in any directory

p = mfilename('fullpath'); % the location of this file
path = fileparts(p);
addpath( fullfile(path,'RecPF_v1.1','solver' ) );
addpath( fullfile(path,'Misc') );


function [subs,vals] = find(t)
%FIND Find subscripts of nonzero elements in a sparse tensor.
%
%   [SUBS,VALS] = FIND(T) returns the subscripts and corresponding
%   values of the nonzero elements of T.
%
%   Note that unlike the standard MATLAB find function for an array,
%   find does not return linear indices. Instead, it returns an M x N
%   array where M is the number of nonzero values and N = ndims(T).
%   Thus, I(k,:) specifies the subscript of value V(k).
%
%   See also SPTENSOR, FIND.
%
%MATLAB Tensor Toolbox.
%Copyright 2015, Sandia Corporation.

% This is the MATLAB Tensor Toolbox by T. Kolda, B. Bader, and others.
% http://www.sandia.gov/~tgkolda/TensorToolbox.
% Copyright (2015) Sandia Corporation. Under the terms of Contract
% DE-AC04-94AL85000, there is a non-exclusive license for use of this
% work by or on behalf of the U.S. Government. Export of this data may
% require a license from the United States Government.
% The full license terms can be found in the file LICENSE.txt

subs = t.subs;
vals = t.vals;


%EXPORT_CSV Export grid and data in CSV format.
%
%   EXPORT_CSV( FILENAME, FEA, EXPR, SOLNUM, FID_LOG )
%
%   Export of grid points and corresponding solution/expression data
%   in CSV format. The CSV file will consist of a header line with the
%   space coordinate names, dependent variable names, and given
%   expressions (columns). This is followed by the actual data rows
%   where one line corresponds to the data for the specific grid
%   point.
%
%   FILENAME gives the output file name. FEA must be a valid FEA data
%   struct, EXPR is optionally a cell array with expressions to
%   process (the grid coordinates and dependent variables in the FEA
%   struct will be prepended to EXPR). SOLNUM is optionally the
%   solution number of which to evaluate the expressions. FID_LOG is
%   an optional log file handle for message output (negative for gui
%   output or empty for no output).

% Copyright 2013-2022 Precise Simulation, Ltd.


function title = p34_title ( )

%*****************************************************************************80
%
%% P34_TITLE returns the title of problem P34.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, string TITLE, the title of the problem.
%
  title = 'Problem 34, The Linearized Damped Pendulum';

  return
end


function [ t_stop, y_stop ] = p00_stop ( test, neqn )

%*****************************************************************************80
%
%% P00_STOP returns the end data for any test problem.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer TEST, the test problem index.
%
%    Input, integer NEQN, the number of equations.
%
%    Output, real T_STOP, the end time.
%
%    Output, real Y_STOP(NEQN), the end value of the dependent
%    variables.
%
  y_stop = zeros ( neqn, 1 );

  if ( test == 1 )
    [ t_stop, y_stop ] = p01_stop ( neqn );
  elseif ( test == 2 )
    [ t_stop, y_stop ] = p02_stop ( neqn );
  elseif ( test == 3 )
    [ t_stop, y_stop ] = p03_stop ( neqn );
  elseif ( test == 4 )
    [ t_stop, y_stop ] = p04_stop ( neqn );
  elseif ( test == 5 )
    [ t_stop, y_stop ] = p05_stop ( neqn );
  elseif ( test == 6 )
    [ t_stop, y_stop ] = p06_stop ( neqn );
  elseif ( test == 7 )
    [ t_stop, y_stop ] = p07_stop ( neqn );
  elseif ( test == 8 )
    [ t_stop, y_stop ] = p08_stop ( neqn );
  elseif ( test == 9 )
    [ t_stop, y_stop ] = p09_stop ( neqn );
  elseif ( test == 10 )
    [ t_stop, y_stop ] = p10_stop ( neqn );
  elseif ( test == 11 )
    [ t_stop, y_stop ] = p11_stop ( neqn );
  elseif ( test == 12 )
    [ t_stop, y_stop ] = p12_stop ( neqn );
  elseif ( test == 13 )
    [ t_stop, y_stop ] = p13_stop ( neqn );
  elseif ( test == 14 )
    [ t_stop, y_stop ] = p14_stop ( neqn );
  elseif ( test == 15 )
    [ t_stop, y_stop ] = p15_stop ( neqn );
  elseif ( test == 16 )
    [ t_stop, y_stop ] = p16_stop ( neqn );
  elseif ( test == 17 )
    [ t_stop, y_stop ] = p17_stop ( neqn );
  elseif ( test == 18 )
    [ t_stop, y_stop ] = p18_stop ( neqn );
  elseif ( test == 19 )
    [ t_stop, y_stop ] = p19_stop ( neqn );
  elseif ( test == 20 )
    [ t_stop, y_stop ] = p20_stop ( neqn );
  elseif ( test == 21 )
    [ t_stop, y_stop ] = p21_stop ( neqn );
  elseif ( test == 22 )
    [ t_stop, y_stop ] = p22_stop ( neqn );
  elseif ( test == 23 )
    [ t_stop, y_stop ] = p23_stop ( neqn );
  elseif ( test == 24 )
    [ t_stop, y_stop ] = p24_stop ( neqn );
  elseif ( test == 25 )
    [ t_stop, y_stop ] = p25_stop ( neqn );
  elseif ( test == 26 )
    [ t_stop, y_stop ] = p26_stop ( neqn );
  elseif ( test == 27 )
    [ t_stop, y_stop ] = p27_stop ( neqn );
  elseif ( test == 28 )
    [ t_stop, y_stop ] = p28_stop ( neqn );
  elseif ( test == 29 )
    [ t_stop, y_stop ] = p29_stop ( neqn );
  elseif ( test == 30 )
    [ t_stop, y_stop ] = p30_stop ( neqn );
  elseif ( test == 31 )
    [ t_stop, y_stop ] = p31_stop ( neqn );
  elseif ( test == 32 )
    [ t_stop, y_stop ] = p32_stop ( neqn );
  elseif ( test == 33 )
    [ t_stop, y_stop ] = p33_stop ( neqn );
  elseif ( test == 34 )
    [ t_stop, y_stop ] = p34_stop ( neqn );
  elseif ( test == 35 )
    [ t_stop, y_stop ] = p35_stop ( neqn );
  elseif ( test == 36 )
    [ t_stop, y_stop ] = p36_stop ( neqn );
  elseif ( test == 37 )
    [ t_stop, y_stop ] = p37_stop ( neqn );
  elseif ( test == 38 )
    [ t_stop, y_stop ] = p38_stop ( neqn );
  elseif ( test == 39 )
    [ t_stop, y_stop ] = p39_stop ( neqn );
  elseif ( test == 40 )
    [ t_stop, y_stop ] = p40_stop ( neqn );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'P00_STOP - Fatal error!\n' );
    fprintf ( 1, '  Illegal problem index TEST = %d\n', test );
    error ( 'P00_STOP - Fatal error!' );
  end

  return
end


function change(file)
[np,nf]=num(file);
fprintf('Number_of_point:%d\n',np);
fprintf('Number_of_face:%d\n',nf);
fid=fopen('OFF','w');
fprintf(fid,'OFF\n');
fprintf(fid,'%d %d 0\n',np,nf);
fid2=fopen(file);
H=0;
while 1
    tline=fgetl(fid2);
    H=H+1;
    if ~ischar(tline) , break , end
    if H > 1
        disp(tline)
        fprintf(fid,'%s\n',tline);
    end

end
fclose(fid2);
fclose(fid);
function [np,nf]=num(file)
fid=fopen(file);
C=0;
while 1
    tline=fgetl(fid);
    C=C+1;
    if C==1
        num=textscan(tline,'%s %d %d %d');
        break;
    end
     if ~ischar(tline) , break , end

end
fclose(fid);
np=num{1,2};
nf=num{1,3};


function [nodes2, edges2] = grRemoveEdges(nodes, edges, rmEdges)
%GRREMOVEEDGES Remove several edges from a graph.
%
%   [NODES2 EDGES2] = grRemoveEdges(NODES, EDGES, EDGES2REMOVE)
%   Remove some edges in the edges list, and return the modified graph.
%   The NODES array is not modified.

% ------
% Author: David Legland
% E-mail: david.legland@inrae.fr
% Created: 2003-08-13
% Copyright 2003-2022 INRA - TPV URPOI - BIA IMASTE

rmEdges = sort(rmEdges);

% do not change the node list
nodes2 = nodes;

% number of edges
N   = size(edges, 1);
NR  = length(rmEdges);
N2  = N - NR;

% allocate memory for new  edges list
edges2 = zeros(N2, 2);

% case of no edge to remove
if NR == 0
    nodes2 = nodes;
    edges2 = edges;
    return;
end

% process the first edge
edges2(1:rmEdges(1)-1,:) = edges(1:rmEdges(1)-1,:);

% process the classical edges
for i = 2:NR
    %if rmEdges(i)-i < rmEdges(i-1)-i+2
    %    continue;
    %end
    edges2(rmEdges(i-1)-i+2:rmEdges(i)-i, :) = edges(rmEdges(i-1)+1:rmEdges(i)-1, :);
end

% process the last edge
edges2(rmEdges(NR)-NR+1:N2, :) = edges(rmEdges(NR)+1:N, :);


function varargout = process_ssmooth( varargin )
% PROCESS_SSMOOTH: Spatial smoothing of the sources (DEPRECATED)

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2010-2016

eval(macro_method);
end

%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'Spatial smoothing (DEPRECATED)';
    sProcess.FileTag     = 'ssmooth';
    sProcess.Category    = 'Filter';
    sProcess.SubGroup    = 'Sources';
    sProcess.Index       = 0;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/Tutorials/VisualGroup';
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'results', 'timefreq'};
    sProcess.OutputTypes = {'results', 'timefreq'};
    sProcess.nInputs     = 1;
    sProcess.nMinFiles   = 1;
    % Default values for some options
    sProcess.isSourceAbsolute = 1;
    sProcess.processDim  = 2;    % Process time by time
    % === GAUSSIAN PROP
    sProcess.options.label1.Comment = 'Gaussian filter properties:';
    sProcess.options.label1.Type    = 'label';
    % === FWHM (kernel size)
    sProcess.options.fwhm.Comment = '      FWHM (Full width at half maximum):  ';
    sProcess.options.fwhm.Type    = 'value';
    sProcess.options.fwhm.Value   = {10, 'mm', 0};
    % === METHOD
    sProcess.options.label2.Comment = '
Distance between vertices (v1,v2):';
    sProcess.options.label2.Type    = 'label';
    sProcess.options.method.Comment = {'Euclidean distance: norm(v1-v2)', ...
                                       'Path length: number of edges between v1 and v2', ...
                                       'Average: (euclidian distance + path length) / 2'};
    sProcess.options.method.Type    = 'radio';
    sProcess.options.method.Value   = 3;
end

%% ===== FORMAT COMMENT =====
function Comment = FormatComment(sProcess) %#ok<DEFNU>
    % Absolute values
    if isfield(sProcess.options, 'source_abs') && sProcess.options.source_abs.Value
        strAbs = ',abs';
    else
        strAbs = '';
    end
    % Method
    switch (sProcess.options.method.Value)
        case 1,    Method = 'euclidian';
        case 2,    Method = 'path';
        case 3,    Method = 'average';
        otherwise, error(['Unknown method: ' sProcess.options.method.Value]);
    end
    % Final comment
    Comment = sprintf('%s (%d%c%s)', sProcess.Comment, sProcess.options.fwhm.Value{1}, Method(1), strAbs);
end

%% ===== RUN =====
function sInput = Run(sProcess, sInput) %#ok<DEFNU>
    global GlobalData;
    % Get options
    FWHM = sProcess.options.fwhm.Value{1} / 1000;
    switch (sProcess.options.method.Value)
        case 1,    Method = 'euclidian';
        case 2,    Method = 'path';
        case 3,    Method = 'average';
        otherwise, error(['Unknown method: ' sProcess.options.method.Value]);
    end

    % ===== LOAD SURFACE =====
    % Load the surface filename from results file
    switch (file_gettype(sInput.FileName))
        case {'results', 'link'}
            FileMat = in_bst_results(sInput.FileName, 0, 'SurfaceFile', 'GridLoc', 'Atlas', 'nComponents', 'HeadModelType');
            nComponents = FileMat.nComponents;
        case 'timefreq'
            FileMat = in_bst_timefreq(sInput.FileName, 0, 'SurfaceFile', 'GridLoc', 'Atlas', 'HeadModelType');
            nComponents = 1;
        otherwise
            error('Unsupported file format.');
    end
    % Error: cannot smooth results on volume grids
    if ~strcmpi(FileMat.HeadModelType, 'surface') % ~isempty(FileMat.GridLoc)
        bst_report('Error', sProcess, sInput, 'Spatial smoothing is only supported for surface head models.');
        sInput = [];
        return;
    % Error: cannot smooth results that are already based on atlases
    elseif ~isempty(FileMat.Atlas)
        bst_report('Error', sProcess, sInput, 'Spatial smoothing is not supported for sources based on atlases.');
        sInput = [];
        return;
    % Error: only for constrained sources
    elseif (nComponents ~= 1)
        bst_report('Error', sProcess, sInput, ['This process is only available for source models with constrained orientations.' 10 'With unconstrained orientations, the source maps are usually already very smooth.']);
        sInput = [];
        return;
    end

    % ===== COMPUTE SMOOTHING OPERATOR =====
    % Get existing interpolation for this surface
    Signature = sprintf('ssmooth(%d,%s):%s', round(FWHM*1000), Method, FileMat.SurfaceFile);
    WInterp = [];
    if isfield(GlobalData, 'Interpolations') && ~isempty(GlobalData.Interpolations) && isfield(GlobalData.Interpolations, 'Signature')
        iInterp = find(cellfun(@(c)isequal(c,Signature), {GlobalData.Interpolations.Signature}), 1);
        if ~isempty(iInterp)
            WInterp = GlobalData.Interpolations(iInterp).WInterp;
        end
    end
    % Calculate new interpolation matrix
    if isempty(WInterp)
        % Load surface file
        SurfaceMat = in_tess_bst(FileMat.SurfaceFile);
        % Compute the smoothing operator
        WInterp = tess_smooth_sources(SurfaceMat.Vertices, SurfaceMat.Faces, SurfaceMat.VertConn, FWHM, Method);
        % Check for errors
        if isempty(WInterp)
            sInput = [];
            return;
        end
        % Save interpolation in memory for future calls
        sInterp = db_template('interpolation');
        sInterp.WInterp   = WInterp;
        sInterp.Signature = Signature;
        if isempty(GlobalData.Interpolations)
            GlobalData.Interpolations = sInterp;
        else
            GlobalData.Interpolations(end+1) = sInterp;
        end
    end

    % ===== APPLY TO THE DATA =====
    % Apply smoothing operator
    for iFreq = 1:size(sInput.A,3)
        sInput.A(:,:,iFreq) = WInterp * sInput.A(:,:,iFreq);
    end
    % Force the output comment
    sInput.CommentTag = [sProcess.FileTag, num2str(FWHM*1000), Method(1)];
    % Do not keep the Std field in the output
    if isfield(sInput, 'Std') && ~isempty(sInput.Std)
        sInput.Std = [];
    end
end


close all
clear
clc

%Select the degraded image
[filename, pathname] = uigetfile({'*.*';'*.bmp';'*.jpg'}, 'Select the Fingerprint image file');

%or_im, read the original image to work on
or_im = imread([pathname,filename]);

[fin_im] =  main_function(or_im);

%imshow(fin_im);
imagesc(fin_im);colormap(gray(256));


% This function output the support polygon depending on the current contact
% status

function CoM_limits = SupportPolygonWRTContactStatusFCN(contactStatus,Config)
CoM_limits = Config.CoM_limit_double;

if(and(contactStatus(1),contactStatus(2))) % Double Support
    CoM_limits = Config.CoM_limit_double;
elseif(and(~contactStatus(1),~contactStatus(2))) % Flying phase
    CoM_limits = Config.CoM_limit_double;
elseif(contactStatus(1)) % Left Foot contact
    CoM_limits =Config.CoM_limit_left;
elseif(contactStatus(2)) % Right Foot contact
    CoM_limits = Config.CoM_limit_right;
end
end


% This file is part of the project NILM-Eval (https://github.com/beckel/nilm-eval).
% Licence: GPL 2.0 (http://www.gnu.org/licenses/gpl-2.0.html)
% Copyright: ETH Zurich, 2014
% Author: Romano Cicchetti

function [plug] = getPlugNr(appliance, house, dataset)

    % returns the plug nr of a specified (appliance, house, dataset)-triple

    appliance_house_matrix = getApplianceHouseMatrix(dataset);
    plug = num2str(appliance_house_matrix(appliance, house), '%02d');

end


function id = get_official_id(joint_id)
    % Convert the joint id to MPII joint order to official id.
    % my joint: 1-14
    % official: 0-15
    order_to_MPI_official = [9 8 12 11 10 13 14 15 2 1 0 3 4 5];
    id = order_to_MPI_official(joint_id);
end


function value = p29_autonomous ( )

%*****************************************************************************80
%
%% P29_AUTONOMOUS reports whether problem P29 is autonomous.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, integer VALUE, is 1 if the equation is autonomous.
%
  value = 0;

  return
end


function jed = epoch_to_jed_persian ( )

%*****************************************************************************80
%
%% EPOCH_TO_JED_PERSIAN returns the epoch of the Persian calendar as a JED.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 June 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real JED, the Julian Ephemeris Date of the epoch.
%
  jed = 1952062.5;

  return
end


%--- help for complementarity_memoizer ---
%
%  Memoize linear and nonlinear restrictions
%
%  ::
%
%    [sep_cf,cf]=complementarity_memoizer(obj)
%
%  Args:
%
%     obj (rise | dsge | svar | rfvar): model object
%
%  Returns:
%     :
%
%     - **sep_cf** [function handle]: function that takes as input a vector of
%       variable values and returns a vector of values that are expected to be
%       greater than or equal to 0.
%
%     - **cf** [function handle]: function that takes as input a vector of
%       variable values and returns a true if all the restrictions are satisfied
%       and returns false otherwise
%
%


function [ nimg ] = num_images(  )
%NUM_IMAGES Determine number of images used in a NEB calculation.
%   N = NUM_IMAGES() determines the number of images used in an NEB
%   calculation by looking for directories 00, 01 ... N+1.

    a = dir;
    images = arrayfun(@(x) ~sum(~isstrprop(x.name,'digit')) & x.isdir , a);
    nimg = sum(images)-2;

end


function [cplx_str,cplx_inc,cplx_lib,cplx_libname,cplx_ver] = opti_FindCplex()
%Finds IBM ILOG CPLEX Libraries and returns path and version

%Known CPLEX path locations (Modify to suit your system by adding to cell arrays, or create a new structure for other versions)
CPLX1260.x64 = {'C:\Program Files\IBM\ILOG\CPLEX_Studio126\cplex\'};
CPLX1260.x86 = {'C:\Program Files (x86)\IBM\ILOG\CPLEX_Studio126\cplex\'};
CPLX1260.ver = '12.6';
CPLX1260.lib = 'cplex1260';
CPLX1260.vs  = 'VS2012';

CPLX1251.x64 = {'C:\Program Files\IBM\ILOG\CPLEX_Enterprise_Server1251\CPLEX_Studio\cplex\'};
CPLX1251.x86 = {'C:\Program Files (x86)\IBM\ILOG\CPLEX_Enterprise_Server1251\CPLEX_Studio\cplex\'};
CPLX1251.ver = '12.5.1';
CPLX1251.lib = 'cplex1251';
CPLX1251.vs  = 'VS2012';

CPLX125.x64 = {'C:\Program Files\IBM\ILOG\CPLEX_Studio125\cplex\'};
CPLX125.x86 = {'C:\Program Files (x86)\IBM\ILOG\CPLEX_Studio125\cplex\'};
CPLX125.ver = '12.5';
CPLX125.lib = 'cplex125';
CPLX125.vs  = 'VS2010';

CPLX124.x64 = {'C:\Program Files\IBM\ILOG\CPLEX_Studio_Academic124\cplex\'};
CPLX124.x86 = {'C:\Program Files (x86)\IBM\ILOG\CPLEX_Studio_Academic124\cplex\'};
CPLX124.ver = '12.4';
CPLX124.lib = 'cplex124';
CPLX124.vs  = 'VS2010';

%Add any new structures to below
CPLXLIB = {CPLX1260,CPLX1251,CPLX125,CPLX124};

%DO NOT MODIFY BELOW HERE
for i = 1:length(CPLXLIB)
    %Check for CPLEX
    [ok,cplx_str,cplx_inc,cplx_lib,cplx_libname,cplx_ver] = checkCPLXVer(CPLXLIB{i});
    if(ok), return; end
end

%Still no Luck - user must locate
error('Could not find the IBM ILOG CPLEX Location on your computer. Please modify this file to locate it');

function [ok,cplx_str,cplx_inc,cplx_lib,cplx_libname,cplx_ver] = checkCPLXVer(cplxstr)
%Local check function
ok = false;
%Defaults
cplx_str = []; cplx_inc = []; cplx_lib = []; cplx_libname = []; cplx_ver = [];
%Find local config paths
switch(computer)
    case 'PCWIN'
        if(~isfield(cplxstr,'x86') || isempty(cplxstr.x86))
            error('No x86 CPLEX directories specified to check');
        end
        paths = cplxstr.x86;
    case 'PCWIN64'
        if(~isfield(cplxstr,'x64') || isempty(cplxstr.x86))
            error('No x64 CPLEX directories specified to check');
        end
        paths = cplxstr.x64;
    otherwise
        error('This function is only setup for Windows PCs');
end
for i = 1:length(paths)
    if(exist(paths{i},'dir'))
        dir_cplx = paths{i};
        %Get Include Directory
        cplx_inc = [dir_cplx 'include\ilcplex'];
        if(~exist(cplx_inc,'dir'))
            error('Could not find Cplex include directory. Checked:\n %s',cplx_inc);
        end
        %Get Library Directory
        switch(computer)
            case 'PCWIN'
                switch(cplxstr.vs)
                    case 'VS2010'
                        cplx_lib = [dir_cplx 'lib\x86_windows_vs2010\stat_mda\'];
                    case 'VS2012'
                        cplx_lib = [dir_cplx 'lib\x86_windows_vs2012\stat_mda\'];
                end
            case 'PCWIN64'
                switch(cplxstr.vs)
                    case 'VS2010'
                        cplx_lib = [dir_cplx 'lib\x64_windows_vs2010\stat_mda\'];
                    case 'VS2012'
                        cplx_lib = [dir_cplx 'lib\x64_windows_vs2012\stat_mda\'];
                end
        end
        if(~exist(cplx_lib,'dir'))
            error('Could not find Cplex lib directory. Checked:\n %s\n',cplx_lib);
        end
        %Build complete linker line
        cplx_str = [' -I"' cplx_inc '" -L"' cplx_lib '" -l' cplxstr.lib ' '];
        cplx_libname = cplxstr.lib;
        cplx_ver = cplxstr.ver;
        ok = true;
        return;
    end
end


function linpack_d_test ( )

%*****************************************************************************80
%
%% LINPACK_D_TEST tests the LINPACK_D library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 June 2009
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'LINPACK_D_TEST\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the LINPACK_D library.\n' );

  linpack_d_test01 ( );
  linpack_d_test02 ( );
  linpack_d_test03 ( );
  linpack_d_test04 ( );
  linpack_d_test05 ( );
  linpack_d_test06 ( );
  linpack_d_test07 ( );
  linpack_d_test08 ( );
  linpack_d_test09 ( );

  linpack_d_test10 ( );
  linpack_d_test11 ( );
  linpack_d_test12 ( );
  linpack_d_test13 ( );
  linpack_d_test14 ( );
  linpack_d_test15 ( );
  linpack_d_test16 ( );
  linpack_d_test17 ( );
  linpack_d_test18 ( );
  linpack_d_test19 ( );

  linpack_d_test20 ( );
  linpack_d_test21 ( );
  linpack_d_test22 ( );
  linpack_d_test23 ( );
  linpack_d_test24 ( );
  linpack_d_test25 ( );
  linpack_d_test26 ( );
  linpack_d_test27 ( );
  linpack_d_test28 ( );
  linpack_d_test29 ( );

  linpack_d_test30 ( );
  linpack_d_test31 ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'LINPACK_D_TEST\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp;

  return
end


function [ t_start, y_start ] = p33_start ( neqn )

%*****************************************************************************80
%
%% P33_START returns the starting point for problem p33.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NEQN, the number of equations.
%
%    Output, real T_START, Y_START(NEQN,1), the initial data.
%
  y_start = zeros ( neqn, 1 );

  t_start = 0.0;
  y_start = [ 2.0; 2.0 ];

  return
end


function [sindex] = OrderingIndexes(varordering,varnames,newstrng)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 'OrderingIndexes' find the specified order of variables

% input:
% - varnames    = the list (names) of all the variables in the database
% - varordering = the names and the order of the variables in the VAR

% output:
% - sindex = the index in the varnames that correspond to the var ordering
% - index_XX = the index that the variable XXX has in the VAR

% Filippo Ferroni,
% Revised, 3/21/2018
% Revised, 9/11/2019
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin<3
    newstrng='';
end

[~,sindex] = ismember(varordering,varnames);
for ii = 1 : size(varordering,2)
    check=0;
    for jjj = 1: size(varnames,2)
         if strcmp(deblank(varnames{jjj}),deblank(varordering{ii})) == 1,
             check = 1;
         end
    end
    if check == 1
        assignin('base', [newstrng 'index_' varordering{ii} ], ii);
    else
        warning(['I did not find ' varordering{ii} ' in varnames'])
    end
end


function varargout = detectChange(alg_cd, config_alg_cd, alg_thre, config_alg_thre, varargin)
%detectChange Perform change detection on a given image pair or data folder.
%
% [CM, DI] = detectChange(alg_cd, config_alg_cd, alg_thre, config_alg_thre, path_t1, path_t2)
%
% returns the change map CM and the difference image DI. alg_cd specifies the name of the CD
% algorithm to use, and config_alg_cd is a cell array that contains the arguments to construct
% the CDAlg object. alg_thre specifies the name of the thresholding algorithm, with
% config_alg_thre being its corresponding configs. path_t1 and path_t2 are the absolute or
% relative paths to the input bi-temporal images.
%
% [CMs, DIs] = detectChange(alg_cd, config_alg_cd, alg_thre, config_alg_thre, data_dir)
%
% handles an image folder, which is specified by data_dir. The image folder
% should be structured as follows:
% |- DATA_DIR
% |     |- t1
% |     |- t2
% |     |_ gt
% where the gt subfolder is optional. t1 contains images acquired at the first time instance
% while t2 at the second time instance. see Datasets.Folder for more details. Note that the CMs
% and the DIs will be returned in cell arrays.
%
% [CM, DI, results] = detectChange(alg_cd, config_alg_cd, alg_thre, config_alg_thre, path_t1,
% path_t2, path_ref, metrics, configs_metrics)
%
% returns evaluation results, additionally. To enable the evaluation metrics, you will have
% to specify the path to the reference image, path_ref, and the names of the metrics to use.
% All names ought to be contained in the cell array metrics, and there should also be
% configuration cells for each metric, which are nested in the cell configs_metrics.
%
% [CMs, DIs, results] = detectChange(alg_cd, config_alg_cd, alg_thre, config_alg_thre, data_dir,
% metrics, configs_metrics)
%
% evaluates each image pair in a folder.In this case, the gt subfolder is required.
%

% Create instances
algCD = Algorithms.(alg_cd)(config_alg_cd{:});
algThre = ThreAlgs.(alg_thre)(config_alg_thre{:});
% Choose the right entrance
if nargin == 9
    % varargin being path_t1, path_t2, path_ref, metrics, and
    % config_metrics
    varargout = cell(1,3);
    [varargout{:}] = cd4Pair_(algCD, algThre, varargin{:});
elseif nargin == 7
    % varargin being dir_, metrics, and config_metrics
    varargout = cell(1,3);
    [varargout{:}] = cd4Dir_(algCD, algThre, varargin{:});
elseif nargin == 6
    % varargin being path_t1 and path_t2
    varargout = cell(1,2);
    [varargout{:}] = cd4Pair_(algCD, algThre, varargin{:}, '', {}, {});
elseif nargin == 5
    % varargin being dir_
    [varargout{1}, varargout{2}] = cd4Dir_(algCD, algThre, varargin{:}, {}, {});
else
    error('Wrong number of input arguments');
end
end

function [CMs, DIs, results] = cd4Dir_(alg_cd, alg_thre, dir_, metrics, configs)
dataset = Datasets.Folder(dir_);
iterator = Datasets.CDDIterator(dataset);

% Create metric instances
nMetrics = length(metrics);
meters = cell(1, nMetrics);
for ii = 1:nMetrics
    meters{ii} = Metrics.(metrics{ii})(configs{ii}{:});
end

DIs = {}; CMs = {};
% Do loop
while(iterator.hasNext())
    % Fetch data
    [t1, t2, ref] = iterator.nextChunk();
    % Check rank
    getRank = @(x) rank(reshape(double(x), size(x, 1)*size(x, 2), size(x, 3)));
    if getRank(t1) <= 1 || getRank(t2) <= 1
        warning('The rank of the input image is detected to be lower than 2.');
    end
    DI = alg_cd.detectChange(t1, t2);
    CM = alg_thre.segment(DI);
    if nMetrics > 0 %&& ~isempty(ref)
        % Update value
        cellfun(@(obj) obj.update(CM, ref, DI), meters);
        % Show logs
        for ii = 1:nMetrics
            m = meters{ii};
            fprintf('type: %s\n', metrics{ii});
            fprintf('\tnewest: %f\n', m.val(end));
            fprintf('\taverage: %f\n', m.avg);
        end
        fprintf('\n');
    end
    DIs = [DIs, DI];
    CMs = [CMs, CM];
end

results = struct();
for ii = 1:nMetrics
    results.(metrics{ii}) = meters{ii}.avg;
end
end

function [CM, DI, results] = cd4Pair_(alg_cd, alg_thre, path_t1, path_t2, path_ref, metrics, configs)
% Load data
imT1 = readFile__(path_t1);
imT2 = readFile__(path_t2);

% Check data redundancy
getRank = @(x) rank(reshape(double(x), size(x, 1)*size(x, 2), size(x, 3)));
if getRank(imT1) <= 1 || getRank(imT2) <= 1
    warning('The rank of the input image is detected to be lower than 2.');
end

DI = alg_cd.detectChange(imT1, imT2);
CM = alg_thre.segment(DI);

if  ~isempty(metrics)% && ~isempty(path_ref)
    ref = readFile__(path_ref);
    % Create metric instances
    nMetrics = length(metrics);
    meters = cell(1, nMetrics);
    for ii = 1:nMetrics
        meters{ii} = Metrics.(metrics{ii})(configs{ii}{:});
        meters{ii}.update(CM, ref, DI);
        results.(metrics{ii}) = meters{ii}.val;
    end
end

    function im = readFile__(path_)
        try
            % Try to read via default loader
            im = Datasets.Loaders.defaultLoader(path_);
        catch ME
            % Otherwise, read as envi file
            if strcmp(ME.identifier, 'MATLAB:imagesci:imread:fileFormat')
                im = Datasets.Loaders.enviLoader(path_);
            else
                rethrow(ME);
            end
        end
    end
end


function [epo, ev]= proc_selectClasses(epo, cls, varargin)
%PROC_SELECTCLASSES - select only a subset of the avialble classes
%
%Synopsis:
%[epo, ev]= proc_selectClasses(epo, classes)
%
% IN   epo     - epoched data structure
%      classes - cell array of classes names or vector of class indices
%
% OUT  epo     - epoch structure containing only selected events
%      ev      - indices of select events
%
%Description:
% This function selects events from a epoch structure that belong
% to given classes. a typical application is to select from a multi-class
% experiment a two-class subproblem.
% Class names may include regular expressions, see regexpi. This also
% implies that you might have to escape some characters, see last example.
%
% Examples
%      epo_lr= proc_selectClasses(epo, {'left', 'right'});
%      epo_12= proc_selectClasses(epo, [1 2]);
%      epo_nl= proc_selectClasses(epo, {'not', 'left*'});
%
%      epo= proc_selectClasses(epo, 'r\^2 \( a , b \)';

% Benjamin Blankertz

props_selectEvents= proc_selectEpochs;

if nargin==0,
  epo= props_selectEvents; return
end

misc_checkType(epo, 'STRUCT(className y)');
epo= misc_history(epo);

opt= opt_proplistToStruct(varargin{:});

clInd= procutil_getClassIndices(epo, cls);
ev= find(any(epo.y(clInd,:)==1,1));

%% the following is done to keep the order of classes as specified
epo.y= epo.y(clInd,:);
epo.className= epo.className(clInd);

%% the following is to avoid an error in proc_selectEpochs
if length(ev)==size(epo.y,2)
  return;
end

epo= proc_selectEpochs(epo, ev, opt);


function data = memmap_file_sequence(foldername)

% read a sequence of stacked tiff arrays, reshapes it to 2d array and saves it a mat file that can be memory mapped.
% The file is saved both in its original format and as a reshaped 2d matrix

% INPUTS
% foldername:     path to tiff folder containing a series of tiff files

% OUTPUT
% data:         object with the data containing:
%   Yr:         reshaped data file
% sizY:         dimensions of original size
%   nY:         minimum value of Y (not subtracted from the dataset)

% Author: Eftychios A. Pnevmatikakis, Simons Foundation, 2016

nY = Inf;
files = dir([foldername,'/*.tif']);
T = 0;
data = matfile([foldername,'/',files(1).name(1:end-8),'.mat'],'Writable',true);
tt1 = tic;
for i = 1:length(files)
    filename = [foldername,'/',files(i).name];
    Y = tiff_reader(filename);
    sizY = size(Y);
    Yr = reshape(Y,prod(sizY(1:end-1)),[]);
    if i == 1; data.Yr(size(Yr,1),size(Yr,2)*length(files)) = single(0); end
    nY = min(min(Yr(:)),nY);
    if length(sizY) == 3
        if i == 1; data.Y(sizY(1),sizY(2),sizY(3)*length(files)) = single(0); end
        data.Y(1:sizY(1),1:sizY(2),T+(1:size(Yr,2))) = single(Y);
    elseif legnth(sizY) == 4
        if i == 1; data.Y(sizY(1),sizY(2),sizY(3),sizY(4)*length(files)) = single(0); end
        data.Y(1:sizY(1),1:sizY(2),1:sizY(3),T+(1:size(Yr,2))) = single(Y);
    end
    data.Yr(1:prod(sizY(1:end-1)),T+(1:size(Yr,2))) = single(Yr);
    T = sizY(end) + T;
    toc(tt1);
end
sizY(end) = T;
data.sizY = sizY;
data.nY = nY;


function s = tt_intvec2str(v)
%TT_VEC2STR Print integer vector to a string with brackets.
%
%MATLAB Tensor Toolbox.
%Copyright 2012, Sandia Corporation.

% This is the MATLAB Tensor Toolbox by T. Kolda, B. Bader, and others.
% http://www.sandia.gov/~tgkolda/TensorToolbox.
% Copyright (2012) Sandia Corporation. Under the terms of Contract
% DE-AC04-94AL85000, there is a non-exclusive license for use of this
% work by or on behalf of the U.S. Government. Export of this data may
% require a license from the United States Government.
% The full license terms can be found in the file LICENSE.txt

if isempty(v)
    s = sprintf('[]');
    return;
end

s = ['[ ' sprintf('%d ',v(1:end)) ']'];


classdef Resampler < Algorithm

    properties (Access = public)
        samplingInterval = 1;
    end

    methods (Access = public)

        function obj = Resampler(samplingInterval)
            if nargin > 0
                obj.samplingInterval = samplingInterval;
            end
            obj.name = 'resampler';
            obj.inputPort = DataType.kSignal;
            obj.outputPort = DataType.kSignal;
        end

        function dataFiltered = compute(obj,data)
            dataFiltered = data(1:obj.samplingInterval:end,:);
        end

        function str = toString(obj)
            str = sprintf('%s_%d',obj.name,obj.samplingInterval);
        end

        function editableProperties = getEditableProperties(obj)
            editableProperties = Property('samplingInterval',obj.samplingInterval,1,100);
        end
    end
end


function p08_default ( dim_num )

%*****************************************************************************80
%
%% P08_DEFAULT sets default values for problem 08.
%
%  Discussion:
%
%    If a problem uses vector parameters, then the spatial dimension
%    DIM_NUM is needed as input, so that the vector parameters can be
%    properly dimensioned.
%
%    Every problem keeps a count of the number of function calls.  Calling
%    this routine causes that count to be reset to 0.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the dimension of the problem.
%
  i4 = 0;
  p08_i4 ( 'D', '*', i4 );

  return
end


function Problem = UFget (matrix, UF_Index)
%UFGET loads a matrix from the UF Sparse Matrix Collection.
%
%   Problem = UFget(matrix) loads a matrix from the UF sparse matrix collection,
%   specified as either a number (1 to the # of matrices in the collection) or
%   as a string (the name of the matrix).  With no input parameters, index=UFget
%   returns an index of matrices in the collection.  A local copy of the matrix
%   is saved (be aware that as of March 2008 the entire collection is 9.5GB
%   in size).  If no input or output arguments are provided, the index is
%   printed.  With a 2nd parameter (Problem = UFget (matrix, index)), the index
%   file is not loaded.  This is faster if you are loading lots of matrices.
%
%   Examples:
%       index = UFget ;                     % loads index
%       index = UFget ('refresh') ;         % forces download of new index
%
%       Problem = UFget (6)                 % 4 ways of loading the same Problem
%       Problem = UFget ('HB/arc130')
%       Problem = UFget (6, index)
%       Problem = UFget ('HB/arc130', index)
%
%   See also UFgrep, UFweb, UFget_example, UFget_defaults, urlwrite.

%   Copyright 2008, Tim Davis, University of Florida.

%-------------------------------------------------------------------------------
% get the parameter settings
%-------------------------------------------------------------------------------

params = UFget_defaults ;
indexfile = sprintf ('%sUF_Index.mat', params.dir) ;
indexurl = sprintf ('%s/UF_Index.mat', params.url) ;

%-------------------------------------------------------------------------------
% get the index file (download a new one if necessary)
%-------------------------------------------------------------------------------

refresh = 0 ;
if nargin == 0
    % if the user passed in a zero or no argument at all, return the index file
    matrix = 0 ;
else
    % UFget ('refresh') downloads the latest index file from the web
    if (ischar (matrix))
        if (strcmp (matrix, 'refresh'))
            matrix = 0 ;
            refresh = 1 ;
        end
    end
end

if (~refresh)
    try
        % load the existing index file
        if (nargin < 2)
            load (indexfile) ;
        end
        % see if the index file is old; if so, download a fresh copy
        refresh = (UF_Index.DownloadTimeStamp + params.refresh < now) ;
    catch
        % oops, no index file, or a refresh is due.  download it.
        refresh = 1 ;
    end
end

err = '' ;      % to catch a download error, if any

if (refresh)
    % a new UF_Index.mat file to get access to new matrices (if any)
    try
        tmp = tempname ;                        % download to a temp file first
        old = sprintf ('%sUF_Index_old.mat', params.dir) ;
        urlwrite (indexurl, tmp) ;              % download the latest index file
        try
            movefile (indexfile, old, 'f') ;    % keep a backup of the old index
        catch
            % backup failed, continue anyway
        end
        movefile (tmp, indexfile, 'f') ;        % move the new index into place
    catch
        err = lasterr ;
    end
    load (indexfile) ;
    UF_Index.DownloadTimeStamp = now ;
    save (indexfile, 'UF_Index') ;
end

%-------------------------------------------------------------------------------
% return the index file if requested
%-------------------------------------------------------------------------------

if (matrix == 0)
    if (nargout == 0)
        % no output arguments have been passed, so print the index file
        fprintf ('\nUF sparse matrix collection index:  %s\n', ...
            UF_Index.LastRevisionDate) ;
        fprintf ('\nLegend:\n') ;
        fprintf ('(p,n)sym:  symmetry of the pattern and values\n') ;
        fprintf ('           (0 = unsymmetric, 1 = symmetric, - = not computed)\n') ;
        fprintf ('type:      real\n') ;
        fprintf ('           complex\n') ;
        fprintf ('           binary:  all entries are 0 or 1\n') ;
        nmat = length (UF_Index.nrows) ;
        for j = 1:nmat
            if (mod (j, 25) == 1)
                fprintf ('\n') ;
                fprintf ('ID   Group/Name                nrows-by-  ncols  nonzeros  (p,n)sym  type\n') ;
            end
            s = sprintf ('%s/%s', UF_Index.Group {j}, UF_Index.Name {j}) ;
            fprintf ('%4d %-30s %7d-by-%7d %9d ', ...
            j, s, UF_Index.nrows (j), UF_Index.ncols (j), UF_Index.nnz (j)) ;
            psym = UF_Index.pattern_symmetry (j) ;
            nsym = UF_Index.numerical_symmetry (j) ;
            if (psym < 0)
                fprintf ('  -  ') ;
            else
                fprintf (' %4.2f', psym) ;
            end
            if (nsym < 0)
                fprintf ('  -  ') ;
            else
                fprintf (' %4.2f', nsym) ;
            end
            if (UF_Index.isBinary (j))
                fprintf (' binary\n') ;
            elseif (~UF_Index.isReal (j))
                fprintf (' complex\n') ;
            else
                fprintf (' real\n') ;
            end
        end
    else
        Problem = UF_Index ;
    end

    if (~isempty (err))
        fprintf ('\nUFget: unable to download latest index; using old one.\n') ;
        disp (err) ;
    end
    return ;
end

%-------------------------------------------------------------------------------
% determine if the matrix parameter is a matrix index or name
%-------------------------------------------------------------------------------

[group matrix id] = UFget_lookup (matrix, UF_Index) ;

if (id == 0)
    error ('invalid matrix') ;
end

%-------------------------------------------------------------------------------
% download the matrix (if needed) and load it into MATLAB

matdir = sprintf ('%s%s%s%s.mat', params.dir, group) ;
matfile = sprintf ('%s%s%s.mat', matdir, filesep, matrix) ;
maturl = sprintf ('%s/%s/%s.mat', params.url, group, matrix) ;

if (~exist (matdir, 'dir'))
    mkdir (matdir) ;                        % create the Group directory
end

if (~exist (matfile, 'file'))
    fprintf ('downloading %s\n', maturl) ;
    fprintf ('to %s\n', matfile) ;
    tmp = tempname ;                        % download to a temp file first
    urlwrite (maturl, tmp) ;
    movefile (tmp, matfile, 'f') ;          % move the new matrix into place
end

load (matfile) ;


% Visualization of the classifier neurons. Modify the targetclass variable
% to see other classes.
% Please feel free to modify all the switches in line 40 - 46 and width,
% height, scale, rotate variables to see what happens.
% The best visualization can be produced by setting use_image_blur = true
% and use_image_deblur = true, with all other switches are turned to false.
% However, with no constraints, you can still get recognizable images.
% Feel the magic by your self!
%
% This code is messay, I will refactor it in the future.
% Based on paper:
% Feng Wang, Haijun Liu, Jian Cheng,
% Visualizing Deep Neural Network by Alternately Image Blurring and Deblurring
caffe.reset_all();
caffe.set_mode_gpu();
gpu_id = 0;  % we will use the first gpu in this demo
caffe.set_device(gpu_id);

% net_model = 'D:\deeplearning\caffe-windows\examples\GoogLeNet\googlenet_deploy_prob3.prototxt';
% net_weights = 'D:\deeplearning\caffe-windows\examples\GoogLeNet\imagenet_googlenet.caffemodel';
net_model ='D:\deepLearning\caffe-windows\models\bvlc_googlenet\deploy.prototxt';
net_weights = 'D:\deepLearning\caffe-windows\models\bvlc_googlenet\thinned.caffemodel';
% mean_file = 'D:\deeplearning\caffe-windows\examples\GoogLeNet\imagenet_mean.binaryproto';

% net_model = 'D:\deeplearning\caffe-windows\examples\PlaceCNN\hybridCNN_deploy_upgraded.prototxt';
% net_weights = 'D:\deeplearning\caffe-windows\examples\PlaceCNN\hybridCNN_iter_700000_upgraded.caffemodel';
% mean_file = 'D:\deeplearning\caffe-windows\examples\PlaceCNN\hybridCNN_mean.binaryproto';

% net_model = 'D:\deeplearning\caffe-windows\examples\VGG\VGG_ILSVRC_16_layers_deploy.prototxt';
% net_weights = 'D:\deeplearning\caffe-windows\examples\VGG\VGG_ILSVRC_16_layers.caffemodel';
% mean_file = [];
% vgg_mean =  [103.939, 116.779, 123.68];
% net_model = 'D:\deeplearning\caffe-windows\models\bvlc_googlenet\deploy.prototxt';
% net_weights = 'D:\deeplearning\caffe-windows\models\bvlc_googlenet\bvlc_googlenet.caffemodel';
mean_file = [];
vgg_mean =  [103.939, 116.779, 123.68];

%%%%%%%%%extract the train features
train_net = caffe.Net(net_model,net_weights,'test');
use_clip = false;
use_cv_norm = false;
use_weight_decay = false;
use_image_blur = true;
use_image_deblur = true;
use_gradient_blur = false;
use_dropout = false;

for targetclass = 13:13
%     if exist(['gallery\' num2str(targetclass) '.png'],'file')
%         continue;
%     end;
if ~isempty(mean_file)
    mean_image = caffe.read_mean(mean_file);
    mean_image = mean_image(16:242,16:242,:);
else
    mean_image = permute(repmat(vgg_mean',[1,224,224]),[2,3,1]);
end;
% mean_image = mean_image + randn(size(mean_image));
input_data = zeros(size(mean_image,1), size(mean_image,2), 3, 1, 'single');

width = 300;
height = 300;
meanV = mean(mean_image(:));
BigImage = permute(repmat(vgg_mean',[1,height,width]),[2,3,1]);%this image will be transposed
H = fspecial('gaussian',[7 7],1.2);

if length(targetclass) > 1
    sample_density = 2;
    class_center = zeros(sample_density*length(targetclass),2);
    for i = 1:sample_density*length(targetclass)
        class_center(i,1) = randi(height - size(mean_image,1),1,1) + size(mean_image,1) / 2;
        class_center(i,2) = randi(width - size(mean_image,2),1,1) + size(mean_image,2) / 2;
        if i > 1
            min_distance = min(pdist2(class_center(i,:),class_center(1:i-1,:)));
            while min_distance < size(mean_image,1) / 2
                class_center(i,1) = randi(height - size(mean_image,1),1,1) + size(mean_image,1) / 2;
                class_center(i,2) = randi(width - size(mean_image,2),1,1) + size(mean_image,2) / 2;
                min_distance = min(pdist2(class_center(i,:),class_center(1:i-1,:)));
            end;
        end;
    end;

    class_label = repmat(targetclass,1,sample_density);
end;

blur_data = zeros(size(input_data));
base_lr = 5000;
max_lr = 5000;
lambda1 = 0.01;
lambda2 = 0.1;
lambda3 = 300;
last_prob = -999;
momentum = 0.8;
lastgrad = zeros(size(mean_image));
mask = ones(size(mean_image,1), size(mean_image,2));
iter = 1;
dropout = 0.5;
sep_iter = zeros(ceil((height - size(mean_image,1)) / size(mean_image,1) *2),ceil((width - size(mean_image,2)) / size(mean_image,2) * 2));
erode = 5;
start_sigma = 1.2;
end_sigma = 0.5;
this_sigma = start_sigma;
sigma_decay = 0.99;
deblur_sigma_ratio = 0.8;
scale = [0.8 1.2];
rotate = [0 0] / 180 * pi;
func_loss = [];
BigGrad = zeros(size(BigImage));

while 1
%     for i = 0:size(mean_image,1) / 2:height - size(mean_image,1)
%         for j = 0:size(mean_image,2) / 2:width - size(mean_image,2)
            this_sigma = this_sigma * sigma_decay;
            if this_sigma < end_sigma
                this_sigma = end_sigma;
            end;
            s = rand(1) * (scale(2)-scale(1)) + scale(1);
            r = rand(1) * (rotate(2)-rotate(1)) + rotate(1);
            if length(targetclass)>1 && iter < 500
                idx = randi(size(class_center,1),1,1);
                x = class_center(idx,1) - size(mean_image,1) / 2;
                y = class_center(idx,2) - size(mean_image,2) / 2;
            else
                if rand() > size(mean_image,1) / height
                    x = randi(height - floor(size(mean_image,1) * s),1,1);% + size(mean_image,1) / 2;
                else
                    pos = randi(2,1,1)-1;
                    x = pos*(height - floor(size(mean_image,1) * s));
                end;
                if rand() > size(mean_image,2) / width
                    y = randi(width - floor(size(mean_image,2) * s),1,1);% - size(mean_image,2) / 2;
                else
                    pos = randi(2,1,1)-1;
                    y = pos*(width - floor(size(mean_image,2) * s));
                end;
            end;

            II = zeros(floor(size(mean_image,1) * s),floor(size(mean_image,2) * s),3);
            II(:,:,1) = BigImage(x + 1:x + floor(size(mean_image,1) * s),y + 1:y + floor(size(mean_image,2) * s),1) - vgg_mean(1);
            II(:,:,2) = BigImage(x + 1:x + floor(size(mean_image,1) * s),y + 1:y + floor(size(mean_image,2) * s),2) - vgg_mean(2);
            II(:,:,3) = BigImage(x + 1:x + floor(size(mean_image,1) * s),y + 1:y + floor(size(mean_image,2) * s),3) - vgg_mean(3);
            input_data(:,:,:,1) = imresize(imrotate(II,r),[size(mean_image,1), size(mean_image,2)]);
            GG = BigGrad(x + 1:x + floor(size(mean_image,1) * s),y + 1:y + floor(size(mean_image,2) * s),:);
            last_grad = imresize(GG,[size(mean_image,1), size(mean_image,2)]);
            for k = 1 : 10

                lr = base_lr;% * sqrt(this_prob / (1 - this_prob));

                prob = train_net.forward({input_data});

                    this_prob = prob{end}(targetclass);
                [max_prob,max_idx] = max(this_prob);
                fprintf('iter=%d,lr=%f,max_idx=%d,prob1=%f,last_prob=%f,this_sigma=%f\n',iter,lr,max_idx,this_prob(max_idx),last_prob,this_sigma);
                func_loss = [func_loss; this_prob(max_idx)];

                if k==1
                    back_data = ones(size(prob{1}),'single') * -1;
%                     back_data = zeros(size(prob{end}),'single');
                    if length(targetclass) >1
                        center_x = x + size(mean_image,1) / 2;
                        center_y = y + size(mean_image,2) / 2;
                        distances = pdist2([center_x center_y],class_center);
                        distances = exp(-(distances / size(mean_image,1) * 4).^2);
                        distances = distances / sum(distances);
                        distances = reshape(distances,length(targetclass),sample_density);
                        distances = sum(distances,2);
                        distances = distances * 2 - 1;
                        back_data(targetclass) = distances';
                    else
                        back_data(targetclass(max_idx)) = 1;
                    end;

                    back_cell = cell(length(prob),1);
%                     back_cell{1} = zeros(size(back_data));
%                     back_cell{2} = zeros(size(back_data));
%                     back_cell{1} = back_data;
%                     back_cell{2} = back_data;
                    back_cell{1} = back_data;
                end;

                iter = iter + 1;

%                 sep_iter(floor(i / size(mean_image,1) * 2)+1,floor(j/size(mean_image,1)*2) + 1) = sep_iter(floor(i / size(mean_image,1) * 2)+1,floor(j/size(mean_image,1)*2) + 1) + 1;

                if max_prob<last_prob
                    base_lr = base_lr * 0.99;
            %         input_data = bak_data;
                end;
                if max_prob>last_prob&&base_lr<max_lr%&& (this_prob-last_prob) / this_prob < 0.001
                    base_lr = base_lr * 1.01;
            %         input_data = bak_data;
                end;
            %     if this_prob>last_prob
                    last_prob = max_prob;
            %     end;

                res = train_net.backward(back_cell);

                bak_data = input_data;

                if use_clip
                    app_gradient = sum(abs(res{1} .* input_data(:,:,:,1)),3);
                    app_gradient = app_gradient < mean(app_gradient(:));
                    grad = reshape(res{1},[size(mean_image,1)*size(mean_image,2) 3]);
                    grad(app_gradient==1,:) = 0;
                    grad = reshape(grad,size(input_data));
                    res{1} = grad;
                end;

                input_data(:,:,:,1) = input_data(:,:,:,1) + res{1} * 1.5 / mean(abs(res{1}(:)));

                if use_cv_norm
                    I = input_data(:,:,:,1);
                    Gx = smoothL1(I(2:end-1,:,:) - I(1:end-2,:,:)) - smoothL1(I(3:end,:,:) - I(2:end-1,:,:));
                    Gx = [smoothL1(I(1,:,:) - I(2,:,:)); Gx; smoothL1(I(end,:,:) - I(end-1,:,:))];
                    Gy = smoothL1(I(:,2:end-1,:) - I(:,1:end-2,:)) - smoothL1(I(:,3:end,:) - I(:,2:end-1,:));
                    Gy = [smoothL1(I(:,1,:) - I(:,2,:)) Gy smoothL1(I(:,end,:) - I(:,end-1,:))];
                    input_data(:,:,:,1) = input_data(:,:,:,1) - lr * lambda2 * (Gx + Gy);
                end;
                if use_weight_decay
                    input_data(:,:,:,1) = input_data(:,:,:,1) - lambda1 * input_data(:,:,:,1);
                end;

                if k==1
                    H = fspecial('gaussian',[randi(6)+4 7],this_sigma);
                    if use_image_blur
                        input_data(:,:,:,1) = imfilter(input_data(:,:,:,1),H,'same');
                    end
                end;
                if k==6
                    H = fspecial('gaussian',[randi(6)+4 7],this_sigma * deblur_sigma_ratio);
                    if use_image_deblur
                        input_data(:,:,:,1) = deconvlucy(input_data(:,:,:,1), H);
                    end;
                end;

                if lr<0.000001
                    break;
                end;
            end;
            II = imresize(imrotate(input_data(:,:,:,1),-r),floor([size(mean_image,1), size(mean_image,2)] * s));
            BigImage(x + 1+erode:x + floor(size(mean_image,1) * s)-erode,y + 1+erode:y + floor(size(mean_image,2) * s)-erode,1) = II(erode+1:end-erode,erode+1:end-erode,1) + vgg_mean(1);
            BigImage(x + 1+erode:x + floor(size(mean_image,1) * s)-erode,y + 1+erode:y + floor(size(mean_image,2) * s)-erode,2) = II(erode+1:end-erode,erode+1:end-erode,2) + vgg_mean(2);
            BigImage(x + 1+erode:x + floor(size(mean_image,1) * s)-erode,y + 1+erode:y + floor(size(mean_image,2) * s)-erode,3) = II(erode+1:end-erode,erode+1:end-erode,3) + vgg_mean(3);
            GG = imresize(last_grad,floor([size(mean_image,1), size(mean_image,2)] * s));
            BigGrad(x + 1+erode:x + floor(size(mean_image,1) * s)-erode,y + 1+erode:y + floor(size(mean_image,2) * s)-erode,:) = GG(erode+1:end-erode,erode+1:end-erode,:);
%             sort_data = sort(BigImage(:));
%             BigImage = BigImage .* (255 / sort_data(floor(length(sort_data) * 0.999)));
            if mod(iter,100)==1
                figure(2);
                % imshow(uint8(mean_image + input_data));
                output = BigImage;
                output = output(:, :, [3, 2, 1]);
                output = permute(output, [2 1 3]);
                output = output(erode+1:end-erode,erode+1:end-erode,:);
                sort_output = sort(output(:));
                output = output .* (255 / sort_output(floor(length(sort_output) * 0.99)));
                imshow(uint8(output));
                figure(3);
%                 hist(output(:),1000);
                plot(1:iter-1, func_loss);
            end;
            if iter > 1500
                break;
            end;
%         end;
%     end;
end;
LastBigImage = BigImage;
imwrite(uint8(output),['gallery\' num2str(targetclass) '.png']);
end;


function simon(varargin)
%SIMON Do what Simon Says...
%   SIMON starts the standard game.
%   SIMON(N) starts the game with N keys.
%
%   Instructions:
%   - Press the start button (the green triangle pointing to the right) to
%     start the game.
%   - Look and listen to what Simon says and repeat it.
%   - Press the stop button (the red square) to stop the game.
%   - Press the up and down buttons (the yellow triangles pointing up and
%     down) to change the number of buttons.
%   - The numbers in the middle give the current score, the high score and
%     the numbers of buttons.
%
%   Example:
%     simon    start the standard game with four buttons.
%     simon(6) start the game with six buttons.

%   Eduard van der Zwan, 21-Jan-2007

%handle input
if nargin==0
    numberOfButtons=4;
elseif nargin==1
    numberOfButtons=varargin{1};
    if ~isnumeric(numberOfButtons)||rem(numberOfButtons,1)~=0||numberOfButtons<=1
        error('Input must be an integer larger then 1.')
    end
else
    error('Too many input arguments.')
end

%load high score file
highScoreFile=[fileparts(which(mfilename)) filesep 'simonHighScore.mat'];
if exist(highScoreFile,'file')
    load(highScoreFile)
    if length(highScore)<numberOfButtons
        %we started with a high number of buttons
        highScore(numberOfButtons)=0;
    end
else
    highScore=zeros(numberOfButtons,1);
end
%create figure
h.figure=figure(...
    'Name','Simon',...
    'NumberTitle','off',....
    'Color','k',...
    'Toolbar','none',...
    'MenuBar','none',...
    'CloseRequestFcn',@closeRequest);

%user data
g=struct(...
    'buttonTime',0.2,...seconds
    'intervalTime',0.3,...seconds
    'sampleFrequency',10000,...Hz
    'dimRatio',0.5,...ratio between lid and dimmed button color
    'innerRadius',1.2,...of the big buttons
    'outerRadius',3,...of the big buttons
    'buttonStepRatio',0.1,...ratio between gap and button size
    'startButtonColor',[0 1 0],...green
    'stopButtonColor',[1 0 0],...red
    'upDownButtonColor',[1 1 0],...yellow
    'buttonRadius',0.2,...of the small button
    'oldPosition',get(h.figure,'Position'),...
    'numberOfButtons',numberOfButtons,...
    'highScore',highScore,...
    'highScoreFile',highScoreFile,...
    'userSequence',[],...
    'simonSequence',[],...
    'playUserSequence',false);

set(h.figure,'UserData',g);

%create axes
h.axes=axes(...
    'DataAspectRatio',[1 1 1],...
    'NextPlot','add',...
    'Visible','off',...
    'Parent',h.figure);

%create small buttons
%location of buttuns relative to origin
xButton=[-2 -2 2 2]*g.buttonRadius;
yButton=[2 -2 2 -2]*g.buttonRadius;

%create start button
angle=linspace(0,2*pi,4);
x=xButton(1)+cos(angle)*g.buttonRadius;
y=yButton(1)+sin(angle)*g.buttonRadius;
h.startButton=patch(...
    x,y,g.startButtonColor,...
    'EdgeColor','none',...
    'Parent',h.axes,...
    'BusyAction','cancel',...
    'Interruptible','off');

%create stop button
angle=linspace(0.25*pi,2.25*pi,5);
x=xButton(2)+cos(angle)*g.buttonRadius;
y=yButton(2)+sin(angle)*g.buttonRadius;
h.stopButton=patch(...
    x,y,g.stopButtonColor*g.dimRatio,...
    'EdgeColor','none',...
    'Parent',h.axes,...
    'BusyAction','cancel',...
    'Interruptible','off');

%create up button
angle=linspace(0.5*pi,2.5*pi,4);
x=xButton(3)+cos(angle)*g.buttonRadius;
y=yButton(3)+sin(angle)*g.buttonRadius;
h.upButton=patch(...
    x,y,g.upDownButtonColor,...
    'EdgeColor','none',...
    'Parent',h.axes,...
    'BusyAction','cancel',...
    'Interruptible','off');

%create down button
angle=linspace(1.5*pi,3.5*pi,4);
x=xButton(4)+cos(angle)*g.buttonRadius;
y=yButton(4)+sin(angle)*g.buttonRadius;
h.downButton=patch(...
    x,y,g.upDownButtonColor,...
    'EdgeColor','none',...
    'Parent',h.axes,...
    'BusyAction','cancel',...
    'Interruptible','off');

%create score text
h.score=text(...
    'Parent',h.axes,...
    'HorizontalAlignment','Center',...
    'VerticalAlignment','Middle',...
    'FontSize',18,...
    'FontWeight','Bold',...
    'Color','w');
setScore(h)

%create buttons in circle
createButtons(h)

function createButtons(h)
%create buttons in the circle
g=get(h.figure,'UserData');

%determine colors and sounds
%about sounds:
%   the 'A' has a frequency of 440 Hz. All other frequncies of the piano
%   keys can be be determined with:
%       keyFrequency=440*2^(keyNumber/12)
%   in which keyNumber is the number of the key relative to the 'A' key;
%   with 'A' being 0, left of that key minus numbers, and right of that key
%   plus numbers
if g.numberOfButtons==4
    %original colors and sounds
    buttonCollor=[1 0 0;0 1 0;1 1 0;0 0 1]*g.dimRatio;
    %red = [1 0 0], green = [0 1 0], yellow = [1 1 0] and blue = [0 0 1]
    buttonFrequency=440*2.^([0 12 10 5]/12);
    %A = 0, a = 12, G = 10 and D = 5
else
    buttonCollor=hsv(g.numberOfButtons)*g.dimRatio;
    buttonFrequency=440*2.^((0:g.numberOfButtons-1)/12);
end

buttonWidthAngle=2*pi/g.numberOfButtons;
outerAngleStep=buttonWidthAngle*g.buttonStepRatio;
innerAngleStep=outerAngleStep*g.outerRadius/g.innerRadius;

h.button=[];
for buttonNumber=1:g.numberOfButtons
    %user data for button
    signalVector=sin(linspace(0,buttonFrequency(buttonNumber)*g.buttonTime*2*pi,g.sampleFrequency*g.buttonTime));
    b=struct(...
        'signalVector',signalVector,...
        'buttonNumber',buttonNumber);
    %draw button
    buttonAngle=(buttonNumber-1)*buttonWidthAngle;
    innerArc=linspace(buttonAngle,buttonAngle+buttonWidthAngle-innerAngleStep,20)+innerAngleStep/2;
    outerArc=linspace(buttonAngle,buttonAngle+buttonWidthAngle-outerAngleStep,40)+outerAngleStep/2;
    x=[g.innerRadius*cos(innerArc) g.outerRadius*cos(fliplr(outerArc))];
    y=[g.innerRadius*sin(innerArc) g.outerRadius*sin(fliplr(outerArc))];
    h.button(buttonNumber)=patch(...
        x,y,buttonCollor(buttonNumber,:),...
        'EdgeColor','none',...
        'Parent',h.axes,...
        'UserData',b,...
        'BusyAction','cancel',...
        'Interruptible','off');
end

%set object functions including the handles to above buttons
for buttonNumber=1:g.numberOfButtons
    set(h.button(buttonNumber),'ButtonDownFcn',{@buttonDown,h})
end
set(h.startButton,'ButtonDownFcn',{@startButtonDown,h});
set(h.stopButton,'ButtonDownFcn',{@stopButtonDown,h});
set(h.upButton,'ButtonDownFcn',{@upButtonDown,h});
set(h.downButton,'ButtonDownFcn',{@downButtonDown,h});
set(h.figure,'ResizeFcn',{@resize,h})

function startButtonDown(hStartButton,eventdata,h)
%start button is pressed
g=get(h.figure,'UserData');
startButtonColor=get(hStartButton,'FaceColor');
if isequal(startButtonColor,g.startButtonColor)
    %make buttons inactive
    set(hStartButton,'FaceColor',g.startButtonColor*g.dimRatio)
    set(h.upButton,'FaceColor',g.upDownButtonColor*g.dimRatio)
    set(h.downButton,'FaceColor',g.upDownButtonColor*g.dimRatio)
    %make stop button active
    set(h.stopButton,'FaceColor',g.stopButtonColor)
    playSimonSequence(h)
end

function stopButtonDown(hStopButton,eventdata,h)
%stop button is pressed
g=get(h.figure,'UserData');
stopButtonColor=get(hStopButton,'FaceColor');
if isequal(stopButtonColor,g.stopButtonColor)
    %make stop button inactive
    set(hStopButton,'FaceColor',g.stopButtonColor*g.dimRatio)
    %make buttons active
    set(h.startButton,'FaceColor',g.startButtonColor)
    set(h.upButton,'FaceColor',g.upDownButtonColor)
    set(h.downButton,'FaceColor',g.upDownButtonColor)
    %reset data
    g.userSequence=[];
    g.simonSequence=[];
    g.playUserSequence=false;
    set(h.figure,'UserData',g)
end

function upButtonDown(hUpButton,eventdata,h)
%up button is pressed
g=get(h.figure,'UserData');
upButtonColor=get(hUpButton,'FaceColor');
if isequal(upButtonColor,g.upDownButtonColor)
    g.numberOfButtons=g.numberOfButtons+1;
    %expand high score
    if length(g.highScore)<g.numberOfButtons
        g.highScore(g.numberOfButtons)=0;
    end
    set(h.figure,'UserData',g)
    setScore(h)
    delete(h.button)
    %create buttons in circle
    createButtons(h)
end

function downButtonDown(hDownButton,eventdata,h)
%down button is pressed
g=get(h.figure,'UserData');
downButtonColor=get(hDownButton,'FaceColor');
if isequal(downButtonColor,g.upDownButtonColor) && g.numberOfButtons>2
    g.numberOfButtons=g.numberOfButtons-1;
    set(h.figure,'UserData',g)
    setScore(h)
    delete(h.button)
    %create buttons in circle
    createButtons(h)
end

function buttonDown(hButton,eventdata,h)
%a button in the circle is pressed
g=get(h.figure,'UserData');
b=get(hButton,'UserData');

dimColor=get(hButton,'FaceColor');
litColor=dimColor/g.dimRatio;
%lid button and play sound
set(hButton,'FaceColor',litColor)
sound(b.signalVector,g.sampleFrequency)
pause(g.buttonTime)
set(hButton,'FaceColor',dimColor)
if g.playUserSequence
    %button is pressed by user
    g.userSequence(end+1)=b.buttonNumber;
    set(h.figure,'UserData',g);
    if isequal(g.userSequence,g.simonSequence)
        %user repeated Simon correctly
        playSimonSequence(h)
    elseif ~isequal(g.userSequence,g.simonSequence(1:length(g.userSequence)))
        %user made mistake
        stopButtonDown(h.stopButton,[],h)
        %play rest of Simons sequence
        restSequence=g.simonSequence(length(g.userSequence):end);
        for counter=1:length(restSequence)
            pause(g.intervalTime)
            hButton=h.button(restSequence(counter));
            buttonDown(hButton,[],h);
        end
    end
end

function closeRequest(hFigure,eventdata)
%figure is closed
g=get(hFigure,'UserData');
%save high score
highScore=g.highScore;
save(g.highScoreFile,'highScore')
%and delete figure
%error if a sequence is played
delete(hFigure)

function resize(hFigure,eventdata,h)
%figure is resized
g=get(hFigure,'UserData');
%change font of score text
newPosition=get(hFigure,'Position');
newFontSize=get(h.score,'FontSize')*min(newPosition(3:4))/min(g.oldPosition(3:4));
set(h.score,'FontSize',newFontSize)
g.oldPosition=newPosition;
set(hFigure,'UserData',g);

function playSimonSequence(h)
%Simon playes his sequence
g=get(h.figure,'UserData');
%change high score
if length(g.simonSequence)>g.highScore(g.numberOfButtons)
    g.highScore(g.numberOfButtons)=length(g.simonSequence);
end
set(h.figure,'UserData',g)
setScore(h)
%expand Simons sequence
g.simonSequence(end+1)=ceil(rand*g.numberOfButtons);
g.userSequence=[];
g.playUserSequence=false;
set(h.figure,'UserData',g)
%play sequence
for counter=1:length(g.simonSequence)
    pause(g.intervalTime)
    hButton=h.button(g.simonSequence(counter));
    buttonDown(hButton,[],h);
end
g.playUserSequence=true;
set(h.figure,'UserData',g);

function setScore(h)
%reset score text
g=get(h.figure,'UserData');
score=int2str(length(g.simonSequence));
highScore=int2str(g.highScore(g.numberOfButtons));
numberOfButtons=int2str(g.numberOfButtons);
set(h.score,'String',[score ' ' highScore ' ' numberOfButtons])


function [maxVal, maxPos] = max(f)
%MAX   Global maximum of a DELTAFUN.
%   MAXVAL = MAX(F) returns the global maximum of the DELTAFUN F.
%
%   [MAXVAL, MAXPOS] = MAX(F) returns also a value such that MAXVAL = F(MAXPOS).
%
% See also MIN, MINANDMAX.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% To avoid code duplication, we simply call MINANDMAX():
[maxVal, maxPos] = minandmax(f);
maxVal = maxVal(2,:);
maxPos = maxPos(2,:);

end


2     % problem
5     % outflow boundary
5     % grid parameter
1     % discretisation
0.02  % viscosity parameter
1     % Picard/Newton/hybrid linearization
9     % number of Picard iterations
1.d-5 % nonlinear tolerance

%% Data file for backward facing step


  function out = full(ob, varargin)
% function out = full(ob, varargin)
%| full(ob) = ob(:,:)
%|
%| note: alternative is ob * eye(np) but this may yield the
%| wrong precision because eye() is double but ob may be single.
%|
%| optional argument(s) passed to fatrix2_subsref_colon()
%| to facilitate test_adjoint
%|
%| Copyright 2010-12-05, Jeff Fessler, University of Michigan

out = fatrix2_subsref_colon(ob, ':', varargin{:}); % ob(:,:)


function [ r, code, w, m ] = s_to_format ( s )

%*****************************************************************************80
%
%% S_TO_FORMAT reads a FORTRAN format from a string.
%
%  Discussion:
%
%    This routine will read as many characters as possible until it reaches
%    the end of the string, or encounters a character which cannot be
%    part of the format.  This routine is limited in its ability to
%    recognize FORTRAN formats.  In particular, we are only expecting
%    a single format specification, and cannot handle extra features
%    such as 'ES' and 'EN' codes, '5X' spacing, and so on.
%
%    Legal input is:
%
%       0 nothing
%       1 blanks
%       2 optional '('
%       3 blanks
%       4 optional repeat factor R
%       5 blanks
%       6 CODE ( 'A', 'B', 'E', 'F', 'G', 'I', 'L', 'O', 'Z', '*' )
%       7 blanks
%       8 width W
%       9 optional decimal point
%      10 optional mantissa M
%      11 blanks
%      12 optional ')'
%      13 blanks
%
%  Example:
%
%    S                 R   CODE   W    M
%
%    'I12              1   I      12   0
%    'E8.0'            1   E       8   0
%    'F10.5'           1   F      10   5
%    '2G14.6'          2   G      14   6
%    '*'               1   *      -1  -1
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 November 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string containing the
%    data to be read.  Reading will begin at position 1 and
%    terminate at the end of the string, or when no more
%    characters can be read.
%
%    Output, integer R, the repetition factor, which defaults to 1.
%
%    Output, character CODE, the format code.
%
%    Output, integer W, the field width.
%
%    Output, integer M, the mantissa width.
%
  LEFT = 1;
  RIGHT = -1;

  state = 0;
  paren_sum = 0;
  pos = 0;
  s_length = s_len_trim ( s );

  r = 0;
  w = 0;
  code = '?';
  m = 0;

  while ( pos < s_length )

    pos = pos + 1;
    c = s(pos);
%
%  BLANK character:
%
    if ( c == ' ' )

      if ( state == 4 )
        state = 5;
      elseif ( state == 6 )
        state = 7;
      elseif ( state == 10 )
        state = 11;
      elseif ( state == 12 )
        state = 13;
      end
%
%  LEFT PAREN
%
    elseif ( c == '(' )

      if ( state < 2 )
        paren_sum = paren_sum + LEFT;
      else
        state = -1;
        break;
      end
%
%  DIGIT (R, F, or W)
%
    elseif ( ch_is_digit ( c ) )

      if ( state <= 3 )
        state = 4;
        r = ch_to_digit ( c );
      elseif ( state == 4 )
        d = ch_to_digit ( c );
        r = 10 * r + d;
      elseif ( state == 6 || state == 7 )
        if ( code == '*' )
          state = -1;
          break;
        end
        state = 8;
        w = ch_to_digit ( c );
      elseif ( state == 8 )
        d = ch_to_digit ( c );
        w = 10 * w + d;
      elseif ( state == 9 )
        state = 10;
        m = ch_to_digit ( c );
      elseif ( state == 10 )
        d = ch_to_digit ( c );
        m = 10 * m + d;
      else
        state = -1;
        break;
      end
%
%  DECIMAL POINT
%
    elseif ( c == '.' )

      if ( state == 8 )
        state = 9;
      else
        state = -1;
        break;
      end
%
%  RIGHT PAREN
%
    elseif ( c == ')' )

      paren_sum = paren_sum + RIGHT;

      if ( paren_sum ~= 0 )
        state = -1;
        break;
      end

      if ( state == 6 & code == '*' )
        state = 12;
      elseif ( 6 <= state )
        state = 12;
      else
        state = -1;
        break;
      end
%
%  Code
%
    elseif ( ch_is_format_code ( c ) )

      if ( state < 6 )
        state = 6;
        code = c;
      else
        state = -1;
        break;
      end
%
%  Unexpected character
%
    else

      state = -1;
      break;

    end

  end

  if ( paren_sum ~= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'S_TO_FORMAT - Fatal error!\n' );
    fprintf ( 1, '  Parentheses mismatch.\n' );
    error ( 'S_TO_FORMAT - Fatal error!' );
  end

  if ( state < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'S_TO_FORMAT - Fatal error!\n' );
    fprintf ( 1, '  Parsing error.\n' );
    error ( 'S_TO_FORMAT - Fatal error!' );
  end

  if ( r == 0 )
    r = 1;
  end

  return
end


% erplab_interpolateElectrodes() - interpolate data channels
%
% Usage: EEG = erplab_interpolateElectrodes(inputEEG, replace_elecs, ignore_elecs, method)
%
% Inputs:
%     EEG           - EEGLAB dataset
%     replace_elecs - [integer array] indices of channels to interpolate.
%                     For instance, these channels might be bad.
%                     [chanlocs structure] channel location structure containing
%                     either locations of channels to interpolate or a full
%                     channel structure (missing channels in the current
%                     dataset are interpolated).
%     ignore_elecs  - Do not include these electrodes as input for interopolation
%     method        - [string] method used for interpolation (default is 'spherical').
%                     'invdist'/'v4' uses inverse distance on the scalp
%                     'spherical' uses superfast spherical interpolation.
% Output:
%     EEGOUT        - data set with bad electrode data replaced by
%                     interpolated data
%
% Author: Jason Arita
%
% Built off of EEGLAB's eeg_interp.m by Arnoud Delorme

% Copyright (C) Arnaud Delorme, CERCO, 2006, arno@salk.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function EEG = erplab_interpolateElectrodes(inputEEG, replace_elecs, ignore_elecs, method, varargin)

%% Error check input variables
if nargin < 2
    help erplab_interpolateElectrodes;
    return;
end;

% Error check: channel structure exists
tmplocs = inputEEG.chanlocs;
if isempty(tmplocs) || isempty([tmplocs.X])
    error(sprintf('Missing Channel Locations:\n\nChannel locations are needed to interpolate. Add channel locations through EEGLAB > Edit > Channel locations')); %#ok<*SPERR>
end

% Error check: Overlapping electrode lists in replace_elecss and
% ignore_elecs
overlap_elec = intersect(replace_elecs, ignore_elecs);
if ~isempty(overlap_elec)
    error(sprintf('Replace/Ignore Electrode Overlap:\n\nThere is overlap in the replace electrodes and the ignore electrodes.\nFix the input to avoid this overlap.\n\nBad electrodes:\t\t%s\nIgnore electrodes:\t%s\nOverlapping electrodes:\t%s', ...
        num2str(replace_elecs), ...
        num2str(ignore_elecs), ...
        num2str(overlap_elec)));
end

% Error check: When the user inputs electrodes not found in the input EEG dataset
missing_replace_elecss = setdiff(replace_elecs, [inputEEG.chanlocs.urchan]);
if(~isempty(missing_replace_elecss))
    error(sprintf('Missing Replace Electrodes:\n\nThe following electrodes entered as input were missing from the EEG dataset:\n\t\t%s', ...
        num2str(missing_replace_elecss)));
end

% Warning check: Missing ignored electrodes in EEG dataset
missing_ignore_elecs = setdiff(ignore_elecs, [inputEEG.chanlocs.urchan]);
if(~isempty(missing_ignore_elecs))
    warning(sprintf('Missing Ignored Electrodes:\n\nThe following electrodes entered as input were missing from the EEG dataset:\n\t%s', ...
        num2str(missing_ignore_elecs))); %#ok<SPWRN>
end

%%
EEG = inputEEG;

% If no method specified: Spherical interpolate default
if nargin < 4
    disp('Using spherical interpolation');
    method = 'spherical';
end

%% Handle optional input variables
optargs = {false}; % Default optional inputs

% Put defaults into the valuesToUse cell array,
% and overwrite the ones specified in varargin.
optargs(1:length(varargin)) = varargin;     % if vargin is empty, optargs keep their default values. If vargin is specified then it overwrites

% Place optional args into variable names
[displayEEG] = optargs{:};

%%
if isstruct(replace_elecs)

    % add missing channels in interpolation structure
    % -----------------------------------------------
    lab1 = { replace_elecs.labels };
    tmpchanlocs = EEG.chanlocs;
    lab2 = { tmpchanlocs.labels };
    [~, tmpchan] = setdiff_bc( lab2, lab1);
    tmpchan = sort(tmpchan);
    if ~isempty(tmpchan)
        newchanlocs = [];
        fields = fieldnames(replace_elecs);
        for index = 1:length(fields)
            if isfield(replace_elecs, fields{index})
                for cind = 1:length(tmpchan)
                    fieldval = getfield( EEG.chanlocs, { tmpchan(cind) },  fields{index});
                    newchanlocs = setfield(newchanlocs, { cind }, fields{index}, fieldval);
                end;
            end;
        end;
        newchanlocs(end+1:end+length(replace_elecs)) = replace_elecs;
        replace_elecs = newchanlocs;
    end;
    if length(EEG.chanlocs) == length(replace_elecs), return; end;

    lab1          = { replace_elecs.labels };
    tmpchanlocs   = EEG.chanlocs;
    lab2          = { tmpchanlocs.labels };
    [~, badchans] = setdiff_bc( lab1, lab2);

    fprintf('Interpolating %d channels...\n', length(badchans));

    if isempty(badchans), return; end;
    goodchans      = sort(setdiff(1:length(replace_elecs), badchans));

    % re-order good channels
    % ----------------------
    [~, tmp2, neworder] = intersect_bc( lab1, lab2 );
    [~, ordertmp2]      = sort(tmp2);
    neworder            = neworder(ordertmp2);
    EEG.data            = EEG.data(neworder, :, :);

    % looking at channels for ICA
    % ---------------------------
    %[~, sorti] = sort(neworder);
    %{ EEG.chanlocs(EEG.icachansind).labels; replace_elecs(goodchans(sorti(EEG.icachansind))).labels }

    % update EEG dataset (add blank channels)
    % ---------------------------------------
    if ~isempty(EEG.icasphere)

        [~, sorti] = sort(neworder);
        EEG.icachansind = sorti(EEG.icachansind);
        EEG.icachansind = goodchans(EEG.icachansind);
        EEG.chaninfo.icachansind = EEG.icachansind;

        % TESTING SORTING
        %icachansind = [ 3 4 5 7 8]
        %data = round(rand(8,10)*10)
        %neworder = shuffle(1:8)
        %data2 = data(neworder,:)
        %icachansind2 = sorti(icachansind)
        %data(icachansind,:)
        %data2(icachansind2,:)
    end;
    % { EEG.chanlocs(neworder).labels; replace_elecs(sort(goodchans)).labels }
    %tmpdata                  = zeros(length(replace_elecs), size(EEG.data,2), size(EEG.data,3));
    %tmpdata(goodchans, :, :) = EEG.data;

    % looking at the data
    % -------------------
    %tmp1 = mattocell(EEG.data(sorti,1));
    %tmp2 = mattocell(tmpdata(goodchans,1));
    %{ EEG.chanlocs.labels; replace_elecs(goodchans).labels; tmp1{:}; tmp2{:} }
    %EEG.data      = tmpdata;

    EEG.chanlocs  = replace_elecs;

else
    badchans  = replace_elecs;
    goodchans = setdiff_bc(1:EEG.nbchan, badchans);
    oldelocs  = EEG.chanlocs;
    EEG       = pop_select(EEG, 'nochannel', badchans);
    EEG.chanlocs = oldelocs;
    disp('Interpolating missing channels...');
end;

% find non-empty good channels
% ----------------------------
origoodchans  = goodchans;
chanlocs      = EEG.chanlocs;
nonemptychans = find(~cellfun('isempty', { chanlocs.theta }));

%% Remove ignored channels from interpolation computation
nonemptychans = setdiff_bc(nonemptychans, ignore_elecs);

[~, indgood ] = intersect_bc(goodchans, nonemptychans);
goodchans = goodchans( sort(indgood) );
datachans = getdatachans(goodchans,badchans);
badchans  = intersect_bc(badchans, nonemptychans);
if isempty(badchans), return; end;

%% Error check: Less than 2 good channels for interpolation
if length(goodchans) < 2
    feedback_str = [ ...
        sprintf('Cannot interpolate \t%.2d channels:\t', length(badchans)) ...
        sprintf(' %2.2d', badchans) ...
        '\n'...
        sprintf('using only\t\t%.2d channel(s):\t', length(goodchans)) ...
        sprintf(' %2.2d', goodchans) ...
        '\n' ...
        sprintf('skipping\t%.2d channels:\t', length(ignore_elecs))...
        sprintf(' %2.2d', ignore_elecs) ...
        '\n'];
    fprintf(feedback_str);
    error('Cannot interpolate with %d channels.\nEither make sure data set contains more than 2 channels \nAND that you are not ignoring too many channels', length(goodchans));
else
    % Print feedback to command window if error check passes
    feedback_str = [ ...
        sprintf('Interpolating \t%.2d channels:\t', length(badchans)) ...
        sprintf(' %2.2d', badchans) ...
        '\n'...
        sprintf('with\t\t%.2d channels:\t', length(goodchans)) ...
        sprintf(' %2.2d', goodchans) ...
        '\n' ...
        sprintf('skipping\t%.2d channels:\t', length(ignore_elecs))...
        sprintf(' %2.2d', ignore_elecs) ...
        '\n'];
    fprintf(feedback_str);
end

%% Warning check: Ignored bad channels
flatlinechans = intersect(replace_elecs, ignore_elecs);
if(~isempty(flatlinechans))
    warning('Warning: %d channels contain no data because they are interpolated with ignored channels: %s', length(flatlinechans), int2str(flatlinechans));
end

% scan data points
% ----------------
if strcmpi(method, 'spherical')
    % get theta, rad of electrodes
    % ----------------------------
    tmpgoodlocs = EEG.chanlocs(goodchans);
    xelec       = [ tmpgoodlocs.X ];
    yelec       = [ tmpgoodlocs.Y ];
    zelec       = [ tmpgoodlocs.Z ];
    rad         = sqrt(xelec.^2+yelec.^2+zelec.^2);
    xelec       = xelec./rad;
    yelec       = yelec./rad;
    zelec       = zelec./rad;
    tmpbadlocs  = EEG.chanlocs(badchans);
    xbad        = [ tmpbadlocs.X ];
    ybad        = [ tmpbadlocs.Y ];
    zbad        = [ tmpbadlocs.Z ];
    rad         = sqrt(xbad.^2+ybad.^2+zbad.^2);
    xbad        = xbad./rad;
    ybad        = ybad./rad;
    zbad        = zbad./rad;

    EEG.data    = reshape(EEG.data, EEG.nbchan, EEG.pnts*EEG.trials);
    %[~, tmp2, tmp3 tmpchans] = spheric_spline_old( xelec, yelec, zelec, EEG.data(goodchans,1));
    %max(tmpchans(:,1)), std(tmpchans(:,1)),
    %[~, tmp2, tmp3 EEG.data(badchans,:)] = spheric_spline( xelec, yelec, zelec, xbad, ybad, zbad, EEG.data(goodchans,:));
    [~, ~, ~, badchansdata] = spheric_spline( xelec, yelec, zelec, xbad, ybad, zbad, EEG.data(datachans,:));
    %max(EEG.data(goodchans,1)), std(EEG.data(goodchans,1))
    %max(EEG.data(badchans,1)), std(EEG.data(badchans,1))
    EEG.data = reshape(EEG.data, EEG.nbchan, EEG.pnts, EEG.trials);
elseif strcmpi(method, 'spacetime') % 3D interpolation, works but x10 times slower
    disp('Warning: if processing epoch data, epoch boundary are ignored...');
    disp('3-D interpolation, this can take a long (long) time...');

    tmpgoodlocs     = EEG.chanlocs(goodchans);
    tmpbadlocs      = EEG.chanlocs(badchans);
    [xbad ,ybad]    = pol2cart([tmpbadlocs.theta],[tmpbadlocs.radius]);
    [xgood,ygood]   = pol2cart([tmpgoodlocs.theta],[tmpgoodlocs.radius]);
    pnts            = size(EEG.data,2)*size(EEG.data,3);
    zgood           = 1:pnts;
    zgood           = repmat(zgood, [length(xgood) 1]);
    zgood           = reshape(zgood,prod(size(zgood)),1); %#ok<*PSIZE>
    xgood           = repmat(xgood, [1 pnts]);
    xgood           = reshape(xgood,prod(size(xgood)),1);
    ygood           = repmat(ygood, [1 pnts]);
    ygood           = reshape(ygood,prod(size(ygood)),1);
    tmpdata         = reshape(EEG.data, prod(size(EEG.data)),1);
    zbad            = 1:pnts;
    zbad            = repmat(zbad, [length(xbad) 1]);
    zbad            = reshape(zbad,prod(size(zbad)),1);
    xbad            = repmat(xbad, [1 pnts]); xbad = reshape(xbad,prod(size(xbad)),1);
    ybad            = repmat(ybad, [1 pnts]); ybad = reshape(ybad,prod(size(ybad)),1);
    badchansdata    = griddata(ygood, xgood, zgood, tmpdata,...
        ybad, xbad, zbad, 'nearest'); % interpolate data
else
    % get theta, rad of electrodes
    % ----------------------------
    tmpchanlocs     = EEG.chanlocs;
    [xbad ,ybad]    = pol2cart([tmpchanlocs( badchans).theta], ...
        [tmpchanlocs( badchans).radius]);
    [xgood,ygood]   = pol2cart([tmpchanlocs(goodchans).theta], ...
        [tmpchanlocs(goodchans).radius]);
    badchansdata = zeros(length(badchans), ...
        size(EEG.data,2)*size(EEG.data,3));
    fprintf('Points (/%d):', size(EEG.data,2)*size(EEG.data,3));

    for t=1:(size(EEG.data,2)*size(EEG.data,3)) % scan data points
        if mod(t,100) == 0, fprintf('%d ', t); end;
        if mod(t,1000) == 0, fprintf('\n'); end;

        %for c = 1:length(badchans)
        %   [h EEG.data(badchans(c),t)]= topoplot(EEG.data(goodchans,t),EEG.chanlocs(goodchans),'noplot', ...
        %        [EEG.chanlocs( badchans(c)).radius EEG.chanlocs( badchans(c)).theta]);
        %end;
        tmpdata = reshape(EEG.data, size(EEG.data,1), size(EEG.data,2)*size(EEG.data,3) );
        if strcmpi(method, 'invdist'), method = 'v4'; end;
        [~,~,badchansdata(:,t)] = griddata(ygood, xgood , double(tmpdata(datachans,t)'),...
            ybad, xbad, method); %#ok<GRIDD> % interpolate data
    end
    fprintf('\n');
end;

tmpdata               = zeros(length(replace_elecs), EEG.pnts, EEG.trials);
tmpdata(origoodchans, :,:) = EEG.data;
%if input data are epoched reshape badchansdata for Octave compatibility...
if length(size(tmpdata))==3
    badchansdata = reshape(badchansdata,length(badchans),size(tmpdata,2),size(tmpdata,3));
end
tmpdata(badchans,:,:) = badchansdata;
EEG.data = tmpdata;
EEG.nbchan = size(EEG.data,1);
EEG = eeg_checkset(EEG);

%% Display input EEG plot to user with rejection windows marked
% Needs to occur before actually deleting the time segments in EEG
if displayEEG
    % Plot EEG data with to-be-rejected time windows

    eegplotoptions = { ...
        'events',       EEG.event,          ...
        'srate',        EEG.srate,          ...
        'winlength',    10};

    % Display channel labels instead of numbers
    if ~isempty(EEG.chanlocs)
        eegplotoptions = [ eegplotoptions {'eloc_file', EEG.chanlocs}];
    end;

    eegplot(EEG.data, eegplotoptions{:});

end

%% Nested functions

function datachans = getdatachans(goodchans, badchans)
% Get data channels

datachans = goodchans;
badchans  = sort(badchans);
for index = length(badchans):-1:1
    datachans(find(datachans > badchans(index))) = ...
        datachans(find(datachans > badchans(index)))-1; %#ok<FNDSB>
end;

%% spherical splines
function [x, y, z, Res] = spheric_spline_old( xelec, yelec, zelec, values) %#ok<*DEFNU>

SPHERERES              = 20;
[x,y,z]                = sphere(SPHERERES);
x(1:(length(x)-1)/2,:) = []; x = x(:)';
y(1:(length(y)-1)/2,:) = []; y = y(:)';
z(1:(length(z)-1)/2,:) = []; z = z(:)';

Gelec = computeg(xelec,yelec,zelec,xelec,yelec,zelec);
Gsph  = computeg(x,y,z,xelec,yelec,zelec);

% equations are
% Gelec*C + C0  = Potential (C unknow)
% Sum(c_i) = 0
% so
%             [c_1]
%      *      [c_2]
%             [c_ ]
%    xelec    [c_n]
% [x x x x x]         [potential_1]
% [x x x x x]         [potential_ ]
% [x x x x x]       = [potential_ ]
% [x x x x x]         [potential_4]
% [1 1 1 1 1]         [0]

% compute solution for parameters C
% ---------------------------------
meanvalues = mean(values);
values = values - meanvalues; % make mean zero
C = pinv([Gelec;ones(1,length(Gelec))]) * [values(:);0];

% apply results
% -------------
Res = zeros(1,size(Gsph,1));
for j = 1:size(Gsph,1)
    Res(j) = sum(C .* Gsph(j,:)');
end
Res = Res + meanvalues;
Res = reshape(Res, length(x(:)),1);

function [xbad, ybad, zbad, allres] = spheric_spline( xelec, yelec, zelec, xbad, ybad, zbad, values)

newchans = length(xbad);
numpoints = size(values,2);

%SPHERERES = 20;
%[x,y,z] = sphere(SPHERERES);
%x(1:(length(x)-1)/2,:) = []; xbad = [ x(:)'];
%y(1:(length(x)-1)/2,:) = []; ybad = [ y(:)'];
%z(1:(length(x)-1)/2,:) = []; zbad = [ z(:)'];

Gelec = computeg(xelec,yelec,zelec,xelec,yelec,zelec);
Gsph  = computeg(xbad,ybad,zbad,xelec,yelec,zelec);

% compute solution for parameters C
% ---------------------------------
meanvalues = mean(values);
values = values - repmat(meanvalues, [size(values,1) 1]); % make mean zero

values = [values;zeros(1,numpoints)];
C = pinv([Gelec;ones(1,length(Gelec))]) * values;
clear values;
allres = zeros(newchans, numpoints);

% apply results
% -------------
for j = 1:size(Gsph,1)
    allres(j,:) = sum(C .* repmat(Gsph(j,:)', [1 size(C,2)]));
end
allres = allres + repmat(meanvalues, [size(allres,1) 1]);

% compute G function
% ------------------
function g = computeg(x,y,z,xelec,yelec,zelec)

unitmat = ones(length(x(:)),length(xelec));
EI = unitmat - sqrt((repmat(x(:),1,length(xelec)) - repmat(xelec,length(x(:)),1)).^2 +...
    (repmat(y(:),1,length(xelec)) - repmat(yelec,length(x(:)),1)).^2 +...
    (repmat(z(:),1,length(xelec)) - repmat(zelec,length(x(:)),1)).^2);

g = zeros(length(x(:)),length(xelec));
%dsafds
m = 4; % 3 is linear, 4 is best according to Perrin's curve
for n = 1:7
    if ismatlab
        L = legendre(n,EI);
    else % Octave legendre function cannot process 2-D matrices
        for icol = 1:size(EI,2)
            tmpL = legendre(n,EI(:,icol));
            if icol == 1, L = zeros([ size(tmpL) size(EI,2)]); end;
            L(:,:,icol) = tmpL;
        end;
    end;
    g = g + ((2*n+1)/(n^m*(n+1)^m))*squeeze(L(1,:,:));
end
g = g/(4*pi);