function [sp_fit_group,sp_profiles,sp_fit] = spectdecompose(sp_fit,options,chan)
%
% From a multitaper or MAR estimation of the states spectra (per subject),
% it factorises the spectral information (which is given by frequency bin)
% into a set of spectral components (which are much fewer than the
% frequency bins), in order to facilitate interpretation and visualisation.
% The decomposition can be done either using PCA or non-negative matrix
% factorisation or NNMF (the default). Note that if NNMF is used, the
% solution might somewhat vary every time the function is called.
%
% INPUTS:
%
% sp_fit                The output of hmmspectramar or hmmspectramt. It
%                       should be a cell, where each element corresponds
%                       to one subject
% options               Struct indicating the decomposing options
%        .Ncomp         Number of components (default 4)
%        .Method        'NNMF' or 'PCA' (default 'NNMF')
%        .Base          What to base the factorisation on: PSD if 'psd' or on
%                       coherence if 'coh' (default: 'coh')
%        .sp_profiles   Spectral profiles; if supplied, these will be used
%                       instead of computing them (default: empty)
%        .plot          If the spectral profiles are to be plotted (default: 0)
% chan                  If supplied, a vector of integers defining which
%                       channels will be used in the decomposion;
%                       if not specified, all will beused
%
% OUTPUT:
%
% sp_fit_group          A single struct containing the mean across subjects
%                       of sp_fit. If there is only one subject, then
%                       sp_fit_group equals sp_fit
% sp_profiles           The (frequency bins by spectral components) mixing
%                       matrix used to project from (no. of frequency bins
%                       by regions) to (no. of components by regions)
% sp_fit                A cell with the spectral components, with the same fields
%                       and dimensions that the input 'sp_fit', but with Ncomp
%                       components instead of No. frequency bins. If there
%                       is only one subject, then sp_fit is a single struct
%
% Authors: Mark Woolrich, OHBA, University of Oxford (2017)
%          Diego Vidaurre, OHBA, University of Oxford (2017)
%          Andrew Quinn, OHBA, University of Oxford (2018)

if ~iscell(sp_fit)
    warning('Only one subject was provided; recommended to run at the group level')
    aux = sp_fit;
    sp_fit = {};
    sp_fit{1} = aux;
    clear aux
end

if nargin < 2, options = struct(); end
if ~isfield(options,'Niterations'), options.Niterations = 10; end
if ~isfield(options,'Ncomp'), options.Ncomp = 4; end
if ~isfield(options,'Method'), options.Method = 'NNMF'; end
if ~isfield(options,'Base'), options.Base = 'coh'; end
if ~isfield(options,'plot'), options.plot = 0; end

ndim = size(sp_fit{1}.state(1).psd,2); % no. channels
if nargin < 3, chan = 1:ndim;
else, ndim = length(chan);
end
ndim2 = ndim*(ndim-1)/2;
Nf = size(sp_fit{1}.state(1).psd,1); % no. frequencies
N = length(sp_fit); % no. subjects
K = length(sp_fit{1}.state); % no. states
ind_offdiag = triu(true(ndim),1)==1;

% check that all estimations have the same number of freq bins
for n = 1:N
    if isempty(sp_fit{n})
        error('One or more elements of sp_fit are empty - remove them first')
    end
    if size(sp_fit{n}.state(1).psd,1) ~= Nf
        error(['It is necessary for the spectral estimation of all subjects ' ...
            'to have the same number of frequency bins. ' ...
            'In the case of the multitaper, this is can be done by setting ' ...
            'the options tapers and win to a fixed value.'])
    end
end

% put coh and psd in temporary arrays
psd_comps = zeros(N,K,Nf,ndim);
coh_comps = zeros(N,K,Nf,ndim,ndim);
for n = 1:N
    for k = 1:K
        psd = sp_fit{n}.state(k).psd(:,chan,chan);
        coh = sp_fit{n}.state(k).coh(:,chan,chan);
        for j = chan
            psd_comps(n,k,:,j) = psd(:,j,j);
            for l = chan
                coh_comps(n,k,:,j,l) = coh(:,j,l);
            end
        end
    end
end

% Build the matrix that is to be factorised
Xpsd = zeros(Nf,ndim*K);
keep_psd = true(1,ndim*K);
for k = 1:K
    ind = (1:ndim) + (k-1)*ndim;
    notnan = ~isnan(psd_comps(:,k,1,1)) & ~isinf(psd_comps(:,k,1,1));
    if any(notnan)
        Xpsd(:,ind)= squeeze(mean(abs(psd_comps(notnan,k,:,:)),1)); % mean across subjects
    else
        keep_psd(ind) = false;
    end
end
Xcoh = zeros(Nf,K*ndim2);
keep_coh = true(1,ndim2*K);
for k = 1:K
    ind = (1:ndim2) + (k-1)*ndim2;
    notnan = ~isnan(coh_comps(:,k,1,1,2)) & ~isinf(coh_comps(:,k,1,1,2));
    if any(notnan)
        ck = squeeze(mean(abs(coh_comps(notnan,k,:,:,:)),1));
        Xcoh(:,ind) = ck(:,ind_offdiag);
    else
        Xcoh(:,ind) = false;
    end

end
if strcmpi(options.Base,'psd')
    X = Xpsd(:,keep_psd);
else
    X = Xcoh(:,keep_coh);
end

% Specify fit function, a unimodal gaussian
gauss_func = @(x,f) f.a1.*exp(-((x-f.b1)/f.c1).^2);
% Default fit options
options_fit = fitoptions('gauss1');
% constrain lower and upper bounds
options_fit.Lower = [0,1,0];
options_fit.Upper = [Inf,size(X,1),size(X,1)];

