function M = decode_qform0(hdr)
% Decode qform info from NIFTI-1 headers.
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id$

dim    = double(hdr.dim);
pixdim = double(hdr.pixdim);
if ~isfield(hdr,'magic') || hdr.qform_code <= 0,
    flp = spm_flip_analyze_images;
    %disp('------------------------------------------------------');
    %disp('The images are in a form whereby it is not possible to');
    %disp('tell the left and right sides of the brain apart.');
    %if flp,
    %    disp('They are assumed to be stored left-handed.');
    %else
    %    disp('They are assumed to be stored right-handed.');
    %end;
    %disp('------------------------------------------------------');

    %R     = eye(4);
    n      = min(dim(1),3);
    vox    = [pixdim(2:(n+1)) ones(1,3-n)];

    if ~isfield(hdr,'origin') || ~any(hdr.origin(1:3)),
       origin = (dim(2:4)+1)/2;
    else
        origin = double(hdr.origin(1:3));
    end;
    off     = -vox.*origin;
    M       = [vox(1) 0 0 off(1) ; 0 vox(2) 0 off(2) ; 0 0 vox(3) off(3) ; 0 0 0 1];

    % Stuff for default orientations
    if flp, M = diag([-1 1 1 1])*M; end;
else

    % Rotations from quaternions
    R = Q2M(double([hdr.quatern_b hdr.quatern_c hdr.quatern_d]));

    % Translations
    T = [eye(4,3) double([hdr.qoffset_x hdr.qoffset_y hdr.qoffset_z 1]')];

    % Zooms.  Note that flips are derived from the first
    % element of pixdim, which is normally unused.
    n = min(dim(1),3);
    Z = [pixdim(2:(n+1)) ones(1,4-n)];
    Z(Z<0) = 1;
    if pixdim(1)<0, Z(3) = -Z(3); end;
    Z = diag(Z);

    M = T*R*Z;

    % Convert from first voxel at [1,1,1]
    % to first voxel at [0,0,0]
    M = M * [eye(4,3) [-1 -1 -1 1]'];
end;
return;


function [mean_m1, b1, sig1, av2] =  bmemag(mag);
    %BMEMAG
    maximum_mag = max(mag );
    minimum_mag = min(mag );
    if minimum_mag > 0 ; minimum_mag = 0 ; end

    % calculate the mean magnitude, b(mean) and std
    n = length(mag );
    mean_m1 = mean(mag );
    b1 = (1/(mean_m1-min(mag -0.05)))*log10(exp(1));
    sig1 = (sum((mag -mean_m1).^2))/(n*(n-1));
    sig1 = sqrt(sig1);
    sig1 = 2.30*sig1*b1^2;            % standard deviation
    %disp ([' b-value segment 1 = ' num2str(b1) ]);
    %disp ([' standard dev b_val_1 = ' num2str(sig1) ]);
    av2 = log10(length(mag ))+b1*min(mag );
end


classdef L2N < dagnn.Filter
% L2N layer that is L2-normalizing input vectors
%
% Authors: F. Radenovic, G. Tolias, O. Chum. 2017.

  methods
    function outputs = forward(self, inputs, params)
      outputs{1} = vl_nnnormalizelp(inputs{1}, 'p', 2, 'epsilon', 1e-6);
    end

    function [derInputs, derParams] = backward(self, inputs, params, derOutputs)
      derInputs{1} = vl_nnnormalizelp(inputs{1}, derOutputs{1}, 'p', 2, 'epsilon', 1e-6);
      derParams = {} ;
    end

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


%Program for Construction of a two-out-of-two Visual Cryptography Scheme

%Author : Athi Narayanan S
%M.E, Embedded Systems,
%K.S.R College of Engineering
%Erode, Tamil Nadu, India.
%http://sites.google.com/site/athisnarayanan/
%s_athi1983@yahoo.co.in

%Program Description
%This program generates a two-out-of-two Visual Cryptography Scheme shares.
%The input image for this program should be a binary image.
%The shares and the overlapping result of the shares are written as output.
%
%Usage:
%Input: inImg - A binary image
%Output: share1  - Generated share 1
%        share2  - Generated share 2
%        share12 - Overlapped result of shares 1 & 2

function [share1, share2, share12] = VisCrypt(inImg)

s = size(inImg);
share1 = zeros(s(1), (2 * s(2)));
share2 = zeros(s(1), (2 * s(2)));

%%White Pixel Processing
%White Pixel share combinations
disp('White Pixel Processing...');
s1a=[1 0];
s1b=[1 0];
[x y] = find(inImg == 1);
len = length(x);

for i=1:len
    a=x(i);b=y(i);
    pixShare=generateShare(s1a,s1b);
    share1((a),(2*b-1):(2*b))=pixShare(1,1:2);
    share2((a),(2*b-1):(2*b))=pixShare(2,1:2);
end

%Black Pixel Processing
%Black Pixel share combinations
disp('Black Pixel Processing...');
s0a=[1 0];
s0b=[0 1];
[x y] = find(inImg == 0);
len = length(x);

for i=1:len
    a=x(i);b=y(i);
    pixShare=generateShare(s0a,s0b);
    share1((a),(2*b-1):(2*b))=pixShare(1,1:2);
    share2((a),(2*b-1):(2*b))=pixShare(2,1:2);
end

share12=bitor(share1, share2);
share12 = ~share12;
disp('Share Generation Completed.');


function Population = ArchiveUpdate(Population,N)
% Update archive

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

    %% Select feasible solutions
    fIndex     = all(Population.cons <= 0,2);
    Population = Population(fIndex);
    if isempty(Population)
        return
    else
        if size(Population.objs,2)==2
            %% Non-dominated sorting
            [FrontNo,~] = NDSort(Population.objs,1);
            Next = (FrontNo == 1);
            Population = Population(Next);
            if sum(Next) > N
                %% Calculate the crowding distance of each solution
                CrowdDis   = CrowdingDistance(Population.objs);
                [~,Rank]   = sort(CrowdDis,'descend');
                Population = Population(Rank(1:N));
            end
        else
            Population = Population(NDSort(Population.objs,1)==1);
            Population = Population(randperm(length(Population)));
            PCObj = Population.objs;
            nND   = length(Population);
            %% Population maintenance
            if length(Population) > N
                % Normalization
                fmax  = max(PCObj,[],1);
                fmin  = min(PCObj,[],1);
                PCObj = (PCObj-repmat(fmin,nND,1))./repmat(fmax-fmin,nND,1);
                % Determine the radius of the niche
                d  = pdist2(PCObj,PCObj);
                d(logical(eye(length(d)))) = inf;
                sd = sort(d,2);
                r  = mean(sd(:,min(3,size(sd,2))));
                R  = min(d./r,1);
                % Delete solution one by one
                while length(Population) > N
                    [~,worst]  = max(1-prod(R,2));
                    Population(worst)  = [];
                    R(worst,:) = [];
                    R(:,worst) = [];
                end
            end
        end
    end
end


function plotData(X, y)
%PLOTDATA Plots the data points X and y into a new figure
%   PLOTDATA(x,y) plots the data points with + for the positive examples
%   and o for the negative examples. X is assumed to be a Mx2 matrix.

% Create New Figure
figure; hold on;

% ====================== YOUR CODE HERE ======================
% Instructions: Plot the positive and negative examples on a
%               2D plot, using the option 'k+' for the positive
%               examples and 'ko' for the negative examples.
%

pos = find(y == 1);
neg = find(y == 0);
plot(X(pos, 1), X(pos, 2), 'k+' ,'LineWidth', 2, 'MarkerSize', 7);
plot(X(neg, 1), X(neg, 2), 'ko', 'MarkerFaceColor', 'y', 'MarkerSize', 7);

% =========================================================================

hold off;

end


%==============================================================================
% This code is part of the Finite Element Method app for the Matlab-based toolbox
%  FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR/FAIRFEM
%==============================================================================
%
% classdef TriMesh3 < handle
%
% Finite Element Mesh based on triangular subdivision of rectangular mesh.
%
% Each Cell is divided into four triangles:
%
%  o---------o---------o---------o---------o
%  | \     / | \     / | \     / | \     / |
%  |   \ /   |   \ /   |   \ /   |   \ /   |
%  |    X    |    X    |    X    |    X    |
%  |  /  \   |  /  \   |  /  \   |  /  \   |
%  |/      \ |/      \ |/      \ |/      \ |
%  o---------o---------o---------o---------o
%  | \     / | \     / | \     / | \     / |
%  |   \ /   |   \ /   |   \ /   |   \ /   |
%  |    X    |    X    |    X    |    X    |
%  |  /  \   |  /  \   |  /  \   |  /  \   |
%  |/      \ |/      \ |/      \ |/      \ |
%  o---------o---------o---------o---------o
%  | \     / | \     / | \     / | \     / |
%  |   \ /   |   \ /   |   \ /   |   \ /   |
%  |    X    |    X    |    X    |    X    |
%  |  /  \   |  /  \   |  /  \   |  /  \   |
%  |/      \ |/      \ |/      \ |/      \ |
%  o---------o---------o---------o---------o
%
%  To construct an instance of this class type:
%
%  >> Mesh = TriMesh3(omega,m)
%
% Input:
% 	omega - description of spatial domain
%   m     - number of cells
%
% Properties:
%   xn     - node list
%   tri    - triangle list
%   dim    - space dimension
%   omega  - description of spatial domain
%   m      - number of cells
%   type   - type of partition
%   vol    - volume of triangles
%   nnodes - number of nodes
%   ntri   - number of triangles
%   dx1    - partial derivative operator
%   dx2    - partial derivative operator
%   GRAD   - gradient operator
%   P1     - projection operator for node 1
%   P2     - projection operator for node 2
%   P3     - projection operator for node 3
%   PC     - projection operator for Barycentrum
%   P      - prolongation operator
%   Pt     - restriction operator
%
%  Methods:
%   mfPu   - matrix free prolongation/restriction
%   mfPi   - matrix free edge projector
%   getP   - builds prolongation operator
%   tri2cc - averaging
%
%
% see also
% =========================================================================
classdef TriMesh3 < handle

    properties
        % ===================================
        % node list
        % ===================================
        xn
        % ===================================
        % triangle list
        % ===================================
        tri
        % ===================================
        % space dimension
        % ===================================
        dim  = 2;
        % ===================================
        % description of computational domain
        % ===================================
        omega
        % ===================================
        % number of cells
        % ===================================
        m
        % ===================================
        % type of partition
        % ===================================
        type = 3;
        % ===================================
        % function handle to myself
        % ===================================
        me = @TriMesh3
        % ===================================
        % volume of triangles
        % ===================================
        vol
        % ===================================
        % number of nodes
        % ===================================
        nnodes
        % ===================================
        % number of triangles in mesh
        % ===================================
        ntri
    end

    properties (Access = public, Dependent) % These will be created when first callend and stores persistently
        % ===================================
        % dx1  - partial derivative operator
        % ===================================
        dx1
        % ===================================
        % dx2  - Partial derivative operator
        % ===================================
        dx2
        % ===================================
        % GRAD - Gradient operator
        %
        %         | dx1 |
        %  GRAD = |     |
        %         | dx2 |
        %
        % ===================================
        GRAD
        % ===================================
        % B - Vector gradient operator
        %
        %         | GRAD  0    |
        %  B =    |            |
        %         | 0     GRAD |
        %
        % ===================================
        B
        % ===================================
        % P1 - Projection operator on Node 1
        % ===================================
        P1
        % ===================================
        % P2 - Projection operator on Node 2
        % ===================================
        P2
        % ===================================
        % P3 - Projection operator on Node 3
        % ===================================
        P3
        % ===================================
        % PC - Projection operator on Barycenter
        % ===================================
        PC
        % ===================================
        % P  - Prolongation operator
        % ===================================
        P
        % ===================================
        % Pt - Restriction operator
        % ===================================
        Pt
        % ===================================
        % Boundary indices
        % ===================================
        boundaryIdx
        % ===================================
        % Boundary projector
        % ===================================
        boundaryProj
        AvN
        mfdx1
        mfdx2
        mfGRAD
    end

    properties (Access = private)
        % These are where the dependent data is actually stored
        dx1_
        dx2_
        GRAD_
        B_
        P1_
        P2_
        P3_
        PC_
        P_
        Pt_
        mfdx1_
        mfdx2_
        mfGRAD_
        boundaryIdx_
        boundaryProj_
        AvN_
    end

    methods
        function this = TriMesh3(omega,m)
            if nargin==0,
                help(mfilename);
                this.runMinimalExample;
                return;
            end
            this.omega = omega;
            this.m     = m;

            this.xn = [ reshape(getNodalGrid(omega,m),[],2);...
               reshape(getCellCenteredGrid(omega,m),[],2)];

            % get indices of bottom left vertices
            nodes = reshape(1:prod(m+1),m+1);
            nodes = reshape(nodes(1:end-1,1:end-1),1,[]);
            % get indices of cell-centered points
            cc    = prod(m+1)+(1:prod(m));
            % specify triangles
            this.tri   = [...
                nodes;          nodes+1;        cc; ...
                nodes+1;        nodes+m(1)+2;   cc; ...
                nodes+m(1)+2;   nodes+m(1)+1;   cc; ...
                nodes+m(1)+1;   nodes;          cc; ...
                ];
            this.tri   = reshape(this.tri,3,[])';

            this.nnodes = prod(m+1)+prod(m);
            this.ntri  = size(this.tri,1);
            this.vol = prod((omega(2:2:end)-omega(1:2:end))./m)/4*ones(this.ntri,1);

        end

        function runMinimalExample(~)
            omega = [0 4 2 6]; m = [3 6];
            Mesh  = feval(mfilename,omega,m);
            figure(3); clf;
            set(gcf,'Name',sprintf('%s, m=[%d,%d]',mfilename,m));
            plotTriMesh(Mesh,Mesh.xn);
        end

        function x = mfPi(this,x,i)
            % =============================================================
            % function x = mfPi(this,x,i)
            %
            % matrix free edge projector
            % =============================================================
            switch i
                case 1
                    P = this.P1;
                case 2
                    P = this.P2;
                case 3
                    P = this.P3;
                case 'C'
                    P = this.PC;
            end
            if size(x,1) == this.ntri,
                % ajoint
                x = P'*x;
            else
                x = P * x;
            end
        end

        function x = tri2cc(this,x)
            % =============================================================
            % function x = tri2cc(x)
            %
            % averaging or adjoint
            % =============================================================
            if numel(x)==this.ntri,
                x = mean(reshape(x,4,[]),1);
            else
                x = reshape(x,1,[]);
                x = .25*repmat(x,[1 4]);
                x = x(:);
            end

        end

        % ===================================
        % x = getNodalGridData(this,x)
        %
        % gets values at triangle nodes that belong the underlying nodal
        % grid
        % ===================================
        function x = getNodalGridData(this,x)
            x = reshape(x,prod(this.nnodes),[]);
            x = x(1:prod(this.m+1),:);
            x = x(:);
        end

        % ===================================
        % x = getCCGridData(this,x)
        %
        % gets values at cell-centers that belong the underlying nodal
        % grid
        % ===================================
        function x = getCCGridData(this,x)
            x = reshape(x,prod(this.nnodes),[]);
            x = x(prod(this.m+1)+1:end,:);
            x = x(:);
        end

        function Pu = mfPuNodal(~,yn,m,flag)
            % =============================================================
            % function Pu = mfPuNodal(~,yn,m,flag)
            %
            % matrix free prolongation/restriction for nodal quantities
            % =============================================================
            switch flag
                case 'Pu' % coarse --> fine
                    yn = reshape(yn,[],2);
                    yc = reshape(yn(prod(m+1)+1:end,:),[m 2]);
                    yn = reshape(yn(1:prod(m+1),:),[m+1 2]);

                    Pyn = zeros([2*m+1 2]);
                    Pyc = zeros([2*m 2]);

                    % include existing nodes
                    Pyn(1:2:end,1:2:end,:) = yn;
                    % prolongate in x direction
                    Pyn(2:2:end-1,:,:) =  .5*(Pyn(1:2:end-2,:,:) + Pyn(3:2:end,:,:));
                    % prolongate in y direction
                    Pyn(1:2:end,2:2:end-1,:) =  .5*(Pyn(1:2:end,1:2:end-2,:) + Pyn(1:2:end,3:2:end,:));
                    % midpoints
                    Pyn(2:2:end,2:2:end,:)   = yc;

                    % compute cell-centers
                    Pyc(1:2:end-1,1:2:end-1,:) = .5*(yn(1:end-1,1:end-1,:) + yc);
                    Pyc(2:2:end  ,1:2:end-1,:) = .5*(yn(2:end  ,1:end-1,:) + yc);
                    Pyc(1:2:end-1,2:2:end  ,:) = .5*(yn(1:end-1,2:end  ,:) + yc);
                    Pyc(2:2:end  ,2:2:end  ,:) = .5*(yn(2:end  ,2:end  ,:) + yc);

                    Pu = [reshape(Pyn,[],2); reshape(Pyc,[],2)];
                    Pu = Pu(:);
                case 'PTu'
                    yn = reshape(yn,[],2);
                    yc = reshape(yn(prod(m+1)+1:end,:),[m 2]);
                    yn = reshape(yn(1:prod(m+1),:),[m+1 2]);

                    % include parent nodes
                    Pyn = yn(1:2:end,1:2:end,:);
                    % distribute in x direction
                    t = .5* yn(2:2:end-1,1:2:end,:);
                    Pyn(1:end-1,:,:)   = Pyn(1:end-1,:,:) + t;
                    Pyn(2:end  ,:,:)   = Pyn(2:end  ,:,:) + t;

                    % distribute in y direction
                    t = .5* yn(1:2:end,2:2:end-1,:);
                    Pyn(:,1:end-1,:) = Pyn(:,1:end-1,:) + t;
                    Pyn(:,2:end  ,:) = Pyn(:,2:end  ,:) + t;

                    % distribute cell-centers
                    t1 = .5*yc(1:2:end-1,1:2:end-1,:);
                    t2 = .5*yc(2:2:end  ,1:2:end-1,:);
                    t3 = .5*yc(1:2:end-1,2:2:end  ,:);
                    t4 = .5*yc(2:2:end  ,2:2:end  ,:);
                    Pyc = yn(2:2:end,2:2:end,:) + (t1+t2+t3+t4);
                    Pyn(1:end-1,1:end-1,:) = Pyn(1:end-1,1:end-1,:) + t1;
                    Pyn(2:end  ,1:end-1,:) = Pyn(2:end  ,1:end-1,:) + t2;
                    Pyn(1:end-1,2:end  ,:) = Pyn(1:end-1,2:end  ,:) + t3;
                    Pyn(2:end  ,2:end  ,:) = Pyn(2:end  ,2:end  ,:) + t4;

                    Pu = [reshape(Pyn,[],2); reshape(Pyc,[],2)];
                    Pu = Pu(:);
            end
        end

        function P = getPuNodal(~,m)
            % =============================================================
            % function P = getPuNodal(~,m)
            %
            % returns prolongation operator for input of cell-width m
            % =============================================================

            mf = 2*m;
            % indices of fine and coarse grid nodes
            indfn = reshape(1:prod(mf+1),mf+1);
            indfc = reshape(prod(mf+1)+(1:prod(mf)),mf);
            indcn = reshape(1:prod(m+1),m+1);
            indcc = reshape(prod(m+1)+(1:prod(m)),m);

            % allocate space
            I = []; J = []; W = [];

            % include existing nodes
            ii = indfn(1:2:end,1:2:end);
            jj = indcn(:);
            ww = ones(size(jj));
            I = [I; ii(:)]; J = [J; jj(:)]; W = [W; ww(:)];

            % include midpoint as node
            ii = indfn(2:2:end,2:2:end);
            jj = indcc(:);
            ww = ones(size(jj));
            I = [I; ii(:)]; J = [J; jj(:)]; W = [W; ww(:)];

            % prolongate in x direction
            ii   = indfn(2:2:end-1,1:2:end);
            jj   = [reshape(indcn(1:end-1,:),[],1); reshape(indcn(2:end,:),[],1)];
            ww = .5*ones(size(jj));
            I = [I; ii(:);ii(:)]; J = [J; jj(:)]; W = [W; ww(:)];

            % prolongate in y direction
            ii   = indfn(1:2:end,2:2:end-1);
            jj   = [reshape(indcn(:,1:end-1),[],1); reshape(indcn(:,2:end),[],1)];
            ww   = .5*ones(size(jj));
            I = [I; ii(:); ii(:)]; J = [J; jj(:)]; W = [W; ww(:)];

            % prolongate from bottom-left to top-right
            ii   = indfc(1:2:end,1:2:end);
            jj   = [reshape(indcn(1:end-1,1:end-1),[],1); reshape(indcc,[],1)];
            ww   = .5*ones(size(jj));
            I = [I; ii(:); ii(:)]; J = [J; jj(:)]; W = [W; ww(:)];
            ii   = indfc(2:2:end,2:2:end);
            jj   = [reshape(indcn(2:end,2:end),[],1); reshape(indcc,[],1)];
            ww   = .5*ones(size(jj));
            I = [I; ii(:); ii(:)]; J = [J; jj(:)]; W = [W; ww(:)];

            % prolongate from top-left to bottom-right
            ii   = indfc(2:2:end,1:2:end);
            jj   = [reshape(indcn(2:end,1:end-1),[],1); reshape(indcc,[],1)];
            ww   = .5*ones(size(jj));
            I = [I; ii(:); ii(:)]; J = [J; jj(:)]; W = [W; ww(:)];
            ii   = indfc(1:2:end,2:2:end);
            jj   = [reshape(indcn(1:end-1,2:end),[],1); reshape(indcc,[],1)];
            ww   = .5*ones(size(jj));
            I = [I; ii(:); ii(:)]; J = [J; jj(:)]; W = [W; ww(:)];

            P = sparse(I,J,W,prod(mf+1)+prod(mf),prod(m+1)+prod(m));
        end

        % ========== get methods ========================================
        function dx1 = get.dx1(this)
            if isempty(this.dx1_),
                [this.dx1_, this.dx2_] = getGradientMatrixFEM(this,0);
            end
            dx1 = this.dx1_;
        end

        function dx2 = get.dx2(this)
            if isempty(this.dx2_),
                [this.dx1_, this.dx2_] = getGradientMatrixFEM(this,0);
            end
            dx2 = this.dx2_;
        end

        function GRAD = get.GRAD(this)
            if isempty(this.GRAD_),
                this.GRAD_ = [this.dx1;this.dx2];
            end
            GRAD = this.GRAD_;
        end
        function B = get.B(this)
            if isempty(this.B_),
                this.B_ = blkdiag(this.GRAD,this.GRAD);
            end
            B = this.B_;
        end

        function P1 = get.P1(this)
            if isempty(this.P1_),
                A = speye(this.nnodes);
                this.P1_ = A(this.tri(:,1),:);
            end
            P1 = this.P1_;
        end
        function P2 = get.P2(this)
            if isempty(this.P2_),
                A = speye(this.nnodes);
                this.P2_ = A(this.tri(:,2),:);
            end
            P2 = this.P2_;
        end

        function P3 = get.P3(this)
            if isempty(this.P3_),
                A = speye(this.nnodes);
                this.P3_ = A(this.tri(:,3),:);
            end
            P3 = this.P3_;
        end
        function PC = get.PC(this)
            if isempty(this.PC_),
                this.PC_ = (this.P1+this.P2+this.P3)/3;
            end
            PC = this.PC_;
        end
        function P = get.P(this)
            if isempty(this.P_),
                this.P_ = this.getPuNodal(this.m);
            end
            P = this.P_;
        end
        function Pt = get.Pt(this)
            if isempty(this.Pt_),
                this.Pt_ = this.getPuNodal(this.m/2);
            end
            Pt = this.Pt_;
        end

        function mfdx1 = get.mfdx1(this)
            if isempty(this.mfdx1_),
                [this.mfdx1_, this.mfdx2_] = getGradientMatrixFEM(this,1);
            end
            mfdx1 = this.mfdx1_;
        end

        function mfdx2 = get.mfdx2(this)
            if isempty(this.mfdx2_),
                [this.mfdx1_, this.mfdx2_] = getGradientMatrixFEM(this,1);
            end
            mfdx2 = this.mfdx2_;
        end

        function AvN = get.AvN(this)
            if isempty(this.AvN_),
                av  = @(n) spdiags(ones(n+1,1)*[0.5 0.5],[0,1],n,n+1);
                this.AvN_ = kron(speye(2), [speye(prod(this.m+1)); kron(av(this.m(2)),av(this.m(1)))]);
            end
            AvN = this.AvN_;
        end

        function mfGRAD = get.mfGRAD(this)
            if isempty(this.mfGRAD_),
                this.mfGRAD_ = getGradientMatrixFEM(this,1);
            end
            mfGRAD = this.mfGRAD_;
        end
        function idx = get.boundaryIdx(this)
            if isempty(this.boundaryIdx_),
                id = reshape(1:prod(this.m+1),this.m+1);
                idx = [reshape(id([1,end],:),[],1);reshape(id(2:end-1,[1,end]),[],1)] ;
                this.boundaryIdx_ = idx;
            end
            idx = this.boundaryIdx_;
        end

        function idx = get.boundaryProj(this)
            if isempty(this.boundaryProj_),
                idx = this.boundaryIdx;

                P = speye(prod(this.m+1));
                P = P(idx,:);
                P = [P,sparse(size(P,1),prod(this.m))];
                P = kron(speye(2),P);

                this.boundaryProj_ = P;
            end
            idx = this.boundaryProj_;
        end

        % ========== set methods ========================================
        function set.xn(this,xn)
            if numel(xn)~=(2*(prod(this.m+1)+prod(this.m))),
                error('Invalid number of nodes');
            end
            if isempty(this.xn),
                this.xn = xn;
            else

                this.xn = xn;
                % delete operators that are sensitive to nodes
                this.dx1_  = [];
                this.dx2_  = [];
                this.GRAD_ = [];
                this.B_    = [];

                this.vol = volTetraGrid(this,this.xn,'matrixFree',1);
            end
        end
    end
end


function l = lumHK(img)
%
%       l = lum(img)
%
%       This function calculates the Helmholtz-Kohlrausch luminance
%
%
%       input:
%           img: an RGB image
%
%       output:
%           l: normalized Helmholtz-Kohlrausch luminance
%
%     Copyright (C) 2015  Francesco Banterle
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
%

check3Color(img);

imgXYZ = ConvertRGBtoXYZ(img, 0);
imgLCh = ConvertXYZtoCIELCh(imgXYZ, 0);

L = imgLCh(:,:,1);
C = imgLCh(:,:,2);
h = imgLCh(:,:,3);

h2 = ((h - 90) / 2) * pi / 360;

l = L + (2.5 - 0.025 * L) .* (0.116 * abs(sin(h2)) + 0.085) .* C;
l = l / max(l(:));

end


function nMM=grMaxMatch(E)
% Function nMM=grMaxMath(E) solve the maximal matching problem.
% Input parameter:
%   E(m,2) or (m,3) - the edges of graph and their weight;
%     1st and 2nd elements of each row is numbers of vertexes;
%     3rd elements of each row is weight of edge;
%     m - number of edges.
%     If we set the array E(m,2), then all weights is 1.
% Output parameter:
%   nMM - the list of the numbers of edges included
%     in the maximal (weighted) matching.
% Uses the reduction to integer LP-problem.
% Required the Optimization Toolbox v.3.0.1 or over.
% Author: Sergiy Iglin
% e-mail: siglin@yandex.ru
% personal page: http://iglin.exponenta.ru

% ============= Input data validation ==================
if nargin<1,
  error('There are no input data!')
end
[m,n,E] = grValidation(E); % E data validation

% ============= Parameters of integer LP problem ==========
A=zeros(n,m); % for incidence matrix
A(E(:,1:2)+repmat(([1:m]'-1)*n,1,2))=1; % we fill the incidence matrix
options=optimset('bintprog'); % the default options
options.Display='off'; % we change the output

% ============= We solve the integer LP problem ==========
xmin=bintprog(-E(:,3),A,ones(n,1),[],[],[],options);
nMM=find(round(xmin)); % the answer - numbers of edges
return


function out = binavgcol(in, numinbin)
% Rebins image by averaging numinbin bins together along columns of the
% 2D data.
% out = binavgcol(in, numinbin)

di=0;
if strcmp(class(in),'dip_image')
    di=1;
    in=double(in);
end
tmp = in;

for ii=2:numinbin
    tmp = tmp + circshift(in,[-1*(ii-1) 0]);
end

nb = floor(size(in,1)/numinbin);
ix=numinbin*(1:nb)-(numinbin-1);
out = tmp(ix,:)/numinbin;
if di
    out=dip_image(out);
end


function [p sres sres_ns] = ResidScan(res, FWHM)
% Calculates P(M>=t) where M is the max value of the smoothed residuals.
% In this implementation the residuals are smoothed using a Gaussian
% kernel.
%
% :Usage:
% ::
%
%     function [p sres sres_ns] = ResidScan(res, FWHM)
%
% :Inputs:
%
%   **res:**
%        residual time course
%
%   **FWHM:**
%        Full Width Half Maximum (in time units)
%
% :Outputs:
%
%   **p:**
%        pvalues
%
%   **sres:**
%        smoothed residuals
%
%   **sres_ns:**
%        smoothed residuals (non standardized)
%
% ..
%    By Martin Lindquist & Ji-Meng Loh, July 2007
%
%    Edited by ML on 10/02/09
% ..

res_ns = res;
res = res./std(res);
len = length(res);

% Create Gaussian Kernel
sig = ceil(FWHM/(2*sqrt(2*log(2))));
klen = 3*sig;
kern = normpdf((-klen:klen),0,sig);
kern = kern./sqrt(sum(kern.^2));

% Convolve
x = conv(res,kern);
sres = x((klen + 1):(end-klen));

x = conv(res_ns,kern/sum(kern));
sres_ns = x((klen + 1):(end-klen));

% Find Max value
[a,location] = max(abs(sres));

% Find p-values using Gaussian Random Field theory
z = Euler_p(1, a, len, FWHM);
z = 2*z;        %Two-sided test
p = min(1, z);

end

% END MAIN FUNCTION

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Subfunctions
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function pval = Euler_p(myDim, value, N, fwhm)
% function z = Euler_p(myDim, value, N, fwhm)
%
% Finds the p value using the expected Euler characteristic.
%
% This function returns P(M \ge value) using the approximation
% \sum_{d=0}^D R_d(V) \rho_d(value) following Worsley et al's "A Unified
% Statistical Approach for Determining Significant Signals in Images of
% Cerebral Activation".
%
% INPUTS:
%
% myDim - the number of dimensions in the data
% value - the value of the maximum.
% N     - the number of (time) points in that 1 dimension
% fwhm  - the full width half maximum
%
% OUTPUTS:
%
% pval - the p-value

% NOTE: CURRENTLY THIS FUNCTION IS ONLY IMPLEMENTED FOR THE 1D CASE

  % Constants
  myfactor = 4*log(2);
  pi2 = 2*pi;
  exptsq = exp(-(value^2)/2);

  % Euler Characteristc Densties
  rho = zeros(5,1);
  rho(1) = 1-normcdf(value);
  rho(2) = myfactor^(0.5)*exptsq/pi2;
  rho(3) = myfactor * exptsq * value / (pi2 ^ (1.5));
  rho(4) = myfactor ^ (1.5) * exptsq * (value^2-1) / (pi2 ^2);
  rho(5) = myfactor ^2 * exptsq * (value^3-3*value) / (pi2 ^ (5/2));

  % Resel Count
  R0 = 1;
  R1 = N/fwhm;

  % P-value
  pval = R0 * rho(1) + R1 * rho(2);

end


% anova1_cell() - compute F-values in cell array using ANOVA.
%
% Usage:
%    >> [F df] = anova1_cell( data );
%
% Inputs:
%   data       = data consisting of PAIRED arrays to be compared. The last
%                dimension of the data array is used to compute ANOVA.
% Outputs:
%   F   - F-value
%   df  - degree of freedom (array)
%
% Note: the advantage over the ANOVA1 function of Matlab statistical
%       toolbox is that this function works on arrays (see examples). Note
%       also that you still need the statistical toolbox to assess
%       significance using the fcdf() function. The other advantage is that
%       this function will work with complex numbers.
%
% Example:
%   a = { rand(1,10) rand(1,10) rand(1,10) }
%   [F df] = anova1_cell(a)
%   signif = 1-fcdf(F, df(1), df(2))
%
%   % for comparison
%   anova1( [ a{1,1}' a{1,2}' a{1,3}' ]) % look in the graph for the F value
%
%   b = { [ a{1,1}; a{1,1} ] [ a{1,2}; a{1,2} ] [ a{1,3}; a{1,3} ] }
%   [F df] = anova1_cell(b)
%
%   c{1,1} = reshape(repmat(b{1,1}, [2 1]),2,2,10);
%   c{1,2} = reshape(repmat(b{1,2}, [2 1]),2,2,10);
%   c{1,3} = reshape(repmat(b{1,3}, [2 1]),2,2,10);
%   [F df] = anova1_cell(c)
%
% Author: Arnaud Delorme, SCCN/INC/UCSD, La Jolla, 2005
%
% Reference:
%   Schaum's outlines in statistics (3rd edition). 1999. Mc Graw-Hill.

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

function [F, df] = anova1_cell(data)

    % This function does not return
    % correct values (see bug 336)
    % It should be fixed with Schaum's outlines p363
    % but requires some work. It now calls
    % anova2_cell which returns correct values

    warning off;
    [ F tmp tmp2 df] =  anova2_cell(data);
    warning on;
    return;

    % compute all means and all std
    % -----------------------------
    nd = myndims( data{1} );
    if nd == 1

        for i = 1:length(data)
            n( i) = length(data{i});
            m( i) = mymean(  data{i});
            sd(i) = mystd(   data{i});
        end;
        nt = sum(n);
        n   = n';
        m   = m';
        sd  = sd';

    elseif nd == 2

        for i = 1:length(data)
            n( :,i) = ones(size(data{i},1),1) * size(data{i},2, 'single');
            m( :,i) = mymean(  data{i},2);
            sd(:,i) = mystd(   data{i},[],2);
        end;
        nt = sum(n(1,:));

    elseif nd == 3

        for i = 1:length(data)
            n( :,:,i) = ones(size(data{i},1),size(data{i},2)) * size(data{i},3, 'single');
            m( :,:,i) = mymean(  data{i},3);
            sd(:,:,i) = mystd(   data{i},[],3);
        end;
        nt = sum(n(1,1,:));

    else

        for i = 1:length(data)
            n( :,:,:,i) = ones(size(data{i},1),size(data{i},2), size(data{i},3)) * size(data{i},4, 'single');
            m( :,:,:,i) = mymean(  data{i},4);
            sd(:,:,:,i) = mystd(   data{i},[],4);
        end;
        nt = sum(n(1,1,1,:));

    end;

    mt = mean(m,nd);
    ng = length(data); % number of conditions

    VinterG  = ( sum( n.*(m.^2), nd ) - nt*mt.^2 )/(ng-1);
    VwithinG = sum( (n-1).*(sd.^2), nd )/(nt-ng);
    F  = VinterG./VwithinG;
    df = [ ng-1 ng*(size(data{1},nd)-1) ];

function val = myndims(a)
    if ndims(a) > 2
        val = ndims(a);
    else
        if size(a,1) == 1,
            val = 2;
        elseif size(a,2) == 1,
            val = 1;
        else
            val = 2;
        end;
    end;

function res = mymean( data, varargin) % deal with complex numbers
    res = mean( data, varargin{:});
    if ~isreal(data)
        res = abs( res );
    end;

function res = mystd( data, varargin) % deal with complex numbers
    res = std( abs(data), varargin{:});


function r = cosh(a)
%COSH         Taylor hyperbolic cosine  cosh(a)
%

% written  05/21/09     S.M. Rump
% modified 08/26/12     S.M. Rump  global variables removed
%

  e = 1e-30;
  if 1+e==1-e                   % fast check for rounding to nearest
    rndold = 0;
  else
    rndold = getround;
    setround(0)
  end

  K = getappdata(0,'INTLAB_TAYLOR_ORDER');

  st = a.t;
  r = a;
  N = size(a.t,2);
  st(1,:) = sinh(a.t(1,:));
  r.t(1,:) = cosh(a.t(1,:));
  for j=2:K
    at_ = a.t(2:j,:);           % some 3 % faster
    st(j,:) = sum( repmat((1:j-1)',1,N).*r.t(j-1:-1:1,:).*at_ , 1 ) ./ (j-1);
    r.t(j,:) = sum( repmat((1:j-1)',1,N).*st(j-1:-1:1,:).*at_ , 1 ) ./ (j-1);
  end
  r.t(K+1,:) = sum( repmat((1:K)',1,N).*st(K:-1:1,:).*a.t(2:K+1,:) , 1 ) ./ K;

  if rndold
    setround(rndold)
  end


function [ Acc ] = ssvep_performance(CNT , params)
opt = opt_cellToStruct(params);
%% CCA - Anaysis
SMT=[];
for onoff=1:2
    cnt = CNT{onoff};
    cnt=prep_filter(cnt, {'frequency', opt.band});
    CNTch = prep_selectChannels(cnt, {'Index', opt.channel_index});
    SMT_iter = prep_segmentation(CNTch, {'interval', opt.time_interval});
    if onoff==1
        SMT= SMT_iter;
        clear SMT_iter
    else
        SMT = prep_addTrials(SMT, SMT_iter);
        clear SMT_iter
    end
end

tot = size(SMT.x, 2);
count1= tot;
for i = 1: size(SMT.x, 2)
    res_cca = ssvep_cca_analysis(squeeze(SMT.x(:,i,:)),{'marker',opt.marker;'freq', opt.freq;'fs', opt.fs;'time',opt.time});
    [~, ind] = max(res_cca);
    if SMT.y_dec(i) ~= ind
        count1 = count1 -1;
    end
end
Acc =count1/tot;
clear CNTch SMT tot count1 i res_cca in
end


function rect = pos2rect(obj_center, obj_size, win_size)
%POS2RECT Get rectangle [x,y,w,h] from obj_center [cx,cy] and size [w,h]
% Parameters:
%   obj_center Rectangle center location [cx, cy]
%   obj_size   Rectangle dimensions [w,h]
%   win_size   (optional) If [width, height] are given, the rectangle will
%              stay within the boundaries [1, 1, width, height]
  rect = [round(obj_center - obj_size./2), obj_size];
  if exist('win_size','var')
    if rect(1) < 1
      corr = abs(rect(1)) + 1;
      rect(1) = 1;
      rect(3) = rect(3) - corr;
    end
    if rect(2) < 1
      corr = abs(rect(2)) + 1;
      rect(2) = 1;
      rect(4) = rect(4) - corr;
    end
    if rect(1) + rect(3) > win_size(1)
      rect(3) = win_size(1) - rect(1);
    end
    if rect(2) + rect(4) > win_size(2)
      rect(4) = win_size(2) - rect(2);
    end
  end
end


function [T, M, S] = dtiTsqTestStat(g1, g2, Y, mask)

% Computes voxel-wise Hotelling T^2 statistics for two groups from a data array of
% diffusion tensors in dt6 format.
%
%   [T, M, S] = dtiTsqTestStat(g1, g2, DT_ARRAY, [MASK])
%
% Input:
%   g1, g2      List of indices that correspond to each group out of 1:N
%                   E.g: g1 = 1:7, g2 = 8:14, N = 14
%   DT_ARRAY    Data array of size XxYxZxpxN (or nxpxN), where X, Y, Z are the volume
%                   dimensions and N is the number of subjects.
%                   p is the vector dimension (p = 6 for DT6 data).
%                   (n is the number of voxels).
%   MASK        Optional XxYxZ binary array. Values of M and S are computed
%                   where mask = 1; in other voxels, M and S are set to 0.
%                   Default is entire volume.
%
% Output:
%   T           XxYxZx1 array of test statistics (0 where mask = 0)
%   M           XxYxZxpx2 array of mean vectors for both groups (0 where mask = 0)
%   S           XxYxZxpxp array of covariances (0 where mask = 0)
%
% Utilities:    ndfun.m, dtiSplitTensor.m, dti33to6.m
%
% WARNING: If using Pentium 4, eliminate NaN's from array before running
% (processor bug).
%
% Copyright by Armin Schwartzman, 2005

% HISTORY:
%   2004.06.23 ASH (armins@stanford.edu) wrote it.
%

% Check inputs
if (ndims(Y)==2 | ndims(Y)==3),
    Ind = 1;    % Data in indexed nx6xN format
    Y = shiftdim(Y, -2);
else
    Ind = 0;    % Data in XxYxZx6xN format
end
if (ndims(Y)<4 | ndims(Y)>5),
    error('Wrong input format');
end
if (~exist('mask')),
    mask = ones([size(Y,1) size(Y,2) size(Y,3)]);
end

% Computations
N1 = length(g1);
N2 = length(g2);
N  = N1 + N2;

p = size(Y, 4);
Y = permute(Y, [4 5 1 2 3]); % permutation required by ndfun
Yavg1 = mean(Y(:,g1,:,:,:), 2);
Yavg2 = mean(Y(:,g2,:,:,:), 2);
davg = Yavg1 - Yavg2;
d1 = Y(:,g1,:,:,:)-repmat(Yavg1, [1 N1 1 1 1]);
d2 = Y(:,g2,:,:,:)-repmat(Yavg2, [1 N2 1 1 1]);
M = cat(2, Yavg1(:,1,:,:,:), Yavg2(:,1,:,:,:));
clear Y*
S = ndfun('mult', d1, permute(d1, [2 1 3:5])) + ndfun('mult', d2, permute(d2, [2 1 3:5]));
outmask = repmat(shiftdim(~mask, -2), [p p 1 1 1]);
S(outmask) = 0;
outmask = repmat(eye(p), [1 1 size(mask)]) & outmask;
S(outmask) = 1;
b = ndfun('backslash', S, davg);
b = ndfun('mult', permute(davg, [2 1 3:5]), b);
T = b * N1*N2/(N1+N2) * (N1+N2-p-1)/p;

% Adjust output
T = permute(T, [3 4 5 1 2]);
M = permute(M, [3 4 5 1 2]);
S = permute(S, [3 4 5 1 2]);
if Ind,
    T = shiftdim(T, 2);
    M = shiftdim(M, 2);
    S = shiftdim(S, 2);
end

return


function [L, stored_at] = quadtree_laplacian(C,W,CH,D,A)
% QUADTREE_LAPLACIAN
% Builds a finite difference Laplacian on a quadtree following the scheme
% suggested by Bickel et al. "Adaptative Simulation of Electrical
% Discharges". This code is *purposefully* not optimized beyond
% asymptotics for simplicity in understanding its functionality and
% translating it to other programming languages beyond prototyping.
%
% L = octree_laplacian(C,W,CH,D,A)
%
% Inputs:
%   C #nodes by 3 matrix of cell centers
%   W #nodes vector of cell widths (**not** half widths)
%   CH #nodes by 4 matrix of child indeces (-1 if leaf node)
%   D #nodes vector of tree depths
%   A #nodes by #nodes sparse adjacency matrix, where a value of a in the
%       (i,j) entry means that node j is to the a-th direction of i
%       (a=1: left;  a=2: right;  a=3: bottom;  a=4: top).
%
% Outputs:
%   L #num_children by #num_children sparse Laplacian matrix
%   stored_at #num_children by 3 matrix of child cell centers, where the
%       values of L are stored
%
%
% Example:
%
% % Build an octree
% P = 0.5*[cos(th),sin(th)];
% P = [P;[-1,-1];[1,1]];
% [C,W,CH,PAR,D,A] = initialize_quadtree(P,'MaxDepth',8,'Graded',true);
% % This is for plotting
% [V,Q] = bad_quad_mesh_from_quadtree(C,W,CH);
% % Call function to construct Laplacian
% [L, stored_at] = quadtree_laplacian(C,W,CH,D,A);
% % Dummy Laplacian function
% gt_fun = stored_at(:,1).^2.0;
% laplacian_fun = 2 + 0.*stored_at(:,1);
% % Find boundary
% Vmin = min(stored_at,[],1);
% Vmax = max(stored_at,[],1);
% is_boundary = (stored_at(:,1)<=(Vmin(1)+0.2)) + (stored_at(:,2)<=(Vmin(2)+0.2)) + ...
%     (stored_at(:,1)>=(Vmax(1)-0.2)) + (stored_at(:,2)>=(Vmax(2)-0.2));
% bb = find(is_boundary);
% bc = gt_fun(bb);
% % Solve as energy minimization
% u = min_quad_with_fixed(0.5*L,-laplacian_fun,bb,bc);
% % Plot solution
% tsurf(Q,V,falpha(1,1),'FaceVertexCData',u)
% hold on
% sct(stored_at(bb,:)) % Visualize boundary conditions
% set(gcf,'Color','w'); grid off; axis equal; colorbar; caxis([0 1]);
%
%
% See also: initialize_quadtree.m

% We will store Laplacian values at
% child cell indeces
children = find(CH(:,1)==-1);
% map from all cells to children
cell_to_children = -ones(size(W,1),1);
cell_to_children(children) = 1:length(children);

% Vectors for constructing the Laplacian
I = [];
J = [];
vals = [];

for i=1:size(children,1)
    new_I = [];
    new_J = [];
    new_vals = [];
    l = [1,1,1,1];
    new_dirs = [];
    child = children(i);
    d = D(child);
    num_dirs = 0;
    % Let's build d u(child)/dx^2 ~ u(child+W(child)*[1,0])/hr(hl+hr) -
    % 2u(child)/hlhr + u(child-W(child)*[1,0])/hr(hl+hr)
    % So, let's look for the value to the j direction. To do this, we seek the
    % lowest-depth neighbor to the j direction. As a reminder the octree
    % adjacency convention is i->j (1:left-2:right-3:bottom-4:top)
    for j=1:4
        j_neighbors = find(A(child,:)==j);
        if ~isempty(j_neighbors)
            depths_j_neighbors = D(j_neighbors);
            [max_depth_j, max_depth_j_neighbor] = max(depths_j_neighbors);
            max_depth_j_neighbor = j_neighbors(max_depth_j_neighbor);
            % There are two options:
            % One: the leaf node to our j direction has lower or equal depth to
            % us
            if max_depth_j<=d
                l(j) = (W(child) + W(max_depth_j_neighbor))/2;
                % then it's easy, just add this node
                new_I = [new_I;i];
                % THIS HAS TO BE A CHILD !
                assert(cell_to_children(max_depth_j_neighbor)>0);
                new_J = [new_J;cell_to_children(max_depth_j_neighbor)];
                new_vals = [new_vals;-1]; % Todo fix this
                new_dirs = [new_dirs;j];
            else
                % In this case, assuming the grid is graded, there should
                % be two j-neighbors at depth d+1
                nn = j_neighbors(D(j_neighbors)==(d+1));
                assert(length(nn)==2,"Are you sure you are inputting a graded quadtree?")
                assert(all(CH(nn,1)==[-1;-1]))
                % Then we simply average both
                l(j) = (W(child) + W(nn(1)))/2;
                new_I = [new_I;i;i];
                new_J = [new_J;cell_to_children(nn(1));cell_to_children(nn(2))];
                new_vals = [new_vals;-0.5;-0.5];
                new_dirs = [new_dirs;j;j];
            end
            num_dirs = num_dirs + 1;
        end
    end
    new_I = [new_I;i];
    new_J = [new_J;i];
    new_vals = [new_vals; 1.0];
    new_dirs = [new_dirs;5]; % just a hack
    % At this point, we have to divide by the edge-lengths
    new_vals(new_dirs==1) = new_vals(new_dirs==1)/(l(1)*(l(1)+l(2)));
    new_vals(new_dirs==2) = new_vals(new_dirs==2)/(l(2)*(l(1)+l(2)));
    new_vals(new_dirs==3) = new_vals(new_dirs==3)/(l(3)*(l(3)+l(4)));
    new_vals(new_dirs==4) = new_vals(new_dirs==4)/(l(4)*(l(3)+l(4)));
    new_vals(new_dirs==5) = 1/(l(1)*l(2)) + 1/(l(3)*l(4));

    % And add them to the big sparse Laplacian construction vectors
    I = [I;new_I];
    J = [J;new_J];
    vals = [vals;new_vals];
end

% THE LAPLACIAN IS NEGATIVE SEMI DEFINITE!
L = -2*sparse(I,J,vals,length(children),length(children));
stored_at = C(children,:);

end


% Compute Hoyer sparsity of x

function spx = sp(x,w)

r = length(x);

spx = 0;
for i = 1 : r
    if x{i} == 0
        spx = 1;
    else
        ni = length(x{i});
        if nargin <= 1
            spx = spx + (sqrt(ni)-norm(x{i},1)/norm(x{i},2))/(sqrt(ni)-1);
        else
            nw = norm(w{i},2);
            spx = spx + (nw-w{i}'*abs(x{i})/norm(x{i},2))/(nw-min(w{i}));
        end
    end
end
spx = spx/r;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   q = solve_spherical_wrist2(robot, q, T, wrist)
%   Solves the inverse kinematic problem for a spherical wrist. This is for
%   the particular RELATIVE orientation of the last three reference systems in
%   ABB robots
%
%   robot: robot structure.
%   q: vector containing the values of the joints 1, 2 and 3.
%   T: orientation of the last reference system.
%   wrist: select -1 or 1 for two possible solutions (wrist up, wrist down)
%
%	See also DIRECTKINEMATIC.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Copyright (C) 2012, by Arturo Gil Aparicio
%
% This file is part of ARTE (A Robotics Toolbox for Education).
%
% ARTE is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% ARTE 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with ARTE.  If not, see <http://www.gnu.org/licenses/>.

function q = solve_spherical_wrist2(robot, q, T, wrist, method)

switch method

    %algebraic solution
    case 'algebraic'
        A01=dh(robot, q, 1);
        A12=dh(robot, q, 2);
        A23=dh(robot, q, 3);

        Q=inv(A23)*inv(A12)*inv(A01)*T;

        %detect the degenerate case when q(5)=0, this leads to zeros
        % in Q13, Q23, Q31 and Q32 and Q33=1
        thresh=1e-12;
        %detect if q(5)==0
        % this happens when cos(q5) in the matrix Q is close to 1
        if abs(Q(3,3)-1)>thresh
            %normal solution
            if wrist==1 %wrist up
                q(4)=atan2(Q(2,3),Q(1,3));
                q(6)=atan2(-Q(3,2),Q(3,1));
            else %wrist down
                q(4)=atan2(Q(2,3),Q(1,3))+pi;
                q(6)=atan2(-Q(3,2),Q(3,1))+pi;
            end
            if abs(cos(q(6)+q(4)))>thresh
                cq5=(-Q(1,1)-Q(2,2))/cos(q(4)+q(6))-1;
            end
            if abs(sin(q(6)+q(4)))>thresh
                cq5=(Q(1,2)-Q(2,1))/sin(q(4)+q(6))-1;
            end
            if abs(sin(q(6)))>thresh
                sq5=Q(3,2)/sin(q(6));
            end
            if abs(cos(q(6)))>thresh
                sq5=-Q(3,1)/cos(q(6));
            end
            q(5)=atan2(sq5,cq5);
        else %degenerate solution, in this case, q4 cannot be determined,
            % so q(4)=0 is assigned
            if wrist==1 %wrist up
                q(4)=0;
                q(5)=0;
                q(6)=atan2(Q(1,2)-Q(2,1),-Q(1,1)-Q(2,2));
            else %wrist down
                q(4)=-pi;
                q(5)=0;
                q(6)=atan2(Q(1,2)-Q(2,1),-Q(1,1)-Q(2,2))+pi;
            end

        end

        %algebraic solution
    case 'geometric'

        % Obtain the position and orientation of the system 3
        % using the already computed joints q1, q2 and q3
        T01=dh(robot, q, 1);
        T12=dh(robot, q, 2);
        T23=dh(robot, q, 3);
        T03=T01*T12*T23;

        x3=T03(1:3,1);
        y3=T03(1:3,2);
        z3=T03(1:3,3);

        % T= [ nx ox ax Px;
        %     ny oy ay Py;
        %     nz oz az Pz];
        a=T(1:3,3);

        % find z4 normal to the plane formed by z3 and a
        z4=cross(z3, a);	% end effector's vector a: T(1:3,3)

        % in case of degenerate solution,
        % when z3 and z6 are parallel, choose q(4)=0 as solution
        if norm(z4) <= 0.000001
            if wrist == 1 %wrist up
                q(4)=0;
            else
                q(4)=-pi;
            end
        else
            cq4=wrist*dot(z4, -y3);
            sq4=wrist*dot(z4, x3);
            q(4)=atan2(sq4, cq4);
        end

        % solve for q5
        T34=dh(robot, q, 4);
        T04=T03*T34;
        x4=T04(1:3, 1);
        y4=T04(1:3, 2);

        z5=T(1:3, 3); % The vector a T(1:3,3) is coincident with z5

        cq5=dot(z5, y4);
        sq5=dot(z5, -x4);
        q(5)=atan2(sq5, cq5);

        % solve for q6
        x6=T(1:3, 1);

        T45=dh(robot, q, 5);
        T05=T04*T45;
        x5=T05(1:3, 1);
        y5=T05(1:3, 2);

        cq6=dot(x6, -x5);
        sq6=dot(x6, -y5);
        q(6)=atan2(sq6, cq6);

    otherwise
        disp('no method specified in solve_spherical_wrist');
end


function s = findspan(n,p,u,U)
% FINDSPAN  Find the span of a B-Spline knot vector at a parametric point
% -------------------------------------------------------------------------
% ADAPTATION of FINDSPAN from C
% -------------------------------------------------------------------------
%
% Calling Sequence:
%
%   s = findspan(n,p,u,U)
%
%  INPUT:
%
%    n - number of control points - 1
%    p - spline degree
%    u - parametric point
%    U - knot sequence
%
%  RETURN:
%
%    s - knot span
%
%  Algorithm A2.1 from 'The NURBS BOOK' pg68

                                                % int findspan(int n, int p, double u, double *U) {

                                                %   int low, high, mid;
                                                %   // special case
if (u==U(n+2)), s=n; return,  end               %   if (u == U[n+1]) return(n);
                                                %
                                                %   // do binary search
low = p;                                        %   low = p;
high = n + 1;                                   %   high = n + 1;
mid = floor((low + high) / 2);                  %   mid = (low + high) / 2;
while (u < U(mid+1) || u >= U(mid+2))           %   while (u < U[mid] || u >= U[mid+1])  {
    if (u < U(mid+1))                           %     if (u < U[mid])
        high = mid;                             %       high = mid;
    else                                        %     else
        low = mid;                              %       low = mid;
    end
    mid = floor((low + high) / 2);              %     mid = (low + high) / 2;
end                                             %   }
                                                %
s = mid;                                        %   return(mid);
                                                %   }


function handle = draw_gmm(haxes,Priors,Mu,Sigma )
%DRAW_GMM Summary of this function goes here
%   Detailed explanation goes here

K = size(Priors,2);
STD=3;

for k=1:K
    l = max(Priors);
    for i=3:(-1):STD
        w = Priors(k)/l;
        handle = plot_gaussian_ellipsoid(Mu(:,k),Sigma(:,:,k),i,100,haxes,w,[0 0 1]);
        set(handle,'LineWidth',2);
      %  obj.text_handle = [obj.text_handle text(obj.Mu(1,k),obj.Mu(2,k),num2str(k),'FontWeight','bold','FontSize',24,'Color',obj.color,'VerticalAlignment','middle','HorizontalAlignment','center')];
    end
end

end


function [elem,bdFlag] = sortelem3(elem,bdFlag)
%% SORTELEM3 sort elem in ascend ordering
%
% [elem,bdFlag] = sortelem3(elem,bdFlag) sorts the elem such that
% elem(t,1)< elem(t,2)< elem(t,3)<elem(t,4). A simple sort(elem,2) cannot
% switch bdFlag.
%
% See also  sortelem
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

%% Step 1: elem(:,4) is the largest one
[tempvar,idx] = max(elem,[],2);  %#ok<*ASGLU>
elem(idx==1,1:4) = elem(idx==1,[2 4 3 1]);
elem(idx==2,1:4) = elem(idx==2,[3 4 1 2]);
elem(idx==3,1:4) = elem(idx==3,[4 2 1 3]);
if exist('bdFlag','var')
    bdFlag(idx==1,1:4) = bdFlag(idx==1,[2 4 3 1]);
    bdFlag(idx==2,1:4) = bdFlag(idx==2,[3 4 1 2]);
    bdFlag(idx==3,1:4) = bdFlag(idx==3,[4 2 1 3]);
end

%% Step 2: elem(:,1) is the smallest one
[tempvar,idx] = min(elem(:,1:3),[],2);
% elem(idx==1,1:3) = elem(idx==1,[1 2 3]);
elem(idx==2,1:3) = elem(idx==2,[2 3 1]);
elem(idx==3,1:3) = elem(idx==3,[3 1 2]);
if exist('bdFlag','var')
    bdFlag(idx==2,1:3) = bdFlag(idx==2,[2 3 1]);
    bdFlag(idx==3,1:3) = bdFlag(idx==3,[3 1 2]);
end

%% Step 3: sort elem(:,2)<elem(:3)
idx = (elem(:,3) < elem(:,2));
elem(idx,[2 3]) = elem(idx,[3 2]);
if exist('bdFlag','var')
    bdFlag(idx,[2 3]) = bdFlag(idx,[3 2]);
end

%% Output
if ~exist('bdFlag','var')
    bdFlag = [];
end


function [fal,dx0] = aliasing_frequency(x0,conf)
%ALIASING_FREQUENCY aliasing frequency for the given secondary sources
%
%   Usage: [fal,dx0] = aliasing_frequency([x0],conf)
%
%   Input parameters:
%       x0      - secondary sources / m
%       conf    - configuration struct (see SFS_config)
%
%   Output parameters:
%       fal     - aliasing frequency / Hz
%       dx0     - mean distance between secondary sources / m
%
%   ALIASING_FREQUENCY(x0,conf) returns the aliasing frequency for the given
%   secondary sources. First the mean distance dx0 between the secondary sources
%   is calculated, afterwards the aliasing frequency is calculated after Spors
%   (2009) as fal = c/(2*dx0). If no secondary sources x0 are provided, they are
%   first calculated by calling secondary_source_positions().
%   For a calculation that includes the dependency on the listener position have
%   a look at Start (1997).
%
%   See also: sound_field_mono_wfs, secondary_source_positions,
%       secondary_source_distance
%
%   References:
%       Spors and Ahrens (2009) - "Spatial sampling artifacts of wave field
%       synthesis for the reproduction of virtual point sources", 126th
%       Convention of the Audio Engineering Society, Paper 7744,
%       http://www.aes.org/e-lib/browse.cfm?elib=14940
%
%       Start (1997) - "Direct Sound Enhancement by Wave Field Synthesis",
%       PhD thesis, TU Delft,
%       http://resolver.tudelft.nl/uuid:c80d5b58-67d3-4d84-9e73-390cd30bde0d

%*****************************************************************************
% The MIT License (MIT)                                                      *
%                                                                            *
% Copyright (c) 2010-2019 SFS Toolbox Developers                             *
%                                                                            *
% Permission is hereby granted,  free of charge,  to any person  obtaining a *
% copy of this software and associated documentation files (the "Software"), *
% to deal in the Software without  restriction, including without limitation *
% the rights  to use, copy, modify, merge,  publish, distribute, sublicense, *
% and/or  sell copies of  the Software,  and to permit  persons to whom  the *
% Software is furnished to do so, subject to the following conditions:       *
%                                                                            *
% The above copyright notice and this permission notice shall be included in *
% all copies or substantial portions of the Software.                        *
%                                                                            *
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
% IMPLIED, INCLUDING BUT  NOT LIMITED TO THE  WARRANTIES OF MERCHANTABILITY, *
% FITNESS  FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL *
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
% LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT  OR OTHERWISE, ARISING *
% FROM,  OUT OF  OR IN  CONNECTION  WITH THE  SOFTWARE OR  THE USE  OR OTHER *
% DEALINGS IN THE SOFTWARE.                                                  *
%                                                                            *
% The SFS Toolbox  allows to simulate and  investigate sound field synthesis *
% methods like wave field synthesis or higher order ambisonics.              *
%                                                                            *
% https://sfs.readthedocs.io                            sfstoolbox@gmail.com *
%*****************************************************************************

%% ===== Checking of input parameters ====================================
nargmin = 1;
nargmax = 2;
narginchk(nargmin,nargmax);
if nargin<nargmax
    conf = x0;
    x0 = [];
end
isargstruct(conf);

%% ===== Configuration ==================================================
c = conf.c;

%% ===== Computation =====================================================
% If no explicit secondary source distribution is given, calculate one
if isempty(x0)
    x0 = secondary_source_positions(conf);
end
% Get average distance between secondary sources
dx0 = secondary_source_distance(x0);
% Calculate aliasing frequency
fal = c/(2*dx0);


function check = logistic_check ( a, b )

%*****************************************************************************80
%
%% LOGISTIC_CHECK checks the parameters of the Logistic CDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A, B, the parameters of the PDF.
%    0.0 < B.
%
%    Output, logical CHECK, is true if the parameters are legal.
%
  if ( b <= 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'LOGISTIC_CHECK - Fatal error!\n' );
    fprintf ( 1, '  B <= 0.\n' );
    check = 0;
    return
  end

  check = 1;

  return
end


function [f,relres,iter]=frsyniter(F,c,varargin)
%FRSYNITER  Iterative synthesis
%   Usage:  f=frsyniter(F,c);
%           f=frsyniter(F,c,Ls);
%           [f,relres,iter]=frsyniter(F,c,...);
%
%   Input parameters:
%         F       : Frame
%         c       : Array of coefficients.
%         Ls      : length of signal.
%   Output parameters:
%         f       : Signal.
%         relres  : Vector of residuals.
%         iter    : Number of iterations done.
%
%   `f=frsyniter(F,c)` iteratively inverts the analysis operator of *F*, so
%   `frsyniter` always performs the inverse operation of |frana|, even
%   when a perfect reconstruction is not possible by using |frsyn|.
%
%   `[f,relres,iter]=frsyniter(...)` additionally returns the relative
%   residuals in a vector *relres* and the number of iteration steps *iter*.
%
%   **Note:** If it is possible to explicitly calculate the canonical dual
%   frame then this is usually a much faster method than invoking
%   `frsyniter`.
%
%   `frsyniter` takes the following parameters at the end of the line of
%   input arguments:
%
%     'tol',t      Stop if relative residual error is less than the
%                  specified tolerance. Default is 1e-9 (1e-5 for single precision)
%
%     'maxit',n    Do at most n iterations.
%
%     'cg'         Solve the problem using the Conjugate Gradient
%                  algorithm. This is the default.
%
%     'pcg'        Solve the problem using the Preconditioned Conjugate Gradient
%                  algorithm. Please note that preconditioning is not supported
%                  for all frame types.
%
%     'print'      Display the progress.
%
%     'quiet'      Don't print anything, this is the default.
%
%   Algorithms
%   ----------
%
%   The function uses the (Preconditioned) Conjugate Gradient algorithm
%   to solve the following problem::
%
%   ..   FF*f=Fc
%
%   .. math:: FF* f = Fc
%
%   The preconditioning alters the equations such that
%
%   ..   inv(M)FF*f=inv(M)Fc
%
%   .. math:: M^{-1}FF* f = M^{-1}Fc
%
%   Examples
%   --------
%
%   The following example shows how to rectruct a signal without ever
%   using the dual frame:::
%
%      F=frame('dgtreal','gauss',10,20);
%      c=frana(F,bat);
%      [r,relres]=frsyniter(F,c,'tol',1e-14);
%      norm(bat-r)/norm(bat)
%      semilogy(relres);
%      title('Conversion rate of the CG algorithm');
%      xlabel('No. of iterations');
%      ylabel('Relative residual');
%
%   See also: frame, frana, frsyn, franaiter

% AUTHORS: Nicki Holighaus & Peter L. Søndergaard

complainif_notenoughargs(nargin,2,'FRSYNITER');
complainif_notvalidframeobj(F,'FRSYNITER');

tolchooser.double=1e-9;
tolchooser.single=1e-5;

definput.keyvals.Ls=[];
definput.keyvals.tol=tolchooser.(class(c));
definput.keyvals.maxit=100;
definput.keyvals.Fd = [];
definput.flags.alg={'cg','pcg'};
definput.keyvals.printstep=10;
definput.flags.print={'quiet','print'};

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

% if flags.do_auto
%     varargin2 = varargin;
%     varargin2(strcmpi(varargin2,'auto')) = [];
%
%     try
%         varargin2{end+1} = 'pcg';
%         [f,relres,iter]=frsyniter(F,c,varargin2{:});
%     catch
%         if ~flags.do_quiet
%             warning(sprintf('%s: Falling back to regular CG.',upper(mfilename)));
%         end
%         varargin2{end+1} = 'cg';
%         [f,relres,iter]=frsyniter(F,c,varargin2{:});
%     end
%     return;
% end

L=framelengthcoef(F,size(c,1));

Fd = kv.Fd;
% Compute the preconditioner
if flags.do_pcg && isempty(Fd)
    try
       d = cast(1./framediag(F,L),class(c));
    catch
       switch F.type
            case {'filterbank','ufilterbank'}
                Fd = frame(F.type,{'dual',F.g,'forcepainless'},F.a,numel(F.g));
            case {'filterbankreal','ufilterbankreal'}
                Fd = frame(F.type,{'realdual',F.g,'forcepainless'},F.a,numel(F.g));
            otherwise
                error('%s: No preconditioning method available for given frame type.',...
                upper(mfilename));
       end
    end
end

F=frameaccel(F,L);

A=@(x) F.frsyn(F.frana(x));

% It is possible to specify the initial guess, but this is not
% currently done

if flags.do_pcg && isempty(Fd)

      [f,flag,~,iter,relres]=pcg(A,F.frsyn(c),kv.tol,kv.maxit,@(x)d.*x);
elseif flags.do_pcg

      Fd = frameaccel(Fd,L);
      A=@(x) Fd.frsyn(F.frana(x));
      [f,flag,~,iter,relres]=pcg(A,Fd.frsyn(c),kv.tol,kv.maxit);
else

      [f,flag,~,iter,relres]=pcg(A,F.frsyn(c),kv.tol,kv.maxit);
end

if nargout>1
      relres=relres/norm(c(:));
end

% Cut or extend f to the correct length, if desired.
if ~isempty(Ls)
    f=postpad(f,Ls);
else
    Ls=L;
end

if 0
      % This code has been disabled, as the PCG algorithm is so much faster.
    if flags.do_unlocbox

          % Get the upper frame bound (Or an estimation bigger than the bound)
          [~,B]=framebounds(F,L,'a');

          % Set the parameter for the fast projection on a B2 ball
          param.At=@(x) frsyn(F,x);     % adjoint operator
          param.A=@(x)  frana(F,x);     % direct operator
          param.y=c;                    % coefficient
          param.tight=0;                % It's not a tight frame
          param.max_iter=kv.maxit;
          param.tol=kv.tol;
          param.nu=B;

          % Display parameter 0 nothing, 1 summary at convergence, 2 all
          % steps
      if flags.do_print
          param.verbose=1;
      else
          param.verbose=0;
      end

      % Make the projection. Requires UNLocBOX
      [f, ~] = fast_proj_B2(zeros(L,1), 0, param);

      % compute the residue
      res = param.A(f) - param.y; norm_res = norm(res(:), 2);
      relres=norm_res/norm(c(:), 2);

      iter=0; % The code of the fast_proj_B2 is not yet compatible with this
    end

end


function DEM_demo_DFP
% DEM demo for linear deconvolution:  This demo considers the deconvolution
% of the responses of a single-input-multiple output input-state-output
% model (DCM) to disclose the input or causes.  It starts by demonstrating
% Variational filtering with spm_DFP; this is a stochastic filtering scheme
% that propagates particles over a changing variational energy landscape
% such that their sample density can be used to approximate the underlying
% ensemble or conditional density.  We then repeat the inversion using
% spm_DEM (i.e., under a Laplace assumption) which involves integrating the
% path of just one particle (i.e., the mode).

% get a simple convolution model
%==========================================================================
spm_figure('GetWin','DEM');

M        = spm_DEM_M('convolution model');
M(1).V   = exp(8);
M(1).W   = exp(16);
M(1).E.N = 32;

% and generate data
%==========================================================================
N     = 32;                                        % length of data sequence
U     = exp(-((1:N) - N/4).^2/(2*(N/32)^2));       % Gaussian cause
DEM   = spm_DEM_generate(M,U,{},{32 16});

% display
%--------------------------------------------------------------------------
spm_DEM_qU(DEM.pU)

% invert model - VF
%==========================================================================
DEM  = spm_DFP(DEM);

% overlay true values
%--------------------------------------------------------------------------
spm_figure('GetWin','Figure 1');
spm_DEM_qU(DEM.qU,DEM.pU)

% invert model - DEM
%==========================================================================
DEM  = spm_DEM(DEM);

% overlay true values
%--------------------------------------------------------------------------
spm_DEM_qU(DEM.qU,DEM.pU)


% $Id: WB08_Fig_2.m,v 1.1.1.1 2008/05/09 21:34:52 myself Exp $
%
% This prepares data for Figure 2 which is created with the corresponding
% shell script using GMT.  It also makes a plot in Matlab/Octave.
%
% Wessel, P. and J. M. Becker, 2008, Interpolation using a
%  generalized Green's function for a spherical surface spline
%  in tension, Geophys. J. Int., doi:10.1111/j.1365-246X.2008.03829.x
%
% Replicate Parker and then find the tension that minimizes the misfit at
% his 8 extra validation stations.

load mag_obs_1990.d
loni = mag_obs_1990(:,1);
lati = mag_obs_1990(:,2);
zi   = mag_obs_1990(:,3);
d=1;
% Set global 1x1 grid output coordinates

[X Y] = meshgrid (0:d:360, 0:d:90);

% First Parker's solution (p = 0)
Z = sphsplinet (loni, lati, zi, X, Y);

figure(1); clf
subplot (2,1,1)
contour (X, Y, Z)
drawnow
A = [X(:) Y(:) Z(:)];
save Fig_2_p0.d A -ascii -tabs

%Then used the wrong Oslo longitude to recreate Parker's figure
k = find (loni == 10.45)
loni(k) = 104.5;
Z = sphsplinet (loni, lati, zi, X, Y);
subplot (2,1,2)
contour (X, Y, Z)
A = [X(:) Y(:) Z(:)];
save Fig_2_orig.d A -ascii -tabs


function [mResult, fMls, fMc, fMu, fSigma, mDatPredBest, vPredBest, fBvalue, fAvalue] = calc_McCdfnormal(mCatalog, fBinning)
    % Determine Mc using maximum likelihood estimate; same as calc_McEMR but with output of modeled data
    % [mResult, fMls, fMc, fMu, fSigma, mDatPredBest, vPredBest, fBvalue, fAvalue] = calc_McCdfnormal(mCatalog, fBinning);
    % -----------------------------------------------------------------------------------------------------------------------------
    % Determine Mc using maximum likelihood estimate; same as calc_McEMR but with output of modeled data
    % Fitting non-cumulative frequency magnitude distribution above and below Mc:
    % below: Cumulative NORMAL density function
    % above: Gutenberg-Richter law
    %
    % Incoming variables:
    % mCatalog   : EQ catalog
    % fBinning   : Binning interval, usually 0.1
    %
    % Outgoing variables:
    % mResult     : Solution matrix including
    %               vProbability: maximum likelihood score
    %               vMc         : Mc values
    %               vX_res      : mu (of normal CDF), sigma (of normal CDF), residuum, exitflag
    %               vNmaxBest   : Number of events in lowest magnitude bin considered complete
    %               vABValue    : a and b-value
    % fMls       : minimum maximum likelihood score --> best Mc
    % fMc        : Best estimated magnitude of completeness
    % mDatPredBest   : Matrix of non-cumulative FMD [Prediction, magnitudes, original distribution]
    % vPredBest      : Matrix of non-cumulative FMD below Mc [magnitude, prediction, uncertainty of prediction]
    % fBvalue        : b-value
    %
    % J. Woessner: woessner@seismo.ifg.ethz.ch
    % updated: 03.11.03

    % Initialize
    vProbability = [];
    vMc = [];
    vABValue =[];
    mFitRes = [];
    vX_res = [];
    vNCumTmp = [];
    mDataPred = [];
    vPredBest = [];
    vDeltaBest = [];
    vX_res = [];
    vNmaxBest = [];
    mResult=[];
    mDatPredBest = [];

    % Determine exact time period
    fPeriod1 = max(mCatalog.Date) - min(mCatalog.Date);

    % Determine max. and min. magnitude
    fMaxMag = ceil(10 * max(mCatalog.Magnitude)) / 10;

    % Set starting value for Mc loop and LSQ fitting procedure
    fMcTry= calc_Mc(mCatalog, McMethods.MaxCurvature);
    fSmu = abs(fMcTry/2);
    fSSigma = abs(fMcTry/4);
    if (fSmu > 1)
        fSmu = fMcTry/10;
        fSSigma = fMcTry/20;
    end
    fMcBound = fMcTry;

    % Calculate FMD for original catalog
    [vFMDorg, vNonCFMDorg, fmdbins] = calc_FMD(mCatalog);
    % convert answer back to this file's expectations...
    vFMDorg = [fmdbins'; vFMDorg'] % as rows
    vNonCFMDorg = [fmdbins'; vNonCFMDorg'];

    fMinMag = min(vNonCFMDorg(1,:));

    %% Shift to positive values
    % if fMinMag ~= 0
    %     fMcBound = fMcTry-fMinMag;
    % end
    % Loop over Mc-values
    for fMc = fMcBound-0.4:0.1:fMcBound+0.4
        fMc = round(fMc, -1);
        vFMD = vFMDorg;
        vNonCFMD = vNonCFMDorg;
        vNonCFMD = fliplr(vNonCFMD);
        % Calculate a and b-value for GR-law and distribution vNCum
        [nIndexLo, fMagHi, vSel, vMagnitudes] = fMagToFitBValue(mCatalog, vFMD, fMc);
        if (length(mCatalog.Longitude(vSel)) >= 20)
            [ fBValue, fStdDev, fAValue] =  calc_bmemag(mCatalog.Magnitude(vSel), fBinning);
            % Normalize to time period
            vFMD(2,:) = vFMD(2,:)./fPeriod1; % ceil taken out
            vNonCFMD(2,:) = vNonCFMD(2,:)./fPeriod1; % ceil removed
            % Compute quantity of earthquakes by power law
            fMaxMagFMD = max(vNonCFMD(1,:));
            fMinMagFMD = min(vNonCFMD(1,:));
            vMstep = [fMinMagFMD:0.1:fMaxMagFMD];
            vNCum = 10.^(fAValue-fBValue.*vMstep); % Cumulative number

            % Compute non-cumulative numbers vN
            fNCumTmp = 10^(fAValue-fBValue*(fMaxMagFMD+0.1));
            vNCumTmp  = [vNCum fNCumTmp ];
            vN = abs(diff(vNCumTmp));

            % Normalize vN
            vN = vN./fPeriod1;
            % Data selection
            % mData = Non-cumulative FMD values from GR-law and original data
            mData = [vN' vNonCFMD'];
            vSel = (mData(:,2) >= fMc);
            mDataTest = mData(~vSel,:);
            mDataTmp = mData.subset(vSel);
            %         % Check for zeros in observed data
            vSelCheck = (mDataTest(:,3) == 0);
            mDataTest = mDataTest(~vSelCheck,:);
            % Choices of normalization
            fNmax = mDataTmp(1,3); % Frequency of events in Mc bin
            %fNmax = max(mDataTest(:,3));  % Use maximum frequency of events in bins below Mc
            %fNmax = mDataTest(length(mDataTest(:,1)),3); % Use frequency of events at bin Mc-0.1 -> best fit
            if (~isempty(isempty(fNmax)) &&  ~isnan(fNmax) & fNmax ~= 0 & length(mDataTest(:,1)) > 4)
                mDataTest(:,3) = mDataTest(:,3)/fNmax; % Normalize datavalues for fitting with CDF
                % Move to M=0 to fit with lsq-algorithm
                fMinMagTmp = min(mDataTest(:,2));
                mDataTest(:,2) = mDataTest(:,2)-fMinMagTmp;
                % Curve fitting: Non cumulative part below Mc
                options = optimset;
                %options = optimset('Display','off','Tolfun',1e-7,'TolX',0.0001,'MaxFunEvals', 100000,'MaxIter',10000);
                options = optimset('Display','off','Tolfun',1e-5,'TolX',0.001,'MaxFunEvals', 1000,'MaxIter',1000);
                [vX, resnorm, resid, exitflag, output, lambda, jacobian]=lsqcurvefit(@calc_normalCDF,[fSmu  fSSigma], mDataTest(:,2), mDataTest(:,3),[],[],options);
                mDataTest(:,1) = normcdf(mDataTest(:,2), vX(1), vX(2))*fNmax;
                if (length(mDataTest(:,2)) > length(vX(1,:)))
                    %% Confidence interval determination
                    % vPred : Predicted values of lognormal function
                    % vPred+-delta : 95% confidence level of true values
                    [vPred,delta] = nlpredci(@calc_normalCDF,mDataTest(:,2),vX, resid, jacobian);
                else
                    vPred = NaN;
                    delta = NaN;
                end; % END: This section is due for errors produced with datasets less long than amount of parameters in vX
                % Results of fitting procedure
                mFitRes = [mFitRes; vX resnorm exitflag];
                % Move back to original magnitudes
                mDataTest(:,2) = mDataTest(:,2)+fMinMagTmp;
                % Set data together
                mDataTest(:,3) = mDataTest(:,3)*fNmax;
                mDataPred = [mDataTest; mDataTmp];
                % Denormalize to calculate probabilities
                mDataPred(:,1) = round(mDataPred(:,1).*fPeriod1);
                mDataPred(:,3) = mDataPred(:,3).*fPeriod1;
                vProb_ = calc_log10poisspdf2(mDataPred(:,3), mDataPred(:,1)); % Non-cumulative

                % Sum the probabilities
                fProbability = (-1) * sum(vProb_);
                vProbability = [vProbability; fProbability];
                % Move magnitude back
                mDataPred(:,2) = mDataPred(:,2)+fMinMag;
                vMc = [vMc; fMc];
                vABValue = [vABValue; fAValue fBValue];

                % Keep values
                vDeltaBest = [vDeltaBest; delta];
                vX_res = [vX_res; vX resnorm exitflag];
                vNmaxBest = [vNmaxBest; fNmax];

                % Keep best fitting model
                if (fProbability == min(vProbability))
                    vDeltaBest = delta;
                    vPredBest = [mDataTest(:,2) vPred*fNmax*fPeriod1 delta*fNmax*fPeriod1]; % Gives back uncertainty
                    %fMc+fMinMag : Test procedure
                    mDatPredBest = [mDataPred];
                end
            else
                %disp('Not enough data');
                % Setting values
                fProbability = NaN;
                fMc = NaN;
                vX(1) = NaN;
                vX(2) = NaN;
                resnorm = NaN;
                exitflag = NaN;
                delta = NaN;
                vPred = [NaN NaN NaN];
                fNmax = NaN;
                fAValue = NaN;
                fBValue = NaN;
                vProbability = [vProbability; fProbability];
                vMc = [vMc; fMc];
                vX_res = [vX_res; vX resnorm exitflag];
                %             vDeltaBest = [vDeltaBest; NaN];
                %             vPredBest = [vPredBest; NaN NaN NaN];
                vNmaxBest = [vNmaxBest; fNmax];
                vABValue = [vABValue; fAValue fBValue];
            end; % END of IF fNmax
        end; % END of IF length(mCatalog.Longitude(vSel))

        % Clear variables
        vNCumTmp = [];
        mModelDat = [];
        vNCum = [];
        vSel = [];
        mDataTest = [];
        mDataPred = [];
    end; % END of FOR fMc
    % Result matrix
    mResult = [mResult; vProbability vMc vX_res vNmaxBest vABValue];

    % Find best estimate, excluding the case of mResult all NAN
    if  ~isempty(min(mResult))
        if ~isnan(min(mResult(:,1)))
            vSel = find(min(mResult(:,1)) == mResult(:,1));
            fMc = min(mResult(vSel,2));
            fMls = min(mResult(vSel,1));
            fMu = min(mResult(vSel,3));
            fSigma = min(mResult(vSel,4));
            fAvalue = min(mResult(vSel,8));
            fBvalue = min(mResult(vSel,9));
        else
            fMc = NaN;
            fMls = NaN;
            fMu = NaN;
            fSigma = NaN;
            fAvalue = NaN;
            fBvalue = NaN;
        end
    else
        fMc = NaN;
        fMls = NaN;
        fMu = NaN;
        fSigma = NaN;
        fAvalue = NaN;
        fBvalue = NaN;
    end
end


clear all; close all; clc

load catData_w.mat; load dogData_w.mat; CD=[dog_wave cat_wave];
train=[dog_wave(:,1:60) cat_wave(:,1:60)];
test=[dog_wave(:,61:80) cat_wave(:,61:80)];
label=[ones(60,1); -1*ones(60,1)].';

A=label*pinv(train); test_labels=sign(A*test);
subplot(4,1,1), bar(test_labels,'FaceColor',[.6 .6 .6],'EdgeColor','k'), axis off
subplot(4,1,2), bar(A,'FaceColor',[.6 .6 .6],'EdgeColor','k'), axis([0 1024 -0.002 0.002]), axis off
figure(2), subplot(2,2,1)
A2=flipud(reshape(A,32,32)); pcolor(A2), colormap(gray), axis off

figure(1), subplot(4,1,3)
A=lasso(train.',label.','Lambda',0.1).';
test_labels=sign(A*test);
bar(test_labels,'FaceColor',[.6 .6 .6],'EdgeColor','k'), axis off
subplot(4,1,4)
bar(A,'FaceColor',[.6 .6 .6],'EdgeColor','k'), axis([0 1024 -0.008 0.008]), axis off
figure(2), subplot(2,2,2)
A2=flipud(reshape(A,32,32)); pcolor(A2), colormap(gray), axis off


%Navigation frame=Local geodetic Frame.
%Position is mechanized in Cen (essentially Ceg) and h.
%Attitude is mechanized in quat

%Compare this with strapdown_Cen_dcm and strandown_wander_quat. Both of
%these strapdowns implement wander frame mechanization. However, only the
%2nd one is non-singular. Furthermore, also note that the only difference
%between this script and the strandown_wander_quat is the 1st argument of
%geoparam function.

function [qbn_new, Vn_new, Cen_new, h_new]=strapdown_Cen_quat(qbn, Vn, Cen, h, velinc, anginc, dt)
%Compute the transport rate of geodetic frame (also the gravity)
[Fc, wen_n, wie_n, g]=geoparam_v001(2, Cen(:,3), h, Vn); %Compute the curvature matrix for local geodetic frame

%% Update the velocity
vel_inc1=quatrot_v000(qbn,velinc,0); %Note: 'a' is assumed to be output of a sculling module.
vel_inc2=(cross(Vn,2*wie_n+wen_n)+[0;0;g])*dt;
Vn_new=Vn+vel_inc1+vel_inc2;

%%update the attitude
%Body frame updates
qb=rvec2quat_v000(anginc);    %Note: 'w' is assumed to be the output of coning module
qbn_new=quatmult_v000(qbn,qb);

%Navigation frame updates
qn=rvec2quat_v000(-(wen_n+wie_n)*dt);
qbn_new=quatmult_v000(qn,qbn_new);

%%Position update
Vmid=(Vn+Vn_new)/2;
wen_n=Fc*[Vmid(2);-Vmid(1);0];
Cn=rot2dcm_v000(-wen_n*dt);
Cen_new=Cn*Cen;

h_new=h-Vmid(3)*dt;


classdef RMMEDA_F2 < PROBLEM
% <multi> <real> <large/none>
% Benchmark MOP for testing RM-MEDA

%------------------------------- Reference --------------------------------
% Q. Zhang, A. Zhou, and Y. Jin, RM-MEDA: A regularity model-based
% multiobjective estimation of distribution algorithm, IEEE Transactions on
% Evolutionary Computation, 2008, 12(1): 41-63.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        %% Default settings of the problem
        function Setting(obj)
            obj.M = 2;
            if isempty(obj.D); obj.D = 30; end
            obj.lower    = zeros(1,obj.D);
            obj.upper    = ones(1,obj.D);
            obj.encoding = ones(1,obj.D);
        end
        %% Calculate objective values
        function PopObj = CalObj(obj,X)
            g = 1 + 9*mean((X(:,2:end)-repmat(X(:,1),1,size(X,2)-1)).^2,2);
            PopObj(:,1) = X(:,1);
            PopObj(:,2) = g.*(1-(PopObj(:,1)./g).^2);
        end
        %% Generate points on the Pareto front
        function R = GetOptimum(obj,N)
            R(:,1) = linspace(0,1,N)';
            R(:,2) = 1 - R(:,1).^2;
        end
        %% Generate the image of Pareto front
        function R = GetPF(obj)
            R = obj.GetOptimum(100);
        end
    end
end


function Y = spdiag(V,K)
%SPDIAG Sparse diagonal matrices.
%   SPDIAG(V,K) when V is a vector with N components is a sparse square
%   matrix of order N+ABS(K) with the elements of V on the K-th diagonal.
%   K = 0 is the main diagonal, K > 0 is above the main diagonal and K < 0
%   is below the main diagonal.
%
%   SPDIAG(V) is the same as SPDIAG(V,0) and puts V on the main diagonal.
%
%   See also DIAG, SPDIAGS.

%  Ron Rubinstein
%  Computer Science Department
%  Technion, Haifa 32000 Israel
%  ronrubin@cs
%
%  June 2008

if (nargin<2)
  K = 0;
end

n = length(V) + abs(K);

if (K>0)
  i = 1:length(V);
  j = K+1:n;
elseif (K<0)
  i = -K+1:n;
  j = 1:length(V);
else
  i = 1:n;
  j = 1:n;
end

Y = sparse(i,j,V(:),n,n);


function V = LR_sort(W)
N = size(W, 2);
LLR = zeros(1, N);
for i = 1 : N
    if (W(1, i) ~= 0) && (W(2, i) ~= 0)
        LLR(i) = log(W(1, i)) - log(W(2, i));
    else
        if (W(1, i) == 0) && (W(2, i) ~= 0)
            LLR(i) = -inf;
        else
            if (W(1, i) ~= 0) && (W(2, i) == 0)
                LLR(i) = inf;
            end
        end
    end
end
[~, ordered]  = sort(LLR, 'descend');
V = W(:, ordered);
end


function phiFaceAverage = upwindMean3D(phi, u)
% This function gets the value of the field variable phi defined
% over the MeshStructure and calculates the upwind average on
% the cell faces, based on the direction of the velocity vector for a uniform mesh.
%
% SYNOPSIS:
%   phiFaceAverage = upwindMean3D(phivar, u)
%
% PARAMETERS:
%
%
% RETURNS:
%
%
% EXAMPLE:
%
% SEE ALSO:
%

% Written by Ali A. Eftekhari
% See the license file

% extract the velocity data
% note: size(ux) = [1:m+1, 1:n] and size(uy) = [1:m, 1:n+1]
ux = u.xvalue;
uy = u.yvalue;
uz = u.zvalue;

% check the size of the variable and the mesh dimension
Nxyz = phi.domain.dims;
Nx = Nxyz(1); Ny = Nxyz(2); Nz = Nxyz(3);

% assign to a temp variable for boundary corrections
phi_tmp = phi.value;

% correct the value of phi at the boundary (calculation trick)
% assign the value of the left boundary to the left ghost cells
phi_tmp(1,:,:) = (phi.value(1,:,:)+phi.value(2,:,:))/2;
% assign the value of the right boundary to the right ghost cells
phi_tmp(end,:,:) = (phi.value(end,:,:)+phi.value(end-1,:,:))/2;
% assign the value of the bottom boundary to the bottom ghost cells
phi_tmp(:,1,:) = (phi.value(:,1,:)+phi.value(:,2,:))/2;
% assign the value of the top boundary to the top ghost cells
phi_tmp(:,end,:) = (phi.value(:,end,:)+phi.value(:,end-1,:))/2;
% assign the value of the back boundary to the back ghost cells
phi_tmp(:,:,1) = (phi.value(:,:,1)+phi.value(:,:,2))/2;
% assign the value of the front boundary to the front ghost cells
phi_tmp(:,:,end) = (phi.value(:,:,end)+phi.value(:,:,end-1))/2;

% calculate the average value
xvalue = (ux>0).*phi_tmp(1:Nx+1,2:Ny+1,2:Nz+1)+ ...
                        (ux<0).*phi_tmp(2:Nx+2,2:Ny+1,2:Nz+1)+ ...
                        0.5*(ux==0).*(phi.value(1:Nx+1,2:Ny+1,2:Nz+1)+phi.value(2:Nx+2,2:Ny+1,2:Nz+1));
yvalue = (uy>0).*phi_tmp(2:Nx+1,1:Ny+1,2:Nz+1)+ ...
                        (uy<0).*phi_tmp(2:Nx+1,2:Ny+2,2:Nz+1)+ ...
                        0.5*(uy==0).*(phi.value(2:Nx+1,1:Ny+1,2:Nz+1)+phi.value(2:Nx+1,2:Ny+2,2:Nz+1));
zvalue = (uz>0).*phi_tmp(2:Nx+1,2:Ny+1,1:Nz+1)+ ...
                        (uz<0).*phi_tmp(2:Nx+1,2:Ny+1,2:Nz+2)+ ...
                        0.5*(uz==0).*(phi.value(2:Nx+1,2:Ny+1,1:Nz+1)+phi.value(2:Nx+1,2:Ny+1,2:Nz+2));
phiFaceAverage=FaceVariable(phi.domain, xvalue, yvalue, zvalue);


function h = p02_fh ( p, varargin )

%*****************************************************************************80
%
%% P02_FH returns a mesh size function for problem 2.
%
%  Licensing:
%
%    (C) 2004 Per-Olof Persson.
%    See COPYRIGHT.TXT for details.
%
%  Modified:
%
%    06 February 2006
%
%  Reference:
%
%    Per-Olof Persson and Gilbert Strang,
%    A Simple Mesh Generator in MATLAB,
%    SIAM Review,
%    Volume 46, Number 2, June 2004, pages 329-345.
%
%  Parameters:
%
%    Input, real P(NP,ND), the point coordinates.
%
%    Input, VARARGIN, room for extra arguments.
%
%    Output, real H(NP,1), the mesh size function.
%
  np = size ( p, 1 );
  h = ones ( np, 1 );

  return
end


function [stats] = est_checkMVARStability(varargin)
%
% Test the stability of a fitted VAR model. See [1-2] for mathematical
% details on testing VAR stability. A stable VAR process is also a
% stationary VAR process [2].
%
% Inputs:
%
%   EEG:        EEGLAB data structure
%   MODEL:      SIFT MODEL structure
%   typeproc:   reserved for future use. Use 0
%
% Optional:
%
%   <Name,Value> pairs containing model fitting parameters. See
%   est_fitMVAR(). Generally, these should be left unspecified.
%
% Outputs:
%
%   stats
%       .stability:  [numwindows x 1] vector of results of stability tests. 1
%                    indicates stable VAR process for that window, 0 indicates
%                    an unstable VAR process.
%
%       .lambda:     [numwindows x nchs*morder] matrix of eigenvalues of VAR
%                    process. All eigenvalues should be < 1 for stable VAR process
%
%
% [1] Mullen T (2010) The Source Information Flow Toolbox (SIFT):
%     Theoretical Handbook and User Manual. Chapters 3,6.
%     Available at: http://www.sccn.ucsd.edu/wiki/Sift
% [2] Lutkepohl, H. (2007) New Introduction to Time Series Analysis.
%     Springer.
%
% Author: Tim Mullen 2010, SCCN/INC, UCSD
% Email:  tim@sccn.ucsd.edu

% This function is part of the Source Information Flow Toolbox (SIFT)
%
% 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, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

g = arg_define([0 2],varargin, ...
        arg_norep({'EEG','ALLEEG'},mandatory,[],'EEGLAB dataset'), ...
        arg_norep({'MODEL','Model'},mandatory,[],'MVAR MODEL object'), ...
        arg_nogui({'winStartIdx','WindowStartIndices'},[],[],'Starting indices for windows. This is a vector of sample points (start of windows) at which to estimate windowed VAR model. Default is empty (use all windows)','cat','Options'), ...
        arg({'prctWinToSample','WindowSamplePercent'},100,[1 100],'Percent of windows to sample','cat','Options'), ...
        arg({'verb','VerbosityLevel'},2,{int32(0) int32(1) int32(2)},'Verbosity level. 0 = no output, 1 = text, 2 = graphical') ...
        );

% commit EEG and MODEL variables to workspace
[data g] = hlp_splitstruct(g,{'EEG','MODEL'});
arg_toworkspace(data);
clear data;

morder = MODEL.morder;

% window size in points
% winLenPnts = floor(MODEL.winlen*EEG.srate);

if isempty(g.winStartIdx)
    % starting point of each window (points)
    g.winStartIdx  = round(MODEL.winStartTimes*EEG.srate)+1;
end

if g.prctWinToSample<100
    % randomly select percentage of windows to work with
    randwin = randperm(length(g.winStartIdx));
    randwin = sort(randwin(1:ceil(length(g.winStartIdx)*g.prctWinToSample/100)));
    g.winStartIdx = g.winStartIdx(randwin);
    g.winArrayIndex = randwin;
end

% get the array indices of the windows we are working with
g.winArrayIndex = getindex(MODEL.winStartTimes,(g.winStartIdx-1)/EEG.srate);

% initialize waitbar
if g.verb==2
    waitbarTitle = sprintf('Checking stability %s...', ...
        fastif(isempty(EEG.condition),'',['for ' EEG.condition]));

    multiWaitbar(waitbarTitle,'Reset');
    multiWaitbar(waitbarTitle,'ResetCancel',true);
    multiWaitbar(waitbarTitle, ...
                 'Color', hlp_getNextUniqueColor, ...
                 'CanCancel','on', ...
                 'CancelFcn',@(a,b) disp('[Cancel requested. Please wait...]'));
end

numWins = length(g.winStartIdx);

stats.stability = zeros(1,numWins);
[nchs Mp] = size(MODEL.AR{1});
stats.lambda = zeros(numWins,Mp);
%lambda = [];
I = eye(nchs*morder-nchs,nchs*morder-nchs);
O = zeros(nchs*morder-nchs,nchs);
for t=1:numWins
    % get the array index of the window we are working with
    winArrIdx = g.winArrayIndex(t);

    % rewrite VAR[p] process as VAR[1]
    A = [MODEL.AR{winArrIdx} ; [I O]];
    stats.lambda(t,:) = log(abs(eig(A)));
    stats.stability(t) = all(stats.lambda(t,:)<0);

    if g.verb==2
        % update waitbar
        drawnow;
        cancel = multiWaitbar(waitbarTitle,t/numWins);
        if cancel && hlp_confirmWaitbarCancel(waitbarTitle)
            stats = [];
            return;
        end
    end

end

stats.winStartIdx = g.winStartIdx;
stats.winStartTimes = MODEL.winStartTimes(g.winArrayIndex);
stats.winArrayIndex = g.winArrayIndex;

% clean up
if g.verb==2
    multiWaitbar(waitbarTitle,'Close');
end


function [M,fig] = plot_marginals(sampleCell,T,truespikes,int_show)

% Plots marginal posterior empirical pdfs for # of spikes for each timebin
% similar to figure 1B in Pnevmatikakis et al., Neuron 2016

% Inputs:
% sampleCell:   Cell array with spike times in continuous time (SAMPLES.ss)
% T:            Number of timebins
% truespikes:   Number of true spikes per timebin (vector of size T x 1)
% int_show:     Show only a specified interval (default: [1,T])

% Output:
% M:            matrix of empirical posterior pdfs for each timebin

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

if nargin < 4
    int_show = 1:T;
end
nT = length(int_show);

if nargin == 2
    truespikes = -0.5*ones(1,nT);
end

if length(truespikes) == T
    truespikes = truespikes(int_show);
end

Mat = samples_cell2mat(sampleCell,T);
Mat = Mat(:,int_show);

mS = min(max([Mat(:);truespikes(:)])+1,6);
M = zeros(mS,nT);
for i = 1:nT
    M(:,i) = hist(Mat(:,i),0:mS-1)/size(Mat,1);
end

cmap = bone(100);
cmap(2:26,:) = [];
fig = figure;
imagesc(M); axis xy;
%set(gca,'Ytick',[0.5:(mS+.5)],'Yticklabel',[-1:(mS)]);  %hold all; plot(traceData.spikeFrames+1); set(gca,'YLim',[1,5])
%set(gca,'YLim',[1.25,mS+.25]);
hold all; scatter(1:nT,truespikes+1,[],'m');
set(gca,'YLim',[1.5,mS+.125]);
pos = get(gca,'Position');
set(gca,'Ytick',0.5+[-0.5:mS-.5],'Yticklabel',[-1+(0:mS)]);
colormap(cmap);
ylabel('# of Spikes ','fontweight','bold','fontsize',14);
xlabel('Timestep ','fontweight','bold','fontsize',14);
title('Posterior Spike Histogram (MCMC) ','fontweight','bold','fontsize',14);
cbar = colorbar('Location','East');
cpos = get(cbar,'Position');
set(cbar,'Position',[pos(1)+pos(4),cpos(2:4)]);
%set(gca,'Xtick',[])
%set(cbar,'Color',[1,1,1]);
set(cbar,'Fontsize',12);


function [v,y,w]=nearnonz(x,d)
%NEARNONZ replace each zero element with the nearest non-zero element [V,Y,W]=nearnonz(X,D)
%
%  Inputs:  x         input vector, matrix or larger array
%           d         dimension to apply filter along [default 1st non-singleton]
%
% Outputs:  v         v is the same size as x but with each zero entry replaced by
%                     the nearest non-zero value along dimension d
%                     elements equidistant from two non-zero entries will be taken
%                     from the higher index
%           y         y is the same size as x and gives the index along dimension d
%                     from which the corresponding entry in v was taken
%                     If there are no non-zero entries, then the corresponding
%                     elements of y will be zero.
%           w         w is the same size as x and gives the distance (+ or -) to the
%                     nearest non-zero entry in x

%      Copyright (C) Mike Brookes 1997
%      Version: $Id: nearnonz.m 713 2011-10-16 14:45:43Z dmb $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
e=size(x);
p=prod(e);
if nargin<2             % if no dimension given, find the first non-singleton
    d=find(e>1,1);
    if ~numel(d)
        d=1;
    end
end
k=e(d);                 % size of active dimension
q=p/k;                  % size of remainder
if d==1
    z=reshape(x,k,q);
else
    z=shiftdim(x,d-1);
    r=size(z);
    z=reshape(z,k,q);
end
xx=z~=0;
cx=cumsum(xx);
[i,j]=find(z);
qq=cx(xx);
pos=full(sparse(qq,j,i,k,q)); % list the positions of non-zero elements in each column
mp=ceil((pos(1:end-1,:)+pos(2:end,:))*0.5); % find the mid point between consecutive non-zero elements
[i2,j2]=find(pos(2:end,:)>0);
zz=1+cumsum(full(sparse(mp(pos(2:end,:)>0),j2,1,k,q)));
y=pos(zz+repmat((0:q-1)*k,k,1));
v=z(max(y,1)+repmat((0:q-1)*k,k,1));
w=y-repmat((1:k)',1,q);
w(y==0)=0;
if d==1
    y=reshape(y,e);
    v=reshape(v,e);
    w=reshape(w,e);
else
    y=shiftdim(reshape(y,r),length(e)+1-d);
    v=shiftdim(reshape(v,r),length(e)+1-d);
    w=shiftdim(reshape(w,r),length(e)+1-d);
end