filename='RVE_Square_Triangle';
ptype = 'MICRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'circleInclusion';
cost={'enforceCh_CCstar_L2','perimeter'};%enforceCh_CCstar_L2
weights=[1, 0.1];
constraint = {'volumeConstraint'};
optimizer = 'MMA'; incrementFactor = 1;%mma CON 1E-4
filterType = 'P1';

nsteps = 1;
Vfrac_final = 0.5;
Perimeter_target=3;
optimality_final =1e-4;
constr_final =1e-3;

Vfrac_initial = 1;
optimality_initial = 1e-3;
constr_initial = 1e-3;

TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 1/3;
TOL.nu_minus = 1/3;

%Micro
epsilon_isotropy_initial=1e-1;
epsilon_isotropy_final = 1e-3;
selectiveC_Cstar = 'Vfrac05';


function DEM = pad(DEM,varargin)

%PAD add or remove a border of pixels around a GRIDobj
%
% Syntax
%
%     DEMp = pad(DEM);
%     DEMp = pad(DEM,px,val)
%
% Description
%
%     This function adds or removes a border of constant values along all
%     edges of a GRIDobj. By default, pad adds a one-pixel wide border with
%     zeros. To control the value and amount of padding, use the arguments
%     val and px, respectively. px can be negative. In this case, the DEM
%     is cropped by the number of pixels at each grid border.
%
% Input arguments
%
%     DEM     GRIDobj
%     px      amount of padding on each of the four edges of the grid.
%             For px=1 the resulting size of DEMp is DEM.size+2.
%     val     pad value (default=0). This value does not have any effects
%             if px<0.
%
% Output arguments
%
%     DEMp    padded or cropped GRIDobj
%
% Example
%
%     DEM = GRIDobj('srtm_bigtujunga30m_utm11.tif');
%     DEMp20 = pad(DEM,20);
%     DEMm100 = pad(DEM,-100);
%     subplot(1,2,1)
%     imageschs(DEMp20)
%     subplot(1,2,2)
%     imageschs(DEMm100)
%
% See also: GRIDobj/crop, padarray
%
% Author: Wolfgang Schwanghart (w.schwanghart[at]geo.uni-potsdam.de)
% Date: 18. August, 2017

% check input arguments
narginchk(1,3)
p = inputParser;
p.FunctionName = 'GRIDobj/pad';

defaultval = 0;
defaultpx  = 1;
addRequired(p,'DEM')
addOptional(p,'px',defaultpx, @(x) isnumeric(x) && isscalar(x));
addOptional(p,'val',defaultval,@(x) isnumeric(x) && isscalar(x));
parse(p,DEM,varargin{:});

px  = sign(p.Results.px)*ceil(abs(p.Results.px));
val = p.Results.val;

% new size of output grid
newsize = DEM.size + px*2;

% check if size is negative and issue an error
if any(newsize < 0)
    error('the number of pixels removed from the grid edges is too large')
end

% create new array
if val == 0
    Znew = zeros(newsize,class(DEM.Z));
elseif isnan(val)
    Znew = nan(newsize,class(DEM.Z),class(DEM.Z));
else
    Znew = zeros(newsize,class(DEM.Z))+val;
end

% transfer values to new array
if px>0;
    Znew(px+1:end-px,px+1:end-px) = DEM.Z;
elseif px<0;
    abspx = abs(px);
    Znew = DEM.Z(abspx+1:end-abspx,abspx+1:end-abspx);
end

% adjust referencing
DEM.Z           = Znew;
DEM.refmat(3,:) = DEM.refmat(3,:)-px*[DEM.refmat(2,1) DEM.refmat(1,2)];
DEM.size        = size(DEM.Z);

if ~isempty(DEM.georef);
DEM.georef.SpatialRef = refmatToMapRasterReference(DEM.refmat,size(Znew));
end


function t_om_solve_nleqs(quiet)
%T_OM_SOLVE_NLEQS  Tests of NLEQ solvers via OM.SOLVE().

%   MP-Opt-Model
%   Copyright (c) 2010-2020, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MP-Opt-Model.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://github.com/MATPOWER/mp-opt-model for more info.

if nargin < 1
    quiet = 0;
end

core_sp_newton = struct( ...
    'alg',              'NEWTON', ...
    'name',             'Newton''s', ...
    'default_max_it',   10, ...
    'need_jac',         1, ...
    'update_fcn',       @(x, f, J)newton_update_fcn(x, f, J, '')  );
core_sp_gs = struct( ...
    'alg',              'GS', ...
    'name',             'Gauss-Seidel', ...
    'default_max_it',   1000, ...
    'need_jac',         0, ...
    'update_fcn',       @(x, f)x_update_fcn2(x, f)  );

if have_feature('matlab')
    %%  alg         name        check       opts
    cfg = {
        {'DEFAULT', 'default',  []          []  },
        {'NEWTON',  'Newton',   [],         []  },
        {'FD',      'fast-decoupled Newton',[],[]  },
        {'FSOLVE',  'fsolve-1', 'fsolve',   []  },
        {'FSOLVE',  'fsolve-2', 'fsolve',   struct('Algorithm', 'trust-region-dogleg')  },
        {'FSOLVE',  'fsolve-3', 'fsolve',   struct('Algorithm', 'trust-region-reflective')  },
        {'FSOLVE',  'fsolve-4', 'fsolve',   struct('Algorithm', 'levenberg-marquardt', 'TolX', 1e-11) },
        {'GS',      'Gauss-Seidel',[],      []  },
        {'CORE-N',  'Newton-CORE',   [],    core_sp_newton  },
        {'CORE-GS', 'Gauss-Seidel-CORE',[], core_sp_gs  },
    };
    if have_feature('matlab', 'vnum') <= 7.010
        cfg([6]) = [];  %% MATLAB 7.10 does not work w/ fsolve alg 3
    end
else    %% octave
    %%  alg         name        check       opts
    cfg = {
        {'DEFAULT', 'default',  []          []  },
        {'NEWTON',  'Newton',   [],         []  },
        {'FD',      'fast-decoupled Newton',[],[]  },
        {'FSOLVE',  'fsolve', 'fsolve',     struct('TolX', 1e-11)  },
        {'GS',      'Gauss-Seidel',[],      []  },
        {'CORE-N',  'Newton-CORE',   [],    core_sp_newton  },
        {'CORE-GS', 'Gauss-Seidel-CORE',[], core_sp_gs  },
    };
end

n = 18;

t_begin(14+n*length(cfg), quiet);

for k = 1:length(cfg)
    alg   = cfg{k}{1};
    name  = cfg{k}{2};
    check = cfg{k}{3};
    opts  = cfg{k}{4};
    if ~isempty(check) && ~have_feature(check)
        t_skip(n, sprintf('%s not installed', name));
    else
        opt = struct('verbose', 0, 'alg', alg, 'tol', 1e-11);
        switch alg
            case {'DEFAULT', 'NEWTON'}
            case {'FD'}
                opt.fd_opt.jac_approx_fcn = @jac_approx_fcn2;
            case 'FSOLVE'
                opt.fsolve_opt = opts;
            case 'GS'
                opt.gs_opt.x_update_fcn = @(x, f)x_update_fcn2(x, f);
            case {'CORE-N', 'CORE-GS'}
                opt.core_sp = opts;
                opt.alg = 'CORE';
        end

        switch alg
            case {'DEFAULT', 'NEWTON', 'FSOLVE', 'CORE-N'}
                t = sprintf('%s - 2-d function : ', name);
                x0 = [-1;0];
                om = opt_model;
                om.add_var('x', 2, x0);
                om.add_nln_constraint('f', 2, 1, @f1, []);
                [x, f, e, out, jac] = om.solve(opt);
                t_is(e, 1, 12, [t 'success']);
                t_is(x, [-3; 4], 8, [t 'x']);
                t_is(f, 0, 10, [t 'f']);
                switch alg
                    case {'DEFAULT', 'CORE-N'}
                        out_alg = 'NEWTON';
                    otherwise
                        out_alg = alg;
                end
                t_str_match(out.alg, out_alg, [t 'out.alg']);
                eJ = [1 1; 6 1];
                t_is(jac, eJ, 5.8, [t 'jac']);

                t = sprintf('%s - 2-d function (max_it) : ', name);
                opt.max_it = 3;
                [x, f, e, out] = om.solve(opt);
                t_is(e, 0, 12, [t 'no success']);
                t_ok(out.iterations == 3 || out.iterations == 4, [t 'iterations']);
                opt = rmfield(opt, 'max_it');

                t = sprintf('%s - 5-d lin/nonlin function : ', name);
                x0_1 = [-1;0];
                x0_2 = [0;0;0];
                A2 = sparse([2 -1 0; -3 1 -2; 0 5 -4]);
                b2 = [-5; 1; -7];
                x2 = [-2; 1; 3];
                om = opt_model;
                om.add_var('x1', 2, x0_1);
                om.add_var('x2', 3, x0_2);
                om.add_nln_constraint('f', 2, 1, @f1, [], {'x1'});
                om.add_lin_constraint('Ax_b', A2, b2, b2, {'x2'});
                [x, f, e, out, jac] = om.solve(opt);
                t_is(e, 1, 12, [t 'success']);
                t_is(x, [-3; 4; -2; 1; 3], 8, [t 'x']);
                t_is(f, 0, 10, [t 'f']);
                t_str_match(out.alg, out_alg, [t 'out.alg']);
                eJ = [[1 1; 6 1] zeros(2, 3);
                      zeros(3, 2) A2 ];
                t_is(jac, eJ, 5.8, [t 'jac']);
            otherwise
                t_skip(12, sprintf('not implemented for solver ''%s''', alg));
        end

        t = sprintf('%s - 2-d function2 (struct) : ', name);
        x0 = [1;2];
        om = opt_model;
        om.add_var('x', 2, x0);
        om.add_nln_constraint('f', 2, 1, @f2, []);
        [x, f, e] = om.solve(opt);
        t_is(e, 1, 12, [t 'success']);
        t_is(x, [2; 3], 8, [t 'x']);
        t_is(f, 0, 10, [t 'f']);
        t_ok(~isfield(om.soln, 'var'), [t 'no parse_soln() outputs']);

        opt.max_it = 3;
        t = sprintf('%s - 2-d function2 (max_it) : ', name);
        [x, f, e, out] = om.solve(opt);
        t_is(e, 0, 12, [t 'no success']);
        t_ok(out.iterations == 3 || out.iterations == 4, [t 'iterations']);
        opt = rmfield(opt, 'max_it');
    end
end

t = 'om.soln.';
opt.alg = 'DEFAULT';
x0_1 = [-1;0];
x0_2 = [0;0;0];
A2 = sparse([2 -1 0; -3 1 -2; 0 5 -4]);
b2 = [-5; 1; -7];
x2 = [-2; 1; 3];
om = opt_model;
om.add_var('x1', 2, x0_1);
om.add_var('x2', 3, x0_2);
om.add_nln_constraint('f', 2, 1, @f1, [], {'x1'});
om.add_lin_constraint('Ax_b', A2, b2, b2, {'x2'});
opt.parse_soln = 1;
[x, f, e, out, jac] = om.solve(opt);
t_is(om.soln.x, x, 14, [t 'x']);
t_is(om.soln.f, f, 14, [t 'f']);
t_is(om.soln.eflag, e, 14, [t 'eflag']);
t_str_match(om.soln.output.alg, out.alg, [t 'output.alg']);
t_is(om.soln.jac, jac, 14, [t 'jac']);

t = 'om.get_soln(''var'', ''x1'') : ';
t_is(om.get_soln('var', 'x1'), x(1:2), 14, [t 'x1']);

t = 'om.get_soln(''var'', ''x'', ''x2'') : ';
t_is(om.get_soln('var', 'x', 'x2'), x(3:5), 14, [t 'x2']);

t = 'om.get_soln(''lin'', ''g'', ''Ax_b'') : ';
g = om.get_soln('lin', 'g', 'Ax_b');
t_is(g{1}, f(3:5), 14, [t 'A * x - u']);
t_is(g{2}, f(3:5), 14, [t 'l - A * x']);

