classdef IMMOEA < ALGORITHM
% <multi> <real/integer> <large/none>
% Inverse modeling based multiobjective evolutionary algorithm
% K --- 10 --- Number of reference vectors

%------------------------------- Reference --------------------------------
% R. Cheng, Y. Jin, K. Narukawa, and B. Sendhoff, A multiobjective
% evolutionary algorithm using Gaussian process-based inverse modeling,
% IEEE Transactions on Evolutionary Computation, 2015, 19(6): 838-856.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        function main(Algorithm,Problem)
            %% Parameter setting
            K = Algorithm.ParameterSet(10);

            %% Generate random population
            [W,K] = UniformPoint(K,Problem.M);
            W     = fliplr(sortrows(fliplr(W)));
            Problem.N     = ceil(Problem.N/K)*K;
            Population    = Problem.Initialization();
            [~,partition] = max(1-pdist2(Population.objs,W,'cosine'),[],2);

            %% Optimization
            while Algorithm.NotTerminated(Population)
                % Modeling and reproduction
                for k = unique(partition)'
                    Population = [Population,Operator(Problem,Population(partition==k))];
                end
                % Environmental selection
                [~,partition] = max(1-pdist2(Population.objs,W,'cosine'),[],2);
                for k = unique(partition)'
                    current = find(partition==k);
                    if length(current) > Problem.N/K
                        Del = EnvironmentalSelection(Population(current),Problem.N/K);
                        Population(current(Del)) = [];
                        partition(current(Del))  = [];
                    end
                end
            end
        end
    end
end


% demos for ch03
clear; close all;
d = 1;
n = 200;
[x,t] = linRnd(d,n);
%% Empirical Bayesian linear regression via EM
[model,llh] = linRegEm(x,t);
plot(llh);
[y,sigma] = linRegPred(model,x,t);
figure
plotCurveBar(x,y,sigma);
hold on;
plot(x,t,'o');
hold off;


function im1 = at_imageresize(im1)

% isz = size(im1(:,:,1));
% if (1920*1440) < prod(isz)
%   if isz(1) > isz(2)
%     im1 = imresize(im1,[1920 NaN]);
%   else
%     im1 = imresize(im1,[NaN 1920]);
%   end
% end

isz = size(im1(:,:,1));
if (1600*1200) < prod(isz)
  scale = 1600/max(isz);
  im1 = imresize(im1, scale);
%   if isz(1) > isz(2)
%     im1 = imresize(im1,[640 NaN]);
%   else
%     im1 = imresize(im1,[NaN 640]);
%   end
end

% isz = size(im1(:,:,1));
% if (1920*1440) < prod(isz)
%   im1 = imresize(im1,sqrt((1920*1440)/prod(isz)));
% end


clear all;

I=double(imread('data/lena.png'))/255;
% extract 8 x 8 patches
X=im2col(I,[8 8],'sliding');
X=X-repmat(mean(X),[size(X,1) 1]);
X=X ./ repmat(sqrt(sum(X.^2)),[size(X,1) 1]);

param.K=64;  % learns a dictionary with 64 elements
param.lambda=0.05;
param.numThreads=4; % number of threads
param.batchsize=400;
param.tol = 1e-3

param.iter=200;  %

if false
param.regul = 'l1';
fprintf('with Fista Regression %s\n',param.regul);
tic
D = mexStructTrainDL(X,param);
t=toc;
fprintf('time of computation for Dictionary Learning: %f\n',t);
%
param.regul = 'l2';
fprintf('with Fista Regression %s\n',param.regul);
tic
D = mexStructTrainDL(X,param);
t=toc;
fprintf('time of computation for Dictionary Learning: %f\n',t);
%
param.regul = 'elastic-net';
fprintf('with Fista %s\n',param.regul);
param.lambda2=0.1;
tic
D = mexStructTrainDL(X,param);
t=toc;
fprintf('time of computation for Dictionary Learning: %f\n',t);

%%% GRAPH
param.lambda=0.1; % regularization parameter
param.tol=1e-5;
param.K = 10
graph.eta_g=[1 1 1 1 1];
graph.groups=sparse([0 0 0 1 0;
                     0 0 0 0 0;
                     0 0 0 0 0;
                     0 0 0 0 0;
                     0 0 1 0 0]);   % g5 is included in g3, and g2 is included in g4
graph.groups_var=sparse([1 0 0 0 0;
                         1 0 0 0 0;
                         1 0 0 0 0 ;
                         1 1 0 0 0;
                         0 1 0 1 0;
                         0 1 0 1 0;
                         0 1 0 0 1;
                         0 0 0 0 1;
                         0 0 0 0 1;
                         0 0 1 0 0]); % represents direct inclusion relations

param.graph = graph

param.regul = 'graph';
fprintf('with Fista %s\n',param.regul);
tic
D = mexStructTrainDL(X,param);
t=toc;
fprintf('time of computation for Dictionary Learning: %f\n',t);

%%
%%% TREE
%?pause;
param = rmfield(param,'graph');

end

param.lambda=0.1; % regularization parameter
param.tol=1e-5;
param.K = 10

tree.own_variables=  int32([0 0 3 5 6 6 8 9]);   % pointer to the first variable of each group
tree.N_own_variables=int32([0 3 2 1 0 2 1 1]); % number of "root" variables in each group
tree.eta_g=[1 1 1 2 2 2 2.5 2.5];
tree.groups=sparse([0 0 0 0 0 0 0 0; ...
                    1 0 0 0 0 0 0 0; ...
                    0 1 0 0 0 0 0 0; ...
                    0 1 0 0 0 0 0 0; ...
                    1 0 0 0 0 0 0 0; ...
                    0 0 0 0 1 0 0 0; ...
                    0 0 0 0 1 0 0 0; ...
                    0 0 0 0 0 0 1 0]);  % first group should always be the root of the tree

param.tree = tree;

param.regul = 'tree-l0';
fprintf('with Fista %s\n',param.regul);

tic
D = mexStructTrainDL(X,param);
t=toc;
fprintf('time of computation for Dictionary Learning: %f\n',t);

%
param.regul = 'tree-l2';
fprintf('with Fista %s\n',param.regul);
tic
D = mexStructTrainDL(X,param);
t=toc;
fprintf('time of computation for Dictionary Learning: %f\n',t);

%
param.regul = 'tree-linf';
fprintf('with Fista %s\n',param.regul);

tic
D = mexStructTrainDL(X,param);
t=toc;
fprintf('time of computation for Dictionary Learning: %f\n',t);


function visible = visiblevertices(FV, R)

