function [model] = bp_resume(model)
% Resume discriminative finetuning of CDBN.

rng('shuffle');
kernels;
debug = 0;

data_list = read_data_list(model.data_path, model.classnames, ....
    model.volume_size + 2 * model.pad_size, 'train', debug);

param = [];
param.epochs = 100;
param.lr = 0.01;
param.weight_decay = 5*10^-4;
param.momentum = 0.9;
param.batch_size = 32;
param.snapshot_iter = 10;
param.snapshot_name = 'bp_finetune_iter';
param.test_iter = 5;
batch_size = param.batch_size;

fprintf('Resume discriminative funetuning the CDBN\n');
fprintf('lr = %f, wd = %d, momentum = %f\n', param.lr, param.weight_decay, param.momentum);

% prepare data and label
[new_list, label] = balance_data(data_list, batch_size);
n = length(new_list);
batch_num = n / batch_size;
assert(batch_num == floor(batch_num));

% prepare model
numLayer = model.numLayer;
for iter = 1 : param.epochs
    loss_all = 0;
    shuffle_index = randperm(n);
    for b = 1 : batch_num
        batch_index = shuffle_index((b-1)*batch_size + 1 : b * batch_size);
        batch = read_batch(model, new_list(batch_index), false);
        batch_label = label(batch_index,:);
        [model, activation] = bp_forward(model, batch);
        [model, loss] = bp_backward(model, activation, batch_label, param.weight_decay);
        loss_all = loss_all + loss;
        model = bp_update(model, param);
    end
    loss_all = loss_all / batch_num;
    fprintf('iteration: %d, loss: %f\n', iter, loss_all);

    if mod(iter, param.snapshot_iter) == 0
        fprintf('snapshoting to %s_%d\n', param.snapshot_name, iter);
        snapshot_name = sprintf('%s_%d', param.snapshot_name, iter);
        save(snapshot_name, 'model');
    end

    if mod(iter, param.test_iter) == 0
        test_loss = bp_test(model);
        fprintf('test loss: %f\n', test_loss);
    end
end

for l = 2 : numLayer
    model.layers{l} = rmfield(model.layers{l},'grdw');
    model.layers{l} = rmfield(model.layers{l},'grdc');
    model.layers{l} = rmfield(model.layers{l},'histw');
    model.layers{l} = rmfield(model.layers{l},'histc');
end

save('bp_finetuned_model', 'model');


%MIT IAP Radar Course 2011
%Resource: Build a Small Radar System Capable of Sensing Range, Doppler,
%and Synthetic Aperture Radar Imaging
%
%Gregory L. Charvat

%Process Range vs. Time Intensity (RTI) plot

%NOTE: set up-ramp sweep from 2-3.2V to stay within ISM band
%change fstart and fstop bellow when in ISM band

clear all;
close all;

%read the raw data .wave file here
[Y,FS,NBITS] = wavread('running_outside_20ms.wav');

%constants
c = 3E8; %(m/s) speed of light

%radar parameters
Tp = 20E-3; %(s) pulse time
N = Tp*FS; %# of samples per pulse
fstart = 2260E6; %(Hz) LFM start frequency for example
fstop = 2590E6; %(Hz) LFM stop frequency for example
%fstart = 2402E6; %(Hz) LFM start frequency for ISM band
%fstop = 2495E6; %(Hz) LFM stop frequency for ISM band
BW = fstop-fstart; %(Hz) transmti bandwidth
f = linspace(fstart, fstop, N/2); %instantaneous transmit frequency

%range resolution
rr = c/(2*BW);
max_range = rr*N/2;

%the input appears to be inverted
trig = -1*Y(:,1);
s = -1*Y(:,2);
clear Y;

%parse the data here by triggering off rising edge of sync pulse
count = 0;
thresh = 0;
start = (trig > thresh);
for ii = 100:(size(start,1)-N)
    if start(ii) == 1 & mean(start(ii-11:ii-1)) == 0
        %start2(ii) = 1;
        count = count + 1;
        sif(count,:) = s(ii:ii+N-1);
        time(count) = ii*1/FS;
    end
end
%check to see if triggering works
% plot(trig,'.b');
% hold on;si
% plot(start2,'.r');
% hold off;
% grid on;

%subtract the average
ave = mean(sif,1);
for ii = 1:size(sif,1);
    sif(ii,:) = sif(ii,:) - ave;
end

zpad = 8*N/2;

%RTI plot
figure(10);
v = dbv(ifft(sif,zpad,2));
S = v(:,1:size(v,2)/2);
m = max(max(v));
imagesc(linspace(0,max_range,zpad),time,S-m,[-80, 0]);
colorbar;
ylabel('time (s)');
xlabel('range (m)');
title('RTI without clutter rejection');

%2 pulse cancelor RTI plot
figure(20);
sif2 = sif(2:size(sif,1),:)-sif(1:size(sif,1)-1,:);
v = ifft(sif2,zpad,2);
S=v;
R = linspace(0,max_range,zpad);
for ii = 1:size(S,1)
    %S(ii,:) = S(ii,:).*R.^(3/2); %Optional: magnitude scale to range
end
S = dbv(S(:,1:size(v,2)/2));
m = max(max(S));
imagesc(R,time,S-m,[-80, 0]);
colorbar;
ylabel('time (s)');
xlabel('range (m)');
title('RTI with 2-pulse cancelor clutter rejection');

% %2 pulse mag only cancelor
% figure(30);
% clear v;
% for ii = 1:size(sif,1)-1
%     v1 = abs(ifft(sif(ii,:),zpad));
%     v2 = abs(ifft(sif(ii+1,:),zpad));
%     v(ii,:) = v2-v1;
% end
% S=v;
% R = linspace(0,max_range,zpad);
% for ii = 1:size(S,1)
%     S(ii,:) = S(ii,:).*R.^(3/2); %Optional: magnitude scale to range
% end
% S = dbv(S(:,1:size(v,2)/2));
% m = max(max(S));
% imagesc(R,time,S-m,[-20, 0]);
% colorbar;
% ylabel('time (s)');
% xlabel('range (m)');
% title('RTI with 2-pulse mag only cancelor clutter rejection');


function [nS, iNonMatch] = merge_spikes0(uBase, nS, uS, crit)

