% Test: Linear subdivision for triangle meshes
%
% Author: Jesus Mena

% Example: Box
vertices = [10 10 10; -10 10 10; 10 -10 10; -10 -10 10; 10 10 -10; -10 10 -10; 10 -10 -10; -10 -10 -10]';
faces = [1 2 3; 4 3 2; 1 3 5; 7 5 3; 1 5 2; 6 2 5; 8 6 7; 5 7 6; 8 7 4; 3 4 7; 8 4 6; 2 6 4]';

figure(1);
subplot(1,4,1);
plotMesh(vertices, faces);
for i=2:4
 subplot(1,4,i);
 [vertices, faces] = linearSubdivision(vertices, faces);
 plotMesh(vertices, faces);
end

% Example: Tetrahedron
vertices = [10 10 10; -100 10 -10; -100 -10 10; 10 -10 -10]';
faces = [1 2 3; 1 3 4; 1 4 2; 4 3 2]';

figure(2);
subplot(1,4,1);
plotMesh(vertices, faces);
for i=2:4
 subplot(1,4,i);
 [vertices, faces] = linearSubdivision(vertices, faces);
 plotMesh(vertices, faces);
end

% Example: Cylinder
vertices = [0 -5 0; 0 5 0; 10 -5 0; 9.65 -5 2.58; 8.66 -5 5; 7.07 -5 7.07; 5 -5 8.66; 2.58 -5 9.65; 0 -5 10; -2.58 -5 9.65; -5 -5 8.66; -7.07 -5 7.07; -8.66 -5 5; -9.65 -5 2.58; -10 -5 0; -9.65 -5 -2.58; -8.66 -5 -5; -7.07 -5 -7.07; -5 -5 -8.66; -2.58 -5 -9.65; -0 -5 -10; 2.58 -5 -9.65; 5 -5 -8.66; 7.07 -5 -7.07; 8.66 -5 -5; 9.65 -5 -2.58; 10 5 0 ; 9.65 5 2.58; 8.66 5 5; 7.07 5 7.07; 5 5 8.66; 2.58 5 9.65; 0 5 10; -2.58 5 9.65; -5 5 8.66; -7.07 5 7.07; -8.66 5 5; -9.65 5 2.58; -10 5 0; -9.65 5 -2.58; -8.66 5 -5; -7.07 5 -7.07; -5 5 -8.66; -2.58 5 -9.65; -0 5 -10; 2.58 5 -9.65; 5 5 -8.66; 7.07 5 -7.07; 8.66 5 -5; 9.65 5 -2.58]';
faces = [1 3 4; 1 4 5; 1 5 6; 1 6 7; 1 7 8; 1 8 9; 1 9 10; 1 10 11; 1 11 12; 1 12 13; 1 13 14; 1 14 15; 1 15 16; 1 16 17; 1 17 18; 1 18 19; 1 19 20; 1 20 21; 1 21 22; 1 22 23; 1 23 24; 1 24 25; 1 25 26; 1 26 3; 2 28 27; 2 29 28; 2 30 29; 2 31 30; 2 32 31; 2 33 32; 2 34 33; 2 35 34; 2 36 35; 2 37 36; 2 38 37; 2 39 38; 2 40 39; 2 41 40; 2 42 41; 2 43 42; 2 44 43; 2 45 44; 2 46 45; 2 47 46; 2 48 47; 2 49 48; 2 50 49; 2 27 50; 3 27 28; 3 28 4; 4 28 29; 4 29 5; 5 29 30; 5 30 6; 6 30 31; 6 31 7; 7 31 32; 7 32 8; 8 32 33; 8 33 9; 9 33 34; 9 34 10; 10 34 35; 10 35 11; 11 35 36; 11 36 12; 12 36 37; 12 37 13; 13 37 38; 13 38 14; 14 38 39; 14 39 15; 15 39 40; 15 40 16; 16 40 41; 16 41 17; 17 41 42; 17 42 18; 18 42 43; 18 43 19; 19 43 44; 19 44 20; 20 44 45; 20 45 21; 21 45 46; 21 46 22; 22 46 47; 22 47 23; 23 47 48; 23 48 24; 24 48 49; 24 49 25; 25 49 50; 25 50 26; 26 50 27; 26 27 3]';

figure(3);
subplot(1,4,1);
plotMesh(vertices, faces);
for i=2:4
 subplot(1,4,i);
 [vertices, faces] = linearSubdivision(vertices, faces);
 plotMesh(vertices, faces);
end

% Example: Grid
vertices = [-4 -4 0; -2 -4 0; 0 -4 0; 2 -4 0; 4 -4 0; -4 -2 0; -2 -2 0; 0 -2 0; 2 -2 0; 4 -2 0; -4 0 0; -2 0 0; 0 0 0; 2 0 0; 4 0 0; -4 2 0; -2 2 0; 0 2 0; 2 2 0; 4 2 0; -4 4 0; -2 4 0; 0 4 0; 2 4 0; 4 4 0]';
faces = [7 2 1; 1 6 7; 8 3 2; 2 7 8; 9 4 3; 3 8 9; 10 5 4; 4 9 10; 12 7 6; 6 11 12; 13 8 7; 7 12 13; 14 9 8; 8 13 14; 15 10 9; 9 14 15; 17 12 11; 11 16 17; 18 13 12; 12 17 18; 19 14 13; 13 18 19; 20 15 14; 14 19 20; 22 17 16; 16 21 22; 23 18 17; 17 22 23; 24 19 18; 18 23 24; 25 20 19; 19 24 25]';

figure(4);
subplot(1,4,1);
plotMesh(vertices, faces);
for i=2:4
 subplot(1,4,i);
 [vertices, faces] = linearSubdivision(vertices, faces);
 plotMesh(vertices, faces);
end


function [X,Y,Z] = idp3elli(idp,IDP,ns,NP)

%IDP3ELLI 3D ellipsoid from Gaussian IDP.
%   [X,Y,Z] = IDP3ELLI(x0,P,ns,NP) gives X, Y and Z coordinates of the
%   points corresponding to the 2 biggest semi-diametres of the ellipsoid
%   defined by the covariances matrix P and centered at x0:
%
%        (x-x0)'*(P^-1)*(x-x0) = ns^2.
%
%   where P and x0 are obtained by transforming the input inverse-depth
%   point idp and covariance IDP to an euclidean point:
%
%       x0 = idp2p(idp)
%       P = J*IDP*J'
%
%   being J the Jacobian of the conversion function. This conversion is
%   performed internally by the function PROPAGATEUNCERTAINTY.
%
%   The ellipsoid can be plotted in a 3D graphic by just creating a line
%   with line(X,Y,Z).
%
%   See also COV3ELLI, LINE, IDP2P, PROPAGATEUNCERTAINTY.

%   Copyright 2008-2009 Joan Sola @ LAAS-CNRS.

[p,P] = propagateUncertainty(idp,IDP,@idp2p);

[X,Y,Z] = cov3elli(p,P,ns,NP);

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB 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.
%
%   SLAMTB 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 SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


%  jSpectral:  Multitaper spectral analysis, and other time series tools
%
%  Multitaper spectral analysis
%   sleptap    - Calculate Slepian tapers.
%   mspec      - Multitaper power and cross spectra.
%   mconf      - Confidence intervals for the multitaper spectral estimate.
%
%  Multitaper polarization analysis
%   msvd       - Singular value decomposition for polarization analysis.
%   polparams  - Spectral matrix polarization parameters.
%   specdiag   - Diagonalize a 2 x 2 spectral matrix.
%
% Assorted other transforms
%   slidetrans  - Sliding-window ('moving-window') Fourier transform.
%   anatrans    - Analytic part of signal.
%   wigdist     - Wigner distribution (alias-free algorithm).
%
% Time series analysis utilities
%   doublen     - Interpolates a time series to double its length.
%   fourier     - The one-sided Fourier frequencies for a given length time series.
%   sampletimes - Computes mean sampling intervals and their statistics.
%
%  Plotting tools
%   twospecplot - Plots a pair of rotary or Cartesian spectra.
%
%  See also jWavelet, jEllipse, jMatern.

%   Low-level functions
%   timeseries_boundary - Apply boundary conditions to data before transform.

help jspectral


function Fitness = CalFitness(PopObj)
% Calculate the fitness of each solution

%------------------------------- 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".
%--------------------------------------------------------------------------

    N = size(PopObj,1);

    %% Detect the dominance relation between each two solutions
    Dominate = false(N);
    for i = 1 : N-1
        for j = i+1 : N
            k = any(PopObj(i,:)<PopObj(j,:)) - any(PopObj(i,:)>PopObj(j,:));
            if k == 1
                Dominate(i,j) = true;
            elseif k == -1
                Dominate(j,i) = true;
            end
        end
    end

    %% Calculate S(i)
    S = sum(Dominate,2);

    %% Calculate R(i)
    R = zeros(1,N);
    for i = 1 : N
        R(i) = sum(S(Dominate(:,i)));
    end

    %% Calculate D(i)
    Distance = pdist2(PopObj,PopObj);
    Distance(logical(eye(length(Distance)))) = inf;
    Distance = sort(Distance,2);
    D = 1./(Distance(:,floor(sqrt(N)))+2);

    %% Calculate the fitnesses
    Fitness = R + D';
end


function[varargout]=cms2kmd(varargin)
%CMS2KMD  Converts centimeters per second to kilometers per day.
%
%   Y=CMS2KMD(X)   <==>  Y=X*(3600*24/100/1000)
%   __________________________________________________________________
%   This is part of JLAB --- type 'help jlab' for more information
%   (C) 2012--2015 J.M. Lilly --- type 'help jlab_license' for details

for i=1:nargin
    varargout{i}=(3600*24/100/1000).*varargin{i};
end


%  Figure 7.18      Feedback Control of Dynamic Systems, 6e
%                        Franklin, Powell, Emami
%
% fig7_18.m
% script to plot the step position responses of the tape
% drive servo with dominant second order, and LQR designs
clf;

f =[0    2.0000         0         0         0;
   -0.1000   -0.3500    0.1000    0.1000    0.7500;
         0         0         0    2.0000         0 ;
    0.4000    0.4000   -0.4000   -1.4000         0  ;
         0   -0.0300         0         0   -1.0000   ];

g =[0;
     0;
     0 ;
     0  ;
     1   ];
h3 =[0.5000         0    0.5000         0         0];
ht =[-0.2000   -0.2000    0.2000    0.2000         0];

p2 =[-0.7070+0.7070*i;
  -0.7070-0.7070*i    ;
  -4.0000               ;
  -4.0000                ;
  -4.0000                 ];

j=0;
p22 =p2/1.5;
k2=acker(f,g,p22);

k2 =[8.5123   20.3457   -1.4911   -7.8821    6.1927];

f2c=f-g*k2;