V2 = (R*FV.vertices')';

% Store the vertex depths for z-buffering
Z = V2(:, 3);

% Compute the projected vertices in the image plane
UV(:, 1)    = V2(:, 1) ;	% orthographic projection for x
UV(:, 2)    = V2(:, 2) ;	% orthographic projection for y

% Transform to the pixel plane (the axes remain switched)
UV(:, 1)    = UV(:, 1)-min(UV(:, 1));
UV(:, 2)    = UV(:, 2)-min(UV(:, 2));
UV          = UV + 1;

UV=(UV./max(UV(:))).*1000;
width=1000;
height=1000;

% Get the triangle vertices
v1      = FV.faces(:, 1);
v2      = FV.faces(:, 2);
v3      = FV.faces(:, 3);
Nfaces  = size(FV.faces, 1);

% Compute bounding boxes for the projected triangles
x       = [UV(v1, 1), UV(v2, 1), UV(v3, 1)];
y       = [UV(v1, 2), UV(v2, 2), UV(v3, 2)];
minx    = ceil (min(x, [], 2));
maxx    = floor(max(x, [], 2));
miny    = ceil (min(y, [], 2));
maxy    = floor(max(y, [], 2));

clear x y

% Frustum culling
minx    = max(1,        minx);
maxx    = min(width,    maxx);
miny    = max(1,        miny);
maxy    = min(height,   maxy);

% Construct the pixel grid (can speed up by precomputing if shared among the images)
[rows, cols] = meshgrid(1: width, 1: height);

% Initialize the depth-, face- and weight-buffers
zbuffer     = -inf(height, width);
fbuffer     = zeros(height, width);
wbuffer1    = NaN(height, width);
wbuffer2    = NaN(height, width);
wbuffer3    = NaN(height, width);

% For each triangle (can speed up by comparing the triangle depths to the z-buffer and priorly sorting the triangles by increasing depth)
for i = 1: Nfaces

    % If some pixels lie in the bounding box
    if minx(i) <= maxx(i) && miny(i) <= maxy(i)

        % Get the pixels lying in the bounding box
        px = rows(miny(i): maxy(i), minx(i): maxx(i));
        py = cols(miny(i): maxy(i), minx(i): maxx(i));
        px = px(:);
        py = py(:);

        % Compute the edge vectors
        e0 = UV(v1(i), :);
        e1 = UV(v2(i), :) - e0;
        e2 = UV(v3(i), :) - e0;

        % Compute the barycentric coordinates (can speed up by first computing and testing a solely)
        det     = e1(1) * e2(2) - e1(2) * e2(1);
        tmpx    = px - e0(1);
        tmpy    = py - e0(2);
        a       = (tmpx * e2(2) - tmpy * e2(1)) / det;
        b       = (tmpy * e1(1) - tmpx * e1(2)) / det;

        % Test whether the pixels lie in the triangle
        test = a >= 0 & b >= 0 & a + b <= 1;

        % If some pixels lie in the triangle
        if any(test)

            % Get the pixels lying in the triangle
            px = px(test);
            py = py(test);

            % Interpolate the triangle depth for each pixel
            w2 = a(test);
            w3 = b(test);
            w1 = 1 - w2 - w3;
            pz = Z(v1(i)) * w1 + Z(v2(i)) * w2 + Z(v3(i)) * w3;

            % For each pixel lying in the triangle
            for j = 1: length(pz)

                % Frustum culling
%                if pz(j) <= -near && pz(j) >= -far

                    % Update the depth-, face- and weight-buffers
                    if pz(j) > zbuffer(py(j), px(j))
                        zbuffer(py(j), px(j))   = pz(j);
                        fbuffer(py(j), px(j))   = i;
                        wbuffer1(py(j), px(j))  = w1(j);
                        wbuffer2(py(j), px(j))  = w2(j);
                        wbuffer3(py(j), px(j))  = w3(j);
                    end

%                end

            end

        end

    end

end

%figure; imshow(zbuffer,[])

clear UV Z zbuffer px py pz minx maxx miny maxy

% Get the vertices to render
test    = fbuffer ~= 0;
f       = unique(fbuffer(test));
v       = unique([v1(f); v2(f); v3(f)]);
f       = find(any(ismember(FV.faces, v), 2));
Nfaces  = length(f);

visible = v;

return

% Compute the edge vectors
e1s = V2(v2(f), :) - V2(v1(f), :);
e2s = V2(v3(f), :) - V2(v1(f), :);
e3s = V2(v2(f), :) - V2(v3(f), :);

clear V2

% Normalize the edge vectors
e1s_norm = e1s ./ repmat(sqrt(sum(e1s.^2, 2)), 1, 3);
e2s_norm = e2s ./ repmat(sqrt(sum(e2s.^2, 2)), 1, 3);
e3s_norm = e3s ./ repmat(sqrt(sum(e3s.^2, 2)), 1, 3);

% Compute the angles
angles(:, 1) = acos(sum(e1s_norm .* e2s_norm, 2));
angles(:, 2) = acos(sum(e3s_norm .* e1s_norm, 2));
angles(:, 3) = pi - (angles(:, 1) + angles(:, 2));

% Compute the triangle weighted normals
triangle_normals    = cross(e1s, e3s, 2);
w1_triangle_normals = triangle_normals .* repmat(angles(:, 1), 1, 3);
w2_triangle_normals = triangle_normals .* repmat(angles(:, 2), 1, 3);
w3_triangle_normals = triangle_normals .* repmat(angles(:, 3), 1, 3);

clear e1s e2s e3s e1s_norm e2s_norm e3s_norm angles triangle_normals

% Initialize the vertex normals
normals = zeros(Nvertices, 3);

% Update the vertex normals
for i = 1: Nfaces
    normals(v1(f(i)), :) = normals(v1(f(i)), :) + w1_triangle_normals(i, :);
    normals(v2(f(i)), :) = normals(v2(f(i)), :) + w2_triangle_normals(i, :);
    normals(v3(f(i)), :) = normals(v3(f(i)), :) + w3_triangle_normals(i, :);
end

clear w1_triangle_normals w2_triangle_normals w3_triangle_normals

% Normalize the vertex normals
normals = normals(v, :);
normals = normals ./ repmat(sqrt(sum(normals.^2, 2)), 1, 3);

% Self-occlusions
test = normals(:, 3) >= 0;

% Interpolate the z-buffer at the projected vertices
vZ          = inf(size(FV.vertices, 1), 1);
vZ(test)    = interp2(rows, cols, zbuffer, UV(test, 1), UV(test, 2), '*linear');

% Fix the border
tmp_test            = vZ(test) == -inf;
vZ(test(tmp_test))	= interp2(rows, cols, zbuffer, UV(test(tmp_test), 1), UV(test(tmp_test), 2), '*nearest');

% Compute the vertex visibility index in terms of relative depth compared to the z-buffer
test(test) = abs(vZ(test) - Z(test)) <= 0.05 * (max(Z) - min(Z));

clear ambient1 diffuse1 specular1 ambient2 diffuse2 specular2 ambient3 diffuse3 specular3 v

% Initialize the image
im1 = NaN(height, width);
im2 = NaN(height, width);
im3 = NaN(height, width);

% Rasterize the image
v1          = v1(fbuffer(test));
v2          = v2(fbuffer(test));
v3          = v3(fbuffer(test));
w1          = wbuffer1(test);
w2          = wbuffer2(test);
w3          = wbuffer3(test);
im1(test)   = w1 .* texture1(v1) + w2 .* texture1(v2) + w3 .* texture1(v3);
im2(test)   = w1 .* texture2(v1) + w2 .* texture2(v2) + w3 .* texture2(v3);
im3(test)   = w1 .* texture3(v1) + w2 .* texture3(v2) + w3 .* texture3(v3);

clear v1 v2 v3 w1 w2 w3

% Reshape the image
im = cat(3, im1, im2, im3);

clear im1 im2 im3 test

im = flipud(fliplr(im));

end


function [mph] = ftps2mph(ftps)
% Convert speed from feet per second to miles per hour
mph = ftps*0.6818181818182 ;


%
% Usage:   alpha=mexSOMP(X,D,list_groups,param);
%
% Name: mexSOMP
%     (this function has not been intensively tested).
%
% Description: mexSOMP is an efficient implementation of a
%     Simultaneous Orthogonal Matching Pursuit algorithm. It is optimized
%     for solving a large number of small or medium-sized
%     decomposition problem (and not for a single large one).
%     It first computes the Gram matrix D'D and then perform
%     a Cholesky-based OMP of the input signals in parallel.
%     It aims at addressing the following NP-hard problem
%
%     X is a matrix structured in groups of signals, which we denote
%     by X=[X_1,...,X_n]
%
%     for all matrices X_i of X,
%         min_{A_i} ||A_i||_{0,infty}  s.t  ||X_i-D A_i||_2^2 <= eps*n_i
%         where n_i is the number of columns of X_i
%
%         or
%
%         min_{A_i} ||X_i-D A_i||_2^2  s.t. ||A_i||_{0,infty} <= L
%
%
% Inputs: X:  double m x N matrix   (input signals)
%            m is the signal size
%            N is the total number of signals
%         D:  double m x p matrix   (dictionary)
%            p is the number of elements in the dictionary
%            All the columns of D should have unit-norm !
%         list_groups : int32 vector containing the indices (starting at 0)
%            of the first elements of each groups.
%         param: struct
%            param.L (maximum number of elements in each decomposition)
%            param.eps (threshold on the squared l2-norm of the residual
%            param.numThreads (optional, number of threads for exploiting
%            multi-core / multi-cpus. By default, it takes the value -1,
%            which automatically selects all the available CPUs/cores).
%
% Output: alpha: double sparse p x N matrix (output coefficients)
%
% Note: this function admits a few experimental usages, which have not
%     been extensively tested:
%      - single precision setting (even though the output alpha is double
%        precision)
%
% Author: Julien Mairal, 2010


classdef DTLZ9 < PROBLEM
% <multi/many> <real> <large/none> <constrained> <expensive/none>
% Benchmark MOP proposed by Deb, Thiele, Laumanns, and Zitzler

%------------------------------- Reference --------------------------------
% K. Deb, L. Thiele, M. Laumanns, and E. Zitzler, Scalable test problems
% for evolutionary multiobjective optimization, Evolutionary multiobjective
% Optimization. Theoretical Advances and Applications, 2005, 105-145.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        %% Default settings of the problem
        function Setting(obj)
            if isempty(obj.M); obj.M = 2; end
            if isempty(obj.D); obj.D = 10*obj.M; end
            obj.D        = ceil(obj.D/obj.M)*obj.M;
            obj.lower    = zeros(1,obj.D);
            obj.upper    = ones(1,obj.D);
            obj.encoding = ones(1,obj.D);
        end
        %% Calculate objective values and constraint violations
        function Population = Evaluation(obj,varargin)
            PopDec = varargin{1};
            PopDec = max(min(PopDec,repmat(obj.upper,size(PopDec,1),1)),repmat(obj.lower,size(PopDec,1),1));
            X      = PopDec;
            PopDec = PopDec.^0.1;
            PopObj = zeros(size(PopDec,1),obj.M);
            for m = 1 : obj.M
                PopObj(:,m) = sum(PopDec(:,(m-1)*obj.D/obj.M+1:m*obj.D/obj.M),2);
            end
            PopCon = 1 - repmat(PopObj(:,obj.M).^2,1,obj.M-1) - PopObj(:,1:obj.M-1).^2;
            Population = SOLUTION(X,PopObj,PopCon,varargin{2:end});
            obj.FE     = obj.FE + length(Population);
        end
        %% Generate points on the Pareto front
        function R = GetOptimum(obj,N)
            Temp = (0:1/(N-1):1)';
            R    = [repmat(cos(0.5.*pi.*Temp),1,obj.M-1),sin(0.5.*pi.*Temp)];
        end
        %% Generate the image of Pareto front
        function R = GetPF(obj)
            if obj.M < 4
                R = obj.GetOptimum(100);
            else
                R = [];
            end
        end
    end
end


function [bcx,bcy] = specific_flow(xbd,ybd)
%backwardstep_flow   Reference problem 5.2 inflow condition
%   [bcx,bcy] = specific_flow(xbd,ybd);
%   input
%          xbd          x coordinate vector
%          ybd          y coordinate vector
%
%   specifies backward step flow boundary condition
%   IFISS function: DJS; 6 March 2005.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage
bcx=0*xbd; bcy=0*xbd;
k=find(xbd==-1); bcx(k)=4*ybd(k).*(1-ybd(k));
return


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

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @defmethod @@sym log2 (@var{x})
%% Symbolic log base 2 function.
%%
%% Examples:
%% @example
%% @group
%% log2(sym(256))
%%   @result{} ans = (sym) 8
%%
%% syms x
%% log2(x)
%%   @result{} ans = (sym)
%%       log(x)
%%       ──────
%%       log(2)
%% @end group
%% @end example
%%
%% @seealso{@@sym/log, @@sym/log10}
%% @end defmethod

function z = log2(x)

  z = elementwise_op ('lambda x: sp.log(x, 2)', x);

end

%!assert (isequal (log2 (sym (1024)), sym (10)))

%!assert (isequal (log2 (sym ([2 16; 32 1])), sym ([1 4; 5 0])))

%!test
%! % round-trip
%! syms x
%! f = log2 (x);
%! h = function_handle (f);
%! A = h (1.1);
%! B = log2 (1.1);
%! assert (A, B, -5*eps)


function curveDisplay(x,y,varargin)
%curveDisplay Display of 2-D curve.
%   curveDisplay(X,Y,LINESPEC) displays the coordinates (x,y) of a CURVE.
%
%   LineSpec is a character string made from one element from any or all
%   the following 3 columns:
%
%            b     blue          .     point           -     solid
%            g     green         o     circle          :     dotted
%            r     red           x     x-mark          -.    dashdot
%            c     cyan          +     plus            --    dashed
%            m     magenta       *     star          (none)  no line
%            y     yellow        s     square
%            k     black         d     diamond
%            w     white         v     triangle (down)
%                                ^     triangle (up)
%                                <     triangle (left)
%                                >     triangle (right)
%                                p     pentagram
%                                h     hexagram
%
%
%   A symbol from the first column gives the color, the second is the
%   symbol used in the plot, and the third specifies the type of line
%   used to join the points in the plot. For example, to plot red circles
%   joined by straight lines we speficify the string 'ro-'. To plot just
%   red circles without any connecting lines we specify the string 'ro'.
%   The default for curveDisplay is black dots with no lines.
%
%   curveDisplay(X,Y,LINESPEC,NAME,VALUE) further modifies the lines and
%   markers using Name,Value pairs. Any Name,Value pairs supported by
%   the PLOT function are allowed, including:
%
%           Name                          Value
%
%        LineWidth         Width (in points) of the line and border
%                          of filled markers (circle, square, diamond,
%                          pentagram, hexagram, and the four triangles
%                          points). The default is 0.5 pt.
%
%          Color           The color of the line. The color can be
%                          specified as an RGB triplet (such as [0.5 1.0
%                          0.8]), a hexadecimal color code (such as
%                          '#FF8800'), a color name (such as 'red'), or
%                          a short color name (listed above in the
%                          description for LineSpec), or 'none'. The
%                          default is 'k' (black).
%
%     MarkerEdgeColor      Color of the marker or the color of the edge
%                          of the marker for filled markers, specified
%                          as described above for the Color parameter.
%                          The default is black, or, if a line is
%                          specified, the same color as the line joining
%                          the markers.
%
%    MarkerFaceColor       The fill color for the filled markers,
%                          specified as described above for the Color
%                          parameter. The default is 'none'.
%
%      MarkerSize          The size of the marker in points. The default
%                          is 7 pt.
%
%  Example: curveDisplay(x,y,'ro-','MarkerFaceColor','g','MarkerSize',4)
%  displays red circles of size 4 pt, connected by red solid line of 0.5
%  pt thick, with the circles filled in green.
%
%	To superimpose the curve on an image, f, use the following syntax:
%	figure, imshow(f)
%	hold on
%	curveDisplay(x,y,varargin)
%	hold off
%
%   Copyright 2002-2020 Gatesmark
%
%   This function, and other functions in the DIPUM Toolbox, are based
%   on the theoretical and practical foundations established in the
%   book Digital Image Processing Using MATLAB, 3rd ed., Gatesmark
%   Press, 2020.
%
%   Book website: http://www.imageprocessingplace.com
%   License: https://github.com/dipum/dipum-toolbox/blob/master/LICENSE.txt

narginchk(2,Inf)
if nargin == 2
   % Default.
   plot(y,x,'.')
else
   if ~isodd(length(varargin))
      error('Wrong number of inputs.');
   end
   plot(y,x,varargin{:});
end


function [V,A,flag] = symeig(S,d,m)
% Compute eigenvalues and eigenvectors of symmetric matrix
%   m == 's' smallest (default)
%   m == 'l' largest
% Written by Mo Chen (sth4nth@gmail.com).
if nargin == 2
    m = 's';
end
opt.disp = 0;
opt.issym = 1;
opt.isreal = 1;
if any(m == 'ls')
    [V,A,flag] = eigs(S,d,[m,'a'],opt);
else
    error('The third parameter must be l or s.');
end


function test_failed = test_wpfbt(verbose)
%TEST_WFBTPR
%
% Checks perfect reconstruction of the general wavelet transform of different
% filters
%
disp('========= TEST WPFBT ============');
global LTFAT_TEST_TYPE;
tolerance = 1e-8;
if strcmpi(LTFAT_TEST_TYPE,'single')
   tolerance = 2e-6;
end

test_failed = 0;
if(nargin>0)
   verbose = 1;
else
   verbose = 0;
end

type = {'dec'};
ext = {'per','zero','odd','even'};
format = {'pack','cell'};

J = 3;
%! Mild tree
wt1 = wfbtinit({'db10',6,'full'});
wt1 = wfbtremove(2,1,wt1,'force');
wt1 = wfbtremove(2,3,wt1,'force');

%! Hardcore tree
wt2 = wfbtinit({'db3',1});
wt2 = wfbtput(1,1,'mband1',wt2);
wt2 = wfbtput(2,2,'mband1',wt2);
wt2 = wfbtput(3,3,'mband1',wt2);
wt2 = wfbtput(3,1,'db10',wt2);
wt2 = wfbtput(4,1,'dgrid2',wt2);
wt2 = wfbtput(5,1,'db3',wt2);

%! Another tree
wt3 = wfbtinit();
wt3 = wfbtput(0,0,'cmband4',wt3);
wt3 = wfbtput(1,0,'cmband6',wt3);
wt3 = wfbtput(1,1,'cmband6',wt3);
wt3 = wfbtput(2,0,'cmband4',wt3);
wt3 = wfbtput(2,1,'cmband4',wt3);
wt3 = wfbtput(3,1,'cmband4',wt3);
wt3 = wfbtput(3,2,'cmband4',wt3);
wt3 = wfbtput(3,3,'cmband4',wt3);
wt3 = wfbtput(3,4,'cmband4',wt3);

% wt2 = wfbtinit();
% wt2 = wfbtput(0,0,{'db',4},wt2);
% wt2 = wfbtput(1,0,{'algmband',1},wt2);
% wt2 = wfbtput(1,1,{'hden',3},wt2);
% wt2 = wfbtput(2,0,{'dgrid',2},wt2);
% wt2 = wfbtput(2,1,{'dgrid',2},wt2);

test_filters = {
               {'algmband2',J} % 4 filters, uniform, crit. sub.
               {'db4',J}
               {'algmband1',J} % 3 filters, uniform, crit. sub.
               %{{'hden',3},J} % 3 filters, non-uniform, no crit. sub. no correct
               {'dgrid1',J} % 4 filters. sub. fac. 2
               wt1
               wt2
               wt3
               };

scaling = {'intscale','intsqrt','intnoscale'};
scalingInv = scaling(end:-1:1);

%testLen = 4*2^7-1;%(2^J-1);
testLen = 53;
f = tester_rand(testLen,1);
for scIdx = 1:numel(scaling)
for extIdx=1:length(ext)
   extCur = ext{extIdx};

   for typeIdx=1:length(type)
     for tt=1:length(test_filters)
        actFilt = test_filters{tt};
         if verbose, if(~isstruct(actFilt))fprintf('J=%d, filt=%s, ext=%s, inLen=%d \n',actFilt{2},actFilt{1},extCur,size(f,1)); else disp('Custom'); end; end;

        [c,info] = wpfbt(f,actFilt,extCur,scaling{scIdx});
        fhat = iwpfbt(c,actFilt,size(f,1),extCur,scalingInv{scIdx});

        %MSE
            err = norm(f-fhat,'fro');
            [test_failed,fail]=ltfatdiditfail(err,test_failed,tolerance);
            if(~verbose)
              if(~isstruct(actFilt))fprintf('J=%d, %5.5s, ext=%4.4s, %s, L=%d, err=%.4e %s \n',actFilt{2},actFilt{1},extCur,scaling{scIdx},size(f,1),err,fail); else fprintf('Custom, %s, err=%.4e %s \n',scaling{scIdx},err,fail); end;
            end
            if strcmpi(fail,'FAILED')
               if verbose
                if(~isstruct(actFilt)) fprintf('err=%d, filt=%s, ext=%s, inLen=%d \n',err,actFilt{1},extCur,testLen); else disp('Custom'); end;
                 figure(1);clf;stem([f,fhat]);
                 figure(2);clf;stem([f-fhat]);
                 break;
               end
            end

           fhat2 = iwpfbt(c,info);
           err = norm(f-fhat2,'fro');
           [test_failed,fail]=ltfatdiditfail(err,test_failed,tolerance);
           if(~isstruct(actFilt))
                fprintf('INFO J=%d, %5.5s, ext=%4.4s, %s, L=%d, err=%.4e %s \n',actFilt{2},actFilt{1},extCur,scaling{scIdx},size(f,1),err,fail);
           else
               fprintf('INFO Custom, %s, err=%.4e %s \n',scaling{scIdx},err,fail);
           end;

            if test_failed && verbose, break; end;

     end
     if test_failed && verbose, break; end;
   end
   if test_failed && verbose, break; end;
end
end


function [opts] = FDDL_SpaCoef(ipts,par)
% ========================================================================
% Coefficient updating of FDDL, Version 1.0
% Copyright(c) 2011  Meng YANG, Lei Zhang, Xiangchu Feng and David Zhang
% All Rights Reserved.
%
% -----------------------------------------------------------------------
% Permission to use, copy, or modify this software and its documentation
% for educational and research purposes only and without fee is here
% granted, provided that this copyright notice and the original authors'
% names appear on all copies and supporting documentation. This program
% shall not be used, rewritten, or adapted as the basis of a commercial
% software or hardware product without first obtaining permission of the
% authors. The authors make no representations about the suitability of
% this software for any purpose. It is provided "as is" without express
% or implied warranty.
%----------------------------------------------------------------------
%
% This is an implementation of the algorithm for updating the
% Coefficient matrix of FDDL (fix the dictionary)
%
% Please refer to the following paper
%
% Meng Yang, Lei Zhang, Xiangchu Feng, and David Zhang,"Fisher Discrimination
% Dictionary Learning for Sparse Representation", In IEEE Int. Conf. on
% Computer Vision, 2011.
% L. Rosasco, A. Verri, M. Santoro, S. Mosci, and S. Villa. Iterative
% Projection Methods for Structured Sparsity Regularization. MIT Technical
% Reports, MIT-CSAIL-TR-2009-050,CBCL-282, 2009.
% J. Bioucas-Dias, M. Figueiredo, ?A new TwIST: two-step iterative shrinkage
% /thresholding  algorithms for image restoration?, IEEE Transactions on
% Image Processing, December 2007.
%----------------------------------------------------------------------
%
%  Inputs :   (1) ipts :    the structre of input data
%                    .D     the dictionary
%                    .X     the training data
%                    .A     the coefficient matrix in the last iteration
%                    .trls  the labels of training data
%             (2) par :     the struture of input parameters
%                    .tau   the parameter of sparse constraint of coef
%                    .lambda  the parameter of within-class scatter
%                    .dls     the labels of dictionary's columns
%                    .index   the label of the class being processed
%
% Outputs:    (1) opts :    the structure of output data
%                    .A     the coefficient matrix
%                    .ert   the total energy sequence
%
%---------------------------------------------------------------------

par.nIter    =     200;   % maximal iteration number
par.isshow   =     false;
par.citeT    =     1e-6;  % stop criterion
par.cT       =     1e+10; % stop criterion

m            =    size(ipts.D,2);
fish_tau3    =    1;  % parameter of ||A_i-D_iX_i^i||_F^2 in fidelity term
fish_tau2    =    1;  % parameter of ||D_jX_i^j||_F^2 in fidelity term Eq.(4)
drls         =    par.dls;
D            =    ipts.D;
X            =    ipts.X;
A            =    ipts.A;
tau          =    par.tau;
lambda1      =    par.tau;
lambda2      =    par.lambda2;
lambda3      =    par.lambda2;
lambda4      =    par.lambda2;
trls         =    ipts.trls;
classn       =    length(unique(trls));
nIter        =    par.nIter;
c            =    par.c;
sigma        =    c;
tau1         =    tau/2;
index        =    par.index;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%TWIST parameter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for_ever           =         1;
IST_iters          =         0;
TwIST_iters        =         0;
sparse             =         1;
verbose            =         1;
enforceMonotone    =         1;
lam1               =         1e-4;   %default minimal eigenvalues
lamN               =         1;      %default maximal eigenvalues
rho0               =         (1-lam1/lamN)/(1+lam1/lamN);
alpha              =         2/(1+sqrt(1-rho0^2));        %default,user can set
beta               =         alpha*2/(lam1+lamN);         %default,user can set

%%%%%%%%%%%%%%%%%%%%%%%%
%preprocessing
%%%%%%%%%%%%%%%%%%%%%%%%
Ai                 =          X;  % the i-th training data
Xa                 =          A;  %
Xi                 =          A(:,trls==index);
Xt_now             =          A(:,trls==index);
% Xi                 =          zeros(size(A(:,trls==index)));
% Xt_now             =          zeros(size(A(:,trls==index)));

newpar.n_d          =   size(Ai,2);             % the sample number of i-th training data
n                   =   size(Xa,2);             % the total sample number of training data

for ci = 1:classn
    t_n_d = sum(trls==ci);
    t_b_line_i     =   ones(t_n_d,newpar.n_d)./t_n_d;
    t_c_j = ones(t_n_d,newpar.n_d)./n;
    t_b_angle_i           =   t_b_line_i-t_c_j;
    CJ(ci).M  = t_c_j;
    BAI(ci).M = t_b_angle_i;
end

newpar.B_line_i     =   ones(newpar.n_d,newpar.n_d)./newpar.n_d;
newpar.C_j          =   ones(newpar.n_d,newpar.n_d)./n;
newpar.CjCj         =   (newpar.C_j)*(newpar.C_j)';
newpar.C_line       =   ones(n,newpar.n_d)./n;
B_i                 =   eye(newpar.n_d,newpar.n_d)-newpar.B_line_i;
newpar.BiBi         =   B_i*(B_i)';
B_angle_i           =   newpar.B_line_i-newpar.C_j;
newpar.Bai          =   B_angle_i;
newpar.BaiBai       =   B_angle_i*(B_angle_i)';
Xo                  =   Xa;
Xo(:,trls==index)   =   0;
G_X_i               =   Xo*newpar.C_line;
newpar.BaiGxi       =   B_angle_i*(G_X_i)';
newpar.DD           =   D'*D;
newpar.DAi          =   D'*Ai;
Di0                 =   D;
Di0(:,drls~=index)  =   0;
newpar.Di0Di0       =   (Di0)'*Di0;
newpar.Di0Ai        =   (Di0)'*Ai;

newpar.DoiDoi       =   zeros(size(D,2));
for t_i  =  1:classn
    if t_i ~= index
    Doi                 =   D;
    Doi(:,drls~=t_i)      =   0;
    newpar.DoiDoi       =   newpar.DoiDoi+(Doi)'*Doi;
    end
end

newpar.m            =   m;                 % the number of dictionary column atoms

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%main loop
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Xa(:,trls==index)  =  Xi;
xm2       =      Xi;%A(:,trls==index);
xm1       =      Xi;%A(:,trls==index); % now

[gap] = FDDL_Class_Energy(Ai,D,xm1,Xa,drls,trls,index,...
        lambda1,lambda2,lambda3,lambda4,classn,fish_tau2,fish_tau3);
prev_f   =   gap;
ert(1) = gap;
for n_it = 2 : nIter;

   Xa(:,trls==index)  =  Xi;

   while for_ever
        % IPM estimate

        grad = FDDL_Gradient_Comp(xm1,Xa,classn,index,...
        lambda2,lambda3,lambda4,fish_tau2,fish_tau3,trls,drls,newpar,...
        BAI,CJ);

        v        =   xm1(:)-grad./(2*sigma);
        tem      =   soft(v,tau1/sigma);
        x_temp   =   reshape(tem,[size(D,2),size(xm1,2)]);

        if (IST_iters >= 2) | ( TwIST_iters ~= 0)
            % set to zero the past when the present is zero
            % suitable for sparse inducing priors
            if sparse
                mask    =   (x_temp ~= 0);
                xm1     =   xm1.* mask;
                xm2     =   xm2.* mask;
            end
            % two-step iteration
            xm2    =   (alpha-beta)*xm1 + (1-alpha)*xm2 + beta*x_temp;
            % compute residual
           [gap] = FDDL_Class_Energy(Ai,D,xm2,Xa,drls,trls,index,...
                lambda1,lambda2,lambda3,lambda4,classn,fish_tau2,fish_tau3);

           f   =   gap;

            if (f > prev_f) & (enforceMonotone)
                TwIST_iters   =  0;  % do a IST iteration if monotonocity fails
            else
                TwIST_iters =   TwIST_iters+1; % TwIST iterations
                IST_iters   =    0;
                x_temp      =   xm2;
                if mod(TwIST_iters,10000) ==0
                   c = 0.9*c;
                   sigma = c;
                end
                break;  % break loop while
            end
        else

        [gap] = FDDL_Class_Energy(Ai,D,x_temp,Xa,drls,trls,index,...
        lambda1,lambda2,lambda3,lambda4,classn,fish_tau2,fish_tau3);

        f   =   gap;

         if f > prev_f
                % if monotonicity  fails here  is  because
                % max eig (A'A) > 1. Thus, we increase our guess
                % of max_svs
                c         =    2*c;
                sigma     =    c;
                if verbose
%                     fprintf('Incrementing c=%2.2e\n',c);
                end
                if  c > par.cT
                    break;  % break loop while
                end
                IST_iters = 0;
                TwIST_iters = 0;
           else
                TwIST_iters = TwIST_iters + 1;
                break;  % break loop while
           end
        end

    end

    citerion      =   abs(f-prev_f)/abs(prev_f);
    if citerion < par.citeT | c > par.cT
%        fprintf('Stop!\n c=%2.2e\n citerion=%2.2e\n',c,citerion);
       break;
    end

    xm2           =   xm1;
    xm1           =   x_temp;
    Xt_now        =   x_temp;
    Xi            =   Xt_now;
    prev_f        =   f;
    ert(n_it)     =   f;
%     fprintf('Iteration:%f  Total gap:%f\n',n_it,ert(n_it-1));
   end

opts.A     =       Xt_now;
opts.ert   =       ert;


function [M,P] = ckf_predict(M,P,f,Q,f_param)
% CKF_PREDICT - Cubature Kalman filter prediction step
%
% Syntax:
%   [M,P] = CKF_PREDICT(M,P,[f,Q,f_param])
%
% In:
%   M - Nx1 mean state estimate of previous step
%   P - NxN state covariance of previous step
%   f - Dynamic model function as a matrix A defining
%       linear function f(x) = A*x, inline function,
%       function handle or name of function in
%       form f(x,param)                   (optional, default eye())
%   Q - Process noise of discrete model   (optional, default zero)
%   f_param - Parameters of f               (optional, default empty)
%
% Out:
%   M - Updated state mean
%   P - Updated state covariance
%
% Description:
%   Perform additive form spherical-radial cubature Kalman filter (CKF)
%   prediction step.
%
%   Function f(.) should be such that it can be given a
%   DxN matrix of N sigma Dx1 points and it returns
%   the corresponding predictions for each sigma
%   point.
%
% See also:
%   CKF_UPDATE, CRTS_SMOOTH, CKF_TRANSFORM, SPHERICALRADIAL
%
% References:
%   Arasaratnam and Haykin (2009). Cubature Kalman Filters.
%    IEEE Transactions on Automatic Control, vol. 54, no. 5, pp.1254-1269

% Copyright (c) 2010 Arno Solin
%
% This software is distributed under the GNU General Public
% Licence (version 2 or later); please refer to the file
% Licence.txt, included with the software, for details.
%%

  %
  % Check which arguments are there
  %
  if nargin < 2
    error('Too few arguments');
  end
  if nargin < 3
    f = [];
  end
  if nargin < 4
    Q = [];
  end

  %
  % Apply defaults
  %
  if isempty(f)
    f = eye(size(M,1));
  end
  if isempty(Q)
    Q = zeros(size(M,1));
  end

  %
  % Do transform and add process noise
  %
  if nargin < 5
    [M,P] = ckf_transform(M,P,f);
  else
    [M,P] = ckf_transform(M,P,f,f_param);
  end
  P = P + Q;


% demo_AAM

% This demo shows how to use the AAM and MESMA code, with a quick example
% on Gaussian artificial data sets.

% Initialization
d=40;         % number of spectral bands
num=1000;     % number of pixels in input data set
p=3;          % number of spectral libraries
N=[10,20,30]; % sizes of spectral libraries

% Generate data sets
L{1}=randn(d,N(1));
L{2}=randn(d,N(2));
L{3}=randn(d,N(3));
x=randn(d,num);

% Call AAM
[index1, abundances1, reconstruction1, error1]=AAM(x,L,3);

% Call MESMA
[index2, abundances2, reconstruction2, error2]=MESMA_bruteforce (x,L);


function [Vx,Vy] = computeFlowBkgSup(im1curr,im2curr,params,gparams)
% function [Vx,Vy] = computeFlowBkgSup(im1curr,im2curr,params)
% Computes flow and then suppresses flow in the background.

%There is some flow towards the center that can't be estimated
% properly. The flow increases as we go away from the center.
% d_err is to account for that.

sz = round(size(im1curr));
bwimg = zeros(sz(1),sz(2));
ctr = [ceil( (sz(1)+1)/2),ceil( (sz(2)+1)/2)];
bwimg(ctr(1),ctr(2))=1;
dimg = bwdist(bwimg,'euclidean');
[xx,yy]= meshgrid(1:sz(2),1:sz(1));
aimg = atan2(-(yy-ctr(1)),-(xx-ctr(2)));

dd_err = dimg/size(im1curr,1);
flow_thres = gparams.flow_thres;

uv = estimate_flow_interface(im1curr,im2curr,...
  'hs-brightness',{'max_warping_iters',gparams.warping_iters});

if ~params.stationary,
  Vx = uv(:,:,1);
  Vy = uv(:,:,2);
  return;
end

cdx = params.dx;
cdy = params.dy;
curt = params.theta;
rotd = [cos(curt) sin(curt); -sin(curt) cos(curt)]*[cdx;cdy];
cdx = -rotd(1); cdy = -rotd(2);

ctheta = params.dtheta;
rotflowu = dimg.*(cos(aimg+ctheta)-cos(aimg));
rotflowv = dimg.*(sin(aimg+ctheta)-sin(aimg));

dd1 = sqrt( (uv(:,:,1)-cdx-rotflowu).^2 + (uv(:,:,2)-cdy-rotflowv).^2);

crdx = params.rdx;  crdy = params.rdy;
rotd = [cos(curt) sin(curt); -sin(curt) cos(curt)]*[crdx;crdy];
fly_flow = rotd;

dd2 = sqrt( (uv(:,:,1)-fly_flow(1)).^2 + (uv(:,:,2)-fly_flow(2)).^2);
dd = min(dd1,dd2);
for ndx = 1:2
  tt = uv(:,:,ndx);
  tt( dd<(dd_err+flow_thres)) = 0;
  uv(:,:,ndx) = tt;
end
Vx = uv(:,:,1);
Vy = uv(:,:,2);


% Copyright 2016 Google Inc.
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http ://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.

function A = buildSecondDerivZMatrix(grid_size)

% d/dz for every entry in the cube except the first and last slice.
m = grid_size(1) * grid_size(2) * (grid_size(3) - 2);
n = grid_size(1) * grid_size(2) * grid_size(3);
e = ones(m, 1);
interior = spdiags([e, -2 * e, e], ...
    [0, grid_size(1) * grid_size(2), 2 * grid_size(1) * grid_size(2)], ...
    m, n);

boundary_z1 = makeBoundaryZ1(n);
boundary_zend = makeBoundaryZEnd(n);

% The matrix for a full cube.
cube = [boundary_z1; interior; boundary_zend];

% Repeat the cube for the last 2 dimensions.
A = sparse(0, 0);
for v = 1:grid_size(5)
    for u = 1:grid_size(4)
        A = blkdiag(A, cube);
    end
end

% Boundary conditions for the first slice.
% n is the number of columns for the full matrix (the number of variables
% in the grid).
function A = makeBoundaryZ1(n)
    mm = grid_size(1) * grid_size(2);
    nn = grid_size(1) * grid_size(2) * 2;
    e = ones(mm, 1);
    B = spdiags([-e, e], [0, grid_size(1) * grid_size(2)], mm, nn);
    % Concat zero columns to the right so we can vertical concat with the full
    % matrix later.
    A = [B, sparse(mm, n - nn)];
end

% Boundary conditions for the last slice.
function A = makeBoundaryZEnd(n)
    mm = grid_size(1) * grid_size(2);
    nn = grid_size(1) * grid_size(2) * 2;
    e = ones(mm, 1);
    B = spdiags([e, -e], [0, grid_size(1) * grid_size(2)], mm, nn);
    % Concat zero columns to the right so we can vertical concat with the full
    % matrix later.
    A = [sparse(mm, n - nn), B];
end

end


function [vars,eval] = km_akcca(pars,data)
% KM_AKCCA performs Alternating Kernel Canonical Correlation Analysis to
% blindly identify and equalize a single-input multiple-output Wiener.
%
% Input:	- pars: structure containing parameters of the alternating KCCA
%             algorithm
%			- data: structure containing the available data x, and the
%             unavailable data (source signal s, internal signals y, and
%             linear channels B)
% Output:	- vars: estimated variables
%           - eval: structure containing the resuls of the algorithm
%             evaluation
% USAGE: [vars,eval] = km_akcca(pars,data)
%
% Author: Steven Van Vaerenbergh (steven *at* gtas.dicom.unican.es), 2011.
%
% The algorithm in this file is based on the following publication:
% S. Van Vaerenbergh, J. Via and I. Santamaria, "Blind Identification of
% SIMO Wiener Systems based on Kernel Canonical Correlation Analysis",
% accepted for publication in IEEE Transactions on Signal Processing, 2013.
%
% This file is part of the Kernel Methods Toolbox for MATLAB.
% https://github.com/steven2358/kmbox

% AKCCA CORE
[vars, eval] = AKCCA_CORE_INIT(pars,data.x); % initialize
vars.it = 0;
eval.converged = false;
while ((vars.it < pars.it_max) && ~eval.converged)
    fprintf('.');
    vars.it = vars.it+1;
    vars = AKCCA_CORE_LINID(pars,vars); % CCA 1: estimate h and obtain z
    vars = AKCCA_CORE_NLINID(pars,vars); % CCA 2: estimate alpha and obtain y
    vars = AKCCA_CORE_EQ(pars,vars); % EQUALIZATION
    eval = AKCCA_CORE_EVAL(pars,vars,data,eval); % Error calculation and check convergence
end
fprintf('\n');

function [vars,eval] = AKCCA_CORE_INIT(pars,x)

% READ PARAMETERS AND VARIABLES
p = pars.p;
m = pars.m;
N = pars.data_N;
num_it = pars.it_max;
ktype = pars.kernel.type;
% ktype = pars.kernel{1};
kpar = pars.kernel.par;
diff_nlin = ~pars.identical_nonlin;	% boolean indicating different nonlinearities

% CONSTRUCT KERNEL MATRIX DECOMPOSITIONS
K = cell(p,1);
c = cell(p,1);
if diff_nlin,
    switch pars.decomp
        case 'KPCA'
            for i=1:p,
                if isa(kpar,'function_handle')	% determine kernel parameter
                    parfun = kpar;
                    c{i} = parfun(x{i});
                else c{i} = kpar(i);
                end
                Kfull = km_kernel_center(x{i},x{i},x{i},ktype,c{i});
                Kfull = 0.5*(Kfull+Kfull');	% avoid matlab rounding errors
                [V,D] = eig(Kfull);
                [D_sort,ind] = sort(real(diag(D)),'descend');
                if m<1,	% m represents the fraction of energy to be witheld
                    energy = sum(D_sort);
                    cumul_energy = cumsum(D_sort)/energy;
                    m = sum(cumul_energy < 1-m)+1;	% new m is number of required eigenvectors
                end
                K{i} = V(:,ind(1:m));
            end
        case 'ICD'

            for i=1:p,
                if isa(kpar,'function_handle')	% determine kernel parameter
                    parfun = kpar;
                    c{i} = parfun(x{i});
                else
                    c{i} = kpar(i);
                end
                if m<1,	% m represents the precision in ICD
                    precision = m;
                    mm = N;
                else
                    precision = 1E-10;
                    mm = m;
                end
                G = km_kernel_icd(x{i},ktype,c{i},mm,precision);
                G = G-repmat(mean(G),N,1);
                K{i} = G;
            end
        otherwise
            error 'wrong decomposition method';
    end

    y_est = x;

else
    Xf = [];
    for i=1:p,
        Xf = [Xf;x{i}]; %#ok<AGROW>
    end

    if isa(kpar,'function_handle')	% determine kernel parameter
        parfun = kpar;
        c = parfun(Xf);
    else c = kpar(i);
    end

    switch pars.decomp
        case 'KPCA'
            Kfull = km_kernel_center(Xf,Xf,Xf,ktype,c);
            Kfull = 0.5*(Kfull+Kfull');
            [V,D] = eig(Kfull);
            [D_sort,ind] = sort(real(diag(D)),'descend');

            if m<1,	% m represents the fraction of energy to be witheld
                energy = sum(D_sort);
                cumul_energy = cumsum(D_sort)/energy;
                m = sum(cumul_energy < 1-m)+1;	% new m is number of required eigenvectors
            else
                m=m*p;
            end
            for i=1:p,
                stind = (i-1)*N + 1;
                ndind = stind+N - 1;
                K{i} = V(stind:ndind,ind(1:m));
            end

        case 'ICD'

            if m<1,	% m represents the precision in ICD
                precision = m;
                mm = N;
            else
                precision = 1E-10;
                mm=m*p;
            end
            G = km_kernel_icd(Xf,ktype,c,mm,precision);
            G = G-repmat(mean(G),p*N,1);

            for i=1:p,
                stind = (i-1)*N + 1;
                ndind = stind+N - 1;
                K{i} = G(stind:ndind,:);
            end
        otherwise
            error 'wrong decomposition method';
    end

    y_est = x;
end

% WRITE EVAL AND VARIABLES
eval.MSE_y = zeros(1,num_it);
eval.MSE_z = zeros(2,num_it);
eval.MSE_h = zeros(1,num_it);
eval.result = zeros(1,num_it);

vars.y_est = y_est;		% initialize without taking into account the nonlinearity
vars.K = K;		% reduced kernel matrices
vars.x = x;		% original output data
vars.c = c;     % kernel parameter

function vars = AKCCA_CORE_LINID(pars,vars)
% estimate linear filters

% COPY PARAMETERS
p = pars.p;
L = pars.model_L;
N = pars.data_N;
K = vars.K;

y_est = vars.y_est;

% PROGRAM
n = N-L+1;

% get time-embedded data matrices
Ka = cell(p,1);
for i=1:p,
	Ka{i} = zeros(n,L);
% 	for n_ind = 1:n,    % too slow, better fill differently
% 		Ka{i}(n_ind,:) = y_est{i}(n_ind+L-1:-1:n_ind)';
% 	end
    for l_ind = 1:L,
        Ka{i}(:,l_ind) = y_est{i}(L-l_ind+1:L-l_ind+n)';
    end
end

h = SIMO_id_CCA(Ka);

zh_est = cell(p);
W = cell(p);
% rescale solution to fulfill restriction sumsqr = 1
sumnrg_h = 0;
for i=1:p,
	for j=1:p,
		if(i~=j)
			sumnrg_h = sumnrg_h + sum((Ka{i}*h{j}).^2);
		end
	end
end
for i=1:p,
	h{i} = h{i}/sqrt(sumnrg_h);
end

for i=1:p,
	for j=1:p,
		if (i~=j)
            mi = size(K{i},2);
            W{i,j} = zeros(n,mi);
			zh_est{i,j} = Ka{i}*h{j};	% system output
%             for n_ind=1:n,  % too slow, better fill differently
%                 kimat = K{i}(n_ind+L-1:-1:n_ind,:);
%                 W{i,j}(n_ind,:) = h{j}'*kimat;	% auxiliary variable
%             end
            for l_ind = 1:L,    % superfast
                W{i,j} = W{i,j} + h{j}(l_ind)*K{i}(L-l_ind+1:L-l_ind+n,:);
            end
		end
	end
end

% COPY VARIABLES
vars.h = h;		% filter estimation
vars.zh_est = zh_est;	% new output estimate
vars.W = W;		% auxiliary variable (filtered kernel matrices)

function vars = AKCCA_CORE_NLINID(pars,vars)
% estimate inverse nonlinearities

% READ PARAMETERS AND VARIABLES
p = pars.p;
diff_nlin = ~pars.identical_nonlin;	% boolean indicating different nonlinearities

K = vars.K;
W = vars.W;
reg = pars.reg;

% PROGRAM: 1 iteration
za_est = cell(p);
y_est = cell(p,1);
if diff_nlin
	% standard case: no identical nonlinearity
	a = SIMO_id_CCA_dual(W,reg);

	% rescale solution to fulfill restriction sumsqr = 1
	sumnrg_a = 0;
	for i=1:p,
		for j=1:p,
			if(i~=j)
				sumnrg_a = sumnrg_a + sum((W{i,j}*a{i}).^2);
			end
		end
	end

	for i=1:p,
		a{i} = a{i}/sqrt(sumnrg_a);
		y_est{i} = K{i}*a{i};	% get y estimates
		y_est{i} = y_est{i}/sqrt(norm(y_est{i}))*sqrt(norm(vars.x{i}));	% normalize
		for j=1:p,
			if (i~=j)
			za_est{i,j} = W{i,j}*a{i};	% system output
			end
		end
	end
else
	% identical nonlinearity
	a = SIMO_id_CCA_dual_identical(W,reg);
	for i=1:p,
		y_est{i} = K{i}*a;	% get y estimates
		for j=1:p,
			if (i~=j)
			za_est{i,j} = W{i,j}*a;	% system output
			end
		end
	end
end

% WRITE VARIABLES
vars.alpha = a;
vars.y_est = y_est;
vars.za_est = za_est;

function vars = AKCCA_CORE_EQ(pars,vars)
% equalize linear channels (zero-forcing)

% COPY PARAMETERS
p = pars.p;
L = pars.model_L;
N = pars.data_N;
k = pars.zf_k;

y_est = vars.y_est;
h = vars.h;

% PROGRAM
% use k observations to generate filter matrix and estimate equalizers
Hc = cell(p,1); Hr = cell(p,1);
TH = zeros(p*k,k+L-1);
for i=1:p,
	Hc{i} = [h{i}(1);zeros(k-1,1)];
	Hr{i} = [h{i}' zeros(1,k-1)];
	TH(i:p:end,:) = toeplitz(Hc{i},Hr{i});
end

% zero-forced equalizing
ZF = pinv(TH);

% S_est = zeros(N-k+1,k);
% Yi = zeros(p*k,1);
% for i=1:N-k+1,  % too slow, better fill differently
% 	for j=1:p,
% 		yi = y_est{j}(i+k-1:-1:i);
% 		Yi(j:p:end) = yi;
% 	end
% 	s_esti = ZF*Yi;
% 	S_est(i,:) = s_esti(1:k).';
% end
YY = zeros(N-k+1,p*k);
for j = 1:p,
    for k_ind=1:k,
        col = (k_ind-1)*p + j;
        YY(:,col) = y_est{j}(k-k_ind+1:N-k_ind+1);
    end
end
S_est = YY*ZF(1:k,:)';

cnorms = zeros(k,1);
for i=1:k,
	cnorms(i) = norm(ZF(:,i));
end
[mm,zfi] = min(cnorms); %#ok<ASGLU>
s_est = S_est(:,zfi);

inds = k-zfi+1:N-zfi+1;

% COPY VARIABLES
vars.s_est = s_est;
vars.ind_s = inds;
vars.ZF = ZF;

function eval = AKCCA_CORE_EVAL(pars,vars,data,eval)
% evaluate solutions: calculate errors

% COPY PARAMETERS
p = pars.p;
vb = pars.verbose;

y_est = vars.y_est;
s_est = vars.s_est;
h = vars.h;
it = vars.it;
inds = vars.ind_s;

s = data.s; % true source signal
B = data.B; % true channels
y = data.y; % true internal channels

% PROGRAM
MSE_y = 0; MSE_h = 0; MSE_za = 0; MSE_zh = 0;
for i=1:p,
	% check if system internals are known
	if (iscell(y))
		% MSE Y
		MSE_y = MSE_y + norm_compare(y{i},y_est{i})/p;
		% MSE H
		numz = length(h{i})-length(B{i});
		if (numz>0)
			% channel overestimation case
			B{i} = [B{i};zeros(numz,1)];
		end
		MSE_h = MSE_h + norm_compare(B{i},h{i})/p;
	end

	% MSE Z
	if isfield(vars,'za_est')
		za_est = vars.za_est;
	end
	zh_est = vars.zh_est;

	for j=i+1:p,
		if (i~=j)
			MSE_zh = MSE_zh + sum((zh_est{i,j}-zh_est{j,i}).^2);
			if isfield(vars,'za_est')
				MSE_za = MSE_za + sum((za_est{i,j}-za_est{j,i}).^2);
			end
		end
	end
end

signal_test = s(inds);
signal_est = s_est;

switch lower(pars.data_type)
	case {'gaussian'}
		% result = MSE between s and s_est
		result = norm_compare(signal_test,signal_est);
	case 'bits'
		% result = BER
		[MSEsb,sci] = scale_compare(signal_test,signal_est); %#ok<ASGLU>
		result = sum(sign(signal_test)~=sign(signal_est/sci))/length(signal_test);
        s_est = sign(signal_est/sci);
	otherwise
		disp('Unknown signal type.')
end

% OUTPUT
if vb, fprintf(1,'MSE z_a: %f\n',MSE_za); end;
if vb, fprintf(1,'MSE z_h: %f\n',MSE_zh); end;
if vb, fprintf(1,'MSE y: %f\n',MSE_y); end;
if vb, fprintf(1,'Result: %f\n',result); end;

% COPY VARIABLES
eval.MSE_h(it) = MSE_h;
eval.MSE_y(it) = MSE_y;
eval.MSE_z(1,it) = MSE_zh;
eval.MSE_z(2,it) = MSE_za;
eval.result(it) = result;
eval.s_est = s_est;

% CHECK STOP
if (it>2)
	% stop when both sub-iterations obtain consecutive equal costs
	change1 = abs(eval.MSE_z(2*it)-eval.MSE_z(2*it-2));
	change2 = abs(eval.MSE_z(2*it-1)-eval.MSE_z(2*it-3));
	if ((change1 < pars.it_stop) && (change2 < pars.it_stop))
		eval.converged = true;
		num = pars.it_max - it;
		eval.MSE_h(it+1:pars.it_max) = repmat(MSE_h,num,1);
		eval.MSE_y(it+1:pars.it_max) = repmat(MSE_y,num,1);
		eval.MSE_z(2*it+1:2*pars.it_max) = repmat(MSE_zh,2*num,1);
		eval.result(it+1:pars.it_max) = repmat(result,num,1);
	end
end

eval.finalresult = result;

function [h,alphas,betas] = SIMO_id_CCA(X)
% SIMO_ID_CCA estimates various channels of a SIMO system using CCA.
% Finds the optimal h_i such that X_i h_j = X_j H_i s.t. sum (i = j)
% ||X_i h_j||^2 = 1.
% Input:	- X: cell containing p sets of length N and dimension L (N x L)
% Output:	- h: identified channels (cell)
%			- alphas: sorted eigenvectors
%			- betas: sorted eigenvalues
%
% Steven Van Vaerenbergh 2008

p = length(X);
L = size(X{1},2);

Rf = zeros(p*L); Df = zeros(p*L);
for i=1:p,
	D = zeros(L);
	for j=1:p,
		if i~=j
			sti = (i-1)*L+1;
			ndi = i*L;
			stj = (j-1)*L+1;
			ndj = j*L;
			Rf(sti:ndi,stj:ndj) = X{j}'*X{i};
			D = D + X{j}'*X{j};
		end
	end
	Df(sti:ndi,sti:ndi) = D;
end

[alphas,betas] = eig(Rf,Df);
[betas,ind] = sort(real(diag(betas)),'ascend');
alpha = alphas(:,ind(end));
% alpha = alpha/norm(alpha);

h = cell(p,1);
for i=1:p,
	sti = (i-1)*L+1;
	ndi = i*L;
	h{i} = alpha(sti:ndi);
end

function [h,alphas,betas] = SIMO_id_CCA_dual_identical(X,reg)
% SIMO_ID_CCA estimates various channels of a SIMO system using CCA.
% Finds the optimal h_i such that X_ij h = X_ji h
% Input:
%	X: cell containing pxp data sets of length N and dimension m (N by m)
%   reg: regularization
%
% outputs:
%	h: identified channels
%	alphas: sorted eigenvectors
%	betas: sorted eigenvalues
%
% Reference: Via, Santamaria [...]
%
% Steven Van Vaerenbergh 2008

if nargin<2
    reg = 1E-8;
end

p = size(X,1);
m = size(X{1,2},2);

Rf = zeros(m); Df = zeros(m);
for i=1:p,
	for j=1:p,
		if i~=j
			Rf = Rf + X{i,j}'*X{j,i};
			Df = Df + X{i,j}'*X{i,j};
		end
	end
end
Df = Df + reg*eye(size(Df));

% solve eigenvalue problem
[alphas,betas] = eig(Rf,Df);
[betas_a,ind] = sort(real(diag(betas))); %#ok<ASGLU>
h = alphas(:,ind(end));

function [h,alphas,betas] = SIMO_id_CCA_dual(X,reg)
% SIMO_ID_CCA estimates various channels of a SIMO system using CCA.
% Finds the optimal h_i such that X_ij h_i = X_ji h_j s.t. sum (i~=j)
% ||X_ij h_i||^2 = 1.
% Input:	- X: cell containing pxp sets of length N and dimension mi (N x mi).
%           - reg: regularization
% Outputs:	- h: identified channels (cell)
%			- alphas: sorted eigenvectors
%			- betas: sorted eigenvalues
%
% Steven Van Vaerenbergh 2008

if nargin<2
    reg = 1E-8;
end

p = size(X,1);
m = zeros(p,1);
for i=1:p,
	j = mod(i,p)+1;
	m(i) = size(X{i,j},2);
end
mcum = [0;cumsum(m)];

Rf = zeros(mcum(end)); Df = zeros(mcum(end));
for i=1:p,
	D = zeros(m(i));
	for j=1:p,
		if i~=j
			sti = mcum(i)+1;
			ndi = sti+m(i)-1;
			stj = mcum(j)+1;
			ndj = stj+m(j)-1;
			Rf(sti:ndi,stj:ndj) = X{i,j}'*X{j,i};
			D = D + X{i,j}'*X{i,j};
		end
	end
	Df(sti:ndi,sti:ndi) = D + reg*eye(size(D));
end

[alphas,betas] = eig(Rf,Df);
[betas,ind] = sort(real(diag(betas)),'ascend');
alpha = alphas(:,ind(end));
% alpha = alpha/norm(alpha);

h = cell(p,1);
for i=1:p
	sti = mcum(i)+1;
	ndi = mcum(i+1);
	h{i} = alpha(sti:ndi);
end

function MSE = norm_compare(data_1,data_2)
% NORM_COMPARE calculates the squared error between 2 normalized signals

data_1_norm = data_1/norm(data_1);
data_2_norm = data_2/norm(data_2);

% take into account sign ambiguity
err_vecA = data_1_norm - data_2_norm;
err_vecB = data_1_norm + data_2_norm;

MSEA = err_vecA'*err_vecA;
MSEB = err_vecB'*err_vecB;

MSE = min(MSEA,MSEB);

function [MSE,sc] = scale_compare(data_1,data_2)

data_1_norm = data_1/norm(data_1);
sc = data_1_norm'*data_2/(data_2'*data_2);

err_vec = data_1_norm - sc*data_2;

MSE = err_vec'*err_vec;
sc = sc*norm(data_1);


% DEMOIL4 Oil data with deterministic training conditional, and MLP back constraints.

% FGPLVM

% Fix seeds
randn('seed', 1e5);
rand('seed', 1e5);

dataSetName = 'oil';
experimentNo = 4;

% load data
[Y, lbls] = lvmLoadData(dataSetName);

% Set up model
options = fgplvmOptions('dtc');
options.optimiser = 'scg';
options.back = 'mlp';
options.backOptions = mlpOptions;
latentDim = 2;
d = size(Y, 2);

model = fgplvmCreate(latentDim, d, Y, options);

% Optimise the model.
iters = 1000;
display = 1;

model = fgplvmOptimise(model, display, iters);

% Save the results.
capName = dataSetName;;
capName(1) = upper(capName(1));
save(['dem' capName num2str(experimentNo) '.mat'], 'model');

if exist('printDiagram') & printDiagram
  fgplvmPrintPlot(model, lbls, capName, experimentNo);
end

% Load the results and display dynamically.
fgplvmResultsDynamic(dataSetName, experimentNo, 'vector')

% compute the nearest neighbours errors in latent space.
errors = fgplvmNearestNeighbour(model, lbls);


function rects = get_rect_from_pts(allpoints)
%from 5 points to rect -- l, t, r, b
if false
    rects = fast_get_rect_from_pts(allpoints);
else
    std_points = [
        0.2 0.2
        0.8 0.2
        0.5 0.5
        0.3 0.75
        0.7 0.75];

    rects = nan(size(allpoints, 1), 4);

    tic;
    for i = 1:size(allpoints, 1)
        try
            points = allpoints(i, :);
            points = reshape(points, 2, [])';
            points = points(1:5, :);
            t = cp2tform(double(points), std_points, 'similarity');

            [xc, yc] = tforminv(t, 0.5, 0.5);
            [xtl, ytl] = tforminv(t, 0, 0);
            [xtr, ytr] = tforminv(t, 1, 0);

            w = sqrt((xtl-xtr).^2+(ytl-ytr).^2);
            rect = [xc-w/2, yc-w/2, xc+w/2, yc+w/2];
            rect = round(rect);
            rects(i, :) = rect;
            if (mod(i, 10000) == 0)
                fprintf('%d/%d... ', i, size(allpoints, 1));
                toc;
            end
        catch
            fprintf('Fail to process: %d!\n', i);
            continue;
        end
    end
end

end


Network torchvision.models.squeezenet {
Layer Conv2d-1 {
Type: CONV
Stride { X: 2, Y: 2 }
Dimensions { K: 96, C: 3, R: 7, S: 7, Y: 224, X: 224 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-2 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 16, C: 96, R: 1, S: 1, Y: 54, X: 54 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-3 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 64, C: 16, R: 1, S: 1, Y: 54, X: 54 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-4 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 64, C: 16, R: 3, S: 3, Y: 54, X: 54 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-5 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 16, C: 128, R: 1, S: 1, Y: 54, X: 54 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-6 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 64, C: 16, R: 1, S: 1, Y: 54, X: 54 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-7 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 64, C: 16, R: 3, S: 3, Y: 54, X: 54 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-8 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 32, C: 128, R: 1, S: 1, Y: 54, X: 54 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-9 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 128, C: 32, R: 1, S: 1, Y: 54, X: 54 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-10 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 128, C: 32, R: 3, S: 3, Y: 54, X: 54 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-11 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 32, C: 256, R: 1, S: 1, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-12 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 128, C: 32, R: 1, S: 1, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-13 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 128, C: 32, R: 3, S: 3, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-14 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 48, C: 256, R: 1, S: 1, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-15 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 192, C: 48, R: 1, S: 1, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-16 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 192, C: 48, R: 3, S: 3, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-17 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 48, C: 384, R: 1, S: 1, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-18 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 192, C: 48, R: 1, S: 1, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-19 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 192, C: 48, R: 3, S: 3, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-20 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 64, C: 384, R: 1, S: 1, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-21 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 256, C: 64, R: 1, S: 1, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-22 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 256, C: 64, R: 3, S: 3, Y: 27, X: 27 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-23 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 64, C: 512, R: 1, S: 1, Y: 13, X: 13 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-24 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 256, C: 64, R: 1, S: 1, Y: 13, X: 13 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-25 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 256, C: 64, R: 3, S: 3, Y: 13, X: 13 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
Layer Conv2d-26 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 1000, C: 512, R: 1, S: 1, Y: 13, X: 13 }
Dataflow {
        SpatialMap(1,1) K;
        TemporalMap(64,64) C;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        Cluster(64, P);
        SpatialMap(1,1) C;
        TemporalMap(Sz(R),1) Y;
        TemporalMap(Sz(S),1) X;
        TemporalMap(Sz(R),Sz(R)) R;
        TemporalMap(Sz(S),Sz(S)) S;
}
}
}


function [fMc, fProbability, mResult] =  plot_SchusterMc(mCatalog)
% function [fMc, fProbability, mResult] = plot_SchusterMc(mCatalog)
% ----------------------------------------------------
% Determine the magnitude of completness using Schuster's Method
% objectively. Philosophy: Detect if walkout > 95%
% significance level two times, then set upper magnitude as Mc. If that
% happens more times, choose the smaller magnitude!
%
% Incoming variables:
% mCatalog : EQ catalog
%
% Outgoing variables:
% fMc          : Magnitude of completeness
% fProbability : Probability of exceeding the 95% level radius
% mResult      : Result matrix for all cases
%
% Author: J. Woessner, woessner@seismo.ifg.ethz.ch
% last update: 04.06.02

fMinMag = round(min(mCatalog(:,6))*10)/10;
fMaxMag = round(max(mCatalog(:,6))*10)/10;

prompt = {'Enter minimum magnitude:','Enter maximum magnitude:','Magnitude increment:'};
dlg_title = 'Search parameters';
num_lines= 1;
def     = {num2str(fMinMag),num2str(fMaxMag),'0.2'};
answer  = inputdlg(prompt,dlg_title,num_lines,def);
fMinMag = str2double(answer(1));
fMaxMag = str2double(answer(2));
fMagIncr = str2double(answer(3));

% Initialize
mResult = [];

fMag=fMinMag;
i=0;
figure_w_normalized_uicontrolunits('tag','schuster','Name','Schuster Walkout');
figure_w_normalized_uicontrolunits('tag','schuster2','Name','Schuster Walkout');
%n = floor((fMaxMag-fMag)/fMagIncr);
n = floor((fMaxMag-fMagIncr-fMag)/0.1)+2;
if mod(n,2) ~= 0
    fN=round(n/2);
else
    fN=floor(n/2);
end
while (fMag+fMagIncr) < (fMaxMag)
    % Calculate result matrix
    vSel = (mCatalog(:,6) >= fMag & mCatalog(:,6) < fMag+fMagIncr);
    mCat = mCatalog(vSel,:);
    [mWalkout, fR95, fProb, PHI, R] = calc_Schusterwalk(mCat);
    [vThetaWalkout,vRadWalkout] = cart2pol(mWalkout(:,1),mWalkout(:,2));
    fMaxRadius = max(abs(vRadWalkout(:,1)));
    mResult = [mResult; fMag+fMagIncr, fMaxRadius, max(abs(mWalkout(:,1))), max(abs(mWalkout(:,2))), fR95, fProb, R];

    % Subplot count
    i=i+1;
    figure_w_normalized_uicontrolunits(findobj('tag','schuster'));
    % Plot Schuster walkout
    subplot(fN,2,i)
    plot(mWalkout(:,1),mWalkout(:,2),'-','Color',[0.5 0.5 0.5]);
    hold on;
    polar([0:360]*pi/180,ones(1,361)*fR95,'--k');
    [x, y] =pol2cart(PHI,R);
    %plot([0,x],[0 y],'g');
    plot ([0 0],[-1/5*fR95,1/5*fR95],'k');
    plot ([-1/5*fR95,1/5*fR95],[0 0],'k');
%     hold off
%     text (0,2/5*fR95,'0:00','HorizontalAlignment','center');
%     text (2/5*fR95,0,'6:00','HorizontalAlignment','left');
%     text (0,-2/5*fR95,'12:00','HorizontalAlignment','center');
%     text (-2/5*fR95,0,'18:00','HorizontalAlignment','right');
%     text (0,fR95 ,'95KI','VerticalAlignment','bottom','HorizontalAlignment','center')
    axis square;
    sTitlestr = ['M = ' num2str(fMag) ' - ' num2str(fMag+fMagIncr)];
    title(sTitlestr);
    % Radius comparison for the plot
    sTextstr = [num2str(length(mCat(:,8))) ' / ' num2str(fMaxRadius/fR95)];
    text (-fR95,-fR95,sTextstr);

    % Plot hourly histogram
    figure_w_normalized_uicontrolunits(findobj('tag','schuster2'));
    subplot(n,1,i);
    vTime = (mCat(:,8)*60+mCat(:,9))/60; % Calculate decimal hour
    histogram(vTime,-0.5:1:24.5)
    fMag= fMag+0.1;
end % END of WHILE

% Select walkout > 95% level
try
    vSel = (mResult(:,2) >= mResult(:,5));
    mResOut = mResult(vSel,:);
    mDiffResOut=diff(mResOut);
    mDiffResOut(:,1) = round(mDiffResOut(:,1)*10)/10;
    [vIndice]=find(mDiffResOut(:,1) == 0.1);
    if isempty(vIndice)
        fMc = nan;
        fProbability = nan;
    else
        fMc = mResult(max(vIndice)+2,1); % Maximum value for Mc
        fProbability = mResult(max(vIndice)+2,6);
        for nCnt=length(vIndice):-1:2
            fdI = vIndice(nCnt)-vIndice(nCnt-1);
            if fdI > 1
                fMc = mResult(vIndice(nCnt-1)+2,1); % Find Mc
                fProbability = mResult(max(vIndice)+2,6);
            end
        end
    end
catch
    fMc = nan;
    fProbability = nan;
end


clear all; close all; clc

addpath('apm')

s = 'http://byu.apmonitor.com';
c = 'mpc';

% Connect to Arduino
tclab;

% Run time in minutes
run_time = 5.0;

% Number of cycles (1 cycle per 3 seconds)
loops = round(20*run_time);

% Temperature (degC)
T1 = ones(1,loops) * T1C(); % measured T
Tsp1 = ones(1,loops) * 30;
T2 = ones(1,loops) * T2C(); % measured T
Tsp2 = ones(1,loops) * 23;
time = zeros(1,loops);

% Changes in set point
Tsp1(50:end) = 40;
Tsp2(10:end) = 35;

% milli-volts input
Q1 = zeros(1,loops);
Q2 = zeros(1,loops);

% model predictive control initialization
mpc_init(s,c);

start_time = clock;
prev_time = start_time;

% dynamic plot (note: subplots needs to be declared here first)
figure(1)
subplot(3,1,1)
hold on, grid on
anexp1 = animatedline('LineStyle','-', 'Color', 'k', 'LineWidth', 2);
ansp1 = animatedline('LineStyle','--','Color', 'r','LineWidth', 2);
ylabel('Temperature \circC')
legend('T_1 Measured', 'T_1 Set Point', ...
    'Location', 'northwest')
subplot(3,1,2)
hold on, grid on
anexp2 = animatedline('LineStyle','-', 'Color', 'k', 'LineWidth', 2);
ansp2 = animatedline('LineStyle','--','Color', 'r','LineWidth', 2);
ylabel('Temperature \circC')
legend('T_2 Measured', 'T_2 Set Point', ...
    'Location', 'northwest')
subplot(3,1,3)
hold on, grid on
anQ1 = animatedline('LineStyle','-', 'Color', 'k', 'LineWidth', 2);
anQ2 = animatedline('LineStyle','--', 'Color', 'b', 'LineWidth', 2);
ylabel('Power Level Q (%)')
legend('Q_1', 'Q_2', 'Location', 'northwest')
xlabel('Time (sec)')

for ii = 1:loops
    % Pause Sleep time
    pause_max = 3.0;
    pause_time = pause_max - etime(clock,prev_time);
    if pause_time >= 0.0
        pause(pause_time - 0.01)
    else
        pause(0.01)
    end

    % Record time and change in time
    t = clock;
    dt = etime(t,prev_time);
    if ii>=2
        time(ii) = time(ii-1) + dt;
    end
    prev_time = t;

    % read and record from temperature controller
    T1(ii) = T1C();
    T2(ii) = T2C();

    % model predictive control
    [Q1(ii), Q2(ii)] = mpc2(T1(ii),Tsp1(ii),T2(ii),Tsp2(ii));

    % adjust power level
    h1(Q1(ii));
    h2(Q2(ii));

    % plot
    addpoints(anexp1,time(ii),T1(ii))
    addpoints(ansp1,time(ii),Tsp1(ii))
    addpoints(anexp2,time(ii),T2(ii))
    addpoints(ansp2,time(ii),Tsp2(ii))
    addpoints(anQ1,time(ii),Q1(ii))
    addpoints(anQ2,time(ii),Q2(ii))
    drawnow

    if ii==10
        apm_web(s,c);
    end
end

h1(0);
h2(0);
disp('Heaters off')
% turn off heater but keep LED on if T > 50
if (T1C() || T2C()) > 50
    led(1)
    disp(['Warning, heater temperature 1 =', num2str(T1C())])
    disp(['Warning, heater temperature 2 =', num2str(T2C())])
else
    led(0)
end

% save txt file with data
data = [time',Q1',Q2',T1',T2',Tsp1',Tsp2'];
csvwrite('data.txt',data);


function test16
%TEST16 test cholmod2 on a large matrix
% Example:
%   test16
% See also cholmod_test

% Copyright 2006-2007, Timothy A. Davis, University of Florida

fprintf ('=================================================================\n');
fprintf ('test16: test cholmod2 on a large matrix\n') ;

rand ('state',1) ;
randn ('state',1) ;

Prob = UFget (936)							    %#ok
A = Prob.A ;
% tic
% [L,s,p] = lchol (A) ;
% toc
% norm (L,1)

n = size (A,1) ;
b = rand (n,1) ;
tic
x = cholmod2(A,b) ;
t = toc ;
fprintf ('time %g\n', t) ;
err = norm (A*x-b) ;

if (err > 1e-5)
    error ('!') ;
end

fprintf ('test16 passed\n') ;


function [p] = ft_connectivity_plm(inputdata, varargin)

% FT_CONNECTIVITY_PLM computes the phase linearity measurement from a cell array of
% time-domain data, where each cell is an epoch. This implements the metric described
% in Baselice et al. "Phase Linearity Measurement: a novel index for brain functional
% connectivity", IEEE Transactions on Medical Imaging, 2018.
%
% Use as
%   [p] = ft_connectivity_plm(inputdata, ...)
%
% The input data input should be organized as a cell-array, one element for each
% epoch/repetition. Each cell should be a matrix of of nchan x nsamples values.
%
% Additional optional input arguments come as key-value pairs:
%   'bandwidth'	=	scalar, half-bandwidth parameter: the frequency range across which to integrate
%   'fsample'   = sampling frequency, needed to convert bandwidth to number of bins
%
% The output p contains the phase linearity measurement in the [0, 1] interval. It is
% organized as a 3D matrix of Nrpt x Nchan x Nchan dimensions.
%
% See also CONNECTIVITY, FT_CONNECTIVITYANALYSIS

% Copyright (C) 2018, Fabio Baselice, Pierpaolo Sorrentino, Jan-Mathijs Schoffelen
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip 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.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

% the sequence of steps is as follows:
%  - Hilbert transformation
%  - multiply with complex conjugate
%  - fft
%  - remove volume conduction component
%  - integrate over bandwidth

% NOTE BY JM: if the user inputs data with different length trials, the fft per trial is going
% to have different frequency resolutions, which is not good. Better to throw an error in that
% case.
fs = ft_getopt(varargin, 'fsample');
B = ft_getopt(varargin, 'bandwidth');
if isempty(fs)
  error('sampling rate is not defined');
end
if isempty(B)
  warning('bandwidth parameter is not defined, assumed 1Hz');
  B=1;
end

nsmp = cellfun('size', inputdata, 2);
assert(all(nsmp==nsmp(1)), 'currently there is no support for input, where the trials are of different length');

nrpt=numel(inputdata);
for k = 1:numel(inputdata)
  inputdata{k} = hilbert(inputdata{k}')';
end
% NOTE by JM: Is it expected that the data has been bandpassfiltered at
% this point? How would this be checked?

nchan=size(inputdata{1},1);
trial_length=size(inputdata{1},2);
ph_min=0.1;        % Eps of Eq.(17) of the manuscript
f=(fs/trial_length)*(0:(trial_length-1));
f_integr=(abs(f)<B) | (abs(f-fs)<B);
p=zeros(nchan, nchan, nrpt);

for ktime=1:nrpt
  for kchan1=1:(nchan-1)
    for kchan2=(kchan1+1):nchan
      temp=fft(inputdata{ktime}(kchan1,:).*conj(inputdata{ktime}(kchan2,:)));    % NOTE BY FB: The inner cycle can be vectorized
      temp(1)=temp(1).*(abs(angle(temp(1)))>ph_min);  % Volume conduction suppression
      temp=(abs(temp)).^2;
      p_temp=sum(temp(f_integr))./sum(temp);
      p(kchan1, kchan2, ktime)=p_temp;
      p(kchan2, kchan1, ktime)=p_temp;
    end
  end
end

p = permute(p, [3 1 2]); % permute to adhere to the conventional matrix shape of the ft_connectivity_* codebase


function A = MetricLearningAutotuneKnn(metric_learn_alg, y, X, params);
% function A = MetricLearningAutotuneKnn(metric_learn_alg, y, X, params);
%
% metric_learn_alg:
% Runs information-theoretic metric learning over various parameters of
% gamma, choosing that with the highest accuracy.
%
% Returns: Mahalanobis matrix A for learned distance metric

if (~exist('params')),
    params = struct();
end
params = SetDefaultParams(params);

% regularize to the identity matrix
A0 = eye(size(X, 2));

% define gamma values for slack variables
gammas = 10.^(-4:4);

accs = zeros(length(gammas), 1);
for (i=1:length(gammas)),
    disp(sprintf('\tTuning burg kernel learning: gamma = %f', gammas(i)));
    params.gamma = gammas(i);
    accs(i) = CrossValidateKNN(y, X, @(y,X) MetricLearning(metric_learn_alg, y, X, A0, params), 2, params.k);
end

[v,i] = max(accs);
gamma = gammas(i);
disp(sprintf('\tOptimal gamma value: %f', gamma));
params.gamma = gamma;
A = MetricLearning(metric_learn_alg, y, X, A0, params);


function varargout=airProp(T, prop)
%---------------------------------------------
% Interpolates thermodynamic air properties
% Temp. range: 250 - 1200 K
% According to W. C. Reynolds, cp. Heywood,
% Internal Combustion Engine Fundamentals,
% p. 127 and p. 912.
%
% Values are in SI-units:
%
% 	col-#	prop. 	units
%	------------------------
%	1		T		K
%	2		h		kJ/kg
%	3		u		kJ/kg
%	4		Psi		kJ/(kgK)
%	5		Fi		kJ/(kgK)
%	6		pr		-
%	7		vr		-
%	8		cp		kJ/(kgK)
%	9		cv		kJ/(kgK)
%
% Example 1:	out=airProp(304, 'Fi')
% Example 2:
% 		[h,u]=airProp([333 999],{'h' 'u'})
%---------------------------------------------
% (c)2004 by Stefan Billig
%---------------------------------------------
% Last Change:	19-May-2004
%---------------------------------------------

% check # of input arguments
if ~isequal(nargin,2)
	error('airProp requires 2 input arguments!')
	return
% check temperature request
elseif find(T<250) | find(T>1200) | ~isnumeric(T)
	error('Valid temperature range: 250 >= T[K] >= 1200')
	return
end
% get table
load propTabAir
% if multi property request
if iscell(prop)
	% scan along cells
	for idx=1:length(prop)
		% identify property column
		col=find(strcmp(propInfo,prop(idx)));
		if isempty(col)
			disp(['Property "' char(prop(idx)) '" not recognized!'])
		else
			% create output
			varargout{idx}=interp1(airTab(:,1),airTab(:,col),T);
		end
	end
% single property request
else
	% identify property column
	col=find(strcmp(propInfo,prop));
	if isempty(col)
		disp(['Property "' prop '" not recognized!'])
	else
		% create output
		varargout{1}=interp1(airTab(:,1),airTab(:,col),T);
	end
end


function p = prob_node(CPD, self_ev, pev)
% PROB_NODE Compute P(y|pa(y), theta) (tabular)
% p = prob_node(CPD, self_ev, pev)
%
% self_ev{m} is the evidence on this node in case m
% pev{i,m} is the evidence on the i'th parent in case m
% If there is a single case, self_ev can be a scalar instead of a cell array

ncases = size(pev, 2);

%assert(~any(isemptycell(pev))); % slow
%assert(~any(isemptycell(self_ev))); % slow

CPT = CPD_to_CPT(CPD);
sz = mysize(CPT);
nparents = length(sz)-1;
assert(nparents == size(pev, 1));

if ncases==1
  x = cat(1, pev{:});
  if iscell(y)
    y = self_ev{1};
  else
    y = self_ev;
  end
  switch nparents
   case 0, p = CPT(y);
   case 1, p = CPT(x(1), y);
   case 2, p = CPT(x(1), x(2), y);
   case 3, p = CPT(x(1), x(2), x(3), y);
   otherwise,
    ind = subv2ind(CPD.sizes, [x y]);
    p = CPT(ind);
  end
else
  x = num2cell(pev)'; % each row is a case
  y = cat(1, self_ev{:})';
  ind = subv2ind(CPD.sizes, [x y]);
  p = CPT(ind);
end


function [X,stat]=fix_state(x_float,x_fb)

nx=size(x_float,1);
X=zeros(nx,1); stat=1;

Cnb = att2Cnb(x_float(1:3));
Cnb = (eye(3)+askew(x_fb(1:3)))*Cnb;
if ~isreal(Cnb)
    stat=0; return;
end

att = Cnb2att(Cnb);
vel = x_float(4:6)-x_fb(4:6);
pos = x_float(7:9)-x_fb(7:9);
bg  = x_float(10:12)+x_fb(10:12);
ba  = x_float(13:15)+x_fb(13:15);

X(1:15,1)  = [att;vel;pos;bg;ba];
X(16:nx,1) = x_float(16:end)+x_fb(16:end);

return


function [J] = Btu2J(Btu)
% Convert energy or work from British thermal units to joules.
% Chad A. Greene 2012
J = Btu*1055.0559 ;


function [edata, adjlist, boundmap, perim] = mcmcGetDisjointEdgeData(imsegs, spdata, npertype, ignorelist)
% edata(nadj, nfeatures)
%   edata feature descriptions:
%      01 - 03: abs diff mean rgb
%      04 - 06: abs diff hsv conversion
%      07 - 07: chi-squared hue histogram
%      08 - 08: chi-squared sat histogram
%      09 - 23: abs diff mean texture response
%      24 - 24: chi-squared texture response histogram
%      25 - 26: abs diff mean x-y
%      27 - 27: smaller area / larger area

% spdata(nseg, nf)
%   spdata feature descriptions:
%      01 - 03: mean rgb
%      04 - 06: hsv conversion
%      07 - 11: hue histogram
%      12 - 14: sat histogram
%      15 - 29: mean texture response
%      30 - 44: texture response histogram
%      45 - 46: mean x-y
%      47 - 48: 10th, 90th perc. x
%      49 - 50: 10th, 90th perc. y
%      51 - 51: h / w
%      52 - 52: area

nfeatures = 27;

nseg = imsegs.nseg;

%[boundmap, perim] = mcmcGetSuperpixelBoundaries(imsegs);

nadj = nseg*(nseg-1)/2;

adjlist = zeros(nadj, 2);
edata = zeros(nadj, nfeatures);
c = 0;
for s1 = 1:nseg
    ns1 = nseg-s1;
    adjlist(c+1:c+ns1, 1) = s1;
    adjlist(c+1:c+ns1, 2) = [s1+1:nseg]';
    c = c + ns1;
end

[imh, imw] = size(imsegs.segimage);

for k = 1:nadj
    s1 = adjlist(k, 1);
    s2 = adjlist(k, 2);

    % differences of spdata
    %edata(k, 1:6) = abs(spdata(s1, 1:6) - spdata(s2, 1:6));
    edata(k, 7) = jensenshannon(spdata(s1, 7:11), spdata(s2, 7:11));
    %edata(k, 8) = jensenshannon(spdata(s1, 12:14), spdata(s2, 12:14));
    %edata(k, 9:23) = abs(spdata(s1, 15:29) - spdata(s2, 15:29));
    edata(k, 24) = jensenshannon(spdata(s1, 30:44), spdata(s2, 30:44));
    %edata(k, 25:26) = abs(spdata(s1, 45:46) - spdata(s2, 45:46));
    %edata(k, 27) = min(spdata([s1 s2], 52)) / max(spdata([s1 s2], 52));

end

% ignore adjacent sp (these are handeld in mcmcGetEdgeData)
keep = ones(nadj, 1);
if exist('ignorelist') && ~isempty(ignorelist)
    ignoremat = zeros(nseg);
    for k = 1:size(ignorelist, 1)
        ignoremat(ignorelist(k, 1), ignorelist(k, 2)) = 1;
    end
    for k = 1:nadj
        if ignoremat(adjlist(k, 1), adjlist(k, 2))
            keep(k) = 0;
        end
    end
    edata = edata(find(keep), :);
    adjlist = adjlist(find(keep), :);
end

% keep only top npertype edges for each type (color, texture)
keep = zeros(nadj, 1);
[val, ind] = sort(edata(:, 7), 'ascend'); % hue chi-square stat
keep(ind(1:npertype)) = 1;
[val, ind] = sort(edata(:, 24), 'ascend'); % texture chi-square stat
keep(ind(1:npertype)) = 1;
edata = edata(find(keep), :);
adjlist = adjlist(find(keep), :);

nadj = size(adjlist, 1);

for k = 1:nadj
    s1 = adjlist(k, 1);
    s2 = adjlist(k, 2);

    % differences of spdata
    edata(k, 1:6) = abs(spdata(s1, 1:6) - spdata(s2, 1:6));
    %edata(k, 7) = jensenshannon(spdata(s1, 7:11), spdata(s2, 7:11));
    edata(k, 8) = jensenshannon(spdata(s1, 12:14), spdata(s2, 12:14));
    edata(k, 9:23) = abs(spdata(s1, 15:29) - spdata(s2, 15:29));
    %edata(k, 24) = jensenshannon(spdata(s1, 30:44), spdata(s2, 30:44));
    edata(k, 25:26) = abs(spdata(s1, 45:46) - spdata(s2, 45:46));
    edata(k, 27) = min(spdata([s1 s2], 52)) / max(spdata([s1 s2], 52));
end

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

function x = chisquare(hist1, hist2)
x = sum((hist1-hist2).^2 ./ hist2);

function d = jensenshannon(hist1, hist2)
% Jensen-Shannon divergence (see wikipedia)
avehist = (hist1 + hist2)/2;
d = 0.5*(sum(hist1.*log(hist1./hist2)) + sum(hist2.*log(hist2./hist1)));


function [ xmax, ixmax ] = i4row_max ( m, n, x )

%*****************************************************************************80
%
%% I4ROW_MAX returns the maximums of rows of an I4ROW.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns in the array.
%
%    Input, integer X(M,N), the array to be examined.
%
%    Output, integer XMAX(M), the maximums of the rows of X.
%
%    Output, integer IXMAX(M); IXMAX(I) is the column of X in which
%    the maximum for row I occurs.
%
  for i = 1 : m

    ixmax(i) = 1;
    xmax(i) = x(i,1);
    for j = 2 : n
      if ( xmax(i) < x(i,j) )
        ixmax(i) = j;
        xmax(i) = x(i,j);
      end
    end

  end

  return
end


function [P] = spm_fp_fmin(M)
% optimises the parameters with respect to an equilibrium density
% FORMAT [P] = spm_fp_fmin(M)
%
% M   - model structure with desired density specified by M(1).fq and
%       support specified by M(1).X = spm_ndgrid(x)
%
% P   - optimised parameters
%
%--------------------------------------------------------------------------
% This routine uses EM (spm_nlsi_NG) and the Fokker Planck formulation to
% minimise the difference between the flow and dispersion terms induced by
% the free parameters of the flow (M(1),f).
%__________________________________________________________________________
% Copyright (C) 2005 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_fp_fmin.m 4136 2010-12-09 22:22:28Z guillaume $

% specify function returning the flow-dependent part of dp/dt 'spm_fp_fun'
%--------------------------------------------------------------------------
M      = M(1);
try, M = rmfield(M,'hE'); end
try, M = rmfield(M,'hC'); end
U      = [];
M.IS   = 'spm_fp_fun';

% Dispersion
%--------------------------------------------------------------------------
N     = size(M.X,1);
D     = inv(M.W)/2;
for i = 1:N
    Y.y(i,1) = trace(D*spm_cat(spm_diff(M.fq,M.X(i,:),[1 1])')');
end

% Optimise
%--------------------------------------------------------------------------
P     = spm_nlsi_GN(M,U,Y);


function [L,L_u,L_k] = pix2PluckerRay(k,u)

% PIX2PLUCKERRAY  Plucker ray from optical center through pixel.
%   PIX2PLUCKERRAY(K,U) is a Plucker line passing over pixel U and the
%   optical center, in a pin-Hole camera of intrinsic vector K.
%
%   [R, R_k, R_u] = PIX2PLUCKERRAY(...) returns the Jacobians wrt K and U.

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

if nargout == 1

    n = [0;0;0];
    v = invPinHole(u,1,k);

    L = [n;v];

else

    n = [0;0;0];
    [v,V_u,~,V_k] = invPinHole(u,1,k);

    L = [n;v];
    L_u = [zeros(3,2);V_u];
    L_k = [zeros(3,4);V_k];

end

return

%%
syms u1 u2 u0 v0 au av real
k = [u0;v0;au;av];
u = [u1;u2];

[L,L_u,L_k] = pix2PluckerRay(k,u);

simplify(L_u - jacobian(L,u))
simplify(L_k - jacobian(L,k))

% ========== 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 = vertcat(varargin)
% function C=vertcat(A,B);
%
% DESCRIPTION
%   Vertical concatenation of polynomial objects.
%
% INPUTS
%   A,B: polynomials
%
% OUTPUTS
%   C:  vertical concatenation of input matrices.
%
% SYNTAX
%   [A; B]
%      Vertical concatenation of polynomial matrices A and B.
%      A and B must have the same number of columns.
%   [A1; A2; A3; ...]
%      Vertical concatenation of several polynomial matrices.
%   C = vertcat(A1,A2,A3,..);
%      Function-call form of vertical concatenation.
%
% See also horzcat

% 6/8/2002: PJS  Initial Coding

if nargin==1
    c = varargin{1};
else
    % Promote a to polynomial
    a = polynomial(varargin{1});
    [nra,nca] = size(a);

    % Promote b to polynomial
    b = polynomial(varargin{2});
    [nrb,ncb] = size(b);

    if isempty(b);
        c = a;
    elseif isempty(a);
        c = b;
    elseif nca == ncb
        % Get Dimensions
        nta = size(a.degmat,1);
        nva = length(a.varname);
        ntb = size(b.degmat,1);
        nvb = length(b.varname);

        if nva==0 && nvb==0
            % Combine constant terms
            ar = combine(a);
            coef1 = reshape(ar.coefficient,[nra nca]);
            br = combine(b);
            coef2 = reshape(br.coefficient,[nrb ncb]);

            % Stack up Coefficients and Form Polynomial
            coefficient = [coef1; coef2];
            c = polynomial(coefficient);
        else
            % Form Degmat, Varname, and Matdim
            adeg = a.degmat;
            bdeg = b.degmat;
            degmat = blkdiag(adeg,bdeg);
            varname = [a.varname(:); b.varname(:)];
            matdim = [nra+nrb nca];

            % Stack up Coefficients
            idx1 = [];
            idx2 = [];
            for i1 = 0:(nca-1);
                idx1 = [idx1 (1:nra)+i1*(nra+nrb)];
                idx2 = [idx2 nra+(1:nrb)+i1*(nra+nrb)];
            end;
            coef1 = spalloc(nta,(nra+nrb)*nca,nnz(a.coefficient));
            coef1(:,idx1) = a.coefficient;
            coef2 = spalloc(ntb,(nra+nrb)*ncb,nnz(b.coefficient));
            coef2(:,idx2) = b.coefficient;
            coefficient = [coef1; coef2];

            % Form Polynomial and combine terms
            chkval = 0; % skip validity check
            c = polynomial(coefficient,degmat,varname,matdim,chkval);
            c = combine(c);
        end

    else
        error('All columns must have the same row dimension')
    end

    if nargin>2
        c = vertcat(c,varargin{3:end});
    end
end