if ~isempty(uBase)
    cdot = uBase * uS';

    baseNorms = sum(uBase.^2, 2)';
    newNorms  = sum(uS.^2, 2)';

    cNorms = 1e-10 + repmat(baseNorms', 1, numel(newNorms)) + repmat(newNorms, numel(baseNorms), 1);

    cdot = 1 - 2*cdot./cNorms;

    [cdotmin, imin] = min(cdot, [], 1);

    iMatch = cdotmin<crit;

    nSnew = hist(imin(iMatch), 1:1:size(uBase,1));
    nS = nS + nSnew';

    iNonMatch = find(cdotmin>crit);
else
   iNonMatch = 1:size(uS,2);
   nS = [];
end


function [varargout] = applyTransM(varargin)
%"applyTransM"
%   Apply transformation matrix transM to points defined in xyz by xV, yV,
%   zV.  In order to run as fast as possible, first computes the rotation
%   component and then adds the translation portion of transM last.
%
%JRA 1/18/04
%
%Usage:
%   function [xT, yT, zT] = applyTransM(transM, xV, yV, zV);
%   function [pointsT]    = applyTransM(transM, pointsM);
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

%Parse input arguments.
if nargin == 2
    usingPointMatrix = 1;
    transM  = varargin{1};
    pointsM = varargin{2}';
elseif nargin == 4
    usingPointMatrix = 0;
    transM  = varargin{1};
    xV      = varargin{2};
    yV      = varargin{3};
    zV      = varargin{4};

    if length(xV) ~= length(yV) | length(xV) ~= length(zV)
        error('xV, yV, and zV must be vectors of the same length.');
    end

    pointsM = [reshape(xV,[],1), reshape(yV,[],1) reshape(zV,[],1)]';

else
    error('Invalid number of input arguments to applyTransM.');
end

%If blank transformation matrix, return originals.
if isempty(transM)
    if usingPointMatrix
        varargout{1} = pointsM;
    else
        varargout{1} = xV;
        varargout{2} = yV;
        varargout{3} = zV;
    end
    return;
end

nPts = size(pointsM, 2);
%If no points passed in, return empty.
if nPts == 0
    if usingPointMatrix
        varargout{1} = [];
    else
        varargout{1} = [];
        varargout{2} = [];
        varargout{3} = [];
    end
    return;
end

%Split the rotation and translation portions of transM.  This is done for
%speed, to avoid allocating a 4th column of ones to pointsM.

%Rotation.
pointsM = transM(1:3,1:3) * pointsM;

%Translation.
pointsM(1,:) = pointsM(1,:) + transM(1,4);
pointsM(2,:) = pointsM(2,:) + transM(2,4);
pointsM(3,:) = pointsM(3,:) + transM(3,4);

if usingPointMatrix
    varargout{1} = pointsM';
else
    varargout{1} = pointsM(1,:);
    varargout{2} = pointsM(2,:);
    varargout{3} = pointsM(3,:);
end


%   ****** See nozzle.m for instructions ******
%   solver.m

%   Solver for the macormack method
function [Q] = solver(Q)
global gamma R

[u,v,rho,p,e,T,ss,F,G] = flowvars(Q);

%   Take one MacCormack step
[Q] = mac(Q);

end

%%%%%%%%    flowvars    %%%%%%%%
function [u,v,rho,p,e,T,ss,F,G] = flowvars(Q)
global gamma R

%	Calculate the actual flow variables at each time step
rho = Q(:,:,1);
u = Q(:,:,2)./rho;
v = Q(:,:,3)./rho;
e = Q(:,:,4);
p = (gamma-1)*(e-(1/2)*rho.*(u.*u+v.*v));
T = p./(R*rho);
ss = sqrt(abs(gamma*R*T));

F(:,:,1) = rho.*u;
F(:,:,2) = rho.*u.*u + p;
F(:,:,3) = rho.*u.*v;
F(:,:,4) = (e+p).*u;

G(:,:,1) = rho.*v;
G(:,:,2) = rho.*u.*v;
G(:,:,3) = rho.*v.*v + p;
G(:,:,4) = (e+p).*v;

end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%    mac    %%%%%%%%

function [Q] = mac(Q)
global gamma R

Q0 = Q;

%	Forward flux
[Qflux,dt] = flux_mc(Q,-1);
Qbar = Q - dt*Qflux;
Q = Qbar;

[Q] = boundary(Q);

%	Backward flux
[Qflux,dt] = flux_mc(Q,0);
Q = (1/2)*(Q0 + Qbar - dt*Qflux );

[Q] = boundary(Q);

end

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

%%%%%%%%    flux_mc    %%%%%%%%

function [Qflux,dt] = flux_mc(Q,dd)
global x y Vol cfl

[u,v,rho,p,e,T,ss,F,G] = flowvars(Q);
nx = size(x,1);
ny = size(x,2);

a(1:nx+1,1:ny+1) = 0;
b(1:nx+1,1:ny+1) = 0;
c(1:nx+1,1:ny+1) = 0;
Qflux(1:nx+1,1:ny+1,1:4) = 0;

%	Get the fluxes
for i = 2: size(x,1)
    for j = 2: size(x,2)

	ii = i-1;
    jj = j-1;

    %	Right face
	sfpx = y(ii+1,jj+1)-y(ii+1,jj);
    sfpy = -( x(ii+1,jj+1)-x(ii+1,jj) );

	%	Left face
    sfmx = -( y(ii,jj+1) - y(ii,jj) );
    sfmy = ( x(ii,jj+1)-x(ii,jj) );

    %	Top face
    sgpx = -( y(ii+1,jj+1) - y(ii,jj+1) );
    sgpy = x(ii+1,jj+1) - x(ii,jj+1);

    %	Bottom face
    sgmx = ( y(ii+1,jj)-y(ii,jj) );
    sgmy = -( x(ii+1,jj) - x(ii,jj) );

	%	Get the flux
	Qflux(i,j,:) = ( F(i+1+dd,j,:)*sfpx + G(i+1+dd,j,:)*sfpy + ...
   		F(i+dd,j,:)*sfmx + G(i+dd,j,:)*sfmy + F(i,j+1+dd,:)*sgpx ...
        + G(i,j+1+dd,:)*sgpy + F(i,j+dd,:)*sgmx + G(i,j+dd,:)*sgmy );

	%	Normalize by Volume
    Qflux(i,j,:) = Qflux(i,j,:)./Vol(i,j);

	%	CFL terms
    a(i,j) = abs(u(i,j)*sfpx + v(i,j)*sfpy);
    b(i,j) = abs(u(i,j)*sgpx + v(i,j)*sgpy);
    c(i,j) = ss(i,j)*sqrt(abs( sfpx^2 + sfpy^2) ...
        + abs( sgpx^2 + sgpy^2) );

    end
end

dt = max(max((a+b+c)./Vol));
dt = cfl/dt;

end

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

%%%%%%%%    boundary    %%%%%%%%

function [Q] = boundary(Q)
global x y gamma R P_amb T_c
[u,v,rho,p,e,T,ss,F,G] = flowvars(Q);

%   Problem boundary conditions here
nx = size(x,1);
ny = size(x,2);

%	Top Wall
p(:,ny+1) = p(:,ny);
v(:,ny+1) = 0;
u(:,ny+1) = 0;
rho(:,ny+1) = rho(:,ny);

%   Symmetry line
p(:,1) = p(:,2);
v(:,1) = -v(:,2);
u(:,1) = u(:,2);
rho(:,1) = rho(:,2);

%	Inflow-shouldn't change from initialization
u(1,:) = sqrt(gamma*R*T_c);
v(1,:) = v(2,:);

%	Out flow - set to upstream cells
u(nx+1,:) = u(nx,:);
v(nx+1,:) = v(nx,:);
p(nx+1,:) = p(nx,:);  %P_amb;
rho(nx+1,:) = rho(nx,:);

%	EOS
e = p/(gamma-1) + (1/2)*rho.*(u.*u + v.*v);

Q(:,:,1) = rho;
Q(:,:,2) = rho.*u;
Q(:,:,3) = rho.*v;
Q(:,:,4) = e;

end

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


%% housekeeping
close all
clear
clc
%% load the data

load tut01_data

%% set up VAR model

warning('This system is nonstationary because of LGDP !!!')

endog={'rtwi','LGDP','Aldp','r','LRER'};

nlags=4;

const=true;

exog={'du93Q1','du95Q4','du92Q3'};

v=rfvar(endog,exog,nlags,const); % formerly redfvar

%%
clc
ve=estimate(v,db,{db.LGDP.start,db.LGDP.finish});

%% should the Feds fund rate react to domestic variables?
linres={};

for ilag=1:nlags

    for iv=2:numel(endog)

        y=endog{iv};

        linres=[linres;{sprintf('b%0.0f(1,%s)=0',ilag,y)}];

    end

end

%%

ve_lr=estimate(v,db,{db.LGDP.start,db.LGDP.finish},[],linres);

%% save estimated models for later use

models=struct('ve',ve,'ve_lr',ve_lr);

save('tut02_estimation','models')


%%
%   Author: Yash Bansod
%
% GitHub: <https://github.com/YashBansod>
%
% This is the main program.

%% Clear the environment and the command line
clear;
clc;
close all;

%% Add the directory containing relevant functions to the path variables
addpath('./INV-functions/')

%% Define the input parameters and simulate

% Set the length of the links of the manipulator robot.
L1 = 5;
L2 = 5;
L3 = 5;

% Set the initial orientation of the robot.
theta1 = 10;
theta2 = 0;
theta3 = 15;

% Define the radius of the circle the end effector should follow
radius = 10;
r_sq = radius ^ 2;

hold on;
% Code for drawing a circle
for i = -radius: radius/10: radius
    expX = i;
    expY = sqrt(r_sq - expX^2);
    cla;
    images.roi.Circle(gca,'Center',[0 0],'Radius',radius, 'Facealpha', 0.05);
    % You can modify the Kp value defined in PLANAR_INV_KIN_3DOF to modify
    % the inverse jacobian controller behavior.
    [expPoint, Joint, Theta] = PLANAR_INV_KIN_3DOF(L1, L2, L3, expX, ...
                                            expY, theta1, theta2, theta3);
    scatter(Joint(end,1), Joint(end,2));
    theta1 = Theta(1, 1);
    theta2 = Theta(2, 1);
    theta3 = Theta(3, 1);
end

for i = radius: -radius/10: -radius
    expX = i;
    expY = -sqrt(r_sq - expX^2);
    cla;
    images.roi.Circle(gca,'Center',[0 0],'Radius',radius, 'Facealpha', 0.05);
    % You can modify the Kp value defined in PLANAR_INV_KIN_3DOF to modify
    % the inverse jacobian controller behavior.
    [expPoint, Joint, Theta] = PLANAR_INV_KIN_3DOF(L1, L2, L3, expX, ...
                                            expY, theta1, theta2, theta3);
    theta1 = Theta(1, 1);
    theta2 = Theta(2, 1);
    theta3 = Theta(3, 1);
end


function varargout = xexpintinv(varargin)
%XEXPINTINV EXPINT(1/Z)/Z

switch class(varargin{1})

    case 'double'
        z = varargin{1};
        varargout{1} = (1./z).*expint(1./z);

    case 'sdpvar'
        varargout{1} = InstantiateElementWise(mfilename,varargin{:});

    case 'char'

        varargout{1} = [];
        varargout{2} = createOperator;
        varargout{3} = varargin{3};

    otherwise
        error('SDPVAR/EXPINT called with CHAR argument?');
end

function operator = createOperator

operator = struct('convexity','none','monotonicity','none','definiteness','positive','model','callback');
operator.derivative = @derivative;
operator.range = [0 1];
operator.domain = [1e-8 inf];

function d = derivative(z);
d = (-1./z.^2).*expint(1./z)+(1./z).*(-z.*exp(-1./z)).*(-1./z.^2);


function ir = shorten_ir(ir,nsamples)
%SHORTEN_IR shortens an impulse response
%
%   Usage: ir = shorten_ir(ir,nsamples)
%
%   Input parameters:
%       ir          - impulse response with length x channels
%       nsamples    - length of the target impulse response
%
%   Output paramteres:
%       ir          - impulse response signal with nsamples x n
%
%   SHORTEN_IR(ir,nsamples) shortens a given impulse response to the given
%   number of samples nsamples and applying a 5% long hanning window.
%
%   See also: get_ir, reduce_ir

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

%% ===== Checking of input  parameters ==================================
nargmin = 2;
nargmax = 2;
narginchk(nargmin,nargmax);
isargpositivescalar(nsamples);

%% ===== Computation ====================================================
% Window impulse response
win = hann_window(0,ceil(0.05*nsamples),nsamples);
ir = ir(1:nsamples,:) .* repmat(win,[1 size(ir,2)]);


% DEMTOYUNSUPERVISED A script to run unsupervised deep GP on toy hierarchical data.
%
% DESC A script to run unsupervised deep GP on toy hierarchical data. The script provides
% the option of parametrising the model and initialisation in many many
% different ways... but the core of the demo (define a deep GP and train
% it) is actually not that big, if you decide to use the default options.
%
% COPYRIGHT: Andreas C. Damianou, 2013
%
% SEE ALSO: demToyRegression.m
%
% DEEPGP

experimentNo = 1;
toyType = 'hgplvmSampleTr1';
baseKern='rbfardjit'; % The mapping kernel between the layers
Q = {6,4}; % Dimensionality of the latent space in each layer
initSNR = {100, 50}; % Initial Signal to Noise ration per layer
% How to initialise X when multiple output modalities are present. See
% hsvargplvm_init for details
initial_X = 'separately';
% How to initialise X (more specifically, means of q(X)) for each layer.
% The selected method (potentially
% different per layer) will be applied in a sequential fashion, eg if we
% use PCA we obtain X_1 from PCA on Y, then X_2 from PCA on X_1 etc. Deep
% GPs are completely different than a stacked method, since X's will be
% integrated out (the initial X's above are actually the initial means of the var.
% distribution) and everythin will be optimised jointly.
% Here we opt for a Bayesian GPLVM that  gives the initial X.
% See hsvargplvm_init for other options (eg pca).
initX = 'vargplvm';
%- options for the BayesianGPLVM used to initialise the variational means
stackedInitIters = 200;
stackedInitVardistIters = 100;
stackedInitSNR = 100;
initVardistIters = 100;
demToyHsvargplvm1; % Run the actual demo

%% --- Plot true data
subplot(3,2,1)
myPlot(Z{3},'X2',[],[],{3,8},0)
subplot(3,2,3)
myPlot(Z{1},'XA',[],[],{3,8},0)
subplot(3,2,4)
myPlot(Z{2},'XB',[],[],{3,8},0)
subplot(3,2,5)
plot(Ytr{1},'x-'); title('YA');
subplot(3,2,6)
plot(Ytr{2},'x-'); title('YB');

%% -- Plot spaces discovered by deep GPs (two most dominant dimensions for
%% top layer and similarly for each of the two modalities of layer 1)
figure
hsvargplvmShowScales(model);

s2 = sort(vargplvmRetainedScales(model.layer{2}.comp{1}));
sA =  sort(vargplvmRetainedScales(model.layer{1}.comp{1}));
sB =  sort(vargplvmRetainedScales(model.layer{1}.comp{2}));

figure
subplot(2,2,1)
myPlot(model.layer{2}.vardist.means(:,s2(1:2)),'deepGP_X2',[],[],{3,8},0)
subplot(2,2,3)
myPlot(model.layer{1}.vardist.means(:,sA(1:2)),'deepGP_XA',[],[],{3,8},0)
subplot(2,2,4)
myPlot(model.layer{1}.vardist.means(:,sB(1:2)),'deepGP_XB',[],[],{3,8},0)

%% --- Compare with stacked Bayesian GP-LVM % TODO
%[XA, s, WA, modelA] = vargplvmEmbed(Ytr{1}, 5, initXOptions{1}{:});
%[XB, s, WB, modelB] = vargplvmEmbed(Ytr{2}, 5, initXOptions{1}{:});
%[X2, s, W2, model2]  = vargplvmEmbed([XA XB], 5, initXOptions{2}{:});

%% --- Compare with stacked PCA and isomap

figure
pcaXA = ppcaEmbed(Ytr{1}, 2);
pcaXB = ppcaEmbed(Ytr{2},2);
pcaX2 = ppcaEmbed([pcaXA pcaXB],2);
subplot(2,2,1)
myPlot(pcaX2,'pcaX2',[],[],{3,8},0)
subplot(2,2,3)
myPlot(pcaXA,'pcaXA',[],[],{3,8},0)
subplot(2,2,4)
myPlot(pcaXB,'pcaXB',[],[],{3,8},0)

figure
isomapXA = isomap2Embed(Ytr{1}, 2);
isomapXB = isomap2Embed(Ytr{2},2);
isomapX2 = isomap2Embed([isomapXA isomapXB],2);
subplot(2,2,1)
myPlot(isomapX2,'isomapX2',[],[],{3,8},0)
subplot(2,2,3)
myPlot(isomapXA,'isomapXA',[],[],{3,8},0)
subplot(2,2,4)
myPlot(isomapXB,'isomapXB',[],[],{3,8},0)


function P=rayleighpdf(M,S)

P= (((M./(S.^2)).*exp((-1.*(M.^2))./(2.*S^2)))).*(M>=0);

%%
% _*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 [d, pre, post, height, cycle, pred] = dfs(adj_mat, start, directed)
% DFS Perform a depth-first search of the graph starting from 'start'.
% [d, pre, post, height, cycle, pred] = dfs(adj_mat, start, directed)
%
% d(i) is the time at which node i is first discovered.
% pre is a listing of the nodes in the order in which they are first encountered (opened).
% post is a listing of the nodes in the order in which they are last encountered (closed).
% A node is last encountered once we have explored all of its neighbors.
% If the graph is directed, i's neighbors are its children.
% If the graph is a tree, preorder is parents before children, and
% postorder is children before parents.
% For a DAG, topological order = reverse(postorder).
% height(i) is the height (distance) of node i from the start.
% 'cycle' is true iff a (directed) cycle is found.
% pred(i) is the parent of i in the dfs tree rooted at start.
% See Cormen, Leiserson and Rivest, "An intro. to algorithms" 1994, p478.

% We can detect undirected cycles by checking if we are about to visit a node n which we have
% already visited. To detect *directed* cycles, we need to know if n has been closed or is still open.
% For example (where arcs are directed down)
%   1    2
%   \   /
%     3
% Assume we visit 1, 3 and then 2 in order. The fact that a child of 2 (namely, 3) has
% already been visited is okay, because 3 has been closed.
% The algorithms in Aho, Hopcroft and Ullman, and Sedgewick, do not detect directed cycles.

n = length(adj_mat);

global white gray black
white = 0; gray = 1; black = 2;

color = white*ones(1,n);
d = zeros(1,n);
height = zeros(1,n);
pred = zeros(1,n);
pre = [];
post = [];
cycle = 0;
global count
count = 0;
h = 0;
[d, pre, post, height, cycle, color, pred] = ...
    dfs2(adj_mat, start, directed, h, d, pre, post, height, cycle, color, pred);

%%%%%%%%%%

function [d, pre, post, height, cycle, color, pred] = ...
    dfs2(adj_mat, i, directed, h, d, pre, post, height, cycle, color, pred)

global count
global white gray black

color(i) = gray;
count = count + 1;
d(i) = count;
pre = [pre i];
height(i) = h;
if directed
  ns = children(adj_mat, i);
else
  ns = neighbors(adj_mat, i);
end
for j=1:length(ns)
  n=ns(j);
  if ~directed & n==pred(i) % don't go back up the edge you just came down
    % continue
  else
    if color(n) == gray % going back to a non-closed vertex via a new edge
      %fprintf(1, 'cycle from %d to %d\n', i, n);
      cycle = 1;
    end
    if color(n) == white % not visited n before
      pred(n)=i;
      [d, pre, post, height, cycle, color, pred] = ...
	  dfs2(adj_mat, n, directed, h+1, d, pre, post, height, cycle, color, pred);
    end
  end
end
color(i) = black;
post = [post i];


function triangulation_orient ( prefix )

%*****************************************************************************80
%
%% MAIN is the main program for TRIANGULATION_ORIENT.
%
%  Discussion:
%
%    TRIANGULATION_ORIENT forces a triangulation to have positive orientation.
%
%    The user supplies a node file and a triangle file, containing
%    the coordinates of the nodes, and the indices of the nodes that
%    make up each triangle.  Either 3-node or 6-node triangles may
%    be used.
%
%    The program reads the data, and for each triangle, determines
%    whether the triangle has positive orientation.  This essentially
%    means that the vertices are listed in counter clockwise order.
%    If the vertices are listed in the wrong order, they are reordered.
%    The reordered triangle file is written out.
%
%    Note that for an order 6 triangulation, the vertices are listed
%    in the first three positions.
%
%  Usage:
%
%    triangulation_orient ( 'prefix' )
%
%    where 'prefix' is the common filename prefix:
%
%    * 'prefix'_nodes.txt contains the node coordinates,
%    * 'prefix'_elements.txt contains the element definitions.
%    * 'prefix'_orient_elements.txt will contain the oriented element definitions.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 October 2009
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TRIANGULATION_ORIENT\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Read a node dataset of NODE_NUM points in 2 dimensions.\n' );
  fprintf ( 1, '  Read an associated triangle file of TRIANGLE_NUM \n' );
  fprintf ( 1, '  triangles using 3 or 6 nodes.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Ensure that every triangle has positive orientation.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Write the reoriented triangle file.\n' );
%
%  The command line argument is the common filename prefix.
%
  if ( nargin < 1 )

    fprintf ( 1, '\n' );
    fprintf ( 1, 'TRIANGULATION_ORIENT:\n' );

    prefix = input ( ...
      'Please enter the filename prefix:' );

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

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

  node_xy(1:dim_num,1:node_num) = r8mat_data_read ( node_filename, ...
    dim_num, node_num );

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

  r8mat_transpose_print_some ( dim_num, node_num, node_xy, 1, 1, dim_num, 5, ...
    '  First 5 nodes:' );
%
%  Read the element data.
%
  [ triangle_order, triangle_num ] = i4mat_header_read ( ...
    element_filename );

  if ( triangle_order ~= 3 && triangle_order ~= 6 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'TRIANGULATION_ORIENT - Fatal error!\n' );
    fprintf ( 1, '  Data is not for a 3-node or 6-node triangulation.\n' );
    error ( 'TRIANGULATION_L2Q - Fatal error!' );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read the header of "%s".\n', element_filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Triangle order = %d\n', triangle_order );
  fprintf ( 1, '  Number of triangles TRIANGLE_NUM  = %d\n', triangle_num );

  triangle_node(1:triangle_order,1:triangle_num) = i4mat_data_read ( ...
    element_filename, triangle_order, triangle_num );

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

  i4mat_transpose_print_some ( triangle_order, triangle_num, triangle_node, ...
    1, 1, triangle_order, 5, '  First 5 triangles:' );