t = 'om.get_soln(''nle'', ''f'') : ';
g = om.get_soln('nle', 'f');
t_is(g, f(1:2), 14, [t 'f']);

t = 'om.get_soln(''nle'', {''g'', ''dg''}, ''f'') : ';
[g, dg] = om.get_soln('nle', {'g', 'dg'}, 'f');
t_is(g, f(1:2), 14, [t 'f']);
t_is(dg, jac(1:2, 1:2), 14, [t 'jac']);

t = 'parse_soln : ';
t_is(om.soln.var.val.x1, om.get_soln('var', 'x1'), 14, [t 'var.val.x1']);
t_is(om.soln.var.val.x2, om.get_soln('var', 'x2'), 14, [t 'var.val.x2']);

t_end;

%% 2-d problem with 2 solutions
%% from https://www.chilimath.com/lessons/advanced-algebra/systems-non-linear-equations/
function [f, J] = f1(x)
if iscell(x)    %% in case it was part of a varset
    x = x{1};
end
f = [  x(1)   + x(2) - 1;
      -x(1)^2 + x(2) + 5    ];
if nargout > 1
    J = sparse([1 1; -2*x(1) 1]);
end

%% another 2-d problem
%% from Christi Patton Luks, https://www.youtube.com/watch?v=pJG4yhtgerg
function [f, J] = f2(x)
f = [  x(1)^2 +   x(1)*x(2)   - 10;
       x(2)   + 3*x(1)*x(2)^2 - 57  ];
if nargout > 1
    J = sparse([    2*x(1)+x(2)    x(1);
                    3*x(2)^2       6*x(1)*x(2)+1    ]);
end

function JJ = jac_approx_fcn2()
%% for use with fast-decoupled Newton's method
J = [7 2; 27 37];
JJ = {J(1,1), J(2,2)};

function x = x_update_fcn2(x, f)
%% for use with Gauss-Seidel method
x(1) = sqrt(10 - x(1)*x(2));
x(2) = sqrt((57-x(2))/3/x(1));

function x = newton_update_fcn(x, f, J, lin_solver)
dx = mplinsolve(J, -f, lin_solver);     %% compute update step
x = x + dx;                             %% update x


%% Demonstrate use of spm_mix
% Best viewed with MATLAB's "publish" functionality.

%% One-dimensional data, simulated from a three-component mixture
% Fitted with mixtures containing from 1 to 5 components
spm_mix_demo1d(3, 5);

%% Two-dimensional data, simulated from a three-component mixture
% Fitted with a mixture containing 5 components
spm_mix_demo2d


% ALM (Tang and Nehorai 2011)
% process_video('RPCA', 'ALM', 'dataset/demo.avi', 'output/demo_ALM.avi');
[L,S] = alm(M);