s=[f g;h3 j];
r=[0 0 0 0 0 1]';
n=s\r;
nu=n(6)
nx=n(1:5)
nbar2=k2*nx+nu
t=0:.2:12;
sys2=ss(f2c,g*nbar2,h3,j);
y2=step(sys2,t);
% lqr
kqr=lqr(f,g,h3'*h3,1)

klqr =[0.6526    2.1667    0.3474    0.5976    1.0616];

flqrc=f-g*klqr;
nbarlqr = klqr*nx+nu;

syslqr=ss(flqrc,g*nbarlqr,h3,j);
ylqr=step(syslqr,t);

plot(t,y2,t,ylqr,'-.','LineWidth',2);
xlabel('Time (msec)');
ylabel('Tape position, x_3');
text(5,1.1, 'LQR');
text(4.5,.9,'Dominant second-order');
title('Fig. 7.18: Step responses of tape servo designs');
nicegrid;


function [x,info] = amgMaxwellinterface(A,b,node,edge,option)
%% AMGMAXWELL algebraic multigrid solver for Maxwell equations.
%
% x = amgMaxwell(A,b,node,edge) attempts to solve the system of
% linear equations Ax = b using multigrid type solver. The linear system is
% obtained by either the first or second family of linear edge element
% discretization of the Maxwell equation; See doc Maxwell.
%
% amgMaxwell is more algebraic than mgMaxwell but still requires geometric
% information node and edge. Grapha Laplacian of vertices are used as
% auxiliary Poisson operator and amg is used as Poisson solver.
%
% Input
%   -  A: curl(alpha curl) + beta I
%   -  b: right hand side
%   -  node,edge: mesh information
%   -  options: extra structures
%
% By default, the HX preconditioned PCG is used which works well for
% symmetric positive definite matrices (e.g. arising from eddy current
% simulation). For symmetric indefinite matrices (e.g. arising from time
% harmonic Maxwell equation), set option.solver = 'minres' or 'bicg' or
% 'gmres' to try other Krylov method with HX preconditioner.
%
% See also mg, mgMaxwell, mgMaxwellsaddle
%
% Reference:
% R. Hiptmair and J. Xu, Nodal Auxiliary Space Preconditioning in
% H(curl) and H(div) Spaces. SIAM J. Numer. Anal., 45(6):2483-2509, 2007.
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

t = cputime;
%% Initial check
Ndof = length(b);                  % number of dof
N = size(node,1);                  % number of nodes
NE = size(edge,1);                 % number of edge;
dim = size(node,2);
% Assign default values to unspecified parameters
if ~exist('option','var')
    option = [];
end
option = mgoptions(option,length(b));    % parameters
x0 = option.x0;
% N0 = option.N0;
tol = option.tol;
%tol = 5*10^(-7);
% mu = option.smoothingstep; preconditioner = option.preconditioner; coarsegridsolver = option.coarsegridsolver;
printlevel = option.printlevel; %setupflag = option.setupflag;
maxIt = 2000; %400;   % increase the default step (200) for Maxwell equations
% tol = 1e-7;    % reset the tol
% Check for zero right hand side
if (norm(b) == 0)                  % if rhs vector is all zeros
    x = zeros(Ndof,1);             % then solution is all zeros
    flag = 0;
    itStep = 0;
    err = 0;
    time = cputime - t;
    info = struct('solverTime',time,'itStep',itStep,'error',err,'flag',flag,'stopErr',max(err(end,:)));
    return
end

%% Transfer operators from nodal element to edge element
if isfield(option,'isBdEdge')
    isBdEdge = option.isBdEdge;
else
    deg = sum(spones(A(1:NE,1:NE)),2);
    isBdEdge = (deg == 1);
end
if Ndof == NE        % lowest order edge element
    II = node2edgematrix(node,edge,isBdEdge);
elseif Ndof >= 2*NE  % first or second order edge element
    II = node2edgematrix1(node,edge,isBdEdge);
end
IIt = II';
[grad,isBdNode] = gradmatrix(edge,isBdEdge);
gradt = grad';

%% Block smoother
%if option.blklevel == 0 || ~isfield(option,'blklevel')

interfaceEdgeID = option.blkId+1:NE;
interfaceEdge = false(NE, 1);
interfaceEdge(option.blkId+1:NE) = true;
regularEdge = false(NE, 1);
regularEdge(1:option.blkId) = true;

if isfield(option,'blklevel')

    ExtLevel = 0;
    while (ExtLevel<option.blklevel)

        V2Emat= sparse([1:NE,1:NE]',[edge(:,1);edge(:,2)],1,NE,N);
        interfaceNodeID = union(edge(interfaceEdgeID,1),edge(interfaceEdgeID,2));
        interfaceNode = false(N, 1); interfaceNode(interfaceNodeID) = true;
        interfaceEdge = (V2Emat*interfaceNode>0);
        regularEdge = ~interfaceEdge;
        interfaceEdgeID = find(interfaceEdge==1);
        ExtLevel = ExtLevel+1;

    end

end

Ainterface = A(interfaceEdge,interfaceEdge);
Aregular = A(regularEdge,regularEdge);
B = A(interfaceEdge, regularEdge);
D = diag(Aregular);

tic
if isfield(option,'fact') == 1
    switch option.fact
        case 'lu'
            [L,U,P,Q] = lu(Ainterface);
        case 'chol'
            [R,flag,P] = chol(Ainterface);
    end
else
    [L,U,P,Q] = lu(Ainterface);
end
toc

%% Auxiliary Poisson matrix
%   -  A: curl(alpha curl) + beta I
%   - AP: - div(alpha grad) + beta I
%   - BP: - div(beta grad)

if isfield(option,'AP')
    AP = option.AP;
   edgeVec = node(edge(:,2),:) - node(edge(:,1),:);
%     edgeLength = sqrt(sum(edgeVec.^2,2));
%     if isfield(option,'beta') % resacle by the dielectric coefficients
%         if isreal(option.beta) && (length(option.beta) == NE)
%            beta = option.beta;
%         else % option.beta is a function
%            edgeMiddle = (node(edge(:,2),:) + node(edge(:,1),:))/2;
%            beta = option.beta(edgeMiddle);
%         end
%     end
%     M = accumarray(edge(:),repmat((edgeLength.^3).*beta,2,1),[N 1]);
%     AP = AP + spdiags(M,0,N,N);
else
    % build graph Laplacian to approximate AP
    edgeVec = node(edge(:,2),:) - node(edge(:,1),:);
    edgeLength = sqrt(sum(edgeVec.^2,2));
    if isfield(option,'alpha') % resacle by the magnetic coefficients
        if isreal(option.alpha) && (length(option.alpha) == NE)
           alpha = option.alpha;
        else % option.alpha is a function
           edgeMiddle = (node(edge(:,2),:) + node(edge(:,1),:))/2;
           alpha = option.alpha(edgeMiddle);
        end
    end
    % edge weight: h*alpha
    % AP = gradt*spdiags(edgeLength.*alpha,0,NE,NE)*grad;
    i1 = (1:NE)'; j1 = double(edge(:,1)); s1 = sqrt(edgeLength.*alpha);
    i2 = (1:NE)'; j2 = double(edge(:,2)); s2 = -s1;
    isFreeEdge = ~isBdEdge;
    G = sparse([i1(isFreeEdge);i2(isFreeEdge)],...
        [j1(isFreeEdge);j2(isFreeEdge)],...
        [s1(isFreeEdge);s2(isFreeEdge)],NE,N);
    %i1 = (1:NE)'; j1 = double(edge(:,1)); s1 = ones(size(alpha)).*sqrt(alpha);
%     i2 = (1:NE)'; j2 = double(edge(:,2)); s2 = -s1;
%     isFreeEdge = ~isBdEdge;
%     G = sparse([i1(:);i2(:)],...
%         [j1(:);j2(:)],...
%         [s1(:);s2(:)],NE,N);
    AP = G'*G;
    %E = G'*A*G;
    % lumped mass matrix: h^3*beta
    if isfield(option,'beta') % resacle by the dielectric coefficients
        if isreal(option.beta) && (length(option.beta) == NE)
           beta = option.beta;
        else % option.beta is a function
           edgeMiddle = (node(edge(:,2),:) + node(edge(:,1),:))/2;
           beta = option.beta(edgeMiddle);
        end
    end
    M = accumarray(edge(:),repmat((edgeLength.^3).*beta,2,1),[N 1]);
    AP = AP + spdiags(M,0,N,N);
end
% BP is Galerkin projection to the free node space
% boundary nodes
bdidx = zeros(N,1);
bdidx(isBdNode) = 1;
Tbd = spdiags(bdidx,0,N,N);
BP = gradt*A(1:NE,1:NE)*grad + Tbd;
%BP = gradt*spdiags(edgeLength.*beta,0,NE,NE)*grad + Tbd;
% if strcmp(option.outsolver,'minres')
%     BP = gradt*option.BPP(1:NE,1:NE)*grad + Tbd;
% end

setupOption.solver = 'NO';
[x,info,APi,Ri,RRi,ResAP,ProAP,clA] = amg(AP,ones(N,1),setupOption); %#ok<ASGLU>
[x,info,BPi,Si,SSi,ResBP,ProBP,clB] = amg(BP,ones(N,1),setupOption); %#ok<ASGLU>

%% Krylov iterative methods with HX preconditioner
k = 1;
err = 1;
switch upper(option.outsolver)
    case 'CG'
        if printlevel>=1
            fprintf('Conjugate Gradient Method using HX preconditioner \n');
        end
        x = x0;
        r = b - A*x;
        nb = norm(b);
        err = zeros(maxIt,2);
        err(1,:) = norm(r)/nb;
        while (max(err(k,:)) > tol) && (k <= maxIt)
            % compute Br by HX preconditioner
            Br = HXpreconditioner(r);
            % update tau, beta, and p
            rho = r'*Br;  % r'*Br = e'*ABA*e approximates e'*A*e
            if k==1
                p = Br;
            else
                beta = rho/rho_old;
                p = Br + beta*p;
            end
            % update alpha, x, and r
            Ap = A*p;
            alpha = rho/(Ap'*p);
            r = r - alpha*Ap;
            x = x + alpha*p;
            rho_old = rho;
            % compute err for the stopping criterion
            k = k + 1;
            err(k,1) = sqrt(abs(rho/(x'*b))); % approximate relative error in energy norm
            err(k,2) = norm(r)/nb; % relative error of the residual in L2-norm
            if printlevel >= 2
                fprintf('#dof: %8.0u, HXCG iter: %2.0u, err = %12.8g\n',...
                         Ndof, k, max(err(k,:)));
            end
        end
        err = err(1:k,:);
        itStep = k-1;
        if k > maxIt || (max(err(end,:))>tol)
            flag = 1;
        else
            flag = 0;
        end
    case 'MINRES'
        fprintf('Minimum Residual Method with HX preconditioner \n')
        [x,flag,err,itStep] = minres(A,b,tol,maxIt,@HXpreconditioner,[],x0);
%         x = minres(A,b,tol,maxIt,@HXpreconditioner,[],x0);
    case 'GMRES'
        fprintf('General Minimum Residual Method with HX preconditioner \n')
        tic
        [x,flag,err,itStep] = gmres(A,b,10,tol,maxIt,@HXpreconditioner,[],x0);
        toc
        itStep = (itStep(1) -1)*10 + itStep(2);
end

%% Output
time = cputime - t;
if printlevel >= 1
    fprintf('#dof: %8.0u,   #nnz: %8.0u,   iter: %2.0u,   err = %8.4e,   time = %4.2g s\n',...
                 Ndof, nnz(A), itStep, max(err(end,:)), time)
end
if  (flag == 1) && (printlevel>0)
    fprintf('NOTE: the iterative method does not converge');
end
info = struct('solverTime',time,'itStep',itStep,'error',err,'flag',flag,'stopErr',max(err(end,:)));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% subfunctions HXpreconditioner
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function Br = HXpreconditioner(r)
    %% 1. Smoothing in the finest grid of the original system
    if strcmp(option.smoother,'BD')
        if isfield(option,'fact') == 1
            switch option.fact
                case 'lu'
                    eh = zeros(NE, 1);
                    eh(regularEdge,:) = 0.75*r(regularEdge,:)./D;
                    %        eh(interfaceEdge,:) = Ainterface\r(interfaceEdge,:);
                    rtmp = P*r(interfaceEdge,:);
                    rtmp = L\rtmp;
                    rtmp = U\rtmp;
                    rtmp = Q*rtmp;
                    eh(interfaceEdge,:) = rtmp;
                case 'chol'
                    eh = zeros(NE, 1);
                    eh(regularEdge,:) = 0.75*r(regularEdge,:)./D;
                    %        eh(interfaceEdge,:) = Ainterface\r(interfaceEdge,:);
                    rtmp = P'*r(interfaceEdge,:);
                    rtmp = R'\rtmp;
                    rtmp = R\rtmp;
                    rtmp = P*rtmp;
                    eh(interfaceEdge,:) = rtmp;
            end
        else
            eh = zeros(NE, 1);
            eh(regularEdge,:) = 0.75*r(regularEdge,:)./D;
            %        eh(interfaceEdge,:) = Ainterface\r(interfaceEdge,:);
            rtmp = P*r(interfaceEdge,:);
            rtmp = L\rtmp;
            rtmp = U\rtmp;
            rtmp = Q*rtmp;
            eh(interfaceEdge,:) = rtmp;
        end
    elseif strcmp(option.smoother,'GS')
        %         eh = triu(A)\(D.*(tril(A)\r)); # does not work if interface edge is
        %         not treated differently
        rN = r(regularEdge); rI = r(interfaceEdge);
        rN = rN./D; rI = Ainterface\rI;
        ehN = rN + B'*(Ainterface\(B*rN))./D - B'*rI./D;
        ehI = -Ainterface\(B*rN) + rI;
        eh = [ehN; ehI];
    else
        eh = 0.75*r./D;  % Jacobi method. less computational time
    end
    %% 2. amg solver for auxiliary operators
    amgoption.solvermaxit = 3;  % 3 for SPD matrix
    amgoption.printlevel = 0;
    rc = reshape(IIt*r(1:size(IIt,2)),N,dim);   % transfer to the nodal linear element space
    %eaux = II*reshape(AP\rc,dim*N,1);
    %eaux = II*reshape(amg(AP,rc,amgoption),dim*N,1);
    rAP = amgInterface(AP,rc,APi,Ri,RRi,ResAP,ProAP,clA,amgoption);
    eaux = II*reshape(rAP,dim*N,1);
    eh = eh + eaux;
    rb = gradt*r(1:NE);
    %eauxb = grad*(BP\rb);
    %eauxb = grad*(amg(BP,rb,amgoption));
    rBP = amgInterface(BP,rb,BPi,Si,SSi,ResBP,ProBP,clB,amgoption);
    eauxb = grad*rBP;
    Br = eh + eauxb;
    end

    function z = amgInterface(M,r0,Ai,Bi,BBi,Res,Pro,cl,amgoption)

        maxItz = amgoption.solvermaxit;
        Nb = size(r0,2);
        z = repmat(zeros(size(r0,1),1),1,Nb);
        kz = 1;
        rz = r0 - M*z;
        nbz = max(sqrt(sum(r0.^2,1)));
        errz = zeros(maxItz,2);
        errz(1,:) = max(sqrt(sum(rz.^2,1)))/nbz;

        amgprintlevel = amgoption.printlevel;
        level = max(min(ceil(log2(N)/2-4),8),2);
        prefunc = @wcycle;
        if amgprintlevel >= 1
            fprintf('Conjugate Gradient Method\n')
        end
        if isfield(amgoption,'smoothingstep')  % smoothing steps
            mu = amgoption.smoothingstep;
        else
            mu = 2;
        end

        while (max(errz(kz,:)) > tol) && (kz <= maxItz)
            % compute Br by MG
            Brz = prefunc(r0);
            % update tau, beta, and p
            rhoz = dot(Brz,r0);  % e'*ABA*e approximates e'*A*e
            if kz == 1
                pz = Brz;
            else
                betaz = rhoz./rho_oldz;
                pz = Brz + betaz.*pz;
            end
            % update alpha, x, and r
            Apz = M*pz;
            alpha = rhoz./dot(Apz,pz);
            r0 = r0 - alpha.*Apz;
            z = z + alpha.*pz;
            rho_oldz = rhoz;
            kz = kz + 1;
            % compute err for the stopping criterion
        %     err(k,1) = alpha*sqrt(p'*Ap/(x'*A*x)); % increamental error in energy norm
            errz(kz,1) = max(sqrt(abs(rhoz./dot(z,r0)))); % approximate relative error in energy norm
            errz(kz,2) = max(sqrt(sum(r0.^2,1)))/nbz; % relative error of the residual in L2-norm
            if amgprintlevel >= 2
                fprintf('#dof: %8.0u, MGCG iter: %2.0u, err = %8.4e\n',...
                         N, kz-1, max(errz(kz,:)));
            end
        end
        errz = errz(1:kz,:);
        itStepz = kz-1;

        function e = wcycle(r,J)        % solve equations Ae = r in each level
            if nargin<=1
                J = level;
            end
            if J == cl
                e = Ai{cl}\r;   % exact solver in the coaresest grid
                return
            end
            % fine grid pre-smoothing
            e = Bi{J}\r;   % pre-smoothing
            for s = 1:mu           % extra mu steps smoothing
                e = e + Bi{J}\(r-Ai{J}*e);
            end
            rc = Res{J}*(r - Ai{J}*e);
            % coarse grid correction twice
            ec = wcycle(rc,J-1);
            ec = ec + wcycle(rc - Ai{J-1}*ec,J-1);
            % fine grid post-smoothing
            e = e + Pro{J-1}*ec;
            e = e + BBi{J}\(r-Ai{J}*e);
            for s = 1:mu
                e = e + BBi{J}\(r-Ai{J}*e); % post-smoothing
            end
        end

    end

end


function [distri]=Cell_follicledistribution(segout, I1,coeff, n)
if(~exist('n','var'))
    n=13;
end
[boundary(:,2),boundary(:,1)]=find(segout==255);

[fo(:,2), fo(:,1)]=find(I1==1);
theta1=orderpoints(boundary, mean(boundary), coeff);
[trash, index1]=sort(theta1,'ascend');
theta1=theta1(index1);
boundary=boundary(index1,:);

theta2=orderpoints(fo, mean(boundary), coeff);
[trash, index2]=sort(theta2,'ascend');
theta2=theta2(index2);
fo=fo(index2,:);

center=mean(boundary);
KK=500;
interval=linspace(0,2*pi,n);
inter=1:floor(n/4):n;
figure;
imshow(I1)

for i=1:n-1
    hold on
    index_boundary=find(theta1>interval(i)&theta1<=interval(i+1));
    index_focell=find(theta2>interval(i)&theta2<=interval(i+1));
    length(i)=level_center_length(boundary(index_boundary,:)',size(boundary,2));
    number_focell(i)=numel(index_focell);
    temp=coeff*[cos(interval(i));sin(interval(i))];
    if ~ismember(i, inter)
        hold on
        plot([center(1)-KK*temp(1), center(1)+KK*temp(1)],...
            [center(2)-KK*temp(2), center(2)+KK*temp(2)],'r-','linewidth',2)
    end
end

hold on
scatter(center(1), center(2),100, 'ro','filled')
hold on
quiver(center(1)-KK*coeff(1,1),center(2)-KK*coeff(2,1),...
    2*KK*coeff(1,1), 2*KK*coeff(2,1),'g-','linewidth',2)
hold on
quiver(center(1)-KK*coeff(1,2),center(2)-KK*coeff(2,2),...
    2*KK*coeff(1,2), 2*KK*coeff(2,2),'g-','linewidth',2)
distri=number_focell./length;

p=[];
for i=1:n-1
    temp=linspace(interval(i),interval(i+1),100);
    ptemp=[distri(i)*sin(temp);distri(i)*cos(temp)];
    p=[p;ptemp'];
end
p=p*coeff';

KK1=25;
figure;
scatter(p(:,2),p(:,1),'filled')
for i=1:n-1
     temp=coeff*[cos(interval(i));sin(interval(i))];
    if ~ismember(i, inter)
        hold on
        plot([-KK1*temp(1), +KK1*temp(1)],...
            [+KK1*temp(2), -KK1*temp(2)],'r-','linewidth',2)
    end
end
hold on
scatter(0, 0,100, 'ro','filled')
hold on
quiver(-KK1*coeff(1,1),KK1*coeff(2,1),...
    2*KK1*coeff(1,1), -2*KK1*coeff(2,1),'g-','linewidth',2)
hold on
quiver(-KK1*coeff(1,2),KK1*coeff(2,2),...
    2*KK1*coeff(1,2), -2*KK1*coeff(2,2),'g-','linewidth',2)
axis equal


function [meanAmp,meanPh,seZ,meanStd] = vectorMean(view,scanNum,ROIcoords)
%
% [meanAmp,meanPh,seZ,meanStd] = vectorMean(view,scanNum,ROIcoords)
%
% Calculates mean amplitude and phase for pixels that are in
% ROIcoords.
% The standard error (std(z)/sqrt(length(z))) can also
% returned.  This is the average distance of the complex values
% z = amp*exp(-i(ph)) from the mean of z.
%
% Can >also< return the mean noise std in the ROI:
% Computed from the coherence and the amplitude.
%
% scanNum: scan number (integer)
% ROIcoords: 3xN array of (y,x,z) coords (e.g., corresponding to
%   the selected ROI).
%
% djh 4/23/98
% bw  2/17/99 Added seZ computation.
%
% Get co and ph (vectors) for the desired scan, within the
% current ROI.
%
subAmp = getCurDataROI(view,'amp',scanNum,ROIcoords);
subPh = getCurDataROI(view,'ph',scanNum,ROIcoords);
subCo = getCurDataROI(view,'co',scanNum,ROIcoords);

% Remove NaNs from subCo and subAmp that may be there if ROI
% includes volume voxels where there is no data.
NaNs = find(isnan(subPh));
if ~isempty(NaNs)
  disp('ROI includes voxels that have no data.  These voxels are being ignored.');
  notNaNs = find(~isnan(subPh));
  subPh = subPh(notNaNs);
  subAmp = subAmp(notNaNs);
  subCo= subCo(notNaNs);

end

% Compute the mean co right here...
meanCo=mean(subCo);

% convert to complex numbers
z = subAmp .* exp(sqrt(-1)*subPh);
if isempty(z)
   disp('Warning: no activity seen for current ROI');
   seZ = 0;
   meanAmp = 0;
   meanPh = 0;
else
	meanZ = mean(z);

    if nargout > 2
        seZ   = std(z)/sqrt(length(z));
    end
    meanAmp = abs(meanZ);
	meanPh = angle(meanZ);
end
% Compute the meanStd right here...
meanStd=meanAmp.*sqrt((1/mean(subCo).^2)-1);

return;

% Debug

coords = INPLANE{1}.ROIs(INPLANE{1}.selectedROI).coords;
scan = 1;
[meanAmp,meanPh] = vectorMean(INPLANE{1},scan,coords)


function lik = lik_lgp(varargin)
%LIK_LGP  Create a logistic Gaussian process likelihood structure
%
%  Description
%    LIK = LIK_LGP creates a logistic Gaussian process likelihood structure
%
%    The likelihood is defined as follows:
%               __ n
%      p(y|f) = || i=1 exp(f_i) / Sum_{j=1}^n exp(f_j),
%
%      where f contains latent values.
%
%  Reference
%
%    Jaakko Riihimäki and Aki Vehtari (2014). Laplace approximation
%    for logistic Gaussian process density estimation and
%    regression. Bayesian analysis, in press.
%
%  See also
%    LGPDENS, GP_SET, LIK_*
%
% Copyright (c) 2011 Jaakko Riihimäki and Aki Vehtari

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

  ip=inputParser;
  ip.FunctionName = 'LIK_LGP';
  ip.addOptional('lik', [], @isstruct);
  ip.parse(varargin{:});
  lik=ip.Results.lik;

  if isempty(lik)
    init=true;
    lik.type = 'LGP';
    lik.nondiagW = true;
  else
    if ~isfield(lik,'type') || ~isequal(lik.type,'LGP')
      error('First argument does not seem to be a valid likelihood function structure')
    end
    init=false;
  end

  if init
    % Set the function handles to the subfunctions
    lik.fh.pak = @lik_lgp_pak;
    lik.fh.unpak = @lik_lgp_unpak;
    lik.fh.ll = @lik_lgp_ll;
    lik.fh.llg = @lik_lgp_llg;
    lik.fh.llg2 = @lik_lgp_llg2;
    lik.fh.llg3 = @lik_lgp_llg3;
    lik.fh.tiltedMoments = @lik_lgp_tiltedMoments;
    lik.fh.predy = @lik_lgp_predy;
    lik.fh.invlink = @lik_lgp_invlink;
    lik.fh.recappend = @lik_lgp_recappend;
  end

end

function [w,s,h] = lik_lgp_pak(lik)
%LIK_LGP_PAK  Combine likelihood parameters into one vector.
%
%  Description
%    W = LIK_LGP_PAK(LIK) takes a likelihood structure LIK
%    and returns an empty verctor W. If LGP likelihood had
%    parameters this would combine them into a single row vector
%    W (see e.g. lik_negbin). This is a mandatory subfunction
%    used for example in energy and gradient computations.
%
%  See also
%    LIK_LGP_UNPAK, GP_PAK

  w = []; s = {}; h=[];
end

function [lik, w] = lik_lgp_unpak(lik, w)
%LIK_LGP_UNPAK  Extract likelihood parameters from the vector.
%
%  Description
%    W = LIK_LGP_UNPAK(W, LIK) Doesn't do anything.
%
%    If LGP likelihood had parameters this would extract them
%    parameters from the vector W to the LIK structure. This
%    is a mandatory subfunction used for example in energy
%    and gradient computations.
%
%
%  See also
%    LIK_LGP_PAK, GP_UNPAK

  lik=lik;
  w=w;

end

function logLik = lik_lgp_ll(lik, y, f, z)
%LIK_LGP_LL    Log likelihood
%
%  Description
%    E = LIK_LGP_LL(LIK, Y, F, Z) takes a likelihood data
%    structure LIK, incedence counts Y, expected counts Z, and
%    latent values F. Returns the log likelihood, log p(y|f,z).
%    This subfunction is needed when using Laplace approximation
%    or MCMC for inference with non-Gaussian likelihoods. This
%    subfunction is also used in information criteria (DIC, WAIC)
%    computations.
%
%  See also
%    LIK_LGP_LLG, LIK_LGP_LLG3, LIK_LGP_LLG2, GPLA_E

  n=sum(y);
  qj=exp(f);
  logLik = sum(f.*y)-n*log(sum(qj));
end

function deriv = lik_lgp_llg(lik, y, f, param, z)
%LIK_LGP_LLG    Gradient of the log likelihood
%
%  Description
%    G = LIK_LGP_LLG(LIK, Y, F, PARAM) takes a likelihood
%    structure LIK, incedence counts Y, expected counts Z
%    and latent values F. Returns the gradient of the log
%    likelihood with respect to PARAM. At the moment PARAM can be
%    'param' or 'latent'. This subfunction is needed when using Laplace
%    approximation or MCMC for inference with non-Gaussian likelihoods.
%
%  See also
%    LIK_LGP_LL, LIK_LGP_LLG2, LIK_LGP_LLG3, GPLA_E

  switch param
    case 'latent'
      n=sum(y);
      qj=exp(f);
      pj=qj./sum(qj);
      deriv=y-n*pj;
  end
end

function g2 = lik_lgp_llg2(lik, y, f, param, z)
%function g2 = lik_lgp_llg2(lik, y, f, param, z)
%LIK_LGP_LLG2  Second gradients of the log likelihood
%
%  Description
%    G2 = LIK_LGP_LLG2(LIK, Y, F, PARAM) takes a likelihood
%    structure LIK, incedence counts Y, expected counts Z,
%    and latent values F. Returns the Hessian of the log
%    likelihood with respect to PARAM. At the moment PARAM can be
%    only 'latent'. G2 is a vector with diagonal elements of the
%    Hessian matrix (off diagonals are zero). This subfunction
%    is needed when using Laplace approximation or EP for
%    inference with non-Gaussian likelihoods.
%
%  See also
%    LIK_LGP_LL, LIK_LGP_LLG, LIK_LGP_LLG3, GPLA_E

  switch param
    case 'latent'
      qj=exp(f);

      % g2 is not the second gradient of the log likelihood but only a
      % vector to form the exact gradient term in gpla_nd_e, gpla_nd_g and
      % gpla_nd_pred functions
      g2=qj./sum(qj);
  end
end

function g3 = lik_lgp_llg3(lik, y, f, param, z)
%LIK_LGP_LLG3  Third gradients of the log likelihood
%
%  Description
%    G3 = LIK_LGP_LLG3(LIK, Y, F, PARAM) takes a likelihood
%    structure LIK, incedence counts Y, expected counts Z
%    and latent values F and returns the third gradients of the
%    log likelihood with respect to PARAM. At the moment PARAM
%    can be only 'latent'. G3 is a vector with third gradients.
%    This subfunction is needed when using Laplace approximation
%    for inference with non-Gaussian likelihoods.
%
%  See also
%    LIK_LGP_LL, LIK_LGP_LLG, LIK_LGP_LLG2, GPLA_E, GPLA_G

  switch param
    case 'latent'
      qj=exp(f);

      % g3 is not the third gradient of the log likelihood but only a
      % vector to form the exact gradient term in gpla_nd_e, gpla_nd_g and
      % gpla_nd_pred functions
      g3=qj./sum(qj);

      %n=sum(y);
      %nf=size(f,1);
      %g3d=zeros(nf,nf);
      %for i1=1:nf
      %  g3dtmp=-g3*g3(i1);
      %  g3dtmp(i1)=g3dtmp(i1)+g3(i1);
      %  g3d(:,i1)=g3dtmp;
      %  %g3i1= n*(-diag(g3d(:,i1)) + bsxfun(@times,g3,g3d(:,i1)') + bsxfun(@times,g3d(:,i1),g3'));
      %end
  end
end

function [logM_0, m_1, sigm2hati1] = lik_lgp_tiltedMoments(lik, y, i1, sigm2_i, myy_i, z)
%LIK_LGP_TILTEDMOMENTS  Returns the marginal moments for EP algorithm
%
%  Description
%    [M_0, M_1, M2] = LIK_LGP_TILTEDMOMENTS(LIK, Y, I, S2,
%    MYY, Z) takes a likelihood structure LIK, incedence counts
%    Y, expected counts Z, index I and cavity variance S2 and
%    mean MYY. Returns the zeroth moment M_0, mean M_1 and
%    variance M_2 of the posterior marginal (see Rasmussen and
%    Williams (2006): Gaussian processes for Machine Learning,
%    page 55). This subfunction is needed when using EP for
%    inference with non-Gaussian likelihoods.
%
%  See also
%    GPEP_E

  error('Not implemented')

end

function [lpy, Ey, Vary] = lik_lgp_predy(lik, Ef, Varf, yt, zt)
%LIK_LGP_PREDY    Returns the predictive mean, variance and density of y
%
%  Description
%    LPY = LIK_LGP_PREDY(LIK, EF, VARF YT, ZT)
%    Returns also the predictive density of YT, that is
%        p(yt | y,zt) = \int p(yt | f, zt) p(f|y) df.
%    This requires also the incedence counts YT, expected counts ZT.
%    This subfunction is needed when computing posterior predictive
%    distributions for future observations.
%
%    [LPY, EY, VARY] = LIK_LGP_PREDY(LIK, EF, VARF) takes a
%    likelihood structure LIK, posterior mean EF and posterior
%    Variance VARF of the latent variable and returns the
%    posterior predictive mean EY and variance VARY of the
%    observations related to the latent variables. This
%    subfunction is needed when computing posterior predictive
%    distributions for future observations.
%

%
%  See also
%    GPLA_PRED, GPEP_PRED, GPMC_PRED

  error('Not implemented')

end

function [df,minf,maxf] = init_lgp_norm(yy,myy_i,sigm2_i,myy)
%INIT_LGP_NORM
%
%  Description
%    Return function handle to a function evaluating LGP *
%    Gaussian which is used for evaluating (likelihood * cavity)
%    or (likelihood * posterior) Return also useful limits for
%    integration. This is private function for lik_lgp. This
%    subfunction is needed by sufunctions tiltedMoments, siteDeriv
%    and predy.
%
%  See also
%    LIK_LGP_TILTEDMOMENTS, LIK_LGP_PREDY

% Not applicable

end

function mu = lik_lgp_invlink(lik, f, z)
%LIK_LGP_INVLINK  Returns values of inverse link function
%
%  Description
%    P = LIK_LGP_INVLINK(LIK, F) takes a likelihood structure LIK and
%    latent values F and returns the values MU of inverse link function.
%    This subfunction is needed when using function gp_predprctmu.
%
%     See also
%     LIK_LGP_LL, LIK_LGP_PREDY

  mu = exp(f);
  mu = mu./sum(mu);

end

function reclik = lik_lgp_recappend(reclik, ri, lik)
%RECAPPEND  Append the parameters to the record
%
%  Description
%    RECLIK = LIK_LGP_RECAPPEND(RECLIK, RI, LIK) takes a
%    likelihood record structure RECLIK, record index RI and
%    likelihood structure LIK with the current MCMC samples of
%    the parameters. Returns RECLIK which contains all the old
%    samples and the current samples from LIK. This subfunction
%    is needed when using MCMC sampling (gp_mc).
%
%  See also
%    GP_MC

  if nargin == 2
    reclik.type = 'LGP';

    % Set the function handles
    reclik.fh.pak = @lik_lgp_pak;
    reclik.fh.unpak = @lik_lgp_unpak;
    reclik.fh.ll = @lik_lgp_ll;
    reclik.fh.llg = @lik_lgp_llg;
    reclik.fh.llg2 = @lik_lgp_llg2;
    reclik.fh.llg3 = @lik_lgp_llg3;
    reclik.fh.tiltedMoments = @lik_lgp_tiltedMoments;
    reclik.fh.predy = @lik_lgp_predy;
    reclik.fh.invlink = @lik_lgp_invlink;
    reclik.fh.recappend = @lik_lgp_recappend;
    return
  end
end


function value = lietzke_condition ( n )

%*****************************************************************************80
%
%% LIETZKE_CONDITION returns the L1 condition of the LIETZKE matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 April 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%
%    Output, real VALUE, the L1 condition.
%
  s = 0;
  k = n;
  for i = 1 : n
    s = s + k;
    if ( mod ( i, 2 ) == 1 )
      k = k - 1;
    end
  end
  a_norm = s;
  if ( n == 1 )
    b_norm = 0.25;
  elseif ( n == 2 )
    b_norm = 5.0 / 6.0;
  else
    b_norm = 2.0;
  end
  value = a_norm * b_norm;

  return
end


function [hold_state, cax, next] = axes(majors,ticks)
% TERNARY.AXES create ternary axis
%   [hold_state, cax, next]  = TERNARY.AXES(MAJORS) creates a ternary axis system using the system
%   defaults and with MAJORS major tickmarks with percentage labels at tick
%   marks. Returns the hold state of the plot.
%
% [hold_state, cax, next]  = TERNARY.AXES(MAJORS,'fractions')  returns the
% axes with fraction of unit at tick marks.

% Author: Carl Sandrock 20050211
% Modifications: FVA:

% To Do

% Modifications

% Modifiers
% (CS) Carl Sandrock

percentage = 1;
if nargin > 1
    switch ticks
        case 'fraction'
            percentage = 0;
        otherwise
            percentage = 1;
    end
end

%TODO: Get a better way of offsetting the labels
xoffset = 0.01;
yoffset = 0.02;

% get hold state
cax = newplot;
next = lower(get(cax,'NextPlot'));
hold_state = ishold;

% get x-axis text color so grid is in same color
tc = get(cax,'xcolor');
ls = get(cax,'gridlinestyle');

% Hold on to current Text defaults, reset them to the
% Axes' font attributes so tick marks use them.
fAngle  = get(cax, 'DefaultTextFontAngle');
fName   = get(cax, 'DefaultTextFontName');
fSize   = get(cax, 'DefaultTextFontSize');
fWeight = get(cax, 'DefaultTextFontWeight');
fUnits  = get(cax, 'DefaultTextUnits');

set(cax, 'DefaultTextFontAngle',  get(cax, 'FontAngle'), ...
    'DefaultTextFontName',   get(cax, 'FontName'), ...
    'DefaultTextFontSize',   get(cax, 'FontSize'), ...
    'DefaultTextFontWeight', get(cax, 'FontWeight'), ...
    'DefaultTextUnits','data')

% only do grids if hold is off
if ~hold_state
	%plot axis lines
	hold on;
	plot ([0 1 0.5 0],[0 0 sin(1/3*pi) 0], 'color', tc, 'linewidth',1,...
                   'handlevisibility','off');
	set(gca, 'visible', 'off');

    % plot background if necessary
    if ~ischar(get(cax,'color')),
       patch('xdata', [0 1 0.5 0], 'ydata', [0 0 sin(1/3*pi) 0], ...
             'edgecolor',tc,'facecolor',get(gca,'color'),...
             'handlevisibility','off');
    end

	% Generate labels
	majorticks = linspace(0, 1, majors + 1);
	majorticks = majorticks(1:end-1);
    if percentage
        labels = num2str(majorticks'*100);
    else
        labels = num2str(majorticks','%1.1g');%Doesn't work! I don't want it to put a leading zero, that's all!
    end

    zerocomp = zeros(size(majorticks)); % represents zero composition

	% Plot right labels (no c - only b a)
	[lxc, lyc] = ternary.coords(1-majorticks, majorticks, zerocomp);
	text(lxc, lyc, [repmat('  ', length(labels), 1) labels]);

	% Plot bottom labels (no b - only a c)
	[lxb, lyb] = ternary.coords(majorticks, zerocomp, 1-majorticks); % fB = 1-fA
	text(lxb, lyb, labels, 'VerticalAlignment', 'Top');

	% Plot left labels (no a, only c b)
	[lxa, lya] = ternary.coords(zerocomp, 1-majorticks, majorticks);
	%text(lxa-xoffset, lya, labels, 'HorizontalAlignment','right');
	text(lxa-xoffset, lya, labels, 'HorizontalAlignment','right');

	nlabels = length(labels)-1;
	for i = 1:nlabels
        plot([lxa(i+1) lxb(nlabels - i + 2)], [lya(i+1) lyb(nlabels - i + 2)], ls, 'color', tc, 'linewidth',1,...
           'handlevisibility','off');
        plot([lxb(i+1) lxc(nlabels - i + 2)], [lyb(i+1) lyc(nlabels - i + 2)], ls, 'color', tc, 'linewidth',1,...
           'handlevisibility','off');
        plot([lxc(i+1) lxa(nlabels - i + 2)], [lyc(i+1) lya(nlabels - i + 2)], ls, 'color', tc, 'linewidth',1,...
           'handlevisibility','off');
    end
end%if ~hold_state

% Reset defaults
set(cax, 'DefaultTextFontAngle', fAngle , ...
    'DefaultTextFontName',   fName , ...
    'DefaultTextFontSize',   fSize, ...
    'DefaultTextFontWeight', fWeight, ...
    'DefaultTextUnits', fUnits );
return%[hold_state, cax, next]


function varargout = pr(varargin)
%VL_PR   Precision-recall curve.
%   [RECALL, PRECISION] = VL_PR(LABELS, SCORES) computes the
%   precision-recall (PR) curve. LABELS are the ground truth labels,
%   greather than zero for a positive sample and smaller than zero for
%   a negative one. SCORES are the scores of the samples obtained from
%   a classifier, where lager scores should correspond to positive
%   samples.
%
%   Samples are ranked by decreasing scores, starting from rank 1.
%   PRECISION(K) and RECALL(K) are the precison and recall when
%   samples of rank smaller or equal to K-1 are predicted to be
%   positive and the remaining to be negative. So for example
%   PRECISION(3) is the percentage of positive samples among the two
%   samples with largest score. PRECISION(1) is the precision when no
%   samples are predicted to be positive and is conventionally set to
%   the value 1.
%
%   Set to zero the lables of samples that should be ignored in the
%   evaluation. Set to -INF the scores of samples which are not
%   retrieved. If there are samples with -INF score, then the PR curve
%   may have maximum recall smaller than 1, unless the INCLUDEINF
%   option is used (see below). The options NUMNEGATIVES and
%   NUMPOSITIVES can be used to add additional surrogate samples with
%   -INF score (see below).
%
%   [RECALL, PRECISION, INFO] = VL_PR(...) returns an additional
%   structure INFO with the following fields:
%
%   info.auc::
%     The area under the precision-recall curve. If the INTERPOLATE
%     option is set to FALSE, then trapezoidal interpolation is used
%     to integrate the PR curve. If the INTERPOLATE option is set to
%     TRUE, then the curve is piecewise constant and no other
%     approximation is introduced in the calculation of the area. In
%     the latter case, INFO.AUC is the same as INFO.AP.
%
%   info.ap::
%     Average precision as defined by TREC. This is the average of the
%     precision observed each time a new positive sample is
%     recalled. In this calculation, any sample with -INF score
%     (unless INCLUDEINF is used) and any additional positive induced
%     by NUMPOSITIVES has precision equal to zero. If the INTERPOLATE
%     option is set to true, the AP is computed from the interpolated
%     precision and the result is the same as INFO.AUC. Note that AP
%     as defined by TREC normally does not use interpolation [1].
%
%   info.ap_interp_11::
%     11-points interpolated average precision as defined by TREC.
%     This is the average of the maximum precision for recall levels
%     greather than 0.0, 0.1, 0.2, ..., 1.0. This measure was used in
%     the PASCAL VOC challenge up to the 2008 edition.
%
%   info.auc_pa08::
%     Deprecated. It is the same of INFO.AP_INTERP_11.
%
%   VL_PR(...) with no output arguments plots the PR curve in the
%   current axis.
%
%   VL_PR() accepts the following options:
%
%   Interpolate:: false
%     If set to true, use interpolated precision. The interpolated
%     precision is defined as the maximum precision for a given recall
%     level and onwards. Here it is implemented as the culumative
%     maximum from low to high scores of the precision.
%
%   NumPositives:: []
%   NumNegatives:: []
%     If set to a number, pretend that LABELS contains this may
%     positive/negative labels. NUMPOSITIVES/NUMNEGATIVES cannot be
%     smaller than the actual number of positive/negative entrires in
%     LABELS. The additional positive/negative labels are appended to
%     the end of the sequence, as if they had -INF scores (not
%     retrieved). This is useful to evaluate large retrieval systems
%     for which one stores ony a handful of top results for efficiency
%     reasons.
%
%   IncludeInf:: false
%     If set to true, data with -INF score SCORES is included in the
%     evaluation and the maximum recall is 1 even if -INF scores are
%     present. This option does not include any additional positive or
%     negative data introduced by specifying NUMPOSITIVES and
%     NUMNEGATIVES.
%
%   Stable:: false
%     If set to true, RECALL and PRECISION are returned in the same order
%     of LABELS and SCORES rather than being sorted by decreasing
%     score (increasing recall). Samples with -INF scores are assigned
%     RECALL and PRECISION equal to NaN.
%
%   NormalizePrior:: []
%     If set to a scalar, reweights positive and negative labels so
%     that the fraction of positive ones is equal to the specified
%     value. This computes the normalised PR curves of [2]
%
%   About the PR curve::
%     This section uses the same symbols used in the documentation of
%     the VL_ROC() function. In addition to those quantities, define:
%
%       PRECISION(S) = TP(S) / (TP(S) + FP(S))
%       RECALL(S) = TPR(S) = TP(S) / P
%
%     The precision is the fraction of positivie predictions which are
%     correct, and the recall is the fraction of positive labels that
%     have been correctly classified (recalled). Notice that the recall
%     is also equal to the true positive rate for the ROC curve (see
%     VL_ROC()).
%
%   REFERENCES:
%   [1] C. D. Manning, P. Raghavan, and H. Schutze. An Introduction to
%   Information Retrieval. Cambridge University Press, 2008.
%   [2] D. Hoiem, Y. Chodpathumwan, and Q. Dai. Diagnosing error in
%   object detectors. In Proc. ECCV, 2012.
%
%   See also VL_ROC(), VL_HELP().
[varargout{1:nargout}] = vl_pr(varargin{:});


function tet_mesh_volumes ( prefix )

%*****************************************************************************80
%
%% MAIN is the main program for TET_MESH_VOLUMES.
%
%  Discussion:
%
%    TET_MESH_VOLUMES determines the element volumes of a tet mesh.
%
%  Usage:
%
%    tet_mesh_volumes ( 'prefix' )
%
%    where
%
%    * 'prefix'_nodes.txt contains nodal coordinates;
%    * 'prefix'_elements.txt contains the element definitions;
%    * 'prefix'_volumes.txt will contain the element volumes.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 August 2009
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  timestamp ( )

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TET_MESH_VOLUMES:\n' );
  fprintf ( 1, '  MATLAB version:\n' );
  fprintf ( 1, '  Compute volume of each tetrahedron in a tet mesh.\n' );
%
%  Argument 1 is the common file prefix.
%
  if ( 1 <= nargin )

  else

    fprintf ( 1, '\n' );
    fprintf ( 1, 'TET_MESH_VOLUMES:\n' );
    prefix = input ( '  Please enter the filename prefix:' );

  end
%
%  Create the filenames.
%
  node_filename = strcat ( prefix, '_nodes.txt' );
  element_filename = strcat ( prefix, '_elements.txt' );
  volume_filename = strcat ( prefix, '_volumes.txt' );
%
%  Read the node data.
%
  [ dim_num, node_num ] = r8mat_header_read ( node_filename );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read the header of "%s".\n', node_filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Spatial dimension DIM_NUM = %d\n', dim_num );
  fprintf ( 1, '  Number of points NODE_NUM = %d\n', node_num );

  if ( dim_num ~= 3 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'TET_MESH_VOLUMES - Fatal error!\n' );
    fprintf ( 1, '  Dataset must have spatial dimension 3.\n' );
    error ( 'TET_MESH_VOLUMES - Fatal error!' );
  end

  node_xyz = r8mat_data_read ( node_filename, dim_num, node_num );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read the data in "%s".\n', node_filename );

  r8mat_transpose_print_some ( dim_num, node_num, node_xyz, 1, 1, 5, 5, ...
    '  5 by 5 portion of data read from file:' );
%
%  Read the element data.
%
  [ element_order, element_num ] = i4mat_header_read ( element_filename );

  if ( element_order ~= 4 && element_order ~= 10 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'TET_MESH_VOLUMES - Fatal error!\n' );
    fprintf ( 1, '  Data is not for a 4 or 10 node tet mesh.\n' );
    error ( 'TET_MESH_VOLUMES - Fatal error!' );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read the header of "%s".\n', element_filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Element order = %d\n', element_order );
  fprintf ( 1, '  Number of elements  = %d\n', element_num );

  element_node = i4mat_data_read ( element_filename, element_order, element_num );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read the data in "%s".\n', element_filename );

  i4mat_transpose_print_some ( element_order, element_num, ...
    element_node, 1, 1, element_order, 10, '  Portion of TETRA_NODE:' );
%
%  Detect and correct 0-based indexing.
%
  element_node = mesh_base_one ( node_num, element_order, element_num, ...
    element_node );
%
%  Compute and the volumes.
%
  volume = zeros ( element_num );

  for element = 1 : element_num
    tetra(1:3,1:4) = node_xyz(1:3,element_node(1:4,element));
    volume(element) = tetrahedron_volume ( tetra );
  end

  volume_max = max ( volume(1:element_num) );
  volume_min = min ( volume(1:element_num) );
  volume_ave = sum ( volume(1:element_num) ) / element_num;
  volume_tot = sum ( volume(1:element_num) );
  volume_var = r8vec_variance ( element_num, volume );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Minimum:  %f\n', volume_min );
  fprintf ( 1, '  Average:  %f\n', volume_ave );
  fprintf ( 1, '  Maximum:  %f\n', volume_max );
  fprintf ( 1, '  Total:    %f\n', volume_tot );
  fprintf ( 1, '  Variance: %f\n', volume_var );

  r8mat_write ( volume_filename, 1, element_num, volume );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Full list of volumes written to "%s".\n',...
    volume_filename );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TET_MESH_VOLUMES:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );

  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function column_num = file_column_count ( input_file_name )

%*****************************************************************************80
%
%% FILE_COLUMN_COUNT counts the columns in the first line of a file.
%
%  Discussion:
%
%    The file is assumed to be a simple text file.
%
%    Most lines of the file are presumed to consist of COLUMN_NUM words,
%    separated by spaces.  There may also be some blank lines, and some
%    comment lines, which have a "#" in column 1.
%
%    The routine tries to find the first non-comment non-blank line and
%    counts the number of words in that line.
%
%    If all lines are blanks or comments, it goes back and tries to analyze
%    a comment line.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 February 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the name of the file.
%
%    Output, integer COLUMN_NUM, the number of columns in the file.
%
  FALSE = 0;
  TRUE = 1;
%
%  Open the file.
%
  input_unit = fopen ( input_file_name );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_COLUMN_COUNT - Error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', input_file_name );
    error ( 'FILE_COLUMN_COUNT - Error!' );
  end
%
%  Read one line, but skip blank lines and comment lines.
%  Use FGETL so we drop the newline character!
%
  got_one = FALSE;

  while ( 1 )

    line = fgetl ( input_unit );

    if ( line == -1 )
      break;
    end

    if ( s_len_trim ( line ) == 0 )

    elseif ( line(1) == '#' )

    else
      got_one = TRUE;
      break;
    end

  end

  fclose ( input_unit );

  if ( got_one == FALSE )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_COLUMN_COUNT - Warning!\n' );
    fprintf ( 1, '  The file does not seem to contain any data.\n' );
    column_num = -1;
    return;
  end

  column_num = s_word_count ( line );

  return
end
function row_num = file_row_count ( input_file_name )

%*****************************************************************************80
%
%% FILE_ROW_COUNT counts the number of row records in a file.
%
%  Discussion:
%
%    Each input line is a "RECORD".
%
%    The records are divided into three groups:
%
%    * BLANK LINES (nothing but blanks)
%    * COMMENT LINES (begin with a '#')
%    * DATA RECORDS (anything else)
%
%    The value returned by the function is the number of data records.
%
%    By the way, if the MATLAB routine FGETS is used, instead of
%    FGETL, then the variable LINE will include line termination
%    characters, which means that a blank line would not actually
%    have zero characters.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 December 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the name of the input file.
%
%    Output, integer ROW_NUM, the number of rows found.
%
  input_unit = fopen ( input_file_name );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_ROW_COUNT - Error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', input_file_name );
    error ( 'FILE_ROW_COUNT - Error!' );
  end

  blank_num = 0;
  comment_num = 0;
  row_num = 0;

  record_num = 0;

  while ( 1 )

    line = fgetl ( input_unit );

    if ( line == -1 )
      break;
    end

    record_num = record_num + 1;
    record_length = s_len_trim ( line );

    if ( record_length <= 0 )
      blank_num = blank_num + 1;
    elseif ( line(1) == '#' )
      comment_num = comment_num + 1;
    else
      row_num = row_num + 1;
    end

  end

  fclose ( input_unit );

  return
end
function table = i4mat_data_read ( input_filename, m, n )

%*****************************************************************************80
%
%% I4MAT_DATA_READ reads data from an I4MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 January 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Input, integer M, N, the number of rows and columns in the data.
%
%    Output, integer TABLE(M,N), the point coordinates.
%
  table = zeros ( m, n );
%
%  Build up the format string for reading M real numbers.
%
  string = ' ';

  for i = 0 : m
    string = strcat ( string, ' %d' );
  end

  input_unit = fopen ( input_filename );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_DATA_READ - Error!\n' );
    fprintf ( 1, '  Could not open the input file.\n' );
    error ( 'I4MAT_DATA_READ - Error!' );
  end

  i = 0;

  while ( i < n )

    line = fgets ( input_unit );

    if ( line == -1 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'I4MAT_DATA_READ - Error!\n' );
      fprintf ( 1, '  End of input while reading data.\n' );
      error ( 'I4MAT_DATA_READ - Error!' );
    end

    if ( line(1) == '#' )

    elseif ( s_len_trim ( line ) == 0 )

    else

      [ x, count ] = sscanf ( line, string );

      if ( count == m )
        i = i + 1;
        table(1:m,i) = x(1:m);
      end

    end

  end

  fclose ( input_unit );

  return
end
function [ m, n ] = i4mat_header_read ( input_filename )

%*****************************************************************************80
%
%% I4MAT_HEADER_READ reads the header from an I4MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Output, integer M, the spatial dimension.
%
%    Output, integer N, the number of points.
%
  m = file_column_count ( input_filename );

  if ( m <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data columns in\n' );
    fprintf ( 1, '  the file %s.\n', input_filename );
  end

  n = file_row_count ( input_filename );

  if ( n <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data rows in\n' );
    fprintf ( 1, '  the file %s\n', input_filename );
  end

  return
end
function i4mat_transpose_print_some ( m, n, a, ilo, jlo, ihi, jhi, title )

%*****************************************************************************80
%
%% I4MAT_TRANSPOSE_PRINT_SOME prints some of an I4MAT, transposed.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 June 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns.
%
%    Input, integer A(M,N), an M by N matrix to be printed.
%
%    Input, integer ILO, JLO, the first row and column to print.
%
%    Input, integer IHI, JHI, the last row and column to print.
%
%    Input, string TITLE, an optional title.
%
  incx = 10;

  if ( 0 < s_len_trim ( title ) )
    fprintf ( 1, '\n' );
    fprintf ( 1, '%s\n', title );
  end

  for i2lo = max ( ilo, 1 ) : incx : min ( ihi, m )

    i2hi = i2lo + incx - 1;
    i2hi = min ( i2hi, m );
    i2hi = min ( i2hi, ihi );

    inc = i2hi + 1 - i2lo;

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Row: ' );
    for i = i2lo : i2hi
      fprintf ( 1, '%7d  ', i );
    end
    fprintf ( 1, '\n' );
    fprintf ( 1, '  Col\n' );
    fprintf ( 1, '\n' );

    j2lo = max ( jlo, 1 );
    j2hi = min ( jhi, n );

    for j = j2lo : j2hi

      fprintf ( 1, '%5d  ', j );
      for i2 = 1 : inc
        i = i2lo - 1 + i2;
        fprintf ( 1, '%7d  ', a(i,j) );
      end
      fprintf ( 1, '\n' );

    end

  end

  return
end
function element_node = mesh_base_one ( node_num, element_order, ...
  element_num, element_node )

%*****************************************************************************80
%
%% MESH_BASE_ONE ensures that the element definition is one-based.
%
%  Discussion:
%
%    The ELEMENT_NODE array contains nodes indices that form elements.
%    The convention for node indexing might start at 0 or at 1.
%    Since a MATLAB program will naturally assume a 1-based indexing, it is
%    necessary to check a given element definition and, if it is actually
%    0-based, to convert it.
%
%    This function attempts to detect 0-based node indexing and correct it.
%
%    Thanks to Feifei Xu for pointing out that I was subtracting 1 when I
%    should have been adding 1!  29 November 2012.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 November 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NODE_NUM, the number of nodes.
%
%    Input, integer ELEMENT_ORDER, the order of the elements.
%
%    Input, integer ELEMENT_NUM, the number of elements.
%
%    Input/output, integer ELEMENT_NODE(ELEMENT_ORDE,ELEMENT_NUM), the element
%    definitions.
%
  node_min = min ( min ( element_node(1:element_order,1:element_num) ) );
  node_max = max ( max ( element_node(1:element_order,1:element_num) ) );

  if ( node_min == 0 && node_max == node_num - 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'MESH_BASE_ONE:\n' );
    fprintf ( 1, '  The element indexing appears to be 0-based!\n' );
    fprintf ( 1, '  This will be converted to 1-based.\n' );
    element_node(1:element_order,1:element_num) = ...
      element_node(1:element_order,1:element_num) + 1;
  elseif ( node_min == 1 && node_max == node_num )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'MESH_BASE_ONE:\n' );
    fprintf ( 1, '  The element indexing appears to be 1-based!\n' );
    fprintf ( 1, '  No conversion is necessary.\n' );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'MESH_BASE_ONE - Warning!\n' );
    fprintf ( 1, '  The element indexing is not of a recognized type.\n' );
  end

  return
end
function table = r8mat_data_read ( input_filename, m, n )

%*****************************************************************************80
%
%% R8MAT_DATA_READ reads data from an R8MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 January 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Input, integer M, N, the number of rows and columns of data.
%
%    Output, real TABLE(M,N), the point coordinates.
%
  table = zeros ( m, n );
%
%  Build up the format string for reading M real numbers.
%
  string = ' ';

  for i = 0 : m
    string = strcat ( string, ' %f' );
  end

  input_unit = fopen ( input_filename );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_DATA_READ - Error!\n' );
    fprintf ( 1, '  Could not open the file.\n' );
    error ( 'R8MAT_DATA_READ - Error!' );
  end

  i = 0;

  while ( i < n )

    line = fgets ( input_unit );

    if ( line == -1 )
      break;
    end

    if ( line(1) == '#' )

    elseif ( s_len_trim ( line ) == 0 )

    else

      [ x, count ] = sscanf ( line, string );

      if ( count == m )
        i = i + 1;
        table(1:m,i) = x(1:m);
      end

    end

  end

  fclose ( input_unit );

  return
end
function det = r8mat_det_4d ( a )

%*****************************************************************************80
%
%% R8MAT_DET_4D computes the determinant of a 4 by 4 matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 January 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A(4,4), the matrix whose determinant is desired.
%
%    Output, real DET, the determinant of the matrix.
%
  det = ...
      a(1,1) * ( ...
        a(2,2) * ( a(3,3) * a(4,4) - a(3,4) * a(4,3) ) ...
      - a(2,3) * ( a(3,2) * a(4,4) - a(3,4) * a(4,2) ) ...
      + a(2,4) * ( a(3,2) * a(4,3) - a(3,3) * a(4,2) ) ) ...
    - a(1,2) * ( ...
        a(2,1) * ( a(3,3) * a(4,4) - a(3,4) * a(4,3) ) ...
      - a(2,3) * ( a(3,1) * a(4,4) - a(3,4) * a(4,1) ) ...
      + a(2,4) * ( a(3,1) * a(4,3) - a(3,3) * a(4,1) ) ) ...
    + a(1,3) * ( ...
        a(2,1) * ( a(3,2) * a(4,4) - a(3,4) * a(4,2) ) ...
      - a(2,2) * ( a(3,1) * a(4,4) - a(3,4) * a(4,1) ) ...
      + a(2,4) * ( a(3,1) * a(4,2) - a(3,2) * a(4,1) ) ) ...
    - a(1,4) * ( ...
        a(2,1) * ( a(3,2) * a(4,3) - a(3,3) * a(4,2) ) ...
      - a(2,2) * ( a(3,1) * a(4,3) - a(3,3) * a(4,1) ) ...
      + a(2,3) * ( a(3,1) * a(4,2) - a(3,2) * a(4,1) ) );

  return
end
function [ m, n ] = r8mat_header_read ( input_filename )

%*****************************************************************************80
%
%% R8MAT_HEADER_READ reads the header from an R8MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Output, integer M, the spatial dimension.
%
%    Output, integer N, the number of points.
%
  m = file_column_count ( input_filename );

  if ( m <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data columns in\n' );
    fprintf ( 1, '  the file %s.\n', input_filename );
  end

  n = file_row_count ( input_filename );

  if ( n <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data rows in\n' );
    fprintf ( 1, '  the file %s\n', input_filename );
  end

  return
end
function r8mat_transpose_print_some ( m, n, a, ilo, jlo, ihi, jhi, title )

%*****************************************************************************80
%
%% R8MAT_TRANSPOSE_PRINT_SOME prints some of an R8MAT, transposed.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 May 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns.
%
%    Input, real A(M,N), an M by N matrix to be printed.
%
%    Input, integer ILO, JLO, the first row and column to print.
%
%    Input, integer IHI, JHI, the last row and column to print.
%
%    Input, string TITLE, an optional title.
%
  incx = 5;

  if ( 0 < s_len_trim ( title ) )
    fprintf ( 1, '\n' );
    fprintf ( 1, '%s\n', title );
  end

  for i2lo = max ( ilo, 1 ) : incx : min ( ihi, m )

    i2hi = i2lo + incx - 1;
    i2hi = min ( i2hi, m );
    i2hi = min ( i2hi, ihi );

    inc = i2hi + 1 - i2lo;

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Row: ' );
    for i = i2lo : i2hi
      fprintf ( 1, '%7d       ', i );
    end
    fprintf ( 1, '\n' );
    fprintf ( 1, '  Col\n' );

    j2lo = max ( jlo, 1 );
    j2hi = min ( jhi, n );

    for j = j2lo : j2hi

      fprintf ( 1, '%5d ', j );
      for i2 = 1 : inc
        i = i2lo - 1 + i2;
        fprintf ( 1, '%12f', a(i,j) );
      end
      fprintf ( 1, '\n' );

    end

  end

  return
end
function r8mat_write ( output_filename, m, n, table )

%*****************************************************************************80
%
%% R8MAT_WRITE writes an R8MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 August 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, real TABLE(M,N), the points.
%

%
%  Open the file.
%
  output_unit = fopen ( output_filename, 'wt' );

  if ( output_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_WRITE - Error!\n' );
    fprintf ( 1, '  Could not open the output file.\n' );
    error ( 'R8MAT_WRITE - Error!' );
  end
%
%  Write the data.
%
%  For greater precision, try:
%
%     fprintf ( output_unit, '  %24,16f', table(i,j) );
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %14f', table(i,j) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

  return
end
function mean = r8vec_mean ( n, x )

%*****************************************************************************80
%
%% R8VEC_MEAN returns the mean of an R8VEC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vector.
%
%    Input, real X(N), the vector whose mean is desired.
%
%    Output, real MEAN, the mean, or average,
%    of the vector entries.
%
  mean = sum ( x(1:n) ) / n;

  return
end
function variance = r8vec_variance ( n, x )

%*****************************************************************************80
%
%% R8VEC_VARIANCE returns the variance of an R8VEC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vector.
%
%    Input, real X(N), the vector whose variance is desired.
%
%    Output, real VARIANCE, the variance of the vector entries.
%
  mean = r8vec_mean ( n, x );

  variance = sum ( ( x(1:n) - mean ).^2 );

  if ( 1 < n )
    variance = variance / ( n - 1 );
  else
    variance = 0.0;
  end

  return
end
function len = s_len_trim ( s )

%*****************************************************************************80
%
% S_LEN_TRIM returns the length of a character string to the last nonblank.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 June 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string to be measured.
%
%    Output, integer LENGTH, the length of the string up to the last nonblank.
%
  len = length ( s );

  while ( 0 < len )
    if ( s(len) ~= ' ' )
      return
    end
    len = len - 1;
  end

  return
end
function word_num = s_word_count ( s )

%*****************************************************************************80
%
%% S_WORD_COUNT counts the number of "words" in a string.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 January 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string to be examined.
%
%    Output, integer WORD_NUM, the number of "words" in the string.
%    Words are presumed to be separated by one or more blanks.
%
  FALSE = 0;
  TRUE = 1;

  word_num = 0;
  s_length = length ( s );

  if ( s_length <= 0 )
    return;
  end

  blank = TRUE;

  for i = 1 : s_length

    if ( s(i) == ' ' )
      blank = TRUE;
    elseif ( blank == TRUE )
      word_num = word_num + 1;
      blank = FALSE;
    end

  end

  return
end
function volume = tetrahedron_volume ( tetra )

%*****************************************************************************80
%
%% TETRAHEDRON_VOLUME computes the volume of a tetrahedron.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 May 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real TETRA(3,4), the vertices of the tetrahedron.
%
%    Output, real VOLUME, the volume of the tetrahedron.
%
  dim_num = 3;

  a(1:dim_num,1:4) = tetra(1:dim_num,1:4);
  a(4,1:4) = 1.0;

  volume = abs ( r8mat_det_4d ( a ) ) / 6.0;

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end


function test_bug905

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

load(dccnpath('/home/common/matlab/fieldtrip/data/test/bug905.mat'));

timeunitinsec=10^(-4); % in seconds
fs=1/(4.8*timeunitinsec);
timestep=1/fs;

windowlength=2;
windowlengthinsamples=ceil(windowlength/timestep);
windowlengthinsec=timestep*windowlengthinsamples;

% determine the fourier frequencies
ralfreq=1/windowlengthinsec;
minfreq=ralfreq;
maxfreq=150;
freqs=minfreq:ralfreq:maxfreq;
nfreq=length(freqs);

smoothfraction=0.50;
smoothfreqs=freqs*smoothfraction;
ntaps=floor(smoothfreqs*windowlengthinsec - 1);
% identify the first frequency bin
selvec=(ntaps<=1);
freqsthisbin=freqs(selvec);
freqbins{1}=[freqsthisbin(1),freqsthisbin(end)];
% identify the remaining frequency bins
% we make frequency bins of increasing width
nfreqsinfreqbin=length(freqsthisbin);
lastfreqindxthisbin=nfreqsinfreqbin;
finished=false;
freqbinindx=1;
while ~finished
    freqbinindx=freqbinindx+1;
    nfreqsinfreqbin=nfreqsinfreqbin+2;
    firstfreqindxthisbin=lastfreqindxthisbin+1;
    lastfreqindxthisbin=lastfreqindxthisbin+nfreqsinfreqbin;
    if lastfreqindxthisbin>=nfreq
        lastfreqindxthisbin=nfreq;
        finished=true;
    end
    freqsthisbin=freqs(firstfreqindxthisbin:lastfreqindxthisbin);
    freqbins{freqbinindx}=[freqsthisbin(1),freqsthisbin(end)];
end
nfreqbins=length(freqbins);
tapsmofreqs=zeros(1,nfreqbins);
freqbinindcs=zeros(1,nfreq);
timeresol=1/fs;
mintapsmofreq=1/(windowlengthinsec - timeresol);
for freqbinindx=1:nfreqbins
    tmpval=mean(freqbins{freqbinindx})*smoothfraction/2;
    tapsmofreqs(freqbinindx)=max([tmpval,mintapsmofreq]);
    freqindx1=find(freqs==freqbins{freqbinindx}(1));
    freqindx2=find(freqs==freqbins{freqbinindx}(2));
    freqbinindcs(freqindx1:freqindx2)=freqbinindx;
end

% perform a frequency analysis
allfreqs=[];
freqout_mtmfft=cell(1,nfreqbins);
for freqbinindx=1:nfreqbins
  freqcfg=[];
  freqcfg.method = 'mtmfft';
  freqcfg.output = 'fourier';
  freqcfg.keeptrials = 'yes';
  freqcfg.foilim = freqbins{freqbinindx};
  freqcfg.tapsmofrq = tapsmofreqs(freqbinindx);
  freqcfg.taper = 'dpss';
  freqcfg.pad='maxperlen';
  freqout_mtmfft{freqbinindx}=ft_freqanalysis(freqcfg,datapart);
  allfreqs=[allfreqs,freqout_mtmfft{freqbinindx}.freq];
end

ntrials=length(datapart.trial);
trialindcs=1:ntrials;

freqdescrout_mtmfft=cell(1,nfreqbins);
for freqbinindx=1:nfreqbins
  freqdescrcfg=[];
  freqdescrcfg.trials=trialindcs;
  freqdescrout_mtmfft{freqbinindx}=ft_freqdescriptives(freqdescrcfg,freqout_mtmfft{freqbinindx});
end


function accuracy = rksr_dsk_classifier(TrainSet, TestSet, options)
% Riemannian kernelized sparse representation classification (R-KSRC) with discriminative Stein kernel algorithm
%
% Inputs:
%       TrainSet            train sets of size dxn, where d is dimension and n is number of sets
%       TestSet             test sets of size dxn, where d is dimension and n is number of sets
%       options             options
% Output:
%       accuracy            classification accurary
%
% References:
%       M. Harandi, R. Hartley, B. Lovell and C. Sanderson,
%       "Sparse coding on symmetric positive definite manifolds using bregman divergences,"
%       IEEE Transactions on Neural Networks and Learning Systems, vol.27, no.6, pp.1294-1306, 2016.
%
%       M. Harandi, C. Sanderson, R. Hartley and B. Lovell,
%       "Sparse coding and dictionary learning for symmetric positive definite matrices: a kernel approach,"
%       European Conference on Computer Vision (ECCV), 2012.
%
%       J. Zhang, L. Wang. L. Zhou, and W. Li,
%       "Learning discriminative Stein kernel for SPD matrices and its applications,"
%       IEEE Transactions on Neural Networks and Learning Systems, vol.27, no.5, pp.1020-1033, 2015.
%
% Originally created by Mehrtash Harandi (mehrtash.harandi at gmail dot com).
% Originally created by J. Zhang (jz163@uowmail.edu.au).
% Modified by H. Kasai on July 10, 2017.

    % retrieve dimension of the SPD matrices
    dim = size(TrainSet.X_cov, 1);
    test_num = length(TestSet.y);
    class_num = length(unique(TestSet.y));

    % calculate eigen decomposition
    train_decomp = Decomposite_eig_new(TrainSet);
    test_decomp = Decomposite_eig_new(TestSet);

    % learn alpha of kernel
    if ~options.original_alpha
        initial_alpha = 1*ones(1,dim); % the initial alpha corresponding to the original Stein kernel
        LB = 0.01*initial_alpha;

        fmincon_opt = optimset('Algorithm', 'interior-point'); % run interior-point algorithm

        if options.verbose
            fmincon_opt.Display = 'iter';
        else
            fmincon_opt.Display = 'off';
        end
        fmincon_opt.MaxIter = 100;
        fmincon_opt.TolFun = 1e-5;
        %tic
        optimal_alpha = fmincon(@(alpha) objfun_ff_new(alpha,TrainSet.y,train_decomp, options.lambda,initial_alpha,options.obj_method,options.theta),initial_alpha,[],[],[],[],LB,[],[],fmincon_opt);
        %toc
    else
        optimal_alpha = ones(1,dim);
    end

    % compute the Stein divergence with the obtained adjustment parameter optimal_alpha
    S_test          = EigComp2SD_power_new(train_decomp, test_decomp, optimal_alpha);
    S_train         = EigComp2SD_power_new(train_decomp, train_decomp, optimal_alpha);
    train_kernel    = exp(-1 * options.theta * S_train);
    test_kernel     = exp(-1 * options.theta * S_test);

    % normalize dictionary
    [KD, ~] = data_normalization(train_kernel, [], 'std');
    [KX, ~] = data_normalization(test_kernel, [], 'std');

    [KD_U, KD_D, ~] = svd(KD);
    A = diag(sqrt(diag(KD_D))) * KD_U';
    D_Inv = KD_U * diag(1./sqrt(diag(KD_D)));
    KX = D_Inv' * KX;

    % perform lasso
    param.lambda = options.lambda;
    param.lambda2 =  0;
    param.mode = 2;
    scX = full(mexLasso(KX,A,param));

    % prepare class array
    classes = unique(TrainSet.y);
    % prepare predicted label array
    identity = zeros(1, test_num);

    for i = 1 : test_num
        % prepare residual array
        residuals = zeros(1, class_num);

        % calculate residual for each class
        for j = 1 : class_num
            idx = find(TrainSet.y == classes(j));
            %residuals(j) = norm(KX(:, i) - A(:,idx)*scX(idx, i))/sum(scX(idx, i) .* scX(idx, i));
            residuals(j) = norm(KX(:, i) - A(:,idx)*scX(idx, i));

            if strcmp(options.mode, 'src')
                residuals(j) = norm(KX(:, i) - A(:,idx)*scX(idx, i));
            elseif strcmp(options.mode, 'ip_linear')
                scX_i = scX(idx, i);
                %residuals(j) = sum(abs(scX_i));
                residuals(j) = sum(scX_i);
            elseif strcmp(options.mode, 'ip_max')
                scX_i = scX(idx, i);
                residuals(j) = max(abs(scX_i));
            end
        end

        % calculate the predicted label
        [~, label] = min(residuals);
        if strcmp(options.mode, 'src')
            [~, label] = min(residuals);
        elseif strcmp(options.mode, 'ip_linear') || strcmp(options.mode, 'ip_max')
            [~, label] = max(residuals);
        end
        identity(i) = label;

        if options.verbose
            correct = (label == TestSet.y(1, i));
            fprintf('# RSR-DSK-%s (with %s metric): test:%03d, predict class: %03d --> ground truth :%03d (%d)\n', options.obj_method, options.mode, i, label, TestSet.y(1, i), correct);
        end
    end

    % calculate accuracy
    correct_num = sum(identity == TestSet.y);
    accuracy = correct_num/test_num;
end


function [rpm] = kHz2rpm(kHz)
% Convert frequency from kilohertz to revolutions per minute.
% Chad A. Greene 2012
rpm = kHz*60*1e+3;


function [xx, BestMetric] = SoftVitDec(G, y, ZeroTail);

%
% SoftVitDec			This function performs Viterbi Decoding for Soft Decision Inputs
%
% 						Inputs: G = [g1; g2; ...; gN] - matrix of generation polynomials
%                                    y - encoded sequence
%                                    ZeroTail - 1/0 - defines if contains zero tail
%
% 						Outputs: xx - recovered encoded bits
%                                       BestMetric - final best metric
%
%           Rule =  MAXIMAL METRIC WINS (Likelihood function)
%

L = size(G, 1);     % --- num of output chips
K= size(G, 2);      % --- length of generation polinom
N = 2^(K-1);         % --- number of states
T = length(y)/L;                % --- maximum trellis depth

%------- Output Generation Matrix Definition (contains all possible state transactions)-------------
OutMtrx = zeros(N, 2*L);
for s = 1:N
    in0 = ones(L, 1)*[0, (dec2bin((s-1), (K-1))-'0')];
    in1 = ones(L, 1)*[1, (dec2bin((s-1), (K-1))-'0')];

    out0 = mod(sum((G.*in0)'), 2);
    out1 = mod(sum((G.*in1)'), 2);

    OutMtrx(s, :) = [out0, out1];
end
OutMtrx = sign(OutMtrx-1/2);

%---------------------------------------------------------------------------------------------
%------------------------------------ Trellis SECTION ----------------------------------
%---------------------------------------------------------------------------------------------
%------- Path Mertrix Initialization -------------
PathMet = [100; zeros((N-1), 1)];       % Initial State = 100 (better initial conditions)
PathMetTemp = PathMet(:,1);

Trellis = zeros(N, T);
Trellis(:,1) = [0 : (N-1)]';

%------------------------ MAIN Trellis Calculation Loop ---------------------------
y = reshape(y, L, length(y)/L);
for t = 1:T

    yy = y(:, t);
    for s = 0:N/2-1
        [B0 ind0] = max(  PathMet(1+[2*s, 2*s+1]) + [OutMtrx(1+2*s, 0+[1:L]) * yy; OutMtrx(1+(2*s+1), 0+[1:L])*yy] );
        [B1 ind1] = max(  PathMet(1+[2*s, 2*s+1]) + [OutMtrx(1+2*s, L+[1:L]) * yy; OutMtrx(1+(2*s+1), L+[1:L]) * yy] );

        PathMetTemp(1+[s, s+N/2]) =  [B0; B1];
        Trellis(1+[s, s+N/2], t+1) = [2*s+(ind0-1); 2*s + (ind1-1)];
    end
   PathMet = PathMetTemp;

end

%---------------------------------------------------------------------------------------------
%---------------------------------- Trace Back Section -----------------------------
%---------------------------------------------------------------------------------------------
%------- Find Best Path Mertric -------------
xx = zeros(T, 1);
if (ZeroTail)
    BestInd = 1;
else
    [Mycop, BestInd]  = max(PathMet);
end

BestMetric = PathMet(BestInd);
xx(T) = floor((BestInd-1)/(N/2));

%------------------------ MAIN Trace Back Loop ---------------------------
NextState = Trellis(BestInd, (T+1));
for t=T:-1:2
    xx(t-1) = floor(NextState/(N/2));
    NextState = Trellis( (NextState+1), t);
end

if (ZeroTail)
    xx = xx(1:end-K+1);
end


function nodevol=nodevolume(node,elem, evol)
%
% nodevol=nodevolume(node,elem)
%
% calculate the volumes of the cells in the barycentric dual-mesh
% (this is different from the Voronoi cells, which blong to the
% circumcentric dual mesh)
%
% author: Qianqian Fang, <q.fang at neu.edu>
% date: 2009/12/31
%
% input:
%    node:  node coordinates
%    elem:  element table of a mesh
%
% output:
%    nodevol:   volume values for all nodes
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

dim=4;
if(size(elem,2)==3) dim=3; end

if(nargin<3)
    evol=elemvolume(node,elem(:,1:dim));
end

elemnum=size(elem,1);
nodenum=size(node,1);
nodevol=zeros(nodenum,1);
for i=1:elemnum
      nodevol(elem(i,1:dim))=nodevol(elem(i,1:dim))+evol(i);
end
nodevol=nodevol/dim;


function [out] = score_KS(mdv, hilo, lambda)
% Calculates KS score
%
% USAGE:
%
%    [out] = score_ridge(mdv, hilo, lambda, crossval)
%
% INPUTS:
%    mdv:         structure
%    hilo:        (0's and 1's), ideally there will be a similar # of each.
%
% OPTIONAL INPUTS:
%    lambda:      weighting, if the mean is less than lambda, the scores get weighted less, default = .02
%
% OUTPUT:
%    out:         score

if nargin < 3
    lambda = .02;
end

[nvars, npoints] = size(mdv);
loset = mdv(:,hilo==0);
hiset = mdv(:,hilo==1);

weights = std(mdv,0,2);

scores = zeros(nvars, 1);
parfor i = 1:nvars

    [h, p] = kstest2(loset(i,:), hiset(i,:));
    scores(i) = max(log(p), -708); % log(realmin) to avoid scores of inf.

end

scores2 = scores .*(1-exp(-weights/lambda));
out = -sum(scores2);


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
%
% Tutorial for FAIR: midpoint quadrature rule for 1D spline
%
%==============================================================================

clear, close all, help(mfilename)

omega = [0,6];   I = 1;  psi = @(x) spline1D(3,x); h = []; Q = [];
for j=1:10,
  m    = 2^j;
  h(j) = diff(omega)/m;
  xc   = getCellCenteredGrid(omega,m);
  Q(j) = h(j)*sum(psi(xc));
end;
figure(1); clf; p1=semilogx(h/h(1),Q+eps,'kx',h/h(1),Q,'k-');
figure(2); clf; p2=loglog(h/h(1),abs(I-Q)+eps,'kx',h/h(1),abs(I-Q),'k-');
%==============================================================================


function D = compute_histogram_distance(H, options)

% compute_histogram_distance - compute distance between histograms
%
%   D = compute_histogram_distance(H, options);
%
%   H(:,i) is the ith histogram.
%	D(i,g) is the distance between histogram i and j.
%
%	options.histmetric is the metric used to compute the distance d(g,h) between two histograms.
%	We denote by G and H the cumulative distribution, i.e. G=cumsum(g)
%		'l2'  -> d(g,h)^2 = sum_i (g(i)-h(i))^2
%		'l1'  -> d(g,h)   = sum_i abs(g(i)-h(i))
%		'cl2' -> d(g,h)^2 = sum_i (G(i)-H(i))^2
%		'cl1' -> d(g,h)   = sum_i abs(G(i)-H(i))
%		'chi2' -> d(g,h) = sum_i (G(i)-H(i))^2 / (G(i)+H(i))
%		'bhatta' -> d(g,h) = 1 - sum_i sqrt(G(i)*H(i))
%   options.sigma is a pre-smoothing factor, counted in pixels.
%
%   Copyright (c) 2007 Gabriel Peyre

if isfield(options, 'sigma')
	sigma = options.sigma;
else
	sigma = 1.2;
end
if isfield(options, 'histmetric')
	histmetric = options.histmetric;
else
	histmetric = 'histmetric';
end

%% smooth the histograms
n = size(H,1);
m = size(H,2);
h = compute_gaussian_filter( 21,sigma/(2*n),n);
for i=1:m
    H(:,i) = perform_convolution(H(:,i),h);
end

% make them sum to 1
H = max(H,0);
H = H ./ repmat( sum(H,1), [n 1] );

%% compute distance
switch lower(histmetric)
    case {'cl2' 'cl1'}
        D = distance_matrix(cumsum(H), histmetric(2:end) );
    otherwise
        D = distance_matrix(H, histmetric );
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function D = distance_matrix(X,metric)

n = size(X,1); % dimension
p = size(X,2);

A = repmat( reshape(X', [p 1 n] ), [1 p]);
B = permute(A, [2 1 3]);

switch metric
    case 'l1'
        D = sum( abs(A-B), 3 );
    case 'l2'
        D = sqrt( sum( (A-B).^2, 3 ) );
    case 'chi2'
        a = A+B; a(a<eps) = 1;
        D = sum( ((A-B).^2) ./ a, 3 );
    case 'bhatta'
        D = 1 - sum( sqrt(A.*B), 3 );
    otherwise
        error('Unknown method');
end


B.e0  = 12.69; % [V]
B.e1  = -3.14; % [V]
B.e2  = 1.58;  % [V]
B.A   = 1.53;  % [V]
B.B   = 29.89; % [Ah^(-1)]
B.V0  = 12.59; % [V]
B.Q0  = 0.034; % [Ah]
B.Qf  = 1.20;  % [Ah]
B.R   = 0.061; % [Ohm]
B.tau = 1.95;  % [s]

B.p1  = 1.31e-7;
B.p2  = 4.03e-15;
B.p3  = -1.22e-23;
B.p4  = 1.65e-31;

Pboard = 0;

% Pboard = ;

nominal_V = @(Q)   B.e0 + B.e1*(Q/B.Qf) + B.e2*(Q/B.Qf)^2; %[V]
power   = @(rpm)   0.73*(B.p1*rpm^2 + B.p2*rpm^4 + B.p3*rpm^6 + B.p4*rpm^8); %[W]

Q       = B.Q0;
V       = B.V0;
i       = zeros(5,1);

w1 = 800*30/pi;  %rad/s to rpm
w2 = 800*30/pi;
w3 = 800*30/pi;
w4 = 800*30/pi;

window_size = 5;
b = (1/window_size)*ones(1,window_size);
a = 1;

dt = 0.1;
t = 0;
figure;

while Q < B.Qf
    % Sum board and motors power
    t           = t + dt;
    Pow         = Pboard + power(w1) + power(w2) + power(w3) + power(w4);
    i           = circshift(i, -1);
    i(end)      = Pow/V;
    signal_filt = filter(b,a,i);
    i_filt      = signal_filt(end);

    Q       = Q + i_filt*dt/3600; %[Ah]
    Vf      = B.A*exp(-B.B*(B.Qf-B.Q0-Q));
    V_nom   = nominal_V(Q);
    V       = V_nom - B.R*i_filt - Vf;

    plot(t,V,'bo', t,Q,'ro');
    hold on;

end


function g = newDomain(g, newDom)
%NEWDOMAIN   Change of domain of a CHEBFUN.
%  NEWDOMAIN(G, DOM) returns the CHEBFUN G but moved to the domain DOM. This is
%  done with a linear map. DOM may be a vector of length G.ends, or a two-vector
%  (in which case all breakpoints are scaled by the same amount).

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

% [TODO]: Unbounded domains.

% Current breakpoints:
oldDom = g.domain;

if ( numel(newDom) == numel(oldDom) )
    % All new breakpoints are given!
elseif ( numel(newDom) == 2 )
    % Scale breakpoints:
    c = oldDom(1);
    d = oldDom(end);
    a = newDom(1);
    b = newDom(2);
    newDom = (b - a)*(oldDom - c)/(d - c) + a;
else
    error('CHEBFUN:CHEBFUN:newDomain:numints', 'Inconsistent domains.');
end

for k = 1:numel(g.funs)
    % Update the domains of each of the funs:
    g.funs{k} = changeMap(g.funs{k}, newDom(k:k+1));
end

% Update the CHEBFUN:
g.domain = newDom;

end


function poly = edgeToPolyline(edge, N)
%EDGETOPOLYLINE Convert an edge to a polyline with a given number of segments
%
%   POLY = edgeToPolyline(EDGE, N)
%
%   Example
%     edge = [10 20 60 40];
%     poly = edgeToPolyline(edge, 10);
%     drawEdge(edge, 'lineWidth', 2);
%     hold on
%     drawPoint(poly);
%     axis equal;
%
%   See also
%     edges2d, drawEdge, drawPolyline
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-11-25,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

if N < 1
    error('number of segments must be greater than 1');
end

if length(edge) == 4
    % case of planar edges
    p1 = edge(1:2);
    p2 = edge(3:4);
    poly = [linspace(p1(1), p2(1), N+1)' linspace(p1(2), p2(2), N+1)'];

else
    % case of 3D edges
    p1 = edge(1:3);
    p2 = edge(4:6);
    poly = [...
        linspace(p1(1), p2(1), N+1)' ...
        linspace(p1(2), p2(2), N+1)' ...
        linspace(p1(3), p2(3), N+1)'];
end


function r = hessianinit(v)
%HESSIANINIT  Initialization of hessian variable
%
%  x = hessianinit(v)
%
%The independent variable(s) x are identified and initialized with value(s) v.
%  v may be scalar for one independent variable, or vector (or matrix)
%  for several independent variables.
%
%The call
%
%  hessianinit
%
%without input parameters sets the number of independent variables to zero.
%
%Hessians are frequently sparsely populated. Therefore, one can choose to store
%first and second derivative dense or sparse, see "help sparsehessian".

%The hessian of arrays is stored in the 'next dimension'. So y.hx is
%  3-dimensional for a column vector y, and y.dx is 3-dimensional for
%  a gradient row vector y.
%Since Matlab does not support multi-dimensional sparse arrays, y.dx
%  and y.hx is not accessible in those cases for sparse y.
%
%As a simple example of hessians
%
%  u = hessianinit([ -3 ; 3+4i ])
%
%initializes the hessian package to have two independent variables. The
%variable u, a column vector, with values u.x(1) = -3 and u.x(2) = 3+4i
%has first derivatives u(1).dx = [1 0] and u(2).dx = [0 1] and second
%derivatives u(1).hx = u(2).hx = zeros(2).
%If after that the statement
%
%  v = hessian( intval('3.14159_') )
%
%is executed, the value v.x is the interval with left bound 3.14158 and
%right bound 3.14160 (correctly rounded), the first derivative v.dx = [0 0]
%and second derivative v.hx = zeros(2) (v is treated like a constant). Similarly,
%
%  u(2) = -4711
%
%produces u.x = [ -3 ; -4711 ], u.dx = [ 1 0 ; 0 0 ] and does not change u.hx.
%
%Hessians frequently depend only on few variables. Therefore, if not specified
%  otherwise, the first and second derivative are stored sparse for eight and
%  more unknowns (see above).
%To change only the display you may use "full(u)" or "sparse(u)".
%
%For some examples, see demohessian.
%

% written  04/04/04     S.M. Rump
% modified 04/06/05     S.M. Rump  rounding unchanged
% modified 08/26/12     S.M. Rump  global variables removed
% modified 10/03/12     S.M. Rump  SlopeSparseArrayDeriv and see removed
%

  if nargin==0
    setappdata(0,'INTLAB_HESSIAN_NUMVAR',0);
    return
  end

  if ~( isa(v,'double') | isa(v,'intval') )
    error('invalid initialization of hessian')
  end
  setappdata(0,'INTLAB_HESSIAN_NUMVAR',prod(size(v)));

  dummy.init = v;
  r = hessian( dummy , 'hessianinit' );


function [q,r] = deconv(p1,p2)
%DECONV       Implements  p1 / p2  for univariate polynomials with remainder term
%
%   [q,r] = deconv(p1,p2)
%

% written  07/24/02     S.M. Rump
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
% modified 09/28/08     S.M. Rump  check for rounding to nearest improved
%

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

  if ~isa(p1,'polynom')
    p1 = polynom(p1,'');
  end

  if ~isa(p2,'polynom')
    p2 = polynom(p2,'');
  end

  if ( size(p1.e,2)>1 ) | ( size(p2.e,2)>1 )
    error('divison only for univariate polynomials')
  end

  % both p1 and p2 univariate polynomials
  if ~isequal(p1.v,p2.v) & ~isempty(p1.v) & ~isempty(p2.v)
    error('division only for univariate polynomials depending on the same variable')
  end

  isint = isa(p1.c,'intval') | isa(p2.c,'intval');

  if p2.e==0                           % p2 is constant
    q = p1;
    q.c = p1.c/p2.c;
    if nargout==2
      if isint
        r = polynom(intval(0),p1.v);
      else
        r = polynom(0,p1.v);
      end
    end
    if rndold
      setround(rndold)
    end
    return
  end

  if p1.e<p2.e                          % deg(p1) < deg(p2)
    q.e = 0;
    if isint
      q.c = intval(0);
    else
      q.c = 0;
    end
    q.v = p1.v;
    q = class(q,'polynom');
    if nargout==2
      r = p1;
    end
    if rndold
      setround(rndold)
    end
    return
  end

  q.e = max(p1.e-p2.e,0);
  if isint
    q.c = intval(zeros(1,q.e+1));
    p1.c = intval(p1.c);
    for i=1:(q.e+1)
      q.c(i) = p1.c(i)/p2.c(1);
      p1.c(i:(i+p2.e)) = p1.c(i:(i+p2.e)) - q.c(i)*p2.c;
    end
    if nargout==2
      np1 = length(p1.c);
      r.e = p2.e-1;
      r.c = p1.c((np1-p2.e+1):np1);
      r.v = p1.v;
      r = class(r,'polynom');
    end
  else
    if nargout==2
      [q.c,rc] = deconv(p1.c,p2.c);
      r.e = min(p2.e-1,length(rc)-1);
      r.c = rc(end-r.e:end);
      r.v = p1.v;
      r = class(r,'polynom');
    else
      q.c = deconv(p1.c,p2.c);
    end
  end
  q.v = p1.v;

  q = class(q,'polynom');

  if rndold
    setround(rndold)
  end


function uniform_run ( )

%*****************************************************************************80
%
%% UNIFORM_RUN varies the parameter DELTA in a log uniform way.
%
%  Discussion:
%
%    Our base value for DELTA_BASE is 0.01.
%
%    Our quantity of interest Q is the time at which the solution achieves
%    the value 0.99.
%
%    Our parameter U is uniformly distributed in [-1,+1], and determines
%    our actual value of DELTA by
%
%      DELTA = 2^U * DELTA_BASE.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 February 2013
%
%  Author:
%
%    John Burkardt
%
  delta_base = 0.01;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'UNIFORM_RUN\n' );
  fprintf ( 1, '  Vary the value of delta using a log-uniformly\n' );
  fprintf ( 1, '  distributed factor between 1/2 and 2.\n' );
  fprintf ( 1, '  Our quantity of interest Q is the time at which the\n' );
  fprintf ( 1, '  solution reaches 0.99.\n' );
  fprintf ( 1, '  Plot the solution curves, and plot Delta versus Q\n' );
  fprintf ( 1, '\n' );
%
%  Set up an option to have ODE45 return when the solution reached 0.99.
%
  options = odeset ( 'EVENTS', @event_function );

  figure ( 1 )
  clf
  hold on

  for trial = 1 : 10
%
%  Uniformly select
%    U, the logarithm base 2, between -1 and +1, of
%    F, a factor between 1/2 and 2, which multiplies
%    DELTA_BASE, the base value, which gives us
%    DELTA, the initial size of the flame.
%
    u = 2 * rand ( 1, 1 ) - 1.0;
    f = 2^u;
    delta = f * delta_base;
    d_plot(trial) = delta;
    fprintf ( 1, '  U = %g, factor = %g, DELTA = %g\n', u, f, delta );
%
%  Set the starting point.
%
    t_start = 0.0;
    y_start(1,1) = delta;
%
%  Get the stopping point.
%
    t_stop = 250.0;
%
%  Call ODE45 to solve the problem, stopping immediately if the event
%  (y=0.99) is observed.
%
    t_span = [ t_start, t_stop ];

    [ t, y ] = ode45 ( @flame_fun, t_span, y_start, options );
    fprintf ( '  Y(T) = 0.99 at T = %g\n', t(end) );
    q_plot(trial) = t(end);

    c = [ trial, 0, 11 - trial ] / 10;

    plot ( t, y(:,1), 'b-', 'Linewidth', 3, 'Color', c );

  end

  title ( 'Shampine Flame, Multiple values of DELTA', 'Fontsize', 24 );
  grid on
  xlabel ( '<--- T --->', 'Fontsize', 24 );
  ylabel ( '<--- X(T) --->', 'Fontsize', 24 );

  hold off

  filename = 'uniform_run.png';
  print ( '-dpng', filename );
  fprintf ( 1, '  Multiple solutions plotted in file "%s".\n', filename );
%
%  Since our deltas were computed randomly, they aren't in order.
%  We need to sort them, and their corresponding function values,
%  before plotting.
%
  [ d_plot, i ] = sort ( d_plot );
  q_plot = q_plot(i);
%
%  Plot the observed values of delta versus F, the time at
%  which the solution reached 0.99.
%
  figure ( 2 )
  plot ( d_plot, q_plot, 'r.-', 'Linewidth', 3, 'Markersize', 25 );
  grid on
  xlabel ( '<-- Parameter Delta -->', 'Fontsize', 24 )
  ylabel ( '<-- Ignition time Q(Delta) -->', 'Fontsize', 24 )
  title ( 'Ignition time as a function of parameter Delta', 'Fontsize', 24 )

  filename = 'uniform_qoi.png';
  print ( '-dpng', filename );
  fprintf ( 1, '  Quantity of Interest plotted in file "%s".\n', filename );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'UNIFORM_RUN\n' );
  fprintf ( 1, '  Normal end of execution\n' );

  return
end