%
%  Detect and correct 0-based indexing.
%
  triangle_node = mesh_base_one ( node_num, triangle_order, triangle_num, ...
    triangle_node );
%
%  Compute the area, and reorient if necessary.
%
  triangle_negative_num = 0;
  triangle_zero_num = 0;

  for triangle = 1 : triangle_num

    t3(1:2,1:3) = node_xy(1:2,triangle_node(1:3,triangle));

    area = triangle_area_2d ( t3 );

    if ( area < 0.0 )

      triangle_negative_num = triangle_negative_num + 1;

      node                      = triangle_node(2,triangle);
      triangle_node(2,triangle) = triangle_node(3,triangle);
      triangle_node(3,triangle) = node;

      if ( triangle_order == 6 )
        node                      = triangle_node(4,triangle);
        triangle_node(4,triangle) = triangle_node(6,triangle);
        triangle_node(6,triangle) = node;
      end
%
%  As a check, repeat the area calculation.
%  Now, we expect to get a positive result.
%
      t3(1:2,1:3) = node_xy(1:2,triangle_node(1:3,triangle));

      area = triangle_area_2d ( t3 );

      if ( area < 0.0 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'TRIANGULATION_ORIENT - Fatal error!\n' );
        fprintf ( 1, '  I thought I fixed the area but I did not!\n' );
        error ( 'TRIANGULATION_L2Q - Fatal error!' );
      end

    elseif ( area == 0.0 )

      triangle_zero_num = triangle_zero_num + 1;

    end

  end

  if ( 0 < triangle_zero_num )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'TRIANGULATION_ORIENT - Warning!\n' );
    fprintf ( 1, '  You have %d triangles with\n', triangle_zero_num );
    fprintf ( 1, '  area equal to zero.\n' );
  end

  if ( 0 < triangle_negative_num )

    i4mat_write ( element_orient_filename, triangle_order, ...
      triangle_num, triangle_node );

    fprintf ( 1, '\n' );
    fprintf ( 1, 'TRIANGULATION_ORIENT - Warning!\n' );
    fprintf ( 1, '  You have %d triangles with\n', triangle_negative_num );
    fprintf ( 1, '  negative area.\n' );
    fprintf ( 1, '\n' );
    fprintf ( 1, '  We have reoriented these triangles to have positive\n' );
    fprintf ( 1,'  area, and written the new triangle data to \n' );
    fprintf ( 1, '  the triangle file "%s".\n', element_orient_filename );

    i4mat_transpose_print_some ( triangle_order, triangle_num, ...
      triangle_node, 1, 1, triangle_order, 5, '  First 5 triangles:' );

  else

    fprintf ( 1, '\n' );
    fprintf ( 1, 'TRIANGULATION_ORIENT:\n' );
    fprintf ( 1, '  None of your triangles had negative area.\n' );
    fprintf ( 1, '  Therefore, no new triangle file was written.\n' );

  end
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TRIANGULATION_ORIENT\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function column_num = file_column_count ( input_file_name )

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

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

  while ( 1 )

    line = fgetl ( input_unit );

    if ( line == -1 )
      break;
    end

    if ( s_len_trim ( line ) == 0 )

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

    else
      got_one = TRUE;
      break;
    end

  end

  fclose ( input_unit );

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

  column_num = s_word_count ( line );

  return