classdef ParadigmRSSD2 < ParadigmDataflowSimplified
    % Advanced paradigm for time-varying oscillatory processes.
    %
    % This paradigm allows to learn the joint space/time/frequency structure in EEG, under the
    % assumption that an overcomplete ICA decomposition can produce a reasonably complete coverage
    % of potentially relevant sources. For each of the resulting (more or less independent) source
    % signals, a full time/freq decomposition is computed in the time epoch of interest, and a
    % regression model is learned which maps from the (very high-dimensional) space of these
    % features onto the desired output variable. The regression is by default logistic, and is
    % "rank-sparse" (using the trace norm regularization), meaning that the time/freq weights
    % learned for each signal component will tend to have low rank (reducing the effective
    % # of parameters) and also a sparse set of component signals will have non-zero weights.
    %
    % In addition, a prior can be imposed on the weights, which is parameterized in space (brain area), time, and
    % frequency. This makes the overall model a fairly general-purpose approach to time-varying / non-stationary
    % oscillations.
    %
    % References:
    %  [1] Ryota Tomioka and Klaus-Robert Mueller, "A regularized discriminative framework for EEG analysis with application to brain-computer interface",
    %      Neuroimage, 49 (1) pp. 415-432, 2010.
    %  [2] Ryota Tomioka & Masashi Sugiyama, "Dual Augmented Lagrangian Method for Efficient Sparse Reconstruction",
    %      IEEE Signal Procesing Letters, 16 (12) pp. 1067-1070, 2009.
    %  [3] Makeig S, Debener S, Onton J, Delorme A, "Mining event-related brain dynamics"
    %      Trends in Cognitive Science, 8(5):204-210, 2004.
    %
    % Name:
    %   Regularized Spatio-Spectral Dynamics v2
    %
    %                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
    %                                2011-01-28

    methods
        function defaults = preprocessing_defaults(self)
            defaults = { ...
                'Resampling',128, ...
                'FIRFilter',{[0.5 1],'highpass'}, ...
                'EpochExtraction',[-2 2], ...
                'ICA','beamica', ...
                ...%'DipoleFitting',{'ConfusionRange',7}, ...
                'Projection','on', ...
                'ERSPTransform',{'WindowStep',1/15,'SpectralMap','sqrt'}, ...
                };
        end

        function defaults = machine_learning_defaults(self)
            defaults = {'dal', 2.^(4:-0.25:-3), 'scaling','none'};
            %defaults = {'logreg', 'variant',{'lars','ElasticMixing',0.5}};
        end

        function model = feature_adapt(self,varargin)
            args = arg_define(varargin, ...
                    arg_norep('signal'), ...
                    arg({'spectral_prior','SpectralPrior'},@(f)1,[],'Spectral prior. Likelihood function of frequency in Hz.','guru',true), ...
                    arg({'temporal_prior','TemporalPrior'},@(t)1,[],'Temporal prior. Likelihood function of time in s.','guru',true), ...
                    arg({'spatial_prior','SpatialPrior'},@(p)1,[],'Spatial prior. Likelihood function of MNI coordinate vector.','guru',true), ...
                    arg({'anatomical_prior','AnatomicalPrior'},{'Left Cerebrum','Right Cerebrum','Left Cerebellum','Right Cerebellum','Left Brainstem','Right Brainstem','Inter-Hemispheric'},{'-- Hemispheres --','Left Cerebrum','Right Cerebrum','Left Cerebellum','Right Cerebellum','Left Brainstem','Right Brainstem','Inter-Hemispheric','-- Lobes --','Anterior Lobe','Frontal Lobe','Frontal-Temporal Space','Limbic Lobe','Medulla','Midbrain','Occipital Lobe','Parietal Lobe','Pons','Posterior Lobe','Sub-lobar','Temporal Lobe','-- Gyri --','Angular Gyrus','Anterior Cingulate','Caudate','Cerebellar Lingual','Cerebellar Tonsil','Cingulate Gyrus','Claustrum','Culmen','Culmen of Vermis','Cuneus','Declive','Declive of Vermis','Extra-Nuclear','Fastigium','Fourth Ventricle','Fusiform Gyrus','Inferior Frontal Gyrus','Inferior Occipital Gyrus','Inferior Parietal Lobule','Inferior Semi-Lunar Lobule','Inferior Temporal Gyrus','Insula','Lateral Ventricle','Lentiform Nucleus','Lingual Gyrus','Medial Frontal Gyrus','Middle Frontal Gyrus','Middle Occipital Gyrus','Middle Temporal Gyrus','Nodule','Orbital Gyrus','Paracentral Lobule','Parahippocampal Gyrus','Postcentral Gyrus','Posterior Cingulate','Precentral Gyrus','Precuneus','Pyramis','Pyramis of Vermis','Rectal Gyrus','Subcallosal Gyrus','Sub-Gyral','Superior Frontal Gyrus','Superior Occipital Gyrus','Superior Parietal Lobule','Superior Temporal Gyrus','Supramarginal Gyrus','Thalamus','Third Ventricle','Transverse Temporal Gyrus','Tuber','Tuber of Vermis','Uncus','Uvula','Uvula of Vermis'}, 'Anatomical prior. Select anatomical structures that are likely to contain processes of interest.'),...
                    arg({'vectorize_features','VectorizeFeatures'},true,[],'Vectorize feature tensors. This is for classifiers that cannot handle matrix or tensor-shaped features.'),...
                    arg({'normalize_features','NormalizeFeatures'},true,[],'Normalize time/frequency features. If enabled, features will be normalized by a rank-1 normalization matrix (rather than pixelwise).'));
%
            model = rmfield(args,'signal');
            % determine data rescaling factors
            if args.normalize_features
                tdata = permute(args.signal.data,[1 2 4 3]);
                sdata = permute(args.signal.data,[1 4 2 3]);
                for c=size(args.signal.data,1):-1:1
                    % temporal scale vector
                    temp = 1./median(abs(bsxfun(@minus,tdata(c,:,:),median(tdata(c,:,:),3))),3);
                    % spectral scale vector
                    spec = 1./median(abs(bsxfun(@minus,sdata(c,:,:),median(sdata(c,:,:),3))),3);
                    % time/freq scaling matrix
                    model.scaling(c,:,:) = sqrt(temp')*sqrt(spec);
                end
            end
            % determine model shape
            model.shape = size(args.signal.data);
            model.shape = model.shape([2 4 1]);
        end

        function [features,shape] = feature_extract(self,signal,featuremodel)
            signal.data = permute(signal.data,[1 2 4 3]);
            % optionally apply normalization
            if featuremodel.normalize_features
                features = bsxfun(@times,signal.data,featuremodel.scaling);
            else
                features = signal.data;
            end
            features = permute(features,[2 3 1 4]);
            % determine feature shape
            siz = size(features);
            shape = siz(1:3);
            % do final vectorization if desired
            if featuremodel.vectorize_features
                features = reshape(features,[],signal.trials)'; end
        end

        function layout = dialog_layout_defaults(self)
            layout = {'SignalProcessing.Resampling.SamplingRate','SignalProcessing.FIRFilter.Frequencies', '', ...
                'SignalProcessing.ICA.DataCleaning.DataSetting', '', 'SignalProcessing.ICA.Variant', ...
                'SignalProcessing.EpochExtraction','', ...
                'SignalProcessing.ERSPTransform','', ...
                'Prediction.FeatureExtraction.SpectralPrior', 'Prediction.FeatureExtraction.TemporalPrior', ...
                'Prediction.FeatureExtraction.SpatialPrior','Prediction.FeatureExtraction.AnatomicalPrior', '', ...
                'Prediction.MachineLearning.Learner.Lambdas', 'Prediction.MachineLearning.Learner.LossFunction','Prediction.MachineLearning.Learner.Regularizer'};
        end
    end
end

% TODO: reimplement priors

%         function [featuremodel,conditioningmodel,predictivemodel] = calibrate_prediction_function(self,varargin)
%             args = arg_define(varargin, ...
%                 arg_norep('signal'), ...
%                 arg_sub({'fex','FeatureExtraction'},{},...
%                     {arg({'spectral_prior','SpectralPrior'},@(f)1,[],'Spectral prior. Likelihood function of frequency in Hz.','guru',true), ...
%                      arg({'temporal_prior','TemporalPrior'},@(t)1,[],'Temporal prior. Likelihood function of time in s.','guru',true), ...
%                      arg({'spatial_prior','SpatialPrior'},@(p)1,[],'Spatial prior. Likelihood function of MNI coordinate vector.','guru',true), ...
%                      arg({'anatomical_prior','AnatomicalPrior'},{'Left Cerebrum','Right Cerebrum','Left Cerebellum','Right Cerebellum','Left Brainstem','Right Brainstem','Inter-Hemispheric'},{'-- Hemispheres --','Left Cerebrum','Right Cerebrum','Left Cerebellum','Right Cerebellum','Left Brainstem','Right Brainstem','Inter-Hemispheric','-- Lobes --','Anterior Lobe','Frontal Lobe','Frontal-Temporal Space','Limbic Lobe','Medulla','Midbrain','Occipital Lobe','Parietal Lobe','Pons','Posterior Lobe','Sub-lobar','Temporal Lobe','-- Gyri --','Angular Gyrus','Anterior Cingulate','Caudate','Cerebellar Lingual','Cerebellar Tonsil','Cingulate Gyrus','Claustrum','Culmen','Culmen of Vermis','Cuneus','Declive','Declive of Vermis','Extra-Nuclear','Fastigium','Fourth Ventricle','Fusiform Gyrus','Inferior Frontal Gyrus','Inferior Occipital Gyrus','Inferior Parietal Lobule','Inferior Semi-Lunar Lobule','Inferior Temporal Gyrus','Insula','Lateral Ventricle','Lentiform Nucleus','Lingual Gyrus','Medial Frontal Gyrus','Middle Frontal Gyrus','Middle Occipital Gyrus','Middle Temporal Gyrus','Nodule','Orbital Gyrus','Paracentral Lobule','Parahippocampal Gyrus','Postcentral Gyrus','Posterior Cingulate','Precentral Gyrus','Precuneus','Pyramis','Pyramis of Vermis','Rectal Gyrus','Subcallosal Gyrus','Sub-Gyral','Superior Frontal Gyrus','Superior Occipital Gyrus','Superior Parietal Lobule','Superior Temporal Gyrus','Supramarginal Gyrus','Thalamus','Third Ventricle','Transverse Temporal Gyrus','Tuber','Tuber of Vermis','Uncus','Uvula','Uvula of Vermis'}, 'Anatomical prior. Select anatomical structures that are likely to contain processes of interest.'),...
%                     }, 'Parameters for the feature-adaptation function. These parameters control how features are statistically adapted and extracted from the filtered data before they are passed int othe machine learning stage.'), ...
%                 arg_sub({'cond','Conditioning'},{},@self.feature_adapt_conditioning,'Feature conditioning parameters. Allows to further process features for better usability with classifiers.'), ...
%                 arg_sub({'ml','MachineLearning'},{'Learner',self.machine_learning_defaults()},@ml_train,'Machine learning stage of the paradigm. Operates on the feature vectors that are produced by the feature-extraction stage.'));
%
%             try
%                 data = self.rssd_load_overcomplete(args.signal);
%                 % read out component dipole fits
%                 if ~isempty(data.dipfit)
%                     if isfield(data.dipfit,'multimodel')
%                         dipfits = [data.dipfit.multimodel{:}];
%                     else
%                         dipfits = data.dipfit.model;
%                     end
%                 else
%                     dipfits = [];
%                 end
%                 if ~isempty(args.fex.anatomical_prior) && ~isequal(args.fex.anatomical_prior,false) && ~isempty(dipfits)
%                     % if an anatomical prior was given, we can pre-prune the potenial ERSPs
%                     ersprange = [];
%                     for k=1:size(data.icaweights,1)
%                         matches{k} = intersect(dipfits(k).structures,args.fex.anatomical_prior);
%                         if ~isempty(matches{k})
%                             ersprange(end+1) = k; end
%                     end
%                 else
%                     % otherwise we need to compute them all
%                     ersprange = 1:size(data.icaweights,1);
%                 end
%
%                 % compute ERSPs
%                 disp('Now computing time/frequency decompositions...');
%                 [T,X,freqs,times] = evalc('self.ersp_compute(data,args,ersprange)'); %#ok<ASGLU>
%                 retain_ics = [];
%                 structures = {};
%                 probabilities = [];
%                 summed_probabilities = [];
%                 for k = ersprange
%                     % get left/right normalization vectors lhs/rhs
%                     lhs = args.fex.spectral_prior(freqs) .* sum(reshape(var(X{k},[],2),size(X{k},1),[]),2).^-0.25;
%                     rhs = args.fex.temporal_prior(times) .* sum(reshape(var(X{k},[],1),[],size(X{k},3)),2).^-0.25;
%                     % make sure that they are well-behaved
%                     lhs(~isfinite(lhs)) = 0; medlhs = median(lhs); lhs(lhs>3*medlhs) = medlhs;
%                     rhs(~isfinite(rhs)) = 0; medrhs = median(rhs); rhs(rhs>3*medrhs) = medrhs;
%                     % turn into a scaling matrix
%                     prior{k} =  diag(lhs) * ones(length(freqs),length(times)) * diag(rhs);
%                     % incorporate the spatial prior
%                     if ~isempty(dipfits)
%                         prior{k} = prior{k} * args.fex.spatial_prior(dipfits(k).posxyz); end
%                 end
%                 for k = ersprange
%                     % incorporate the anatomical prior
%                     if ~isempty(args.fex.anatomical_prior) && ~isequal(args.fex.anatomical_prior,false) && ~isempty(dipfits)
%                         [matches,idx] = intersect(dipfits(k).structures,args.fex.anatomical_prior); %#ok<ASGLU>
%                         % sum the probabilities for being in each of the accepted structures (can be > 1 as the structures are highly overlapping)
%                         prior{k} = sum(dipfits(k).probabilities(idx)) * prior{k};
%                         structures{k} = dipfits(k).structures(idx);
%                         probabilities{k} = dipfits(k).probabilities(idx);
%                         summed_probabilities(k) = sum(dipfits(k).probabilities(idx));
%                         % figure; topoplot(data.icawinv(:,k),data.chanlocs(data.icachansind),'electrodes','labels'); title([hlp_tostring(xdipfits(k).structures(idx)) ' - ' hlp_tostring(dipfits(k).probabilities(idx))]);
%                     end
%                     if ~all(all(prior{k}==0))
%                         retain_ics(end+1) = k; end
%                 end
%                 featuremodel.prior = prior;
%                 featuremodel.retain_ics = retain_ics;
%                 featuremodel.args = args;
%                 blocksizes = cellfun(@size,featuremodel.prior,'UniformOutput',false);
%
%                 % update machine learning parameters
%                 args.ml.learner.shape = vertcat(blocksizes{retain_ics}); %vertcat(blocksizes{cellfun(@prod,blocksizes)});
%
%         end
%
%         function features = feature_extract(self,signal,featuremodel)
%             try
%                 data = self.rssd_load_overcomplete(signal);
%                 % compute ERSP features
%                 [T,features] = evalc('self.ersp_compute(data,featuremodel.args,featuremodel.retain_ics)'); %#ok<ASGLU>
%                 % scale each component-ERSP by the respective prior & sparsify
%                 for c=featuremodel.retain_ics
%                     features{c} = bsxfun(@times,features{c},featuremodel.prior{c}); end
%                 % generate block-compressed version of the data
%                 features = reshape([features{featuremodel.retain_ics}],[],data.trials)';
%             catch
%                 disp('Glitch in para_rssd. halting...');
%                 keyboard;
%             end
%         end


function [K] = kv0v0(x, xp, hyp, ubar, vbar, ubarp, vbarp, dt, i)

logsigmau = hyp(1);
logthetau = hyp(2);
logsigmav = hyp(3);
logthetav = hyp(4);

a1 = hyp(5);
a2 = hyp(6);

n_x = size(x,1);
n_xp = size(xp,1);

x = repmat(x,1,n_xp);
xp = repmat(xp',n_x,1);

ubar = repmat(ubar,1,n_xp);
vbar = repmat(vbar,1,n_xp);
ubarp = repmat(ubarp',n_x,1);
vbarp = repmat(vbarp',n_x,1);

switch i

case 0

K=exp(1).^(logsigmav+(-1/2).*exp(1).^((-1).*logthetav).*(x+(-1).*xp).^2)+ ...
  dt.^2.*exp(1).^(logsigmau+(-4).*logthetau+(-1/2).*exp(1).^((-1).* ...
  logthetau).*(x+(-1).*xp).^2).*(a2.*exp(1).^(2.*logthetau).*(ubar.^2+ ...
  vbar.^2).*(a2.*exp(1).^(2.*logthetau).*(ubarp.^2+vbarp.^2)+a1.*((-1).* ...
  exp(1).^logthetau+(x+(-1).*xp).^2))+(-1).*a1.*(a2.*exp(1).^(2.* ...
  logthetau).*(ubarp.^2+vbarp.^2).*(exp(1).^logthetau+(-1).*(x+(-1).*xp) ...
  .^2)+(-1).*a1.*(3.*exp(1).^(2.*logthetau)+(-6).*exp(1).^logthetau.*(x+( ...
  -1).*xp).^2+(x+(-1).*xp).^4)));

case 1 % logsigmau

K=dt.^2.*exp(1).^(logsigmau+(-4).*logthetau+(-1/2).*exp(1).^((-1).* ...
  logthetau).*(x+(-1).*xp).^2).*(a2.*exp(1).^(2.*logthetau).*(ubar.^2+ ...
  vbar.^2).*(a2.*exp(1).^(2.*logthetau).*(ubarp.^2+vbarp.^2)+a1.*((-1).* ...
  exp(1).^logthetau+(x+(-1).*xp).^2))+(-1).*a1.*(a2.*exp(1).^(2.* ...
  logthetau).*(ubarp.^2+vbarp.^2).*(exp(1).^logthetau+(-1).*(x+(-1).*xp) ...
  .^2)+(-1).*a1.*(3.*exp(1).^(2.*logthetau)+(-6).*exp(1).^logthetau.*(x+( ...
  -1).*xp).^2+(x+(-1).*xp).^4)));

case 2 % logthetau

K=dt.^2.*exp(1).^(logsigmau+(-4).*logthetau+(-1/2).*exp(1).^((-1).* ...
  logthetau).*(x+(-1).*xp).^2).*(a2.*exp(1).^(3.*logthetau).*(ubar.^2+ ...
  vbar.^2).*((-1).*a1+2.*a2.*exp(1).^logthetau.*(ubarp.^2+vbarp.^2))+(-1) ...
  .*a1.*exp(1).^logthetau.*(a2.*exp(1).^logthetau.*(ubarp.^2+vbarp.^2).*( ...
  3.*exp(1).^logthetau+(-2).*(x+(-1).*xp).^2)+(-6).*a1.*(exp(1) ...
  .^logthetau+(-1).*(x+(-1).*xp).^2))+2.*a2.*exp(1).^(2.*logthetau).*( ...
  ubar.^2+vbar.^2).*(a2.*exp(1).^(2.*logthetau).*(ubarp.^2+vbarp.^2)+a1.*( ...
  (-1).*exp(1).^logthetau+(x+(-1).*xp).^2))+(a2.*exp(1).^(2.*logthetau).*( ...
  ubar.^2+vbar.^2).*(a2.*exp(1).^(2.*logthetau).*(ubarp.^2+vbarp.^2)+a1.*( ...
  (-1).*exp(1).^logthetau+(x+(-1).*xp).^2))+(-1).*a1.*(a2.*exp(1).^(2.* ...
  logthetau).*(ubarp.^2+vbarp.^2).*(exp(1).^logthetau+(-1).*(x+(-1).*xp) ...
  .^2)+(-1).*a1.*(3.*exp(1).^(2.*logthetau)+(-6).*exp(1).^logthetau.*(x+( ...
  -1).*xp).^2+(x+(-1).*xp).^4))).*((-4)+(1/2).*exp(1).^((-1).*logthetau).* ...
  (x+(-1).*xp).^2));

case 3 % logsigmav

K=exp(1).^(logsigmav+(-1/2).*exp(1).^((-1).*logthetav).*(x+(-1).*xp).^2); ...

case 4 % logthetav

K=(1/2).*exp(1).^(logsigmav+(-1).*logthetav+(-1/2).*exp(1).^((-1).* ...
  logthetav).*(x+(-1).*xp).^2).*(x+(-1).*xp).^2;

case 5 % a1

K=dt.^2.*exp(1).^(logsigmau+(-4).*logthetau+(-1/2).*exp(1).^((-1).* ...
  logthetau).*(x+(-1).*xp).^2).*((-1).*a2.*exp(1).^(2.*logthetau).*( ...
  ubarp.^2+vbarp.^2).*(exp(1).^logthetau+(-1).*(x+(-1).*xp).^2)+a2.*exp(1) ...
  .^(2.*logthetau).*(ubar.^2+vbar.^2).*((-1).*exp(1).^logthetau+(x+(-1).* ...
  xp).^2)+(-1).*a1.*((-3).*exp(1).^(2.*logthetau)+6.*exp(1).^logthetau.*( ...
  x+(-1).*xp).^2+(-1).*(x+(-1).*xp).^4)+a1.*(3.*exp(1).^(2.*logthetau)+( ...
  -6).*exp(1).^logthetau.*(x+(-1).*xp).^2+(x+(-1).*xp).^4));

case 6 % a2

K=dt.^2.*exp(1).^(logsigmau+(-2).*logthetau+(-1/2).*exp(1).^((-1).* ...
  logthetau).*(x+(-1).*xp).^2).*(a2.*exp(1).^(2.*logthetau).*(ubar.^2+ ...
  vbar.^2).*(ubarp.^2+vbarp.^2)+(ubar.^2+vbar.^2).*(a2.*exp(1).^(2.* ...
  logthetau).*(ubarp.^2+vbarp.^2)+a1.*((-1).*exp(1).^logthetau+(x+(-1).* ...
  xp).^2))+(-1).*a1.*(ubarp.^2+vbarp.^2).*(exp(1).^logthetau+(-1).*(x+(-1) ...
  .*xp).^2));

otherwise

        K = zeros(n_x, n_xp);
end

if K == 0

    K = zeros(n_x, n_xp);

end

end


function [ahp, AHP_idp] = idp2ahp(idp)

% IDP2AHP IDP to AHP point transformation.
%   IDP2AHP(IDP) transforms the IDP point into its AHP representation.
%
%   [ahp, AHP_idp] = IDP2AHP(...) returns the Jacobian.

%   Copyright 2010 Joan Sola

x0 = idp(1:3,:);
py = idp(4:5,:);
r = idp(6,:);

if nargout == 1

    ahp = [x0; py2vec(py); r];

else

    if size(idp,2) == 1

        [v,V_py] = py2vec(py);
        ahp = [x0;v;r];
        AHP_idp = [...
            eye(3) zeros(3)
            zeros(3) V_py zeros(3,1)
            zeros(1,5) 1];

    else

        error ('Jacobians not defined for multiple idps.');

    end

end

return

%%
syms x y z e a r real
idp = [x;y;z;e;a;r];
[ahp,AHP_idp] = idp2ahp(idp);

simplify(AHP_idp - jacobian(ahp,idp))

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

%   # START GPL LICENSE

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

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

%   # END GPL LICENSE


function c = clq_containing_nodes(engine, nodes, fam)
% CLQ_CONTAINING_NODES Find the lightest clique (if any) that contains the set of nodes
% c = clq_containing_nodes(engine, nodes, family)
%
% If the optional 'family' argument is specified, it means nodes = family(nodes(end)).
% (This is useful since clq_ass_to_node is not accessible to outsiders.)
% Returns c=-1 if there is no such clique.

if nargin < 3, fam = 0; else fam = 1; end

if length(nodes)==1
  c = engine.clq_ass_to_node(nodes(1));
%elseif fam
%  c = engine.clq_ass_to_node(nodes(end));
else
  B = engine.cliques_bitv;
  w = engine.clique_weight;
  clqs = find(all(B(:,nodes), 2)); % all selected columns must be 1
  if isempty(clqs)
    c = -1;
  else
    c = clqs(argmin(w(clqs)));
  end
end


%% Find a bipolar colormap, linear in grayscale, close to a template map.

%%
% Linearity in gray is important for a colormap to look reasonable when
% printed in grayscale ("black and white"), but note that precise linearity
% depends on the particular (non-unique) choice for conversion from RGB
% values to grayscale brightness/luminance, which would ideally be
% (printing-) device-dependent in this context, and using ICC color
% profiles, etc. In practice, we use a simpler conversion, like rgb2gray,
% (see code comments in colormap_optimization for further details).

%%
% We explore a range of template colormaps, but note that others could be
% better still... In particular, a colormap "dusk" has recently been added
% to real2rgb (see below), which I have not had time to investigate...
% Another area for future work would be a CIELAB-based investigation, see:
%%
% <http://www.mathworks.com/matlabcentral/fileexchange/11037-lab-color-scale>
%%
% <http://en.wikipedia.org/wiki/Lab_color_space>

%% CMRmap from Carey Rappaport
% http://www.mathworks.com/matlabcentral/fileexchange/2662
cmr = [
    0         0         0
    0.1500    0.1500    0.5000
    0.3000    0.1500    0.7500
    0.6000    0.2000    0.5000
    1.0000    0.2500    0.1500
    0.9000    0.5000    0
    0.9000    0.7500    0.1000
    0.9000    0.9000    0.5000
    1.0000    1.0000    1.0000
    ];
cmr = colormap_optimization(cmr); display(cmr)
colormap_visualization(cmr, 1)

%%
% This is nice, but I would argue it is perceptually asymmetric in that
% there is a relatively smooth transition in the positive half, while the
% negative half has a more distinct mauve band around -0.2 to -0.3.

%% Thermal from Oliver Woodford's real2rgb
% http://www.mathworks.com/matlabcentral/fileexchange/23342
therm = thermal(inf); display(therm)
therm = colormap_optimization(therm); display(therm)
colormap_visualization(therm, 1)

%%
% I think this is a really nice bipolar colormap. My only minor quibble
% is that the off-white and off-black ends are not very appealing (to me).
% Note that they are pure white and pure black in Oliver's original thermal
% scheme, but I don't like that, since I want hardcopy to be distinguished
% from any black lines or text labels and from a white background.

%% Based on recommendations in Brewer (1996), but with gray central color
% http://www.ingentaconnect.com/content/maney/caj/1996/00000033/00000002/art00002
brew1 = [
    0.2500         0    0.3333 % purple
    0.5000    0.5000    0.5000 % grey
    1.0000    1.0000    0.1667 % yellow
    ];
brew1 = colormap_optimization(brew1); display(brew1)
colormap_visualization(brew1, 1)

%%
% Although academically well-motivated, I find the single-color transitions
% away from the origin don't seem to make as good use of color to aid
% visualisation compared to some of the other maps here.

%% Based on my adaption of Brewer's (1996) recommendations
% with a neutral central colour, and two colours on each side, which I feel
% better discriminates between values within each of the two halves.
% Brewer (1996) considers issues such as colorblindness, etc. She
% recommends (separately) blue-red and purple-yellow schemes (but not
% blue-purple or red-yellow). The following seems like a reasonable
% compromise given that Brewer's table 2 shows no ideal paths through four
% colors (only a few ideal color-pairs, which sadly cannot be linked up).
brew2 = [
    0.2500         0    0.3333 % purple
    0.0000    0.2500    1.0000 % blue
    0.5000    0.5000    0.5000 % grey
    1.0000    0.2500    0.3333 % red
    1.0000    1.0000    0.1667 % yellow
    ];
brew2 = colormap_optimization(brew2); display(brew2)
brew2fine = colormap_visualization(brew2, 1);

%%
% I am probably biased, but I think the two-color transitions here are
% helpful, and there is reasonable (though not perfect) perceptual symmetry
% between the orange-yellow and blue-purple transitions (if anything, the
% purple transitions a little too sharply near the end, around -0.95). It
% could undoubtedly be improved further, but seems good enough to me...

%% Check linearity in grayscale luminance of raw and interpolated maps
colormap_visualization(brew2, 2)
colormap_visualization(brew2fine, 2)

%%
% See also: colormap_visualization, colormap_optimization, bipolar
%%
% Example:
%  map = bipolar(m, 0.5); % (gives the optimized brew2 that we get here)
%%
% Copyright 2009 Ged Ridgway at gmail com


function M = fixedrankfactory_3factors_preconditioned(m, n, k)
% Manifold of m-by-n matrices of rank k with three factor quotient geometry.
%
% function M = fixedrankfactory_3factors_preconditioned(m, n, k)
%
% This geometry is tuned to least squares problems such as low-rank matrix
% completion with ell-2 loss.
%
% A point X on the manifold is represented as a structure with three
% fields: L, S and R. The matrices L (mxk) and R (nxk) are orthonormal,
% while the matrix S (kxk) is a full rank matrix such that X = L*S*R'.
%
% Tangent vectors are represented as a structure with three fields: L, S
% and R.
%
% Please cite the Manopt paper as well as the research paper:
%     @InProceedings{mishra2014r3mc,
%       Title        = {{R3MC}: A {R}iemannian three-factor algorithm for low-rank matrix completion},
%       Author       = {Mishra, B. and Sepulchre, R.},
%       Booktitle    = {{53rd IEEE Conference on Decision and Control}},
%       Year         = {2014},
%       Organization = {{IEEE CDC}}
%     }
%
%
% See also: fixedrankfactory_3factors fixedrankfactory_2factors_preconditioned

% This file is part of Manopt: www.manopt.org.
% Original author: Bamdev Mishra, Dec. 30, 2012.
% Contributors:
% Change log:
%
%	April 04, 2015 (BM):
%       Cosmetic changes including avoiding storing the inverse of a kxk matrix.

    M.name = @() sprintf('LSR'' (tuned for least square problems) quotient manifold of %dx%d matrices of rank %d', m, n, k);

    M.dim = @() (m+n-k)*k;

    % Some precomputations at the point X that are to be used in the inner product (and
    % pretty much everywhere else).
    function X = prepare(X)
        if ~all(isfield(X,{'StS','SSt'}) == 1)
            X.SSt = X.S*X.S';
            X.StS = X.S'*X.S;
        end
    end

    % The choice of metric is motivated by symmetry and tuned to least square
    % objective function.
    M.inner = @iproduct;
    function ip = iproduct(X, eta, zeta)
        X = prepare(X);

        ip = trace(X.SSt*(eta.L'*zeta.L)) + trace(X.StS*(eta.R'*zeta.R)) ...
            + trace(eta.S'*zeta.S);
    end

    M.norm = @(X, eta) sqrt(M.inner(X, eta, eta));

    M.dist = @(x, y) error('fixedrankfactory_3factors_preconditioned.dist not implemented yet.');

    M.typicaldist = @() 10*k;

    skew = @(X) .5*(X-X');
    symm = @(X) .5*(X+X');

    M.egrad2rgrad = @egrad2rgrad;
    function rgrad = egrad2rgrad(X, egrad)
        X = prepare(X);

        SSL = X.SSt;
        ASL = 2*symm(SSL*(egrad.S*X.S'));

        SSR = X.StS;
        ASR = 2*symm(SSR*(egrad.S'*X.S));

        [BL, BR] = tangent_space_lyap(X.S, ASL, ASR); % It computes the solution without calling Matlab's Lyap.

        rgrad.L = (egrad.L - X.L*BL)/X.SSt;
        rgrad.R = (egrad.R - X.R*BR)/X.StS;
        rgrad.S = egrad.S;

        % Debug
        %         BL1 = lyap(SSL, -ASL); % Alternate way
        %         BR1 = lyap(SSR, -ASR);
        %         norm(skew(X.SSt*(rgrad.L'*X.L) + rgrad.S*X.S'), 'fro')
        %         norm(skew(X.StS*(rgrad.R'*X.R) - X.S'*rgrad.S), 'fro')

    end

    M.ehess2rhess = @ehess2rhess;
    function Hess = ehess2rhess(X, egrad, ehess, eta)
        X = prepare(X);

        % Riemannian gradient.
        SSL = X.SSt;
        ASL = 2*symm(SSL*(egrad.S*X.S'));
        SSR = X.StS;
        ASR = 2*symm(SSR*(egrad.S'*X.S));
        [BL, BR] = tangent_space_lyap(X.S, ASL, ASR);

        rgrad.L = (egrad.L - X.L*BL)/X.SSt;
        rgrad.R = (egrad.R - X.R*BR)/X.StS;
        rgrad.S = egrad.S;

        % Directional derivative of the Riemannian gradient.
        ASLdot = 2*symm((2*symm(X.S*eta.S')*(egrad.S*X.S')) + X.SSt*(ehess.S*X.S' + egrad.S*eta.S')) - 4*symm(symm(eta.S*X.S')*BL);
        ASRdot = 2*symm((2*symm(X.S'*eta.S)*(egrad.S'*X.S)) + X.StS*(ehess.S'*X.S + egrad.S'*eta.S)) - 4*symm(symm(eta.S'*X.S)*BR);

        %         SSLdot = X.SSt;
        %         SSRdot = X.StS;
        %         BLdot = lyap(SSLdot, -ASLdot);
        %         BRdot = lyap(SSRdot, -ASRdot);

        [BLdot, BRdot] = tangent_space_lyap(X.S, ASLdot, ASRdot);

        Hess.L = (ehess.L - eta.L*BL - X.L*BLdot - 2*rgrad.L*symm(eta.S*X.S'))/X.SSt;
        Hess.R = (ehess.R - eta.R*BR - X.R*BRdot - 2*rgrad.R*symm(eta.S'*X.S))/X.StS;
        Hess.S = ehess.S;

        % BM: Till this, everything seems correct.
        % We still need a correction factor for the non-constant metric
        % that is imposed.
        % The computation of the correction factor owes itself to the Koszul formula.
        % This corresponds to the Riemannian connection in the Euclidean space with the
        % scaled metric.
        Hess.L = Hess.L + (eta.L*symm(rgrad.S*X.S') + rgrad.L*symm(eta.S*X.S'))/X.SSt;
        Hess.R = Hess.R + (eta.R*symm(rgrad.S'*X.S) + rgrad.R*symm(eta.S'*X.S))/X.StS;
        Hess.S = Hess.S - symm(rgrad.L'*eta.L)*X.S - X.S*symm(rgrad.R'*eta.R);

        % The Riemannian connection on the quotient space is the
        % projection of the Riemmian connection in the ambient space onto the tangent space of the total space and
        % then onto the horizontal space.
        % This is accomplished by the following operation.
        Hess = M.proj(X, Hess);

        % Debug
        %         norm(skew(X.SSt*(Hess.L'*X.L) + Hess.S*X.S'))
        %         norm(skew(X.StS*(Hess.R'*X.R) - X.S'*Hess.S))

    end

    M.proj = @projection;
    function etaproj = projection(X, eta)
        X = prepare(X);

        % First, projection onto the tangent space of the total space.
        SSL = X.SSt;
        ASL = 2*symm(X.SSt*(X.L'*eta.L)*X.SSt);
        BL = lyap(SSL, -ASL);
        eta.L = eta.L - X.L*(BL/X.SSt);

        SSR = X.StS;
        ASR = 2*symm(X.StS*(X.R'*eta.R)*X.StS);
        BR = lyap(SSR, -ASR);
        eta.R = eta.R - X.R*(BR/X.StS);

        % Project onto the horizontal space
        PU = skew((X.L'*eta.L)*X.SSt) + skew(X.S*eta.S');
        PV = skew((X.R'*eta.R)*X.StS)  + skew(X.S'*eta.S);
        [Omega1, Omega2] = coupled_lyap(X.S, PU, PV);
        %         norm(2*skew(Omega1*X.SSt) - PU -(X.S*Omega2*X.S'),'fro' )
        %         norm(2*skew(Omega2*X.StS) - PV -(X.S'*Omega1*X.S),'fro' )
        %

        etaproj.L = eta.L - (X.L*Omega1);
        etaproj.S = eta.S - (X.S*Omega2 - Omega1*X.S) ;
        etaproj.R = eta.R - (X.R*Omega2);

        % Debug
        %         norm(skew(X.SSt*(etaproj.L'*X.L) + etaproj.S*X.S'))
        %         norm(skew(X.StS*(etaproj.R'*X.R) - X.S'*etaproj.S))
        %
        %         norm(skew(X.SSt*(etaproj.L'*X.L) - X.S*etaproj.S'))
        %         norm(skew(X.StS*(etaproj.R'*X.R) + etaproj.S'*X.S))

    end

    M.tangent = M.proj;
    M.tangent2ambient = @(X, eta) eta;

    M.retr = @retraction;
    function Y = retraction(X, eta, t)
        if nargin < 3
            t = 1.0;
        end

        Y.S = (X.S + t*eta.S);
        Y.L = uf((X.L + t*eta.L));
        Y.R = uf((X.R + t*eta.R));

        Y = prepare(Y);
    end

    M.exp = @exponential;
    function Y = exponential(X, eta, t)
        if nargin < 3
            t = 1.0;
        end
        Y = retraction(X, eta, t);
        warning('manopt:fixedrankfactory_3factors_preconditioned:exp', ...
            ['Exponential for fixed rank ' ...
            'manifold not implemented yet. Used retraction instead.']);
    end

    M.hash = @(X) ['z' hashmd5([X.L(:) ; X.S(:) ; X.R(:)])];

    M.rand = @random;
    % Factors L and R live on Stiefel manifolds, hence we will reuse
    % their random generator.
    stiefelm = stiefelfactory(m, k);
    stiefeln = stiefelfactory(n, k);
    function X = random()
        X.L = stiefelm.rand();
        X.R = stiefeln.rand();
        X.S = diag(1+rand(k, 1));

        X = prepare(X);
    end

    M.randvec = @randomvec;
    function eta = randomvec(X)
        % A random vector on the horizontal space
        eta.L = randn(m, k);
        eta.R = randn(n, k);
        eta.S = randn(k, k);
        eta = projection(X, eta);
        nrm = M.norm(X, eta);
        eta.L = eta.L / nrm;
        eta.R = eta.R / nrm;
        eta.S = eta.S / nrm;
    end

    M.lincomb = @lincomb;

    M.zerovec = @(X) struct('L', zeros(m, k), 'S', zeros(k, k), ...
        'R', zeros(n, k));

    M.transp = @(x1, x2, d) projection(x2, d);

    % vec and mat are not isometries, because of the unusual inner metric.
    M.vec = @(X, U) [U.L(:) ; U.S(:); U.R(:)];
    M.mat = @(X, u) struct('L', reshape(u(1:(m*k)), m, k), ...
        'S', reshape(u((m*k+1): m*k + k*k), k, k), ...
        'R', reshape(u((m*k+ k*k + 1):end), n, k));
    M.vecmatareisometries = @() false;

end

% Linear combination of tangent vectors
function d = lincomb(x, a1, d1, a2, d2) %#ok<INUSL>

    if nargin == 3
        d.L = a1*d1.L;
        d.R = a1*d1.R;
        d.S = a1*d1.S;
    elseif nargin == 5
        d.L = a1*d1.L + a2*d2.L;
        d.R = a1*d1.R + a2*d2.R;
        d.S = a1*d1.S + a2*d2.S;
    else
        error('Bad use of fixedrankfactory_3factors_preconditioned.lincomb.');
    end

end

function A = uf(A)
    [L, unused, R] = svd(A, 0); %#ok
    A = L*R';
end

function[BU, BV] = tangent_space_lyap(R, E, F)
    % We intent to solve a linear system    RR^T  BU + BU RR^T  = E
    %                                       R^T R BV + BV R^T R = F
    % for BU and BV.
    %
    % This can be solved using two calls to the Matlab's lyap.
    % However, we can still have a more efficient implementation
    % that does not require the full functionaliyt of Matlab's lyap.

    [U, Sigma, V] = svd(R);
    E_mod = U'*E*U;
    F_mod = V'*F*V;
    b1 = E_mod(:);
    b2 = F_mod(:);

    r = size(Sigma, 1);
    sig = diag(Sigma); % all the singular values in a vector
    sig1 = sig*ones(1, r); % columns repeat
    sig1t = sig1'; % rows repeat
    s1 = sig1(:);
    s2 = sig1t(:);

    % The block elements
    a =  s1.^2 + s2.^2; % a column vector

    % Solve the linear system of equations
    cu = b1./a; %a.\b1;
    cv = b2./a; %a.\b2;

    % Matricize
    CU = reshape(cu, r, r);
    CV = reshape(cv, r, r);

    % Do the similarity transforms
    BU = U*CU*U';
    BV = V*CV*V';

    % %% Debug
    %
    % norm(R*R'*BU + BU*R*R' - E, 'fro');
    % norm((Sigma.^2)*CU + CU*(Sigma.^2) - E_mod, 'fro');
    % norm(a.*cu - b1, 'fro');
    %
    % norm(R'*R*BV + BV*R'*R - F, 'fro');
    %
    % BU1 = lyap(R*R', - E);
    % norm(R*R'*BU1 + BU1*R*R' - E, 'fro');
    %
    % BV1 = lyap(R'*R, - F);
    % norm(R'*R*BV1 + BV1*R'*R - F, 'fro');
    %
    % % as accurate as the lyap
    % norm(BU - BU1, 'fro')
    % norm(BV - BV1, 'fro')
end

function[Omega1, Omega2] = coupled_lyap(R, E, F)
    % We intent to solve the coupled system of Lyapunov equations
    %
    % RR^T Omega1 + Omega1 RR^T  - R Omega2 R^T = E
    % R^T R Omega2 + Omega1 R^T R  - R^T Omega2 R = F,
    %
    % for Omega1 and Omega2, both are skew symmetric matrices.
    %
    % Below is an efficient implementation

    [U, Sigma, V] = svd(R);
    E_mod = U'*E*U;
    F_mod = V'*F*V;
    b1 = E_mod(:);
    b2 = F_mod(:);

    r = size(Sigma, 1);
    sig = diag(Sigma); % All the singular values in a vector
    sig1 = sig*ones(1, r); % Columns repeat
    sig1t = sig1'; % Rows repeat
    s1 = sig1(:);
    s2 = sig1t(:);

    % The block elements
    a =  s1.^2 + s2.^2; % A column vector
    c = s1.*s2;

    % Solve directly using the formula
    % A = diag(a);
    % C = diag(c);
    % Y1_sol = (A*(C\A) - C) \ (b2 + A*(C\b1));
    % Y2_sol = A\(b2 + C*Y1_sol);

    Y1_sol = (b2 + (a./c).*b1) ./ ((a.^2)./c - c);
    Y2_sol = (b2 + c.*Y1_sol)./a;

    % Matricize
    Omega1 = reshape(Y1_sol, r, r);
    Omega2 = reshape(Y2_sol, r, r);

    % Do the similarity transforms
    Omega1 = U*Omega1*U';
    Omega2 = V*Omega2*V';

    % %% Debug: whether we have the right solution.
    % norm(R*R'*Omega1 + Omega1*R*R'  - R*Omega2*R' - E, 'fro')
    % norm(R'*R*Omega2 + Omega2*R'*R  - R'*Omega1*R - F, 'fro')
end


function p04_title ( )

%*****************************************************************************80
%
%% P04_TITLE prints a title for problem 04.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    None
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'Problem 04\n' );
  fprintf ( 1, '  Name:       HexSum\n' );
  fprintf ( 1, '              Davis, Rabinowitz, page 370, #2.\n' );
  fprintf ( 1, '  Region:     0 <= X(i) <= 1\n' );
  fprintf ( 1, '  Integrand:  F(X) = ( sum ( 2 * X(i) - 1 ) )^6\n' );

  return
end


% eeg_interp_scalp_script - Script to interpolate scalp potentials over mesh
%
% This is part of the development and testing of
% functions to implement:
%
% Oostendorp T, Oosterom A, & Huiskamp G (1989),
% Interpolation on a triangulated 3D surface.
% Journal of Computational Physics, 80: 331-343.
%

% $Revision: 1.1 $ $Date: 2009-04-28 22:13:51 $

% Licence:  GNU GPL, no implied or express warranties
% History:  04/2002, Darren.Weber_at_radiology.ucsf.edu
%           - needs verification and conversion to function
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

clear all

% run R. Oostendorp's script to load simulated data
cd d:\matlab\cvs\eeg_toolbox\lapint
%sphere_load;
%cd ..

% If this script has already been run and the data
% saved, then just load the saved data and return
if isequal(exist('eeg_interp_scalp_mesh_data.mat'),2),
    fprintf('\nLoading saved data.\n');
    load 'eeg_interp_scalp_mesh_data';
    return
end

p = eeg_toolbox_defaults('create');
% Load electrode coordinates 'Cartesian'
p = elec_open(p);
% Load potential values at each electrode
p = eeg_open(p);
% Load a tesselation dataset (scalp, 'skull', cortex)
p = mesh_open(p);

% Find the nearest scalp vertices to each
% electrode vertex
p = mesh_plot(p);
close all

% Extract tesselations from p struct
scalpvert = p.mesh.data.vertices{3};
scalpface = p.mesh.data.faces{3};
elecvert  = p.mesh.data.vertices{4};
elecface  = p.mesh.data.faces{4};

% Extract electric potential at time t for electrodes
Velec = p.volt.data;

clear p;

% This command retains the shape of scalp, while reducing
% the number of faces from ~4000 to 1000.  In doing so, it
% reduces the resolution of the scalp mesh and we need to
% recompute the nearest scalp vertices for each electrode
% vertex below
%[scalpface, scalpvert] = reducepatch(scalpface,scalpvert,1000);

% find the scalp vertex indices for each electrode vertex.
% In this example, this generates replicate indices when
% the reducepatch command above is executed
Scalpindex = dsearchn(scalpvert,elecvert)';

% Calculate the Laplacian matrix
lap = mesh_laplacian(scalpvert,scalpface);

% Calculate interpolation matrix, based on Laplacian
[Lint, keepindex, repindex] = mesh_laplacian_interp(lap,Scalpindex);

% Interpolate potential to scalp
time = 100;
if isempty(repindex),
    Vscalp = Lint * Velec(time,:)';
else
    Vscalp = Lint * Velec(time,keepindex)';
end

%save eeg_interp_scalp_mesh_data

return

% Plot scalp with voltages at all interpolated vertices

fig = figure;
Hp = patch('vertices',scalpvert,'faces',scalpface,'FaceVertexCdata',Vscalp,'facecolor','interp','edgecolor','none');
axis off tight vis3d
lighting gouraud

map = eeg_colormap('Red/Blue/White');
colormap(map)

[az,el] = view;
lit = lightangle(az,el);

set(Hp,'AmbientStrength',.7);
set(Hp,'DiffuseStrength',.3);
set(Hp,'SpecularStrength',0);
set(Hp,'SpecularColorReflectance',0);

%colorbar

% Animation of the timeseries & save movie
set(gcf,'BackingStore','off');
set(Hp,'EraseMode','normal');
figure(fig);
% Define movie region as figure size
rect = get(fig,'Position');
rect(1:2) = [0 0];

clear M

start = 120;
finish = 160;
for t=start:finish,
    Vscalp = Lint * Velec(t,:)';
    set(Hp,'FaceVertexCdata',Vscalp);
    drawnow;
    M(t-(start-1)) = getframe(gcf,rect);
end
% Play the movie in another figure
playtimes = 1;
fps = 15;
figure; axis off; movie(gcf,M,playtimes,fps,rect);
movie2avi(M,'scalp_interpolation.avi','quality',100);

return


classdef PTKVesselness < PTKPlugin
    % PTKVesselness. Plugin for detecting blood vessels
    %
    %     This is a plugin for the Pulmonary Toolkit. Plugins can be run using
    %     the gui, or through the interfaces provided by the Pulmonary Toolkit.
    %     See PTKPlugin.m for more information on how to run plugins.
    %
    %     Plugins should not be run directly from your code.
    %
    %     PTKVesselness computes a mutiscale vesselness filter based on Frangi et
    %     al., 1998. "Multiscale Vessel Enhancement Filtering". The filter
    %     returns a value at each point which in some sense representes the
    %     probability of that point belonging to a blood vessel.
    %
    %     To reduce memory usage, the left and right lungs are filtered
    %     separately and each is further divided into subimages using the
    %     PTKImageDividerHessian function. This will compute the eigenvalues of
    %     the Hessian matrix for each subimage and use these to compute the
    %     vesselness using the PTKComputeVesselnessFromHessianeigenvalues
    %     function.
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2012.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    properties
        ButtonText = 'Vesselness'
        ToolTip = 'Shows the multiscale vesselness filter for detecting blood vessels'
        Category = 'Vessels'
        AllowResultsToBeCached = true
        AlwaysRunPlugin = false
        PluginType = 'ReplaceOverlay'
        HidePluginInDisplay = false
        FlattenPreviewImage = false
        PTKVersion = '1'
        ButtonWidth = 6
        ButtonHeight = 2
        GeneratePreview = true
        Visibility = 'Developer'
    end

    methods (Static)

        function results = RunPlugin(dataset, reporting)

            right_lung = dataset.GetResult('PTKGetRightLungROI');

            reporting.PushProgress;

            reporting.UpdateProgressStage(0, 2);
            vesselness_right = PTKVesselness.ComputeVesselness(right_lung, reporting, false);

            reporting.UpdateProgressStage(1, 2);
            left_lung = dataset.GetResult('PTKGetLeftLungROI');
            vesselness_left = PTKVesselness.ComputeVesselness(left_lung, reporting, true);

            reporting.PopProgress;

            left_and_right_lungs = dataset.GetResult('PTKLeftAndRightLungs');

            results = PTKCombineLeftAndRightImages(dataset.GetTemplateImage(PTKContext.LungROI), vesselness_left, vesselness_right, left_and_right_lungs);

            lung = dataset.GetResult('PTKLeftAndRightLungs');
            results.ChangeRawImage(results.RawImage.*single(lung.RawImage > 0));
            results.ImageType = PTKImageType.Scaled;
        end

        function results = GenerateImageFromResults(results, ~, ~)
            vesselness_raw = 3*uint8(results.RawImage > 5);
            results.ChangeRawImage(vesselness_raw);
            results.ImageType = PTKImageType.Colormap;
        end

    end

    methods (Static, Access = private)

        function vesselness = ComputeVesselness(image_data, reporting, is_left_lung)

            reporting.PushProgress;

            sigma_range = 0.5 : 0.5: 2;
            num_calculations = numel(sigma_range);
            vesselness = [];
            progress_index = 0;
            for sigma = sigma_range
                reporting.UpdateProgressStage(progress_index, num_calculations);
                progress_index = progress_index + 1;

                mask = [];
                vesselness_next = PTKImageDividerHessian(image_data.Copy, @PTKVesselness.ComputeVesselnessPartImage, mask, sigma, [], false, false, is_left_lung, reporting);
                vesselness_next.ChangeRawImage(100*vesselness_next.RawImage);
                if isempty(vesselness)
                    vesselness =  vesselness_next.Copy;
                else
                    vesselness.ChangeRawImage(max(vesselness.RawImage, vesselness_next.RawImage));
                end
            end

            reporting.PopProgress;

        end

        function vesselness_wrapper = ComputeVesselnessPartImage(hessian_eigs_wrapper, voxel_size)
            vesselness_wrapper = PTKComputeVesselnessFromHessianeigenvalues(hessian_eigs_wrapper, voxel_size);
        end

    end
end


function [mesh1,mesh2] = mshSplit(mesh,X0,U)
%+========================================================================+
%|                                                                        |
%|                 OPENMSH - LIBRARY FOR MESH MANAGEMENT                  |
%|           openMsh is part of the GYPSILAB toolbox for Matlab           |
%|                                                                        |
%| COPYRIGHT : Matthieu Aussal (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       : mshSplit.m                                    |
%|    #    |   VERSION    : 0.51                                          |
%|   _#_   |   AUTHOR(S)  : Matthieu Aussal                               |
%|  ( # )  |   CREATION   : 14.03.2019                                    |
%|  / 0 \  |   LAST MODIF : 21.06.2019                                    |
%| ( === ) |   SYNOPSIS   : Split mesh with planar cut                    |
%|  `---'  |                (to be clearly improved)                      |
%+========================================================================+

% Normalize direction
N = U./norm(U);

% Split mesh
lambda = (mesh.ctr-ones(length(mesh),1)*X0) * N';
ind    = (lambda>0);
mesh1  = mesh.sub(ind);
mesh2  = mesh.sub(~ind);

% Extract free boundary
bound  = mesh1.bnd;
mu     = (bound.vtx-ones(size(bound.vtx,1),1)*X0) * N';

% Move upper boundary
[~,IA] = intersect(msh(mesh1.vtx),msh(bound.vtx));
mesh1.vtx(IA,:) = mesh1.vtx(IA,:) - mu*N;

% Move lower boundary
[~,IA] = intersect(msh(mesh2.vtx),msh(bound.vtx));
mesh2.vtx(IA,:) = mesh2.vtx(IA,:) - mu*N;
end


function Y=plot(varargin)
%PLOT (overloaded)

% Fast version for plotting simple PWA objects
if nargin == 1
    X = varargin{1};
    if isa(varargin{1},'sdpvar')
        if length(X) == 1
            if isequal(full(getbase(X)),[0 1])
                extstruct = yalmip('extstruct',getvariables(X));
                if ~isempty(extstruct)
                    if isequal(extstruct.fcn,'pwa_yalmip') | isequal(extstruct.fcn,'pwq_yalmip')%#ok
                        switch extstruct.arg{3}
                            case ''
                            otherwise
                                Pn = polytope; Bi = {}; Ci = {};
                                index = extstruct.arg{5};
                                for i = 1:length(extstruct.arg{1})
                                    % Pick out row
                                    for j = 1:length(extstruct.arg{1}{i}.Bi)
                                        extstruct.arg{1}{i}.Bi{j} = extstruct.arg{1}{i}.Bi{j}(index,:);
                                        extstruct.arg{1}{i}.Ci{j} = extstruct.arg{1}{i}.Ci{j}(index,:);
                                    end
                                    if isempty(extstruct.arg{1}{i}.Ai{1})
                                        Pn = [Pn extstruct.arg{1}{i}.Pn];
                                        Bi = cat(2, Bi, extstruct.arg{1}{i}.Bi);
                                        Ci = cat(2, Ci, extstruct.arg{1}{i}.Ci);
                                    else
                                        if nnz([extstruct.arg{1}{i}.Ai{:}]) == 0
                                            Pn = [Pn extstruct.arg{1}{i}.Pn];
                                            Bi = cat(2, Bi, extstruct.arg{1}{i}.Bi);
                                            Ci = cat(2, Ci, extstruct.arg{1}{i}.Ci);
                                        else

                                            hold on
                                            mpt_plotPWQ(extstruct.arg{1}{i}.Pn, ...
                                                extstruct.arg{1}{i}.Ai, ...
                                                extstruct.arg{1}{i}.Bi, ...
                                                extstruct.arg{1}{i}.Ci, []);
                                            hold off
                                        end
                                    end
                                end
                                if ~isempty(Bi),
                                    mpt_plotPWA(Pn, Bi, Ci);
                                end
                                drawnow
                                return
                        end
                    end
                end
            end
        end
    end
end

% More complex expression. Get epi-graph model
% project to our variables, and extract defining facets
if nargin == 1
    [p,Bi,Ci,Pn,Pfinal] = pwa(varargin{1});%#ok
elseif isa(varargin{2},'lmi')
    [p,Bi,Ci,Pn,Pfinal] = pwa(varargin{1},varargin{2});%#ok
else
    error('Second argument should be a domain defining SET object.');
end
if nargout>0
    Y = mpt_plotPWA(Pn,Bi,Ci);
else
    mpt_plotPWA(Pn,Bi,Ci);
end

function S = extractrow(S,index)
for i = 1:length(S)
    S{i} = S{i}(index,:);
end


function p02_story ( )

%*****************************************************************************80
%
%% P02_STORY prints the "story" for problem p02.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 August 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    ETY Lee,
%    Choosing Nodes in Parametric Curve Interpolation,
%    Computer-Aided Design,
%    Volume 21, Number 6, July/August 1989, pages 363-370.
%
%  Parameters:
%
%    None
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  This example is due to ETY Lee of Boeing.\n' );
  fprintf ( 1, '  Data near the corners is more dense than in regions of small curvature.\n' );
  fprintf ( 1, '  A local interpolation method will produce a more plausible\n' );
  fprintf ( 1, '  interpolant than a nonlocal interpolation method, such as\n' );
  fprintf ( 1, '  cubic splines.\n' );

  return
end


%% Work out the eye scaling first using the PDM
addpath('../PDM_helpers/');
% also work out a size for each window
% Replace this with the location of in 300 faces in the wild data
if(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
    root_test_data = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
else
    root_test_data = 'F:/Dropbox/Dropbox/AAM/test data/';
end

[~, detections, labels] = Collect_wild_imgs(root_test_data, true, true, true, true);

% load('../models/pdm/pdm_68_multi_pie');
load('../models/pdm/pdm_68_aligned_wild');

%%
shapes = zeros(size(labels));
num_points = 68;

for i=1:size(labels,1)

    [ a_orig, R, ~, ~, ~, ~] = fit_PDM_ortho_proj_to_2D(M, E, V, squeeze(labels(i,:,:)));
    view_actual = Rot2Euler(R);

    views = [0,0,0; 0,-30,0; -30,0,0; 0,30,0; 30,0,0];
    views = views * pi/180;

    [~,view_id] = min(sum(abs(bsxfun(@plus, views, -view_actual)), 2));

    rot = Euler2Rot(views(view_id,:));

    rot_m = rot * reshape(M, num_points, 3)';
    width_model = max(rot_m(1,:)) - min(rot_m(1,:));
    height_model = max(rot_m(2,:)) - min(rot_m(2,:));

    bounding_box = detections(i,:);

    a = (((bounding_box(3) - bounding_box(1)) / width_model) + ((bounding_box(4) - bounding_box(2))/ height_model)) / 2;

    tx = (bounding_box(3) + bounding_box(1))/2;
    ty = (bounding_box(4) + bounding_box(2))/2;

    % correct it so that the bounding box is just around the minimum
    % and maximum point in the initialised face
    tx = tx - a*(min(rot_m(1,:)) + max(rot_m(1,:)))/2;
    ty = ty - a*(min(rot_m(2,:)) + max(rot_m(2,:)))/2;

    % visualisation of the initial state
    %hold off;imshow(Image);hold on;plot(a*rot_m(1,:)+tx, a*rot_m(2,:)+ty,'.r');hold on;rectangle('Position', [bounding_box(1), bounding_box(2), bounding_box(3)-bounding_box(1), bounding_box(4)-bounding_box(2)]);
    global_params = [a, 0, 0, 0, tx, ty]';
    global_params(2:4) = views(view_id);

    local_params = zeros(numel(E), 1);

    shape = GetShapeOrtho(M, V, local_params, global_params);
    shape = shape(:,1:2);
    shapes(i,:,:) = shape;

    shapes(i,:,:) = shapes(i,:,:) / a_orig;
    labels(i,:,:) = labels(i,:,:) / a_orig;

end

%%
errs_img = sort(squeeze(mean(mean(abs(labels - shapes), 2), 3)));

errs_lmk = squeeze(mean(mean(abs(labels - shapes), 1), 3));

errs_img_95 = errs_img(round(0.95*end));

scales = [0.25, 0.35, 0.5];

windows = floor(errs_img_95 * 2 * scales + 11) + 1


function [mGrid]=calc_SynRateGrid(nNeqM4,fMinLon,fMaxLon,fMinLat,fMaxLat,dfLon,dfLat,nMode,mCat)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Example: [mGrid] = calc_SynRateGrid(12,-118.2,-114.5,32.1,36.1,0.25,0.25,2,a);
%
% This function (calc_SynRateGrid) calculates the rates on the grid for the
% background rate used for calc_SynCat (program package ETESProject by karen
% Felzer was used.)
%
% Author: van Stiphout, Thomas
% Email: vanstiphout@sed.ethz.ch
% Created: 12. Nov 2007
% Changed: -
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Variables
% Input:
% nNeqM4         No. of Events with greater M>=4 eqs/year
% fMinLon    Min Longitude of rate grid
% fMaxLon    Max Longitude of rate grid
% fMinLat    Min Latitude of rate grid
% fMaxLat    Max Latitiude of rate grid
% dfLon      discretization for Longitude grid
% dfLat      discretization for Latitude grid
% nMode      rate grid mode 1: uniform rate, 2: rate according to real data
%              3: probability of an earthquake to occure in this polygon
%
% Output:
% SynCat Simulated ETES catalog [yr lon lat month day mag depth hrs min sec]
% vMain            Vector with assignments if main (=1) or aftershock (=0)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

vLon=[fMinLon:dfLon:fMaxLon]';
vLat=[fMinLat:dfLat:fMaxLat]';

for i=1:size(vLon,1)-1
    for j=1:size(vLat,1)-1
        mGrid((i-1)*(size(vLat,1)-1)+j,1:4)=[vLon(i),vLon(i+1), vLat(j),vLat(j+1)];
    end
end

% switch btw different rategrids (uniform (nMode = 1)  according to real
% data (n Mode = 2)
switch nMode
    case 1
        mGrid(:,5)=nNeqM4/size(mGrid,1);
    case 2
        nNeqM4=sum(mCat(:,6)>=4)/(max(mCat(:,3))-min(mCat(:,3)))
        for i=1:size(mGrid)
            mGrid_sum(i)= sum(mCat(:,1)>=mGrid(i,1) & mCat(:,1)<mGrid(i,2) & ...
                mCat(:,2)>=mGrid(i,3) & mCat(:,2)<mGrid(i,4));
        end
        % normalize values in mGrid_sum
        mGridNorm=mGrid_sum/sum(mGrid_sum);
        mGrid(:,5)=nNeqM4*mGridNorm;
    case 3
%         nNeqM4=sum(mCat(:,6)>=4)/(max(mCat(:,3))-min(mCat(:,3)))
        for i=1:size(mGrid)
            mGrid_sum(i)= sum(mCat(:,1)>=mGrid(i,1) & mCat(:,1)<mGrid(i,2) & ...
                mCat(:,2)>=mGrid(i,3) & mCat(:,2)<mGrid(i,4));
        end
        % normalize values in mGrid_sum
        mGridNorm=mGrid_sum/max(mGrid_sum);
        mGrid(:,5)=mGridNorm;
end


classdef ZeroLinePlotAdder < handle

    properties (Access = private)
        x
        y
        z
        figID
        meshBackground
        unfittedMesh
    end

    methods (Access = public)

        function obj = ZeroLinePlotAdder(cParams)
            obj.init(cParams);
        end

        function addLine(obj)
            obj.createMeshBackground();
            obj.createUnfittedMesh();
            obj.plotLine();
        end
    end

    methods (Access = private)

        function init(obj,cParams)
            obj.x = cParams.x;
            obj.y = cParams.y;
            obj.z = cParams.z;
            obj.figID = cParams.figID;
        end

        function createMeshBackground(obj)
            [xp,yp] = meshgrid(obj.x,obj.y);
            xp = xp(:);
            yp = yp(:);
            tri = delaunay(xp,yp);
            s.coord = [xp yp];
            s.connec = tri;
            mesh = Mesh_Total(s);
            obj.meshBackground = mesh;
        end

        function createUnfittedMesh(obj)
            s.meshBackground = obj.meshBackground;
            s.backgroundMesh = obj.meshBackground.innerMeshOLD;
            s.boundaryMesh   = obj.meshBackground.boxFaceMeshes;
            s.unfittedType   = 'BOUNDARY';
            s.isInBoundary = false;
            cParams = SettingsMeshUnfitted(s);
            uMesh = UnfittedMesh(cParams);
            levelSet = obj.z;
            uMesh.compute(levelSet);
            obj.unfittedMesh = uMesh;
        end

        function plotLine(obj)
            figure(obj.figID)
            patch('vertices',obj.unfittedMesh.coord,...
                  'faces',obj.unfittedMesh.connec,...
                  'edgecolor',[0.5 0 0],...
                   'edgealpha',0.5,...
                   'edgelighting','flat',...
                   'facecolor',[1 0 0],...
                   'facelighting','flat',...
                   'LineWidth',6)
            axis('equal')
        end

    end

end


function h = times(f,g)
% .*    Pointwise multiplication for SPHEREFUN objects.
%
%   F.*G multiplies SPHEREFUN objects F and G. Alternatively F or G could be a
%   double.

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

if ( isa(f, 'spherefun') && isa(g, 'spherefun') )
    % Grady's faster times for rank 1 functions:
    if ( length( f ) == 1 )
        [C, D, R] = cdr( f );
        h = g;
        onesForC = sqrt(abs(D))*ones(1,length(g));
        onesForR = sign(D)*onesForC;
        h.cols = (C*onesForC).*g.cols;
        h.rows = (R*onesForR).*g.rows;
        % Switch the parity terms if needed:
        % plus*plus = plus -> do nothing
        % plus*minus = minus -> do nothing
        % minus*minus = plus -> switch minus to plus
        % minus*plus = minus -> switch plus to minus
        if ( isempty( f.idxPlus ) )  % f is a minus
            h.idxMinus = g.idxPlus;
            h.idxPlus = g.idxMinus;
        end
        % Both terms have to be non-zero at the poles for the product to be
        % non-zero at the poles.
        h.nonZeroPoles = f.nonZeroPoles & g.nonZeroPoles;
    elseif ( length( g ) == 1 )
         h = times(g, f);
    else
        % Let separableApprox deal with the multiplication
        h = times@separableApprox(f,g);
    end
else
    % Let separableApprox deal with the multiplication
    h = times@separableApprox(f,g);
end

end


classdef nnconvt < nntest
  properties (TestParameter)
    depth = {1 2 3}
    numImages = {1 2 3 4}
    numFilters = {1 2 3}
    upx = {1 2 3}
    upy = {1 2 3}
    padx1 = {1 2 3}
    padx2 = {1 2 3}
    pady1 = {1 2 3}
    pady2 = {1 2 3}
    up = {1 2}
    fsx = {1 2}
    crop = {1 2 3 4 5 6 7 8}
    numGroups = {1 2 3}
  end

  methods (Test)
    function basic(test, depth, numImages, numFilters)
      m = depth ;
      n = numImages ;
      k = numFilters;
      x = test.randn(10,12,m,n) ;
      f = test.randn(3,4,k,m) ;
      b = test.randn(1,k) ;
      y = vl_nnconvt(x,f,b) ;
      dzdy = test.randn(size(y)) ;
      [dzdx,dzdf,dzdb] = vl_nnconvt(x,f,b,dzdy) ;
      test.der(@(x) vl_nnconvt(x,f,b), x, dzdy, dzdx, test.range * 1e-2) ;
      test.der(@(f) vl_nnconvt(x,f,b), f, dzdy, dzdf, test.range * 1e-2) ;
      test.der(@(b) vl_nnconvt(x,f,b), b, dzdy, dzdb, test.range) ;
    end

    function upsample_crop(test,upx,upy,padx1,pady1,padx2,pady2)
      m = 3 ; n = 2 ; k = 3;
      opts = {'upsample',[upy upx],'crop',[pady1 pady2 padx1 padx2]} ;
      x = test.randn(5,6,m,n) ;
      f = test.randn(3,4,k,m) ;
      b = test.randn(1,k) ;
      y = vl_nnconvt(x,f,b,opts{:}) ;
      dzdy = test.randn(size(y)) ;
      [dzdx,dzdf,dzdb] = vl_nnconvt(x,f,b,dzdy,opts{:}) ;
      test.der(@(x) vl_nnconvt(x,f,b,opts{:}), x, dzdy, dzdx, test.range * 1e-2) ;
      test.der(@(f) vl_nnconvt(x,f,b,opts{:}), f, dzdy, dzdf, test.range * 1e-2) ;
      test.der(@(b) vl_nnconvt(x,f,b,opts{:}), b, dzdy, dzdb, test.range) ;
    end

    function grouped_filters(test, numGroups, depth, numFilters)
      ng = numGroups ;
      m = depth ;
      k = numFilters ;
      n = 3 ;
      opts = {'numgroups',ng} ;
      x = test.randn(10,12,m*ng,n) ;
      f = test.randn(3,4,k,m*ng) ;
      b = test.randn(1,k*ng) ;
      y = vl_nnconvt(x,f,b,opts{:}) ;
      dzdy = test.randn(size(y)) ;
      [dzdx,dzdf,dzdb] = vl_nnconvt(x,f,b,dzdy,opts{:}) ;
      test.der(@(x) vl_nnconvt(x,f,b,opts{:}), x, dzdy, dzdx, test.range * 1e-2) ;
      test.der(@(f) vl_nnconvt(x,f,b,opts{:}), f, dzdy, dzdf, test.range * 1e-2) ;
      test.der(@(b) vl_nnconvt(x,f,b,opts{:}), b, dzdy, dzdb, test.range) ;
    end

    function one_one_image(test,up,fsx,crop)
      fsx = fsx*up ;
      if crop > fsx-1, return ; end
      m = 3 ;
      n = 4 ;
      k = 3 ;
      fsy = fsx * 3 ;
      x = test.randn(1,1,m,n) ;
      f = test.randn(fsy,fsx,k,m) ;
      b = test.randn(1,k) ;
      croph = floor(crop/2) ;
      opts = {'crop', [croph, crop-croph, croph, crop-croph], 'upsample', [up up]} ;
      y = vl_nnconvt(x,f,b,opts{:}) ;
      dzdy = test.randn(size(y)) ;
      [dzdx,dzdf,dzdb] = vl_nnconvt(x,f,b,dzdy,opts{:}) ;
      test.der(@(x) vl_nnconvt(x,f,b,opts{:}), x, dzdy, dzdx, test.range * 1e-2) ;
      test.der(@(f) vl_nnconvt(x,f,b,opts{:}), f, dzdy, dzdf, test.range * 1e-2) ;
      test.der(@(b) vl_nnconvt(x,f,b,opts{:}), b, dzdy, dzdb, test.range * 1e-1) ;
    end

    function test_gpu_correctnes(test)
      if ~strcmp(test.currentDevice, 'gpu'), return ; end
      opts = {...
        {'crop', [0 0 0 0], 'upsample', [1 1]}, ...
        {'crop', [5 5 8 8], 'upsample', [1 1]}, ...
        {'crop', [5 5 8 8], 'upsample', [3 2]}} ;

      variants = {{'nocudnn'}, ...
                  {'cudnn', 'cudnnworkspacelimit', 0}, ...
                  {'cudnn', 'cudnnworkspacelimit', +inf}} ;

      fh = 11 ;
      fw = 11 ;
      fn = 10 ;
      n = 32 ;
      depth = 32 ;
      x = test.randn(32,32,depth,n) ;
      w = test.randn(fh,fw,fn,depth) ;
      b = test.randn(1,fn) ;

      for o = 1:numel(opts)
        for v = 1:numel(variants)
          %args = horzcat(variants{v}, opts{o}, {'verbose'}) ;
          args = horzcat(variants{v}, opts{o}) ;
          y = vl_nnconvt(x,w,b,args{:}) ;
          dzdy = test.randn(size(y)) ;
          [dzdx,dzdw,dzdb] = vl_nnconvt(x,w,b,dzdy,args{:}) ;

          dzdy_ = gather(dzdy) ;
          y_ = vl_nnconvt(gather(x), gather(w), gather(b), opts{o}{:}) ;
          [dzdx_,dzdw_,dzdb_] = vl_nnconvt(gather(x),gather(w),gather(b), ...
                                           gather(dzdy), opts{o}{:}) ;

          test.eq(y, y_) ;
          test.eq(dzdx, dzdx_) ;
          test.eq(dzdw, dzdw_) ;
          test.eq(dzdb, dzdb_) ;
        end
      end
    end

  end
end


function [quality probs] = biqi(im)

%========================================================================
%
% -----------COPYRIGHT NOTICE STARTS WITH THIS LINE------------
% Copyright (c) 2009 The University of Texas at Austin
% All rights reserved.
%
% Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy,
% modify, and distribute this code (the source files) and its documentation for
% any purpose, provided that the copyright notice in its entirety appear in all copies of this code, and the
% original source of this code, Laboratory for Image and Video Engineering (LIVE, http://live.ece.utexas.edu)
% and Center for Perceptual Systems (CPS, http://www.cps.utexas.edu) at the University of Texas at Austin (UT Austin,
% http://www.utexas.edu), is acknowledged in any publication that reports research using this code. The research
% is to be cited in the bibliography as:
%
% 1. A. K. Moorthy and A. C. Bovik, "A Modular Framework for Constructing Blind
% Universal Quality Indices", submitted to IEEE Signal Processing Letters (2009).
%
% 2. A. K. Moorthy and A. C. Bovik, "BIQI Software Release",
% URL: http://live.ece.utexas.edu/research/quality/biqi.zip, 2009.
%
% IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT AUSTIN BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
% OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS DATABASE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF TEXAS
% AT AUSTIN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%
% THE UNIVERSITY OF TEXAS AT AUSTIN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
% WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE DATABASE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
% AND THE UNIVERSITY OF TEXAS AT AUSTIN HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
%
% -----------COPYRIGHT NOTICE ENDS WITH THIS LINE------------%

%Author  : Anush Krishna Moorthy
%Version : 1.0
%
%The authors are with the Laboratory for Image and Video Engineering
%(LIVE), Department of Electrical and Computer Engineering, The
%University of Texas at Austin, Austin, TX.
%
%Kindly report any suggestions or corrections to anushmoorthy@gmail.com
%
%========================================================================
%
% This is a demonstration of the Blind Image Quality Index (BIQI) .
% It is an implementation of the BIQI in the reference.
% The algorithm is described in:
% A. K. Moorthy and A. C. Bovik, "A Modular Framework for Constructing Blind
% Universal Quality Indices", submitted to IEEE Signal Processing Letters (2009).
%
%You can change this program as you like and use it anywhere, but please
%refer to its original source (cite our paper and our web page at
% http://live.ece.utexas.edu/research/quality/biqi.zip).
%
%Input : A test 8bits/pixel grayscale image loaded in a 2-D array
%Output: A quality score of the image. The score typically has a value
%        between 0 and 100 (0 represents the best quality, 100 the worst).
%
%Usage:
%
%1. Load the image, for example
%
%   image = rgb2gray(imread('testimage.jpg'));
%
%2. Call this function to calculate the quality score:
%
%    quality = biqi(image)
%
% Dependencies:
% MATLAB Wavelet  Toolbox
% You may need the MATLAB Image Processing Toolbox
% Binaries: svm-train, svm-scale (from LibSVM) - provided with release
% Other m files: jpeg_quality_score.m (provided with release)
% Data files: range2, range2_wn, range2_blur, range2_jp2k, model_89,
% model_89_wn, model_89_blur, model_89_jp2k, rang2_ff model_ff
%========================================================================

import biqi.*

if(size(im,3)~=1)
    im = rgb2gray(im);
end

%% First compute statistics
num_scales = 3; % somethings are hardcoded for this...please be careful when changing.
gam = 0.2:0.001:10;
r_gam = gamma(1./gam).*gamma(3./gam)./(gamma(2./gam)).^2;

[C S] = wavedec2(im,num_scales,'db9');
for p = 1:num_scales
    [horz_temp,vert_temp,diag_temp] = detcoef2('all',C,S,p) ;
    horz(p) = {[horz_temp(:)]};
    diag(p) = {[diag_temp(:)]};
    vert(p) = {[vert_temp(:)]};

    h_horz_curr  = cell2mat(horz(p));
    h_vert_curr  = cell2mat(vert(p));
    h_diag_curr  = cell2mat(diag(p));

    mu_horz(p) = mean(h_horz_curr);
    sigma_sq_horz(p)  = mean((h_horz_curr-mu_horz(p)).^2);
    E_horz = mean(abs(h_horz_curr-mu_horz(p)));
    rho_horz = sigma_sq_horz(p)/E_horz^2;
    [min_difference, array_position] = min(abs(rho_horz - r_gam));
    gam_horz(p) = gam(array_position);

    mu_vert(p) = mean(h_vert_curr);
    sigma_sq_vert(p)  = mean((h_vert_curr-mu_vert(p)).^2);
    E_vert = mean(abs(h_vert_curr-mu_vert(p)));
    rho_vert = sigma_sq_vert(p)/E_vert^2;
    [min_difference, array_position] = min(abs(rho_vert - r_gam));
    gam_vert(p) = gam(array_position);

    mu_diag(p) = mean(h_diag_curr);
    sigma_sq_diag(p)  = mean((h_diag_curr-mu_diag(p)).^2);
    E_diag = mean(abs(h_diag_curr-mu_diag(p)));
    rho_diag = sigma_sq_diag(p)/E_diag^2;
    [min_difference, array_position] = min(abs(rho_diag - r_gam));
    gam_diag(p) = gam(array_position);
end
rep_vec = [mu_horz mu_vert mu_diag sigma_sq_horz sigma_sq_vert sigma_sq_diag gam_horz gam_vert gam_diag];
rep_vec(:,1:9) = []; % remove the means...
%% Now classify

fid = fopen('test_ind.txt','w')
for j = 1:size(rep_vec,1)
    fprintf(fid,'%d ',j);
    for k = 1:size(rep_vec,2)
        fprintf(fid,'%d:%f ',k,rep_vec(j,k));
    end
    fprintf(fid,'\n');
end
fclose(fid);

system(['/usr/local/Cellar/libsvm/3.22/bin/svm-scale -r +biqi/range2 test_ind.txt >> test_ind_scaled']);
system(['/usr/local/Cellar/libsvm/3.22/bin/svm-predict -b 1 test_ind_scaled +biqi/model_89 output_89']);
delete test_ind.txt test_ind_scaled

%% Quality along each dimension

% Write out SVM compatible

fid = fopen('test_ind.txt','w');
for j = 1:size(rep_vec,1)
    fprintf(fid,'%f ',j);
    for k = 1:size(rep_vec,2)
        fprintf(fid,'%d:%f ',k,rep_vec(j,k));
    end
    fprintf(fid,'\n');
end
fclose(fid);

% Jp2k quality
system(['/usr/local/Cellar/libsvm/3.22/bin/svm-scale -r +biqi/range2_jp2k test_ind.txt >> test_ind_scaled']);
system(['/usr/local/Cellar/libsvm/3.22/bin/svm-predict  -b 1 test_ind_scaled +biqi/model_89_jp2k output_blur']);
load output_blur
jp2k_score = output_blur;
delete output_blur test_ind_scaled

% JPEG quality
jpeg_score  = jpeg_quality_score(im);

% WN quality
system(['/usr/local/Cellar/libsvm/3.22/bin/svm-scale -r +biqi/range2_wn test_ind.txt >> test_ind_scaled']);
system(['/usr/local/Cellar/libsvm/3.22/bin/svm-predict -b 1 test_ind_scaled +biqi/model_89_wn output_blur']);
load output_blur
wn_score = output_blur;
delete output_blur test_ind_scaled

% Blur quality
system(['/usr/local/Cellar/libsvm/3.22/bin/svm-scale -r +biqi/range2_blur test_ind.txt >> test_ind_scaled']);
system(['/usr/local/Cellar/libsvm/3.22/bin/svm-predict  -b 1 test_ind_scaled +biqi/model_89_blur output_blur']);
load output_blur
blur_score = output_blur;
delete output_blur test_ind_scaled

% FF quality
system(['/usr/local/Cellar/libsvm/3.22/bin/svm-scale -r +biqi/range2_ff test_ind.txt >> test_ind_scaled']);
system(['/usr/local/Cellar/libsvm/3.22/bin/svm-predict  -b 1 test_ind_scaled +biqi/model_89_ff output_blur']);
load output_blur
ff_score = output_blur;

delete output_blur
delete test_ind.txt test_ind_scaled

%% Final pooling

% figure out probabilities
fid = fopen('output_89','r');
fgetl(fid);
C = textscan(fid,'%f %f %f %f %f %f');
output = [C{1} C{2} C{3} C{4} C{5} C{6}];
fclose(fid);
probs = output(:,2:end);
scores  = [jp2k_score jpeg_score wn_score blur_score ff_score];
quality = sum(probs.*scores,2);
delete output_89
clc