function plotSigmoidalResponse_LGG(resp,Y,modelCI,nameOutcome,pathFig)
% -------------------------------------------------------------------------
% function plotSigmoidalResponse_LGG(resp,Y,modelCI,nameOutcome,pathFig)
% -------------------------------------------------------------------------
% DESCRIPTION:
% This function plots the sigmoidal response (P(y=1|x)) of a linear
% multivariable model response. See ref. [1] for more details.
% -------------------------------------------------------------------------
% REFERENCE:
% [1] Vallieres, M. et al. (2015). A radiomics model from joint FDG-PET and
%     MRI texture features for the prediction of lung metastases in soft-tissue
%     sarcomas of the extremities. Physics in Medicine and Biology, 60(14),
%     5471-5496. doi:10.1088/0031-9155/60/14/5471
% -------------------------------------------------------------------------
% INPUTS:
% 1. resp: Column vector of size [nInst X 1] specifying the linear
%          multivariable model response, where 'nInst' refers to the number
%          of instances.
% 2. Y: Column vector of size [nInst X 1] specifying the outcome status
%       (1 or 0) for all instances.
% 3. modelCI: Column vector of size [nInst X 2] specifying the 95%
%             confidence interval on the multivariable model response as
%             defined by the 2.5 (modelCI(i,1)) and the 97.5 (modelCI(i,2))
%             percentiles, for the ith instance. To plot without CIs, use []
%             for the 3rd argument.See ref. [1] for more
%             details.
% 4. nameOutcome: String specifying the name of the
%                 modeled outcome.
%                 --> Ex: 'progression'
% 5. pathFig: (optional).  Full path to where figure is saved without
%             displaying it. Put '' for displaying the figure and not
%             saving it to 'pathFig' (default).
%             --> Ex: ''
% -------------------------------------------------------------------------
% AUTHOR(S): Martin Vallieres <mart.vallieres@gmail.com>
% -------------------------------------------------------------------------
% HISTORY:
% - Creation: January 2017
%--------------------------------------------------------------------------
% STATEMENT:
% This file is part of <https://github.com/mvallieres/radiomics/>,
% a package providing MATLAB programming tools for radiomics analysis.
% --> Copyright (C) 2015-2017  Martin Vallieres
%
%    This package is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    This package is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with this package.  If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------

startpath = pwd;

if nargin < 5
    pathFig = '';
end

prob = 1./(1 + exp(-resp)); % Sigmoidal response, or P(y=1|x)
respPos = resp(Y==1);
respNeg = resp(Y==0);
probPos = prob(Y==1);
probNeg = prob(Y==0);
name = nameOutcome;
symbols = {'ob','xr'}; % First entry for positive instances, second entry for negative instances

if isempty(pathFig)
    figure
else
    h = figure('visible','off');
end
[sortResp,~] = sort(resp);
sigX = (sortResp(1)-5):0.1:sortResp(end)+5;
sigY = 1./(1 + exp(-sigX));
plot(sigX,sigY,'-k','LineWidth',3);
hold on
if ~isempty(modelCI)
    lowXpos = modelCI(Y==1,1); highXpos = modelCI(Y==1,2);
    lowXneg = modelCI(Y==0,1); highXneg = modelCI(Y==0,2);
    [~] = herrorbar(respPos,probPos,respPos-lowXpos,highXpos-respPos,'ob');
    hold on
    [~] = herrorbar(respNeg,probNeg,respNeg-lowXneg,highXneg-respNeg,'xr');
    legend('Sigmoidal response',['95% CI: ',name,' = 1'],['Status: ',name,' = 1'],['95% CI: ',name,' = 0'],['Status: ',name,' = 0'],'Location','NorthWest')
else
    plot(respPos,probPos,symbols{1},'LineWidth',6,'MarkerSize',18,'MarkerFaceColor',symbols{1}(end),'MarkerEdgeColor',symbols{1}(end));
    hold on
    plot(respNeg,probNeg,symbols{2},'LineWidth',6,'MarkerSize',20,'MarkerFaceColor',symbols{2}(end),'MarkerEdgeColor',symbols{2}(end));
    legend('Sigmoidal response',['Status: ',name,' = 1'],['Status: ',name,' = 0'],'Location','NorthWest')
end
xlabel('Multivariable model response','FontSize',30)
ylabel(['Probability that ',name,' = 1'],'FontSize',30)
axis([sortResp(1)-0.33*abs(sortResp(1)),sortResp(end)+0.33*abs(sortResp(end)),-0.05,1.05])
set(gca,'FontSize',24)

if ~isempty(pathFig)
    cd(pathFig)
    saveas(h,['sigPlotResponse_',name],'fig')
end

cd(startpath)
end


function [y] = spm_int_D(P,M,U)
% integrates a MIMO bilinear system dx/dt = f(x,u) = A*x + B*x*u + Cu + D;
% FORMAT [y] = spm_int_D(P,M,U)
% P   - model parameters
% M   - model structure
%   M.delays - sampling delays (s); a vector with a delay for each output
%   M.states - a vector of indices if M.x(:) to be used in updating df/dx
%   M.nsteps - increase number of time steps by this number (default = 1)
%
% U   - input structure or matrix
%
% y   - response y = g(x,u,P)
%__________________________________________________________________________
% Integrates the bilinear approximation to the MIMO system described by
%
%    dx/dt = f(x,u,P) = A*x + u*B*x + C*u + D
%    y     = g(x,u,P) = L*x;
%
% at v = M.ns is the number of samples [default v = size(U.u,1)]
%
% spm_int_D will also handle static observation models by evaluating
% g(x,u,P).  It will also handle timing delays if specified in M.delays
%
%--------------------------------------------------------------------------
%
% SPM solvers or integrators
%
% spm_int_ode:  uses ode45 (or ode113) which are one and multi-step solvers
% respectively.  They can be used for any ODEs, where the Jacobian is
% unknown or difficult to compute; however, they may be slow.
%
% spm_int_J: uses an explicit Jacobian-based update scheme that preserves
% nonlinearities in the ODE: dx = (expm(dt*J) - I)*inv(J)*f.  If the
% equations of motion return J = df/dx, it will be used; otherwise it is
% evaluated numerically, using spm_diff at each time point.  This scheme is
% infallible but potentially slow, if the Jacobian is not available (calls
% spm_dx).
%
% spm_int_E: As for spm_int_J but uses the eigensystem of J(x(0)) to eschew
% matrix exponentials and inversion during the integration. It is probably
% the best compromise, if the Jacobian is not available explicitly.
%
% spm_int_B: As for spm_int_J but uses a first-order approximation to J
% based on J(x(t)) = J(x(0)) + dJdx*x(t).
%
% spm_int_L: As for spm_int_B but uses J(x(0)).
%
% spm_int_U: like spm_int_J but only evaluates J when the input changes.
% This can be useful if input changes are sparse (e.g., boxcar functions).
% It is used primarily for integrating EEG models
%
% spm_int_D: Fast integrator that uses a bilinear approximation to the
% Jacobian evaluated using spm_soreduce. This routine will also allow for
% sparse sampling of the solution and delays in observing outputs. It is
% used primarily for integrating fMRI models
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_int_D.m 5667 2013-10-02 18:26:06Z karl $

% convert U to U.u if necessary
%--------------------------------------------------------------------------
if ~isstruct(U), u.u = U; U = u; end
try, dt = U.dt; catch, U.dt = 1; end

 % number of times to sample (v) and number of microtime bins (u)
%--------------------------------------------------------------------------
u      = size(U.u,1);
try, v = M.ns;  catch, v = u;    end

% get expansion point
%--------------------------------------------------------------------------
x = [1; spm_vec(M.x)];

% add [0] states if not specified
%--------------------------------------------------------------------------
if ~isfield(M,'f')
    M.f = inline('sparse(0,1)','x','u','P','M');
    M.n = 0;
    M.x = sparse(0,0);
end

% output nonlinearity, if specified
%--------------------------------------------------------------------------
try
    g   = fcnchk(M.g,'x','u','P','M');
catch
    g   = inline('x','x','u','P','M');
    M.g = g;
end

% Bilinear approximation (1st order)
%--------------------------------------------------------------------------
[M0,M1,M2] = spm_soreduce(M,P);
n          = length(M2);                     % n states
m          = length(M1);                     % m inputs

% delays
%--------------------------------------------------------------------------
try
    D  = max(round(M.delays/U.dt),1);
catch
    D  = ones(M.l,1)*round(u/v);
end

% state-dependent effects to include during integration
%--------------------------------------------------------------------------
try
    M2 = M2(M.states);
    n  = length(M2);
end

% decrease integration time steps
%--------------------------------------------------------------------------
try
    N  = max(M.nsteps,1);
catch
    N  = 1;
end

% Evaluation times (t) and indicator array for inputs (su) and output (sy)
%==========================================================================

