classdef Max < dagnn.ElementWise
  %MAX DagNN max layer
  %   The Max layer takes the max of all its inputs and store the result
  %   as its only output.

  properties (Transient)
    numInputs
%     inputSize
  end

  methods
    function outputs = forward(obj, inputs, params)
      obj.numInputs = numel(inputs) ;
%       [h w d]=size(inputs{1});
%       obj.inputSize = ones(h,w,d);
      outputs{1} = inputs{1} ;
      for k = 2:obj.numInputs
          outputs{1} = max(outputs{1},inputs{k});

%           for hight = 1:h
%               for width = 1:w
%                   for depth = 1:d
%         if(outputs{1}(hight,width,depth) < inputs{k}(hight,width,depth))
%             outputs{1}(hight,width,depth) = inputs{k}(hight,width,depth);
%             obj.inputSize(hight,width,depth) = k;
%         end
%                   end
%               end
%           end
      end
    end

    function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
        sz = size(inputs{1});
        if numel(sz) < 4, sz(4) = 1;
        sz(5) = obj.numInputs;
        tempinputs = single(zeros(sz));
        tempinputs = gpuArray(tempinputs);
        end
      for k = 1:obj.numInputs

          tempinputs(:,:,:,:,k) = inputs{k};
      end
         testinputs{1} = permute(tempinputs, [1 2 5 3 4]);
         sz_in = size(testinputs{1});
         [~, idx]  = mex_maxpool3d(testinputs{1},...
        'pool',[1,1,obj.numInputs], 'stride', [1,1,obj.numInputs], 'pad', [0,0,0,0,0,0]);

%          sz = size(derOutputs{1});
%          if numel(sz) < 4, sz(4) = 1;
%          sz(5) = obj.numInputs;
%          tempoutputs = single(zeros(sz));
% %          tempoutputs = gpuArray(tempoutputs);
%          end
%          for k = 1:obj.numInputs
%              tempoutputs(:,:,:,:,k) = derOutputs{1};
%          end

         derOutputs{1} = permute(derOutputs{1}, [1 2 5 3 4]);
         derInputs{1} = mex_maxpool3d(derOutputs{1}, idx, sz_in ,...
        'pool',[1,1,obj.numInputs], 'stride', [1,1,obj.numInputs], 'pad', [0,0,0,0,0,0]);
         tempoutputs = permute(derInputs{1}, [1 2 4 5 3]);
         for k = 1:obj.numInputs

          derInputs{k} = tempoutputs(:,:,:,:,k);
         end
%         for hight = 1:h
%               for width = 1:w
%                   for depth = 1:d
%                derInputs{obj.inputSize(hight,width,depth)}(hight,width,depth) = derOutputs{1}(hight,width,depth);
% %              if (obj.inputSize(hight,width,depth) ==k)
% %           derInputs{k}(hight,width,depth) = derOutputs{1}(hight,width,depth) ; %not sure whether times obj.numInputs
% %              end
%                   end
%               end
%         end

      derParams = {} ;
    end

    function outputSizes = getOutputSizes(obj, inputSizes)
      outputSizes{1} = inputSizes{1} ;
      for k = 2:numel(inputSizes)
        if all(~isnan(inputSizes{k})) && all(~isnan(outputSizes{1}))
          if ~isequal(inputSizes{k}, outputSizes{1})
            warning('Max layer: the dimensions of the input variables is not the same.') ;
          end
        end
      end
    end

    function rfs = getReceptiveFields(obj)
      numInputs = numel(obj.net.layers(obj.layerIndex).inputs) ;
      rfs.size = [1 1] ;
      rfs.stride = [1 1] ;
      rfs.offset = [1 1] ;
      rfs = repmat(rfs, numInputs, 1) ;
    end

    function obj = Max(varargin)
      obj.load(varargin) ;
    end
  end
end


function x = loop(x, continue_fcn, f, cleanup_fcn)

% x = loop(x, continue_fcn, f, cleanup_fcn)
%
% Looping function. Provides the ability to treating "looping" as a
% function instead of a command.
%
% See functional_programming_examples.m for a discussion of this function.
%
% Inputs:
% x            - Initial state (can be cell array of arguments to f)
% continue_fcn - Continue function, returns true iff the loop should go on
% f            - Function of the state (x) to run every iteration
% cleanup_fcn  - Function to select what to return from the state when the
%                looping is complete (optional)
%
% Outputs:
% x        - The updated state. If a cleanup function is supplied, this
%            will be cleanup(x).
%
% Fibonacci example:
%
% fib = @(n) loop({1, 0, 1}, ...          % {k, fib(k-1), fib(k)}
%                 @(x) x{1} < n, ...      % While k < n
%                 @(x) {x{1} + 1, ...     %   Increase k
%                       x{3}, ...         %   Store fib(k-1)
%                       x{3} + x{2}}, ... %   Store fib(k-1) + fib(k-2)
%                 @(x) x{3})              % End, returning only fib(k)
%
% arrayfun(fib, 1:10)
%
% Tucker McClure
% Copyright 2013 The MathWorks, Inc.

    while tern(iscell(x), @()continue_fcn(x{:}), @()continue_fcn(x))
        if iscell(x)
            x = f(x{:});
        else
            x = f(x);
        end
    end

    if nargin == 4
        if iscell(x)
            x = cleanup_fcn(x{:});
        else
            x = cleanup_fcn(x);
        end
    end

end


function [data] = blc(data, interval, optional)

% BLC does a baseline correction using the prestimulus interval of the data
%
%   [data] = baseline(data, interval);
%   [data] = baseline(data, begin, end);
%
% If no begin and end are specified, the whole timeinterval is
% used for baseline correction.

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

% determine the dimension of the data
if length(size(data))==3
  % multiple epochs
  dim=3;
  nepoch = size(data,1);
  nchan  = size(data,2);
  ntime  = size(data,3);
else
  % single epoch with multiple channels
  dim=2;
  nchan  = size(data,1);
  ntime  = size(data,2);
end

% determine the interval to use for baseline correction
if nargin==1
  % default is to use the whole timeinterval for baseline correction
  interval = 1:ntime;
elseif nargin==2
  % use the interval specified by the user
elseif nargin==3
  % create the interval from the specified begin and end point
  interval = interval:optional;
end

if dim==3
  % the data contains multiple epochs
  for epoch=1:nepoch
    baseline = mean(data(epoch,:,interval), 3);
    for chan=1:nchan
      data(epoch,chan,:) = data(epoch,chan,:) - baseline(chan);
    end
  end
else
  % the data contains a single epoch
  baseline = mean(data(:,interval), 2);
  for chan=1:nchan
    data(chan,:) = data(chan,:) - baseline(chan);
  end
end


% Under construction...
%
%
% Usage
% >> waverage = medianbin(ERP, bop)
%
% For Bin Operations GUI/scripting purposes
%
% Author: Javier
%

function  medb = medianbin(ERP, bop)

if nargin<1
      help medianbin
      return
end
if nargin<2
      error('ERPLAB says: You must specify bin indexes to be processed!')
end
if ~iserpstruct(ERP)
      error('ERPLAB says: Your data structure is not an ERP structure!')