if ~isfield(options,'sp_profiles') || isempty(options.sp_profiles)
    % Doing the decomposition
    if strcmpi(options.Method,'NNMF')
        bestval = Inf; fitval = zeros(options.Niterations,1);
        for ii = 1:options.Niterations
            try
                [A,~] = nnmf(X,options.Ncomp,'replicates',500,'algorithm','als');
            catch
                error('nnmf not found - perhaps the Matlab version is too old')
            end
            for jj = 1:size(A,2)
                f = fit( linspace(1,size(A,1),size(A,1))',A(:,jj), 'gauss1',options_fit);
                residuals = A(:,jj) - gauss_func(1:size(A,1),f)';
                fitval(ii) = fitval(ii) + sum( residuals.^2 ) / size(A,2);
            end
            if fitval(ii) < bestval
                bestval = fitval(ii);
                bestfit = A;
            end
        end
        %sp_profiles = pinv(X') * b'; % you lose non-negativity by doing this
        sp_profiles = bestfit;
        [~,ind] = max(sp_profiles,[],1);
        [~,neworder_auto] = sort(ind);
        sp_profiles = sp_profiles(:,neworder_auto);
    else
        try
            m = mean(X);
            X = X - repmat(m,Nf,1);
            [~,A] = pca(X,'NumComponents',options.Ncomp);
        catch
            error('Error running pca - maybe not matlab''s own?')
        end
        sp_profiles = A;
    end
else
    sp_profiles = options.sp_profiles;
end

% plot if required
if options.plot
    figure;
    if options.Ncomp > 4
        j1 = ceil(options.Ncomp/2); j2 = 2;
    else
        j1 = options.Ncomp; j2 = 1;
    end
    for j = 1:options.Ncomp
        subplot(j1,j2,j)
        plot(sp_profiles(:,j),'LineWidth',2.5)
    end
end

% group level
sp_fit_group = struct();
sp_fit_group.state = struct();

% NNMF / PCA
psd = zeros(ndim*K,options.Ncomp);
coh = zeros(ndim2*K,options.Ncomp);
if strcmpi(options.Method,'NNMF')
   psd(keep_psd,:) = (Xpsd(:,keep_psd)' * sp_profiles); % ndim by components
   coh(keep_coh,:) = (Xcoh(:,keep_coh)' * sp_profiles);
%     opt = statset('maxiter',0);
%     [~,b] = nnmf(Xpsd,options.Ncomp,'algorithm','als',...
%         'w0',sp_profiles,'Options',opt);
%     psd = b'; % regions by components
%     [~,b] = nnmf(Xcoh,options.Ncomp,'algorithm','als',...
%         'w0',sp_profiles,'Options',opt);
%     coh = b'; % pairs of regions by components
else
    Xpsd(:,keep_psd) = Xpsd(:,keep_psd) - repmat(mean(Xpsd(:,keep_psd)),Nf,1);
    Xcoh(:,keep_coh) = Xcoh(:,keep_coh) - repmat(mean(Xcoh(:,keep_coh)),Nf,1);
    psd(keep_psd,:) = (Xpsd(:,keep_psd)' * sp_profiles); % ndim by components
    coh(keep_coh,:) = (Xcoh(:,keep_coh)' * sp_profiles);
end
if any(isnan(psd(:))) || any(isnan(coh(:)))
   warning('There are NaNs in the estimations for those states that were not used')
end
for k = 1:K
    sp_fit_group.state(k).psd = zeros(options.Ncomp,ndim,ndim);
    sp_fit_group.state(k).coh = ones(options.Ncomp,ndim,ndim);
    ind = (1:ndim) + (k-1)*ndim;
    for i = 1:options.Ncomp
        sp_fit_group.state(k).psd(i,:,:) = diag(psd(ind,i));
    end
    ind = (1:ndim2) + (k-1)*ndim2;
    for i = 1:options.Ncomp
        graphmat = zeros(ndim);
        graphmat(ind_offdiag) = coh(ind,i);
        graphmat=(graphmat+graphmat') + eye(ndim);
        sp_fit_group.state(k).coh(i,:,:) = graphmat;
    end
end

% Subject level
if N > 1 && nargout == 3
    for n = 1:N
        sp_fit{n} = struct();
        sp_fit{n}.state = struct();
        % prepare matrix
        Xpsd = zeros(Nf,ndim*K);
        keep_psd = true(1,ndim*K);
        for k = 1:K
            ind = (1:ndim) + (k-1)*ndim;
            Xpsd(:,ind)= squeeze(abs(psd_comps(n,k,:,:)));
            if any(isnan(var(Xpsd(:,ind)))) || any(isinf(var(Xpsd(:,ind))))
                keep_psd(ind) = false;
                warning(['Session ' num2str(n) ' did not use state ' num2str(k) '; PSD set to NaN'])
            end
        end
        Xcoh = zeros(Nf,K*ndim2);
        keep_coh = true(1,K*ndim2);
        for k = 1:K
            ind = (1:ndim2) + (k-1)*ndim2;
            ck = squeeze(abs(coh_comps(n,k,:,:,:)));
            Xcoh(:,ind) = ck(:,ind_offdiag);
            if any(isnan(var(Xcoh(:,ind)))) || any(isinf(var(Xcoh(:,ind))))
                keep_coh(ind) = false;
                warning(['Session ' num2str(n) ' did not use state ' num2str(k) '; Coh set to NaN'])
            end
        end
        % NNMF / PCA
        psd = zeros(ndim*K,options.Ncomp);
        coh = zeros(ndim2*K,options.Ncomp);
        if strcmpi(options.Method,'NNMF')
            opt = statset('maxiter',1);
            [~,b] = nnmf(Xpsd(:,keep_psd),options.Ncomp,'algorithm','als',...
                'w0',sp_profiles,'Options',opt);
            psd(keep_psd,:) = b'; % regions by components
            [~,b] = nnmf(Xcoh(:,keep_coh),options.Ncomp,'algorithm','als',...
                'w0',sp_profiles,'Options',opt);
            coh(keep_coh,:) = b';
        else
            Xpsd(:,keep_psd) = Xpsd(:,keep_psd) - repmat(mean(Xpsd(:,keep_psd)),Nf,1);
            Xcoh(:,keep_coh) = Xcoh(:,keep_coh) - repmat(mean(Xcoh(:,keep_coh)),Nf,1);
            psd(keep_psd,:) = (Xpsd(:,keep_psd)' * sp_profiles);
            coh(keep_coh,:) = (Xcoh(:,keep_coh)' * sp_profiles);
        end
        % Reshape stuff
        for k = 1:K
            sp_fit{n}.state(k).psd = zeros(options.Ncomp,ndim,ndim);
            sp_fit{n}.state(k).coh = ones(options.Ncomp,ndim,ndim);
            ind = (1:ndim) + (k-1)*ndim;
            for i = 1:options.Ncomp
                sp_fit{n}.state(k).psd(i,:,:) = diag(psd(ind,i));
            end
            ind = (1:ndim2) + (k-1)*ndim2;
            for i = 1:options.Ncomp
                graphmat = zeros(ndim);
                graphmat(ind_offdiag) = coh(ind,i);
                graphmat=(graphmat+graphmat') + eye(ndim);
                sp_fit{n}.state(k).coh(i,:,:) = graphmat;
            end
        end
    end
else
    sp_fit = sp_fit_group;
end

end


% Laser sensor's parameters
function lidar = SetLidarParameters()

lidar.angle_min = -2.351831;
lidar.angle_max =  2.351831;
lidar.angle_increment = 0.004363;
lidar.npoints   = 1079;
lidar.range_min = 0.023;
lidar.range_max = 60;
lidar.scan_time = 0.025;
lidar.time_increment  = 1.736112e-05;
lidar.angles = (lidar.angle_min : lidar.angle_increment : lidar.angle_max)';


function [prob] = predictRF(X,RF)

nInst = size(X,1);
trees = RF.Trees; numTrees = numel(trees);
predictions = zeros(nInst,1);
for t = 1:numTrees
    temp = trees{t}.predict(X); temp = str2double(temp);
    predictions = predictions + temp;
end
prob = predictions/numTrees;
end


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

%%
clear; close all; clc;

%% Syntax
% |[hp]=gpatch(F,V,C,CE,A,L)|;

%% Description
% This function is a short-hand version of the |patch| command. The inputs
% for |gpatch| are the faces (F), the vertices (V), the color description
% (C), the edge color description CE, the transparancy (A), and the edge
% width (L).
% The color data descriptions C (or equivalently CE for edges) can be:
% 1) A string such as 'g' for green
% 2) A triplet of RGD values e.g. [1 0 0] is blue
% 3) A nx1 or a mx1 array of colormapped colors (where n=size(F,1) or m=size(V,1))
% 4) (simiarl to 3) A nx3 or a mx3 RGB color value array for the faces or vertices respectively.

%% Examples

%%
% Create example mesh data

[F,V,~]=geoSphere(2,1); %Faces and vertices
CV=V(:,1); %Color information for vertices
CF=vertexToFaceMeasure(F,CV); %Color information for faces
CF_rgb=abs(vertexToFaceMeasure(F,V)); %Color information for faces

%% Example: Introduction to using |gpatch| for mesh visualization
% The below visualization show the syntax require using |patch| and
% |gpatch|. Essentially |gpatch| is just a short-hand version of |patch|
% allowing for quick and easy visualization using patch graphics.

%%
% Using patch graphics in MATLAB see documentation on |patch| for more information

cFigure;
subplot(2,3,1);
title('Single face and edge color');
patch('Faces',F,'Vertices',V,'FaceColor','r','EdgeColor','g','FaceAlpha',0.5);
axisGeom;

subplot(2,3,2);
title('Colormapped face colors');
patch('Faces',F,'Vertices',V,'FaceColor','flat','CData',CF,'EdgeColor','k','FaceAlpha',1);
colormap gjet; colorbar;
axisGeom;

subplot(2,3,3);
title('RGB driven face colors');
patch('Faces',F,'Vertices',V,'FaceColor','flat','FaceVertexCData',CF_rgb,'EdgeColor','k','FaceAlpha',1,'LineWidth',3);
axisGeom;

subplot(2,3,4);
title('Colormapped edge colors');
patch('Faces',F,'Vertices',V,'FaceColor',grayColor(0.5),'EdgeColor','flat','CData',CV,'LineWidth',3);
colormap gjet; colorbar;
axisGeom;

subplot(2,3,5);
title('alpha mapping');
patch('Faces',F,'Vertices',V,'FaceColor','g','FaceVertexAlphaData',CV,'EdgeColor','none','FaceAlpha','flat');
axisGeom;

drawnow;

% Using |gpatch| shorthand alternative to |patch|

cFigure;
subplot(2,3,1);
title('Single face and edge color');
gpatch(F,V,'r','g',0.5);
axisGeom;

subplot(2,3,2);
title('Colormapped face colors');
gpatch(F,V,CF);
colormap gjet; colorbar;
axisGeom;

subplot(2,3,3);
title('RGB driven face colors');
gpatch(F,V,CF_rgb,'k',1,3);
axisGeom;

subplot(2,3,4);
title('Colormapped edge colors');
gpatch(F,V,'kw',CV,1,3); %kw -> grayColor(0.5)
colormap gjet; colorbar;
axisGeom;

subplot(2,3,5);
title('alpha mapping');
gpatch(F,V,'g','none',CV);
axisGeom;

drawnow;

%% Using |gpatch| with cell arrays containing patch data

%%
% Use of |gpatch| when both the faces and vertices are stored in a cell
% array

% Create example cell arrays
[F1,V1]=graphicsModels(1); V1=V1-mean(V1,1); V1=V1./max(V1(:)); V1=V1-1;
[F2,V2]=graphicsModels(2); V2=V2-mean(V2,1); V2=V2./max(V2(:));
[F3,V3]=graphicsModels(3); V3=V3-mean(V3,1); V3=V3./max(V3(:)); V3=V3+1;
F={F1,F2,F3}; %Cell array containing faces
V={V1,V2,V3}; %Cell array containing vertices
C={ones(size(F1,1),1),2*ones(size(F2,1),1),3*ones(size(F3,1),1)}; %Cell array containing color labels

cFigure;
title('Cell array of patch data');
hp=gpatch(F,V,C,'none',1);
axisGeom; camlight headlight;
colormap spectral; icolorbar;
drawnow;

%%
% Use of |gpatch| when only the faces are stored in a cell array

% Create example cell array

[F1,V1]=graphicsModels(1); V1=V1-mean(V1,1); V1=V1./max(V1(:)); V1=V1-1;
[F2,V2]=graphicsModels(2); V2=V2-mean(V2,1); V2=V2./max(V2(:));
[F3,V3]=graphicsModels(3); V3=V3-mean(V3,1); V3=V3./max(V3(:)); V3=V3+1;
F={F1,F2+size(V1,1),F3+size(V1,1)+size(V2,1)}; %Cell array containing faces
V=[V1;V2;V3]; %Normal array containing all vertices
C={ones(size(F1,1),1),2*ones(size(F2,1),1),3*ones(size(F3,1),1)}; %Cell array containing color labels

cFigure;
title('Cell array of patch data');
hp=gpatch(F,V,C,'none',1);
axisGeom; camlight headlight;
colormap spectral; icolorbar;
drawnow;

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function value = s_s_subanagram ( s1, s2 )

%*****************************************************************************80
%
%% S_S_SUBANAGRAM determines if S2 is a "subanagram" of S1.
%
%  Discussion:
%
%    S2 is an anagram of S1 if S2 can be formed by permuting the letters
%    of S1
%
%    S2 is an subanagram of S1 if S2 can be formed by selecting SOME of
%    the letters of S1 and permuting them.
%
%    Blanks (trailing or otherwise), punctuation, and capitalization
%    are all significant, so be sure to input exactly the information
%    you want to check.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 June 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S1, the master string.
%
%    Input, string S2, the second string.
%
%    Output, logical VALUE is TRUE if S2 is a subanagram of S1.
%
  value = 0;
%
%  Sort both.
%
  s1 = s_sort_a ( s1 );
  s2 = s_sort_a ( s2 );

  s1_length = length ( s1 );
  s2_length = length ( s2 );

  i1 = 0;

  for i2 = 1 : s2_length

    while ( 1 )

      i1 = i1 + 1;
%
%  Ran out of S1 before finishing.  No match is possible.
%
      if ( s1_length < i1 )
        return;
      end
%
%  The current character in S1 is already greater than the character in S2.
%  No match is possible.
%
      if ( s2(i2) < s1(i1) )
        return
      end
%
%  Found an exact match for current character.  Keep going.
%
      if ( s1(i1) == s2(i2) )
        break
      end
%
%  Didn't find a match, but one might be possible if we increase I1.
%
    end

  end
%
%  We matched every character of S2 with something in S1.
%
  value = 1;

  return
end


function test_ft_math

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

%% create some test data
raw1 = [];
raw1.time = {[1:10], [1:10], [1:10]};
raw1.trial = {ones(2,10), ones(2,10), ones(2,10)};
raw1.label = {'chan01';'chan02'};
raw1.trialinfo = rand(3,4);

timelock1.label  = {'chan1'; 'chan2'};
timelock1.time   = 1:5;
timelock1.dimord = 'chan_time';
timelock1.avg    = ones(2,5);
timelock1.cfg    = struct([]);

timelock2 = timelock1;
timelock2.avg  = ones(2,5)*2;

timelock3 = timelock1;
timelock3.var = ones(2,5);

source1 = [];
source1.pos = randn(10,3);
source1.pow = randn(10,1);
source1.powdimord = 'pos';
source1.mom = cell(10,1);
for i=1:10
  source1.mom{i} = ones(3, 20)*1;
end
source1.momdimord = '{pos}_ori_time';
source1.time = 1:20;

source2 = source1;
for i=1:10
  source2.mom{i} = ones(3, 20)*2;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% do operation with one raw input

cfg=[];
cfg.showcallinfo = 'no';
cfg.parameter = 'trial';

cfg.operation = 'log10';
tmp = ft_math(cfg, raw1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');

cfg.scalar = pi;

cfg.operation = 'add';
tmp = ft_math(cfg, raw1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');

cfg.operation = 'subtract';
tmp = ft_math(cfg, raw1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');

cfg.operation = 'multiply';
tmp = ft_math(cfg, raw1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');

cfg.operation = 'divide';
tmp = ft_math(cfg, raw1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% do operation with one timelock input

cfg = [];
cfg.showcallinfo = 'no';
cfg.parameter    = 'avg';

cfg.operation = 'log10';
tmp = ft_math(cfg, timelock1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

cfg.scalar = pi;

cfg.operation = 'add';
tmp = ft_math(cfg, timelock1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

cfg.operation = 'subtract';
tmp = ft_math(cfg, timelock1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

cfg.operation = 'multiply';
tmp = ft_math(cfg, timelock1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

cfg.operation = 'divide';
tmp = ft_math(cfg, timelock1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% do operation with one timelock input, multiple parameters

cfg = [];
cfg.showcallinfo = 'no';
cfg.parameter    = {'avg', 'var'};

cfg.operation = 'log10';
tmp = ft_math(cfg, timelock3);
assert(isfield(tmp, 'avg') && isfield(tmp, 'var'), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');
assert(isequal(tmp.var, log10(timelock3.var)));
assert(isequal(tmp.avg, log10(timelock3.avg)));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% do operation with one source input

cfg = [];
cfg.showcallinfo = 'no';
cfg.parameter    = 'mom'; % note that this is {pos}_ori_time

cfg.operation = 'log10';
tmp = ft_math(cfg, source1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

cfg.scalar = pi;

cfg.operation = 'add';
tmp = ft_math(cfg, source1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

cfg.operation = 'subtract';
tmp = ft_math(cfg, source1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

cfg.operation = 'multiply';
tmp = ft_math(cfg, source1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

cfg.operation = 'divide';
tmp = ft_math(cfg, source1);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% do operation with two timelock inputs

cfg = [];
cfg.showcallinfo = 'no';
cfg.parameter    = 'avg';

cfg.operation = 'add';
tmp = ft_math(cfg, timelock1, timelock2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

cfg.operation = 'subtract';
tmp = ft_math(cfg, timelock1, timelock2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

cfg.operation = 'multiply';
tmp = ft_math(cfg, timelock1, timelock2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

cfg.operation = 'divide';
tmp = ft_math(cfg, timelock1, timelock2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% do operation with two source inputs

cfg = [];
cfg.showcallinfo = 'no';
cfg.parameter    = 'mom';

cfg.operation = 'add';
tmp = ft_math(cfg, source1, source2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

cfg.operation = 'subtract';
tmp = ft_math(cfg, source1, source2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

cfg.operation = 'multiply';
tmp = ft_math(cfg, source1, source2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

cfg.operation = 'divide';
tmp = ft_math(cfg, source1, source2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% do operation with more than two timelock inputs

cfg = [];
cfg.showcallinfo = 'no';
cfg.parameter    = 'avg';

cfg.operation = 'add';
tmp = ft_math(cfg, timelock1, timelock2, timelock1, timelock2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

cfg.operation = 'multiply';
tmp = ft_math(cfg, timelock1, timelock2, timelock1, timelock2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, 'dimord'), 'the output dimord is missing');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% do operation with more than two source inputs

cfg = [];
cfg.showcallinfo = 'no';
cfg.parameter    = 'mom';

cfg.operation = 'add';
tmp = ft_math(cfg, source1, source2, source1, source2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

cfg.operation = 'multiply';
tmp = ft_math(cfg, source1, source2, source1, source2);
assert(isfield(tmp, cfg.parameter), 'the output parameter is missing');
assert(isfield(tmp, [cfg.parameter 'dimord']), 'the output dimord is missing');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% check the numerical output of the operation

cfg = [];
cfg.parameter = 'trial';

cfg.operation = 'log10';
tmp = ft_math(cfg, raw1);
assert(tmp.trial{1}(1)==0);

cfg.operation = 'multiply';
cfg.scalar = -1;
tmp = ft_math(cfg, raw1);
assert(tmp.trial{1}(1)==-1);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% idem for a timelock input

cfg = [];
cfg.parameter = 'avg';
cfg.operation = 'add';
tmp = ft_math(cfg, timelock1, timelock2);
assert(tmp.avg(1)==3);

cfg.operation = 'subtract';
tmp = ft_math(cfg, timelock1, timelock2);
assert(tmp.avg(1)==-1);

cfg.operation = 'divide';
tmp = ft_math(cfg, timelock1, timelock2);
assert(tmp.avg(1)==1/2);

cfg.operation = 'multiply';
tmp = ft_math(cfg, timelock1, timelock2);
assert(tmp.avg(1)==2);

cfg.operation = 'log10';
tmp = ft_math(cfg, timelock1);
assert(tmp.avg(1)==0);

cfg.operation = 'log(x1)';
tmp = ft_math(cfg, timelock1);
assert(tmp.avg(1)==0);

cfg.operation = '(x1-x2)/(x1+x2)';
tmp = ft_math(cfg, timelock1, timelock2);
assert(tmp.avg(1)==-1/3);

cfg.scalar = 2;
cfg.operation = '(x1+x2)^s';
tmp = ft_math(cfg, timelock1, timelock2);
assert(tmp.avg(1)==9);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% idem for a source structure with a cell-array

cfg = [];
cfg.parameter = 'mom';
cfg.operation = 'add';
tmp = ft_math(cfg, source1, source2);
assert(tmp.mom{1}(1)==3);

cfg.operation = 'subtract';
tmp = ft_math(cfg, source1, source2);
assert(tmp.mom{1}(1)==-1);

cfg.operation = 'divide';
tmp = ft_math(cfg, source1, source2);
assert(tmp.mom{1}(1)==1/2);

cfg.operation = 'multiply';
tmp = ft_math(cfg, source1, source2);
assert(tmp.mom{1}(1)==2);

cfg.operation = 'log10';
tmp = ft_math(cfg, source1);
assert(tmp.mom{1}(1)==0);

cfg.operation = 'log(x1)';
tmp = ft_math(cfg, source1);
assert(tmp.mom{1}(1)==0);

cfg.operation = '(x1-x2)/(x1+x2)';
tmp = ft_math(cfg, source1, source2);
assert(tmp.mom{1}(1)==-1/3);

cfg.scalar = 2;
cfg.operation = '(x1+x2)^s';
tmp = ft_math(cfg, source1, source2);
assert(tmp.mom{1}(1)==9);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% do operation with a matrix

cfg = [];
cfg.showcallinfo = 'no';
cfg.parameter    = 'avg';

cfg.matrix = zeros(size(timelock1.avg));

cfg.operation = 'add';
tmp = ft_math(cfg, timelock1);
assert(isequal(timelock1.avg, tmp.avg));
cfg.operation = 'subtract';
tmp = ft_math(cfg, timelock1);
assert(isequal(timelock1.avg, tmp.avg));

cfg.matrix = ones(size(timelock1.avg));

cfg.operation = 'multiply';
tmp = ft_math(cfg, timelock1);
assert(isequal(timelock1.avg, tmp.avg));
cfg.operation = 'divide';
tmp = ft_math(cfg, timelock1);
assert(isequal(timelock1.avg, tmp.avg));

try
  failed = false;
  cfg = [];
  cfg.showcallinfo = 'no';
  cfg.parameter    = 'avg';
  cfg.operation    = 'log10';
  cfg.matrix       = randn(3);
  tmp = ft_math(cfg, timelock1);
catch
  failed = true;
end
assert(failed, 'this should have failed');


function [L1t,L2t,L3t]=triplet_find(DT1,DT2,DT3,Vn1,Vn2,Vn3,T_dist,opt)

switch opt
    case 1 %Full Delaunay input based
        [~,Dc12] = nearestNeighbor(DT2,Vn1);
        [~,Dc13] = nearestNeighbor(DT3,Vn1);
        L1t=Dc12<=T_dist & Dc13<=T_dist;

        [~,Dc21] = nearestNeighbor(DT1,Vn2);
        [~,Dc23] = nearestNeighbor(DT3,Vn2);
        L2t=Dc21<=T_dist & Dc23<=T_dist;

        [~,Dc31] = nearestNeighbor(DT1,Vn3);
        [~,Dc32] = nearestNeighbor(DT2,Vn3);
        L3t=Dc31<=T_dist & Dc32<=T_dist;

    case 2 %Accelerating renew with cropped Delaunay if possible otherwise full

        [~,Dc12] = nearestNeighbor(DT2,Vn1);
        L12t=Dc12<=T_dist;
        if any(L12t)
            [~,Dc13] = nearestNeighbor(DT3,Vn1);
            L1t=L12t & Dc13<=T_dist;
        else
            L1t=false(size(Vn1,1),1);
        end

        if any(L1t)
            if nnz(L1t)>=4
                DT=delaunayTriangulation(Vn1(L1t,:)); %Tesselation of selected coordinates
                if ~isempty(DT.ConnectivityList)
                    DT1=DT;
                end
            end

            [~,Dc21] = nearestNeighbor(DT1,Vn2);
            L21t=Dc21<=T_dist;
            if any(L21t)
                [~,Dc23] = nearestNeighbor(DT3,Vn2);
                L2t=L21t & Dc23<=T_dist;
            else
                L2t=false(size(Vn2,1),1);
            end
        else
            L2t=false(size(Vn2,1),1);
        end

        if any(L2t)
            if nnz(L2t)>=4
                DT=delaunayTriangulation(Vn2(L2t,:)); %Tesselation of selected coordinates
                if ~isempty(DT.ConnectivityList)
                    DT2=DT;
                end
            end

            [~,Dc31] = nearestNeighbor(DT1,Vn3);
            L31t=Dc31<=T_dist;
            if any(L31t)
                [~,Dc32] = nearestNeighbor(DT2,Vn3);
                L3t=L31t & Dc32<=T_dist;
            else
                L3t=false(size(Vn3,1),1);
            end
        else
            L3t=false(size(Vn3,1),1);
        end

    case 3 %Accelerating renew with cropped Delaunay/non-Delaunay
        [~,Dc12] = nearestNeighbor(DT2,Vn1);
        [~,Dc13] = nearestNeighbor(DT3,Vn1);
        L1t=Dc12<=T_dist & Dc13<=T_dist;
        if any(L1t)
            if nnz(L1t)>=4
                DT=delaunayTriangulation(Vn1(L1t,:)); %Tesselation of selected coordinates
                if ~isempty(DT.ConnectivityList)
                    DT1=DT;
                end
                [~,Dc21] = nearestNeighbor(DT1,Vn2);
                [~,Dc31] = nearestNeighbor(DT1,Vn3);
            else
                [INDc,Dc12] = dsearchn(Vn2,Vn1(L1t,:));
                Dc21=NaN(size(Vn2,1),1); Dc21(INDc)=Dc12;

                [INDc,Dc13] = dsearchn(Vn3,Vn1(L1t,:));
                Dc31=NaN(size(Vn3,1),1); Dc31(INDc)=Dc13;
            end
            [~,Dc23] = nearestNeighbor(DT3,Vn2);
            L2t=Dc21<=T_dist & Dc23<=T_dist;
        else
            L2t=false(size(Vn2,1),1);
        end
        if any(L2t)
            if nnz(L2t)>=4 && nnz(L1t)>=4
                 DT=delaunayTriangulation(Vn2(L2t,:)); %Tesselation of selected coordinates
                if ~isempty(DT.ConnectivityList)
                    DT2=DT;
                end
                [~,Dc32] = nearestNeighbor(DT2,Vn3);
            else
                [INDc,Dc23] = dsearchn(Vn3,Vn2(L2t,:));
                Dc32=NaN(size(Vn3,1),1); Dc32(INDc)=Dc23;
            end
            L3t=Dc31<=T_dist & Dc32<=T_dist;
        else
            L3t=false(size(Vn3,1),1);
        end
end
end

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function outputImage = remove_clusters(this, varargin)
% Removes all voxel clusters within a given range of voxel counts, and/or
% a given range of percent of the area that is (approximately) filled;
% either slice-wise or volume-wise (8 or 26 neighbours) using Matlab's
% bwareaopen
%
%   Y = MrImage()
%   clusterRemovedImage = Y.remove_clusters('nPixelRange', nPixelRange, ...
%           'pAreaRange', pAreaRange, 'applicationDimension', applicationDimension)
%
% This is a method of class MrImage.
%
% IN
%   nPixelsPerClusterRange
%   percentAreaFilledRange
%           percent area of the cluster filled estimated using the
%           Solidity property
%   applicationDimension
%           dimensionality to perform operation
%           '2d' = slicewise application, separate 2d images (cluster
%           neighbours only considered within slice)
%           '3d' = neighbourhood considered as volume
%
% OUT
%   outputImage
%           MrImage where data matrix does not contain removed clusters
%
% EXAMPLE
%   Y = MrImage();
%   % remove all pixel clusters with 15 or less pixels (3D neighbourhood)
%   Y.remove_clusters('nPixelRange', [0 15], 'applicationDimension', '3D');
%   Y.remove_clusters('areaRange', [0 40], 'applicationDimension', '2D');
%
%   See also MrImage imdilate MrImage.imerode perform_unary_operation bwareaopen

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

defaults.nPixelRange = [0 0];
defaults.pAreaRange = [0 0];
defaults.applicationDimension = '3D';

args = tapas_uniqc_propval(varargin, defaults);
tapas_uniqc_strip_fields(args);

areaRange = pAreaRange/100;
is3D = strcmpi(applicationDimension, '3D');

BW = this.copyobj.binarize(0, 'exclude');

if is3D
    conn = 26; % use 26 neighbours in 3D (all faces and corners connected)
else
    conn = 8; % use 8 neighbours (in 2D)
end

%% step 1 - remove cluster based on voxel count

% only crop, if required (i.e., connectivity components greater than 1)
if nPixelRange(1) > 1
    % since we want to reinclude this mask later on (range!), we do not add
    % the +1 usually needed for bwareaopen, i.e., we only remove smaller
    % clusters here
    BW1 = BW.perform_unary_operation(@(x) bwareaopen(x, nPixelRange(1), conn), ...
        applicationDimension);
else
    BW1 = BW.copyobj;
end

if nPixelRange(2) > 0
    % since we indeed use this as a subtractive mask, we have to add +1 to
    % remove the clusters at the upper end of the cluster range as well
    BW2 = BW.perform_unary_operation(@(x) bwareaopen(x, nPixelRange(2) + 1, conn), ...
        applicationDimension);
else
    BW2 = BW.copyobj;
end

% by the following subtraction, excluded voxels in both BW1 and BW2 will be
% reincluded, hence, an exclusive or is reached, only removing clusters in
% the range between BW1 and BW2
BW = abs(BW - BW1 - BW2);

%% step 2 - remove cluster based on percent area filled
% extract region properties
if is3D
    stats = bwconncomp(BW.data, conn);
    props = regionprops3(stats, 'Solidity');
    % threshold solidity
    solidity = [props.Solidity];
    removeClusters = (solidity > areaRange(1) & solidity < areaRange(2));
    removeVoxels = vertcat(stats.PixelIdxList{removeClusters});
    % remove voxel
    BW.data(removeVoxels) = 0;
else
    % regionprops does not automatically take into account the defined
    % connectivity, so we have to do the split by hand
    nSamplesZ = BW.dimInfo.nSamples('z');
    for z = 1:nSamplesZ
        tempData = BW.select('z', z).data;
        stats = bwconncomp(tempData, conn);
        props = regionprops(stats, 'Solidity');
        % threshold solidity
        solidity = [props.Solidity];
        removeClusters = (solidity > areaRange(1) & solidity < areaRange(2));
        removeVoxels = vertcat(stats.PixelIdxList{removeClusters});
        % remove voxel
        tempData(removeVoxels) = 0;
        BW.data(:,:,z) = tempData;
    end
end

outputImage = this.*BW;

end


function x = cifft2(xf)

if isa(xf, 'gpuArray')
    x = real(ifft2(ifftshift(ifftshift(xf, 1), 2)));
else
    x = ifft2(ifftshift(ifftshift(xf, 1), 2), 'symmetric');
end


close all
clear

% system setup and initial condition
timestep = 0.1;
system_param.A = [[1 ,timestep, 0]; [0, 1, timestep]; [0, 0, 1]];
system_param.B = [0; 0; timestep];
system_param.ul = -1;
system_param.uu = 1;
system_param.timestep = timestep;
x0 = [-2;0;1];
t0 = 0.0;
total_time = 1.0;

% problem setup
simulator = CBFDT(system_param, x0, t0);

param_mpcdcbf = ParamMPCDCBF(6, 0.1, 10 * eye(3), 10.0 * eye(3), 1.0);
simulator.setOpt('mpcdcbf', param_mpcdcbf);
simulator.sim(total_time);

param_mpcgcbf = ParamMPCGCBF(6, 0.1, 10 * eye(3), 10.0 * eye(3), 1.0);
simulator.setOpt('mpcgcbf', param_mpcgcbf);
simulator.sim(total_time);

param_nmpcdcbf = ParamNMPCDCBF(6, 6, 0.1, 10 * eye(3), 10.0 * eye(3), 1.0, 10.0);
simulator.setOpt('nmpcdcbf', param_nmpcdcbf);
simulator.sim(total_time);

param_dclfdcbf = ParamDCLFDCBF(0.1, 0.1, 10 * eye(3), 1.0, 10.0);
simulator.setOpt('dclfdcbf', param_dclfdcbf);
simulator.sim(total_time);

param_nmpcdclfdcbf = ParamNMPCDCLFDCBF(6, 6, 6, 0.1, 0.1, 10.0 * eye(3), 10.0 * eye(3), 1.0, 10.0, 10.0);
simulator.setOpt('nmpcdclfdcbf', param_nmpcdclfdcbf);
simulator.sim(total_time);


% readneurodat() - read neuroscan location file (.dat)
%
% Usage:
%   >> [ CHANLOCS labels theta theta ] = readneurodat( filename );
%
% Inputs:
%   filename       - file name or matlab cell array { names x_coord y_coord }
%
% Outputs:
%   CHANLOCS       - [structure] EEGLAB channel location data structure. See
%                    help readlocs()
%   labels         - [cell arrya] channel labels
%   theta          - [float array]array containing 3-D theta angle electrode
%                    position (in degree)
%   phi            - [float array]array containing 3-D phi angle electrode
%                    position (in degree)
%
% Author: Arnaud Delorme, CNL / Salk Institute, 28 Nov 2003
%
% See also: readlocs(), readneurolocs()

% Copyright (C) Arnaud Delorme, CNL / Salk Institute, 15 March 2003, 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 [chanlocs, labels, theta, phi] = readneurodat(filename)

    if nargin < 1
        help readneurodat;
        return;
    end

    % enter file name here
    % --------------------
    %tmp = loadtxt('/home/ftp/pub/locfiles/neuroscan/cap128.dat');
    %tmp = loadtxt('/home/arno/temp/quik128.DAT');
    tmp = loadtxt(filename);

    % resort electrodes
    % -----------------
    [tmp2, tmpind] = sort(celltomat(tmp(:,1))');
    tmp = tmp(tmpind,:);

    % convert to polar coordinates
    % ----------------------------
    %figure; plot(celltomat(tmp(:,2)), celltomat(tmp(:,3)), '.');
    [phi,theta] = cart2pol(celltomat(tmp(:,end-1)), celltomat(tmp(:,end)));
    theta = theta/513.1617*44;
    phi   = phi/pi*180;

    % convert to other types of coordinates
    % -------------------------------------
    labels = tmp(:,end-2)';
    numLabel = labels{1};
    if isnumeric(numLabel)
        if numLabel ~= round(numLabel) % floating point label
            error('Wrong file format')
        end
    end
    chanlocs = struct('labels', labels, 'sph_theta_besa', mattocell(theta)', 'sph_phi_besa', mattocell(phi)');
    chanlocs = convertlocs( chanlocs, 'sphbesa2all');
    for index = 1:length(chanlocs)
        chanlocs(index).labels = num2str(chanlocs(index).labels);
    end
    theta = theta/pi*180;
    fprintf('Note: .dat file contain polar 2-D coordinates. EEGLAB will use these coordinates\n');
    fprintf('      to recreated 3-D coordinates.\n');
    fprintf('\n');
    fprintf('Warning: if the channels are clustered in the middle or oddly spaced removed\n');
    fprintf('         the peripheral channels and then used the optimize head function\n');
    fprintf('         in the Channel Locations GUI. It seems that sometimes the peripherals\n');
    fprintf('         are throwing off the spacing.\n');


function SR = superresolve_wnuisr(slidingWindows, magFactor)

numberOfFrames = size(slidingWindows.frames,3);

% Set PSF kernels for the different binning factors.
psf{1} = fspecial('gaussian', 5, 0.8); % PSF for binning factor 2
psf{2} = fspecial('gaussian', 7, 1.2); % PSF for binning factor 3
psf{3} = fspecial('gaussian', 9, 1.6); % PSF for binning factor 4

% Specific preprocessing steps for the non-uniform interpolation based multi-frame methods.
weighting_struct = struct('mec_weight_flag',4,'dis_weight_flag',1,'qps_weight_flag',0,'mec_confMapN',[],...
    'mec_thr_scaler',2,'mec_weight_exp',2,'mec_weighting',[],'dis_rho',0.7,'dis_scaler',magFactor*10,'dis_weighting',[],...
    'qps_map',[],'qps_rho',0.7,'qps_weighting',[],'alpha',1,'beta',1,'gamma',1,'whi_mode',2);
warped_meshXN = zeros(size(slidingWindows.referenceFrame,1),size(slidingWindows.referenceFrame,2),numberOfFrames-1);
warped_meshYN = zeros(size(slidingWindows.referenceFrame,1),size(slidingWindows.referenceFrame,2),numberOfFrames-1);

lr_seq_sorted = slidingWindows.frames;
lr_seq_tmp = lr_seq_sorted(:,:,(numberOfFrames+1)/2);
lr_seq_sorted(:,:,(numberOfFrames+1)/2) = lr_seq_sorted(:,:,1);
lr_seq_sorted(:,:,1) = lr_seq_tmp;

lr_seq_sorted = permute(lr_seq_sorted,[1 2 4 3]);

permutation_vec = 1:numberOfFrames-1;
permutation_vec((numberOfFrames+1)/2:end) = permutation_vec((numberOfFrames+1)/2:end) + 1;
permutation_vec(1:(numberOfFrames-1)/2)   = circshift(permutation_vec(1:(numberOfFrames-1)/2),[0 -1]);

for itera = 1:numberOfFrames-1
    [warped_meshXN(:,:,itera),warped_meshYN(:,:,itera)] = lmsSR_warpImgGridLocalTrans(size(slidingWindows.referenceFrame,1),size(slidingWindows.referenceFrame,2),slidingWindows.flowToReference{permutation_vec(itera)}.mvs_xc);

    % Storing the MEC-SSD-Confidence into the Weighting Struct
    weighting_struct.mec_confMapN(:,:,itera) = slidingWindows.mec_confMap{permutation_vec(itera)};
end

% Actual SR call
[SR,~,~,~] = lmsSR_generateSRusingNUIv4weighted(lr_seq_sorted,warped_meshXN,warped_meshYN,[magFactor, magFactor],psf{magFactor-1},2,weighting_struct);


switch dataName
    case 'circle'
        [data4, data] = curves_with_angles(300);

         [data_noise, noise, temp_max_index] = addnoise(data, 0.4);
        feats = data_noise;

    case  'square'
          [data]=square(200);
           [data_noise, noise, temp_max_index] = addnoise(data, 0.05);
           feats=data_noise;
    case 'hole'
        [data] = generate.Generate_Ground_Truth(dataName,1000);
        [data_noise, noise, temp_max_index] = generate.addnoise(data, 0.1);
        feats = data_noise;
    case 'fishbowl'
        [data] = generate.Generate_Ground_Truth(dataName,600);
        [data_noise, noise, temp_max_index] = generate.addnoise(data, 0.1);%0.1
        feats = data_noise;
        [feats]=double(outlier_generation(feats));
       case 'sphere_helix'
        [data]=generate.Generate_Ground_Truth(dataName);
        [data_noise, noise, temp_max_index] = generate.addnoise(data, 0.4);
        feats = data_noise;

     case 'box_plane'
        box_plane;
        feats=data;
    case 'Hemisphere_plane'
        [data,data_clean]=Hemisphere_plane;
        feats=data;

    case 'planes'
    [feats,data]=pctest5 ();

case 'cyclo'
        load('test_cyclo.mat');
        data=X_iso;
        data=data(:,1:6000);
       var_noise=0.2;
       [data_noise,noise,temp_max_index] = generate.addnoise(data, var_noise);
       feats=data_noise;

end


function F = vertcat( varargin )
%VERTCAT   Vertical concatenation of BALLFUN objects.
%
% K = VERTCAT(F, G, H) is the vertical concatenation of BALLFUN objects F,
% G, and H. The function K is a BALLFUNV object.
%
% [F ; G ; H] is equivalent to VERTCAT(F, G, H).
%
% VERTCAT(F, G) returns an error. BALLFUNV objects have three components.
%
% VERTCAT(F) returns the BALLFUN F.
%
% See also BALLFUNV.

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

if ( nargin == 1 )
    % VERTCAT of one argument just returns the same thing back to the user:
    F = varargin{1};
elseif ( nargin == 3 )
    if all( cellfun(@(F) isa(F,'ballfun'), varargin) )
        F = ballfunv( varargin{:} );
    else
        error('BALLFUN:vertcat:tooManyComponents', ...
            'Only BALLFUN objects are valid to concatenate.');
    end
else
    error('BALLFUN:vertcat:tooManyInputs', ...
        'Can only vertically concatenate three BALLFUN objects.');
end

end


function [parameters, fitnessScore, exitFlag, newModel]=fitParameters(model,xRxns,xValues,rxnsToFit,valuesToFit,parameterPositions,fitToRatio,initialGuess,plotFitting)
% fitParameters
%   Fits parameters such as maintenance ATP by quadratic programming
%
%   model                 a model structure
%   xRxns                 cell array with the IDs of the reactions that will be
%                         fixed for each data point
%   xValues               matrix with the corresponding values for each
%                         xRxns (columns are reactions)
%   rxnsToFit             cell array with the IDs of reactions that will be fitted to
%   valuesToFit           matrix with the corresponding values for each
%                         rxnsToFit (columns are reactions)
%   parameterPositions    stucture that determines where the parameters are in the
%                         stoichiometric matrix. Contains the fields:
%   	position          cell array of vectors where each element contains
%                         the positions in the S-matrix for that parameter
%   	isNegative        cell array of vectors where the elements are true
%                         if that position should be the negative of the
%                         fitted value (to differentiate between
%                         production/consumption)
%	fitToRatio            if the ratio of simulated to measured values should
%                         be fitted instead of the absolute value. Used to prevent
%                         large fluxes from having too large impact (opt,
%                         default true)
%   initialGuess          initial guess of the parameters (opt)
%   plotFitting           true if the resulting fitting should be plotted
%                         (opt, default false)
%
%   parameters            fitted parameters in the same order as in
%                         parameterPositions
%   fitnessScore          the correponding residual sum of squares
%   newModel              updated model structure with the fitted parameters
%
%   Usage: [parameters, fitnessScore, exitFlag, newModel]=fitParameters(model,...
%           xRxns,xValues,rxnsToFit,valuesToFit,parameterPositions,fitToRatio,...
%           initialGuess,plotFitting)

if nargin<7
    fitToRatio=true;
end
if nargin<8
    initialGuess=ones(numel(parameterPositions.position),1);
end
if isempty(initialGuess)
    initialGuess=ones(numel(parameterPositions.position),1);
end
if nargin<9
    plotFitting=false;
end

xRxns=convertCharArray(xRxns);
rxnsToFit=convertCharArray(rxnsToFit);

%Find the indexes of reactions that will be fitted
[I, rxnsToFitIndexes]=ismember(rxnsToFit,model.rxns);

if ~all(I)
    EM='Could not find all reactions in rxnsToFit';
    dispEM(EM);
end

%Find the indexes of reactions that will be used for constraints.
[I, xRxnsIndexes]=ismember(xRxns,model.rxns);

if ~all(I)
    EM='Could not find all reactions in xRxns';
    dispEM(EM);
end

[parameters, fitnessScore, exitFlag]=fminsearch(@(parameters) getRSS(parameters,model,xRxnsIndexes,xValues,rxnsToFitIndexes,valuesToFit,parameterPositions,fitToRatio),initialGuess);

parameters=abs(parameters);

if plotFitting==true
    %Set the resulting parameters
    [~, resultingFluxes, newModel]=getRSS(parameters,model,xRxnsIndexes,xValues,rxnsToFitIndexes,valuesToFit,parameterPositions,true);
    plot(xValues,valuesToFit,'o',xValues,resultingFluxes,'-*');
end
end

function [rss, resultingFluxes, newModel]=getRSS(parameters,model,xRxnsIndexes,xValues,rxnsToFitIndexes,valuesToFit,parameterPositions,fitToRatio)
parameters=abs(parameters);

%Set the parameters at the positions specified in parameterPositions
for i=1:numel(parameterPositions.position)
    %Set positive
    model.S(parameterPositions.position{i}(parameterPositions.isNegative{i}==false))=parameters(i);

    %Set negative
    model.S(parameterPositions.position{i}(parameterPositions.isNegative{i}==true))=parameters(i)*-1;
end

%Also return an updated model
newModel=model;

%Loop through each data point, set xRxns to xValues and calculate the sum
%of squares for the rxnsToFit
rss=0;
resultingFluxes=[];
for i=1:size(xValues,1)
    %Fix for more xRxns!
    model.lb(xRxnsIndexes)=xValues(i,:);
    model.ub(xRxnsIndexes)=xValues(i);

    sol=solveLP(model);

    %Calculate the rss
    if fitToRatio==false
        rs=sol.x(rxnsToFitIndexes)'-valuesToFit(i,:);
    else
        rs=sol.x(rxnsToFitIndexes)'./valuesToFit(i,:)-ones(1,size(valuesToFit,2));
    end
    rss=rss+rs*rs';
    resultingFluxes=[resultingFluxes sol.x(rxnsToFitIndexes)];
end
end


function opt_vect = foptions()
% FOPTIONS Sets default parameters for optimisation routines
% For compatibility with MATLAB's foptions()
%
% Copyright (c) Dharmesh Maniyar, Ian T. Nabney (2004)

opt_vect      = zeros(1, 18);
opt_vect(2:3) = 1e-4;
opt_vect(4)   = 1e-6;
opt_vect(16)  = 1e-8;
opt_vect(17)  = 0.1;


%% Machine Learning Online Class
%  Exercise 7 | Principle Component Analysis and K-Means Clustering
%
%  Instructions
%  ------------
%
%  This file contains code that helps you get started on the
%  exercise. You will need to complete the following functions:
%
%     pca.m
%     projectData.m
%     recoverData.m
%     computeCentroids.m
%     findClosestCentroids.m
%     kMeansInitCentroids.m
%
%  For this exercise, you will not need to change any code in this file,
%  or any other files other than those mentioned above.
%

%% Initialization
clear ; close all; clc

%% ================= Part 1: Find Closest Centroids ====================
%  To help you implement K-Means, we have divided the learning algorithm
%  into two functions -- findClosestCentroids and computeCentroids. In this
%  part, you shoudl complete the code in the findClosestCentroids function.
%
fprintf('Finding closest centroids.\n\n');

% Load an example dataset that we will be using
load('ex7data2.mat');

% Select an initial set of centroids
K = 3; % 3 Centroids
initial_centroids = [3 3; 6 2; 8 5];

% Find the closest centroids for the examples using the
% initial_centroids
idx = findClosestCentroids(X, initial_centroids);

fprintf('Closest centroids for the first 3 examples: \n')
fprintf(' %d', idx(1:3));
fprintf('\n(the closest centroids should be 1, 3, 2 respectively)\n');

fprintf('Program paused. Press enter to continue.\n');
pause;

%% ===================== Part 2: Compute Means =========================
%  After implementing the closest centroids function, you should now
%  complete the computeCentroids function.
%
fprintf('\nComputing centroids means.\n\n');

%  Compute means based on the closest centroids found in the previous part.
centroids = computeCentroids(X, idx, K);

fprintf('Centroids computed after initial finding of closest centroids: \n')
fprintf(' %f %f \n' , centroids');
fprintf('\n(the centroids should be\n');
fprintf('   [ 2.428301 3.157924 ]\n');
fprintf('   [ 5.813503 2.633656 ]\n');
fprintf('   [ 7.119387 3.616684 ]\n\n');

fprintf('Program paused. Press enter to continue.\n');
pause;

%% =================== Part 3: K-Means Clustering ======================
%  After you have completed the two functions computeCentroids and
%  findClosestCentroids, you have all the necessary pieces to run the
%  kMeans algorithm. In this part, you will run the K-Means algorithm on
%  the example dataset we have provided.
%
fprintf('\nRunning K-Means clustering on example dataset.\n\n');

% Load an example dataset
load('ex7data2.mat');

% Settings for running K-Means
K = 3;
max_iters = 10;

% For consistency, here we set centroids to specific values
% but in practice you want to generate them automatically, such as by
% settings them to be random examples (as can be seen in
% kMeansInitCentroids).
initial_centroids = [3 3; 6 2; 8 5];

% Run K-Means algorithm. The 'true' at the end tells our function to plot
% the progress of K-Means
[centroids, idx] = runkMeans(X, initial_centroids, max_iters, true);
fprintf('\nK-Means Done.\n\n');

fprintf('Program paused. Press enter to continue.\n');
pause;

%% ============= Part 4: K-Means Clustering on Pixels ===============
%  In this exercise, you will use K-Means to compress an image. To do this,
%  you will first run K-Means on the colors of the pixels in the image and
%  then you will map each pixel on to it's closest centroid.
%
%  You should now complete the code in kMeansInitCentroids.m
%

fprintf('\nRunning K-Means clustering on pixels from an image.\n\n');

%  Load an image of a bird
A = double(imread('bird_small.png'));

% If imread does not work for you, you can try instead
%   load ('bird_small.mat');

A = A / 255; % Divide by 255 so that all values are in the range 0 - 1

% Size of the image
img_size = size(A);

% Reshape the image into an Nx3 matrix where N = number of pixels.
% Each row will contain the Red, Green and Blue pixel values
% This gives us our dataset matrix X that we will use K-Means on.
X = reshape(A, img_size(1) * img_size(2), 3);

% Run your K-Means algorithm on this data
% You should try different values of K and max_iters here
K = 16;
max_iters = 10;

% When using K-Means, it is important the initialize the centroids
% randomly.
% You should complete the code in kMeansInitCentroids.m before proceeding
initial_centroids = kMeansInitCentroids(X, K);

% Run K-Means
[centroids, idx] = runkMeans(X, initial_centroids, max_iters);

fprintf('Program paused. Press enter to continue.\n');
pause;

%% ================= Part 5: Image Compression ======================
%  In this part of the exercise, you will use the clusters of K-Means to
%  compress an image. To do this, we first find the closest clusters for
%  each example. After that, we

fprintf('\nApplying K-Means to compress an image.\n\n');

% Find closest cluster members
idx = findClosestCentroids(X, centroids);

% Essentially, now we have represented the image X as in terms of the
% indices in idx.

% We can now recover the image from the indices (idx) by mapping each pixel
% (specified by it's index in idx) to the centroid value
X_recovered = centroids(idx,:);

% Reshape the recovered image into proper dimensions
X_recovered = reshape(X_recovered, img_size(1), img_size(2), 3);

% Display the original image
subplot(1, 2, 1);
imagesc(A);
title('Original');

% Display compressed image side by side
subplot(1, 2, 2);
imagesc(X_recovered)
title(sprintf('Compressed, with %d colors.', K));

fprintf('Program paused. Press enter to continue.\n');
pause;

github-repos/MATLAB/Borye-machine-learning-coursera-1/machine-learning-coursera-1-033fdc2e6da393eeb1179a09aafe92362021effb/Week 8 Assignments/K-Means Clustering and PCA/mlclass-ex7/ex7.m


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
%
% KERNEL/DISTANCES
%
% Contents of FAIR's Distance Toolbox
%
% This folder provides several distance measures, wrappers and utilities.
%
% general purpose tools:
%   contents        - this file
%   distance        - the specific distance measure used in FAIR
%     initialize:   distance('reset','distance','SSD');
%     usage:        D = distance(Tc,Rc,omega,m);
%   testDistances   - test the files in this folder
%   see also E9_Hands_MLIR_SSD_mbElas
%
% measures and wrappers:
%   MI              - wrapper for MIcc
%   MImex           - Mutual Information based on rhoSplineC (C-implementation)
%   MIspline        - Mutual Information based on rhoSpline  (MATLAB-implementation)
%   rhoSpline       - MATLAB implementation of joint entropy estimator (spline kernel)
%   rhoSplineC      - C based implementation of joint entropy estimator (spline kernel)
%   NCC             - Normalized Cross Correlation
%   NCCmex          - Wrapper for NCCmexC
%   NCCmexC         - C version of NCC
%   NGF             - wrapper for NGFdot
%   NGFdot          - Normalized Gradient Fields, dot product based (THE implementation)
%   NGFcross        - Normalized Gradient Fields, cross product based (to be used with care)
%   NGFmex          - Wrapper for NGFdotMexC
%   NGFdotMexC      - C version of NGFdot
%   SSD             - Sum of Squared Differences
%   SSDmex          - Wrapper for SSDmexC
%   SSDmexC         - C version of SSD
%   parseDistance   - parse distances for derivative checks
%  see also E9_Hands_MLIR_SSD_mbElas
%
%==============================================================================

function debit = contents
if nargout == 0,
    help(mfilename);
    return;
end;

debit = {
  'contents.m'
  'distance.m'
  'testDistances.m'

  'SSD.m'
  'SSDmex.m'
  'SSDmexC.cpp'

  'NCC.m'
  'NCCmex.m'
  'NCCmexC.cpp'

  'NGF.m'
  'NGFcross.m'
  'NGFdot.m'
  'NGFmex.m'
  'NGFdotMexC.cpp'

  'rhoSpline.m'
  'rhoSplineC.cpp'

  'MI.m'
  'MImex.m'
  'MIspline.m'

  'parseDistance.m'
  };
  %==============================================================================


% M1QN3  Solve a UNO using M1QN3
%
% THIS IS A LOW LEVEL FUNCTION - USE opti_m1qn3() INSTEAD!
%
%   [x,fval,exitflag,iter,feval] = m1qn3(fun,grad,x0,opts)
%
%   Input arguments:
%       fun - nonlinear function handle
%       grad - nonlinear gradient function handle (required)
%       x0 - initial solution guess
%       opts - solver options (see below)
%
%   Return arguments:
%       x - solution vector
%       fval - objective value at the solution
%       exitflag - exit status (see below)
%       iter - number of iterations taken by the solver
%       feval - number of function evaluations taken by the solver
%
%   Option Fields (all optional):
%       display - solver display level [0,1,2]
%       tolafun - gradient convergence tolerance
%       maxiter - maximum solver iterations {1000}
%       maxfeval - Maximum number of function evaluations {1500}
%       maxtime - Maximum solver execution time {1000s}
%       nupdate - Number of L-BFGS updates for Hessian (5-10) {5}
%       iterfun - Iteration callback function handle
%
%   Return Status:
%       0 - user exited
%       1 - successful termination
%       2 - input argument error
%       3 - line-search is blocked
%       4 - maximum iterations reached
%       5 - maximum function evaluations reached
%       6 - stop on dxmin during the line-search
%       7 - numerical error
%       8 - maximum time reached
%
%
%   Copyright (C) 2012 Jonathan Currie (IPL)


% eeg_anova_script - example task ERP analysis

%  Analysis script for ERP components in
%  fixed and variable task waveforms for PTSD-PET project

% Define sample rate & epoch parameters
fprintf('Defining ERP parameters\n');
sample_rate = 2.5;
epoch_start = -200;
epoch_end = 1500;
points = 680;
times = linspace(epoch_start,(epoch_end - sample_rate),points);

% Define component timing & rows
comp = [145 195 250 385 550 750 950 1150 1350];
comp_rows = (comp - epoch_start) / sample_rate;

% Load data (680 rows x 124 cols)
path = 'd:\data_emse\ptsdpet\link14hz\';
for i=1:10,
    file = sprintf('%sc%02do_link14hz.txt',path,i);
    var  = sprintf('c%02do_link14hz',i);
    if ~exist(var,'var')
        fprintf('loading %s\n',file);
        load(file);
    end
    file = sprintf('%sc%02dt_link14hz.txt',path,i);
    var  = sprintf('c%02dt_link14hz',i);
    if ~exist(var,'var')
        fprintf('loading %s\n',file);
        load(file);
    end
    file = sprintf('%sp%02do_link14hz.txt',path,i);
    var  = sprintf('p%02do_link14hz',i);
    if ~exist(var,'var')
        fprintf('loading %s\n',file);
        load(file);
    end
    file = sprintf('%sp%02dt_link14hz.txt',path,i);
    var  = sprintf('p%02dt_link14hz',i);
    if ~exist(var,'var')
        fprintf('loading %s\n',file);
        load(file);
    end
end

% Select data rows for each component

cont = zeros(1,2,124);
ptsd = zeros(1,2,124);

for i = 1:max(size(comp))
    c = comp(i);
    t = comp_rows(i);
    for j=1:10,
        sub = sprintf('c%02do_link14hz',j);
        fprintf('Component %d, selecting subject %s\n',c,sub);
        data = eval(sub);
        cont(j,1,:) = data(t,:);

        sub = sprintf('c%02dt_link14hz',j);
        fprintf('Component %d, selecting subject %s\n',c,sub);
        data = eval(sub);
        cont(j,2,:) = data(t,:);

        sub = sprintf('p%02do_link14hz',j);
        fprintf('Component %d, selecting subject %s\n',c,sub);
        data = eval(sub);
        ptsd(j,1,:) = data(t,:);

        sub = sprintf('p%02dt_link14hz',j);
        fprintf('Component %d, selecting subject %s\n',c,sub);
        data = eval(sub);
        ptsd(j,2,:) = data(t,:);
    end

    % Combine component data into single matrix
    data = [cont;ptsd]; % 20x2x124

    % Output ANOVA analysis.
    file = sprintf('%scomp%d_anova.txt',path,c);
    ANOVA = fopen(file,'w');
    file = sprintf('%scomp%d_p_task.txt',path,c);
    TASK = fopen(file,'w');
    file = sprintf('%scomp%d_p_group.txt',path,c);
    GROUP = fopen(file,'w');
    file = sprintf('%scomp%d_p_taskxgroup.txt',path,c);
    TASKxGROUP = fopen(file,'w');

    formatstr = '';

    fprintf('Doing ANOVA on electrode:\n');

    x = 0;
    for k=1:124,

        % Extract data for analysis
        anova_data = data(:,:,k);

        if (x==24),
            x=0;
            fprintf('%3d\n',k);
        else,
            x = x + 1;
            fprintf('%3d ',k);
        end
        fprintf(ANOVA,'\n\nELECTRODE %3d\n',k);

        % Calculate & output summary stats
        avg.cont = mean(anova_data( 1:10,:));
        avg.ptsd = mean(anova_data(10:20,:));
        sd.cont = std(anova_data( 1:10,:));
        sd.ptsd = std(anova_data(10:20,:));
        se.cont = sd.cont / sqrt(10);
        se.ptsd = sd.ptsd / sqrt(10);
        fprintf(ANOVA,'%-12s\t%-12s\t%12s\t%12s\t%12s\n','Group','Task','Mean','StDev','SE');
        fprintf(ANOVA,'%-12s\t%-12s\t%12s\t%12s\t%12s\n','-----','----','----','-----','--');
        fprintf(ANOVA,'%-12s\t%-12s\t%12.6f\t%12.6f\t%12.6f\n','Cont','Fixed',   avg.cont(1),sd.cont(1),se.cont(1));
        fprintf(ANOVA,'%-12s\t%-12s\t%12.6f\t%12.6f\t%12.6f\n','Cont','Variable',avg.cont(2),sd.cont(2),se.cont(2));
        fprintf(ANOVA,'%-12s\t%-12s\t%12.6f\t%12.6f\t%12.6f\n','PTSD','Fixed',   avg.ptsd(1),sd.ptsd(1),se.ptsd(1));
        fprintf(ANOVA,'%-12s\t%-12s\t%12.6f\t%12.6f\t%12.6f\n\n','PTSD','Variable',avg.ptsd(2),sd.ptsd(2),se.ptsd(2));

        % Run 2way ANOVA
        [p, tab] = anova2(anova_data,10,'off');

        % Collate the p values
        task(k) = p(1);
        group(k) = p(2);
        taskxgroup(k) = p(3);

        % Output ANOVA table
        tab(2,1) = {'Task'};
        tab(3,1) = {'Group'};
        tab(4,1) = {'Task x Group'};
        for m=1:6,
            for n=1:6,
                if n==1, fprintf(ANOVA,'%-12s\t',tab{m,n});
                else
                    if m==1, fprintf(ANOVA,'%12s\t',tab{m,n});
                    else     fprintf(ANOVA,'%12.6f\t',tab{m,n});
                    end
                end
            end
            fprintf(ANOVA,'\n');
        end

        % This string is used to output all the p values below
        formatstr = strcat(formatstr,'%12.6f\t');

    end
    fclose(ANOVA);

    % Output the p values
    fprintf(TASK,formatstr,task); fclose(TASK);
    fprintf(GROUP,formatstr,group); fclose(GROUP);
    fprintf(TASKxGROUP,formatstr,taskxgroup); fclose(TASKxGROUP);

end


function [ y, m ] = month_carry_alexandrian ( y, m )

%*****************************************************************************80
%
%% MONTH_CARRY_ALEXANDRIAN carries a year of months on the Alexandrian calendar.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 July 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input/output, integer Y, M, the YM date.
%
  months = year_length_months_alexandrian ( y );

  while ( 1 )

    if ( m <= months )
      break
    end

    m = m - months;
    y = y + 1;

  end

  return
end


function bbox_reg = spp_train_bbox_regressor(imdb, roidb, spp_model, varargin)
% bbox_reg = spp_train_bbox_regressor(imdb, roidb, spp_model, varargin)
%   Trains a bounding box regressor on the image database imdb
%   for use with the SPP model spp_model. The regressor is trained
%   using ridge regression.
%
%   Keys that can be passed in:
%
%   min_overlap     Proposal boxes with this much overlap or more are used
%   layer           The CNN layer features to regress from (either 5, 6 or 7)
%   lambda          The regularization hyperparameter in ridge regression
%   robust          Throw away examples with loss in the top [robust]-quantile
%   binarize        Binarize features or leave as real values >= 0
%
% Adapted from spp code written by Ross Girshick
% AUTORIGHTS
% ---------------------------------------------------------
% Copyright (c) 2014, Shaoqing Ren
%
% This file is part of the SPP code and is available
% under the terms of the Simplified BSD License provided in
% LICENSE. Please retain this notice and LICENSE if you use
% this file (or any portion of it) in your project.
% ---------------------------------------------------------
% Copyright (c) 2014, Ross Girshick
%
% This file is part of the R-CNN code and is available
% under the terms of the Simplified BSD License provided in
% LICENSE. Please retain this notice and LICENSE if you use
% this file (or any portion of it) in your project.
% ---------------------------------------------------------

ip = inputParser;
ip.addRequired('imdb',       @iscell);
ip.addRequired('spp_model',  @isstruct);
ip.addParamValue('min_overlap', 0.5,   @isscalar);
ip.addParamValue('layer',       5,     @isscalar);
ip.addParamValue('lambda',      4000,  @isscalar);
ip.addParamValue('robust',      0,     @isscalar);
ip.addParamValue('binarize',    false, @islogical);

ip.parse(imdb, spp_model, varargin{:});
opts = ip.Results;
opts = rmfield(opts, 'spp_model');
opts = rmfield(opts, 'imdb');
opts.cache_name = spp_model.cache_name;

fprintf('\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n');
fprintf('Training options:\n');
disp(opts);
fprintf('~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n');

imdbs_name = cell2mat(cellfun(@(x) x.name, imdb, 'UniformOutput', false));
conf = spp_config('sub_dir', fullfile(opts.cache_name, imdbs_name));
clss = spp_model.classes;
num_clss = length(clss);

% ------------------------------------------------------------------------
% Get the average norm of the features
opts.feat_norm_mean = spp_feature_stats(imdb, roidb, opts.layer, spp_model);
fprintf('average norm = %.3f\n', opts.feat_norm_mean);
% ------------------------------------------------------------------------

% ------------------------------------------------------------------------
% Get all positive examples
imdbs_name = cell2mat(cellfun(@(x) x.name, imdb, 'UniformOutput', false));
save_file = sprintf('./cachedir/%s/%s/bbox_regressor_XY_layer_%d_overlap_%.5g.mat', ...
                    spp_model.cache_name, imdbs_name, opts.layer, opts.min_overlap);
try
  load(save_file);
  fprintf('Loaded saved positives from ground truth boxes\n');
catch
  [X, Y, O, C] = get_examples(spp_model, imdb, roidb, opts);
  save(save_file, 'X', 'Y', 'O', 'C', '-v7.3');
end
for i = 1:num_clss
  fprintf('%14s has %6d samples\n', spp_model.classes{i}, length(find(C == i)));
end
X = spp_poolX_to_fcX(X, opts.layer, spp_model, false);
X = spp_scale_features(X, opts.feat_norm_mean);
% ------------------------------------------------------------------------

% use ridge regression solved by cholesky factorization
method = 'ridge_reg_chol';

models = cell(num_clss, 1);
for i = 1:num_clss
  fprintf('Training regressors for class %s (%d/%d)\n', ...
      spp_model.classes{i}, i, num_clss);
  I = find(O > opts.min_overlap & C == i);
  Xi = X(:, I);
  if opts.binarize
    Xi = single(Xi > 0);
  end
  Yi = Y(I,:);
  Oi = O(I);
  Ci = C(I);

  % add bias feature
  Xi = cat(1, Xi, ones(1, size(Xi,2), class(Xi)));

  % Center and decorrelate targets
  mu = mean(Yi);
  Yi = bsxfun(@minus, Yi, mu);
  S = Yi'*Yi / size(Yi,1);
  [V, D] = eig(S);
  D = diag(D);
  T = V*diag(1./sqrt(D+0.001))*V';
  T_inv = V*diag(sqrt(D+0.001))*V';
  Yi = Yi * T;

  models{i}.mu = mu;
  models{i}.T = T;
  models{i}.T_inv = T_inv;

  models{i}.Beta = [ ...
    solve_robust(Xi, Yi(:,1), opts.lambda, method, opts.robust) ...
    solve_robust(Xi, Yi(:,2), opts.lambda, method, opts.robust) ...
    solve_robust(Xi, Yi(:,3), opts.lambda, method, opts.robust) ...
    solve_robust(Xi, Yi(:,4), opts.lambda, method, opts.robust)];
end
bbox_reg.models = models;
bbox_reg.training_opts = opts;
save([conf.cache_dir 'bbox_regressor_final'], 'bbox_reg');

% ------------------------------------------------------------------------
function [X, Y, O, C] = get_examples(spp_model, imdb, roidb, opts)
% ------------------------------------------------------------------------
num_classes = length(spp_model.classes);

cls_counts = zeros(num_classes, 1);
for idb = 1:length(imdb)
    for i = 1:length(imdb{idb}.image_ids)
      tic_toc_print('%s: counting %d/%d\n', ...
                    procid(), i, length(imdb{idb}.image_ids));

      d = roidb{idb}.rois(i);
      [max_ov cls] = max(d.overlap, [], 2);
      sel_ex = find(max_ov >= 0.5);
      cls = cls(sel_ex);
      for j = 1:length(sel_ex)
        cls_counts(cls(j)) = cls_counts(cls(j)) + 1;
      end
    end
end
total = sum(cls_counts);
feat_dim = size(spp_model.cnn.layers(1).weights{1},2);
% features
X = zeros(feat_dim, total, 'single');
% target values
Y = zeros(total, 4, 'single');
% overlap amounts
O = zeros(total, 1, 'single');
% classes
C = zeros(total, 1, 'single');
cur = 1;

for idb = 1:length(imdb)
    for i = 1:length(imdb{idb}.image_ids)
      tic_toc_print('%s: pos features %d/%d\n', ...
                    procid(), i, length(imdb{idb}.image_ids));
      d = roidb{idb}.rois(i);
      d.feat = spp_load_cached_poolX_features(spp_model.spp_pooler, spp_model.feat_cache{idb}, ...
          imdb{idb}.name, imdb{idb}.image_ids{i}, d.boxes);

      sel_gt = find(d.class > 0);
      gt_boxes = d.boxes(sel_gt, :);
      gt_classes = d.class(sel_gt);

      max_ov = max(d.overlap, [], 2);
      sel_ex = find(max_ov >= opts.min_overlap);
      ex_boxes = d.boxes(sel_ex, :);

      X(:, cur+(0:length(sel_ex)-1)) = d.feat(:, sel_ex);

      for j = 1:size(ex_boxes, 1)
        ex_box = ex_boxes(j, :);
        ov = boxoverlap(gt_boxes, ex_box);
        [max_ov, assignment] = max(ov);
        gt_box = gt_boxes(assignment, :);
        cls = gt_classes(assignment);

        src_w = ex_box(3) - ex_box(1) + eps;
        src_h = ex_box(4) - ex_box(2) + eps;
        src_ctr_x = ex_box(1) + 0.5*src_w;
        src_ctr_y = ex_box(2) + 0.5*src_h;

        gt_w = gt_box(3) - gt_box(1) + eps;
        gt_h = gt_box(4) - gt_box(2) + eps;
        gt_ctr_x = gt_box(1) + 0.5*gt_w;
        gt_ctr_y = gt_box(2) + 0.5*gt_h;

        dst_ctr_x = (gt_ctr_x - src_ctr_x) * 1/src_w;
        dst_ctr_y = (gt_ctr_y - src_ctr_y) * 1/src_h;
        dst_scl_w = log(gt_w / src_w);
        dst_scl_h = log(gt_h / src_h);

        target = [dst_ctr_x dst_ctr_y dst_scl_w dst_scl_h];

        if 0
          % debugging visualizations and checks
          im = imread(imdb.image_at(i));
          showboxesc(im, gt_box, 'g', '-');
          showboxesc([], ex_box, 'r', '-');
          hold on;
          plot(gt_ctr_x, gt_ctr_y, 'gd');
          plot(src_ctr_x, src_ctr_y, 'rd');
          hold off;
          fprintf('target = [%.3f %.3f %.3f %.3f]\n', target(1), target(2), target(3), target(4));
          fprintf('cls = %s\n', spp_model.classes{cls});

          % check that we can correctly reconstruct the gt_box from the
          % gold-standard target
          pred_ctr_x = (target(1) * src_w) + src_ctr_x;
          pred_ctr_y = (target(2) * src_h) + src_ctr_y;
          pred_w = exp(target(3)) * src_w;
          pred_h = exp(target(4)) * src_h;
          pred_box = [pred_ctr_x - 0.5*pred_w, pred_ctr_y - 0.5*pred_h, ...
                      pred_ctr_x + 0.5*pred_w, pred_ctr_y + 0.5*pred_h];
          disp(pred_box);
          disp(gt_box);
          assert(sum(abs(pred_box - gt_box)) < 0.0001);

          pause;
        end

        assert(cur <= total);
        Y(cur, :) = target;
        O(cur)    = max_ov;
        C(cur)    = cls;
        cur = cur + 1;
      end
    end
end

% ------------------------------------------------------------------------
function [x, losses] = solve_robust(A, y, lambda, method, qtile)
% ------------------------------------------------------------------------
[x, losses] = solve(A, y, lambda, method);
fprintf('loss = %.3f\n', mean(losses));
if qtile > 0
  thresh = quantile(losses, 1-qtile);
  I = find(losses < thresh);
  [x, losses] = solve(A(I,:), y(I), lambda, method);
  fprintf('loss (robust) = %.3f\n', mean(losses));
end

% ------------------------------------------------------------------------
function [x, losses] = solve(A, y, lambda, method)
% ------------------------------------------------------------------------

%tic;
switch method
case 'ridge_reg_chol'
  % solve for x in min_x ||Ax - y||^2 + lambda*||x||^2
  %
  % solve (A'A + lambdaI)x = A'y for x using cholesky factorization
  % R'R = (A'A + lambdaI)
  % R'z = A'y  :  solve for z  =>  R'Rx = R'z  =>  Rx = z
  % Rx = z     :  solve for x
  R = chol(A*A' + lambda*eye(size(A,1)));
  z = R' \ (A*y);
  x = R \ z;
case 'ridge_reg_inv'
  % solve for x in min_x ||Ax - y||^2 + lambda*||x||^2
  x = inv(A*A' + lambda*eye(size(A,1)))*A*y;
case 'ls_mldivide'
  % solve for x in min_x ||Ax - y||^2
  if lambda > 0
    warning('ignoring lambda; no regularization used');
  end
  x = A'\y;
end
%toc;
losses = 0.5 * (A'*x - y).^2;


function sdd = settings_detection_default()
% Default settings for detection.
sdd.thr_method = 'median'; % median, wavelet, plexon
sdd.side = 'negative'; % two, positive, negative, mean
sdd.spike_filter_type = 'butter';
sdd.spike_filter_order = 4;
sdd.spike_Rp = 300; % Hz
sdd.spike_Rs = 3000; % Hz
sdd.pre_thresh = 40; % samples
sdd.post_thresh = 59; % samples
sdd.dead_time = 20; % samples
sdd.sampling_rate = 40000; % sampling rate

write_arguments_to_json(sdd,'config_detection');


function h=convolve(f,g,varargin)
%CONVOLVE  Convolution
%   Usage:  h=convolve(f,g);
%
%   `convolve` has been deprecated. Please use |lconv| instead.
%
%   A call to `convolve(f,g)` can be replaced by ::
%
%     lconv(f,g);
%
%   See also: lconv

warning(['LTFAT: CONVOLVE has been deprecated, please use LCONV ' ...
         'instead. See the help on LCONV for more details.']);

if nargin<2
  error('%s: Too few input parameters.',upper(mfilename));
end;

definput.keyvals.L=[];
definput.keyvals.dim=[];

[flags,kv,L,dim]=ltfatarghelper({'L','dim'},definput,varargin);

[f,L1,Lf,Wf,dimout,permutedsize_f,order_f]=assert_sigreshape_pre(f,L,dim,'CONVOLVE');
[g,L2,Lg,Wg,dimout,permutedsize_g,order_g]=assert_sigreshape_pre(g,L,dim,'CONVOLVE');

Lh=Lf+Lg-1;

if (Wf>1) && (Wg>1)
  error('%s: Only one of the inputs can be multi-dimensional.',upper(mfilename));
end;

W=max(Wf,Wg);
if Wf<W
  f=repmat(f,1,W);
end;

if Wg<W
  g=repmat(g,1,W);
end;

if isreal(f) && isreal(g)
  h=comp_ifftreal(comp_fftreal(postpad(f,Lh)).*...
                  comp_fftreal(postpad(g,Lh)),Lh);
else
  h=ifft(fft(postpad(f,Lh)).*...
         fft(postpad(g,Lh)));

end;


function [ know, x ] = p13_sol ( n )

%*****************************************************************************80
%
%% P13_SOL returns the solution for problem 13.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 March 2000
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the problem.  This value
%    is only needed for those problems with variable N.
%
%    Output, integer KNOW.
%    If KNOW is 0, then the solution is not known.
%    If KNOW is positive, then the solution is known, and is returned in X.
%
%    Output, real X(N), the solution, if known.
%
  know = 0;

  x = zeros ( n, 1 );

  return
end


function X=rectsample(N)

X=rand(N,2);
X=X+repmat([-0.5,-0.5],N,1);


function drawRobotStopAction(q,p)
% drawRobotStopAction(q,p)
%
% This function draws the robot with configuration q and parameters p over
% a series of configurations, leaving hold on so that the motion can be
% seen in a single (static) frame.
%
% INPUTS:
%   q = [5, 1] = column vector of a single robot configuration
%   p = parameter struct
%

nTime = size(q,2);

% Compute the points that will be used for plotting
[P, G] = getPoints(q,p);

x = [zeros(1,nTime); P(1:2:end,:)];
y = [zeros(1,nTime); P(2:2:end,:)];

P1 = P(1:2,:);
P2 = P(3:4,:);
P3 = P(5:6,:);
P4 = P(7:8,:);
P5 = P(9:10,:);

% G1 = G(1:2,:);
% G2 = G(3:4,:);
% G3 = G(5:6,:);
% G4 = G(7:8,:);
% G5 = G(9:10,:);

% Heuristics:
L = (p.l1 + p.l2);  % Maximum extended leg length
xBnd = L*[-1.2,1.2];
yBnd = [-0.2*L, L + p.l3];

% Colors:
colorGround = [118,62,12]/255;
colorStance = [200,60,60]/255;
colorSwing = [60,60,200]/255;
colorTorso = [160, 80, 160]/255;

% Plot parameters:
legWidth = 2;
jointSize = 20;

% Set up the figure
hold off;

% Plot the ground:
plot(xBnd,[0,0],'LineWidth',6,'Color',colorGround);

hold on;

% Plot the links:
for i=1:nTime
plot(x(1:3,i),y(1:3,i),'--','LineWidth',legWidth,'Color',colorStance);
plot(0, 0,'k.','MarkerSize',jointSize,'Color',colorStance);
plot(P1(1,i), P1(2,i),'k.','MarkerSize',jointSize,'Color',colorStance);
plot(P2(1,i), P2(2,i),'k.','MarkerSize',jointSize,'Color',colorStance);
% plot(G1(1,i), G1(2,i),'ko','MarkerSize',8,'LineWidth',2);
% plot(G2(1,i), G2(2,i),'ko','MarkerSize',8,'LineWidth',2);
end
for i=1:nTime
plot(x(3:4,i),y(3:4,i),'LineWidth',legWidth+1,'Color',colorTorso);
plot(P3(1,i), P3(2,i),'k.','MarkerSize',jointSize,'Color',colorTorso);
% plot(G3(1,i), G3(2,i),'ko','MarkerSize',8,'LineWidth',2,'Color',colorTorso);
end
for i=1:nTime
plot(x([3,5,6],i),y([3,5,6],i),'LineWidth',legWidth,'Color',colorSwing);
plot(P4(1,i), P4(2,i),'k.','MarkerSize',jointSize,'Color',colorSwing);
plot(P5(1,i), P5(2,i),'k.','MarkerSize',jointSize,'Color',colorSwing);
% plot(G4(1,i), G4(2,i),'ko','MarkerSize',8,'LineWidth',2,'Color',colorSwing);
% plot(G5(1,i), G5(2,i),'ko','MarkerSize',8,'LineWidth',2,'Color',colorSwing);
end

% Format the axis:
axis([xBnd,yBnd]); axis equal; axis off;

end


function dramap_z(STYLE, bg_color, value_map)
    % drap a colormap of variance, S1 orientation onto topography
    %
    % requires:
    %   tmap : topography map
    %   tmapleg :
    %   gx, gy
    %   s1_north...s4_south

    assert(ismember(STYLE, {'dramap2_z','dramap_z','stress2'}));

    report_this_filefun();

    % STYLE simply allows this function to merge functionality of
    % two versions...
    %STYLE = "dramap2_z";
    %STYLE = "stress2";
    STYLE = "dramap_z";
    USE_SCALE_RULER = false; % SCALE_RULER code was commmented out in dramap_z and dramap_stress2.
                             % and didn't exist in dramap_z

    if ~has_mapping_toolbox()
        return
    end

    if ~exist('tmap', 'var')
        tmap = 0;
    end
    [xx, yy] = size(tmap);
    if xx*yy < 30
        errordlg('Please create a topomap first, using the options from the seismicity map window');
        return
    end
    if STYLE == "dramap2_z"
        projections = {... % friendly name      , official
            'Albers Equal-Area Conic'           , 'equaconic';...
            'Mercator Projection'               , 'mercator';...
            'Plate Carree Projection'           , 'pcarree'; ...
            'Lambert Conformal Conic Projection', 'lambert';...
            'Robinson Projection'               , 'robinson'};
        selz = menu('Choose a projection', projections{:,1});
        selected_proj = projections{selz, 2}; % was 'mapz(...)'
        mic_offset = 0.1;
    else
        selected_proj = 'eqaconic';
        mic_offset = 0;
    end

    dlgtitle ='Topo map input parameters';
    dstr(1).prompt = 'Longitude label spacing (degrees)';   dstr(1).value = 1;
    dstr(2).prompt = 'Latitude label spacing (degrees)';    dstr(2).value = 1;
    dstr(3).prompt = 'Topo data-aspect (steepness)';        dstr(3).value = 5;
    dstr(4).prompt = ' Minimum datavalue (cmin)';           dstr(4).value = min(value_map(:));
    dstr(5).prompt = ' Maximum datavalue cmap';             dstr(5).value = max(value_map(:));
    dstr(6).prompt = ' Sea Level (set values below this to 0. ex 0.01)';     dstr(6).value = -inf;

    [~, ~, dlo, dla, dda, mic, mac, sealevel] = smart_inputdlg(dlgtitle, dstr);

    % use this for setting water levels to one color
    %tmap(isnan(tmap)) = 1;

    tmap(tmap < sealevel) = 0;

    value_map(value_map < mic) = mic + mic_offset;
    value_map(value_map > mac) = mac;

    [lat, lon] = meshgrat(tmap, tmapleg);
    [X , Y]  = meshgrid(gx, gy);

    ren = interp2(X, Y, value_map, lon, lat);

    ren(isnan(ren)) = min(ren(:)) - 20;

    if STYLE == "dramap2_z"
        ren(tmap <= 1 & ren < mic) = nan;
    end

    %start figure
    fig = figure_w_normalized_uicontrolunits('pos', [50 100 800 600]);
    ax = gca;
    set(ax, 'NextPlot', 'add');
    axis off
    axesm('MapProjection', selected_proj, 'MapParallels', [],...
        'MapLatLimit', [s4_south s3_north], 'MapLonLimit', [s2_west s1_east])

    meshm(ren, tmapleg, size(tmap), tmap);

    daspectm('m', dda);
    tightmap
    view([0 90])
    camlight;
    lighting phong
    set(ax, 'projection', 'perspective');

    if STYLE == "stress2"
        % plot the bars
        plq = quiverm(newgri(:,2), newgri(:,1), -cos(ste(:,SA*2)*pi/180), sin(ste(:,SA*2)*pi/180),0.9);
        set(plq,'LineWidth', 0.4, 'Color', 'k', 'Markersize',0.1);
        set(gca,'NextPlot', 'add');

        delete(plq(2));
    end

    if STYLE == "dramap2_z" || STYLE == "stress2"
        if ~isempty(coastline)
            pl = plotm(coastline(:,2), coastline(:,1), 'k');
            set(pl, 'LineWidth', 0.5)
        end

        if ~isempty(ZG.maepi)
            pl = plotm(ZG.maepi.Y, ZG.maepi.X, 'hw');
            set(pl,'LineWidth', 1, 'MarkerSize', 14,...
                'MarkerFaceColor', 'w', 'MarkerEdgeColor', 'k')
        end
        if STYLE == "stress2"
            zdatam(handlem('allline'), max(tmap(:))) % keep line on surface
        end

        j = jet(64); % different from dramap2_z
        j = [ [ 0.8 0.8 0.8 ] ; j  ];
    else
        j = colormap;
        j = [ [ 0.9 0.9 0.9 ] ; j];
    end

    caxis([ mic * 0.99, mac * 1.01 ]);
    colormap(j);
    brighten(0.1);
    axis off;

    setm(ax,'mlabellocation', dlo)
    setm(ax,'meridianlabel', 'on')
    setm(ax,'plabellocation', dla)
    setm(ax,'parallellabel', 'on')

    if ~exist('bg_color', 'var') || bg_color == 'w' % white background
        fg = 'k';
        bg = 'w';
    else  % black background
        fg = 'w';
        bg = 'k';
    end

    set(fig, 'color', bg)
    setm(ax, 'ffacecolor', bg)
    setm(ax, 'fedgecolor', fg, 'flinewidth', 3);

    % change the labels if needed
    setm(ax,'Fontcolor', fg, 'Fontweight', 'bold', 'FontSize', 12, 'Labelunits', 'dm')

    h5 = colorbar;
    set(h5,'position',[0.8 0.35 0.01 0.3], 'TickDir', 'out', 'Ycolor', fg, 'Xcolor', fg,...
        'Fontweight', 'bold', 'FontSize', 12);
    set(fig, 'Inverthardcopy', 'off');

    if USE_SCALE_RULER
        scaleruler
        if STYLE == "dramap2_z"
            XLoc = -0.0133;
            YLoc = 0.639;
            MajorTick = 0:10:50;
            majorTickLength = 4;
        elseif STYLE == "stress2"
            XLoc = 12;
            YLoc = 40;
            MajorTick = 0:50:200;
            majorTickLength = 12;
        end

        setm(handlem('scaleruler1'), 'XLoc', XLoc, 'YLoc', YLoc, 'units', 'km')
        setm(handlem('scaleruler2'),'MajorTick', MajorTick,...
                'MinorTick', 0:10:25, 'TickDir', 'down',...
                'MajorTickLength', majorTickLength,...
                'MinorTickLength', 4)

        setm(handlem('scaleruler1'), 'RulerStyle', 'ruler')
        if STYLE == "dramap2_z"
            setm(handlem('scaleruler2'), 'RulerStyle', 'patches')
        end
        refresh
    end
end


function prediction = AlexNet(varargin)
%AlexNet Returns an AlexNet model for ImageNet
%   M = models.AlexNet() returns the model proposed in:
%
%     Krizhevsky et al., "ImageNet classification with deep convolutional
%     neural networks", NIPS 2012.
%
%   models.AlexNet(..., 'option', value, ...) accepts the following
%   options:
%
%   `pretrained`:: false
%     If true, returns a model pre-trained on ImageNet (using the
%     MatConvNet example code).
%
%   `input`:: default input
%     Specifies an input (images) layer for the network. If unspecified, a
%     new one is created.
%
%   `numClasses`:: 1000
%     Number of output classes.
%
%   `batchNorm`:: true
%     Whether to use batch normalization.
%
%   `normalization`:: [5 1 0.0001/5 0.75]
%     Parameters for vl_nnnormalize layer (only used without batch-norm).
%
%   Any other options will be passed to models.ConvBlock(), and can be used
%   to change the activation function, weight initialization, etc.
%
%   Suggested SGD training options are also returned in the struct M.meta.

% Copyright (C) 2018 Joao F. Henriques, Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

  % parse options. unknown arguments will be passed to ConvBlock (e.g.
  % activation).
  opts.pretrained = false ;  % whether to fetch a pre-trained model
  opts.input = Input('name', 'images', 'gpu', true) ;  % default input layer
  opts.numClasses = 1000 ;  % number of predicted classes
  opts.batchNorm = true ;  % whether to use batch normalization
  opts.normalization = [5 1 0.0001/5 0.75] ;  % for LRN layer (vl_nnnormalize)
  [opts, convBlockArgs] = vl_argparse(opts, varargin, 'nonrecursive') ;

  % default training options for this network (returned as output.meta)
  meta.batchSize = 256 ;
  meta.imageSize = [227, 227, 3] ;
  meta.augmentation.crop = 227 / 256;
  meta.augmentation.location = true ;
  meta.augmentation.flip = true ;
  meta.augmentation.brightness = 0.1 ;
  meta.augmentation.aspect = [2/3, 3/2] ;
  meta.weightDecay = 0.0005 ;

  % the default learning rate schedule
  if ~opts.pretrained
    if ~opts.batchNorm
      meta.learningRate = logspace(-2, -4, 60) ;
    else
      meta.learningRate = logspace(-1, -4, 20) ;
    end
    meta.numEpochs = numel(meta.learningRate) ;
  else  % fine-tuning has lower LR
    meta.learningRate = 1e-5 ;
    meta.numEpochs = 20 ;
  end

  % return a pre-trained model
  if opts.pretrained
    if opts.batchNorm
      warning('The pre-trained model does not include batch-norm (set batchNorm to false).') ;
    end
    if opts.numClasses ~= 1000
      warning('Model options are ignored when loading a pre-trained model.') ;
    end
    prediction = models.pretrained('imagenet-matconvnet-alex') ;

    % return prediction layer (not softmax)
    assert(isequal(prediction{1}.func, @vl_nnsoftmax)) ;
    prediction = prediction{1}.inputs{1} ;

    % replace input layer with the given one
    input = prediction.find('Input', 1) ;
    prediction.replace(input, opts.input) ;

    prediction.meta = meta ;
    return
  end

  % get conv block generator with the given options. default activation is
  % ReLU, with pre-activation batch normalization (can be overriden).
  conv = models.ConvBlock('batchNorm', opts.batchNorm, ...
    'preActivationBatchNorm', true, 'weightScale', 0.01, convBlockArgs{:}) ;

  % build network
  images = opts.input ;

  % first conv block
  x = conv(images, 'size', [11, 11, 3, 96], 'stride', 4) ;
  if ~opts.batchNorm
    x = vl_nnnormalize(x, opts.normalization) ;
  end
  x = vl_nnpool(x, 3, 'stride', 2) ;

  % second conv block
  x = conv(x, 'size', [5, 5, 48, 256], 'pad', 2) ;
  if ~opts.batchNorm
    x = vl_nnnormalize(x, opts.normalization) ;
  end
  x = vl_nnpool(x, 3, 'stride', 2) ;

  % conv blocks 3-5
  x = conv(x, 'size', [3, 3, 256, 384], 'pad', 1) ;
  x = conv(x, 'size', [3, 3, 192, 384], 'pad', 1) ;
  x = conv(x, 'size', [3, 3, 192, 256], 'pad', 1) ;
  x = vl_nnpool(x, 3, 'stride', 2) ;

  % first fully-connected block
  x = conv(x, 'size', [6, 6, 256, 4096]) ;
  if ~opts.batchNorm
    x = vl_nndropout(x) ;
  end

  % second fully-connected block
  x = conv(x, 'size', [1, 1, 4096, 4096]) ;
  if ~opts.batchNorm
    x = vl_nndropout(x) ;
  end

  % prediction layer
  prediction = conv(x, 'size', [1, 1, 4096, opts.numClasses], ...
    'batchNorm', false, 'activation', 'none') ;

  prediction.meta = meta ;

end


function [a]=minus(b,c)
%A=B-C
%   [A]=MINUS(B,C) Subtraction of two tensors
%
%Adds two TT-tensors B and C
%
%
% TT-Toolbox 2.2, 2009-2012
%
%This is TT Toolbox, written by Ivan Oseledets et al.
%Institute of Numerical Mathematics, Moscow, Russia
%webpage: http://spring.inm.ras.ru/osel
%
%For all questions, bugs and suggestions please mail
%ivan.oseledets@gmail.com
%---------------------------

a=b+(-1.0)*c;
return
end