% get times that the input changes
%--------------------------------------------------------------------------
i     = [1 (1 + find(any(diff(U.u),2))')];
su    = sparse(1,i,1,1,u);

% get times that the response is sampled
%--------------------------------------------------------------------------
s     = ceil([0:v - 1]*u/v);
for j = 1:M.l
    i       = s + D(j);
    sy(j,:) = sparse(1,i,1:v,1,u);
end

% get (N) intervening times to evaluate
%--------------------------------------------------------------------------
i     = ceil((0:(v - 1)*N)*u/v/N) + D(1);
sx    = sparse(1,i,1,1,u);

% time in seconds
%--------------------------------------------------------------------------
t     = find(su | any(sy,1) | sx);
sy    = full(sy(:,t));
dt    = [diff(t) 0]*U.dt;

% Integrate
%--------------------------------------------------------------------------
y     = zeros(M.l,v);
J     = M0;
U.u   = full(U.u);
for i = 1:length(t)

    % input dependent changes in Jacobian
    %----------------------------------------------------------------------
    u     = U.u(t(i),:);
    J     = M0;
    for j = 1:m
        J = J + u(j)*M1{j};
    end

    % state dependent changes in Jacobian
    %----------------------------------------------------------------------
    for j = 1:n
        J = J + (x(j + 1) - M.x(j))*M2{j};
    end

    % output sampled
    %----------------------------------------------------------------------
    if any(sy(:,i))
        q      = spm_unvec(x(2:end),M.x);
        q      = spm_vec(feval(g,q,u,P,M));
        j      = find(sy(:,i));
        s      = sy(j(1),i);
        y(j,s) = q(j);
    end

    % compute updated states x = expm(J*dt)*x;
    %----------------------------------------------------------------------
    x  = spm_expm(J*dt(i),x);

    % check for convergence
    %----------------------------------------------------------------------
    if norm(x,1) > 1e6, break, end

end
y      = real(y');


function f_x = ParFor3(in1)
%PARFOR3
%    F_X = PARFOR3(IN1)

%    This function was generated by the Symbolic Math Toolbox version 8.2.
%    20-Sep-2019 09:35:35

u = in1(:,1);
ux = in1(:,4);
uxx = in1(:,5);
uxxx = in1(:,6);
f_x = (u.*1.034220113405542e16+ux.*6.575036155887616e15+uxx.*1.215253266628608e17-uxxx.*4.601209472843776e15-u.*ux.*5.099459193028608e15+u.*uxx.*5.032641492680704e16+u.*uxxx.*4.967741975658496e15-2.603211137867776e15)./(u.*3.126267420934144e16+4.755897990407782e16);


%returns the first component of the frequency representation of the signal
classdef SpectralSpread < Algorithm

    methods (Access = public)

        function obj = SpectralSpread()
            obj.name = 'SpectralSpread';
            obj.inputPort = DataType.kSignal;
            obj.outputPort = DataType.kFeature;
        end

        %receives a fourier transform
        function result = compute(~,Y)
            N = length(Y);
            Y = abs(Y) / N;
            Y = Y / max(Y);

            m = ((1/(2*N))*(1:N))';

            % compute the spectral spread
            C = sum(m .* Y) / (sum(Y)+eps);
            result = sqrt(sum(((m-C).^2) .* Y)/ (sum(Y)+eps));
        end

        function metrics = computeMetrics(~,input)
            n = size(input,1);
            flops = 11 * n;
            memory = n;
            outputSize = Constants.kFeatureBytes;
            metrics = Metric(flops,memory,outputSize);
        end
    end
end


% OP_V_GRADP: assemble the matrix B = [b(i,j)], b(i,j) = (epsilon grad p_i, v_j).
%
%   mat = op_v_gradp (spv, spp, msh, epsilon);
%   [rows, cols, values] = op_v_gradp (spv, spp, msh, epsilon);
%
% INPUT:
%
%   spv:     structure representing the space of vectorial trial functions  (see sp_vector/sp_evaluate_col)
%   spp:     structure representing the space of scalar test functions (see sp_scalar/sp_evaluate_col)
%   msh:     structure containing the domain partition and the quadrature rule (see msh_cartesian/msh_evaluate_col)
%   epsilon: physical parameter
%
% OUTPUT:
%
%   mat:    assembled matrix
%   rows:   row indices of the nonzero entries
%   cols:   column indices of the nonzero entries
%   values: values of the nonzero entries
%
% Copyright (C) 2009, 2010 Carlo de Falco
% Copyright (C) 2011, 2017 Rafael Vazquez
%
%    This program is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.

%    This program is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with this program.  If not, see <http://www.gnu.org/licenses/>.

function varargout = op_v_gradp (spv, spp, msh, coeff)

  ndir = size (spp.shape_function_gradients, 1);

  if (ndir ~= spv.ncomp)
    error ('Inconsistent dimensions between the number of components of v and the gradient of p')
  end

  rows = zeros (msh.nel * spp.nsh_max * spv.nsh_max, 1);
  cols = zeros (msh.nel * spp.nsh_max * spv.nsh_max, 1);
  values = zeros (msh.nel * spp.nsh_max * spv.nsh_max, 1);

  jacdet_weights = msh.jacdet .* msh.quad_weights .* coeff;

  ncounter = 0;
  for iel = 1:msh.nel
    if (all (msh.jacdet(:, iel)))
      shpv_iel = reshape (spv.shape_functions(:, :, :, iel), spv.ncomp, msh.nqn, 1, spv.nsh_max);
      gradp_iel = reshape (spp.shape_function_gradients(:, :, :, iel), ndir, msh.nqn, spp.nsh_max, 1);

      jacdet_iel = reshape (jacdet_weights(:,iel), [1,msh.nqn,1,1]);

      jacdet_shpv = bsxfun (@times, jacdet_iel, shpv_iel);
      tmp1 = sum (bsxfun (@times, jacdet_shpv, gradp_iel), 1);
      elementary_values = reshape (sum (tmp1, 2), spp.nsh_max, spv.nsh_max);

      [rows_loc, cols_loc] = ndgrid (spp.connectivity(:,iel), spv.connectivity(:,iel));
      indices = rows_loc & cols_loc;
      rows(ncounter+(1:spv.nsh(iel)*spp.nsh(iel))) = rows_loc(indices);
      cols(ncounter+(1:spv.nsh(iel)*spp.nsh(iel))) = cols_loc(indices);
      values(ncounter+(1:spv.nsh(iel)*spp.nsh(iel))) = elementary_values(indices);
      ncounter = ncounter + spv.nsh(iel)*spp.nsh(iel);
    else
      warning ('geopdes:jacdet_zero_at_quad_node', 'op_v_gradp: singular map in element number %d', iel)
    end
  end

  if (nargout == 1 || nargout == 0)
    varargout{1} = sparse (rows(1:ncounter), cols(1:ncounter), ...
                           values(1:ncounter), spp.ndof, spv.ndof);
  elseif (nargout == 3)
    varargout{1} = rows(1:ncounter);
    varargout{2} = cols(1:ncounter);
    varargout{3} = values(1:ncounter);
  else
    error ('op_v_gradp: wrong number of output arguments')
  end

end

%% COPY OF THE FIRST VERSION OF THE FUNCTION (MORE UNDERSTANDABLE)
% function mat = op_v_gradp (spv, spp, msh, coeff)
%
%   mat = spalloc(spp.ndof, spv.ndof, 1);
%   ndir = size (spp.shape_function_gradients, 1);
%   for iel = 1:msh.nel
%     if (all (msh.jacdet(:,iel)))
%       mat_loc = zeros (spp.nsh(iel), spv.nsh(iel));
%       for idof = 1:spp.nsh(iel)
%         ishg = reshape(spp.shape_function_gradients(:,:,idof,iel),ndir,[]);
%         for jdof = 1:spv.nsh(iel)
%           jshg = reshape(spv.shape_functions(:,:,jdof,iel),ndir,[]);
% % The cycle on the quadrature points is vectorized
%           %for inode = 1:msh.nqn
%             mat_loc(idof, jdof) = mat_loc(idof, jdof) + ...
%              sum (msh.jacdet(:, iel) .* msh.quad_weights(:, iel) .* ...
%              sum (ishg .* jshg, 1).' .* coeff(:, iel));
%           %end
%         end
%       end
%       mat(spp.connectivity(:, iel), spv.connectivity(:, iel)) = ...
%         mat(spp.connectivity(:, iel), spv.connectivity(:, iel)) + mat_loc;
%     else
%       warning ('geopdes:jacdet_zero_at_quad_node', 'op_v_gradp: singular map in element number %d', iel)
%     end
%   end
%
% end


function exact = p13_exact ( )

%*****************************************************************************80
%
%% P13_EXACT returns the estimated integral for problem 13.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 July 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real EXACT, the estimated value of the integral.
%
  exact = pi / 2.0;

  return
end


%%
function Metrics = ...
    performCalcu(datasetStruct,algStructArray)

evaluateSal = @(sMap,thresholds,gtMap) thresholdBased_HR_FR(sMap,thresholds,gtMap);

thresholds = [255:-1:0]/255;         % thresholding image from 0 - 255
GTfiles=dir([datasetStruct.GTdir '/*.png']); % gather the GT files in png
GTfiles = [GTfiles; dir([datasetStruct.GTdir '/*.jpg'])]; % gather the GT files in jpg
GTfiles = [GTfiles; dir([datasetStruct.GTdir '/*.bmp'])]; % gather the GT files in bmp

numOfFiles = size(GTfiles,1); % totalImgNum*1
numOfAlgos = length(algStructArray);  % num of algorithmos to be evaluated

[hitRate, falseAlarm] = deal(zeros(numOfFiles,length(thresholds),numOfAlgos));%

%% initial

[IoU, TPR, FPR, Pre, Recall] = deal(zeros(numOfFiles,length(thresholds),numOfAlgos));

[mean_Fmeasure] = deal(zeros(numOfFiles,3,numOfAlgos)); % totalImgNum*3*numOfAlgos [precision, recall, fmeasure]

[MAE] = deal(zeros(numOfFiles,1,numOfAlgos)); % totalImgNum*1*numOfAlgos

[S_measure] = deal(zeros(numOfFiles,1,numOfAlgos)); % totalImgNum*1*numOfAlgos

%Iterate over images
hwait  = waitbar(0,['Processing ', num2str(numOfFiles),' images on ',datasetStruct.datasetName,': 0%']);

for imIndx=1:numOfFiles
    % read the ground truth files
    [~,base_name,ext] = fileparts(GTfiles(imIndx).name);

    gtMap = im2double(imread([datasetStruct.GTdir base_name ext]));
    gtSize = size(gtMap);
    if (length(gtSize) == 3)
        gtMap = rgb2gray(gtMap);
        gtSize(3)= [];
    end

    gtMap = logical(gtMap>=0.1); % get binary mask
    totalNum = numOfFiles* ones(numOfAlgos,1); %3*1   ( [totalImgNum;totalImgNum;totalImgNum;totalImgNum] )
    for algIdx = 1:numOfAlgos % compute over each algorithms iteratively
        sMap = readSaliencyMap(algStructArray{algIdx},[base_name],gtSize);% read and resize saliency maps
        if sum(sum(sMap)) == 0
            totalNum(algIdx) = totalNum(algIdx) - 1;
        end

        [IoU(imIndx,:,algIdx), TPR(imIndx,:,algIdx), FPR(imIndx,:,algIdx), Pre(imIndx,:,algIdx), Recall(imIndx,:,algIdx), ...        % calculate IoU, TPR, FPR, Pre, Recall, hitRate, falseAlarm
         hitRate(imIndx,:,algIdx), falseAlarm(imIndx,:,algIdx)] ...
            = evaluateSal(sMap,thresholds,gtMap);

        [mean_Fmeasure(imIndx,:,algIdx)] = Fmeasure_calu(sMap,gtMap,gtSize); % calculate F-measure using 2 x MeanValueOfSalMap [precision,recall,fmeasure]

        MAE(imIndx,:,algIdx) = CalMAE(sMap, gtMap); % clculate MAE

        S_measure(imIndx,:,algIdx) = StructureMeasure(sMap, gtMap); % calculate S-measure

    end
    pct     = sprintf('%5.1f',imIndx/numOfFiles*100);
    waitbar(imIndx/numOfFiles,hwait,['Processing ', num2str(numOfFiles),...
        ' images on ',datasetStruct.datasetName,': ',pct,'%']);
end %End of image loop

close(hwait);
%Average across images -
mmHitRate = permute( sum(hitRate,1),[2 3 1] );
mmFalseAlarm = permute( sum(falseAlarm,1),[2 3 1]);

nanind = isnan(Pre);
Pre(nanind) = 0;
mmPre = permute( sum(Pre,1),[2 3 1]);
mmRecall = permute( sum(Recall,1),[2 3 1]);
mmTPR = permute( sum(TPR,1),[2 3 1]);
mmFPR = permute( sum(FPR,1),[2 3 1]);
mmIoU = permute( sum(IoU,1),[2 3 1]);

mmmean_Fmeasure = permute( sum(mean_Fmeasure,1),[2 3 1]);
mmMAE = zeros(1,numOfAlgos);
mmS_measure = zeros(1,numOfAlgos);

for j=1:numOfAlgos
    nanind = isnan(MAE(:,1,j));
    mmmMAE = MAE(:,1,j);
    mmmMAE(nanind) = [];

    nanind = isnan(S_measure(:,1,j));
    mmmS_measure = S_measure(:,1,j);
    mmmS_measure(nanind) = [];

    mmHitRate(:,j) = mmHitRate(:,j)./totalNum(j);
    mmFalseAlarm(:,j) = mmFalseAlarm(:,j)./totalNum(j);
    mmPre(:,j) = mmPre(:,j)./totalNum(j);
    mmRecall(:,j) = mmRecall(:,j)./totalNum(j);
    mmTPR(:,j) = mmTPR(:,j)./totalNum(j);
    mmFPR(:,j) = mmFPR(:,j)./totalNum(j);
    mmIoU(:,j) = mmIoU(:,j)./totalNum(j);

    mmmean_Fmeasure(:,j) = mmmean_Fmeasure(:,j)./totalNum(j);
    mmMAE(:,j) = mean(mmmMAE,1);
    mmS_measure(:,j) = mean(mmmS_measure,1);
end
Metrics.HitRate = mmHitRate;
Metrics.FalseAlarm = mmFalseAlarm;
Metrics.Pre = mmPre;
Metrics.Recall = mmRecall;
Metrics.TPR = mmTPR;
Metrics.FPR = mmFPR;
Metrics.IoU = mmIoU;

Metrics.mean_Fmeasure = mmmean_Fmeasure;
Metrics.MAE = mmMAE;
Metrics.S_measure = mmS_measure;
Metrics.AUC = nan(1,size(Metrics.FalseAlarm,2));
for algIdx=1:numOfAlgos
        Metrics.AUC(algIdx) = trapz(Metrics.FalseAlarm(:,algIdx),Metrics.HitRate(:,algIdx));
end

Metrics.mean_Fmeasure_image = mean_Fmeasure;
Metrics.MAE_image = MAE;
Metrics.S_measure_image = S_measure;
Metrics.TPR_image = TPR;
Metrics.FPR_image = FPR;
Metrics.Pre_image = Pre;
Metrics.Recall_image = Recall;

Metrics.Fmeasure_Curve                  = (1+0.3).*Metrics.Pre.*Metrics.Recall./...
                                            (0.3*Metrics.Pre+Metrics.Recall);
[Metrics.MaxFmeasure, ind]              = max(Metrics.Fmeasure_Curve, [], 1);
Metrics.IoU_at_maxF                     = Metrics.IoU(ind);
[Metrics.maxIoU, ~]                     = max(Metrics.IoU, [], 1);
Metrics.meanIoU                         = mean(Metrics.IoU, 1);
end

%% Read Saliency Maps

% Read and resize saliency map
function sMap = readSaliencyMap(algStruct,base_name,gtSize)
if strcmp(algStruct.dir(end-3:end),'DSR')
    algStruct.ext='jpg';
elseif strcmp(algStruct.dir(end-12:end-10),'DSR')
    algStruct.ext='jpg';
end
file_name = fullfile(algStruct.dir,[algStruct.prefix base_name algStruct.postfix '.' algStruct.ext]);
sMap = imresize(im2double(imread(file_name)),gtSize(1:2));
if (size(sMap,3)==3)
    sMap = rgb2gray(sMap);
end
sMap(sMap<0)=0;
maxnum = max(sMap(:));
if maxnum==0
    sMap = zeros(gtSize(1:2));
else
    sMap = sMap./maxnum;
end

end

%% Calculate the scores
function [IoU, TPR, FPR, Pre, Recall, hitRate, falseAlarm] ...
    = thresholdBased_HR_FR(sMap,thresholds,gtMap) %calculate the threshold based scores
    gtPxlNum = sum(gtMap(:));
    totalNum = size(gtMap,1)*size(gtMap,2);
    targetHist = histc(sMap(gtMap), fliplr(thresholds));
    nontargetHist = histc(sMap(~gtMap), fliplr(thresholds));

    targetHist = flipud(targetHist);
    nontargetHist = flipud(nontargetHist);

    targetHist = cumsum( targetHist );
    nontargetHist = cumsum( nontargetHist );

    Pre = targetHist ./ (targetHist + nontargetHist);
    Recall = targetHist / gtPxlNum;
    TPR = Recall;
    FPR = nontargetHist / (totalNum-gtPxlNum);
    IoU = targetHist ./ (gtPxlNum + nontargetHist);
    hitRate = targetHist / gtPxlNum;
    falseAlarm = 1 - (repmat(totalNum-gtPxlNum,size(nontargetHist)) - nontargetHist)/(totalNum-gtPxlNum);
end
%%


function Sf = FreeBoundary(S,t,V,K,type)

Sf = zeros(1,length(t));
eps_star = K*1e-5;

switch type
    case 'put'
        for j = 1:length(t)
            Sf(j) = S(find(abs(V(:,j)-K+S)< eps_star, 1, 'last'));
        end
    case 'call'
        for j = 1:length(t)
            Sf(j) = S(find(abs(V(:,j)+K-S)< eps_star, 1, 'first'));
        end
end


classdef SimplAllTestExplicitVsImplicit < handle

     properties (Access = protected)
        rho
        matInterpExplicit
        matInterpImplicit
        materialPropertiesSettings
        nElem
        nGaus
        dim
     end

     methods (Access = public)

        function obj = SimplAllTestExplicitVsImplicit(dim)
            obj.dim = dim;
            obj.init();
            obj.createProperties();
            obj.computeExplicitMaterialInterpolation();
            obj.computeImplicitMaterialInterpolation();
        end

        function error = computeError(obj)
            mE = obj.matInterpExplicit;
            mI = obj.matInterpImplicit;
            err(1) = norm(mE.mu(:) - mI.mu(:));
            err(2) = norm(mE.kappa(:) - mI.kappa(:));
            err(3) = norm(mE.dmu(:) - mI.dmu(:));
            err(4) = norm(mE.dkappa(:) - mI.dkappa(:));
            error = max(err);
        end
     end

     methods (Access = protected)

        function init(obj)
            obj.nElem = 800;
            obj.nGaus = 4;
            obj.rho = rand(obj.nElem,obj.nGaus);
        end

        function createProperties(obj)
            sC = SettingsConstitutiveProperties();
            sC.E_plus   = rand(1);
            sC.E_minus  = rand(1);
            sC.nu_minus = rand(1);
            sC.nu_plus  = rand(1);
            obj.materialPropertiesSettings = sC;
        end

        function computeExplicitMaterialInterpolation(obj)
            type = 'EXPLICIT';
            mI = obj.computeMaterialInterpolation(type);
            obj.matInterpExplicit = mI;
        end

        function computeImplicitMaterialInterpolation(obj)
            type = 'IMPLICIT';
            mI = obj.computeMaterialInterpolation(type);
            obj.matInterpImplicit = mI;
        end

        function p = computeMaterialInterpolation(obj,type)
            sC = obj.materialPropertiesSettings;
            s = SettingsInterpolation();
            s.constitutiveProperties = sC;
            s.nElem = obj.nElem;
            s.simpAllType = type;
            s.dim = obj.dim;
            mI = MaterialInterpolation.create(s);
            p = mI.computeMatProp(obj.rho);
            obj.matInterpExplicit = p;
        end

     end

end


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

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @defmethod @@sym ei (@var{x})
%% Symbolic exponential integral (Ei) function.
%%
%% Definition and example:
%% @example
%% @group
%% syms x
%% f = ei(x)
%%   @result{} f = (sym) Ei(x)
%% rewrite(f, 'Integral')         % doctest: +SKIP
%%   @result{} (sym)
%%       x
%%       ⌠
%%       ⎮   t
%%       ⎮  ℯ
%%       ⎮  ── dt
%%       ⎮  t
%%       ⌡
%%       -∞
%% @end group
%% @end example
%% (@strong{Note} rewriting as an integral is not yet supported.)
%%
%% Other examples:
%% @example
%% @group
%% diff(f)
%%   @result{} (sym)
%%        x
%%       ℯ
%%       ──
%%       x
%% @end group
%% @end example
%%
%% @seealso{@@sym/expint}
%% @end defmethod

function y = ei(x)
  if (nargin ~= 1)
    print_usage ();
  end
  y = elementwise_op ('Ei', x);
end

%!test
%! syms x
%! f = ei(sym(0));
%! assert (double(f) == -inf)

%!test
%! D = [1.895117816355937  4.954234356001890];
%! A = ei(sym([1 2]));
%! assert (all (abs(double(A) - D) < 1e-15))


function bs = bct_toolbox_undirected_graph_metrics(bs, thresh, varargin)
% bs = bct_toolbox_undirected_graph_metrics(bs)
%
% thresh = proportional link density threshold; 0 to 1 value. (.1 is a common value)
%
% Method for brainpathway_multisubject that extracts graph metrics using
% the Sporns lab (et al.) BCT toolbox.
% Uses bct_toolbox_undirected_graph_metrics
%
% Stores results in bs.graph_properties.regions
% - Nodes x subjects matrix for each graph property
% - Can do group stats/t-tests/etc on (matrices)'
%
% Examples:
% ------------------------------------------------------------------
% Load brainpathway_data_gsr_censoring_pipeline.mat % from OLP/Yoni
% bs = bct_toolbox_undirected_graph_metrics(bs);
% mean_degree = nanmean(bs.graph_properties.regions.degree')'; % mean degree for each node
%
% % Plot montage of mean degree on brain
% fmri_dat_obj = brainpathway2fmri_data(bs, bs.graph_properties.regions.degree);
% montage(mean(fmri_dat_obj));

r = double(bs.connectivity.regions.r);

n = size(r, 3); % subjects
n_nodes = size(r, 1); % nodes

bs.graph_properties.regions = table(); % clear out -- overwrite

fprintf('Completed  subject        ');

warning off
for i = 1:n

    [graph_prop, graph_prop_glob] = bct_toolbox_undirected_graph_metrics(r(:, :, i), thresh, varargin{:});

    % nodal properties
    vnames = graph_prop.Properties.VariableNames;
    for j = 1:length(vnames)

        bs.graph_properties.regions.(vnames{j})(i, 1:n_nodes) = graph_prop.(vnames{j});

    end

    % global properties
    vnames = graph_prop_glob.Properties.VariableNames;
    for j = 1:length(vnames)

        bs.graph_properties.regions.(vnames{j})(i, 1) = graph_prop_glob.(vnames{j});

    end

    % print to update status
    fprintf('\b\b\b\b\b\b%5d\n',i)

end % subject loop
warning on

end % function


function [imgCrop, scaling, seg, warn, valid] = LMobjectnormalizedcrop(img, annotation, j, b, height, width)
%
% Crop object from image using a normalized frame
% [imgCrop, scaling] = LMobjectnormalizedcrop(img, annotation, j, [bh bw], height, width)
% [imgCrop, scaling] = LMobjectnormalizedcrop(img, [xmin ymin xmax ymax], j, [bh bw], height, width)
%  extract object index j from the annotation.
%
%   ------------
%   |    bh    |   b = [bh bw] = number of boundary pixels
%   |   ----   |   h = height inner bounding box
%   |bw |  |   |   w = width inner bounding box
%   |   |h |   |
%   |   ----   |
%   |    w     |
%   ------------
%

if length(b) == 1
    b = b *[1 1];
end
bh = b(1);
bw = b(2);

if isstruct(annotation)
    [X,Y,t] = getLMpolygon(annotation.object(j).polygon);
else
    xmin = annotation(1); % [xmin ymin xmax ymax]
    ymin = annotation(2); % [xmin ymin xmax ymax]
    xmax = annotation(3); % [xmin ymin xmax ymax]
    ymax = annotation(4); % [xmin ymin xmax ymax]
    X = [xmin xmin xmax xmax];
    Y = [ymin ymax ymax ymin];
    t = 1;
end
numFrames = length(t);

if nargin < 6
    % decide which dimension is larger and use
    Dx = max(X)-min(X);
    Dy = max(Y)-min(Y);
    if Dy>Dx
        width = round(height*Dx/Dy);
    else
        % if Dx>Dy,
        h = round(height*Dy/Dx);
        width = height;
        height = h;
    end
end

imgCrop = zeros([height+2*bh width+2*bw size(img,3) numFrames], 'uint8');
seg = zeros([height+2*bh width+2*bw numFrames], 'uint8');
valid = zeros([height+2*bh width+2*bw numFrames], 'uint8');
warn = zeros(1, numFrames);
for f = t
    if numFrames>1
        i = find(t==f); i = i(1);
        x = X(:,i);
        y = Y(:,i);
    else
        i = 1;
        x = X;
        y = Y;
    end

    %  bb = boundingbox = [xmin ymin xmax ymax]
    bb = [min(x) min(y) max(x) max(y)];

    % 1) Resize image so that object is normalized in size
    scaling = min(height/(bb(4)-bb(2)), width/(bb(3)-bb(1)));
    if numFrames>1
        [foo, I] = LMimscale([], img(:,:,:,f+1), scaling, 'bilinear');
    else
        [foo, I] = LMimscale([], img, scaling, 'bilinear');
    end
    bb = bb*scaling; x = x*scaling; y = y*scaling;

    % 2) pad image (just to make sure)
    margin = 5+max(width,height)+ceil(max(bh,bw)+1 + max([0 -bb(1) -bb(2) bb(4)-size(I,1) bb(3)-size(I,2)]));
    [foo, I] = LMimpad(foo, single(I), [size(I,1)+2*margin size(I,2)+2*margin], NaN);
    bb = bb+margin; x = x+margin; y = y+margin;

    % 2) Crop result
    cx = fix((bb(3)+bb(1))/2); cy = fix((bb(4)+bb(2))/2);

    bb = round([cx-width/2-bw+1 cy-height/2-bh+1 cx+width/2+bw cy+height/2+bh]);

    x = x - bb(1)+2; y = y - bb(2)+2;

    % Image crop:
    crop = I(bb(2):bb(4), bb(1):bb(3), :);
    imgCrop(:,:,:,i) = uint8(crop);

    [xx,yy] = meshgrid(1:size(imgCrop,2),1:size(imgCrop,1));
    seg(:,:,i) = uint8(255*double(inpolygon(xx, yy, x, y)));

    valid(:,:,i) = 1-isnan(sum(crop,3));

    % warnings by crops of scales
    warn(i) = (scaling>1) || (sum(isnan(crop(:)))>500);
end


function [Fmax, iMax] = bst_max(F, dim)
% BST_MAX: Get the maximum in magnitude, but with the correct sign.
%
% USAGE:  [Fmax, iMax] = bst_max(F, dim=1)

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

% Parse inputs
if (nargin < 2) || isempty(dim)
    dim = [];
end

% Get the sign of each maximum
if isempty(dim)
    [Fmax, iMax] = max(abs(F(:)));
    Fmax = sign(F(iMax)) .* Fmax;
elseif (dim <= 5)
    % Permute with first dimension
    if (dim > 1)
        permdim = [dim, 2:ndims(F)];
        permdim(dim) = 1;
        F = permute(F, permdim);
    end
    % Reshape to ensure that the matrix has 2 dimensions
    nd = ndims(F);
    if (nd > 2)
        oldSize = [size(F,1), size(F,2), size(F,3), size(F,4), size(F,5)];
        F = reshape(F, size(F,1), []);
    end
    % Get maximum absolute values
    [Fmax, iMax] = max(abs(F), [], 1);
    % Build indices of the values to read
    iF = sub2ind(size(F), iMax, 1:size(F,2));
    Fmax = sign(F(iF)) .* Fmax;
    % Restore initial shape
    if (nd > 2)
        Fmax = reshape(Fmax, 1, oldSize(2), oldSize(3), oldSize(4), oldSize(5));
        iMax = reshape(iMax, 1, oldSize(2), oldSize(3), oldSize(4), oldSize(5));
    end
    % Restore initial dimensions
    if (dim > 1)
        Fmax = permute(Fmax, permdim);
        iMax = permute(iMax, permdim);
    end
else
    error('Not supported yet.');
end


function CM=ImaGIN_connectivity_matrix(N)
% -=============================================================================
% This function is part of the ImaGIN software:
% https://f-tract.eu/
%
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE AUTHORS
% DO NOT ASSUME ANY LIABILITY OR RESPONSIBILITY FOR ITS USE IN ANY CONTEXT.
%
% Copyright (c) 2000-2018 Inserm U1216
% =============================================================================-
%
% Authors: Olivier David

ncouple	= N*(N-1)/2;
if ncouple>0
    CM	= zeros(2,ncouple);
    cou	= 0;
    for ii	= 1:N-1
        j	= ii+1;
        cou	= cou+1;
        CM(1,cou)	= ii;
        CM(2,cou)	= j;
        while j < N
            j	= j+1;
            cou	= cou+1;
            CM(1,cou)	= ii;
            CM(2,cou)	= j;
        end
    end
else
    CM=[];
end
return


function spm_mvb_cvk_display(MVB)
% model display for MVB with cross-validation
% FORMAT spm_mvb_cvk_display(MVB)
% MVB  - multivariate Bayes structure, select one if not provided
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Christophe Phillips
% $Id: spm_mvb_cvk_display.m 3806 2010-04-06 14:42:32Z ged $

if nargin<1
    load(spm_select(1,'^MVB.*\.mat','Select MVB to display'))
end
if ~isfield(MVB,'cvk')
    error(['No crossvalidation data available. ' ...
        'Select another file or perform the crossvalidation']);
end

%-Get figure handles and set title
%--------------------------------------------------------------------------
Fmvb = spm_figure('GetWin','MVB');
spm_clf(Fmvb);

% get stuff in place for display
%--------------------------------------------------------------------------
K     = MVB.K;
X     = K*MVB.X;
X0    = orth(K*MVB.X0);
R     = speye(length(X)) - X0*X0';
R     = orth(R);
pX     = R*R'*X;

% plot validation
%--------------------------------------------------------------------------
subplot(2,2,1)
s      = 1:length(pX);
plot(s,pX,s,MVB.cvk.qX,'-.')
xlabel('sample')
ylabel('response (adjusted)')
title('cross-validation')
axis square

subplot(2,2,2)
plot(pX,MVB.cvk.qX,'.')
xlabel('true')
ylabel('predicted')
title(sprintf('p-value (parametric) = %.5f',MVB.p_value))
axis square
abc = axis;
hold on
plot([max(abc([1 3])) min(abc([2 4]))],[max(abc([1 3])) min(abc([2 4]))],'k')

% plot feature weights
%--------------------------------------------------------------------------
subplot(2,2,3)
imagesc(corrcoef(MVB.cvk.qE))
colorbar
caxis([0 1])
xlabel('bipartition (k)')
title({'correlations among';'k-fold feature weights'})
axis square

subplot(2,2,4)
if ~isempty(MVB.XYZ) && ~isempty(MVB.VOX)
    if isfield(MVB.cvk, 'P')
        spm_mip(prod(MVB.cvk.P,2),MVB.XYZ(1:3,:),MVB.VOX)
        title({[MVB.name ' (' MVB.contrast ')'];'prod( P(|weights| > 0) )'})
    else % reproduce plot from original spm_mvb_cvk2
        qe = mean(MVB.cvk.qE,2);
        qe = qe.*(qe > 0);
        spm_mip(qe,MVB.XYZ(1:3,:),MVB.VOX)
        title({[MVB.name ' (' MVB.contrast ')'];'mean (positive) weights'})
    end
else
    % (Allows MVB for non-spatial data, excluding smooth or compact priors)
    title('No spatial info in MVB')
end
axis square

fprintf('\np-value = %.4f; classification: %.1f%%; R-squared %.1f%%\n', ...
    MVB.p_value,MVB.percent,MVB.R2)


% Test file for chebfun constructor (basic).

function pass = test_constructor_basic(pref)

if ( nargin == 0 )
    pref = chebfunpref();
end

% Some basic test functions:
FF = {@sin, @(x) [sin(x), cos(x)], @(x) [sin(x), cos(x), exp(-x)]};

for j = 1:numel(FF);
    % Initialise k:
    k = 0;

    % Pick the test function:
    F = FF{j};

    % Test on [-1 1]:
    f = chebfun(F, [-1, 1], pref);
    xx = linspace(-1, 1);
    err = norm(feval(f, xx) - F(xx), inf);
    pass(j, k+1) = err < 10*eps*vscale(f);
    pass(j, k+2) = err < 50*pref.chebfuneps;
    k = k + 2;

    % Test on [-1 1] (no domain passed):
    f = chebfun(F, pref);
    xx = linspace(-1, 1);
    err = norm(feval(f, xx) - F(xx), inf);
    pass(j, k+1) = err < 10*eps*vscale(f);
    pass(j, k+2) = err < 500*pref.chebfuneps;
    k = k + 2;

    % Test on [0 10000]:
    f = chebfun(F, [0, 10000], pref);
    xx = linspace(0, 10000);
    err = norm(feval(f, xx) - F(xx), inf);
    pass(j, k+1) = err < 1e4*eps*vscale(f);
    pass(j, k+2) = err < 1e2*hscale(f)*pref.chebfuneps;
    k = k + 2;

    % Test on piecewise domain:
    f = chebfun(F, [-1, 0, .5, sqrt(pi/4), 1], pref);
    xx = linspace(-1, 1);
    err = norm(feval(f, xx) - F(xx), inf);
    pass(j, k+1) = err < 10*eps*vscale(f);
    pass(j, k+2) = err < 100*pref.chebfuneps;
    k = k + 2;
end

end


function point_num = sparse_grid_cc_size_old ( dim_num, level_max )

%*****************************************************************************80
%
%% SPARSE_GRID_CC_SIZE_OLD sizes a sparse grid of Clenshaw Curtis points.
%
%  Discussion:
%
%    This function has been replaced by a much faster version.
%
%    It is retained for historical interest only.
%
%    The grid is defined as the sum of the product rules whose LEVEL
%    satisfies:
%
%      0 <= LEVEL <= LEVEL_MAX.
%
%    This routine works on an abstract set of nested grids.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 July 2008
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Fabio Nobile, Raul Tempone, Clayton Webster,
%    A Sparse Grid Stochastic Collocation Method for Partial Differential
%    Equations with Random Input Data,
%    SIAM Journal on Numerical Analysis,
%    Volume 46, Number 5, 2008, pages 2309-2345.
%
%  Parameters:
%
%    Input, integer DIM_NUM, the spatial dimension.
%
%    Input, integer LEVEL_MAX, the maximum value of LEVEL.
%
%    Output, integer POINT_NUM, the total number of unique points in the grids.
%

%
%  Special case.
%
  if ( level_max == 0 )
    point_num = 1;
    return
  end
%
%  The outer loop generates LEVELs from 0 to LEVEL_MAX.
%
  point_num = 0;

  for level = 0 : level_max
%
%  The middle loop generates the next partition that adds up to LEVEL.
%
    level_1d = [];
    more = 0;
    h = 0;
    t = 0;

    while ( 1 )

      [ level_1d, more, h, t ] = comp_next ( level, dim_num, level_1d, more, h, t );
%
%  Transform each 1D level to a corresponding 1D order.
%
      order_1d = level_to_order_closed ( dim_num, level_1d );
%
%  The product of the 1D orders gives us the number of points in this grid.
%
      order_nd = prod ( order_1d(1:dim_num) );
%
%  The inner (hidden) loop generates all points corresponding to given grid.
%
      grid_index = multigrid_index0 ( dim_num, order_1d, order_nd );
%
%  Adjust these grid indices to reflect LEVEL_MAX.
%
      grid_index = multigrid_scale_closed ( dim_num, order_nd, level_max, ...
        level_1d, grid_index );
%
%  Determine the first level of appearance of each of the points.
%
      grid_level = abscissa_level_closed_nd ( level_max, dim_num, order_nd, ...
        grid_index );
%
%  Only keep those points which first appear on this level.
%
      for point = 1 : order_nd

        if ( grid_level(point) == level )

          point_num = point_num + 1;

        end

      end

      if ( ~more )
        break
      end

    end

  end

  return
end


function obj = updateImplicitFunctionSurface(obj, surfaceIndex)

%-AXIS INDEX-%
axIndex = obj.getAxisIndex(obj.State.Plot(surfaceIndex).AssociatedAxis);

%-CHECK FOR MULTIPLE AXES-%
[xsource, ysource] = findSourceAxis(obj,axIndex);

%-SURFACE DATA STRUCTURE- %
image_data = get(obj.State.Plot(surfaceIndex).Handle);
figure_data = get(obj.State.Figure.Handle);

%-AXIS DATA-%
eval(['xaxis = obj.layout.xaxis' num2str(xsource) ';']);
eval(['yaxis = obj.layout.yaxis' num2str(ysource) ';']);

%-------------------------------------------------------------------------%

%-surface xaxis-%
obj.data{surfaceIndex}.xaxis = ['x' num2str(xsource)];

%-------------------------------------------------------------------------%

%-surface yaxis-%
obj.data{surfaceIndex}.yaxis = ['y' num2str(ysource)];

%-------------------------------------------------------------------------%

%-surface type-%
obj.data{surfaceIndex}.type = 'surface';

%---------------------------------------------------------------------%

%-getting x,y,z surface data-%

strf = func2str(image_data.Function);
ind1 = strfind(strf, '('); ind1 = ind1(1)+1;
ind2 = strfind(strf, ')'); ind2 = ind2(1)-1;
vars = split(strf(ind1:ind2), ',');

strf = [strf(ind2+2:end) '==0'];
strf = replace(strf, vars{1}, 'Xx');
strf = replace(strf, vars{2}, 'Yy');
strf = replace(strf, vars{3}, 'Zz');

syms Xx Yy Zz;
f = eval(strf);
s = solve(f, Zz);

x = image_data.XRange;
y = image_data.YRange;
z = image_data.ZRange;
N = 400;

[Xx,Yy] = meshgrid(linspace(x(1),x(2),N), linspace(y(1),y(2),N));
X = []; Y = []; Z = [];

for n = 1:length(s)
    X = [X; Xx];
    Y = [Y; Yy];
    Z = [Z; eval(s(n))];
end

clear Xx Yy Zz;
Z(Z < z(1)) = nan; Z(Z > z(2)) = nan;
X(Z < z(1)) = nan; X(Z > z(2)) = nan;
Y(Z < z(1)) = nan; Y(Z > z(2)) = nan;

%---------------------------------------------------------------------%

%-surface x-%
obj.data{surfaceIndex}.x = X;

%---------------------------------------------------------------------%

%-surface y-%
obj.data{surfaceIndex}.y = Y;

%---------------------------------------------------------------------%

%-surface z-%
obj.data{surfaceIndex}.z = Z;

%---------------------------------------------------------------------%

%- setting grid mesh by default -%
% x-direction
mden = image_data.MeshDensity;
xsize = (x(2) - x(1)) / mden;
obj.data{surfaceIndex}.contours.x.start = x(1);
obj.data{surfaceIndex}.contours.x.end = x(2);
obj.data{surfaceIndex}.contours.x.size = xsize;
obj.data{surfaceIndex}.contours.x.show = true;
obj.data{surfaceIndex}.contours.x.color = 'black';
% y-direction
ysize = (y(2) - y(1)) / mden;
obj.data{surfaceIndex}.contours.y.start = y(1);
obj.data{surfaceIndex}.contours.y.end = y(2);
obj.data{surfaceIndex}.contours.y.size = ysize;
obj.data{surfaceIndex}.contours.y.show = true;
obj.data{surfaceIndex}.contours.y.color = 'black';
% z-direction
zsize = (z(2) - z(1)) / mden;
obj.data{surfaceIndex}.contours.z.start = z(1);
obj.data{surfaceIndex}.contours.z.end = z(2);
obj.data{surfaceIndex}.contours.z.size = zsize;
obj.data{surfaceIndex}.contours.z.show = true;
obj.data{surfaceIndex}.contours.z.color = 'black';

%-------------------------------------------------------------------------%

%-image colorscale-%

cmap = figure_data.Colormap;
len = length(cmap)-1;

for c = 1: length(cmap)
    col = 255 * cmap(c, :);
    obj.data{surfaceIndex}.colorscale{c} = { (c-1)/len , ['rgb(' num2str(col(1)) ',' num2str(col(2)) ',' num2str(col(3)) ')'  ]  };
end

%-------------------------------------------------------------------------%

%-image surfacescale-%
obj.data{surfaceIndex}.surfacecolor = Z;

%-------------------------------------------------------------------------%

%-surface name-%
obj.data{surfaceIndex}.name = image_data.DisplayName;

%-------------------------------------------------------------------------%

%-surface showscale-%
obj.data{surfaceIndex}.showscale = false;

%-------------------------------------------------------------------------%

%-surface visible-%
obj.data{surfaceIndex}.visible = strcmp(image_data.Visible,'on');

%-------------------------------------------------------------------------%

leg = get(image_data.Annotation);
legInfo = get(leg.LegendInformation);

switch legInfo.IconDisplayStyle
    case 'on'
        showleg = true;
    case 'off'
        showleg = false;
end

obj.data{surfaceIndex}.showlegend = showleg;

%-------------------------------------------------------------------------%

end


function [bcx,bcy] = specific_flow(xbd,ybd)
%forwardstep_flow   Forward facing step inflow condition
%   [bcx,bcy] = specific_flow(xbd,ybd);
%   input
%          xbd          x coordinate vector
%          ybd          y coordinate vector
%
%   specifies forward step flow boundary condition
%   IFISS function: DJS; 6 March 2005.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage
bcx=0*xbd; bcy=0*xbd;
k=find(xbd==5); bcx(k)=-0.5*(1+ybd(k)).*(1-ybd(k));
return


function varargout = plotlattice(varargin)
%PLOTLATTICE  Plots an integer lattice
%
% p = plotlattice(C,which,c,size,options)
%
% C    :  Constraint object
% which:  'inner' (default) or 'outer'
% color:  color [double] ([r g b] format) or char from 'rymcgbk'
% size :  Size of marker
% options: options structure from sdpsettings
% Example
% sdpvar x1 x2
% plot(x1^2+x2^2 <= 1.5,'green');hold on
% plotlattice(x1^2+x2^2 <= 1.5,'outer','yellow');
% plotlattice(x1^2+x2^2 <= 1.5,'inner','black');

h = ishold;
hold on
F = varargin{1};
if nargin > 1 && ~isempty(varargin{2})
    which = varargin{2};
else
    which = 'inner';
end
if nargin > 2 && ~isempty(varargin{3})
    color = varargin{3};
else
    color = 'yellow';
end
if nargin > 3 && ~isempty(varargin{4})
    size = varargin{4};
else
    size = 5;
end
if nargin > 4
    ops = varargin{5};
    if ~isempty(ops)
        ops = sdpsettings(ops,'verbose',0);
    else
        ops = sdpsettings('relax',2,'verbose',0);
    end
else
    ops = sdpsettings('relax',2,'verbose',0);
end

X = recover(depends(F));
[~,L,U] = boundingbox(F,ops);

x = floor(L(1)):ceil(U(1));
y = floor(L(2)):ceil(U(2));
ThreeD = length(L)>2;
if ThreeD
    z = floor(L(3)):ceil(U(3));
else
    z = 1;
end
V = [];
for i = x
    for j = y
        for k = z
        switch which
            case 'outer'
                if ThreeD
                    l = plot3(i,j,k,'or','MarkerSize',size);
                else
                    l = plot(i,j,'or','MarkerSize',size);
                end
                set(l,'MarkerFaceColor',color);
                V = [V [i;j;k]];
            case 'inner'
                if ThreeD
                    assign(X,[i;j;k]);
                else
                    assign(X,[i;j]);
                end
                p = check(F);
                if min(p) >= 0
                    if ThreeD
                        l = plot3(i,j,k,'or','MarkerSize',size,'MarkerFaceColor','yellow');
                        V = [V [i;j;k]];
                    else
                        l = plot(i,j,'or','MarkerSize',size,'MarkerFaceColor','yellow');
                        V = [V [i;j]];
                    end
                    set(l,'MarkerFaceColor',color);
                end
            otherwise
                error
        end
        end
    end
end
if ~h
    hold off;
end
if nargout > 0
    varargout{1} = V;
end


function OUT = TabPrint(DATA,hlabel,vlabel,approx)
% =======================================================================
% Prints a numerical table with labels, with specified numbers of decimal
% digits
% =======================================================================
% OUT = TabPrint(DATA,hlabel,vlabel,approx)
% -----------------------------------------------------------------------
% INPUT
%   - DATA = a (TxN) matrix of numbers
% -----------------------------------------------------------------------
% OPTIONAL INPUT
%	- hlabel = a (Tx1) vector of horizontal labels
%	- vlabel = a (1xT) vector of vertical labels
%   - approx = number of decimal digits. Default = 2
% -----------------------------------------------------------------------
% OUTPUT
%   - OUT = a cell array with the formatted table
% -----------------------------------------------------------------------
% EXAMPLE
%   x = [1 2; 3 4; 5 6; 7 8; 9 10];
%   hlab = {'a';'b';'c';'d';'e';}
%   vlab = {'A','B'}
%   OUT = TabPrint(x,hlab,vlab)
% =======================================================================
% VAR Toolbox 3.0
% Ambrogio Cesa-Bianchi
% ambrogiocesabianchi@gmail.com
% March 2012. Updated November 2020
% -----------------------------------------------------------------------

[n, m] = size(DATA);

if ~exist('hlabel','var') || isempty(hlabel)
    hlabel = cell(1,m);
end

if ~exist('vlabel','var') || isempty(vlabel)
    vlabel = cell(n,1);
end

if ~exist('approx','var')
    approx = 2;
end

if length(hlabel)~=m
    error('ERROR: horizontal label has wrong dimension')
end

if length(vlabel)~=n
    error('ERROR: vertical label has wrong dimension')
end

OUT = roundnum2cell(DATA,approx); % Trasform matrix in cell wih approx decimal digits

OUT = [hlabel ; OUT];
aux = cell(rows(hlabel),cols(vlabel));
vlabel = [aux; vlabel];
OUT = [vlabel, OUT];


function [x,options] = lsqnonneg_fast(C,d,options)
%LSQNONNEG Linear least squares with nonnegativity constraints.
%
%function [x,resnorm,resid,exitflag,output,lambda] =
%lsqnonneg(C,d,x0,options)
%
%   X = LSQNONNEG(C,d) returns the vector X that minimizes NORM(C*X - d)
%   subject to X >= 0. C and d must be real.
%
%   X = LSQNONNEG(C,d,X0) uses X0 as the starting point if all(X0 > 0);
%   otherwise the default is used. The default start point is the
%   origin (the default is used when X0==[] or when only two input
%   arguments are provided).
%
%   X = LSQNONNEG(C,d,X0,OPTIONS) minimizes with the default optimization
%   parameters replaced by values in the structure OPTIONS, an argument
%   created with the OPTIMSET function.  See OPTIMSET for details.  Used
%   options are Display and TolX. (A default tolerance TolX of
%   10*MAX(SIZE(C))*NORM(C,1)*EPS is used).
%
%   [X,RESNORM] = LSQNONNEG(...) also returns the value of the squared 2-norm of
%   the residual: norm(C*X-d)^2.
%
%   [X,RESNORM,RESIDUAL] = LSQNONNEG(...) also returns the value of the
%   residual: C*X-d.
%
%   [X,RESNORM,RESIDUAL,EXITFLAG] = LSQNONNEG(...) returns an EXITFLAG that
%   describes the exit condition of LSQNONNEG.
%   If EXITFLAG is:
%     1 then LSQNONNEG converged with a solution X.
%     0 then the iteration count was exceeded. Increasing the tolerance
%       (OPTIONS.TolX) may lead to a solution.
%
%   [X,RESNORM,RESIDUAL,EXITFLAG,OUTPUT] = LSQNONNEG(...) returns a structure
%   OUTPUT with the number of steps taken in OUTPUT.iterations and the type
%   of algorithm used in OUTPUT.algorithm.
%
%   [X,RESNORM,RESIDUAL,EXITFLAG,OUTPUT,LAMBDA] = LSQNONNEG(...) returns
%   the dual vector LAMBDA  where LAMBDA(i) <= 0 when X(i) is (approximately) 0
%   and LAMBDA(i) is (approximately) 0 when X(i) > 0.
%
%   See also LSCOV, SLASH.

%   L. Shure 5-8-87
%   Revised, 12-15-88,8-31-89 LS, 5-26-98 MAB.
%   Copyright (c) 1984-98 by The MathWorks, Inc.
%   $Revision: 1.6 $  $Date: 1998/08/25 15:18:02 $

% Reference:
%  Lawson and Hanson, "Solving Least Squares Problems", Prentice-Hall, 1974.

if nargin<3
    %disp('Calculating optimset');

    defaultopt = optimset('display','final','TolX','10*eps*norm(C,1)*length(C)');
    if ~isreal(C) || ~isreal(d), error('C and d must be real.'); end
    options = [];
    options = optimset(defaultopt,options);
    printtype = optimget(options,'display');
    tol = optimget(options,'tolx');

    % In case the defaults were gathered from calling: optimset('fminsearch'):
    c=C;
    if ischar(tol)
        tol = eval(tol);
    end

    switch printtype
        case {'none','off'}
            verbosity = 0;
        case 'iter'
            warning('''iter'' value not valid for ''Display'' parameter for lsqnonneg');
            verbosity = 2;
        case 'final'
            verbosity = 1;
        otherwise
            error('Bad value for options parameter: ''Display''');
    end
end
tol = optimget(options,'tolx');
c=C;
if ischar(tol)
    tol = eval(tol);
end

[m,n] = size(C);
P = zeros(1,n);
Z = 1:n;
x = P';

ZZ=Z;
resid = d-C*x;
w = C'*(resid);

% set up iteration criterion
outeriter = 0;
iter = 0;
itmax = 3*n;
exitflag = 1;

% outer loop to put variables into set to hold positive coefficients
while any(Z) && any(w(ZZ) > tol)
   outeriter = outeriter + 1;
   [wt,t] = max(w(ZZ));
   t = ZZ(t);
   P(1,t) = t;
   Z(t) = 0;
   PP = find(P);
   ZZ = find(Z);
   nzz = size(ZZ);
   CP(1:m,PP) = C(:,PP);
   CP(:,ZZ) = zeros(m,nzz(2));
   z = pinv(CP)*d;
   z(ZZ) = zeros(nzz(2),nzz(1));
   % inner loop to remove elements from the positive set which no longer belong
   while any((z(PP) <= tol))
      iter = iter + 1;
      if iter > itmax
         if verbosity
            warnstr = sprintf('Exiting: Iteration count is exceeded, exiting LSQNONNEG.', ...
               '\n','Try raising the tolerance (OPTIONS.TolX).');
            disp(warnstr);
         end
         exitflag = 0;
         output.iterations = outeriter;
         resnorm = sum(resid.*resid);
         x = z;
         lambda = w;
         return
      end
      QQ = find((z <= tol) & P');
      alpha = min(x(QQ)./(x(QQ) - z(QQ)));
      x = x + alpha*(z - x);
      ij = find(abs(x) < tol & P' ~= 0);
      Z(ij)=ij';
      P(ij)=zeros(1,length(ij));
      PP = find(P);
      ZZ = find(Z);
      nzz = size(ZZ);
      CP(1:m,PP) = C(:,PP);
      CP(:,ZZ) = zeros(m,nzz(2));
      z = pinv(CP)*d;
      z(ZZ) = zeros(nzz(2),nzz(1));
   end
   x = z;
   resid = d-C*x;
   w = C'*(resid);
end

lambda = w;
resnorm = sum(resid.*resid);
output.iterations = outeriter;
output.algorithm = 'active-set using svd';

verbosity =0;

if verbosity > 0
   disp('Optimization terminated successfully.');
end


function [bnt_data, old_values] = transform_data_into_bnt_format(data,cnodes)
% TRANSFORM_DATA_TO_BNT_FORMAT Ensures discrete variables have values 1,2,..,k
% e.g., if the values of a discrete are [0 1 6], they must be mapped to [1 2 3]
%
% data(i,j) is the value for i-th node in j-th case.
% bnt_data(i,j) is the new value.
% old_values{i} are the original values for node i.
% cnodes is the list of all continous nodes, e.g. [3 5] means the 3rd and 5th node is continuous
%
% Author: yimin.zhang@intel.com
% Last updated: Jan. 22, 2002 by Kevin Murphy.

num_nodes=size(data,1);
num_cases=size(data,2);
old_values=cell(1,num_nodes);

for i=1:num_nodes
  if (myismember(i,cnodes)==1)  %cts nodes no need to be transformed
    %just copy the data
    bnt_data(i,:)=data(i,:);
    continue;
  end
  values = data(i,:);
  sort_v = sort(values);
  %remove the duplicate values in sort_v
  v_set = unique(sort_v);

  %transform the values
  for j=1:size(values,2)
    index = binary_search(v_set,values(j));
    if (index==-1)
      fprintf('value not found in tranforming data to bnt format.\n');
      return;
    end
    bnt_data(i,j)=index;
  end
  old_values{i}=v_set;
end

%%%%%%%%%%%%

function index=binary_search(vector, value)
% BI_SEARCH do binary search for value in the vector
% Author: yimin.zhang@intel.com
% Last updated: Jan. 19, 2002

begin_index=1;
end_index=size(vector,2);
index=-1;
while (begin_index<=end_index)
  mid=floor((begin_index+end_index)/2);
  if (isstr(vector(mid)))
    % need to write a strcmp to return three result (< = >)
  else
    if (value==vector(mid))
      index=mid;
      return;
    elseif (value>vector(mid))
      begin_index=mid+1;
    else
      end_index=mid-1;
    end
  end
end
return;


function [varargout]=spmax(varargin)

% function [maxVal,maxInd]=spmax(A,B,vecdim,nanflag,logicRelevant,nanOut)
% ------------------------------------------------------------------------
%
%
% Kevin Moerman
% ------------------------------------------------------------------------

%%

A=varargin{1};

if nargin>=3
    dimDir=varargin{3};
else
    dimDir=1;
end

switch nargin
    case 5
        logicRelevant=varargin{5};
        varargin=varargin(1:4);
        nanOut=0;
        if isempty(varargin{4})
            varargin=varargin(1:3);
        end
    case 6
        logicRelevant=varargin{5};
        nanOut=varargin{6};
        varargin=varargin(1:4);
        if isempty(varargin{4})
            varargin=varargin(1:3);
        end
    otherwise
        logicRelevant=[];
        nanOut=0;
end

if isempty(logicRelevant)
    logicRelevant=A~=0;
end

logicRelevantRow=full(any(logicRelevant,dimDir));

%%

minOffset=min(A(logicRelevant));

A(logicRelevant)=A(logicRelevant)-minOffset; %Shift to negative to zeros loose
varargin{1}=A;
[maxVal,maxInd]=max(varargin{:});
maxVal(logicRelevantRow)=maxVal(logicRelevantRow)+minOffset; %Shift back
if nanOut==1
    maxVal(~logicRelevantRow)=NaN;
end

%% Collect output
varargout{1}=maxVal;
varargout{2}=maxInd;

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


function M = perform_lic(v, w, options)

% perform_lic - perform line integral convolution
%
%   M = perform_lic(v, w, options);
%
%   v is a vector field (should be approximately of unit norm).
%   w is the length of the convolution (in pixels)
%   M is an image of filtered noise that illustrate well the flow of v.
%
%   options.spot_size set the size of the features.
%
%   Set options.flow_correction=1 in order to fix problem
%   around singularity points of the flow.
%
%   The method is described in
%       Imaging vector fields using line integral convolution
%       Brian Cabral, Leith Casey Leedom
%       Siggraph 1993
%
%   If the vector field is not oriented (e.g. if it is an eigenvector field
%   of a tensor field) then set options.isoriented=1. It will perform two
%   LIC (horizontal and vertical) and then average them. This trick is
%   explained in
%       Interactive Tensor Field Design and Visualization on Surfaces
%       Eugene Zhang, James Hays, and Greg Turk
%       IEEE Transactions on Visualization and Computer Graphics
%       Volume 13 ,  Issue 1, Pages: 94-107, 2007.
%
%   Copyright (c) Gabriel Peyre 2007

n = size(v,1);

options.null = 0;
if isfield(options, 'M0')
    M0 = options.M0;
else
    M0 = randn(n);
    if isfield(options, 'spot_size')
        sigma = options.spot_size;
    else
        sigma = 2;
    end
    M0 = perform_blurring(M0, sigma, options);
end

if size(M0,3)>1
    % lic on each channel
    for i=1:size(M0,3)
        options.M0 = M0(:,:,i);
        M(:,:,i) = perform_lic(v, w, options);
    end
    return;
end

isoriented = getoptions(options, 'isoriented', 1);

if isoriented==0
    % run twice the lic in each direction
    options.isoriented = 1;
    options.method = 'xproj';
    v = perform_vf_reorientation(v, options);
    M1 = perform_lic(v, w, options);
    options.method = 'yproj';
    v = perform_vf_reorientation(v, options);
    M2 = perform_lic(v, w, options);
    % weight
    v = perform_vf_normalization(v);
    T = v(:,:,1).^2;
    M = T.*M1 + (1-T).*M2;
    return;
end

if isfield(options, 'niter_lic') && options.niter_lic>1
    M = options.M0;
    niter_lic = options.niter_lic;
    options.niter_lic = 1;
    for i=1:niter_lic
        options.M0 = M;
        M = perform_lic(v, w, options);
    end
    return;
end

histogram = getoptions(options, 'histogram', 'gaussian');
flow_correction = getoptions(options, 'flow_correction', 1);

if isstr(histogram)
    switch histogram
        case 'linear'
            hist = linspace(0,1, 100^2);
        case 'gaussian'
            hist = randn(100); hist = hist(:);
        otherwise
            error('Unkown kind of histograms');
    end
else
    hist = histogram;
end

if isfield(options, 'dt')
    dt = options.dt;
else
    dt = 0.5;
end

% perform integration of the vector field: Forward
T_list = 0:dt:w/2;
H = perform_vf_integration(v, dt, T_list, options );

% perform integration of the vector field: Backward
T_list(1) = [];
H1 = perform_vf_integration(-v, dt, T_list, options );
H = cat(4, H1(:,:,:,end:-1:1), H );
p = size(H,4);

% try to remove sampling problems
if flow_correction
    A = H(:,:,:,(end+1)/2);
    dX = H(:,:,1,:)-repmat(A(:,:,1,:), [1 1 1 p]);
    dY = H(:,:,2,:)-repmat(A(:,:,2,:), [1 1 1 p]);
    dX(dX>n/2) = dX(dX>n/2)-(n-1); dX(dX<-n/2) = dX(dX<-n/2)+(n-1);
    dY(dY>n/2) = dY(dY>n/2)-(n-1); dY(dY<-n/2) = dY(dY<-n/2)+(n-1);
    d = sqrt(dX.^2 + dY.^2);
    d = repmat( mean(mean(d)), [n n 1] ) - d;
    % threshold on the distance map deviation
    eta = 0.5;
end

% compute averaging
M = zeros(n);
[Y,X] = meshgrid(1:n,1:n);
W = zeros(n);
for i=1:p
    A = interp2(1:n,1:n, M0, H(:,:,2,i), H(:,:,1,i) );
    if flow_correction
        w = d(:,:,i)<eta;
    else
        w = ones(n);
    end
    M = M + A.*w;
    W = W+w;
end
W(W==0) = 1;
M = M./W;

if not(isempty(hist))
    M = perform_histogram_equalization(M, hist);
end


function z = h2z(h);

% Z = h2z(H)
%
% Hybrid to Admittance transformation
% only for 2-by-2 matrices
%
% martie 27

if h(2,2) == 0
  disp('correspondent admittance matrix non-existent');
else
z(1,1) = h(1,1) - h(1,2)*h(2,1)/h(2,2);
z(1,2) = h(1,2)/h(2,2);
z(2,1) = -h(2,1)/h(2,2);
z(2,2) = 1/h(2,2);
end;


% Group (split) position data by time
%
% This function divides position data into groups based on value of groupParam parameter.
% You can use it to split position data into halves, or into groups of equal time.
%
%  USAGE
%   [groupIndices, edges] = general.groupByTime(pos, groupParam)
%   pos             Position samples. Matrix of size at least Nx3.
%   groupParam      Parameter that defines how groups are formed. Can be string
%                   or digit. The only possible value for string is 'half', which
%                   means that data will be divided into two groups.
%                   Numerical value defines group interval in seconds.
%   groupIndices    Vector of length equal to number of position samples. Each value
%                   indicates group belongingness. If groupIndices(3) == 1, means that
%                   position sample number 3 belongs to group number 1.
%   edges           Vector of edges that define groups. For example, if data is split
%                   in halves, then edges = [0 <middle_point> Inf].
%
%  EXAMPLE
%
%   pos = data.getPositions();
%   groupIndices = general.groupByTime(pos, 'half'); % divide data into halves
%   positionsOfFirstGroup = pos(groupIndices == 1, :);
%
%   general.groupByTime(pos, 1); % divide data into groups each duration of 1 second
%
function [groupIndices, edges] = groupByTime(pos, groupParam)
    if nargin < 2
        error('BNT:numArgs', 'Incorrect number of parameters (type ''help general.groupByTime'' for details).');
    end

    if size(pos, 2) < 3
        error('BNT:arg', 'Incorrect argument ''pos'' (type ''help general.groupByTime'' for details).');
    end

    duration = pos(end, 1) - pos(1, 1);

    if ischar(groupParam)
        if ~strcmpi(groupParam, 'half')
            error('Incorrect argument ''groupParam'' (type ''help general.groupByTime'' for details).');
        end
        midPoint = pos(1, 1) + round(duration / 2);
        edges = [0 midPoint inf];
    else
        grpInterval = groupParam;
        if ~helpers.isdscalar(grpInterval, '>0')
            error('Incorrect argument ''groupParam'' (type ''help general.groupByTime'' for details).');
        end
        edges = [0:grpInterval:duration];
        edges(end+1) = inf;
    end

    [~, groupIndices] = histc(pos(:, 1), edges);
end


%%*********************************************************************
%% sortA: sort columns of At{p} in ascending order according to the
%%        number of nonzero elements.
%%
%% [At,C,b,X0,Z0,permA,permZ] = sortA(blk,At,C,b,X0,Z0);
%%
%% SDPT3: version 3.1
%% Copyright (c) 1997 by
%% K.C. Toh, M.J. Todd, R.H. Tutuncu
%% Last Modified: 16 Sep 2004
%%*********************************************************************

   function [At,C,X0,Z0,permA,permZ] = sortA(blk,At,C,b,X0,Z0);

   global spdensity smallblkdim
%%
   if isempty(spdensity); spdensity = 0.4; end
   if isempty(smallblkdim); smallblkdim = 50; end
%%
   numblk = size(blk,1);
   m = length(b);
   nnzA = zeros(numblk,m);
   permA = kron(ones(numblk,1),[1:m]);
   permZ = cell(size(blk,1),1);
%%
   for p=1:size(blk,1)
      pblk = blk(p,:);
      n = sum(pblk{2});
      numblk = length(pblk{2});
      if strcmp(pblk{1},'s') & (max(pblk{2}) > smallblkdim)
         n2 = sum(pblk{2}.*pblk{2});  n22 = sum(pblk{2}.*(pblk{2}+1))/2;
         m1 = size(At{p,1},2);
         if (length(pblk{2}) == 1)
            tmp = abs(C{p}) + abs(Z0{p});
            if  (~isempty(At{p,1}))
                tmp = tmp + smat(blk(p,:),abs(At{p,1})*ones(m1,1),1);
            end
            if (nnz(tmp) < spdensity*n22);
               per = symamd(tmp);
               invper = zeros(n,1); invper(per) = [1:n];
               permZ{p} = invper;
               if (~isempty(At{p,1}))
                  isspAt = issparse(At{p,1});
                  for k = 1:m1
                     Ak = smat(pblk,At{p,1}(:,k),1);
                     At{p,1}(:,k) = svec(pblk,Ak(per,per),isspAt);
                  end
               end
               C{p}  = C{p}(per,per);
               Z0{p} = Z0{p}(per,per);
               X0{p} = X0{p}(per,per);
            else
               per = [];
            end
            if (length(pblk) > 2) & (~isempty(per))
               m2 = length(pblk{3});
               P = spconvert([(1:n)', per', ones(n,1)]);
               At{p,2} = P*At{p,2};
            end
         end
         if ~isempty(At{p,1}) & (mexnnz(At{p,1}) < m*n22/2)
            for k = 1:m1
                Ak = At{p,1}(:,k);
                nnzA(p,k) = length(find(abs(Ak) > eps));
            end
            [dummy,permAp] = sort(nnzA(p,1:m1));
            At{p,1}  = At{p,1}(:,permAp);
            permA(p,1:m1) = permAp;
         end
      elseif strcmp(pblk{1},'q') | strcmp(pblk{1},'l') | strcmp(pblk{1},'u');
         if ~issparse(At{p,1});
            At{p,1} = sparse(At{p,1});
         end
      end
   end
%%*********************************************************************


clear;
clc
close all;

%% EXAMPLE 2.3 Calculation of Gravity at various latitudes and heights
lat = deg2rad(45);
lon = 0;
hgt = 10000;

[~, ~, ~, ~, gravity]= ch_earth(lat, lon, hgt);
gravity


function [EB] = MB2EB(MB)
% Convert computery things from megabytes to exabytes.
% Chad A. Greene 2012
EB = MB*2^-40 ;


% Re-rank the top k candidates by searching a transformation when given camera intrinsics
% pred: the prediction 3D pose
% M_pool: the 2D pose library for matching
% GT_pool: the 3D pose library
% k: the number of extracted nearest candidates
% cameraParams: a camera object compatible with Matlab
function j_NN = kNN_cam_align(M_pool,GT_pool,pred,k,cameraParams)
    temp = zeros(1,28);
    temp_root = 0.5 * (pred(9,:) + pred(12,:));
    for a = 1:14
        temp(1,a*2-1) = pred(a,1) - temp_root(1);
        temp(1,a*2) = pred(a,2) - temp_root(2);
        y_c(a) = temp(1,2*a);
    end
    scale = max(y_c)-min(y_c);
    temp = temp / scale;
    m_idx = knnsearch(M_pool,temp,'k',k);
    e = zeros(1,k);
    for ii=1:k
        j_2d = GT_pool(m_idx(ii),:);
        j_2d = reshape(j_2d,3,14);
        j_2d = double(j_2d');

        %scale = (max(j_2d(:,2))-min(j_2d(:,2)))/(max(pred(:,2))-min(pred(:,2)));
        [r,~] = extrinsics(pred(:,1:2),j_2d,cameraParams);

        p2d = j_2d*r*cameraParams.IntrinsicMatrix';
        [~,Z] = procrustes(p2d,pred(:,1:2));
        su = j_2d(:,1:2)-Z(:,1:2);
        Sum = zeros(size(su,1),1);
        for i = 1:size(su,2)
            Sum = Sum+su(:,i).^2;
        end
        e(ii) = mean(sqrt(Sum));

        %e(ii) = MPJPE_procrus(pred(:,1:2),j_2d(:,1:2));
        %e(ii) = MPJPE_procrus([pred(:,1:2)*scale, j_2d(:,3)] ,j_2d);

    end

    [~,iid] = min(e);
    j_2d = GT_pool(m_idx(iid),:);
    j_2d = reshape(j_2d,3,14);
    j_NN = double(j_2d');
end


%compute length of tailinflvector

function [data,units]=compute_tailinflmag(trx,n)

larvae=trx.exp2flies{n};
numlarvae=numel(larvae);
tailinflmag=cell(1,numlarvae);

for i=1:numlarvae
    larva=larvae(i);
    tailinflmag{1,i}=bsxfun(@hypot,trx(larva).xinflection_mm-trx(larva).xtail_mm,trx(larva).yinflection_mm-trx(larva).ytail_mm);
end

units=parseunits('mm');
data=tailinflmag;


function L = obslikepoisson(X,hmm)
%
% Evaluate likelihood of data given observation model, for one continuous trial
%
% INPUT
% X          N by ndim data matrix
% hmm        hmm data structure
%
% OUTPUT
% B          Likelihood of N data points
%
% Author: Cam Higgins, OHBA, University of Oxford

K = hmm.K;
[T,ndim] = size(X);

L = zeros(T,K);

for k=1:K
    constterm = -gammaln(X + 1);
    % note the expectation of log(lambda) is -log(lambda_b) + psigamma(lambda_a)
    num = (X.*(repmat(psi(hmm.state(k).W.W_shape),T,1) - log(hmm.state(k).W.W_rate))) - ...
        repmat(hmm.state(k).W.W_mean,T,1);
    L(:,k) = sum(num + constterm,2);
end
L = exp(L);
end


function [x, infos] = smu_nmf(V, rank, in_options)
% Stochastic multiplicative update for non-negative matrix factorization (SMU-NMF) algorithm.
%
% Inputs:
%       matrix      V
%       rank        rank
%       options     options
% Output:
%       w           solution of w
%       infos       information
%
%
% This file is part of NMFLibrary.
%
% Created by H.Kasai on Mar. 28, 2017
%
% Change log:
%
%       Mar. 15, 2018 (Hiroyuki Kasai): Fixed algorithm.
%
%       May. 20, 2019 (Hiroyuki Kasai): Added initialization module.
%
%       Jul. 12, 2022 (Hiroyuki Kasai): Modified code structures.
%

    % set dimensions and samples
    [m, n] = size(V);

    % set local options
    local_options = [];
    local_options.W_sub_mode    = 'Precon';
    local_options.H_sub_mode    = 'STD';
    local_options.accel         = false;
    local_options.ls            = false;
    local_options.precon        = false;
    local_options.h_repeat      = 1;
    local_options.rep_mode      = 'fix';
    local_options.robust        = false;

    % check input options
    if ~exist('in_options', 'var') || isempty(in_options)
        in_options = struct();
    end
    % merge options
    options = mergeOptions(get_nmf_default_options(), local_options);
    options = mergeOptions(options, in_options);

    % initialize factors
    init_options = options;
    [init_factors, ~] = generate_init_factors(V, rank, init_options);
    Wt = init_factors.W;
    H = init_factors.H;
    R = init_factors.R;

    % determine sub_mode
    if options.accel
        options.H_sub_mode = 'ACC';
    else
        if options.ls
            options.H_sub_mode = 'LS';
        else
            options.H_sub_mode = 'STD';
        end
        options.h_repeat = 1;
    end

    if options.precon
        options.W_sub_mode = 'Precon';
    else
        options.W_sub_mode = 'STD';
    end

    % permute samples
    if options.permute_on
        perm_idx = randperm(n);
    else
        perm_idx = 1:n;
    end
    V = V(:,perm_idx);
    H = H(:,perm_idx);

    % initialize
    method_name = sprintf('SMU-NMF (%s,%s)', options.W_sub_mode, options.H_sub_mode);
    epoch = 0;
    grad_calc_count = 0;

    if options.verbose > 0
        fprintf('# %s: started ...\n', method_name);
    end

    if strcmp(options.rep_mode, 'adaptive')
        rhoh = 1+(m+m*rank)/(1*(rank+1));
        alpha = 2;
        delta = 0.01;
    end

    % store initial info
    clear infos;
    [infos, f_val, optgap] = store_nmf_info(V, Wt, H, R, options, [], epoch, grad_calc_count, 0);

    if options.verbose > 1
        fprintf('SMU-NMF (%s,%s): Epoch = 0000, cost = %.16e, optgap = %.4e\n', options.W_sub_mode, options.H_sub_mode, f_val, optgap);
    end

    % set start time
    start_time = tic();

    % main outer loop
    while true

        % check stop condition
        [stop_flag, reason, max_reached_flag] = check_stop_condition(epoch, infos, options);
        if stop_flag
            display_stop_reason(epoch, infos, options, method_name, reason, max_reached_flag);
            break;
        end

        cnt = 0;

        % main inner loop
        for t = 1 : options.batch_size : n - 1
            cnt = cnt + 1;

            % retrieve vt and ht
            vt = V(:,t:t+options.batch_size-1);
            ht = H(:,t:t+options.batch_size-1);

            % uddate ht
            Wtv = Wt.' * vt;
            WtW = Wt.' * Wt;
            if strcmp(options.H_sub_mode, 'ACC')
                if strcmp(options.rep_mode, 'adaptive')
                    gamma = 1;
                    eps0 = 1;
                    j = 1;
                    rhoh_alpha = rhoh*alpha;
                    %while j <= floor(1+rhoh*alpha) &&  gamma >= delta*eps0
                    while j <= rhoh_alpha && gamma >= delta*eps0
                        ht0 = ht;
                        ht = ht .* (Wtv) ./ (WtW * ht);
                        ht = ht + (ht<eps) .* eps;
                        if j == 1
                            eps0 = norm(ht0-ht);
                        end
                        gamma = norm(ht0-ht);
                        j = j+1;
                    end
                else
                    for ii=1:options.h_repeat
                        ht = ht .* (Wtv) ./ (WtW * ht);
                        ht = ht + (ht<eps) .* eps;
                    end
                end
            elseif strcmp(options.H_sub_mode, 'LS')
                ht = calc_nls_nmf(vt, Wt, 1e-16);
                ht = ht + (ht<eps) * eps;
            else
                ht = ht .* (Wtv) ./ (WtW * ht);
                ht = ht + (ht<eps) .* eps;
            end

            % update W
            delta_minus = vt * ht';
            delta_plus = Wt * (ht * ht');
            if strcmp(options.W_sub_mode, 'Precon')
                invhht = inv(ht * ht');
                invhht = max(invhht,0);
                Wt = Wt .* ((delta_minus * invhht) ./ (delta_plus * invhht));
            else
                Wt = Wt .* (delta_minus ./delta_plus);
            end
            Wt = Wt + (Wt<eps) .* eps;

            % store new h
            H(:,t:t+options.batch_size-1) = ht;

            grad_calc_count = grad_calc_count + m * options.batch_size;
        end

        % measure elapsed time
        elapsed_time = toc(start_time);

        % update epoch
        epoch = epoch + 1;

        % store info
        infos = store_nmf_info(V, Wt, H, R, options, infos, epoch, grad_calc_count, elapsed_time);

        % display info
        display_info(method_name, epoch, infos, options);

    end

    x.W = Wt;
    x.H(:,perm_idx) = H;

end


function predict_label = CNN_SVM_prediction(imdb,OP)
%
% predict_label:
%   if OP.class = 1 then: predict_label = 1:Wake, 2:REM sleep, 3:NREM light sleep, 4:NREM deep sleep
%   if OP.class = 2 then: predict_label = 1:NREM sleep (light + deep), 2:REM sleep, 3: wake
%   if OP.class = 3 then: predict_label = 1:NREM deep sleep, 2:NREM light sleep, 3:Wake + REM sleep
%   if OP.class = 4 then: predict_label = 1:NREM sleep (light + deep), 2: Wake + REM sleep

imdb.meta.features(isinf(imdb.meta.features))=NaN;
sqi=nanmean(imdb.meta.sqi,1);
sqi(find(isnan(sqi)))=nanmean(sqi);

% load model
load(OP.model);

net=stat.net;
net.layers{1,end}.type='softmax';
mean_features=stat.mean_features;
std_features=stat.std_features;

mean_sqi=stat.mean_sqi;
std_sqi=stat.std_sqi;

model=stat.model;

% standardization
for i=8:13
    for j=1:size(imdb.meta.features,1)
        imdb.meta.features(j,i)=log(imdb.meta.features(j,i));
    end
end
imdb.meta.features(find(isinf(imdb.meta.features)))=NaN;

% subtract data_mean
for k=1:size(imdb.images.data,4)
    imdb.images.data(:,:,1,k)=imdb.images.data(:,:,1,k)-stat.data_mean;
end

for i=1:size(imdb.meta.features,2)
    imdb.meta.features(find(isnan(imdb.meta.features(:,i))),i)=mean_features(i);
    imdb.meta.features(:,i)=bsxfun(@minus, imdb.meta.features(:,i),mean_features(i));
    imdb.meta.features(:,i)=bsxfun(@rdivide, imdb.meta.features(:,i),std_features(i));
end
sqi=bsxfun(@minus,sqi,mean_sqi);
sqi=bsxfun(@rdivide,sqi,std_sqi);

% CNN prediction
if size(imdb.images.data,4)>1000
    split=round(size(imdb.images.data,4)/1000);
else
    split=1;
end

retall=[];
for kk=1:split
    each=ceil(size(imdb.images.data,4)/split);
    res=vl_simplenn(net,imdb.images.data(:,:,:,(kk-1)*each+1:min(kk*each,size(imdb.images.data,4))));

    ret=[];
    for i=1:OP.nclass
        for j=1:size(res(end).x,4)
            ret(i,j)=res(end).x(1,1,i,j);
        end
    end
    retall=[retall,ret];
end
% probability of CNN output
ret=retall;

xtest=[];
for i=1:size(ret,1)
    xtest(:,end+1)=ret(i,:);
end
for i=1:13
    if i~=6 % remove DFA feature
        xtest(:,end+1)=imdb.meta.features(:,i);
    end
end
xtest(:,end+1)=sqi;

% SVM prediction
[predict_label, accuracy_test, ytest_out] = svmpredict(ones(size(xtest,1),1), xtest, model,'-b 1');
end


function [GAmp,GTime]=GxTrapezoid(p)

tStart=p.tStart; % start time ms
tEnd=p.tEnd;     % end time ms
tRamp=p.tRamp;   % ramp duration time ms
sRamp=p.sRamp;   % ramp steps
GxAmp=p.GxAmp;   % Gx amplitude
Duplicates=max(1,p.Duplicates);
DupSpacing=max(0,p.DupSpacing);

[GAmp,GTime]=StdTrap(tStart-tRamp, ...
                     tEnd+tRamp,   ...
                     tStart,               ...
                     tEnd,                 ...
                     GxAmp,max(2,sRamp),2,max(2,sRamp));

[GTime,m,n]=unique(GTime);
GAmp=GAmp(m);

% Create Duplicates
if Duplicates~=1 & DupSpacing ~=0
    GAmp=repmat(GAmp,[1 Duplicates]);
    TimeOffset = repmat(0:DupSpacing:(Duplicates-1)*DupSpacing,[length(GTime) 1]);
    GTime=repmat(GTime,[1 Duplicates]) + (TimeOffset(:))';
end

end


function qout = vgg_quat_mul(r,q)
% VGG_QUAT_MUL  Quaternion multiplication
%               pq = vgg_quat_mul(p,q)

% awf@robots.ox.ac.uk, 30/01/05

qout = ...
     [(r(1)*q(1) - r(2)*q(2) - r(3)*q(3) - r(4)*q(4))
      (r(1)*q(2) + r(2)*q(1) + r(3)*q(4) - r(4)*q(3))
      (q(3)*r(1) - q(4)*r(2) + q(1)*r(3) + q(2)*r(4))
      (q(4)*r(1) + q(3)*r(2) - q(2)*r(3) + q(1)*r(4)) ];


function res = bf_sources_grid(BF, S)
% Generate beamforming grid
% Copyright (C) 2012 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak
% $Id: bf_sources_grid.m 7703 2019-11-22 12:06:29Z guillaume $

%--------------------------------------------------------------------------
if nargin == 0
    resolution = cfg_entry;
    resolution.tag = 'resolution';
    resolution.name = 'Grid resolution';
    resolution.strtype = 'n';
    resolution.num = [1 1];
    resolution.val = {5};
    resolution.help = {'Select the resolution of the grid (in mm)'};

    space = cfg_menu;
    space.tag = 'space';
    space.name = 'Coordinate system';
    space.help = {'Select the coordinate system in which the grid should be generated'};
    space.labels = {'MNI template', 'MNI-aligned', 'Head', 'Native'};
    space.values = {'MNI template', 'MNI-aligned', 'Head', 'Native'};
    space.val = {'MNI template'};

    constrain = cfg_menu;
    constrain.tag = 'constrain';
    constrain.name = 'Coordinate sources to';
    constrain.help = {'The boundary to which the grid is confined'};
    constrain.labels = {'Inner skull', 'Scalp'};
    constrain.values = {'iskull', 'scalp'};
    constrain.val = {'iskull'};

    grid = cfg_branch;
    grid.tag = 'grid';
    grid.name = 'Grid';
    grid.val = {resolution, space, constrain};

    res = grid;

    return
elseif nargin < 2
    error('Two input arguments are required');
end

if ~isfield(S, 'constrain')
    S.constrain = 'iskull';
end

switch S.constrain
    case 'iskull'
        constraint = export(gifti(BF.data.mesh.tess_iskull), 'ft');
    case 'scalp'
        constraint = export(gifti(BF.data.mesh.tess_scalp), 'ft');
end

M1 = BF.data.transforms.toNative;

switch S.space
    case 'MNI template'
        M1 = BF.data.transforms.toMNI/M1;
        M2 = inv(BF.data.transforms.toMNI);
    case 'MNI-aligned'
        M1 = BF.data.transforms.toMNI_aligned/M1;
        M2 = inv(BF.data.transforms.toMNI_aligned);
    case 'Head'
        M1 = BF.data.transforms.toHead/M1;
        M2 = inv(BF.data.transforms.toHead);
    case 'Native'
        M2 = inv(M1);
        M1 = eye(4);
end

constraint = ft_convert_units(ft_transform_geometry(M1, constraint));

mn = min(constraint.pnt);
mx = max(constraint.pnt);

resolution = S.resolution;

if isequal(constraint.unit, 'm')
    resolution = 1e-3*resolution;
end

% If zero is inside the brain, make sure grid points fall on multiples of
% resolution to ease simulating data from points on the grid
if mn(1)<0 && mx(1)>0
    grid.xgrid = [fliplr(0:-resolution:mn(1)) resolution:resolution:mx(1)];
else
    grid.xgrid = mn(1):resolution:mx(1);
end

if mn(2)<0 && mx(2)>0
    grid.ygrid = [fliplr(0:-resolution:mn(2)) resolution:resolution:mx(2)];
else
    grid.ygrid = mn(2):resolution:mx(2);
end

if mn(3)<0 && mx(3)>0
    grid.zgrid = [fliplr(0:-resolution:mn(3)) resolution:resolution:mx(3)];
else
    grid.zgrid = mn(3):resolution:mx(3);
end

grid.dim   = [length(grid.xgrid) length(grid.ygrid) length(grid.zgrid)];
[X, Y, Z]  = ndgrid(grid.xgrid, grid.ygrid, grid.zgrid);

pos   = [X(:) Y(:) Z(:)];

inside = ft_inside_headmodel(pos, struct('bnd', constraint));

pos    = spm_eeg_inv_transform_points(M2, pos);

grid.allpos  = pos;
grid.inside  = find(inside);
grid.outside = find(~inside);

grid.pos     = pos(inside, :);

res = grid;


function varargout = plot_spline(P,C)
  % PLOT_SPLINE Plot a cubic Bezier spline.
  %
  % [pe,p] = plot_spline(P,C)
  %
  % Inputs:
  %   P  #P by dim list of control point locations
  %   C  #C by 4 list of indices into P of cubic Bezier curves
  % Outputs:
  %   pe  plot handles for UI
  %   p  plot handle for curves
  % Example:
  %   cellfun(@(pe) arrayfun(@(p) set(p,'Color','r'),pe),plot_spline(P,C))
  p = {};
  pe = {};
  ish = ishold;
  for c = 1:size(C,1)
    [pe{c},p{c}] = plot_cubic(P(C(c,:),:));
    hold on;
  end
  hold off;
  if ish
    hold on
  end
  if nargout>=1
    varargout{1} = pe;
    if nargout >= 2
      varargout{2} = p;
    end
  end
end


function inc = crswap ( a, c, c_size, m, k, n, critvl, i1, i2, c1, c2, ...
  iswitch )

%*****************************************************************************80
%
%% CRSWAP determines the effect of swapping two objects.
%
%  Discussion:
%
%    This computation is very inefficient.  It is only set up so that we
%    can compare algorithm ASA 113 to the K-means algorithms ASA 058 and
%    ASA 136.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Colin Banfield, LC Bassill,
%    Algorithm AS 113:
%    A transfer for non-hierarchichal classification,
%    Applied Statistics,
%    Volume 26, Number 2, 1977, pages 206-210.
%
%  Parameters:
%
%    Input, real  A(M,N), the data values.  There are M objects,
%    each having spatial dimension N.
%
%    Input, integer C(M), the classification of each object.
%
%    Input, integer  C_SIZE(K), the number of objects in each class.
%
%    Input, integer M, the number of objects.
%
%    Input, integer K, the number of classes.
%
%    Input, integer N, the number of spatial dimensions, or variates,
%    of the objects.
%
%    Input, real CRITVL, the current value of the criterion.
%
%    Input, integer I1, I2, the objects to be swapped.
%
%    Input, integer C1, C2, the current classes of objects I1 and I2.
%
%    Input, integer ISWITCH:
%    1, indicates that I1 and I2 should be temporarily swapped, the
%       change in CRITVL should be computed, and then I1 and I2 restored.
%    2, indicates that I1 and I2 will be swapped.
%
%    Output, real INC, the change to CRITVL that would occur if I1 and
%    I2 were swapped.  This is only computed for ISWITCH = 1.
%
  if ( iswitch == 2 )
    inc = 0;
    return
  end
%
%  Move object I1 from class C1 to class C2.
%  Move object I2 from class C2 to class C1.
%
  c(i1) = c2;
  c(i2) = c1;
%
%  Define the critical value as the sum of the squares of the distances
%  of the points to their cluster center.
%
  for i = 1 : k
    c_size(i) = 0;
    for j = 1 : n
      c_center(i,j) = 0.0;
    end
  end

  for i = 1 : m
    ci = c(i);
    c_size(ci) = c_size(ci) + 1;
    for j = 1 : n
      c_center(ci,j) = c_center(ci,j) + a(i,j);
    end
  end

  for i = 1 : k
    for j = 1 : n
      c_center(i,j) = c_center(i,j) / c_size(i);
    end
  end

  for i = 1 : k
    wss(i) = 0.0;
  end

  for i = 1 : m
    ci = c(i);
    for j = 1 : n
      wss(ci) = wss(ci) + ( a(i,j) - c_center(ci,j) )^2;
    end
  end

  critvl_new = 0.0;
  for i = 1 : k
    critvl_new = critvl_new + wss(i);
  end

  inc = critvl_new - critvl;
%
%  Move object I1 from class C2 to class C1.
%  Move object I2 from class C1 to class C2.
%
  c(i1) = c1;
  c(i2) = c2;

  return
end


% demo_example_lmgp_data - demonstration script file for LMGP model identification.
%
%% Description
% Demo to present how to obtain and compose data for the identification
% of GP model with incorporated local models (LMGP model).
%
% There are two options how to obtain local model data:
% a. analytically (set fIdentifyLm to 0)
% b. with identification (set fIdentifyLm to 1)
%
% It can be used only with the Gaussian covariance function and
% with the white noise model (sum of covSEard and covNoise).
%
% See Also
% example.m, demo_example_LMGP_training.m, demo_example_LMGP_simulation.m,
% example_LM_ident.m, example_derivative.m
%
%%
% Written by K. Azman, 2007
%
% Changelog:
%
% 16.2.2015, Martin Stepancic:
%		 	-included the gathering of both equilibrium and non-equilibrium
%			 points in the same matlab script;
%			-changed .mat filenames and their structure contents to:
%			 {train|valid}_data.{x|u|y}
%
clear;
global flag_LM_data_ident
% LM generation data
flag_LM_data_ident = 0; % 0=calculated, 1=identified using IV

me = mfilename;                                            % what is my filename
mydir = which(me); mydir = mydir(1:end-2-numel(me));        % where am I located
addpath([mydir 'system']);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%                 Points at Equilibrium                              %%%%

% local model ident
ord = 1;    % order of identified LMs
eq.U = [-1.5 -1.1 -0.7 -0.3 0 0.3 0.7 1.1 1.5]';
dU = 0.1;  % depending on diference between the elements of eq.U, valid only if LMs identified!

noiseStd = 0.1;
% lm calculated/identified
if (flag_LM_data_ident)
    % *** local model's parameters identified and not calculated ***

    for ii = 1:length(eq.U)
        [lm{ii},y0] = demo_example_LM_ident(eq.U(ii), dU, noiseStd, 2000+ii);

        eq.Y(ii,1) = y0;
        eq.dfdy(ii,1) = -lm{ii}.a(2);
        eq.dfdu(ii,1) = -lm{ii}.b(2);
    end
    eq.lm = lm;

    filename = 'example_data_lmgp_eq_ident';

else
    % *** local model's parameters calculated ***
    [eq.dfdy, eq.dfdu, eq.Y] = demo_example_derivative(eq.U);

    filename = 'example_data_lmgp_eq_anal';

end

figure('Name', 'EQ Curve');
plot(eq.U,eq.Y);

save(filename,'eq');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%                 Non-eqilibrium points                              %%%%
umax = 1.5;
umin = -umax;
N_training_points = 200;
N_validation_points = 200;
noise_std = 0.05;

utrain = sig_prs_minmax(N_training_points,2,umin,umax); % create input singal

% simulate example system, to obtain delayed outputs and delayed outputs
[ytrain, xtrain, utrain] = demo_example(utrain);
% add noise to training data
[ytrain, ytrain_no_noise] = add_noise_to_vector(ytrain, noise_std);
figure('Name', 'Training Input Signal');
t=1:length(utrain);
plot(t, utrain, t, xtrain);
legend('u', 'y');
grid on;

% validation data --> less excited signal
uvalid = sig_prs_minmax(N_validation_points,5,umin,umax);
[yvalid, xvalid, uvalid] = demo_example(uvalid);

figure('Name', 'Validation Input Signal');
plot(uvalid);

% training data
train_data.u = utrain;
train_data.x = xtrain;
train_data.y = ytrain;

% validation data
valid_data.u = uvalid;
valid_data.x = xvalid;
valid_data.y = yvalid;

save example_data_lmgp_oeq valid_data train_data umax umin noise_std
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

save(filename,'eq')
rmpath([mydir 'system'])
return


function [labelErrors, labelSharingErrors, wrongIndices] = findLabelErrors(realLabels, predLabels)

% FINDLABELERRORS Find the number of errors in the predicted vs the real
% labels
% COPYRIGHT: Andreas C. Damianou, 2012
% VARGPLVM

%%% WARNING: This function only works if there are no multi-label examples!

% First, transform any encoding to binary
% (e.g. if it is 1 -1 -1 -> 1 0 0)
lb = min(min(realLabels));
ub = max(max(realLabels));
realLabels(realLabels == lb) = 0;
realLabels(realLabels == ub) = 1;

predLabels(predLabels >= 0.5) = 1;
predLabels(predLabels < 0.5) = 0;

% %--- Old code
%     realUb = find(realLabels == ub);
%     predUb = predLabels(realUb);
%     % The number of times that a true label wasn't found
%     labelErrors = length(realUb) - sum(predUb); %equivalent to: length(find(~predUb))
%
 % The number of times more than one label was found

 labelSharingErrors = sum((sum(predLabels,2)>1));

 %--
 realLabels2 = transformLabels(realLabels);
 predLabels2 = transformLabels(predLabels);
 uniqueLabels = unique(realLabels2);
 labelErrors = 0;
 for j=1:length(uniqueLabels)
     trueClassInd = find(realLabels2 == uniqueLabels(j));
     wrongIndices{j} = find(~(predLabels2(trueClassInd) == uniqueLabels(j)));
     labelErrors = labelErrors + length(wrongIndices{j});
 end


function min_f = minf(datafe,dataor)
T=length(dataor);
sum=0;
for i=1:T
   sum=sum+ abs((datafe(i)-dataor(i))*100/dataor(i));
end

min_f=sum;


function dat = probability_maps_to_region_index(dat)
% Use dat.probability_maps to rebuild integer vector of index labels (dat.dat)
%
% dat = probability_maps_to_region_index(dat)
%

% Start: dat has one image per region, with probability values
% convert to integer vector

[maxval, condf] = max(double(full(dat.probability_maps)),[], 2);   % double is safer

allempty = all(dat.probability_maps == 0, 2) | isnan(maxval);  % some out-of-mask values may get NaNs

condf(allempty) = 0;

dat.dat = int32(condf);

end