end
if ischar(bop)
      bop = str2num(char(regexp(bop,'\d+','match')'))';
end

binarray = unique_bc2(bop);

if length(binarray)~=length(bop)
      fprintf('\n*** WARNING: Repeated bins were ignored.\n\n')
end
if length(binarray)<2
      error('ERPLAB says: You must specify 2 bin indexes at leat!')
end
if max(binarray)>ERP.nbin
      error('ERPLAB says: Some specified bins do not exist!')
end

datavg = ERP.bindata(:,:,binarray);
medb   = median(datavg, 3);


function [KM] = calc(kern,dat1,dat2,ind1,ind2)

% [KM] = calc(k,dat1,[d2],[ind1],[ind2])
%
% Calculate the kernel with specific indexed data from
% datasets d1 and (optionally) d2.
% If d2 is not given it is assumed to make the matrix between d1 and itself

  global caching_kernel;

  if nargin<3,
      dat2=[];
  end;

  if isempty(dat2)
      dat2=dat1;
  end;

  if nargin<4
    ind1=[1:length(get_index(dat1))];
  end

  if nargin<5
    ind2=[1:length(get_index(dat2))];
  end

  if kern.calc_on_output
      dat1.X=dat1.Y;
      dat2.X=dat2.Y;
  end %% output kernels

  index1 = get_index(dat1);
  index2 = get_index(dat2);

  if strcmp(kern.ker,'custom')
   % the kernel matrix is stored in param{1} of kernel
   KM = kern.kerparam;
   KM = KM(index2(ind2),index1(ind1));
   return;
  end

  if strcmp(kern.ker,'custom_fast')
   global K;
   KM = K(index2(ind2),index1(ind1));
   return;
 end

 if kern.kercaching==1 & (~isa(dat1,'data_global')|~isa(dat2,'data_global')),
   error('Caching kernel only for data_global');
 else
   if (kern.kercaching==1)&~ismyX(dat1)&~ismyX(dat2),
     if caching_kernel==kern,
       global K;
       index1 = get_index(dat1);
       index2 = get_index(dat2);
       KM = K(index2(ind2),index1(ind1));
       return;
     else
       global K;
       %global X;global Y;
       dtmp=data_global('get_kernel tmp',[],[]);
       [numEx vDim oDim]  = get_dim(dtmp);
       ind1=[1:numEx]; ind2=[1:numEx];
       caching_kernel=kern;
     end
   end
 end

  paramtmp=[];
  if iscell(kern.kerparam),
    for i=1:length(kern.kerparam),
      paramtmp{i} = kern.kerparam{i};
    end
  else
    paramtmp = kern.kerparam;
  end
  if kern.kercaching~=1|ismyX(dat1)|ismyX(dat2),

    %% --- normal Kernel calculation ----------------------
    KM = feval(kern.ker,kern,dat1,dat2,ind1,ind2,paramtmp);

  else
    K = feval(kern.ker,kern,dtmp,dtmp,ind1,ind2,paramtmp);
    KM = K(get_index(dat2),get_index(dat1));
  end;

  if kern.output_distance  %% ------------ convert kernel to a distance
    kern.output_distance=0;
    Kdn = get_norm(kern,dat1,ind1).^2;
    Kn = get_norm(kern,dat2,ind2).^2;
    KM = ones(length(Kn),1)*Kdn' + Kn*ones(1,length(Kdn)) - 2*KM;
    KM = sqrt(KM);
  end


function PlotPacketTimeStamps(aedat, newFigure, diffs)

%{
Takes 'aedat' - a data structure containing an imported .aedat file,
as created by ImportAedat.
When imported from aedat3, there is an info field packetTimeStamps. Plot
this.
%}

if ~isfield(aedat, 'info') || ~isfield(aedat.info, 'packetTimeStamps')
    disp('No packet timestamps found')
    return
end

% newFigure - default is to create a new figure in which to plot - supress
% this with the newFigure flag
if ~exist('newFigure', 'var') || newFigure
    figure
end
if exist('diffs', 'var') && diffs
    % In the diffs mode, plots the difference in timestamp from one packet
    % to the next. Exclude packets before last timestanmp reset
    aedat = FindFirstPacketAfterLastTimeStampReset(aedat);
    firstPacket = aedat.info.firstPacketAfterLastTimeStampReset;
    ts = double(aedat.info.packetTimeStamps(firstPacket : end)) / 1e6;
    diffs = [0; ts(2 : end) - ts(1 : end - 1)] * 1e3;
    plot(ts, diffs, '.-')
    xlabel('Packet timestamp (s)')
    ylabel('time difference from previous timestamp (ms)')
else
    plot(aedat.info.packetTimeStamps, '.-')
    xlabel('Packet number')
    ylabel('Time (us)')
end


function test_example_fem

% WALLTIME 08:00:00
% MEM 12gb
% DEPENDENCY ft_prepare_headmodel ft_prepare_mesh ft_datatype_segmentation

[ftver, ftpath] = ft_version;

%% read mri
mri = ft_read_mri(dccnpath('/home/common/matlab/fieldtrip/data/ftp/test/ctf/Subject01.mri'));

%% segmentation
cfg          = [];
cfg.output   = {'gray', 'white', 'csf', 'skull', 'scalp'};
segmentedmri = ft_volumesegment(cfg, mri);

%% mesh
cfg        = [];
cfg.shift  = 0.3;
cfg.method = 'hexahedral';
mesh       = ft_prepare_mesh(cfg,segmentedmri);

%% volume conductor
cfg              = [];
cfg.method       = 'simbio';
cfg.conductivity = [0.33 0.14 1.79 0.01 0.43];
headmodel        = ft_prepare_headmodel(cfg, mesh);

%% electrode alignment
elec = ft_read_sens(fullfile(ftpath,'template/electrode/standard_1020.elc'));

nas = mri.hdr.fiducial.head.nas;
lpa = mri.hdr.fiducial.head.lpa;
rpa = mri.hdr.fiducial.head.rpa;

%
fiducials.pos     = [nas; lpa; rpa];
fiducials.label   = {'Nz','LPA','RPA'};
fiducials.unit    = 'mm';

cfg          = [];
cfg.method   = 'fiducial';
cfg.target   = fiducials;
cfg.elec     = elec;
cfg.fiducial = {'Nz', 'LPA', 'RPA'};
elec_align   = ft_electroderealign(cfg);

% add 12 mm to x-axis
n=size(elec_align.chanpos,1);
for i=1:n
 elec_align.chanpos(i,1)=elec_align.chanpos(i,1)+12;
 elec_align.elecpos(i,1)=elec_align.elecpos(i,1)+12;
end

%% make the sourcemodel/grid

% At the moment the sourcemodel is defined prior
% to the leadfield because ft_prepare_sourcemodel does not automatically create
% a sourcemodel based on a hexahedral headmodel.

cfg                 = [];
cfg.mri             = mri;
cfg.resolution      = 3;
sourcemodel         = ft_prepare_sourcemodel(cfg);
sourcemodel         = ft_convert_units(sourcemodel, headmodel.unit);
sourcemodel.inside(500:end) = false; % do only a few dipoles

cfg            = [];
cfg.headmodel  = headmodel;
cfg.elec       = elec_align;
cfg.sourcemodel = sourcemodel;
cfg.channel    = elec_align.label(4:6); % do only a few channels, to save time
lf             = ft_prepare_leadfield(cfg);

m = cellfun(@mean,lf.leadfield(lf.inside),'uniformoutput',false)';
m = cat(1, m{:});
assert(all(m(:)<eps));


% NOTE: This srcipt will not run as expected unless you fill in proper
% code in trajhandle and controlhandle
% You should not modify any part of this script except for the
% visualization part
%
% ***************** MEAM 620 QUADROTOR SIMULATION *****************
close all
clear all
addpath('utils')
addpath('trajectories')

% You can change trajectory here

% trajectory generator
% trajhandle = @step;
% trajhandle = @circle;
trajhandle = @diamond;

% controller
controlhandle = @controller;

% real-time
real_time = true;

% *********** YOU SHOULDN'T NEED TO CHANGE ANYTHING BELOW **********
% number of quadrotors
nquad = 1;

% max time
time_tol = 25;

% parameters for simulation
params = crazyflie();

%% **************************** FIGURES *****************************
fprintf('Initializing figures...\n')
h_fig = figure;
h_3d = gca;
axis equal
grid on
view(3);
xlabel('x [m]'); ylabel('y [m]'); zlabel('z [m]')
quadcolors = lines(nquad);

set(gcf,'Renderer','OpenGL')

%% *********************** INITIAL CONDITIONS ***********************
fprintf('Setting initial conditions...\n')
max_iter  = 5000;      % max iteration
starttime = 0;         % start of simulation in seconds
tstep     = 0.01;      % this determines the time step at which the solution is given
cstep     = 0.05;      % image capture time interval
nstep     = cstep/tstep;
time      = starttime; % current time
err = []; % runtime errors
for qn = 1:nquad
    % Get start and stop position
    des_start = trajhandle(0, qn);
    des_stop  = trajhandle(inf, qn);
    stop{qn}  = des_stop.pos;
    x0{qn}    = init_state( des_start.pos, 0 );
    xtraj{qn} = zeros(max_iter*nstep, length(x0{qn}));
    ttraj{qn} = zeros(max_iter*nstep, 1);
end

x         = x0;        % state

pos_tol   = 0.01;
vel_tol   = 0.01;

%% ************************* RUN SIMULATION *************************
OUTPUT_TO_VIDEO = 1;
if OUTPUT_TO_VIDEO == 1
    v = VideoWriter('diamond.avi');
    open(v)
end

fprintf('Simulation Running....')
% Main loop
for iter = 1:max_iter
    iter;
    timeint = time:tstep:time+cstep;

    tic;
    % Iterate over each quad
    for qn = 1:nquad
        % Initialize quad plot
        if iter == 1
            QP{qn} = QuadPlot(qn, x0{qn}, 0.1, 0.04, quadcolors(qn,:), max_iter, h_3d);
            desired_state = trajhandle(time, qn);
            QP{qn}.UpdateQuadPlot(x{qn}, [desired_state.pos; desired_state.vel], time);
            h_title = title(sprintf('iteration: %d, time: %4.2f', iter, time));
        end

        % Run simulation
        [tsave, xsave] = ode45(@(t,s) quadEOM(t, s, qn, controlhandle, trajhandle, params), timeint, x{qn});
        x{qn}    = xsave(end, :)';

        % Save to traj
        xtraj{qn}((iter-1)*nstep+1:iter*nstep,:) = xsave(1:end-1,:);
        ttraj{qn}((iter-1)*nstep+1:iter*nstep) = tsave(1:end-1);

        % Update quad plot
        desired_state = trajhandle(time + cstep, qn);
        QP{qn}.UpdateQuadPlot(x{qn}, [desired_state.pos; desired_state.vel], time + cstep);
        set(h_title, 'String', sprintf('iteration: %d, time: %4.2f', iter, time + cstep))
        if OUTPUT_TO_VIDEO == 1
            im = frame2im(getframe(gcf));
            writeVideo(v,im);
        end
    end
    time = time + cstep; % Update simulation time
    t = toc;
    % Check to make sure ode45 is not timing out
    if(t> cstep*50)
        err = 'Ode45 Unstable';
        break;
    end

    % Pause to make real-time
    if real_time && (t < cstep)
        pause(cstep - t);
    end

    % Check termination criteria
    if terminate_check(x, time, stop, pos_tol, vel_tol, time_tol)
        break
    end
end

if OUTPUT_TO_VIDEO == 1
    close(v);
end

%% ************************* POST PROCESSING *************************
% Truncate xtraj and ttraj
for qn = 1:nquad
    xtraj{qn} = xtraj{qn}(1:iter*nstep,:);
    ttraj{qn} = ttraj{qn}(1:iter*nstep);
end

% Plot the saved position and velocity of each robot
for qn = 1:nquad
    % Truncate saved variables
    QP{qn}.TruncateHist();
    % Plot position for each quad
    h_pos{qn} = figure('Name', ['Quad ' num2str(qn) ' : position']);
    plot_state(h_pos{qn}, QP{qn}.state_hist(1:3,:), QP{qn}.time_hist, 'pos', 'vic');
    plot_state(h_pos{qn}, QP{qn}.state_des_hist(1:3,:), QP{qn}.time_hist, 'pos', 'des');
    % Plot velocity for each quad
    h_vel{qn} = figure('Name', ['Quad ' num2str(qn) ' : velocity']);
    plot_state(h_vel{qn}, QP{qn}.state_hist(4:6,:), QP{qn}.time_hist, 'vel', 'vic');
    plot_state(h_vel{qn}, QP{qn}.state_des_hist(4:6,:), QP{qn}.time_hist, 'vel', 'des');
end
if(~isempty(err))
    error(err);
end

fprintf('finished.\n')


%% [B3_] = tensor_fibers_tube(A)
%
function [B3_] = tensor_fibers_tube(A)
  [n1, n2, n3] = size(A);
  for i = 1:n1
    for j = 1:n2
      B3_{i,j} = A(i,j,:);
    end
  end
end


clc; clear variables; close all;
addpath(genpath(fileparts(mfilename('fullpath'))));

clear variables;

%% Main
filenames={
    'paramsTopOptProblem'
    };

for icases=1:size(filenames,1)
    clearvars -except filenames icases;
    close all;

    settings = SettingsTopOptProblem(filenames{icases});

    topOptProblem = TopOpt_Problem(settings);
    topOptProblem.computeVariables;
    topOptProblem.postProcess;
end
close all


% RRT for Redundant manipulator example.
% by Olzhas Adiyatov
% 08/28/2013

map = struct('name', 'bench_redundant_3.mat', 'start_point', [0 0], 'goal_point', [35 35]);
max_iter = 10e3;
is_benchmark = false;
rand_seed = 40;
variant = 'FNRedundantManipulator';
result = rrt_star(map, max_iter, is_benchmark, rand_seed, variant);


function kts = kmph2kts(kmph)
%KMPH2KTS Convert speed from kilometers per hour to knots
%
%  kts = KMPH2KTS(kmph) converts speeds from kilometers per hour to knots.
%
%  See also KMPH2FTPS, KMPH2MPH, KMPH2MPS, KTS2KMPH.

% Jonathan Sullivan
% Original: May 2011
% jonathan.sullivan@ll.mit.edu

kts = kmph/1.852;


function [c,ceq] = nl_constraints(t, x, u, mpcModel, varargin) %add battery SOC constraints

    c(1) = x(2)-mpcModel.battery.range(2);
    c(2) = mpcModel.battery.range(1)-x(2);

    ceq =  [];

end


function res = imSkeleton(img, varargin)
% Homothopic skeleton of a binary image.
%
%   SK = imSkeleton(IMG)
%   Computes the skeleton of the binary image IMG. The skeleton is computed
%   by iterative homothopic thinning of the input image.
%   Basically, this is just a wrapper for the "bwmorph" function. If the
%   "bwskel" function (introduced in 2018) is found, it is used instead.
%
%   Example
%     img = imread('circles.png');
%     skel = imSkeleton(img);
%     ovr = imOverlay(img, skel);
%     imshow(ovr)
%
%   See also
%     bwmorph, bwskel, imLabelSkeleton, imBoundary, imOverlay
%

% ------
% Author: David Legland
% e-mail: david.legland@inrae.fr
% Created: 2012-05-16,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2012 INRA - Cepia Software Platform.

if exist('bwskel', 'file')
    res = bwskel(img);
else
    res = bwmorph(img, 'thin', Inf);
end


function gscatter3(x,y,z,group,clr,sym,siz,doleg,xnam,ynam,znam)
%GSCATTER3  3D Scatter plot with grouping variable
%   gscatter3(x,y,z,group,clr,sym,siz,doleg,xnam,ynam,znam)
%   Designed to work in the exactly same fashion as statistics toolbox's gscatter
%   This function does not require the statistics toolbox installed.
%
%
%   See also GSCATTER, GSCATTER3B
%
%   Copyright 2017 Gustavo Ferraz Trinade.

% Set number of groups
cgroups = unique(group);

cmap = lines(size(cgroups,1));

% Input variables
if (nargin < 5),  clr = lines(max(size(cgroups))); end
if (nargin < 6) || isempty(sym), sym = 'odphs><v^odphs><v^odphs><v^odphs><v^'; end
if (nargin < 7),  siz = 100;           end
if (nargin < 8),  doleg = 'on';        end
if (nargin < 9),  xnam = inputname(1); end
if (nargin < 10), ynam = inputname(2); end
if (nargin < 11), znam = inputname(3); end

% Get current axes
a = gca;
hold(a,'on')

% Plot
for i=1:max(size(cgroups))

    if iscell(cgroups) || ischar(cgroups)
        gi = find(strcmp(group,cgroups(i)));
    else
        gi = find(group == cgroups(i));
    end

    scatter3(a,x(gi),y(gi),z(gi),siz,clr(i,:),'filled',sym(i));
end

% Axes labels and legend (this bit slows down the function)
xlabel(a,xnam);
ylabel(a,ynam);
zlabel(a,znam);

if strcmp(doleg,'on')
    if iscell(cgroups) || ischar(cgroups)
        legend(cgroups')
    else
        legend(num2str(cgroups'))
    end
end

end


% VECTDATA - vector data interpolation with optional moving
%              average.
%
% Usage:
%   >> [interparray timesout] = vectdata( array, timesin, 'key', 'val', ... );
%
% Inputs:
%   array      - 1-D or 2-D float array. If 2-D, the second dimension
%                only is interpolated.
%   timesin    - [float vector] time point indices. Same dimension as
%                the interpolated dimension in array.
%
% Optional inputs
%   'timesout' - [float vector] time point indices for interpolating
%                data.
%   'method'   - method for interpolation
%        'linear'    -> Triangle-based linear interpolation (default).
%        'cubic'     -> Triangle-based cubic interpolation.
%        'nearest'   -> Nearest neighbor interpolation.
%        'v4'        -> MATLAB 4 griddata method.
%   'average'  - [real] moving average in the dimension of timesin
%                note that extreme values might be inaccurate (see 'borders').
%                Default none or [].
%   'avgtype'  - ['const'|'gauss'] use a const value when averaging (array of
%                ones) or a gaussian window. Default is 'const'.
%   'border'   - ['on'|'off'] correct border effect when smoothing.
%                default is 'off'.
%
% Outputs:
%   interparray - interpolated array
%   timesout    - output time points
%
% Author: Arnaud Delorme, CNL / Salk Institute, 20 Oct 2002
%
% See also: GRIDDATA

% Copyright (C) 2002 Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function [interparray, timesout] = vectdata( array, timevect, varargin );

if nargin < 3
    help vectdata;
    return;
end

g = finputcheck( varargin, { 'timesout'   'real'  []           [];
                             'average'    'real'  []           [];
                             'gauss'      'real'  []           [];
                             'border'     'string' { 'on','off' } 'off';
                             'avgtype'    'string' { 'const','gauss' } 'const';
                             'method'     'string' { 'linear','cubic','nearest','v4' } 'linear'});
if ischar(g), error(g); end

if size(array,2) == 1
    array = transpose(array);
end

if ~isempty(g.average)
    timediff = timevect(2:end) -timevect(1:end-1);
    if any( (timediff - mean(timediff)) > 1e-8 ) % not uniform values
        fprintf('Data has to be interpolated uniformly for moving average\n');
        minspace = mean(timediff);
        newtimevect = linspace(timevect(1), timevect(end), ceil((timevect(end)-timevect(1))/minspace));
        array = interpolate( array, timevect, newtimevect, g.method);
        timevect = newtimevect;
    end
    oldavg = g.average;
    g.average = round(g.average/(timevect(2)-timevect(1)));
    if oldavg ~= g.average
        fprintf('Moving average updated from %3.2f to %3.2f (=%d points)\n', ...
                oldavg, g.average*(timevect(2)-timevect(1)), g.average);
    end
    if strcmpi(g.border, 'on')
        if strcmpi(g.avgtype, 'const')
            array = convolve(array, ones(1, g.average));
        else
            convolution = gauss2d(1,g.average,1,round(0.15*g.average));
            array = convolve(array, convolution);
        end
    else
        if strcmpi(g.avgtype, 'const')
            array = conv2(array, ones(1, g.average)/g.average, 'same');
        else
            convolution = gauss2d(1,g.average,1,round(0.15*g.average));
            array = conv2(array, convolution/sum(convolution), 'same');
        end
    end
end

interparray = interpolate( array, timevect, g.timesout, g.method);
timesout = g.timesout;

% interpolation function
% ----------------------
function [interparray] = interpolate( array, timesin, timesout, method);
    interparray = zeros(size(array,1), length(timesout));
    for index = 1:size(array,1)
        tmpa = [array(index,:) ; array(index,:)];

        [Xi,Yi,Zi] = griddata(timesin, [1 2]', tmpa, timesout, [1 2]', method); % Interpolate data
        interparray(index,:) = Zi(1,:);
    end


function [Fo,Oq,Oqval,DEOPA,goodperiods,OqS,OqvalS,DEOPAS,goodperiodsS,simppeak,dSIG,SdSIG] = ...
    FO(COEF,method,propthresh,resampC,maxF,SIG,FS)

% FO: detection of Fundamental frequency and Open quotient on the basis of the
% derivative of the electroglottographic signal.
% This is the script that calls the various functions for analysis of the
% electroglottographic signal.
%
% The sequence of operations is as follows:
% - the function CRO detects the points where the DEGG signal crosses the threshold
% set for peak detection, and calls the function RIM which determines where peaks
% begin and end
%
% - the function AMPOS reinterpolates the signal within the peak regions (to
% obtain a more accurate measurement of peak height) and calls the function
% PEAKSHAPE to detect the number of summits and the ratio of the amplitude of
% the summits
%
% - the function DETECTMULT treats double peaks of another kind: double peaks
% that are almost completely distinct, and belong in different "peak bunches"
% (regions created by CRO), but which are too close for their Fo to make sense,
% and are thus considered as making up one double/multiple peak.
% There are thus two vectors containing information on double peaks: verif, for
% peaks which are unique at threshold level and fork at a higher level; and
% doublepeaks for peaks which fork below threshold level.
%
% - the function SIMP calculates an approximative Fo value.

% retrieving user choice for smoothing step. Reminder: 0 means no smoothing; 1
% means smoothing 1 point to the left and right, i.e. over 3 data points; 2
% means smoothing 2 points to the left and right, i.e. over 5 data points, etc.
C_SMOO = COEF(2);

% retrieving user choice for amplitude threshold setting method
toggle = COEF(3);

% retrieving user choice for amplitude threshold
AMP = COEF(4);

% Placing the sampling rate in first slot of <COEF> vector
COEF(1) = FS;

% Sampling period: (T for: period, s for: sampling)
Ts = 1 / COEF(1);

% check that the signal is Mono; if it is stereo: de-multiplexing it
[S,P] = size(SIG);
%%%% calculating the derivative of the signal
% <dSIG> is the first derivative of <SIG>. No smoothing is done at this stage, as the
% detection of the closing peaks is best done using the unsmoothed signal. If a
% smoothing step has been specified, it is used later: in the detection of opening peaks.
dSIG = [];
for w = 1 : length(SIG) - 1
   dSIG (w) = SIG (w + 1) - SIG (w);
end

%%%% smoothing the derivative of the signal
if C_SMOO > 0
    disp('Smoothing signal...')
    SdSIG = smoo(dSIG,C_SMOO);
    disp('Smoothed.')
else
    SdSIG = dSIG;
end

% detecting points where the DEGG signal crosses the threshold; this is done
% using the smoothed signal, otherwise the number of crossings may be very high
% due to a saw-like shape of the signal
[rims] = CRO(SdSIG,COEF);

% detection of the amplitude and position of the peaks (on the reinterpolated signal)
[Tgci,valid,validtime,numberofpeaks] = AMPOS(SIG,rims,resampC,Ts,method,propthresh);

% detection of double / multiple closing peaks ("peak clusters")
doublepeaks = detectmult(Tgci,maxF);

% choice of closing peaks, creating a matrix with only one maximum per cycle.
[simppeak,BUND] = simp(Tgci,doublepeaks,method);

%%%%%%%%%%% Calculating Fo on the basis of the unique peaks
Fo = [];
for w = 1:length(simppeak(:,1)) - 1
    Fo(w) = 1 / (simppeak(w + 1,1) - simppeak(w,1));
end

% Retrieving opening peaks where possible on unsmoothed signal
[Oq,Oqval,DEOPA,goodperiods] = OP(simppeak,SIG,dSIG,valid,doublepeaks,COEF,resampC,Ts,method);

%%% Second call to the function OP, with smoothed signal
[OqS,OqvalS,DEOPAS,goodperiodsS] = OP(simppeak,SIG,SdSIG,valid,doublepeaks,COEF,resampC,Ts,method);


function PopDec = EvolALG(Problem,PCheby,Dec,model,IFEs)
% Solution update in ParEGO, where a solution with the best expected
% improvement is re-evaluated

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

% This function is written by Cheng He

    Off   = [OperatorGA(Problem,Dec(TournamentSelection(2,size(Dec,1),PCheby),:));OperatorGA(Problem,Dec,{0,0,1,20})];
    N     = size(Off,1);
    EI    = zeros(N,1);
    Gbest = min(PCheby);
    E0    = inf;
    while IFEs > 0
        drawnow('limitrate');
        for i = 1 : N
            [y,~,mse] = predictor(Off(i,:),model);
            s         = sqrt(mse);
            EI(i)     = -(Gbest-y)*normcdf((Gbest-y)/s)-s*normpdf((Gbest-y)/s);
        end
        [~,index] = sort(EI);
        if EI(index(1)) < E0
            Best = Off(index(1),:);
            E0   = EI(index(1));
        end
        Parent = Off(index(1:ceil(N/2)),:);
        Off    = [OperatorGA(Problem,Parent(TournamentSelection(2,size(Parent,1),EI(index(1:ceil(N/2)))),:));OperatorGA(Problem,Parent,{0,0,1,20})];
        IFEs   = IFEs - size(Off,1);
    end
    PopDec = Best;
end


function [params, names] = gibbsperiodicKernExtractParam(kern)

% GIBBSPERIODICKERNEXTRACTPARAM Extract parameters from the GIBBSPERIODIC kernel structure.
% FORMAT
% DESC extracts parameters from the Gibbs-kernel derived periodic
% kernel structure into a vector of parameters for optimisation.
% ARG kern : the kernel structure containing the parameters to be
% extracted.
% RETURN param : vector of parameters extracted from the kernel. If
% the field 'transforms' is not empty in the kernel structure, the
% parameters will be transformed before optimisation (for example
% positive only parameters could be logged before being returned).
%
% FORMAT
% DESC extracts parameters and parameter names from the Gibbs-kernel derived periodic
% kernel structure.
% ARG kern : the kernel structure containing the parameters to be
% extracted.
% RETURN param : vector of parameters extracted from the kernel. If
% the field 'transforms' is not empty in the kernel structure, the
% parameters will be transformed before optimisation (for example
% positive only parameters could be logged before being returned).
% RETURN names : cell array of strings containing names for each
% parameter.
%
% SEEALSO gibbsperiodicKernParamInit, gibbsperiodicKernExpandParam, kernExtractParam, scg, conjgrad
%
% COPYRIGHT : Neil D. Lawrence, 2007

% KERN

params = zeros(1, kern.nParams);
if nargout < 2
  params(1:end-1) = modelExtractParam(kern.lengthScaleFunc);
  params(end) = kern.variance;
else
  names = cell(1, kern.nParams);
  [params(1:end-1), names(1:end-1)] = modelExtractParam(kern.lengthScaleFunc);
  params(end) = kern.variance;
  names{end} = 'variance';
end


classdef TestRectify3Collinear
    %TestRectify3Collinear

    properties (Constant)
        fields = {'R1', 'R2', 'R3', 'P1', 'P2', 'P3', 'Q', ...
            'roi1', 'roi2', 'ratio'};
    end

    methods (Static)
        function test_1
            imgSz = [640 480];
            cam1 = eye(3);
            cam2 = eye(3);
            cam3 = eye(3);
            distort1 = zeros(1,5);
            distort2 = zeros(1,5);
            distort3 = zeros(1,5);
            R12 = [cv.getRotationMatrix2D(imgSz./2, 0, 1); 0 0 1];
            R13 = [cv.getRotationMatrix2D(imgSz./2, 0, 1); 0 0 1];
            T12 = [1; 0; 0];
            T13 = [1; 0; 0];
            S = cv.rectify3Collinear(cam1, distort1, cam2, distort2, ...
                cam3, distort3, imgSz, R12, T12, R13, T13, ...
                'ZeroDisparity',false, 'Alpha',-1, 'NewImageSize',imgSz./2);
            validateattributes(S, {'struct'}, {'scalar'});
            assert(all(ismember(TestRectify3Collinear.fields, fieldnames(S))));
            validateattributes(S.R1, {'numeric'}, {'size',[3 3]});
            validateattributes(S.R2, {'numeric'}, {'size',[3 3]});
            validateattributes(S.R3, {'numeric'}, {'size',[3 3]});
            validateattributes(S.P1, {'numeric'}, {'size',[3 4]});
            validateattributes(S.P2, {'numeric'}, {'size',[3 4]});
            validateattributes(S.P3, {'numeric'}, {'size',[3 4]});
            validateattributes(S.Q, {'numeric'}, {'size',[4 4]});
            validateattributes(S.roi1, {'numeric'}, ...
                {'vector', 'numel',4, 'integer'});
            validateattributes(S.roi2, {'numeric'}, ...
                {'vector', 'numel',4, 'integer'});
            validateattributes(S.ratio, {'numeric'}, {'scalar'});
        end

        function test_error_argnum
            try
                cv.rectify3Collinear();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


function SimVaryResults = SimVary(obj, runs, OptTable, Opts)
% Performs Sensitivity analysis on Model object
% Each Parameter (obj.xnames) is varied in 10 steps between OptTable.lb and OptTable.ub.
% Noise is added N=runs times and simulated MR signals is fitted using obj.Sim_Single_Voxel_Curve
%
% USAGE: SimVaryResults = SimVary(obj, runs, OptTable, Opts)
%
%        obj: qMR Model
%        runs: Number of runs
%        OptTable: structure with vectors defining options for each fitting parameters obj.xnames
%               OptTable.fx: true/false. Vary this parameter?
%               OptTable.st: Nominal Values
%               OptTable.lb: Vary from lb...
%               OptTable.ub: ..to ub value
%        Opts.SNR
%

Nsteps = 10;

if ~exist('OptTable','var') || isempty(OptTable), OptTable = obj; end % use fitting boundaries
if ~exist('Opts','var') || isempty(Opts), Opts.SNR = 50; end
if isempty(getenv('ISCITEST')) || str2double(getenv('ISCITEST'))==0
    waitbarcreate = true;
else
    waitbarcreate = false;
    Nsteps=3;
end

if ~isempty(getenv('ISDOC')), Nsteps=10; end

fx = [OptTable.fx];
st = [OptTable.st];
lb = [OptTable.lb];
ub = [OptTable.ub];

for pp=1:length(fx)
    if ~fx(pp)
        Sens.x = linspace(lb(pp),ub(pp),Nsteps);
        % Create waitbar
        if waitbarcreate
            h = waitbar(0, sprintf('Data 0/%0.0f',length(Sens.x)), 'Name', sprintf('Simulating %s sensitivity data', obj.xnames{pp}),...
                'CreateCancelBtn', 'if ~strcmp(get(gcbf,''Name''),''canceling...''), setappdata(gcbf,''canceling'',1); set(gcbf,''Name'',''canceling...''); else delete(gcbf); end');
            setappdata(h,'canceling',0);
        end
        setappdata(0,'Cancel',0);

        for ii=1:length(Sens.x)
            x = st; x(pp)=Sens.x(ii);
            for N=1:runs
                if waitbarcreate && (~ishandle(h) || getappdata(h,'canceling')); setappdata(0,'Cancel',1); break; end
                Fittmp = obj.Sim_Single_Voxel_Curve(x, Opts,0);
                if ~isfield(Sens,'fit')
                    Sens.fit = Fittmp;
                else
                    for ff=fieldnames(Fittmp)'
                        Sens.fit.(ff{1})(ii,N) = Fittmp.(ff{1})(1);
                    end
                end
                %if ~ishandle(h), return; end
            end
            if waitbarcreate && (~ishandle(h) || getappdata(h,'canceling')); break; end
            if waitbarcreate && ishandle(h)
                waitbar(ii/length(Sens.x),h,sprintf('Data %0.0f/%0.0f',ii,length(Sens.x)));
            end
        end

        if waitbarcreate
            delete(h)       % DELETE the waitbar; don't try to CLOSE it.
        end

        for ff=fieldnames(Sens.fit)'
            Sens.(ff{1}).mean = mean(Sens.fit.(ff{1}),2);
            Sens.(ff{1}).std = std(Sens.fit.(ff{1}),0,2);
            Sens.(ff{1}).GroundTruth = st(strcmp(obj.xnames,ff{1}));
        end
        SimVaryResults.(obj.xnames{pp})=Sens;
    end
end


%% computeKappas.m
% This scripts computes normalization coefficient for each image in database.
%
% 02-08-11 Michal Uricar

clc;
close all; clearvars;

%% Timestamp

fprintf(1,'Started on %s\n\n', datestr(now));

%% load GT - TRN

gt_fname = './MAT/GT_nImages-all.mat';
load(gt_fname);

%% compute kappas

kappa = inf(1, numel(gt));

for i = 1 : numel(gt)
    GT = gt{i};
    C = ( (GT(:, 2)+GT(:, 6))/2 + (GT(:, 3)+GT(:, 7))/2 )/2;
    kappa(i) = 1/sqrt(sum(( C - (GT(:, 4)+GT(:, 5))/2 ).^2));
end;

%% save kappas

save('./MAT/kappas.mat', 'kappa');

%% load GT - VAL

gt_fname = './MAT/GTVal_nImages-all.mat';
load(gt_fname);

%% compute kappas

kappa = inf(1, numel(gt));

for i = 1 : numel(gt)
    GT = gt{i};
    C = ( (GT(:, 2)+GT(:, 6))/2 + (GT(:, 3)+GT(:, 7))/2 )/2;
    kappa(i) = 1/sqrt(sum(( C - (GT(:, 4)+GT(:, 5))/2 ).^2));
end;

%% save kappas

save('./MAT/kappasVAL.mat', 'kappa');

%% load GT - TST

gt_fname = './MAT/GTTst_nImages-all.mat';
load(gt_fname);

%% compute kappas

kappa = inf(1, numel(gt));

for i = 1 : numel(gt)
    GT = gt{i};
    C = ( (GT(:, 2)+GT(:, 6))/2 + (GT(:, 3)+GT(:, 7))/2 )/2;
    kappa(i) = 1/sqrt(sum(( C - (GT(:, 4)+GT(:, 5))/2 ).^2));
end;

%% save kappas

save('./MAT/kappasTST.mat', 'kappa');

%% Timestamp

fprintf(1,'Finished on %s\n\n', datestr(now));


function x = mysvec(X)
% This function is my implementation of the svec function of SDPT3

% SP

s = size(X,1);
ii = ones(s);
idx1 = find(triu(ii));
idx2 = find(triu(ii,1));
X(idx2) = X(idx2)*sqrt(2);
x = X(idx1);


function as = make3daxes(h)
% make3daxes creates a dextral set of coordinate axes for animation.
%
% as = make3daxes returns an array (as) continaing handles to three surface
% objects created in figure h representing the unit vectors of a dextral
% reference frame.
%
% Note: This function is intended to be called by animEuler.m
%
% Examples:
%     as = make3daxes(1);

% Written by Dmitry Savransky 29 April 2009

%set figure and remove all children
figure(h);
clf(h,'reset');
hold off

%create an axis
[xrod,yrod,zrod] = cylinder(0.05,12);

%create and place the axes
a3 = surface(xrod,yrod,zrod,'FaceColor','b','AlphaData',0.5);
a2 = surface(xrod,yrod,zrod,'FaceColor','g','AlphaData',0.5);
a1 = surface(xrod,yrod,zrod,'FaceColor','r','AlphaData',0.5);
rotate(a2,[1 0 0],-90,[0,0,0])
rotate(a1,[0 1 0],90,[0,0,0])

%clean up display
axis equal;
axis([-1 1 -1 1 -1 1])
view(100,15)
grid on
xlabel('x');
ylabel('y');
zlabel('z');

%return handles
as = [a1 a2 a3];


function disp(t,name)
%DISP Command window display of a matricized tensor (tenmat).
%
%   DISP(T) displays a tensor as matrix with no name.
%
%   DISP(T,NAME) display a tensor as matrix with the given name.
%
%   See also TENMAT, TENMAT/DISPLAY.
%
%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

if ~exist('name','var')
    name = 'ans';
end

fprintf('%s is a matrix corresponding to a tensor of size %s\n',...
        name,tt_size2str(t.tsize));
fprintf('\t%s.rindices = %s (modes of tensor corresponding to rows)\n',...
        name,['[ ' num2str(t.rindices) ' ]']);
fprintf('\t%s.cindices = %s (modes of tensor corresponding to columns)\n',...
        name,['[ ' num2str(t.cindices) ' ]']);

if isempty(t.data)
    fprintf('\t%s.data = []\n',name);
else
    fprintf('\t%s.data = \n',name);
    output = tt_matrix2cellstr(t.data);
    fprintf('\t\t%s\n',output{:});
end


classdef MaterialFactory < handle

    methods (Access = public, Static)

        function material = create(cParams)
            switch cParams.ptype
                case {'ELASTIC','DIFF-REACT'}
                    switch cParams.pdim
                        case '2D'
                            cParams.nstre = 3;
                            material = Isotropic2dElasticMaterial(cParams);
                        case '3D'
                            cParams.nstre = 6;
                            material = Isotropic3dElasticMaterial(cParams);
                    end

                case 'HYPERELASTIC'
                    switch cParams.pdim
                        case '2D'
                            cParams.connec = cParams.mesh.connec;
                            cParams.dNdx   = cParams.geometry.dNdx;
                            cParams.nnode  = cParams.mesh.nnodeElem;
                            cParams.coord  = cParams.mesh.coord;
                            material = Isotropic2dHyperElasticMaterial(cParams);
                    end

                case 'THERMAL'
                    error('Still not implemented.')
                case 'Stokes'
                    material = Material_Stokes(cParams);
                otherwise
                    error('Invalid ptype.')
            end

        end

    end
end


function [net, info] = cnn_train_adagrad(net, imdb, getBatch, varargin)
% CNN_TRAIN   Demonstrates training a CNN
%    CNN_TRAIN() is an example learner implementing stochastic gradient
%    descent with momentum to train a CNN for image classification.
%    It can be used with different datasets by providing a suitable
%    getBatch function.

opts.train = [] ;
opts.val = [] ;
opts.numEpochs = 300 ;
opts.batchSize = 256 ;
opts.useGpu = false ;
opts.learningRate = 0.001 ;
opts.continue = false ;
opts.expDir = fullfile('data','exp') ;
opts.conserveMemory = false ;
opts.sync = true ;
opts.prefetch = false ;
opts.weightDecay = 0.0005 ;
opts.errorType = 'multiclass' ;
opts.plotDiagnostics = false ;
opts.delta = 1e-8;
opts.display = 1;
opts.snapshot = 1;
opts.test_interval = 1;
opts = vl_argparse(opts, varargin) ;

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

% -------------------------------------------------------------------------
%                                                    Network initialization
% -------------------------------------------------------------------------

for i=1:numel(net.layers)
  if ~strcmp(net.layers{i}.type,'conv'), continue; end
  net.layers{i}.filtersMomentum = zeros(size(net.layers{i}.filters), ...
    class(net.layers{i}.filters)) ;
  net.layers{i}.biasesMomentum = zeros(size(net.layers{i}.biases), ...
    class(net.layers{i}.biases)) ; %#ok<*ZEROLIKE>
  if ~isfield(net.layers{i}, 'filtersLearningRate')
    net.layers{i}.filtersLearningRate = 1 ;
  end
  if ~isfield(net.layers{i}, 'biasesLearningRate')
    net.layers{i}.biasesLearningRate = 1 ;
  end
  if ~isfield(net.layers{i}, 'filtersWeightDecay')
    net.layers{i}.filtersWeightDecay = 1 ;
  end
  if ~isfield(net.layers{i}, 'biasesWeightDecay')
    net.layers{i}.biasesWeightDecay = 1 ;
  end
end

if opts.useGpu
  net = vl_simplenn_move(net, 'gpu') ;
  for i=1:numel(net.layers)
    if ~strcmp(net.layers{i}.type,'conv'), continue; end
    net.layers{i}.filtersMomentum = gpuArray(net.layers{i}.filtersMomentum) ;
    net.layers{i}.biasesMomentum = gpuArray(net.layers{i}.biasesMomentum) ;
  end
end

G_f = cell(numel(net.layers), 1);
G_b = cell(numel(net.layers), 1);

for l=1:numel(net.layers)

  if ~strcmp(net.layers{l}.type, 'conv'), continue ; end

  G_f{l} = zeros(size(net.layers{l}.filters), 'single');
  G_b{l} = zeros(size(net.layers{l}.biases), 'single');

end

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

rng(0) ;

if opts.useGpu
  one = gpuArray(single(1)) ;
else
  one = single(1) ;
end

info.train.objective = [] ;
info.train.error = [] ;
info.train.topFiveError = [] ;
info.train.speed = [] ;
info.val.objective = [] ;
info.val.error = [] ;
info.val.topFiveError = [] ;
info.val.speed = [] ;

lr = opts.learningRate ;
res = [] ;
for epoch=1:opts.numEpochs

  % fast-forward to where we stopped
  modelPath = @(ep) fullfile(opts.expDir, sprintf('net-epoch-%d.mat', ep));
  modelFigPath = fullfile(opts.expDir, 'net-train.pdf') ;
  if opts.continue
    if exist(modelPath(epoch),'file')
      if epoch == opts.numEpochs
        load(modelPath(epoch), 'net', 'info') ;
      end
      continue ;
    end
    if epoch > 1
      fprintf('resuming by loading epoch %d\n', epoch-1) ;
      load(modelPath(epoch-1), 'net', 'info') ;
    end
  end

  train = opts.train(randperm(numel(opts.train))) ;
  val = opts.val ;

  info.train.objective(end+1) = 0 ;
  info.train.error(end+1) = 0 ;
  info.train.topFiveError(end+1) = 0 ;
  info.train.speed(end+1) = 0 ;
  info.val.objective(end+1) = 0 ;
  info.val.error(end+1) = 0 ;
  info.val.topFiveError(end+1) = 0 ;
  info.val.speed(end+1) = 0 ;

  for t=1:opts.batchSize:numel(train)
    % get next image batch and labels
    batch = train(t:min(t+opts.batchSize-1, numel(train))) ;
    batch_time = tic ;
    fprintf('training: epoch %02d: processing batch %3d of %3d ...', epoch, ...
            fix(t/opts.batchSize)+1, ceil(numel(train)/opts.batchSize)) ;
    [im, labels] = getBatch(imdb, batch) ;
    if opts.prefetch
      nextBatch = train(t+opts.batchSize:min(t+2*opts.batchSize-1, numel(train))) ;
      getBatch(imdb, nextBatch) ;
    end
    if opts.useGpu
      im = gpuArray(im) ;
    end

    % backprop
    net.layers{end}.class = labels ;
    res = vl_simplenn(net, im, one, res, ...
      'conserveMemory', opts.conserveMemory, ...
      'sync', opts.sync) ;

    % gradient step
    for l=1:numel(net.layers)
      if ~strcmp(net.layers{l}.type, 'conv'), continue ; end

      g_f = (net.layers{l}.filtersLearningRate) * ...
            (opts.weightDecay * net.layers{l}.filtersWeightDecay) * net.layers{l}.filters + ...
            (net.layers{l}.filtersLearningRate) / numel(batch) * res(l).dzdw{1};
      g_b = (net.layers{l}.biasesLearningRate) * ...
            (opts.weightDecay * net.layers{l}.biasesWeightDecay) * net.layers{l}.biases + ...
            (net.layers{l}.biasesLearningRate) / numel(batch) * res(l).dzdw{2};

      G_f{l} = G_f{l} + g_f .^ 2;
      G_b{l} = G_b{l} + g_b .^ 2;

      net.layers{l}.filters = net.layers{l}.filters - lr ./ (opts.delta + sqrt(G_f{l})) .* g_f;
      net.layers{l}.biases  = net.layers{l}.biases - lr ./ (opts.delta + sqrt(G_b{l})) .* g_b;
    end

    % print information
    batch_time = toc(batch_time) ;
    speed = numel(batch)/batch_time ;
    info.train = updateError(opts, info.train, net, res, batch_time) ;

    fprintf(' %.2f s (%.1f images/s)', batch_time, speed) ;
    n = t + numel(batch) - 1 ;
    switch opts.errorType
      case 'multiclass'
        fprintf(' err %.1f err5 %.1f', ...
          info.train.error(end)/n*100, info.train.topFiveError(end)/n*100) ;
        fprintf('\n') ;
      case 'binary'
        fprintf(' err %.1f', ...
          info.train.error(end)/n*100) ;
        fprintf('\n') ;
      case 'euclideanloss'
        fprintf(' err %.1f', info.train.error(end) / n);
        fprintf('\n') ;
    end

    % debug info
    if opts.plotDiagnostics
      figure(2) ; vl_simplenn_diagnose(net,res) ; drawnow ;
    end
  end % next batch

  % evaluation on validation set
  if epoch == 1 || rem(epoch, opts.test_interval) == 0 || epoch == opts.numEpochs
  for t=1:opts.batchSize:numel(val)
    batch_time = tic ;
    batch = val(t:min(t+opts.batchSize-1, numel(val))) ;
    fprintf('validation: epoch %02d: processing batch %3d of %3d ...', epoch, ...
            fix(t/opts.batchSize)+1, ceil(numel(val)/opts.batchSize)) ;
    [im, labels] = getBatch(imdb, batch) ;
    if opts.prefetch
      nextBatch = val(t+opts.batchSize:min(t+2*opts.batchSize-1, numel(val))) ;
      getBatch(imdb, nextBatch) ;
    end
    if opts.useGpu
      im = gpuArray(im) ;
    end

    net.layers{end}.class = labels ;
    res = vl_simplenn(net, im, [], res, ...
      'disableDropout', true, ...
      'conserveMemory', opts.conserveMemory, ...
      'sync', opts.sync) ;

    % print information
    batch_time = toc(batch_time) ;
    speed = numel(batch)/batch_time ;
    info.val = updateError(opts, info.val, net, res, batch_time) ;

    fprintf(' %.2f s (%.1f images/s)', batch_time, speed) ;
    n = t + numel(batch) - 1 ;
    switch opts.errorType
      case 'multiclass'
        fprintf(' err %.1f err5 %.1f', ...
          info.val.error(end)/n*100, info.val.topFiveError(end)/n*100) ;
        fprintf('\n') ;
      case 'binary'
        fprintf(' err %.1f', ...
          info.val.error(end)/n*100) ;
        fprintf('\n') ;
      case 'euclideanloss'
        fprintf(' err %.1f', info.val.error(end) / n);
        fprintf('\n') ;
    end
  end
  end

  % save
  info.train.objective(end) = info.train.objective(end) / numel(train) ;
  info.train.error(end) = info.train.error(end) / numel(train)  ;
  info.train.topFiveError(end) = info.train.topFiveError(end) / numel(train) ;
  info.train.speed(end) = numel(train) / info.train.speed(end) ;
  info.val.objective(end) = info.val.objective(end) / numel(val) ;
  info.val.error(end) = info.val.error(end) / numel(val) ;
  info.val.topFiveError(end) = info.val.topFiveError(end) / numel(val) ;
  info.val.speed(end) = numel(val) / info.val.speed(end) ;
  if epoch == 1 || rem(epoch, opts.snapshot) == 0 || epoch == opts.numEpochs
  save(modelPath(epoch), 'net', 'info') ;
  end

  if epoch == 1 || rem(epoch, opts.display) == 0 || epoch == opts.numEpochs
  figure(1) ; clf ;
  subplot(1,2,1) ;
  semilogy(1:epoch, info.train.objective, 'k') ; hold on ;
  semilogy([1 opts.test_interval : opts.test_interval : epoch epoch], info.val.objective([1 opts.test_interval : opts.test_interval : epoch epoch]), 'b') ;
  xlabel('training epoch') ; ylabel('energy') ;
  grid on ;
  h=legend('train', 'val') ;
  set(h,'color','none');
  title('objective') ;
  subplot(1,2,2) ;
  switch opts.errorType
    case 'multiclass'
      plot(1:epoch, info.train.error, 'k') ; hold on ;
      plot(1:epoch, info.train.topFiveError, 'k--') ;
      plot([1 opts.test_interval : opts.test_interval : epoch epoch], info.val.error([1 opts.test_interval : opts.test_interval : epoch epoch]), 'b') ;
      plot([1 opts.test_interval : opts.test_interval : epoch epoch], info.val.topFiveError([1 opts.test_interval : opts.test_interval : epoch epoch]), 'b--') ;
      h=legend('train','train-5','val','val-5') ;
    case 'binary'
      plot(1:epoch, info.train.error, 'k') ; hold on ;
      plot([1 opts.test_interval : opts.test_interval : epoch epoch], info.val.error([1 opts.test_interval : opts.test_interval : epoch epoch]), 'b') ;
      h=legend('train','val') ;
    case 'euclideanloss'
      plot(1 : epoch, info.train.error, 'k'); hold on;
      plot([1 opts.test_interval : opts.test_interval : epoch epoch], info.val.error([1 opts.test_interval : opts.test_interval : epoch epoch]), 'b') ;
      h = legend('train', 'val') ;
  end
  grid on ;
  xlabel('training epoch') ; ylabel('error') ;
  set(h,'color','none') ;
  title('error') ;
  drawnow ;
  print(1, modelFigPath, '-dpdf') ;
  end
end

% -------------------------------------------------------------------------
function info = updateError(opts, info, net, res, speed)
% -------------------------------------------------------------------------
predictions = gather(res(end-1).x) ;
sz = size(predictions) ;
n = prod(sz(1:2)) ;

labels = net.layers{end}.class ;
info.objective(end) = info.objective(end) + sum(double(gather(res(end).x))) ;
info.speed(end) = info.speed(end) + speed ;
switch opts.errorType
  case 'multiclass'
    [~,predictions] = sort(predictions, 3, 'descend') ;
    error = ~bsxfun(@eq, predictions, reshape(labels, 1, 1, 1, [])) ;
    info.error(end) = info.error(end) +....
      sum(sum(sum(error(:,:,1,:))))/n ;
    info.topFiveError(end) = info.topFiveError(end) + ...
      sum(sum(sum(min(error(:,:,1:5,:),[],3))))/n ;
  case 'binary'
    error = bsxfun(@times, predictions, labels) < 0 ;
    info.error(end) = info.error(end) + sum(error(:))/n ;
  case 'euclideanloss'
    error = euclideanloss(sigmoid(predictions), labels);
    info.error(end) = info.error(end) + error;
end


classdef dbn
% Deep Belief Network object.
%-----------------------------------------------------------------------------
% Initialize, train, and fine-tune a deep belief network.
% Note this function calls the rbm.m object to form layers.
%-----------------------------------------------------------------------------
% Dustin E. Stansbury
% stan_s_bury@berkeley.edu

properties
	class = 'dbn';			% OBJECT CLASS
	arch;					% ARCHITECTURE/OPTIONS
	inputType='binary';		% DEFAULT INPUT TYPE
	classifier=false;		% CLASSIFIER LAYER AT TOP
	nLayers;				% TOTAL # OF LAYERS (INCLUDING INPUT)
	nRBMLayers;				% # OF RBM LAYERS
	rbmLayers;				% RBM LAYERS
	verbose = 1;			% DISPLAY OUTPUT
	saveDir
end

methods
	function self = dbn(arch)
	% d = dbn(arch)
	%--------------------------------------------------------------------------
	% DBN constructor
	%--------------------------------------------------------------------------
	% INPUT:
	%  <arch>:  - a set of arguments defining the DBN architecture.
	%
	% OUTPUT:
	%     <d>:  - an DBN model object.
	%--------------------------------------------------------------------------
		self = self.init(arch);
	end

	function print(self)
	% print()
	%--------------------------------------------------------------------------
	% Display the properties and methods for the DBN object class.
	%--------------------------------------------------------------------------
		properties(self)
		methods(self)
	end

	function self = train(self,X,targets);
	% self = train(X,[targets])
	%--------------------------------------------------------------------------
	% Perform greedy layer-wise training of of a DBN
	%--------------------------------------------------------------------------
	% INPUT:
	%        <X>:  - to-be modeled data |X| = [#Obs x #Vis]
	%  <targets>:  - category targets. can be either [#Obs x #Class] as 1 of
	%                K representation or [#Obs x 1], where each entry is a
	%                numerical category label. (optional)
	% OUTPUT:
	%     <self>:  - trained DBN object.
	%--------------------------------------------------------------------------
		for iL = 1:self.nRBMLayers
			if self.verbose,
				self.printProgress('layerTrain',iL);
			end

			% TRAIN AN RBM LAYER
			if iL == self.nRBMLayers & self.classifier
				self.rbmLayers{iL} = self.rbmLayers{iL}.train(X,targets);
			else

				self.rbmLayers{iL} = self.rbmLayers{iL}.train(X,[]);
			end

			% PREPROCESS INPUT FOR NEXT LAYER
			X = self.rbmLayers{iL}.hidExpect(X);
		end
		if ~isempty(self.saveDir),
			d = self;
			save(fullfile(self.saveDir,'dbn.mat'),'d','-v7.3');
		end
	end

	function net = fineTune(self,X,targets,ftArch);
	%  net = fineTune(X,targets,ftArch);
	%--------------------------------------------------------------------------
	% Initialize a multi-layer neural network with trained DBN features and
	% fine tune for a task using backprop (stochastic gradient descent)
	%--------------------------------------------------------------------------
	% INPUT:
	%        <X>:  - to-be modeled data |X| = [#Obs x #Vis]
	%  <targets>:  - target variables.
	%   <ftArch>:  - architecture for the corresponding neural network (see
	%                mlnn.m)
	%
	% OUTPUT:
	%      <net>:  - a trained multi-layer neural network
	%--------------------------------------------------------------------------
		[nObs,nOut] = size(targets);
		if self.verbose
			self.printProgress('fineTune')
		end

		ftArch.size = [self.arch.size,nOut];

		net = mlnn(ftArch);
		% INITIALIZE MLNN WITH DBN WEIGHTS
		for iL = 1:numel(self.arch.size)-1
			net.layers{iL}.W = self.rbmLayers{iL}.W';
			net.layers{iL}.b = self.rbmLayers{iL}.c';
		end
		% FINE TUNE
		net = net.train(X,targets);
	end

	function [outAct,outProb,layerOut] = fProp(self,X,targets);
	% [outAct,outProb] = fProp(X,[targets]);
	%--------------------------------------------------------------------------
	% Forward propagate signal up through the layers of the dbn.
	%--------------------------------------------------------------------------
	% OUTPUT:
	%  <outAct>:  - activation of the top layer/output hidden units
	% <outProb>:  - probabilities of top layer hidden units
	%--------------------------------------------------------------------------
		if notDefined('targets'),
			targets = 0;
		end

		for iL = 1:self.nRBMLayers-1
			X = self.rbmLayers{iL}.hidExpect(X);
		end
		layerOut = self.rbmLayers{end}.hidGivVis(X,targets,1);
		outAct = layerOut.aHid;
		outProb = layerOut.pHid;
	end

	function [pred,error,misClass] = classify(self,X,targets)
	%  [pred,error,misClass] = classify(X,[targets])
	%--------------------------------------------------------------------------
	% Forward propagate data <X> through the layers of the DBN and classify.
	% If <targets> provided, also returns the classification error <error>,
	% and the indices of the misclassified inputs <misClass>.
	%--------------------------------------------------------------------------

		if notDefined('targets')
			targets = [];
		else
			if isvector(targets);
				targets = self.oneOfK(targets);
			end
		end

		% PROPAGATE DATA SIGNALS UP
		for iL = 1:self.nRBMLayers-1
			X = self.rbmLayers{iL}.hidExpect(X);
		end

		% CALCULATE TOP LAYER ACTIVATIONS
		nClasses = self.rbmLayers{end}.nClasses;
		tmp = self.rbmLayers{end}.hidGivVis(X,zeros(size(X,1),nClasses),1);

		% CALCULATE CLASS PROBABILITY
		pClass = tmp.softMax(bsxfun(@plus,tmp.aHid*tmp.classW',tmp.d));

		% WINNER-TAKE-ALL CLASSIFICATION
		[~, pred] = max(pClass,[],2);

		if ~notDefined('targets') && nargout > 1
			[~,targets] = max(targets,[],2);

			% CALCULATE MISSCLASSIFICATION RATE
			misClass = find(pred~=targets);
			error = numel(misClass)/size(X,1);
		end
	end

	function self = init(self,arch)
	% dbn = init(arch)
	%--------------------------------------------------------------------------
	% Initialize deep belief network, based on architecture structure <arch>.
	%--------------------------------------------------------------------------
	% INPUT:
	% <arch>:  - Is an archtiecture struct with the fields:
	%            .shape    --> [#Vis #Hid1, ..., #HidN, #out]
	%            .lRate    --> the learning rate for each layer
	%            .sparsity --> the sparsity target for hidden units
	%            .dropout  --> the hidden unit dropout rate for each rbm layer
	%--------------------------------------------------------------------------
		arch = self.ensureArchetecture(arch);

		% GLOBAL OPTIONS
		if isfield(arch,'opts');
			opts = arch.opts;
			fn = fieldnames(self);
			for iA = 1:2:numel(opts)
				if ~isstr(opts{iA})
					error('<opts> must be a cell array string-value pairs.');
				elseif sum(strcmp(fn,opts{iA}))
					self.(opts{iA})=opts{iA+1};
				end
			end
		end

		self.arch = arch;
		self.nLayers = numel(arch.size);
		self.nRBMLayers = self.nLayers - 1;

		% INITIALIZE RBM LAYERS
		for iL = 2:self.nLayers
			layerArch.size = [arch.size(iL-1),arch.size(iL)];
			if iL == 2
				layerArch.inputType = self.inputType;
			else
				layerArch.inputType = 'binary';
			end

			self.rbmLayers{iL-1} = rbm(layerArch);
			self.rbmLayers{iL-1}.lRate = arch.lRate(iL-1);
			self.rbmLayers{iL-1}.nEpoch = arch.nEpoch(iL-1);
			self.rbmLayers{iL-1}.sparsity = arch.sparsity(iL-1);
			self.rbmLayers{iL-1}.dropout = arch.dropout(iL-1);

			if self.classifier & (iL == self.nLayers)
				self.rbmLayers{end}.classifier = true;
			end
		end
	end

	function arch = ensureArchetecture(self,arch)
	% arch = ensureArchitecture(arch)
	%--------------------------------------------------------------------------
	% Preprocess the provided architecture structure <arch>.
	%--------------------------------------------------------------------------
	% INPUT:
	% <arch>:  - is either a [2 x 1] vector giving the [#Vis x #Hid], in which
	%            case we use the default model parameters, or it is a strucure
	%            with any of the fields:
	%             .size                --> Network size; [#Vis x # Hid]
	%             .nEpoch(optional)    --> # of training epochs for each layer
	%             .lRate (optional)    --> learing rate for each layer
	%             .sparsity (optional) --> sparsity rate for each layer
	%             .dropout (optional)  --> dropout rate for each layer
	%--------------------------------------------------------------------------
		if ~isstruct(arch),arch.size = arch; end

		nLayers = numel(arch.size);

		% CHECK # EPOCHS
		if ~isfield(arch,'nEpoch')
			arch.lRate = repmat(100,1,nLayers-1);
		elseif numel(arch.nEpoch) == 1
			arch.nEpoch = repmat(arch.nEpoch,1,nLayers-1);
		end

		% CHECK LEARNING RATES
		if ~isfield(arch,'lRate')
			arch.lRate = repmat(.01,1,nLayers-1);
		elseif numel(arch.lRate) == 1
			arch.lRate = repmat(arch.lRate,1,nLayers-1);
		end

		% CHECK SPARSITY TARGET RATES
		if ~isfield(arch,'sparsity')
			arch.sparsity = repmat(0,1,nLayers-1);
		elseif numel(arch.sparsity) == 1
			arch.sparsity = repmat(arch.sparsity,1,nLayers-1);
		end

		% CHECK DROPOUT
		if ~isfield(arch,'dropout')
			arch.dropout = repmat(0,1,nLayers-1);
		elseif numel(arch.dropout) == 1
			arch.dropout = repmat(arch.dropout,1,nLayers-1);
		end
	end

	function printProgress(self,type,aux)
	% VERBOSE
		switch type
			case 'layerTrain'
				fprintf('\n\nTraining RBM Layer: %i / %i\n',aux(1),self.nLayers-1);
			case 'fineTune'
				fprintf('\n\nFine-tuning using backprop:\n')
			case 'save'
				fprintf('\nSaving...\n\n');
		end
	end
end

end


function TessMat = in_tess_vtk(TessFile)
% IN_TESS_VTK: Read Visualization Toolkit .vtk mesh files
%
% USAGE:  TessMat = in_tess_vtk(TessFile);
%
% INPUT:
%     - TessFile : full path to a tesselation file
% OUTPUT:
%     - TessMat:  Brainstorm tesselation structure
% FORMAT:
%     ASCII file with the following structure:
%     - Header line 1: "# vtk DataFile Version ???"
%     - Header line 2: "surface file"
%     - Header line 3: "ASCII"
%     - Header line 4: "DATASET POLYDATA"
%     - Header line 5: "POINTS <nVertices>  float"
%     - Vertices     : nVertices lines ("x y z"), values in miliimeters
%     - Header line 6: "POLYGONS <nFaces> <nValues>"
%     - Faces        : nFaces lines ("nvert vertex1 vertex2 vertex3")
%
% SEE ALSO: in_tess

% @=============================================================================
% 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, 2012

% Open tesselation file
fid = fopen(TessFile, 'r');
if fid < 0
    error(['Cannot open file ', TessFile])
end

% ===== READ HEADER =====
% Read 5 lines of header
h1 = fgetl(fid);
h2 = fgetl(fid);
h3 = fgetl(fid);
h4 = fgetl(fid);
h5 = fgetl(fid);
% Check file format
if isempty(strfind(h1, 'vtk'))
    error('Not a valid VTF ASCII mesh file.');
end
% Get number of vertices
nVertices = sscanf(h5, '%*s %d %*s', 1);

% ===== READ MESH =====
% Read vertices
Vertices = double(fscanf(fid, '%f', [3 nVertices])) / 1000;
% Go to next line
fgetl(fid);
% Read number of faces
h6 = fgetl(fid);
res = textscan(h6, '%s %d', 1);
if ~iscell(res{1}) || isempty(res{1}) || ~ischar(res{1}{1}) || ~isequal(res{1}{1}, 'POLYGONS')
    error(['Unsupported faces format. Only "POLYGONS" is supported.']);
end
nFaces = res{2};
% Read faces
Faces = double(fscanf(fid, '%f',[4 nFaces]) + 1);
Faces = Faces(2:4,:);
% Close file
fclose(fid);

%% ===== CONVERT IN BRAINSTORM FORMAT =====
TessMat.Vertices = Vertices';
TessMat.Faces    = Faces';


function varargout = subsref(f, index)
%SUBSREF   DISKFUN subsref.
%( )
%   F(TH, R, 'polar') returns the values of the DISKFUN F evaluated at the
%   value(s) (TH, R) in polar coordinates. See CHEBFUN/FEVAL for
%   further details.
%
%   F(:, R) returns a chebfun representing the function F along a radial
%   slice fixed by R, and F(TH, :) returns a chebfun representing F along
%   an angular slice.
%
%   F(:, :) returns F.
%
%   F(X, Y) or F(X,Y, 'cart') returns the values of the DISKFUN F evaluated
%   at the value(s) (X,Y) in Cartesian coordinates.
%   The colon operator for Cartesian coordinates is not supported,
%   except for F(:, :), which just returns F.
%
%   F(c) where c is a complex-valued chebfun evaluates F along the contour
%   parametrized by the real and imaginary parts of c, and returns a
%   chebfun representing the values of F along the contour.
%
%   F.PROP returns the property PROP of F as defined by GET(F, 'PROP').
%
% {}
%   F{S1, S2, S3, S4} restricts F to the domain [S1, S2, S3, S4]. See
%   SEPARABLEAPPROX/RESTRICT for further details. Note that
%   F{[S1,S2, S3, S4]} is not supported due to the behaviour of the MATLAB
%   subsref() command.
%
% See also DISKFUN/FEVAL, DISKFUN/GET and DISKFUN/RESTRICT.

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

idx = index(1).subs;

% Check for the cases that must be explicitly handled here, which are
% 1. f(x, y), x, y are numeric, cartesian flag.
% 2. f(t,r) t, r are numeric, polar flag.
% Pass the other cases off to separableApprox/subsref.

if ( strcmp(index(1).type, '()') )
    x = idx{1};
    if ( length(idx) == 3 ) && (strcmp(idx{3}, 'polar'))
        y = idx{2};
        out = feval(f, x, y, 'polar');
        varargout = { out };

    elseif ( length(idx) == 3 ) && (strcmp(idx{3}, 'cart'))
        y = idx{2};
        out = feval(f, x, y, 'cart');
        varargout = { out };

    else  % Pass to separableApprox.
        out = subsref@separableApprox(f, index);
        varargout = { out };
    %else
      % error('CHEBFUN:DISKFUN:subsref:inputs', ...
               % 'Can only evaluate diskfuns at (X,Y) or (TH,R)');
    end

elseif ( strcmp(index(1).type,'()') )
    if ( numel(idx)==4 )
        % This intentionally fails:
        varargout = { restrict(f,[idx{1}, idx{2}, idx{3}, idx{4}]) };

    else
        error('CHEBFUN:DISKFUN:SUBSREF:restrict',...
              'Restriction domain should be given by four corners');
    end

else
    [varargout{1:nargout}] = subsref@separableApprox(f, index);
end

end


function c = demean(c,varargin);

% DEMEAN removes the mean of each trace.
%
% C = DEMEAN(C) removes the DC offset from each trace. In most cases it is
% unnecessary to call this function directly. By default, all traces are
% demeaned and detrended when they are loaded into a correlation object.
% This is one of the assumptions of the correlation toolbox.

% Author: Michael West, Geophysical Institute, Univ. of Alaska Fairbanks
% $Date$
% $Revision$

c.W = demean(c.W);


function [y] = cellshift(x, shift, dim, maxshift, flag)

% CELLSHIFT(X, SHIFT, DIM)

if nargin<5 || isempty(flag)
  flag = 'overlap'; % can also be 'zero' or 'nan'
  % overlap: only return the data samples that fully overlap for all shifts
  % zero: return 0's for the samples at which no data is present
  % nan: return nans for the samples at which no data is present
end

if nargin<4 || isempty(maxshift)
  maxshift = max(abs(shift));
else
  if any(abs(shift(:)))>abs(maxshift)
    error('the value for maxshift should be >= shift');
  end
end

if nargin<3 || isempty(dim)
  dim = find(size(x{1})>1, 1, 'first');
end

siz = size(shift);
if siz(1)==1 && siz(2)==1
  % this is OK, continue below
elseif siz(1)==1 && siz(2)>1
  % call the function recursively, and concatenate, same set of shifts for
  % all channels
  x = x(:)';
  y = cell(numel(shift),numel(x));
  for k = 1:numel(shift)
    %y(k,:) = cellshift(x, shift(k), dim, max(abs(shift)));
    y(k,:) = cellshift(x, shift(k), dim, [abs(min(shift)) abs(max(shift))], flag);
  end
  for k = 1:size(y,2)
    y{1,k} = cat(1,y{:,k});
  end
  y = y(1,:);
  return;
elseif siz(1)>1 && siz(2)>=1
  % different shifts, call the function recursively, and concatenate.
  % note that the order of the rows in the output is different from when
  % the same shift applies to all channels
  edges =[abs(nanmin(shift(:))) abs(nanmax(shift(:)))];
  y     = cell(siz(1),numel(x));
  for k = 1:siz(1)
    tmpshift = shift(k,:);
    tmpshift(~isfinite(tmpshift)) = [];
    if isempty(tmpshift)
      tmpshift = 0;
    end
    y(k,:) = cellshift(cellrowselect(x, k), tmpshift, dim, edges, flag);
  end
  for k = 1:size(y,2)
    y{1,k} = cat(1,y{:,k});
  end
  y = y(1,:);
  return;
end

%-----------------------------------------------------
maxshift = abs(maxshift);
if numel(maxshift)==1, maxshift = maxshift([1 1]); end

nx = size(x);
if ~iscell(x) || length(nx)>2 || all(nx>1)
  error('incorrect input for cellshift');
end

n    = numel(x);
nsmp = cellfun('size', x, dim);

switch flag
  case 'overlap'
    beg1 = ones(1,n) + shift + maxshift(1);
    end1 = nsmp      + shift - maxshift(2);

    beg2 = ones(size(beg1));
    end2 = end1-beg1+1;

    nsmp = nsmp - sum(maxshift);

  case {'zero' 'nan'}
    beg1 = ones(1,n);
    end1 = nsmp;

    beg2 = ones(1,n) - shift + maxshift(2);
    end2 = nsmp      - shift + maxshift(2);

    nsmp = nsmp + sum(maxshift);
end

usenans = strcmp(flag, 'nan');

switch dim
case 1
  y   = cell(size(x));
  for k = 1:n
    tmp = zeros(nsmp(k), size(x{k},2));
    if usenans, tmp(:) = nan; end
    tmp(beg2(k):end2(k),:) = x{k}(beg1(k):end1(k),:);
    y{k} = tmp;
  end
case 2
  y   = cell(size(x));
  for k = 1:n
    tmp = zeros(size(x{k},1), nsmp(k));
    if usenans, tmp(:) = nan; end
    tmp(:, beg2(k):end2(k)) = x{k}(:,beg1(k):end1(k));
    y{k} = tmp;
  end
otherwise
  error('dimensionality of >2 is not supported');
end


function Igo = GetRemoveResult(f, e)

Igo = f.df1/f.df*double(e.eroded_co12)+f.df2/f.df*double(e.eroded_co22)+...
    f.df3/f.df*double(e.eroded_co32)+f.df4/f.df*double(e.eroded_co42);
Igo = mat2gray(Igo);


%--------------------------------------------------------------------------
%   [dataout] = read_bin(file_name,file_type,mode_bl)
%--------------------------------------------------------------------------
%   功能:
%   读取bin文件数据
%--------------------------------------------------------------------------
%   输入:
%           file_name                  文件名
%           file_type                  类型,如int8,single(float),double
%           mode_bl                    大小端     'n'系统默认
%                                                 'b' 大端(常用)
%                                                 'l' 小端(常用)
%                                                 's' 大端64bit
%                                                 'a' 小端64bit
%   output:
%           output                     输出读取数据结果
%--------------------------------------------------------------------------
%   例子:
%   read_bin('1.bin','int8','b')
% ans =
%      1
%      2
%      3
%      4
%      5
%--------------------------------------------------------------------------
function [output] = read_bin(file_name,file_type,mode_bl)
if nargin == 2
    mode_bl = 'n';
end
f = fopen(file_name,'r');
output = fread(f,file_type,mode_bl);
fclose(f);


classdef prtRegress < prtAction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% prtRegress is an abstract base class for all regression objects.

    properties
        plotOptions = prtRegress.initializePlotOptions(); % Plotting Options
    end

    properties (SetAccess = protected)
        isSupervised = true; % True
        isCrossValidateValid = true; % True
	end

    methods (Hidden = true)
        function featureNameModificationFunction = getFeatureNameModificationFunction(obj)
			featureNameModificationFunction = prtUtilFeatureNameModificationFunctionHandleCreator('%s Output_{#index#}', obj.nameAbbreviation);
        end
	end

    methods
        function obj = prtRegress()
            % As an action subclass we must set the properties to reflect
            % our dataset requirements
            obj.classTrain = 'prtDataSetRegress';
            obj.classRun = 'prtDataSetStandard';
            obj.classRunRetained = true;
        end

        function varargout = plot(Obj)
            % PLOT  Plot the prtRegress object
            %
            % OBJ.plot() plots a trained prtRegress object. The plot
            % displays the original data points, the regressed data points,
            % and a line or curve interpolating between the regressed data
            % points.

            assert(Obj.isTrained,'Regressor must be trained before it can be plotted.');

            [OutputDataSet, linGrid] = runRegressorOnGrid(Obj);

            colors = Obj.plotOptions.colorsFunction(Obj.dataSetSummary.nTargetDimensions);
            lineWidth = Obj.plotOptions.lineWidth;

            switch Obj.dataSetSummary.nFeatures
                case 1
                    HandleStructure.regressorPlotHandle = plot(linGrid,OutputDataSet.getObservations,'color',colors(1,:),'lineWidth',lineWidth);
                case 2
                    sz = ones(1,Obj.dataSetSummary.nFeatures)*Obj.plotOptions.nSamplesPerDim(Obj.dataSetSummary.nFeatures);
                    HandleStructure.regressorPlotHandle = surf(...
                        reshape(linGrid(:,1),sz),...
                        reshape(linGrid(:,2),sz),...
                        reshape(OutputDataSet.getObservations,sz));
                    HandleStructure.regressorPlotHandle.EdgeColor = colors(1,:);
                    HandleStructure.regressorPlotHandle.FaceColor = 'none';
                    HandleStructure.regressorPlotHandle.LineWidth = lineWidth;
                otherwise
                    error('nFeatures in the training dataset must be 1 or 2');
            end

            holdState = get(gca,'nextPlot');
            if ~isempty(Obj.dataSet)
                hold on
                HandleStructure.dataSetPlotHandle = plot(Obj.dataSet);
            end
            set(gca,'nextPlot',holdState);

            axis tight;
            title(Obj.name)

            varargout = {};
            if nargout > 0
                varargout = {HandleStructure};
            end
        end

        function [OutputDataSet, linGrid, gridSize] = runRegressorOnGrid(Obj, upperBounds, lowerBounds)

            if nargin < 3 || isempty(lowerBounds)
                lowerBounds = Obj.dataSetSummary.lowerBounds;
            end

            if nargin < 2 || isempty(upperBounds)
                upperBounds = Obj.dataSetSummary.upperBounds;
            end

            [linGrid, gridSize] = prtPlotUtilGenerateGrid(upperBounds, lowerBounds, Obj.plotOptions.nSamplesPerDim);

            OutputDataSet = run(Obj,prtDataSetRegress(linGrid));
        end
    end
    methods (Static, Hidden = true)
        function plotOptions = initializePlotOptions()
            if ~isdeployed
                plotOptions = prtOptionsGet('prtOptionsRegressPlot');
            else
                plotOptions = prtOptions.prtOptionsRegressPlot;
            end
        end
    end
end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%% Show results for system identification [training, validation]

clear ph
figure,box on, hold on,
ccolors = get(gca,'colororder');
plot([tA(1),tA(1)],[min(xB(:)) max([xA(:);xB(:)])],':','Color',[0.4,0.4,0.4],'LineWidth',1.5)
ylim([min(xB(:)) max([xA(:);xB(:)])])
plot(t,x(:,1),'Color',ccolors(1,:),'LineWidth',1);
plot(t,x(:,2),'Color',ccolors(2,:),'LineWidth',1);
ph(1) = plot([t;tA],[x(:,1);xA(:,1)],'Color',ccolors(1,:),'LineWidth',1);
ph(2) = plot([t;tA],[x(:,2);xA(:,2)],'Color',ccolors(2,:),'LineWidth',1);
ph(3) = plot([t;tA],[x(:,3);xA(:,3)],'Color',ccolors(3,:),'LineWidth',1);
ph(4) = plot(tB,xB(:,1),'-.','Color',ccolors(1,:)-[0 0.2 0.2],'LineWidth',2);
ph(5) = plot(tB,xB(:,2),'-.','Color',ccolors(2,:)-[0.1 0.2 0.09],'LineWidth',2);
ph(6) = plot(tB,xB(:,3),'-.','Color',ccolors(3,:)-[0.1 0.2 0.09],'LineWidth',2);
grid off
xlim([0 tB(end)])
xlabel('Time')
ylabel('xi')
t1 = text(tA(1)-5,40,'Training', 'FontSize',12);
t2 = text(1+tA(1),40,'Validation', 'FontSize',12);
lh = legend(ph([1,4]),'True',ModelName);
lh.Position = [lh.Position(1)-0.5,lh.Position(2)-0.15,lh.Position(3:4)];
set(gca,'LineWidth',1, 'FontSize',14)
set(gcf,'Position',[100 100 300 200])
set(gcf,'PaperPositionMode','auto')
print('-depsc2', '-loose','-cmyk', [figpath,'EX_',SystemModel,'_SI_',ModelName,'_',InputSignalType,'_Validation_OneFig.eps']);

delete(lh); delete(t1), delete(t2);
print('-depsc2', '-loose','-cmyk', [figpath,'EX_',SystemModel,'_SI_',ModelName,'_',InputSignalType,'_Validation_OneFig_noleg.eps']);

%% Actuation signal
clear ph
figure,box on, hold on,
ccolors = get(gca,'colororder');
plot([tA(1),tA(1)],[-15 260],':','Color',[0.4,0.4,0.4],'LineWidth',1.5)
plot(t,u,'-k','LineWidth',1);
plot(tv,uv,'-k','LineWidth',1);
grid off
ylim([min([u uv])+0.05*min([u uv]) max([u uv])+0.05*max([u uv])])
xlim([0 tB(end)])
xlabel('Time')
ylabel('Input')
set(gca,'LineWidth',1, 'FontSize',14)
set(gcf,'Position',[100 100 300 200])
set(gcf,'PaperPositionMode','auto')
print('-depsc2', '-loose','-cmyk', [figpath,'EX_',SystemModel,'_SI_',ModelName,'_',InputSignalType,'_Actuation_OneFig.eps']);


function pass = test_isempty( )

% Example 1:
v = ballfunv();
pass(1) = isempty(v);

% Example 2:
f = ballfun(1);
g = ballfun();
v = ballfunv(f,g,f);
pass(2) = ~isempty(v);

% Example 3:
f = ballfun(1);
v = ballfunv(f,f,f);
pass(3) = ~isempty(v);

if (nargout > 0)
    pass = all(pass(:));
end
end


function test_issue1214

% WALLTIME 00:10:00
% MEM 1gb
% DEPENDENCY ft_singleplotER ft_multiplotER ft_plot_vector

%% make some data

timelock1 = ft_timelockanalysis([], ft_freqsimulation([]));

cfg = [];
cfg.parameter = 'avg';
cfg.operation = '-1*x1';
timelock2 = ft_math(cfg, timelock1);

%% this works

cfg = [];
cfg.channel = 'mix';
figure; ft_singleplotER(cfg, timelock1, timelock2);

%% this works

cfg = [];
cfg.channel = 'mix';
cfg.graphcolor = 'my';
figure; ft_singleplotER(cfg, timelock1, timelock2);

%% this failed

cfg = [];
cfg.channel = 'mix';
cfg.graphcolor = [
  1 0 0
  0 1 0
  ];
figure; ft_singleplotER(cfg, timelock1, timelock2);

%% this failed

cfg = [];
cfg.layout = 'vertical';
cfg.graphcolor = [
  1 0 0
  0 1 0
  ];
figure; ft_multiplotER(cfg, timelock1, timelock2);


function [p,t]=fixmesh(p,t)
%FIXMESH  Remove duplicated/unused nodes and fix element orientation.
%   [P,T]=FIXMESH(P,T)

%   Copyright (C) 2004-2006 Per-Olof Persson. See COPYRIGHT.TXT for details.

snap=max(max(p,[],1)-min(p,[],1),[],2)*1024*eps;
[foo,ix,jx]=unique(round(p/snap)*snap,'rows');
p=p(ix,:);
t=jx(t);

[pix,ix,jx]=unique(t);
t=reshape(jx,size(t));
p=p(pix,:);

flip=simpvol(p,t)<0;
t(flip,[1,2])=t(flip,[2,1]);


function map = mapcolor2(A, breaks)
%MAPCOLOR2 Create a blue-gray-red colormap.
%   MAPCOLOR2(A, BREAKS), when A is a matrix and BREAKS a vector, returns a
%   colormap that can be used as a parameter in COLORMAP function. BREAKS
%   has to contain six break values for a 7-class colormap. The break
%   values define the points at which the scheme changes color. The first
%   three colors are blue, the middle one gray and the last three ones
%   are red.
%
%   Example: A = ones(100, 100);
%            for i=1:10:100
%               A(i:end, i:end) = A(i,i) + 5;
%            end
%            A = A + rand(100, 100);
%            map = mapcolor2(A, [10 15 20 25 30 35]);
%            pcolor(A), shading flat
%            colormap(map), colorbar
%

% Copyright (c) 2006 Markus Siivola

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

% there must be 6 break values for seven colors
if length(breaks) ~= 6
   error('Break point vector must have 6 elements.');
end

% sort break values in ascending order if necessary
if ~issorted(breaks)
    breaks = sort(breaks);
end

% check the value range consumed by the data
rng = [min(A(:)) max(A(:))];

if any(breaks > rng(2)) | any(breaks < rng(1))
    error('Break point out of value range');
end

if ispc
    n = 256;
else
    n = 1000;
end

% a color scheme from blue through gray to red
colors = flipud([ 140 0   0;
                  194 80  68;
                  204 143 151;
                  191 191 191;
                  128 142 207;
                  70  84  158;
                  7   39  115 ] / 255);

% create a colormap with 256 colors
map = []; n = 256; ibeg = 1;
for i = 1:6
    iend = round(n * (breaks(i) - rng(1)) / (rng(2) - rng(1)));
    map  = [map; repmat(colors(i,:), [iend-ibeg+1 1])];
    ibeg = iend+1;
end
map = [map; repmat(colors(7,:), [n - size(map, 1) 1])];


function U = rhs_computation(M,sphere_translational_velocity)
%+========================================================================+
%|                                                                        |
%|           This function uses the GYPSILAB toolbox for Matlab           |
%|                                                                        |
%| COPYRIGHT :                                                            |
%| PROPERTY  :                                                            |
%| LICENCE   :                                                            |
%| CONTACT   :                                                            |
%| WEBSITE   : www.cmap.polytechnique.fr/~aussal/gypsilab                 |
%|                                                                        |
%| Please acknowledge the gypsilab toolbox in programs or publications in |
%| which you use it.                                                      |
%|________________________________________________________________________|
%|   '&`   |                                                              |
%|    #    |   FILE       : rhs_computation.m                             |
%|    #    |   VERSION    : 0.10                                          |
%|   _#_   |   AUTHOR(S)  : Luca Berti                                    |
%|  ( # )  |   CREATION   : 25.12.2018                                    |
%|  / 0 \  |   LAST MODIF :                                               |
%| ( === ) |   SYNOPSIS   :                                               |
%|  `---'  |                                                              |
%+========================================================================+
% COMPUTE THE RIGHT-HAND SIDE OF THE STOKES SINGLE LAYER PROBLEM
% ONLY P1 CASE TESTED FOR THE MOMENT

N_unknown = size(M,1)/3;

U = M*[sphere_translational_velocity(1)*ones(N_unknown,1);
     sphere_translational_velocity(2)*ones(N_unknown,1);
     sphere_translational_velocity(3)*ones(N_unknown,1)];

end