end
function row_num = file_row_count ( input_file_name )

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

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

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

  record_num = 0;

  while ( 1 )

    line = fgetl ( input_unit );

    if ( line == -1 )
      break;
    end

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

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

  end

  fclose ( input_unit );

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

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

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

  input_unit = fopen ( input_filename );

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

  i = 0;

  while ( i < n )

    line = fgets ( input_unit );

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

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

    elseif ( s_len_trim ( line ) == 0 )

    else

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

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

    end

  end

  fclose ( input_unit );

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

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

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

  n = file_row_count ( input_filename );

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

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

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

  fprintf ( 1, '\n' );
  fprintf ( 1, '%s\n', title );

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

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

    inc = i2hi + 1 - i2lo;

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

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

    for j = j2lo : j2hi

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

    end

  end

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

%*****************************************************************************80
%
%% I4MAT_WRITE writes an I4MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 August 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, integer TABLE(M,N), the points.
%
%    Input, logical HEADER, is TRUE if the header is to be included.
%

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

  if ( output_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_WRITE - Error!\n' );
    fprintf ( 1, '  Could not open the output file.\n' );
    error ( 'I4MAT_WRITE - Error!' );
  end
%
%  Write the data.
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %12d', round ( table(i,j) ) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

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

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

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

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

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

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

  input_unit = fopen ( input_filename );

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

  i = 0;

  while ( i < n )

    line = fgets ( input_unit );

    if ( line == -1 )
      break;
    end

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

    elseif ( s_len_trim ( line ) == 0 )

    else

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

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

    end

  end

  fclose ( input_unit );

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

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

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

  n = file_row_count ( input_filename );

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

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

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

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

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

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

    inc = i2hi + 1 - i2lo;

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

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

    for j = j2lo : j2hi

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

    end

  end

  return
end
function len = s_len_trim ( s )

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

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

  return
end
function word_num = s_word_count ( s )

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

  word_num = 0;
  s_length = length ( s );

  if ( s_length <= 0 )
    return;
  end

  blank = TRUE;

  for i = 1 : s_length

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

  end

  return
end
function timestamp ( )

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

  return
end
function area = triangle_area_2d ( t )

%*****************************************************************************80
%
%% TRIANGLE_AREA_2D computes the area of a triangle in 2D.
%
%  Discussion:
%
%    If the triangle's vertices are given in counterclockwise order,
%    the area will be positive.  If the triangle's vertices are given
%    in clockwise order, the area will be negative!
%
%    An earlier version of this routine always returned the absolute
%    value of the computed area.  I am convinced now that that is
%    a less useful result!  For instance, by returning the signed
%    area of a triangle, it is possible to easily compute the area
%    of a nonconvex polygon as the sum of the (possibly negative)
%    areas of triangles formed by node 1 and successive pairs of vertices.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 October 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real T(2,3), the triangle vertices.
%
%    Output, real AREA, the area of the triangle.
%
  area = 0.5 * ( ...
      t(1,1) * ( t(2,2) - t(2,3) ) ...
    + t(1,2) * ( t(2,3) - t(2,1) ) ...
    + t(1,3) * ( t(2,1) - t(2,2) ) );

  return
end


function y = cvx_s_symmetric( m, n )
%CVX_S_SYMMETRIC Symmetric matrices (lower triangle storage).

if m ~= n,
    error( 'Symmetric structure requires square matrices.' );
end

nsq = n * n;
ntr = 0.5 * ( nsq + n );
c  = 0 : n - 1;
c  = c( ones( 1, n ), : );
r  = c';
mn = min( r, c );
mx = max( r, c );
y  = mx + mn .* ( n - 0.5 * ( mn + 1 ) ) + 1;
y  = sparse( y( : ), 1 : nsq, 1, ntr, nsq );

% Copyright 2010 Michael C. Grant and Stephen P. Boyd.
% See the file COPYING.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


%+========================================================================+
%|                                                                        |
%|            This script uses the GYPSILAB toolbox for Matlab            |
%|                                                                        |
%| COPYRIGHT : Matthieu Aussal & Yosra Boukari & Houssem Haddar (c) 2017-2018.|
%| PROPERTY  : Centre de Mathematiques Appliquees, Ecole polytechnique,   |
%| route de Saclay, 91128 Palaiseau, France. All rights reserved.         |
%| LICENCE   : This program is free software, distributed in the hope that|
%| it will be useful, but WITHOUT ANY WARRANTY. Natively, you can use,    |
%| redistribute and/or modify it under the terms of the GNU General Public|
%| License, as published by the Free Software Foundation (version 3 or    |
%| later,  http://www.gnu.org/licenses). For private use, dual licencing  |
%| is available, please contact us to activate a "pay for remove" option. |
%| CONTACT   : matthieu.aussal@polytechnique.edu                          |
%| WEBSITE   : www.cmap.polytechnique.fr/~aussal/gypsilab                 |
%|                                                                        |
%| Please acknowledge the gypsilab toolbox in programs or publications in |
%| which you use it.                                                      |
%|________________________________________________________________________|
%|   '&`   |                                                              |
%|    #    |   FILE       : nrtIpbHelmholtz0.m                            |
%|    #    |   VERSION    : 0.40                                          |
%|   _#_   |   AUTHOR(S)  : Matthieu Aussal & Yosra Boukari               |
%|  ( # )  |                & Houssem Haddar                              |
%|  / 0 \  |   CREATION   : 14.03.2017                                    |
%| ( === ) |   LAST MODIF : 14.03.2018                                    |
%|  `---'  |   SYNOPSIS   : Completion data for spherical helmholtz       |
%|         |                scatering                                     |
%|         |   ref1 : A Convergent Data Completion Algorithm Using Surface|
%|         |   Integral Equation, Inverse Problems, IOP Publishing ...    |
%|         |   ref2: Poly cours Terasse p. 194, Calderon operators        |
%+========================================================================+

% Cleaning
clear all
close all
clc

% Gypsilab path
run('../../addpathGypsilab.m')

% Wave number and frequency
k = 1
f = (k*340)/(2*pi)

% Data noise
noise = 0%1e-2

% Incident plane wave with normlized direction
X0         = [0 0 -1];
X0         = X0./norm(X0);
PW         = @(X) exp(1i*k*X*X0');
gradxPW{1} = @(X) 1i*k*X0(1) .* PW(X);
gradxPW{2} = @(X) 1i*k*X0(2) .* PW(X);
gradxPW{3} = @(X) 1i*k*X0(3) .* PW(X);

% Green kernel function --> G(x,y) = exp(ik|x-y|)/|x-y|
Gxy = @(X,Y) femGreenKernel(X,Y,'[exp(ikr)/r]',k);

% grady Green kernel function --> G(x,y) = grady[exp(ik|x-y|)/|x-y|]
dyGxy{1} = @(X,Y) femGreenKernel(X,Y,'grady[exp(ikr)/r]1',k);
dyGxy{2} = @(X,Y) femGreenKernel(X,Y,'grady[exp(ikr)/r]2',k);
dyGxy{3} = @(X,Y) femGreenKernel(X,Y,'grady[exp(ikr)/r]3',k);

% Green kernel function --> G(x,y) = gradx[exp(ik|x-y|)/|x-y|]
dxGxy{1} = @(X,Y) femGreenKernel(X,Y,'gradx[exp(ikr)/r]1',k);
dxGxy{2} = @(X,Y) femGreenKernel(X,Y,'gradx[exp(ikr)/r]2',k);
dxGxy{3} = @(X,Y) femGreenKernel(X,Y,'gradx[exp(ikr)/r]3',k);

% Finite element
gss = 3;
typ = 'P1';
tol = 1e-3;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SCATERING PROBLEM %%%%%%%%%%%%%%%%%%%%%%%%%%%
% Fictive mesh for diffraction problem (sphere)
mesh = mshSphere(4e2,1);

% % Fictive mesh for diffraction problem (cube)
% mesh = mshCube(4e2,[1 1 1]);
% mesh = mesh.bnd;

% Verify wave number
stp = mesh.stp;
if k > 1/stp(2)
    error('completionHelmholtz.m : wave number k is too high for mesh')
end

% Quadrature
sigma = dom(mesh,gss);

% Finite element
u = fem(mesh,typ);

% Boundary element operator on fictive domain (Hypersingular)
H = 1/(4*pi) .* (k^2 * integral(sigma,sigma,ntimes(u),Gxy,ntimes(u)) ...
    - integral(sigma,sigma,nxgrad(u),Gxy,nxgrad(u)));
H = H + 1/(4*pi) .* (k^2 * regularize(sigma,sigma,ntimes(u),'[1/r]',ntimes(u)) ...
    - regularize(sigma,sigma,nxgrad(u),'[1/r]',nxgrad(u)));

% Solve neumann problem on fictive boundary : - [H] mu = - dnP0
RHS = - integral(sigma,ntimes(u),gradxPW);
mu  = (-H) \ RHS;

% Radiation on boundary :  p(x) =  - [D + I/2] mu
Id  = integral(sigma,u,u);
D   = 1/(4*pi) .* integral(sigma,sigma,u,dyGxy,ntimes(u));
D   = D + 1/(4*pi) .* regularize(sigma,sigma,u,'grady[1/r]',ntimes(u));
sol = - Id \ ( (D + 0.5*Id) * mu);

% Comparare to analytic solution
ref = sphereHelmholtz('dom','neu',1,k,1.0001*mesh.vtx);
errScatMesh = norm(ref - sol)/norm(ref)

% Graphical representation
figure
plot(mesh)
hold on
plot(mesh,abs(sol+PW(u.dof)))
xlabel('X');   ylabel('Y');   zlabel('Z');
title('Total field')
axis equal
colorbar

%%%%%%%%%%%%%%%%%%%%%%%%%%%% SCATERING RADIATION %%%%%%%%%%%%%%%%%%%%%%%%%%
% Interior boundary
meshInt = mshSphere(5e2,1.25);
meshInt = swap(meshInt);

% Exterior boundary
meshExt = mshSphere(1e3,1.5);

% Fusion des maillages
meshTot = union(meshExt,meshInt);

% Verify wave number
stp = mesh.stp;
if k > 1/stp(2)
    error('completionHelmholtz.m : wave number k is too high for mesh')
end

% Quadrature
sigmaTot = dom(meshTot,gss);

% Finite element
uTot = fem(meshTot,typ);

% Mass matrix
IdTot = integral(sigmaTot,uTot,uTot);

% Solution of the scatering problem : p(x) = - [D] mu
p = - 1/(4*pi) .* integral(sigmaTot,sigma,uTot,dyGxy,ntimes(u)) * mu;

% Extract Galerkin
p = IdTot \ p;

% Compare to analytical solution
ref = sphereHelmholtz('dom','neu',1,k,uTot.dof);
errScat = norm(ref-p)/norm(ref)

% Scatered speed : dnp(x) = - [H] mu
dnp = - 1/(4*pi) .* (k^2 * integral(sigmaTot,sigma,ntimes(uTot),Gxy,ntimes(u)) ...
    - integral(sigmaTot,sigma,nxgrad(uTot),Gxy,nxgrad(u))) * mu;

% Extract Galerkin
dnp = IdTot \ dnp;

% % Graphical representation
% figure
% plot(mesh)
% hold on
% plot(mesh,abs(p+PW(uTot.dof)))
% plotNrm(mesh,'r')
% xlabel('X');   ylabel('Y');   zlabel('Z');
% title('Interior radiation')
% axis equal
% alpha(0.5)
% colorbar

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% OPERATOR %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Single layer --> \int_Sx \int_Sy psi(x)' G(x,y) psi(y) dx dy
S = 1/(4*pi) .* integral(sigmaTot,sigmaTot,uTot,Gxy,uTot);
S = S + 1/(4*pi) .* regularize(sigmaTot,sigmaTot,uTot,'[1/r]',uTot);

% Double layer --> \int_Sx \int_Sy psi(x)' dny G(x,y) psi(y) dx dy
D = 1/(4*pi) .* integral(sigmaTot,sigmaTot,uTot,dyGxy,ntimes(uTot));
D = D + 1/(4*pi) .* regularize(sigmaTot,sigmaTot,uTot,'grady[1/r]',ntimes(uTot));

% Double layer --> \int_Sx \int_Sy psi(x)' dnx G(x,y) psi(y) dx dy
Dt = D.';

% Hypersingular --> k^2 * \int_Sx \int_Sy n.psi(x) G(x,y) n.psi(y) dx dy
%                   - \int_Sx \int_Sy nxgrad(psi(x)) G(x,y) nxgrad(psi(y)) dx dy
N = 1/(4*pi) .* (k^2 * integral(sigmaTot,sigmaTot,ntimes(uTot),Gxy,ntimes(uTot)) ...
    - integral(sigmaTot,sigmaTot,nxgrad(uTot),Gxy,nxgrad(uTot)));
N = N + 1/(4*pi) .* (k^2 * regularize(sigmaTot,sigmaTot,ntimes(uTot),'[1/r]',ntimes(uTot)) ...
    - regularize(sigmaTot,sigmaTot,nxgrad(uTot),'[1/r]',nxgrad(uTot)));

% Calderon operators
Z = sparse(length(uTot),length(uTot));
I = [IdTot Z ; Z IdTot];
H = [-D S ; -N Dt];

% Calderon operator for interior problem (projector)
A = H + 0.5*I;
errCalderon = norm(A*(I\A)-A,'fro')/norm(A,'fro')

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% INVERSE PROBLEM %%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Indices des dof
N    = size(meshTot.vtx,1);
Iext = 1:size(meshExt.vtx,1);
Iint = Iext(end)+1:N;

% Excitation
f = p(Iext);
g = dnp(Iext);

% Solutions
pSol   = p(Iint);
dnpSol = dnp(Iint);

% Indice operateur
Iext = [Iext , N + Iext];
Iint = [Iint , N + Iint];

% Extraction des sous matrices
A11 = A(Iext,Iext);
A12 = A(Iext,Iint);
A21 = A(Iint,Iext);
A22 = A(Iint,Iint);

% Matrices identite
I11 = I(Iext,Iext);
I22 = I(Iint,Iint);

% Linear system
LHS = [A12 ; A22 - I22];

% Right hand side
RHS = [ I11 - A11 ; -A21] * [f;g];

% Solve linear system with gaussian noise
X = LHS \ (RHS .* (1 + noise*(1 + randn(size(RHS,1),1))));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% TICHONOV %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% data  = F1;
% datan = B * F1n;
% [U,S,V]=svd(A);
% global s2 delta rhs2
% a1 = length(fe{2});
% rhs=(U')*datan;
% rhsr =rhs(1:a1+a1);
% s2 = diag(S).^2;
% rhs2 = abs(rhsr).^2;
% delta=norm(datan-B*(data))/norm(datan);
% alpha0=delta*min(s2)/(1-delta);
% alpha1=delta*max(s2)/(1-delta);
%
% fmor = @(x)sum(((x ./(x+s2)).^2 - delta^2).*rhs2);
% alphaM = fzero(fmor,[alpha0 alpha1]);
%
% X2 = V*((diag(S)./(alphaM+s2)).*rhsr);
% errTichonov = norm(X-X2)./norm(X2)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ERROR ANALYSIS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Compare external pression
sol = X(1:end/2);
ref = pSol;
errSolution = norm(ref-sol)/norm(ref)

% Graphical representation
figure(13)
plot(meshInt,abs(sol+PW(meshInt.vtx)))
xlabel('X');   ylabel('Y');   zlabel('Z');
title('Reconstructed total field')
axis equal
colorbar

% Graphical representation
figure(14)
plot(meshInt,abs(sol-ref)./abs(ref))
xlabel('X');   ylabel('Y');   zlabel('Z');
title('Relative error on reconstructed field')
axis equal
colorbar

% Compare normal derivative
sol = X(end/2+1:end);
ref = dnpSol;
errDerivative = norm(ref-sol)/norm(ref)

disp('~~> Michto gypsilab !')


function [f] = spm_fp_cmc_tfm(x,u,P,M)
% parameter equations for a neural mass model (canonical microcircuit)
% FORMAT [f] = spm_fp_cmc_tfm(x,u,P,M)
%
% x      - state vector
%   x(:,1) - voltage     (spiny stellate cells)
%   x(:,2) - conductance (spiny stellate cells)
%   x(:,3) - voltage     (superficial pyramidal cells)
%   x(:,4) - conductance (superficial pyramidal cells)
%   x(:,5) - voltage     (inhibitory interneurons)
%   x(:,6) - conductance (inhibitory interneurons)
%   x(:,7) - voltage     (deep pyramidal cells)
%   x(:,8) - conductance (deep pyramidal cells)
%
% f        - dP = h(x(t),u(t),P,M)
%
% Prior fixed parameter scaling
%
% G  = intrinsic rates
% D  = propagation delays (intrinsic, extrinsic)
% T  = synaptic time constants
% R  = slope of sigmoid activation function
%
%__________________________________________________________________________
% David O, Friston KJ (2003) A neural mass model for MEG/EEG: coupling and
% neuronal dynamics. NeuroImage 20: 1743-1755
%__________________________________________________________________________
% Copyright (C) 2005 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_fp_cmc_tfm.m 6234 2014-10-12 09:59:10Z karl $

% Neuronal states (deviations from baseline firing)
%--------------------------------------------------------------------------
%   x(:,1) - voltage     (spiny stellate cells)
%   x(:,2) - conductance (spiny stellate cells)
%   x(:,3) - voltage     (superficial pyramidal cells)
%   x(:,4) - conductance (superficial pyramidal cells)
%   x(:,5) - voltage     (inhibitory interneurons)
%   x(:,6) - conductance (inhibitory interneurons)
%   x(:,7) - voltage     (deep pyramidal cells)
%   x(:,8) - conductance (deep pyramidal cells)
%--------------------------------------------------------------------------
persistent iG nP Ca G
if isempty(iG)
    Ca  = zeros(size(P.G));
    G   = zeros(size(P.G));                    % parameter (deviates)
    iG  = spm_fieldindices(P,'G');
    nP  = spm_length(P);
end

% get dimensions and configure state variables
%--------------------------------------------------------------------------
f  = zeros(nP,1);                              % flow
x  = spm_unvec(x,M.x);                         % neuronal states
x  = x(:,1:2:end);                             % depolarisation

% neuronal populations with Voltage-dependent connectivity
%==========================================================================
%                  ss sp ii dp                 % neuronal populations
%--------------------------------------------------------------------------
a     = [1 8 2 1]*64;                          % potentiation rate
b     = [4 2 2 1]*4;                           % decay rate

NMDA  = @(x)1./(1 + exp(-x)) - 1/2;            % depolarisation CDF

% NMDA-like Voltage-dependent changes in (recurrent) synaptic efficacy
%--------------------------------------------------------------------------
A     = exp(P.E)*diag(a);
B     = exp(P.F)*diag(b);
dC    = (A.*NMDA(8*x) - Ca).*B;
dG    = Ca.*(2 - G)/2  - G.*B;
Ca    = Ca + dC*M.dt;
G     = G  + dG*M.dt;
f(iG) = G(:);


classdef ShFunc_Chomog_fraction < ShFunc_Chomog

    properties (Access = private)
        invChAA
        invChBB
        invChAB
        invChBA
    end

    properties (Access = private)
        alpha
        beta
    end

    methods (Access = public)

        function obj=ShFunc_Chomog_fraction(cParams)
            obj.initChomog(cParams);
            obj.alpha = cParams.alpha/norm(cParams.alpha);
            obj.beta  = cParams.beta/norm(cParams.beta);
        end

        function computeFunctionValue(obj)
            obj.computeInvChProyections();
            obj.value = obj.invChAB/obj.invChAA + obj.invChBA/obj.invChBB;
        end

        function computeGradientValue(obj)
            obj.computeChDerivative();
            a = obj.alpha;
            b = obj.beta;
            beta1 = obj.invChAA*b - obj.invChAB*a;
            beta2 = obj.invChBB*a - obj.invChBA*b;
            g1    = obj.computedChInv(obj.Chomog,a,beta1);
            g2    = obj.computedChInv(obj.Chomog,b,beta2);
            grad = g1/(obj.invChAA)^2 + g2/(obj.invChBB)^2;
            obj.gradient = grad;
        end

    end

    methods (Access = private)

        function computeInvChProyections(obj)
            invCh = inv(obj.Chomog);
            a = obj.alpha;
            b = obj.beta;
            obj.invChAB  = obj.projectTensor(invCh,a,b);
            obj.invChBA  = obj.projectTensor(invCh,b,a);
            obj.invChAA  = obj.projectTensor(invCh,a,a);
            obj.invChBB  = obj.projectTensor(invCh,b,b);
        end

    end

end


function igood = get_good_channels(ops, chanMap)
% of the channels indicated by the user as good (chanMap)
% further subset those that have a mean firing rate above a certain value
% (default is ops.minfr_goodchannels = 0.1Hz)
% needs the same filtering parameters in ops as usual
% also needs to know where to start processing batches (twind)
% and how many channels there are in total (NchanTOT)

Nbatch = ops.Nbatch;
twind = ops.twind;
NchanTOT = ops.NchanTOT;
NT = ops.NT;
Nchan = numel(chanMap);

% load data into patches, filter, compute covariance
if isfield(ops,'fslow')&&ops.fslow<ops.fs/2
    [b1, a1] = butter(3, [ops.fshigh/ops.fs,ops.fslow/ops.fs]*2, 'bandpass');
else
    [b1, a1] = butter(3, ops.fshigh/ops.fs*2, 'high');
end

fid = fopen(ops.fbinary, 'r');
% irange = [NT/8:(NT-NT/8)];

ibatch = 1;
ich = gpuArray.zeros(5e4,1, 'int16');
k = 0;
ttime = 0;

% from a subset of batches, count threshold crossings
while ibatch<=Nbatch
    offset = twind + 2*NchanTOT*NT* (ibatch-1);
    fseek(fid, offset, 'bof');
    buff = fread(fid, [NchanTOT NT], '*int16');

    if isempty(buff)
        break;
    end

    datr    = gpufilter(buff, ops, chanMap); % apply filters and median subtraction

    % very basic threshold crossings calculation
    datr = datr./std(datr,1,1); % standardize each channel ( but don't whiten)

    mdat = my_min(datr, 30, 1); % get local minima as min value in +/- 30-sample range
    ind = find(datr<mdat+1e-3 & datr<ops.spkTh); % take local minima that cross the negative threshold
    [xi, xj] = ind2sub(size(datr), ind); % back to two-dimensional indexing
    xj(xi<ops.nt0 | xi>NT-ops.nt0) = []; % filtering may create transients at beginning or end. Remove those.
    if k+numel(xj)>numel(ich)
        ich(2*numel(ich)) = 0; % if necessary, extend the variable which holds the spikes
    end
    ich(k + [1:numel(xj)]) = xj; % collect the channel identities for the detected spikes

    k = k + numel(xj);

    ibatch = ibatch + ceil(Nbatch/100); % skip every 100 batches
    ttime = ttime + size(datr,1)/ops.fs; % keep track of total time where we took spikes from
end
fclose(fid);

ich = ich(1:k);

nc = histcounts(ich, .5 + [0:Nchan]); % count how many spikes each channel got
nc = nc/ttime; % divide by total time to get firing rate

% igood = nc>.1;
igood = nc>=getOr(ops, 'minfr_goodchannels', .1); % keep only those channels above the preset mean firing rate

fprintf('found %d threshold crossings in %2.2f seconds of data \n', k, ttime)
fprintf('found %d bad channels \n', sum(~igood))


function maskM = fastPolyFill(pointsM,optS)
%function maskM = fastPolyFill(pointsM,optS)
%fastPolyFill:  fills in images given polygons defining edges.
%Intention is to only fill a voxel if it's center is in the polygon.
%Faster than previous version by a significant factor (about x10).
%JOD; 17 June 05.
%Fixed bug, 5 July 05.
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

imageSizeV = optS.ROIImageSize;

xOffset = optS.xCTOffset;
yOffset = optS.yCTOffset;

numRows = imageSizeV(1);
numCols = imageSizeV(2);

xInV = pointsM(:,1);
yInV = pointsM(:,2);

maskM = zeros(numRows,numCols);
%could also be a double.

%preallocate a table of voxel indices
%'next to' refers to voxel centers just to the right of where polygon
%edges cross a line connecting voxel centers.
nextToPtsM = sparse(numRows * 4, numCols * 4); %hard to imagine bigger (sparse is faster than full)
numNextToPtsV = zeros(numRows,1);

%convert to "row and col space", that is, a continuous space where
%s is a coord that runs from 1 to numCols (along x axis)
%t is a coord that runs from 1 to numRows (along -y axis)
sInV = (xInV - xOffset)/optS.ROIxVoxelWidth + (numCols + 1)/2;
tInV = (yInV - yOffset)/optS.ROIyVoxelWidth + (numRows + 1)/2;

%For each polygonal element, compute and add one to 'row starters,' centers of
%voxels (assumed at image coords) whose rows cross the polygonal elements
%and are the first element to the right of that polygonal element's row crossing.
%
%Use the parameterization col = n * deltaRow + c + rowURPt    (URPt = upper
%right point).
%
%Algorithm:
%1.  Determine n
%2.  Determine c
%3.  Determine vector of row crossings
%4.  Determine vector of column crossings
%5.  Add one to row starters.

%Loop over polygonal elements
%For polygonal elements:

shift_sV = [sInV(end); sInV(1:end-1)];
shift_tV = [tInV(end); tInV(1:end-1)];

sM = [sInV(:), shift_sV];
tM = [tInV(:), shift_tV];

%Loop over polygonal edges, put ones where voxel centers are inside
%polygon.
for i = 1 : length(sInV)

    if tM(i,1) ~= tM(i,2)   %skip horizontal lines

        tMax = max([tM(i,1),tM(i,2)]);
        tMin = min([tM(i,1),tM(i,2)]);

        %determine n (line parameterization: s = n * t + c )
        n = (sM(i,1) - sM(i,2))/(tM(i,1) - tM(i,2));
        %determine c, could vectorize these two
        c = sM(i,1) - n * tM(i,1);

        %get delta_tV
        tPtsV = ceil(tMin) : floor(tMax);
        delta_tV = tPtsV - tMax;
        sPtsV = n * delta_tV + c + n * tMax; %these are s values at edge 'crossings'

        %derive s values 'next to the right' of the crossings
        sVoxelsV = ceil(sPtsV);

        %catalogue
        for j = 1: length(sVoxelsV)

         num = numNextToPtsV(tPtsV(j));
         numNextToPtsV(tPtsV(j)) = num + 1;
         nextToPtsM(tPtsV(j),num+1) = sVoxelsV(j);

        end

    end

end

%This should be faster than the oft-used cumsum trick:
for i = 1 : numRows
   num = numNextToPtsV(i);
   if num ~=0
       %get 'em
       nextToPtsV = nextToPtsM(i,1:num);
       %sort 'em
       sortPtsV = sort(full(nextToPtsV));
       %fill image
       for j = 1 : length(sortPtsV)/2
         indV = sortPtsV(2*j-1) : sortPtsV(2*j) - 1;
         maskM(i * ones(1,length(indV)),indV) = 1;
       end
   end
end

%lastly, correct an oversight in writing the code: rows need to be flipped:
maskM = flipud(maskM);  %fast operation.


function m = cvecrep(v,c)

% CVECREP  Column vector replicate
%
%   M = cvecrep(V, C) Replicates a Nx1 dimensional column vector V, C times to generate a
%   NxC dimensional matrix M.
%
%   See also
%   RVECREP, REPMAT
%   Copyright (c) Oregon Health & Science University (2006)
%
%   This file is part of the ReBEL Toolkit. The ReBEL Toolkit is available free for
%   academic use only (see included license file) and can be obtained from
%   http://choosh.csee.ogi.edu/rebel/.  Businesses wishing to obtain a copy of the
%   software should contact rebel@csee.ogi.edu for commercial licensing information.
%
%   See LICENSE (which should be part of the main toolkit distribution) for more
%   detail.

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

if isempty(v)

  m = zeros(0,c);

else

  m = v(:,ones(c,1));

end


function [Iq, A, W, S, index]=icassoShow(sR,varargin)
%function icassoShow(sR,['identifier1',value1,'indentifier2',value2,...])
%
%PURPOSE
%
%To generate explorative visualizations for Icasso
%
%EXAMPLES OF BASIC USAGE
%
%  [Iq, A, W, S]=icassoShow(sR);
%
%shows results for as many estimate-clusters as there are (reduced)
%data dimensions. Also, return the estimates of independent
%components estimates (A,W,S) that correspond to the centroid of
%each estimate-cluster. The first output Iq contain the quality of
%the  estimates. You can rank the estimates according to this index.
%
%  icassoShow(sR,'colorlimit',[0.7 0.9],'estimate','demixing','L',9);
%
%changes the color scale
%0...0.7 (not shown), 0.7...0.9 (light red), 0.9...1 (bright red)
%and suppresses the graph lines for similarities under value 0.7 in
%general, and inside clusters that are dense (0.9...1). Shows rows
%of demixing matrix instead of sources in the estimate
%window. Aggregate results in 9 estimate-clusters.
%
%INPUTS
%
%sR (struct) Icasso result data structure
%
%Optional input arguments are given as argument identifier - value
%pairs: 'identifier1', value1, 'identifier2', value2,...
%(case insensitive)
%
% 'L' (string) 'rdim' (default) | (integer)
%   sets the number of estimate-clusters 'rdim' sets it equal to the
%   (reduced) data dimension
% 'estimate' (string) 'source' (default) | 'demixing' | 'mixing' | 'off'
%   whether to show the estimates of the
%   - independent components (sources),
%   - rows of the demixing matrix (W), or
%   - columns of the mixing matrix (A)
%    that are associated to the centrotype of each estimate-cluster.
%   Argument 'off' suppresses the window.
% 'colorlimit' (vector) default [0.5 0.75 0.9]
%   sets the thresholds for color of graph lines and clusters
%   in the 2D plot; if the cluster density (the average
%   intra-cluster similarity) exceeds the highest value, the
%   cluster/lines will be bright red, if it is below the minimum,
%   the cluster is white/lines are suppressed. The rest is colored
%   with shades of red.
% 'line' (string) 'on' (default) | 'off'
%   whether to show the similarity graph lines in the 2D plot or not
% 'hull' (string) 'on' (default) | 'off'
%   whether to show the "cluster hulls" in the 2D plot or not
% 'graphlimit' (scalar) in 0...1 | (string) 'auto' (default)
%   Controls the 2D plot: See function icassoGraph
% 'dense' (scalar) in 0...1 | (string) 'auto' (default)
%   Controls the 2D plot: See function icassoGraph
% 'quality' (string) 'simple' (default) | 'detailed'
%   'simple' shows the cluster quality index, 'detailed' shows also
%   more detailed info in a separate window (figure 6)
%
%OUTPUT
%
% Iq    (vector) stability index of each estimate (see function
%         icassoResult)
% A     (matrix) estimated columns of the mixing matrix (A) =
%         pinv(W) (see function icassoResult)
% W     (matrix) estimated rows of the demixing matrix (W) (see
%         function icassoResult)
% S     (matrix) estimated independent components (see function
%         icassoResult)
% index (vector) indices to the centrotypes (centroids) of each
%         estimate-cluster (see function icassoResult)
%
%DETAILS
%
%Detailed explanation of the resulting figures can be found in help
%texts of the functions mentioned below:
%
%[Figures in brackets can be suppressed or are optional by default]
%
%Figure 1: Relative clustering quality index for different number
%of clusters and additional information: number of clusters used in
%the rest of figures (L), number of ICs, and (reduced) data
%dimension. See function icassoRindex.
%
%Figure 2: Stability (reliability) indices  of the selected L
%estimate-clusters. See function icassoStability.
%
%Figure 3: Correlation structure as a matrix and a dendrogram
%representation for L clusters. See function icassoDendrogram.
%
%Figure 4: Graph of the correlations between all the estimates and
%estimate-clusters as convex hulls for L clusters
%(see function icassoGraph)
%
%[Figure 5: IC estimates, rows of W, or columns of A (depends on user
%selection) that correspond to the centroid (actually centrotype)
%of the selected estimate-clusters. See function signalplot.]
%
%[Figure 6: more detailed statistics on the estimate
%clusters: components of stability index Iq. See function
%icassoStability.]
%
%SEE ALSO
% icassoGet
% icassoResult
% signalplot
% icassoStability
% icassoViz
% icasso

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

% ver 1.21 040305 johan

if nargin<1|isempty(sR),
  error('At least one input argument expected');
end

if isempty(sR.projection.coordinates) | isempty(sR.cluster.partition) | ...
      isempty(sR.cluster.index) | isempty(sR.cluster.similarity),
  error('Missing similarity/projection/cluster information.');
end

% initiate output args.
index2centrotypes=[]; clusterquality=[]; partition=[];

%% Set defaults and process optional input
default={'line','on','estimate','source', 'quality','simple','L',icassoGet(sR,'rdim'),...
	 'graphlimit','auto','colorlimit',[0.5 0.75 0.9],...
	 'dense','auto','hull','on'};

% initiate arguments to icassoGraph
graphArgs=[];

varargin=processvarargin(varargin,default);
num_of_args=length(varargin);

for i=1:2:num_of_args,
  id=varargin{i}; value=varargin{i+1};
  switch lower(id)
   % Check first icassoShow
   case 'quality'
    switch lower(value)
     case 'simple'
      detailedrankplot=0;
     case 'detailed'
      detailedrankplot=1;
     otherwise
      error('Option ''quality'' must be ''simple'' or ''detailed''.');
    end
   case 'estimate'
    switch lower(value)
     case {'demixing','mixing','off','source'}
      est=lower(value);
     otherwise
      error(['Option ''estimate'' must be ''source'',''demixing'',' ...
	     ' ''mixing'', or ''off''.']);
    end
   case 'l'
    if isnumeric(value);
      level=value;
    else
      switch lower(value)
       case 'rdim'
	level=icassoGet(sR,'rdim');
       otherwise
	error(['Option ''L'' must be an integer or string ''rdim''']);
      end
    end
    % submit also to icassoGraph
    graphArgs{1,end+1}=id;
    graphArgs{1,end+1}=value;
    % submit the following to icassoGraph
   case {'line','graphlimit','colorlimit','dense','hull'}
    graphArgs{1,end+1}=id;
    graphArgs{1,end+1}=value;
   otherwise
    error(['Option ''' lower(id) ''' not available.' sprintf('\n') ...
	   'Available: ''L'', ''line'',''graphlimit'',''colorlimit'',''hull'',' ...
	   '''estimate'', and ''quality''.']);
  end
end

% Check if cluster level is valid
maxCluster=size(sR.cluster.partition,1);
if level<=0 | level>maxCluster,
  error('Cluster level out of range or not specified.');
end

%%%% Get main results %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[Iq, A, W, S, index2centrotypes]=icassoResult(sR,level);

%%%%% Compute some cluster statistics %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Get the partition

partition=sR.cluster.partition(level,:);
Ncluster=max(partition);

% cluster statistics
c=sR.cluster.similarity;
s=clusterstat(c,partition);

%%%%%%%%%%%%%%%%% Clustering validity index %%%%%%%%%%%%%%%%%%%%%%%%%%%

figure(1); clf reset;

icassoRindex(sR,level);

%%%%%%%%%%%%%%%% Ranking clusters & number of estimates %%%%%%%%%%%%%%%

figure(2); clf;

% compute & plot quality index

subplot(1,2,1);
Iq=icassoStability(sR,level,'plotindex');

% compute the rank order of estimates
clusterlabels=1:Ncluster;
[tmp,estimateOrder]=sort(-Iq);

% plot number of estimates in each cluster
subplot(1,2,2);
barh(s.N(estimateOrder));
set(gca,'ytick',1:Ncluster,'yticklabel', ...
	clusterlabels(estimateOrder),'ydir','reverse');
text(s.N(estimateOrder),1:Ncluster,cellstr(num2str(s.N(estimateOrder)')));
axis([0 max(s.N) 0.5 Ncluster+.5]);
title('Number of ICA estimates in the estimate-clusters');
ylabel('Label');
xlabel('Number of estimates');

set(2,'name','Icasso: Estimate Quality');

%%%%%%%%%%%%%%% Dendrogram %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Show dendrogram

figure(3);
clf reset;
icassoDendrogram(sR,level);

%%%%%%%%%%%%%%% Correlation graph %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

figure(4); clf reset;
if ~isempty(sR.projection.coordinates),
  icassoGraph(sR,graphArgs{:});
else
  warning(['Projection coordinates not computed, can''t start ' ...
           'icassoGraph.']);
end

%%%%%%%%%%%%% Source plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

switch est
 case 'source'
  figure(5); clf reset;
  set(5,'name','Icasso: Source Estimates (centrotypes)');
  signalplot(S(estimateOrder,:));
  set(gca,'yticklabel',estimateOrder);
  ylabel('Label');
  xlabel('Sample #');
  title(['Independent components (ranked according to I_q)']);
 case 'demixing'
  figure(5); clf reset;
  set(5,'name','Icasso: Demixing Matrix Estimate');
  signalplot(W(estimateOrder,:));
  set(gca,'yticklabel',estimateOrder);
  ylabel('Label');
  xlabel('Column #');
  title(['Demixing matrix rows (ranked according to' ...
	 ' I_q)']);
 case 'mixing'
  figure(5); clf reset;
  set(5,'name','Icasso: Mixing Matrix Estimate');
  signalplot(A(:,estimateOrder)');
  set(gca,'yticklabel',estimateOrder);
  ylabel('Label');
  xlabel('Row #');
  view([-90 90])
  title(['Mixing matrix columns (ranked according to' ...
	 ' I_q)']);
end

%%%%%%%%%%%%% Details of Iq %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if detailedrankplot,
  figure(6); clf;
  set(6,'name','Icasso: Detaild Estimate Stability');
  icassoStability(sR,level,'plotstat');
end

%%% subfunctions


function [Population,RankSolution] = EnvironmentalSelection_noCon(Population,N,alpha,gamma,para)

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

% This function is written by Mengjun Ming

    %% Parameter
    popSize   = length(Population);
    NumSeq    = (1:popSize)';
    RankConvg = zeros(popSize,1);
    RankDivs  = zeros(popSize,1);

    %% Modify the infeasible solutions
    PopObj = Population.objs;
    PopCon = Population.cons;
    z      = min(PopObj,[],1);
    n      = max(PopObj,[],1);

    Infeasible_all = any(PopCon>0,2);
    phi_max = max(sum(max(0,PopCon(Infeasible_all,:)),2));

    M          = length(z);
    [W,~]      = UniformPoint(N,M);
    [~,Region] = min(pdist2(PopObj-z,W,'cosine'),[],2);
    PopObj_2   = PopObj;
    for i = 1:size(W,1)
        index = find(Region==i);
        if (~isempty(index))
            Objs_temp  = PopObj_2(index,:);
            Cons_temp  = PopCon(index,:);
            Infeasible = any(Cons_temp>0,2);
            if (sum(Infeasible)~=0)
                F_max = max(Objs_temp,[],1);
                PopObj_2(index(Infeasible),:) = Objs_temp(Infeasible,:)+(sum(max(0,Cons_temp(Infeasible,:)),2)/phi_max).^(exp(para)/max(gamma,0.000001)).*(F_max-Objs_temp(Infeasible,:));
            end
        end
    end

    %% Non-dominated sorting
    Dominate = false(popSize);
    for i = 1 : popSize-1
        for j = i+1 : popSize
            k = any(PopObj_2(i,:)<PopObj_2(j,:)) - any(PopObj_2(i,:)>PopObj_2(j,:));
            if k == 1
                Dominate(i,j) = true;
            elseif k == -1
                Dominate(j,i) = true;
            end
        end
    end

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

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

    %% Calculate the crowding distance of each solution
    PopObj   = Population.objs;
    Distance = pdist2(PopObj,PopObj);
    Distance(logical(eye(length(Distance)))) = inf;
    Distance = sort(Distance,2);
    CrowdDis = Distance(:,floor(sqrt(popSize)));

    %% Add a middle column
    MiddleLevel = zeros(popSize,1);

    %% Environmental selection
    Next = FrontNo == 1;
    if sum(Next) <= N
        [~,indx_Convg] = sortrows([FrontNo',-CrowdDis]);
    elseif sum(Next) > N
        Del  = Truncation(Population(Next).objs,sum(Next)-N);
        Temp = find(Next);
        Next(Temp(Del)) = false;
        MiddleLevel(Temp(Del)) = 1;
        [~,indx_Convg] = sortrows([FrontNo',MiddleLevel,-CrowdDis]);
    end
    RankConvg(indx_Convg) = NumSeq;

    %% Environmental selection -- diversity
    FrontNo_D = ones(popSize,1);
    for i = 1:size(W,1)
        index = find(Region==i);
        if (~isempty(index))
            Objs_temp = PopObj_2(index,:);
            g_temp = sum((Objs_temp-z).*W(i,:),2);
            [~,index_FrontNo_D] = sort(g_temp);
            FrontNo_D(index(index_FrontNo_D)) = (1:length(g_temp))';
        end
    end
    [~,indx_divs] = sortrows([FrontNo_D,-CrowdDis]);
    RankDivs(indx_divs) = NumSeq;

    %% Population for next generation
    RankSolution = alpha*RankConvg+(1-alpha)*RankDivs;
    [~,Rank]     = sort(RankSolution);
    Population   = Population(Rank(1:N));
    RankSolution = 1 : N;
end

function Del = Truncation(PopObj,K)
% Select part of the solutions by truncation

    %% Truncation
    Distance = pdist2(PopObj,PopObj);
    Distance(logical(eye(length(Distance)))) = inf;
    Del = false(1,size(PopObj,1));
    while sum(Del) < K
        Remain   = find(~Del);
        Temp     = sort(Distance(Remain,Remain),2);
        [~,Rank] = sortrows(Temp);
        Del(Remain(Rank(1))) = true;
    end
end


function [M,G]=triSurf2ImSpec(F,V,voxelSize)

% function [M,G,bwLabels]=triSurf2Im(F,V,voxelSize)
% -----------------------------------------------------------------------
% This function converts the input triangulated surface, specified by the
% faces F and the vertices V into an image based on the voxel size
% specified in the input voxelSize. If the latter is empty then the
% voxelSize is based on the maximum edge length. If required the surface is
% resampled to subvoxel resolution using the |subtri| function. Then
% surface vertices are simply mapped to an image coordinate system and
% since they are densely sampled with respect to the voxel size form an
% enclosing boundary of voxels. The exterior, boundary and interior are
% then formulated using the bwlabeln function. The exterior, boundary and
% intertior voxels are labelled using 0's, 1's and 2's in the output image
% M. The second output G is a structure containing the fields G.voxelSize
% and G.origin which form the geometric information for the image.
%
% Kevin Mattheus Moerman
% kevinmoerman@hotmail.com
% 28/08/2013
%------------------------------------------------------------------------

%%
%Checking edge lenghts of surface
TR = triangulation(F,V);
E=edges(TR);
Ed=0;
for q=1:1:size(V,2)
    Ed=Ed+(V(E(:,1),q)-V(E(:,2),q)).^2;
end
edgeLengths=sqrt(Ed);
maxEdgeLength=max(edgeLengths(:));

if isempty(voxelSize)
    voxelSize=maxEdgeLength;
end

%Resample surface if voxelsize is small with respect to edgelenghts
n=maxEdgeLength/voxelSize;
if n>(1-eps(1))
    n=floor(n);
    [~,V]=subtri(F,V,n);
end

%Determine surface set coordinate minima
minV=min(V,[],1);

%Determine shift so all coordinates are positive
imOrigin=-(minV-voxelSize);

%Shift points using origin
V=V+imOrigin(ones(size(V,1),1),:);

%Convert to image coordinates
V_IJK=V;
[V_IJK(:,1),V_IJK(:,2),V_IJK(:,3)]=cart2im(V(:,1),V(:,2),V(:,3),voxelSize*ones(1,3));

%Rounding image coordinates to snap to voxel
V_IJK=round(V_IJK);

%Determin image size
siz=max(V_IJK,[],1)+1;

%Get linear indices of points
indV=sub2ind(siz,V_IJK(:,1),V_IJK(:,2),V_IJK(:,3));

%Create surface boundary image
L=false(siz);
L(indV)=1;

%Create boundary, interior and exterior image
LL = bwlabeln(~L,6); %Get labels for ~L image which will segment interior, exterior and boundary
uniqueLabels=unique(LL(:));

labelsBoundary=LL(L); %The label numbers for the boundary

indExteriorVoxel=1; %First is outside since image is at least a voxel too big on all sides
labelExterior=LL(indExteriorVoxel); %The label number for the exterior

labelsInterior=uniqueLabels(~ismember(uniqueLabels,[labelsBoundary(:); labelExterior])); %Labels for the interior (possibly multiple)

M=zeros(size(L)); %The exterior is set to 0
M(L)=1; %The boundary is set to 1
M(ismember(LL,labelsInterior))=2; %Interior is set to 2

%Storing image geometry metrics
G.voxelSize=voxelSize;
G.origin=imOrigin;

%%
% _*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 [hd_estimates]=hdols123(const,exo,betahat,k,n,p,D,m,T,X,Y,data_exo)

contributors = n + const + length(exo) + 1; %variables + constant + exogenous + initial conditions
hd_estimates=cell(contributors+2,n); %shocks+constant+initial values+exogenous+unexplained+to be explained by shocks only
hd_estimates2=cell(contributors+2,n); %contributors + to be explained by shocks only (unexplained part, other part)

identified=n;

%% compute the historical decomposition, if its not yet computed
%===============================================
%%%%% could take this part from previous computations if possible
Bfull=reshape(betahat,k,n);                    %get the Bfull matrix
B=Bfull(1:n*p,:);                           %drop the coefficients for all exogenous variables from the matrix
B_comp = [B'; eye(n*(p-1)) zeros(n*(p-1),n)];%put into companion form
EPS=Y-X*Bfull;                               %get reduced form residuals
ETA=(D\EPS');                              %get structural shocks

%% Compute historical decompositions
%===============================================

% Contribution of each shock
    aux_D = zeros(n*p,n); %auxilary D matrix, that is consistent with companion matrix
    aux_D(1:n,:) = D; %set the first entrys equal to Dinv
    Selec = [eye(n) zeros(n,(p-1)*n)]; %selection matrix
    HDestimates_store = zeros(p*n,T+1,n); %cell aray to store results
    HDestimates = zeros(n,T+1,n);
    for j=1:n % for each variable %%%%%
        ETA_comp = zeros(n,T+1); % structural shock matrix that is consistent with companion form
        if j <= identified % if j is an identified shock
        ETA_comp(j,2:end) = ETA(j,:); % fill in the entry for shock n, leave the first entry blank
        end
        for i = 2:T+1
            HDestimates_store(:,i,j)=aux_D*ETA_comp(:,i) + B_comp*HDestimates_store(:,i-1,j); %recursively sum over shock impulse at period i on variable j and the previous period
            HDestimates(:,i,j)=Selec*HDestimates_store(:,i,j); %select the entry corresponding to the current period
        end
    end

%% contribution of the initial values
    HDinitial_storage   = zeros(p*n,T+1);
    HDinitial_estimates = zeros(n, T+1);
    Xnoexo = X(:,1:n*p);
    HDinitial_storage(:,1) = Xnoexo(1,:)'; %set the initial values to the first row of X (n*P)+exo
    HDinitial_estimates(:,1) = Selec*HDinitial_storage(:,1); %select the initial values for the first n variables (i.e. the values at Y_{t-1}
    for i = 2:T+1 %loop over periods and compute the impact of the initial conditions recursively
        HDinitial_storage(:,i) = B_comp*HDinitial_storage(:,i-1); %compute the impact of those values (which in principle consist of past shocks)
        HDinitial_estimates(:,i) = Selec*HDinitial_storage(:,i);
    end

if const==1
%%  Contribution of the Constant
    HDconstant_storage = zeros(p*n,T+1);
    HDconstant_estimates = zeros(n, T+1);
    Coefficients = zeros(p*n,1);
        Coefficients(1:n,:) = Bfull(n*p+1,:);
        for i = 2:T+1 %loop over periods
            HDconstant_storage(:,i)=Coefficients+B_comp*HDconstant_storage(:,i-1);
            HDconstant_estimates(:,i)=Selec*HDconstant_storage(:,i);
        end
end
%% Contribution of exogenous variables
 if m > 1
    HDexo_storage = zeros(p*n,T+1);
    HDexo_estimates = zeros(n,T+1);
    Coefficients_exo = zeros(p*n,(m-1)*(1));
    data_exocut=data_exo(p+1:end,:); %cut initial conditions from exogenous
    Coefficients_exo(1:n,:) = Bfull(n*p+const+1:end,:)'; %get the corresponding coefficients
        for i = 2:T+1
            HDexo_storage(:,i)=Coefficients_exo*data_exocut(i-1,:)'+B_comp*HDexo_storage(:,i-1);
            HDexo_estimates(:,i)=Selec*HDexo_storage(:,i);
        end
 end

%% put these values into the corresponding cell for hd_estimates such that
% for variable x (hd_estimates(x,n+1)) = HDinitial_estimates(x,:)
%reorganize storage
        for jj=1:n %for variables
            for kk=1:T+1 %for periods
                for ii=1:n %for shock contributions
                    hd_estimates2{ii,jj}(1,kk)=HDestimates(jj,kk,ii);
                end
                hd_estimates2{n+1,jj}(1,kk)=HDinitial_estimates(jj,kk);
                if const==1
                hd_estimates2{n+2,jj}(1,kk)=HDconstant_estimates(jj,kk);
                end
                if m>1
                hd_estimates2{n+3,jj}(1,kk)=HDexo_estimates(jj,kk);
                end
            end
        end

 HDsum = zeros(T+1,n); %if we sum over all variables this should give Y
 for jj=1:n %loop over variables (columns)
 sumvariable = zeros(1,T+1);
 for kk=1:T+1 %loop over periods
     sumperiod=0;
  for ii=1:contributors %loop over contributors (rows)
      sumperiod=sumperiod+hd_estimates2{ii,jj}(1,kk);
  end
  sumvariable(1,kk)=sumperiod;
 end
 HDsum(:,jj)=sumvariable(1,:);  %%%%% this should be Y?
 end

 %% determine the unexplained part (if model is not fully identified) %%%%% does that mean in IRFt5???
 aux=zeros(1,n);
 unexplained = Y-HDsum(2:end,:);
 unexplained = [aux; unexplained];
for jj=1:n
    hd_estimates2{contributors+1,jj}=unexplained(:,jj)';
end

%% finally substract the sum of the contribution of the (residual?)
%exogenous, constant,initial conditions from Y to get the
%part that was left to be explained by the shocks (for plotting reasons)
 Exosum = zeros(T+1,n); %if we sum over all variables this should give Y
 for jj=1:n %loop over variables (columns)
 sumvariable = zeros(1,T+1);
 for kk=1:T+1 %loop over periods
     sumperiod=0;
  for ii=n+1:contributors %loop over contributors (rows)
      sumperiod = sumperiod+hd_estimates2{ii,jj}(1,kk);
  end
  sumvariable(1,kk)=sumperiod;
 end
 Exosum(:,jj)=sumvariable(1,:);
 end

 %% determine the part that was left to be explained by the shocks
 aux = zeros(1,n);
 tobeexplained = [aux; Y-Exosum(2:end,:)];
for jj=1:n
    hd_estimates2{contributors+2,jj}=tobeexplained(:,jj)';
end

%drop the initial entry for each cell in hd_estimates
for jj=1:n % over variables
    for ii=1:contributors+2 %all contributions
        hd_estimates{ii,jj}=hd_estimates2{ii,jj}(2:end);
    end
end


function errorbar_tick(h,w,xtype)
%ERRORBAR_TICK Adjust the width of errorbars
%   ERRORBAR_TICK(H) adjust the width of error bars with handle H.
%      Error bars width is given as a ratio of X axis length (1/80).
%   ERRORBAR_TICK(H,W) adjust the width of error bars with handle H.
%      The input W is given as a ratio of X axis length (1/W). The result
%      is independent of the x-axis units. A ratio between 20 and 80 is usually fine.
%   ERRORBAR_TICK(H,W,'UNITS') adjust the width of error bars with handle H.
%      The input W is given in the units of the current x-axis.
%
%   See also ERRORBAR
%

% Author: Arnaud Laurent
% Creation : Jan 29th 2009
% MATLAB version: R2007a
%
% Notes: This function was created from a post on the french forum :
% http://www.developpez.net/forums/f148/environnements-developpement/matlab/
% Author : Jerome Briot (Dut)
%   http://www.mathworks.com/matlabcentral/newsreader/author/94805
%   http://www.developpez.net/forums/u125006/dut/
% It was further modified by Arnaud Laurent and Jerome Briot.

% Check numbers of arguments
error(nargchk(1,3,nargin))

% Check for the use of V6 flag ( even if it is depreciated ;) )
flagtype = get(h,'type');

% Check number of arguments and provide missing values
if nargin==1
	w = 80;
end

if nargin<3
   xtype = 'ratio';
end

% Calculate width of error bars
if ~strcmpi(xtype,'units')
    dx = diff(get(gca,'XLim'));	% Retrieve x limits from current axis
    w = dx/w;                   % Errorbar width
end

% Plot error bars
if strcmpi(flagtype,'hggroup') % ERRORBAR(...)

    hh=get(h,'children');		% Retrieve info from errorbar plot
    x = get(hh(2),'xdata');		% Get xdata from errorbar plot

    x(4:9:end) = x(1:9:end)-w/2;	% Change xdata with respect to ratio
    x(7:9:end) = x(1:9:end)-w/2;
    x(5:9:end) = x(1:9:end)+w/2;
    x(8:9:end) = x(1:9:end)+w/2;

    set(hh(2),'xdata',x(:))	% Change error bars on the figure

else  % ERRORBAR('V6',...)

    x = get(h(1),'xdata');		% Get xdata from errorbar plot

    x(4:9:end) = x(1:9:end)-w/2;	% Change xdata with respect to the chosen ratio
    x(7:9:end) = x(1:9:end)-w/2;
    x(5:9:end) = x(1:9:end)+w/2;
    x(8:9:end) = x(1:9:end)+w/2;

    set(h(1),'xdata',x(:))	% Change error bars on the figure

end