classdef prtKernelStep < prtKernel

    properties (SetAccess = private)
        name = 'Kernel Step'; % RBF Kernel
        nameAbbreviation = 'Step'; % RBF
    end

    properties
        sigma = 1; % The inverse kernel width
    end

    methods (Access = protected, Hidden = true)
        function Obj = trainAction(Obj,ds)
            Obj.internalDataSet = ds;
            Obj.isTrained = true;
        end

        function dsOut = runAction(Obj,ds)
            if ~Obj.isTrained
                error('prtKernelRbf:run','Attempt to run an untrained kernel; use kernel.train(ds) to train');
            end
            if Obj.internalDataSet.nObservations == 0
                dsOut = prtDataSetClass;
            else
                gram = prtKernelStep.kernelFn(ds.getObservations,Obj.internalDataSet.getObservations);
                dsOut = ds.setObservations(gram);
            end
        end
    end

    methods
        function Obj = prtKernelStep(varargin)
            Obj = prtUtilAssignStringValuePairs(Obj,varargin{:});
        end

    end

    methods(Hidden = true)
        function varargout = plot(obj)
            x = obj.internalDataSet.getObservations;

            if size(x,2) <= 3
                if size(x,2) == 1 && obj.internalDataSet.isLabeled
                    xy = cat(2,x,obj.internalDataSet.getTargets);
                    h = prtPlotUtilScatter(xy, {}, obj.plotOptions.symbol, obj.plotOptions.markerFaceColor, obj.plotOptions.color, obj.plotOptions.symbolLineWidth, obj.plotOptions.symbolSize);
                else
                    h = prtPlotUtilScatter(x, {}, obj.plotOptions.symbol, obj.plotOptions.markerFaceColor, obj.plotOptions.color, obj.plotOptions.symbolLineWidth, obj.plotOptions.symbolSize);
                end
            else
                h = nan;
            end

            varargout = {};
            if nargout
                varargout = {h};
            end
        end
    end

    methods (Static, Hidden = true)
        function gram = kernelFn(x,y)
            [n1, d] = size(x);
            [n2, nin] = size(y);
            if d ~= nin
                error('size(x,2) must equal size(y,2)');
            end

            gram = true(n1,n2);
            for dim = 1:d;
                gram = gram & bsxfun(@(x,y) x > y,x(:,d),y(:,d)');
            end
            gram = double(gram);
%             gram = imfilter(gram,fspecial('gaussian',[11,1],4));

        end
    end
end


function halham_write ( dim_num, n, step, seed, leap, base, r, file_out_name )

%*****************************************************************************80
%
%% HALHAM_WRITE writes a Halton or Hammersley dataset to a file.
%
%  Discussion:
%
%    The initial lines of the file are comments, which begin with a
%    '#' character.
%
%    Thereafter, each line of the file contains the DIM_NUM-dimensional
%    components of the next entry in the dataset.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the spatial dimension.
%
%    Input, integer N, the number of elements in the subsequence.
%
%    Input, integer STEP, the index of the subsequence element.
%    0 <= STEP is required.
%
%    Input, integer SEED(DIM_NUM), the sequence index corresponding
%    to STEP = 0.
%
%    Input, integer LEAP(DIM_NUM), the successive jumps in the sequence.
%
%    Input, integer BASE(DIM_NUM), the bases.
%
%    Input, real R(DIM_NUM,N), the points.
%
%    Input, string FILE_OUT_NAME, the name of
%    the output file.
%
  file_out_unit = fopen ( file_out_name, 'w' );

  if ( file_out_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'HALHAM_WRITE - Fatal error!\n' );
    fprintf ( 1, '  Could not open the output file:\n' );
    fprintf ( 1, '  "%s".\n', file_out_name );
    error ( 'HALHAM_WRITE - Fatal error!' );
  end

  fprintf ( file_out_unit, '#  %s\n', file_out_name );
  fprintf ( file_out_unit, '#  created by HALHAM_WRITE.M\n' );
  fprintf ( file_out_unit, '#\n' );
  fprintf ( file_out_unit, '#  DIM_NUM = %d\n', dim_num );
  fprintf ( file_out_unit, '#  N =    %d\n', n );
  fprintf ( file_out_unit, '#  STEP = %d\n', step );

  for mlo = 1 : 5 : dim_num
    mhi = min ( mlo + 5 - 1, dim_num );
    if ( mlo == 1 )
      fprintf ( file_out_unit, '#  SEED = ' );
    else
      fprintf ( file_out_unit, '#         ' );
    end
    for i = mlo : mhi
      fprintf ( file_out_unit, '  %12d', seed(i) );
    end
    fprintf ( file_out_unit, '\n' );
  end
  for mlo = 1 : 5 : dim_num
    mhi = min ( mlo + 5 - 1, dim_num );
    if ( mlo == 1 )
      fprintf ( file_out_unit, '#  LEAP = ' );
    else
      fprintf ( file_out_unit, '#         ' );
    end
    for i = mlo : mhi
      fprintf ( file_out_unit, '  %12d', leap(i) );
    end
    fprintf ( file_out_unit, '\n' );
  end
  for mlo = 1 : 5 : dim_num
    mhi = min ( mlo + 5 - 1, dim_num );
    if ( mlo == 1 )
      fprintf ( file_out_unit, '#  BASE = ' );
    else
      fprintf ( file_out_unit, '#         ' );
    end
    for i = mlo : mhi
      fprintf ( file_out_unit, '  %12d', base(i) );
    end
    fprintf ( file_out_unit, '\n' );
  end
  fprintf ( file_out_unit, '#\n' );

  for j = 1 : n
    for i = 1 : dim_num
      fprintf ( file_out_unit, '  %10f', r(i,j) );
    end
    fprintf ( file_out_unit, '\n' );
  end

  fclose ( file_out_unit );

  return
end


function bnet = mk_limid(dag, node_sizes, varargin)
% MK_LIMID Make a limited information influence diagram
%
% BNET = MK_LIMID(DAG, NODE_SIZES, ...)
% DAG is the adjacency matrix for a directed acyclic graph.
% The nodes are assumed to be in topological order. Use TOPOLOGICAL_SORT if necessary.
% For decision nodes, the parents must explicitely include all nodes
% on which it can depends, in contrast to the implicit no-forgetting assumption of influence diagrams.
% (For details, see "Representing and solving decision problems with limited information",
%    Lauritzen and Nilsson, Management Science, 2001.)
%
% node_sizes(i) is the number of values node i can take on,
%   or the length of node i if i is a continuous-valued vector.
% node_sizes(i) = 1 if i is a utility node.
%
% The list below gives optional arguments [default value in brackets].
%
% chance   - the list of nodes which are random variables [1:N]
% decision - the list of nodes which are decision nodes [ [] ]
% utility  - the list of nodes which are utility nodes [ [] ]
% equiv_class - equiv_class(i)=j  means node i gets its params from CPD{j} [1:N]
%
% e.g., limid = mk_limid(dag, ns, 'chance', [1 3], 'utility', [2])

n = length(dag);

% default values for parameters
bnet.chance_nodes = 1:n;
bnet.equiv_class = 1:n;
bnet.utility_nodes = [];
bnet.decision_nodes = [];
bnet.dnodes = 1:n; % discrete

if nargin >= 3
  args = varargin;
  nargs = length(args);
  if ~isstr(args{1})
    if nargs >= 1, bnet.dnodes = args{1}; end
    if nargs >= 2, bnet.equiv_class = args{2}; end
  else
    for i=1:2:nargs
      switch args{i},
       case 'equiv_class', bnet.equiv_class = args{i+1};
       case 'chance',      bnet.chance_nodes = args{i+1};
       case 'utility',     bnet.utility_nodes = args{i+1};
       case 'decision',    bnet.decision_nodes = args{i+1};
       case 'discrete',    bnet.dnodes = args{i+1};
        otherwise,
	error(['invalid argument name ' args{i}]);
      end
    end
  end
end

bnet.limid = 1;

bnet.dag = dag;
bnet.node_sizes = node_sizes(:)';

bnet.cnodes = mysetdiff(1:n, bnet.dnodes);
% too many functions refer to cnodes to rename it to cts_nodes -
% We hope it won't be confused with chance nodes!

bnet.parents = cell(1,n);
for i=1:n
  bnet.parents{i} = parents(dag, i);
end

E = max(bnet.equiv_class);
mem = cell(1,E);
for i=1:n
  e = bnet.equiv_class(i);
  mem{e} = [mem{e} i];
end
bnet.members_of_equiv_class = mem;

bnet.CPD = cell(1, E);

% for e=1:E
%   i = bnet.members_of_equiv_class{e}(1); % pick arbitrary member
%   switch type{e}
%     case 'tabular',  bnet.CPD{e} = tabular_CPD(bnet, i);
%     case 'gaussian', bnet.CPD{e} = gaussian_CPD(bnet, i);
%     otherwise, error(['unrecognized CPD type ' type{e}]);
%   end
% end

directed = 1;
if ~acyclic(dag,directed)
  error('graph must be acyclic')
end

bnet.order = topological_sort(bnet.dag);


function handle = vwhist(x,y,dx,dy,direction,FaceColor,EdgeColor)
%VWHIST   Variable width histogram
%   Draws a variable width histogram.
%   Does not calculate data, it is just a drawing utility.
%   Draws histogram with defined x, so data length(data)=length(x)-1,
%   or, if lengths are equal, bars are centred at x.
%
%   Syntax:
%      HANDLES = VWHIST(X,Y,DX,DY,DIREC,FaceColor,EdgeColor)
%
%   Inputs:
%      X           X locations
%      Y           Data
%      DX, DY      Offset added to bars [ 0 ]
%      DIREC       Direction, horizontal or vertical [ {0} | 1 ]
%      FaceColor   Bars FaceColor [ 'y' ]
%      EdgeColor   Bars EdgeColor [ 'r' ]
%
%   Output:
%      HANDLES   Handles to fill objects (bars)
%
%   Example:
%      x= [1.5 3 4 6 7 7.5];
%      y =[  3  7  2  0 3  ];
%      figure,
%
%      subplot(2,2,1)
%      handle = vwhist(x,y);
%      axis([0 10 0 10]);
%
%      subplot(2,2,2)
%      handle = vwhist(x,y,0,2,1); set(handle,'facecolor','g');
%      axis([0 10 0 10]);
%
%      y = [4 y];
%      subplot(2,2,3)
%      handle = vwhist(x,y,0,2); set(handle,'facecolor','w')
%      axis([0 10 0 10]);
%
%
%   MMA 8-10-2004, martinho@fis.ua.pt

%   Department of physics
%   University of Aveiro, Portugal

handle=[];

if nargin < 7
  EdgeColor = 'r';
end
if nargin < 6
  FaceColor = 'y';
end
if nargin < 5
  direction = 0;
end
if nargin < 4
  dy = 0;
end
if nargin < 3
  dx = 0;
end
if nargin < 2
  y = x;
  x=1:length(y);
end
if nargin < 1
  disp('# nothing to do...');
end

% check lengths:
nx = length(x);
ny = length(y);

if nx == ny
  x_ = (x(2:end)+x(1:end-1))/2;
  dx1 = x_(1) - x(1);
  dxe = x(end) - x_(end);
  x = [x(1)-dx1 x_ x(end)+dxe];
elseif nx ~= ny+1
  disp('# wrong lengths of x and y, nx=ny or nx=ny+1, only')
end

for i=1:length(x)-1
  xx = [x(i) x(i+1) x(i+1) x(i) x(i) ] + dx;
  yy = [0    0      y(i)   y(i) 0    ] + dy;

  if ~direction
    handle(i) = fill(xx,yy,FaceColor);
  else
    handle(i) = fill(yy,xx,FaceColor);
  end
  set(handle(i),'EdgeColor',EdgeColor);
  if i==1
    h = ishold;
    hold on
  end
end

if ~h
  hold off
end


function results = vl_test_imwbackward(varargin)
% VL_TEST_IMWBACKWARD
vl_test_init ;

function s = setup()
s.I = im2double(imread(fullfile(vl_root,'data','spots.jpg'))) ;

function test_identity(s)
xr = 1:size(s.I,2) ;
yr = 1:size(s.I,1) ;
[x,y] = meshgrid(xr,yr) ;
vl_assert_almost_equal(s.I, vl_imwbackward(xr,yr,s.I,x,y)) ;

function test_invalid_args(s)
xr = 1:size(s.I,2) ;
yr = 1:size(s.I,1) ;
[x,y] = meshgrid(xr,yr) ;
vl_assert_exception(@() vl_imwbackward(xr,yr,single(s.I),x,y), 'vl:invalidArgument') ;


classdef prtPreProcLabelVoting < prtPreProc
    % Switches labels of the training data to be the most popular label amoungst k neihbors
    % This isn't necessarily a great idea but it has been proposed by several people.
    %
    % Example:
    %
    % ds = prtDataGenXor;
    %
    % eta = 0.2;
    % flipLabel = rand(ds.nObservations,1) < eta;
    %
    % newY = ds.Y;
    % newY((ds.Y == 0) & flipLabel) = 1;
    % newY((ds.Y == 1) & flipLabel) = 0;
    %
    % dsFlippedY = ds;
    % dsFlippedY.Y = newY;
    %
    % class = train(prtClassMap('rvs',prtRvGmm('nComponents',2)), dsFlippedY);
    %
    % subplot(1,2,1)
    % plot(class)
    %
    % class = train(prtPreProcLabelVoting('k',10) + prtClassMap('rvs',prtRvGmm('nComponents',2)), dsFlippedY);
    %
    % subplot(1,2,2)
    % plot(class.actionCell{2})

    properties (SetAccess=private)
        name = 'Label Voting'
        nameAbbreviation = 'LVNN'
    end
    properties
        k = 3;
    end

    methods
        function self = prtPreProcLabelVoting(varargin)
            self = prtUtilAssignStringValuePairs(self, varargin{:});
        end
    end
    methods (Access=protected,Hidden=true)
        function self = preTrainProcessing(self,DataSet)
            if ~self.verboseStorage
                warning('prtPreProcLabelVoting:verboseStorage:false','prtPreProcLabelVoting requires verboseStorage to be true; overriding manual settings');
            end
            self.verboseStorage = true;
            self = preTrainProcessing@prtPreProc(self,DataSet);
        end
        function self = trainAction(self,~)
            %Do nothing; we've already specified "verboseStorage = true",
            %so the ".dataSet" field will be set when it comes time to test
        end

        function ds = runActionOnTrainingData(self, ds)

            distanceMat = prtDistanceEuclidean(ds.X,ds.X);
            [~,I] = sort(distanceMat,1,'ascend');
            I = I(1:self.k+1,:);
            L = ds.Y(I);

            if self.k ~= 1
                L = L';
            end
            L = L(:,2:end); % First one is yourself...

            uClasses = ds.uniqueClasses;
            confOut = zeros(size(L,1), ds.nClasses);
            for iY = 1:ds.nClasses
                confOut(:,iY) = sum(L == uClasses(iY),2);
            end
            [~, classInd] = max(confOut,[],2);

            ds.Y = uClasses(classInd);

        end
        function ds = runAction(~, ds)
            % Nadda
        end
    end
end


function [nodesBF, rangeLoc, rangeOut] = treeBFranges(wt,varargin)
%TREEBFRANGES Tree nodes output ranges in BF order
%   Usage: [nodesBF, rangeLoc, rangeOut] = treeBFranges(wt);
%          [nodesBF, rangeLoc, rangeOut] = treeBFranges(wt,'rev');
%
%   Input parameters:
%         wt       : Filterbank tree struct.
%   Output parameters:
%         nodesBF  : All nodes in a breadth-first order
%         rangeLoc : Local ranges of unconnected (terminal) outputs
%         rangeOut : Global ranges of unconnected (terminal) outputs
%
%   `[nodesBF, rangeLoc, rangeOut] = treeBFranges(wt)` is a helper function
%   extracting all nodes of a tree in a BF order (root and low-pass first)
%   (numeric array of indexes `nodesBF`), and two cell arrays of ranges of
%   outputs. Each element of `rangeLoc` specifies range of unconnected
%   outputs of a node with at the corresponding position in `nodesBF`.
%   Elements `rangeOut` specify contain the resulting global indexes
%   (in the resulting coefficient cell array) of such unconnected nodes.
%
%   `[nodesBF, rangeLoc, rangeOut] = treeBFranges(wt,'rev')` does the same
%   but the arrays are reversed.

nodesBF = nodeBForder(0,wt);
do_rev = 0;
if ~isempty(varargin(strcmp('rev',varargin)));
   nodesBF = fliplr(nodesBF);
   do_rev = 1;
end

rangeLoc = nodesLocOutRange(nodesBF,wt);

rangeOut = treeOutRange(wt);
if do_rev
    %rangeOut = nodesOutRange(nodesBF,wt);
    rangeOut = rangeOut(end:-1:1);
end


function c=voigtUnMap(cVoigt)

if isvector(cVoigt) %assume that c is a 4th order tensor
    siz_c=[3 3];
    cVoigt(4:end)=(1/2).*cVoigt(4:end); %Undo doubling
else
    siz_c=[3 3 3 3];
end

[linearIndexVoigt,linearIndexFourthOrder]=tensor2voigtMap(zeros(siz_c));

switch class(cVoigt)
    case 'double'
        c=zeros(siz_c);
    case 'sym'
        c=sym(zeros(siz_c));
end

c(linearIndexFourthOrder)=cVoigt(linearIndexVoigt);

end

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


function edges=meshedge(elem,varargin)
%
% edges=meshedge(elem,opt)
%
% return all edges in a surface or volumetric mesh
%
% author: Qianqian Fang, <q.fang at neu.edu>
% date: 2011/02/26
%
% input:
%    elem:  element table of a mesh (support N-d space element)
%    opt: optional input, giving the additional options. If opt
%         is a struct, it can have the following field:
%       opt.nodeorder: if 1, assuming the elem node indices is in CCW
%                      orientation; 0 use nchoosek() output to order edges
%         you can replace opt by a series of ('param', value) pairs.
%
% output:
%    edge:  edge list; each row is an edge, specified by the starting and
%           ending node indices, the total edge number is
%           size(elem,1) x nchoosek(size(elem,2),2). All edges are ordered
%           by looping through each element first.
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

dim=size(elem);
edgeid=nchoosek(1:dim(2),2);
len=size(edgeid,1);
edges=zeros(dim(1)*len,2);
for i=0:len-1
    edges((i*dim(1)+1):((i+1)*dim(1)),:)=[elem(:,edgeid(i+1,1)) elem(:,edgeid(i+1,2))];
end


function [ y2, m2, d2, f2 ] = yjf_to_ymdf_common ( y1, j1, f1 )

%*****************************************************************************80
%
%% YJF_TO_YMDF_COMMON converts a Common date from YJF to YMDF format.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer Y1, J1, real F1, the YJF date.
%
%    Output, integer Y2, M2, D2, real F2,
%    the YMDF date.
%

%
%  Copy the input.
%
  y2 = y1;
  j2 = j1;
  f2 = f1;
%
%  Check the input.
%
  [ y2, j2, f2, ierror ] = yjf_check_common ( y2, j2, f2 );

  if ( ierror ~= 0 )
    y2 = 0;
    m2 = 0;
    d2 = 0;
    f2 = 0.0;
    return
  end
%
%  Convert the input.
%
  d2 = j2;
  m2 = 1;

  [ y2, m2, d2 ] = day_borrow_common ( y2, m2, d2 );

  [ y2, m2, d2 ] = day_carry_common ( y2, m2, d2 );

  return
end


function FeatureDetection(wkdir, dataset)
% Detect and save DoG keypoints

disp('Detecting keypoints...');

dataset_dir = [wkdir 'Dataset/' dataset '/'];

feature_dir = [wkdir 'Features/' dataset '/'];
if exist(feature_dir, 'dir') == 0
    mkdir(feature_dir);
end

pairs_gts = dlmread([dataset_dir 'pairs_with_gt.txt']);
pairs_which_dataset = importdata([dataset_dir 'pairs_which_dataset.txt']);

pairs = pairs_gts(:,1:2);
l_pairs = pairs(:,1);
r_pairs = pairs(:,2);

num_pairs = size(pairs,1);
for idx = 1 : num_pairs
    l = l_pairs(idx);
    r = r_pairs(idx);

    I1 = imread([dataset_dir pairs_which_dataset{idx} 'Images/' sprintf('%.8d.jpg', l)]);
    I2 = imread([dataset_dir pairs_which_dataset{idx} 'Images/' sprintf('%.8d.jpg', r)]);

    if size(I1,3) == 3
        I1gray = rgb2gray(I1);
    else
        I1gray = I1;
    end

    if size(I2,3) == 3
        I2gray = rgb2gray(I2);
    else
        I2gray = I2;
    end

    path_l = [feature_dir sprintf('%.4d_l', idx)];
    path_r = [feature_dir sprintf('%.4d_r', idx)];

    if exist([path_l '.keypoints'], 'file') == 2 && exist([path_r '.keypoints'], 'file') == 2
        continue;
    end

    keypoints_l = vl_sift(single(I1gray))';
    write_keypoints([path_l '.keypoints'], keypoints_l);

    keypoints_r = vl_sift(single(I2gray))';
    write_keypoints([path_r '.keypoints'], keypoints_r);
end

disp('Finished.');
end


classdef TestEllipse2Poly
    %TestEllipse2Poly

    methods (Static)
        function test_1
            pts = cv.ellipse2Poly([64,64], [20,10]);
            validateattributes(pts, {'numeric'}, ...
                {'2d', 'size',[NaN 2], 'integer'});
        end

        function test_2
            pts = cv.ellipse2Poly([64,64], [20,10], 'Angle',30, ...
                'StartAngle',15, 'EndAngle',200, 'Delta',2);
            validateattributes(pts, {'numeric'}, ...
                {'2d', 'size',[NaN 2], 'integer'});
        end

        function test_3
            pts = cv.ellipse2Poly([64,64], [20,10], 'DoublePrecision',true);
            validateattributes(pts, {'numeric'}, ...
                {'2d', 'size',[NaN 2], 'real'});
        end

        function test_error_argnum
            try
                cv.ellipse2Poly();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


function F = diff(F, dim, n)
%DIFF   Componentwise derivative of a SPHEREFUNV.
%   DIFF(F) is the tangetial derivative of each component of F in
%   x-direction.
%
%   DIFF(F, DIM) is the first tangential derivative of F along the
%   dimension DIM.
%     DIM = 1 (default) is the derivative in the x-direction.
%     DIM = 2 is the derivative in the y-direction.
%     DIM = 3 is the derivative in the z-direction.
%
%   DIFF(F, DIM, N) is the Nth tangential derivative of each component of F
%   along the dimension specified.
%
%   See also SPHEREFUNV/CURL and SPHEREFUNV/DIV.

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

% Empty check:
if ( isempty(F) )
    return
end

% Defaults:
if ( nargin == 1 || isempty(dim) )
    dim = 1;
end
if ( nargin < 3 )
    n = 1;
end

% Diff each component.
for j = 1:F.nComponents
    F.components{j} = diff(F.components{j}, dim, n);
end

end


function gX = rbfperiodicKernDiagGradX(kern, X)

% RBFPERIODICKERNDIAGGRADX Gradient of RBFPERIODIC kernel's diagonal with respect to X.
% FORMAT
% DESC computes the gradient of the diagonal of the RBF derived periodic kernel matrix with
% respect to the elements of the design matrix given in X.
% ARG kern : the kernel structure for which gradients are being computed.
% ARG X : the input data in the form of a design matrix.
% RETURN gX : the gradients of the diagonal with respect to each element
% of X. The returned matrix has the same dimensions as X.
%
% SEEALSO : rbfperiodicKernParamInit, kernDiagGradX, rbfperiodickernGradX
%
% COPYRIGHT : Neil D. Lawrence, 2007

% KERN

gX = zeros(size(X));


function [ epsilon_soft, time_sum, compressIndex  ] = Uniform_loopCompress( lamda, qFile, filesDir, cut_num, totalNum, bValue, saveDir )
%LOOPCOMPRESS Summary of this function goes here
%   Detailed explanation goes here

    fileExt = '*.txt';
    files = dir(fullfile(filesDir,fileExt));

    splitLength =  floor(length(files) / cut_num);

    q_file_t = fopen(qFile);
    observe_value = fscanf(q_file_t, '%d');
    fclose(q_file_t);
    observe_value(find(observe_value > 100)) = 100;  % remove some unusual counts
    q_value = (1 - mapminmax(observe_value', 0, 1))';  % actually same as in CVPR_W 2013

    time_sum = 0;
    saveCnt = 0;
    epsilon_soft = [];

    for i=0:splitLength:length(files)-1
        disp('-----------------------------------------------------------------------');
        start = i;
        finish = i + splitLength - 1;
        % for the last section
        if finish > (length(files) - splitLength) % last section will be longer than others
            finish = length(files) - 1;
        end
        disp(start);
        disp(finish);

        % core
        [compressIndex, time_sec, epsilon_part] = section_compress(lamda, q_value, filesDir, start, finish, totalNum, bValue);
        time_sum = time_sum + time_sec;
        saveName = [saveDir, num2str(saveCnt), '.txt'];
        dlmwrite(saveName, compressIndex, 'precision', '%d');

        % soft part
        epsilon_soft  = [epsilon_soft;epsilon_part];

        disp('Compressed & Saved')
        saveCnt = saveCnt + 1;

        % added fucked!
        if finish == length(files) - 1
            break; % jump out the fucking looping
        end

    end

    disp('All time of programming:');
    disp(time_sum)

end


function x = meyer(p, data1, data2)
  n=16;

% data1, data2 are actually unused

  for i=1:n
    ui=0.45+0.05*i;
    x(i)=p(1)*exp(10.0*p(2)/(ui+p(3)) - 13.0);
  end


classdef FiveLinkAnimator < Animator.AbstractAnimator
    properties
        leg1Color = 'r';
        leg2Color = 'b';
        torsoColor = 'k';
        groundColor = 'g';
    end

    properties (Access = private)
        ground;

        pH_RKnee;
        pH_LKnee;
        pRKnee_RFoot;
        pLKnee_LFoot;
        pHT;

        text;

        starting_index;
        next_frame_time;

        H;

        q_all;
        t_all;
    end

    properties
        updateWorldPosition logical
    end

    methods
        function obj = FiveLinkAnimator(t, q, varargin)
            obj = obj@Animator.AbstractAnimator(); % Calling super constructor

            obj.q_all = q;
            obj.t_all = t;

            obj.startTime = t(1);
            obj.currentTime = obj.startTime;
            obj.endTime = t(end);
            obj.updateWorldPosition = false;

            if isempty(varargin)
                [terrain.Tx, terrain.Ty] = meshgrid(-10:1:10, -10:1:10);
                terrain.Tz = 0.*terrain.Tx;
            else
                terrain = varargin{1};
            end

            Rz = @(th) [cos(th), -sin(th), 0; sin(th), cos(th), 0; 0,0,1];
            Ry = @(th) [cos(th), 0, sin(th); 0, 1, 0; -sin(th), 0, cos(th)];
            Rx = @(th) [1,0,0; 0, cos(th), -sin(th); 0, sin(th), cos(th)];

            r = obj.q_all(1:3, end) - obj.q_all(1:3, 1);
            th = obj.q_all(4:6, end) - obj.q_all(4:6, 1);
            obj.H = [Rx(th(1))*Ry(th(2))*Rz(th(3)), r; 0,0,0,1];

            % Initialization
            q = obj.q_all(:,1);

            pH = [q(1);0;q(2)];
            pT = p_Torso(q);
            pRK = p_q2_right(q);
            pLK = p_q2_left(q);
            pR = p_RightToe(q);
            pL= p_LeftToe(q);

            % Define Terrain
            obj.ground = surf(terrain.Tx,terrain.Ty,terrain.Tz); hold on;

            % Define links
            obj.pH_RKnee = line([0,0],[pH(1) pRK(1)],[pH(3) pRK(3)]);
            obj.pH_LKnee = line([0,0],[pH(1) pLK(1)],[pH(3) pLK(3)]);
            obj.pRKnee_RFoot = line([0,0],[pRK(1) pR(1)],[pRK(3) pR(3)]);
            obj.pLKnee_LFoot = line([0,0],[pLK(1) pL(1)],[pLK(3) pL(3)]);
            obj.pHT = line([0,0],[pH(1) pT(1)],[pH(3) pT(3)]);

            set(obj.pH_RKnee,'LineWidth',3,'Color',obj.leg1Color);
            set(obj.pH_LKnee,'LineWidth',3,'Color',obj.leg2Color);
            set(obj.pRKnee_RFoot,'LineWidth',3,'Color',obj.leg1Color);
            set(obj.pLKnee_LFoot,'LineWidth',3,'Color',obj.leg2Color);
            set(obj.pHT,'LineWidth',3,'Color',obj.torsoColor);

        end

        function Draw(obj, t, x)
            q = x;

            pH = [q(1);0;q(2)];
            pT = p_Torso(q);
            pRK = p_q2_right(q);
            pLK = p_q2_left(q);
            pR = p_RightToe(q);
            pL= p_LeftToe(q);

            set(obj.pH_RKnee,'YData',[pH(1) pRK(1)],'ZData',[pH(3) pRK(3)], 'XData',[0 0]);
            set(obj.pH_LKnee,'YData',[pH(1) pLK(1)],'ZData',[pH(3) pLK(3)],'XData',[0 0]);
            set(obj.pRKnee_RFoot,'YData',[pRK(1) pR(1)],'ZData',[pRK(3) pR(3)],'XData',[0 0]);
            set(obj.pLKnee_LFoot,'YData',[pLK(1) pL(1)],'ZData',[pLK(3) pL(3)],'XData',[0 0]);
            set(obj.pHT,'YData',[pH(1) pT(1)],'ZData',[pH(3) pT(3)],'XData',[0 0]);

            delete(obj.text);
            obj.text = text(0,pH(1),pH(3)+1,['t = ',sprintf('%.2f',t)]);
            obj.text.FontSize = 14;
            obj.text.FontWeight = 'Bold';
            obj.text.Color = [0,0,0];
            %  set(obj.text);

            drawnow;
        end

        function x = GetData(obj, t)
            t_start = obj.t_all(1);
            t_end = obj.t_all(end);
            delta_t = t_end - t_start;

            val = 0;

            if t < t_start || t > t_end
                val = floor((t - t_start) / delta_t);
                t = t - val * delta_t;
            end

            if t < t_start
                t = t_start;
            elseif t > t_end
                t = t_end;
            end

            n = length(obj.t_all);
            x = obj.q_all(:, 1); % Default

            a = 1;
            b = n;

            while (a <= b)
                c = floor((a + b) / 2);

                if t < obj.t_all(c)
                    x = obj.q_all(:, c);
                    b = c - 1;
                elseif t > obj.t_all(c)
                    a = c + 1;
                else
                    x = obj.q_all(:, c);
                    break;
                end
            end

            delta_q = obj.q_all(1:6, end) - obj.q_all(1:6, 1);

            %T = obj.H(1:3,4);
            %roll = atan2(-obj.H(2,3),obj.H(3,3));
            %pitch = asin(obj.H(1,3));
            %yaw = atan2(-obj.H(1,2),obj.H(1,1));

            if obj.updateWorldPosition
                Rz = @(th) [cos(th), -sin(th), 0; sin(th), cos(th), 0; 0,0,1];
                Ry = @(th) [cos(th), 0, sin(th); 0, 1, 0; -sin(th), 0, cos(th)];
                Rx = @(th) [1,0,0; 0, cos(th), -sin(th); 0, sin(th), cos(th)];

                x_orig_init = obj.q_all(1:6, 1);
                x_current_init = obj.q_all(1:6, 1);
                if val > 0
                    for i = 1:val
                        x_end = obj.q_all(1:6, end);

                        r1 = x_current_init(1:3) - x_orig_init(1:3);
                        th1 = x_current_init(4:6) - x_orig_init(4:6);
                        H1 = [Rx(th1(1))*Ry(th1(2))*Rz(th1(3)), r1; 0,0,0,1];

                        r2 = x_end(1:3) - x_orig_init(1:3);
                        th2 = x_end(4:6) - x_orig_init(4:6);
                        H2 = [Rx(th2(1))*Ry(th2(2))*Rz(th2(3)), r2; 0,0,0,1];

                        H = H1*H2;
                        T = H(1:3,4);
                        roll = atan2(-H(2,3),H(3,3));
                        pitch = asin(H(1,3));
                        yaw = atan2(-H(1,2),H(1,1));

                        x_current_init = x_orig_init(1:6) + [T;roll;pitch;yaw];
                    end

                    x_current = x(1:6);

                    r1 = x_current_init(1:3) - x_orig_init(1:3);
                    th1 = x_current_init(4:6) - x_orig_init(4:6);
                    H1 = [Rx(th1(1))*Ry(th1(2))*Rz(th1(3)), r1; 0,0,0,1];

                    r2 = x_current(1:3) - x_orig_init(1:3);
                    th2 = x_current(4:6) - x_orig_init(4:6);
                    H2 = [Rx(th2(1))*Ry(th2(2))*Rz(th2(3)), r2; 0,0,0,1];

                    H = H1*H2;
                    T = H(1:3,4);
                    roll = atan2(-H(2,3),H(3,3));
                    pitch = asin(H(1,3));
                    yaw = atan2(-H(1,2),H(1,1));

                    x(1:6) = x_orig_init(1:6) + [T;roll;pitch;yaw];
                end
            end
        end

        function [center, radius, yaw] = GetCenter(obj, t, x)
            q = x;

            center = [0; q(1:2)];
            radius = 1.5;
            yaw = 0;
        end
    end
end


% This file is part of the project NILM-Eval (https://github.com/beckel/nilm-eval).
% Licence: GPL 2.0 (http://www.gnu.org/licenses/gpl-2.0.html)
% Copyright: ETH Zurich, 2014
% Author: Christian Beckel;

figure_path = 'projects/buildsys/images/pie_chart/';
fontsize = 9;
% width = 4.8;
% height = 4.8;
households = [ 5 ];
if ~exist(figure_path, 'dir')
    mkdir(figure_path);
end

for household = households
    %params
    dataset = 'eco';
    % evalDays_type = 'completeSM_first90';
    evalDays_type = 'plug_statistics';
    granularity = 1;

    path_to_evalDays = strcat(pwd, '/input/autogen/evaluation_days/', dataset, '/', evalDays_type, '/', num2str(household, '%02d'), '.mat');
    load(path_to_evalDays); % evalDays

    % total consumption
    fprintf('Processing household %d, smart meter\n', household);
    smartmeter_consumption = read_smartmeter_data(dataset, household, evalDays, granularity, 'powerallphases');
    missing_values_idx_sm = smartmeter_consumption == -1;
    total_consumption = sum(smartmeter_consumption(~missing_values_idx_sm));

    % consumption of each appliance
    appliances = findAppliances(household, 'eco');
    % power_pct = zeros(length(appliances)+1, 1);
    avg_cons = zeros(length(appliances)+1, 1);
    for i = 1:length(appliances)
       fprintf('Processing household %d, plug %d/%d\n', household, i, length(appliances));
       plug_consumption = read_plug_data(dataset, household, appliances(i), evalDays, granularity);
       missing_values_idx_plug = plug_consumption == -1;
       sum_plug_consumption = sum(plug_consumption(~missing_values_idx_plug));
    %    ratio = nnz(~missing_values_idx_sm) / nnz(~missing_values_idx_plug);
    %    extrapolated_plug_consumption = ratio*sum_plug_consumption;
    %    power_pct(i) = extrapolated_plug_consumption / total_consumption;
        avg_cons(i) = sum_plug_consumption / nnz(~missing_values_idx_plug);
    end

    % power_pct(end) = 1 - sum(power_pct(~isnan(power_pct)));
    avg_cons(end) = (total_consumption / nnz(~missing_values_idx_sm)) - sum(avg_cons);

%     % plot pie chart
%     if household == 5
%         names{end+1} = '';
%         avg_cons(end+1) = avg_cons(end);
%         avg_cons(end-1) = 0;
%     end
%
    names = getApplianceNames(appliances);
    names{end+1} = 'Other';
    fig = figure();
    %title(strcat('Household: ', num2str(household)));
    % pie_handle = pie(power_pct);
    pie_handle = pie(avg_cons);
    % set(pie_handle(2:2:end));
    handle_array = findobj(pie_handle, 'Type', 'text');
%     percentages = get(handle_array, 'String');
%     new_labels = strcat(names',{': '}, percentages);
    new_labels = strcat(names', {': '}, num2str(avg_cons * 24/1000*30, 3));
    set(handle_array, {'String'}, new_labels);

%     fig = make_report_ready(fig, 'size', [width height], 'fontsize', fontsize);
    fig = make_report_ready(fig, 'fontsize', fontsize);

    filename = ['household_', num2str(household)];
    print('-depsc2', '-cmyk', '-r600', [figure_path, filename, '.eps']);
  	% saveas(fig_h, [figure_path, filename, '.png'], 'png');
    pause(1);
  	close(fig);

end


% function spm_dcm_Granger_Jacobian
% Demo routine for induced responses
%==========================================================================
%
% This routine illustrates the derivation of spectral Granger causal
% measures from the inversion of a simple state-space DCM paramterised in
% explcicity in terms of its Jacobian (null model).
%
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_dcm_Granger_Jacobian.m 5908 2014-03-05 20:31:57Z karl $

% Process (model) specification
%==========================================================================
rng('default')

% number of regions
%--------------------------------------------------------------------------
Nc    = 2;                                       % number of channels
Ns    = 2;                                       % number of sources
ns    = 2*128;                                   % sampling frequency
dt    = 1/ns;                                    % time bins
Hz    = 1:128;                                   % frequency
p     = 16;                                      % autoregression order
options.spatial  = 'LFP';
options.model    = 'CMC';
options.analysis = 'CSD';
M.dipfit.model = options.model;
M.dipfit.type  = options.spatial;
M.dipfit.Nc    = Nc;
M.dipfit.Ns    = Ns;
M.pF.D         = [1 4];

% extrinsic connections (forward an backward)
%--------------------------------------------------------------------------
A{1} = [0 0; 0 0];
A{2} = [0 0; 0 0];
A{3} = [0 0; 0 0];
B    = {};
C    = sparse(2,0);

% get priors
%--------------------------------------------------------------------------
pE    = spm_dcm_neural_priors(A,B,C,options.model);
pE    = spm_L_priors(M.dipfit,pE);
pE    = spm_ssr_priors(pE);
[x,f] = spm_dcm_x_neural(pE,options.model);

% create forward model
%--------------------------------------------------------------------------
M.f   = f;
M.g   = 'spm_gx_erp';
M.x   = x;
M.n   = length(spm_vec(x));
M.pE  = pE;
M.m   = Ns;
M.l   = Nc;
M.Hz  = Hz;
M.Rft = 4;

% specify M.u - endogenous input (fluctuations) and intial states
%--------------------------------------------------------------------------
M.u   = sparse(Ns,1);
M.x   = spm_dcm_neural_x(pE,M);

% get expected CSD (observations)
%==========================================================================

% (log) connectivity parameters (forward connection only)
%--------------------------------------------------------------------------
pE.A{1}(2,1) = 2;
pE.S         = 1/8;

% (log) amplitude of fluctations and noise
%--------------------------------------------------------------------------
pE.a(1,:) = -2;
pE.b(1,:) = -4;
pE.c(1,:) = -4;

% expected cross spectral density
%--------------------------------------------------------------------------
[csd,Hz,mtf] = spm_csd_mtf(pE,M);

% place in data structure
%--------------------------------------------------------------------------
DCM.xY.y  = csd;
DCM.xY.dt = dt;
DCM.xY.Hz = Hz;

% Invert using a null model
%==========================================================================
DCM.options.model   = 'NULL';
DCM.options.spatial = 'LFP';
DCM.options.DATA    = 0;

DCM.M.dipfit.Nc  = Nc;
DCM.M.dipfit.Ns  = Ns;
DCM.M.U  = eye(Nc,Nc);

DCM.A = {ones(Nc,Nc)};
DCM.B = {};
DCM.C = sparse(Nc,0);

% estimate
%--------------------------------------------------------------------------
DCM   = spm_dcm_csd(DCM);

% show results in terms of transfer functions and Granger causality
%==========================================================================
spm_figure('GetWin','Figure 1'); clf

% transfer functions in the absence of measurement noise
%--------------------------------------------------------------------------
Ep    = DCM.Ep;
Ep.b  = Ep.b - 32;              % and suppress non-specific and
Ep.c  = Ep.c - 32;              % specific channel noise

Gu           = spm_csd_mtf_gu(pE,Hz);
[psd Hz dtf] = spm_csd_mtf(Ep,DCM.M);

mtf   = mtf{1};
csd   = csd{1};
psd   = psd{1};

tew   = spm_dtf2gew(mtf,Gu);
ccf   = spm_csd2ccf(psd,Hz,dt);
qew   = spm_ccf2gew(ccf,Hz,dt,p);
ccf   = spm_csd2ccf(csd,Hz,dt);
gew   = spm_ccf2gew(ccf,Hz,dt,p);

spm_spectral_plot(Hz,tew, 'b', 'frequency','density')
spm_spectral_plot(Hz,qew, 'r',  'frequency','density')
spm_spectral_plot(Hz,gew, 'g',  'frequency','density')
legend('Granger causality (true)',...
       'Granger causality (source)',...
       'Granger causality (channel)')

subplot(2,2,3), a = axis;
subplot(2,2,1), axis(a);
subplot(2,2,2), axis(a);
subplot(2,2,4), axis(a);


function r = getResidual(SR, LR, W, photometricParams)
% GETRESIDUAL Get residual error for low-resolution and super-resolved
% data.
%   GETRESIDUAL computes the the residual error caused by a super-resolved
%   image with the associated low-resolution frames and the model
%   parameters (system matrix and photometric parameters).

    if nargin < 4 || isempty(photometricParams)
        r = LR - W*SR;
    else
        numFrames = size(photometricParams.mult, 3);
        numLRPixel = length(LR)/numFrames;
        if isvector(photometricParams.mult(:,:,1))
            bm = zeros(size(LR));
            ba = zeros(size(LR));
            for k = 1:numFrames
                bm( ((k-1)*numLRPixel + 1):(k*numLRPixel) ) = repmat(photometricParams.mult(k), numLRPixel, 1);
                ba( ((k-1)*numLRPixel + 1):(k*numLRPixel) ) = repmat(photometricParams.add(k), numLRPixel, 1);
            end
        else
            bm = zeros(size(LR));
            ba = zeros(size(LR));
            for k = 1:numFrames
                bm( ((k-1)*numLRPixel + 1):(k*numLRPixel) ) = imageToVector(photometricParams.mult(:,:,k));
                ba( ((k-1)*numLRPixel + 1):(k*numLRPixel) ) = imageToVector(photometricParams.add(:,:,k));
            end
        end
        r = LR - bm .* (W*SR) - ba;
    end


function [D, Y, optinf] = cbpdndl(D0, S, lambda, opt)

% cbpdndl -- Convolutional BPDN Dictionary Learning
%
%         argmin_{x_m,d_m} (1/2) \sum_k ||\sum_m d_m * x_k,m - s_k||_2^2 +
%                           lambda \sum_k \sum_m ||x_k,m||_1
%
%         The solution is computed using Augmented Lagrangian methods
%         (see boyd-2010-distributed) with efficient solution of the
%         main linear systems (see wohlberg-2016-efficient).
%
% Usage:
%       [D, Y, optinf] = cbpdndl(D0, S, lambda, opt)
%
% Input:
%       D0          Initial dictionary
%       S           Input images
%       lambda      Regularization parameter
%       opt         Options/algorithm parameters structure (see below)
%
% Output:
%       D           Dictionary filter set (3D array)
%       X           Coefficient maps (4D array)
%       optinf      Details of optimisation
%
%
% Options structure fields:
%   Verbose          Flag determining whether iteration status is displayed.
%                    Fields are iteration number, functional value,
%                    data fidelity term, l1 regularisation term, and
%                    primal and dual residuals (see Sec. 3.3 of
%                    boyd-2010-distributed). The values of rho and sigma
%                    are also displayed if options request that they are
%                    automatically adjusted.
%   MaxMainIter      Maximum main iterations
%   AbsStopTol       Absolute convergence tolerance (see Sec. 3.3.1 of
%                    boyd-2010-distributed)
%   RelStopTol       Relative convergence tolerance (see Sec. 3.3.1 of
%                    boyd-2010-distributed)
%   L1Weight         Weight array for L1 norm
%   Y0               Initial value for Y
%   U0               Initial value for U
%   G0               Initial value for G (overrides D0 if specified)
%   H0               Initial value for H
%   rho              Augmented Lagrangian penalty parameter
%   AutoRho          Flag determining whether rho is automatically updated
%                    (see Sec. 3.4.1 of boyd-2010-distributed)
%   AutoRhoPeriod    Iteration period on which rho is updated
%   RhoRsdlRatio     Primal/dual residual ratio in rho update test
%   RhoScaling       Multiplier applied to rho when updated
%   AutoRhoScaling   Flag determining whether RhoScaling value is
%                    adaptively determined (see wohlberg-2015-adaptive). If
%                    enabled, RhoScaling specifies a maximum allowed
%                    multiplier instead of a fixed multiplier
%   sigma            Augmented Lagrangian penalty parameter
%   AutoSigma        Flag determining whether sigma is automatically
%                    updated (see Sec. 3.4.1 of boyd-2010-distributed)
%   AutoSigmaPeriod  Iteration period on which sigma is updated
%   SigmaRsdlRatio   Primal/dual residual ratio in sigma update test
%   SigmaScaling     Multiplier applied to sigma when updated
%   AutoSigmaScaling Flag determining whether SigmaScaling value is
%                    adaptively determined (see wohlberg-2015-adaptive). If
%                    enabled, SigmaScaling specifies a maximum allowed
%                    multiplier instead of a fixed multiplier.
%   StdResiduals     Flag determining whether standard residual definitions
%                    (see Sec 3.3 of boyd-2010-distributed) are used instead
%                    of normalised residuals (see wohlberg-2015-adaptive)
%   XRelaxParam      Relaxation parameter (see Sec. 3.4.3 of
%                    boyd-2010-distributed) for X update
%   DRelaxParam      Relaxation parameter (see Sec. 3.4.3 of
%                    boyd-2010-distributed) for D update
%   LinSolve         Linear solver for main problem: 'SM' or 'CG'
%   MaxCGIter        Maximum CG iterations when using CG solver
%   CGTol            CG tolerance when using CG solver
%   CGTolAuto        Flag determining use of automatic CG tolerance
%   CGTolFactor      Factor by which primal residual is divided to obtain CG
%                    tolerance, when automatic tolerance is active
%   NoBndryCross     Flag indicating whether all solution coefficients
%                    corresponding to filters crossing the image boundary
%                    should be forced to zero.
%   DictFilterSizes  Array of size 2 x M where each column specifies the
%                    filter size (rows x columns) of the corresponding
%                    dictionary filter
%   NonNegCoef       Flag indicating whether solution should be forced to
%                    be non-negative
%   ZeroMean         Force learned dictionary entries to be zero-mean
%
%
% Author: Brendt Wohlberg <brendt@lanl.gov>  Modified: 2015-12-18
%
% This file is part of the SPORCO library. Details of the copyright
% and user license can be found in the 'License' file distributed with
% the library.

if nargin < 4,
  opt = [];
end
checkopt(opt, defaultopts([]));
opt = defaultopts(opt);

% Set up status display for verbose operation
hstr = ['Itn   Fnc       DFid      l1        Cnstr     '...
        'r(X)      s(X)      r(D)      s(D) '];
sfms = '%4d %9.2e %9.2e %9.2e %9.2e %9.2e %9.2e %9.2e %9.2e';
nsep = 84;
if opt.AutoRho,
  hstr = [hstr '     rho  '];
  sfms = [sfms ' %9.2e'];
  nsep = nsep + 10;
end
if opt.AutoSigma,
  hstr = [hstr '     sigma  '];
  sfms = [sfms ' %9.2e'];
  nsep = nsep + 10;
end
if opt.Verbose && opt.MaxMainIter > 0,
  disp(hstr);
  disp(char('-' * ones(1,nsep)));
end

% Collapsing of trailing singleton dimensions greatly complicates
% handling of both SMV and MMV cases. The simplest approach would be
% if S could always be reshaped to 4d, with dimensions consisting of
% image rows, image cols, a single dimensional placeholder for number
% of filters, and number of measurements, but in the single
% measurement case the third dimension is collapsed so that the array
% is only 3d.
if size(S,3) > 1,
  xsz = [size(S,1) size(S,2) size(D0,3) size(S,3)];
  % Insert singleton 3rd dimension (for number of filters) so that
  % 4th dimension is number of images in input s volume
  S = reshape(S, [size(S,1) size(S,2) 1 size(S,3)]);
else
  xsz = [size(S,1) size(S,2) size(D0,3) 1];
end
Nx = prod(xsz);
Nd = prod(xsz(1:2))*size(D0,3);
cgt = opt.CGTol;

% Dictionary size may be specified when learning multiscale
% dictionary
if isempty(opt.DictFilterSizes),
  dsz = [size(D0,1) size(D0,2)];
else
  dsz = opt.DictFilterSizes;
end

% Mean removal and normalisation projections
Pzmn = @(x) bsxfun(@minus, x, mean(mean(x,1),2));
Pnrm = @(x) bsxfun(@rdivide, x, sqrt(sum(sum(x.^2, 1), 2)));

% Projection of filter to full image size and its transpose
% (zero-pad and crop respectively)
Pzp = @(x) zpad(x, xsz(1:2));
PzpT = @(x) bcrop(x, dsz);

% Projection of dictionary filters onto constraint set
if opt.ZeroMean,
  Pcn = @(x) Pnrm(Pzp(Pzmn(PzpT(x))));
else
  Pcn = @(x) Pnrm(Pzp(PzpT(x)));
end

% Start timer
tstart = tic;

% Project initial dictionary onto constraint set
D = Pnrm(D0);

% Compute signal in DFT domain
Sf = fft2(S);

% Set up algorithm parameters and initialise variables
rho = opt.rho;
if isempty(rho), rho = 50*lambda+1; end;
if opt.AutoRho,
  asgr = opt.RhoRsdlRatio;
  asgm = opt.RhoScaling;
end
sigma = opt.sigma;
if isempty(sigma), sigma = size(S,3); end;
if opt.AutoSigma,
  asdr = opt.SigmaRsdlRatio;
  asdm = opt.SigmaScaling;
end
optinf = struct('itstat', [], 'opt', opt);
rx = Inf;
sx = Inf;
rd = Inf;
sd = Inf;
eprix = 0;
eduax = 0;
eprid = 0;
eduad = 0;

% Initialise main working variables
X = [];
if isempty(opt.Y0),
  Y = zeros(xsz, class(S));
else
  Y = opt.Y0;
end
Yprv = Y;
if isempty(opt.U0),
  if isempty(opt.Y0),
    U = zeros(xsz, class(S));
  else
    U = (lambda/rho)*sign(Y);
  end
else
  U = opt.U0;
end
Df = [];
if isempty(opt.G0),
  G = Pzp(D);
else
  G = opt.G0;
end
Gprv = G;
if isempty(opt.H0),
  if isempty(opt.G0),
    H = zeros(size(G), class(S));
  else
    H = G;
  end
else
  H = opt.H0;
end
Gf = fft2(G, size(S,1), size(S,2));
GSf = bsxfun(@times, conj(Gf), Sf);

% Main loop
k = 1;
while k <= opt.MaxMainIter && (rx > eprix|sx > eduax|rd > eprid|sd >eduad),

  % Solve X subproblem. It would be simpler and more efficient (since the
  % DFT is already available) to solve for X using the main dictionary
  % variable D as the dictionary, but this appears to be unstable. Instead,
  % use the projected dictionary variable G
  Xf = solvedbi_sm(Gf, rho, GSf + rho*fft2(Y - U));
  X = ifft2(Xf, 'symmetric');
  clear Xf Gf GSf;

  % See pg. 21 of boyd-2010-distributed
  if opt.XRelaxParam == 1,
    Xr = X;
  else
    Xr = opt.XRelaxParam*X + (1-opt.XRelaxParam)*Y;
  end

  % Solve Y subproblem
  Y = shrink(Xr + U, (lambda/rho)*opt.L1Weight);
  if opt.NonNegCoef,
    Y(Y < 0) = 0;
  end
  if opt.NoBndryCross,
    %Y((end-max(dsz(1,:))+2):end,:,:,:) = 0;
    Y((end-size(D0,1)+2):end,:,:,:) = 0;
    %Y(:,(end-max(dsz(2,:))+2):end,:,:) = 0;
    Y(:,(end-size(D0,2)+2):end,:,:) = 0;
  end
  Yf = fft2(Y);
  YSf = sum(bsxfun(@times, conj(Yf), Sf), 4);

  % Update dual variable corresponding to X, Y
  U = U + Xr - Y;
  clear Xr;

  % Compute primal and dual residuals and stopping thresholds for X update
  nX = norm(X(:)); nY = norm(Y(:)); nU = norm(U(:));
  if opt.StdResiduals,
    % See pp. 19-20 of boyd-2010-distributed
    rx = norm(vec(X - Y));
    sx = norm(vec(rho*(Yprv - Y)));
    eprix = sqrt(Nx)*opt.AbsStopTol+max(nX,nY)*opt.RelStopTol;
    eduax = sqrt(Nx)*opt.AbsStopTol+rho*nU*opt.RelStopTol;
  else
    % See wohlberg-2015-adaptive
    rx = norm(vec(X - Y))/max(nX,nY);
    sx = norm(vec(Yprv - Y))/nU;
    eprix = sqrt(Nx)*opt.AbsStopTol/max(nX,nY)+opt.RelStopTol;
    eduax = sqrt(Nx)*opt.AbsStopTol/(rho*nU)+opt.RelStopTol;
  end
  clear X;

  % Compute l1 norm of Y
  Jl1 = sum(abs(vec(bsxfun(@times, opt.L1Weight, Y))));

  % Update record of previous step Y
  Yprv = Y;

  % Solve D subproblem. Similarly, it would be simpler and more efficient to
  % solve for D using the main coefficient variable X as the coefficients,
  % but it appears to be more stable to use the shrunk coefficient variable Y
  if strcmp(opt.LinSolve, 'SM'),
    Df = solvemdbi_ism(Yf, sigma, YSf + sigma*fft2(G - H));
  else
    [Df, cgst] = solvemdbi_cg(Yf, sigma, YSf + sigma*fft2(G - H), ...
                              cgt, opt.MaxCGIter, Df(:));
  end
  clear YSf;
  D = ifft2(Df, 'symmetric');
  if strcmp(opt.LinSolve, 'SM'), clear Df; end

  % See pg. 21 of boyd-2010-distributed
  if opt.DRelaxParam == 1,
    Dr = D;
  else
    Dr = opt.DRelaxParam*D + (1-opt.DRelaxParam)*G;
  end

  % Solve G subproblem
  G = Pcn(Dr + H);
  Gf = fft2(G);
  GSf = bsxfun(@times, conj(Gf), Sf);

  % Update dual variable corresponding to D, G
  H = H + Dr - G;
  clear Dr;

  % Compute primal and dual residuals and stopping thresholds for D update
  nD = norm(D(:)); nG = norm(G(:)); nH = norm(H(:));
  if opt.StdResiduals,
    % See pp. 19-20 of boyd-2010-distributed
    rd = norm(vec(D - G));
    sd = norm(vec(sigma*(Gprv - G)));
    eprid = sqrt(Nd)*opt.AbsStopTol+max(nD,nG)*opt.RelStopTol;
    eduad = sqrt(Nd)*opt.AbsStopTol+sigma*nH*opt.RelStopTol;
  else
    % See wohlberg-2015-adaptive
    rd = norm(vec(D - G))/max(nD,nG);
    sd = norm(vec(Gprv - G))/nH;
    eprid = sqrt(Nd)*opt.AbsStopTol/max(nD,nG)+opt.RelStopTol;
    eduad = sqrt(Nd)*opt.AbsStopTol/(sigma*nH)+opt.RelStopTol;
  end

  % Apply CG auto tolerance policy if enabled
  if opt.CGTolAuto && (rd/opt.CGTolFactor) < cgt,
    cgt = rd/opt.CGTolFactor;
  end

  % Compute measure of D constraint violation
  Jcn = norm(vec(Pcn(D) - D));
  clear D;

  % Update record of previous step G
  Gprv = G;

  % Compute data fidelity term in Fourier domain (note normalisation)
  Jdf = sum(vec(abs(sum(bsxfun(@times,Gf,Yf),3)-Sf).^2))/(2*xsz(1)*xsz(2));
  clear Yf;
  Jfn = Jdf + lambda*Jl1;

  % Record and display iteration details
  tk = toc(tstart);
  optinf.itstat = [optinf.itstat;...
       [k Jfn Jdf Jl1 rx sx rd sd eprix eduax eprid eduad rho sigma tk]];
  if opt.Verbose,
    dvc = [k, Jfn, Jdf, Jl1, Jcn, rx, sx, rd, sd];
    if opt.AutoRho,
      dvc = [dvc rho];
    end
    if opt.AutoSigma,
      dvc = [dvc sigma];
    end
    disp(sprintf(sfms, dvc));
  end

  % See wohlberg-2015-adaptive and pp. 20-21 of boyd-2010-distributed
  if opt.AutoRho,
    if k ~= 1 && mod(k, opt.AutoRhoPeriod) == 0,
      if opt.AutoRhoScaling,
        rhomlt = sqrt(rx/sx);
        if rhomlt < 1, rhomlt = 1/rhomlt; end
        if rhomlt > opt.RhoScaling, rhomlt = opt.RhoScaling; end
      else
        rhomlt = opt.RhoScaling;
      end
      rsf = 1;
      if rx > opt.RhoRsdlRatio*sx, rsf = rhomlt; end
      if sx > opt.RhoRsdlRatio*rx, rsf = 1/rhomlt; end
      rho = rsf*rho;
      U = U/rsf;
    end
  end
  if opt.AutoSigma,
    if k ~= 1 && mod(k, opt.AutoSigmaPeriod) == 0,
      if opt.AutoSigmaScaling,
        sigmlt = sqrt(rd/sd);
        if sigmlt < 1, sigmlt = 1/sigmlt; end
        if sigmlt > opt.SigmaScaling, sigmlt = opt.SigmaScaling; end
      else
        sigmlt = opt.SigmaScaling;
      end
      ssf = 1;
      if rd > opt.SigmaRsdlRatio*sd, ssf = sigmlt; end
      if sd > opt.SigmaRsdlRatio*rd, ssf = 1/sigmlt; end
      sigma = ssf*sigma;
      H = H/ssf;
    end
  end

  k = k + 1;

end

D = PzpT(G);

% Record run time and working variables
optinf.runtime = toc(tstart);
optinf.Y = Y;
optinf.U = U;
optinf.G = G;
optinf.H = H;
optinf.lambda = lambda;
optinf.rho = rho;
optinf.sigma = sigma;
optinf.cgt = cgt;
if exist('cgst'), optinf.cgst = cgst; end

if opt.Verbose && opt.MaxMainIter > 0,
  disp(char('-' * ones(1,nsep)));
end

return

function u = vec(v)

  u = v(:);

return

function u = shrink(v, lambda)

  if isscalar(lambda),
    u = sign(v).*max(0, abs(v) - lambda);
  else
    u = sign(v).*max(0, bsxfun(@minus, abs(v), lambda));
  end

return

function u = zpad(v, sz)

  u = zeros(sz(1), sz(2), size(v,3), size(v,4), class(v));
  u(1:size(v,1), 1:size(v,2),:,:) = v;

return

function u = bcrop(v, sz)

  if numel(sz) <= 2,
    if numel(sz) == 1
      cs = [sz sz];
    else
      cs = sz;
    end
    u = v(1:cs(1), 1:cs(2), :);
  else
    cs = max(sz,[],2);
    u = zeros(cs(1), cs(2), size(v,3), class(v));
    for k = 1:size(v,3),
      u(1:sz(1,k), 1:sz(2,k), k) = v(1:sz(1,k), 1:sz(2,k), k);
    end
  end

return

function opt = defaultopts(opt)

  if ~isfield(opt,'Verbose'),
    opt.Verbose = 0;
  end
  if ~isfield(opt,'MaxMainIter'),
    opt.MaxMainIter = 1000;
  end
  if ~isfield(opt,'AbsStopTol'),
    opt.AbsStopTol = 1e-6;
  end
  if ~isfield(opt,'RelStopTol'),
    opt.RelStopTol = 1e-4;
  end
  if ~isfield(opt,'L1Weight'),
    opt.L1Weight = 1;
  end
  if ~isfield(opt,'Y0'),
    opt.Y0 = [];
  end
  if ~isfield(opt,'U0'),
    opt.U0 = [];
  end
  if ~isfield(opt,'G0'),
    opt.G0 = [];
  end
  if ~isfield(opt,'H0'),
    opt.H0 = [];
  end
  if ~isfield(opt,'rho'),
    opt.rho = [];
  end
  if ~isfield(opt,'AutoRho'),
    opt.AutoRho = 0;
  end
  if ~isfield(opt,'AutoRhoPeriod'),
    opt.AutoRhoPeriod = 10;
  end
  if ~isfield(opt,'RhoRsdlRatio'),
    opt.RhoRsdlRatio = 10;
  end
  if ~isfield(opt,'RhoScaling'),
    opt.RhoScaling = 2;
  end
  if ~isfield(opt,'AutoRhoScaling'),
    opt.AutoRhoScaling = 0;
  end
  if ~isfield(opt,'sigma'),
    opt.sigma = [];
  end
  if ~isfield(opt,'AutoSigma'),
    opt.AutoSigma = 0;
  end
  if ~isfield(opt,'AutoSigmaPeriod'),
    opt.AutoSigmaPeriod = 10;
  end
  if ~isfield(opt,'SigmaRsdlRatio'),
    opt.SigmaRsdlRatio = 10;
  end
  if ~isfield(opt,'SigmaScaling'),
    opt.SigmaScaling = 2;
  end
  if ~isfield(opt,'AutoSigmaScaling'),
    opt.AutoSigmaScaling = 0;
  end
  if ~isfield(opt,'StdResiduals'),
    opt.StdResiduals = 0;
  end
  if ~isfield(opt,'XRelaxParam'),
    opt.XRelaxParam = 1;
  end
  if ~isfield(opt,'DRelaxParam'),
    opt.DRelaxParam = 1;
  end
  if ~isfield(opt,'LinSolve'),
    opt.LinSolve = 'SM';
  end
  if ~isfield(opt,'MaxCGIter'),
    opt.MaxCGIter = 1000;
  end
  if ~isfield(opt,'CGTol'),
    opt.CGTol = 1e-3;
  end
  if ~isfield(opt,'CGTolAuto'),
    opt.CGTolAuto = 0;
  end
  if ~isfield(opt,'CGTolAutoFactor'),
    opt.CGTolFactor = 50;
  end
  if ~isfield(opt,'NoBndryCross'),
    opt.NoBndryCross = 0;
  end
  if ~isfield(opt,'DictFilterSizes'),
    opt.DictFilterSizes = [];
  end
  if ~isfield(opt,'NonNegCoef'),
    opt.NonNegCoef = 0;
  end
  if ~isfield(opt,'ZeroMean'),
    opt.ZeroMean = 0;
  end

return


function [ node_num, tree, tree_data ] = r8btree_node_add ( node_num, tree, ...
  data_num, tree_data, node_data )

%*****************************************************************************80
%
%% R8BTREE_NODE_ADD adds one node to a BTREE.
%
%  Discussion:
%
%    A BTREE is a binary tree.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NODE_NUM, the number of nodes in the tree.
%
%    Input, integer TREE(4,NODE_NUM).
%    TREE(1,I), the index in TREE_DATA(1,*) of the coordinate of node I.
%    TREE(2,I), the left child of node I.
%    TREE(3,I), the right child of node I.
%    TREE(4,I), the parent of node I.
%
%    Input, integer DATA_NUM, the number of data items per node.
%
%    Input, real TREE_DATA(DATA_NUM,NODE_NUM), node data.
%
%    Input, real NODE_DATA(DATA_NUM), data associated with the new node.
%
%    Output, integer NODE_NUM, the updated value.
%
%    Output, integer TREE(4,NODE_NUM), the updated value.
%
%    Output, integer TREE_DATA(DATA_NUM,NODE_NUM), the updated value.
%
  if ( node_num <= 0 )
    tree(1:4,1) = [ 1, -1, -1, -1 ];
    tree_data(1:data_num,1) = node_data(1:data_num);
    node_num = 1;
    return
  end

  l = -1;
  m = 1;
  r = -1;
%
%  Divide the current interval [L,R] by the midpoint M.
%  X falls either into [L,M] or [M,R].
%
  x = node_data(1);

  while ( 1 )

    xm = tree_data(1,tree(1,m));
    m_old = m;

    if ( x < xm )
      r = m;
      m = tree(2,m);
      if ( m == - 1 )
        tree(2,m_old) = node_num + 1;
        tree(1,node_num+1) = node_num + 1;
        tree(2,node_num+1) = -1;
        tree(3,node_num+1) = -1;
        tree(4,node_num+1) = m_old;
        tree_data(1:data_num,node_num+1) = node_data(1:data_num);
        node_num = node_num + 1;
        break
      end
    elseif ( xm < x )
      l = m;
      m = tree(3,m);
      if ( m == -1 )
        tree(3,m_old) = node_num + 1;
        tree(1,node_num+1) = node_num + 1;
        tree(2,node_num+1) = -1;
        tree(3,node_num+1) = -1;
        tree(4,node_num+1) = m_old;
        tree_data(1:data_num,node_num+1) = node_data(1:data_num);
        node_num = node_num + 1;
        break
      end
    else
      r = m;
      l = m;
      break
    end

  end

  return
end


%% test_all.m
%|
%| Attempt to run all test routines
%| to verify completeness of software distribution.
%|
%| I recommend running these tests to verify the completeness
%| of your installation!  If some test fails, please email me
%| the relevant output messages and tell me what version of Matlab
%| and what OS you are using.  Then go ahead and try to use the
%| toolbox because often most things work even if one test fails.
%|
%| If you do not have all the matlab toolboxes (e.g., image, signal, wavelet)
%| then some tests will fail.  But don't worry about it, I am trying to
%| make it work with just plain matlab, so most of it should work even
%| without any extra toolboxes.
%|
%| Jeff Fessler

%double6 double
%disp 'Note: forcing double precision because sparse(double)*single fails :-('

im off-quiet

prompt draw % do all plots without pausing/prompting
%printm 'Note: hit "r" at the prompt to disable subsequent prompts'

diary_file = ['~/' date '-test_all.txt'];
diary(diary_file)

% uncomment the suite(s) you want to test

test_all_mex % see if all the mex files work (this will fail on Windows)

list = {...
'test_all_util', ...
'test_all_graph', ...
'test_all_reg', ...
'test_all_nufft', ...
'test_all_systems', ...
'test_all_emission', ...
'test_all_transmission', ...
'test_all_wls', ...
'test_all_ct', ...
'test_all_mri', ...
'test_all_example'
};

run_mfile_local(list, 'pause', 0)

diary off


function [p,dp] = spm_LAP_eval(M,qu,qh)
% Evaluate precisions for a LAP model
% FORMAT [p dp] = spm_LAP_eval(M,qu,qh)
%
% p.h     - vector of precisions for causal states (v)
% p.g     - vector of precisions for hidden states (x)
%
% dp.h.dx - dp.h/dx
% dp.h.dv - dp.h/dv
% dp.h.dh - dp.h/dh
%
% dp.g.dx - dp.g/dx
% dp.g.dv - dp.g/dv
% dp.g.dg - dp.g/dg
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_LAP_eval.m 6290 2014-12-20 22:11:50Z karl $

% Get states {qu.v{1},qu.x{1}} in hierarchical form (v{i},x{i})
%--------------------------------------------------------------------------
N          = length(M);
v          = cell(N,1);
x          = cell(N,1);
v(1:N - 1) = spm_unvec(qu.v{1},{M(1 + 1:N).v});
x(1:N - 1) = spm_unvec(qu.x{1},{M(1:N - 1).x});

% precisions
%==========================================================================
for i = 1:N

    % precision of causal and hidden states
    %----------------------------------------------------------------------
    try
        h{i,1} = spm_vec(feval(M(i).ph,x{i},v{i},qh.h{i},M(i)));
    catch
        h{i,1} = sparse(M(i).l,1);
    end
    try
        g{i,1} = spm_vec(feval(M(i).pg,x{i},v{i},qh.g{i},M(i)));
    catch
        g{i,1} = sparse(M(i).n,1);
    end

end

% Concatenate over hierarchical levels
%--------------------------------------------------------------------------
p.h  = spm_cat(h);
p.g  = spm_cat(g);

if nargout < 2, return, end

% gradients
%==========================================================================

% assume precisions can be functions of hyper-parameters and states
%--------------------------------------------------------------------------
try method.h = M(1).E.method.h; catch, method.h = 1; end
try method.g = M(1).E.method.g; catch, method.g = 1; end
try method.x = M(1).E.method.x; catch, method.x = 1; end
try method.v = M(1).E.method.v; catch, method.v = 1; end

% number of variables
%--------------------------------------------------------------------------
nx      = numel(spm_vec(x));
nv      = numel(spm_vec(v));
hn      = numel(spm_vec(qh.h));
gn      = numel(spm_vec(qh.g));
nh      = size(p.h,1);
ng      = size(p.g,1);

dp.h.dh = sparse(nh,hn);
dp.g.dg = sparse(ng,gn);
dp.h.dx = sparse(nh,nx);
dp.h.dv = sparse(nh,nv);
dp.g.dx = sparse(ng,nx);
dp.g.dv = sparse(ng,nv);

% gradients w.r.t. h only (no state-dependent noise)
%----------------------------------------------------------------------
if method.h || method.g

    for i = 1:N

        % precision of causal and hidden states
        %--------------------------------------------------------------
        dhdh{i,i} = spm_diff(M(i).ph,x{i},v{i},qh.h{i},M(i),3);
        dgdg{i,i} = spm_diff(M(i).pg,x{i},v{i},qh.g{i},M(i),3);

    end

    % Concatenate over hierarchical levels
    %------------------------------------------------------------------
    dp.h.dh = spm_cat(dhdh);
    dp.g.dg = spm_cat(dgdg);

end

% gradients w.r.t. causal states
%----------------------------------------------------------------------
if method.v

    for i = 1:N

        % precision of causal states
        %--------------------------------------------------------------
        dhdv{i,i} = spm_diff(M(i).ph,x{i},v{i},qh.h{i},M(i),2);

        % precision of hidden states
        %--------------------------------------------------------------
        dgdv{i,i} = spm_diff(M(i).pg,x{i},v{i},qh.g{i},M(i),2);

    end

    % Concatenate over hierarchical levels
    %------------------------------------------------------------------
    dp.h.dv = spm_cat(dhdv);
    dp.g.dv = spm_cat(dgdv);

end

% gradients w.r.t. hidden states
%----------------------------------------------------------------------
if method.x

    for i = 1:N

        % precision of causal states
        %--------------------------------------------------------------
        dhdx{i,i} = spm_diff(M(i).ph,x{i},v{i},qh.h{i},M(i),1);

        % precision of hidden states
        %--------------------------------------------------------------
        dgdx{i,i} = spm_diff(M(i).pg,x{i},v{i},qh.g{i},M(i),1);

    end

    % Concatenate over hierarchical levels
    %------------------------------------------------------------------
    dp.h.dx = spm_cat(dhdx);
    dp.g.dx = spm_cat(dgdx);

end


% SYNTAX:
% [pValuesS, pValuesS_cond]  = hmrS_CalcPvalue(yRuns, stimRuns, mlActRuns, baselineRange, hrfTimeWindow)
%
% UI NAME:
% Pvalues_on_Session
%
% DESCRIPTION:
% Calculate the p-value matrix for a single session.
%
% INPUTS:
% yRuns:
% stimRuns:
% mlActRuns:
% baselineRange:
% hrfTimeWindow:
%
% OUTPUTS:
% pValuesS:
% pValuesS_cond
% USAGE OPTIONS:
% Pvalues_on_Session_Concentration_Data: [pValuesS, pValuesS_cond] = hmrS_CalcPvalue(dcRuns, stimRuns, mlActRuns, baselineRange, hrfTimeWindow)
%
% PARAMETERS:
% baselineRange: [-2.0, 0.0]
% hrfTimeWindow: [-2.0, 20.0]

function [pValuesS, pValuesS_cond] = hmrS_CalcPvalue(yRuns, stimRuns, mlActRuns, baselineRange, hrfTimeWindow)

pValues = cell(length(yRuns{1}),1);

% extract fq and number of conditions from the first run:
snirf = SnirfClass(yRuns{1}, stimRuns{1});
t = snirf.GetTimeCombined();
s = snirf.GetStims(t);
ncond = size(s,2);
fq = abs(1/(t(1)-t(2)));
nDataBlks = length(yRuns{1});

%% BASELINE vs CONDITION, PAIRED T-TEST
for iBlk = 1:nDataBlks
    for cond = 1:ncond % for each condition
        for iRun = 1:length(yRuns)

            % Get stim vector by instantiating temporary SnirfClass object with this
            % function's stim argument as input, and then using the SnirfClass object's
            % GetStims method to convert stim to the s vector that this function needs.
            snirf = SnirfClass(yRuns{iRun}, stimRuns{iRun});
            t = snirf.GetTimeCombined();
            s = snirf.GetStims(t);     % stim matrix for run iRun is same for all of a run's data blocks

            % extract HRF at baselineRange and at hrfTimeWindow
            lst_stim = find(s(:,cond)==1);

            % get active measuremnt list for each run
            if isempty(mlActRuns{iRun})
                mlActRuns{iRun} = cell(length(nDataBlks),1);
            end
            ml    = yRuns{iRun}(iBlk).GetMeasListSrcDetPairs('reshape');

            if isempty(mlActRuns{iRun}{iBlk})
                mlActRuns{iRun}{iBlk} = ones(size(ml,1),1);
            end
            mlAct = mlActRuns{iRun}{iBlk}(1:size(ml,1));

            % GetDataTimeSeries() extract data in old homer2 dimensions (time X Hb X channel)
            y = yRuns{iRun}(iBlk).GetDataTimeSeries('reshape'); % yRuns{iRun}(iBlk).GetDataTimeSeries('reshape');  % data matrix for run iRun, data block iBlk
            for hb = 1:3 % across HbO/HbR/HbT
                for iTrial = 1:size(lst_stim,1) % across trials
                    % Hb: # of time points X # of trials X # of runs X # of channels X HbO/HbR
                    Hb_baseline(:,iTrial,iRun,:,hb,cond) = squeeze(y([lst_stim(iTrial) - round(abs(baselineRange(1))*fq)]:lst_stim(iTrial),hb,:)); % get each trial
                    Hb_peak(:,iTrial,iRun,:,hb,cond) = squeeze(y([lst_stim(iTrial) + round(abs(hrfTimeWindow(1))*fq)]:[lst_stim(iTrial) + round(hrfTimeWindow(2)*fq)],hb,:)); % get each trial

                end
            end
        end
    end

    % put together trials from all runs:
    Hb_baseline_rs = reshape(Hb_baseline, size(Hb_baseline,1),  size(Hb_baseline,2)* size(Hb_baseline,3),  size(Hb_baseline,4),size(Hb_baseline,5),size(Hb_peak,6));
    Hb_peak_rs = reshape(Hb_peak, size(Hb_peak,1),  size(Hb_peak,2)* size(Hb_peak,3),  size(Hb_peak,4),size(Hb_peak,5),size(Hb_peak,6));

    % take the mean in time ranges: baselineRange, hrfTimeWindow
    for hb = 1:3 % HbO/HbR/HbT
        for ch=1:size(Hb_peak_rs,3) % across channels
            MEAN_Hb_baseline(:,ch,hb)= nanmean(squeeze(Hb_baseline_rs(:,:,ch,hb)),1);
            MEAN_Hb_peak(:,ch,hb)= nanmean(squeeze(Hb_peak_rs(:,:,ch,hb)),1);
        end
    end

    % get stats
    if isempty(pValues{iBlk})
        for ch = 1:size(MEAN_Hb_peak,2) % channels
                 for hb = 1:3% HbO/HbR/HbT
                    [h,p,c,stats] = ttest(MEAN_Hb_baseline(:,ch,hb),(MEAN_Hb_peak(:,ch,hb)));
                    pValuesS(hb,ch,cond) = p;

                    % 2) Pvalue SHOULD BE CONVERTED TO DATA CLASS IN THE RIGHT DIM AT THE END

                end
        end
    end
end

pValuesS(:,find(mlAct==0),:) = NaN;

%% CONDITION vs CONDITION, UNPAIRED T-TEST
% get all combinations of conditions
cond_2_comb = sort(combnk(1:ncond,2));
% extract HRF at hrfTimeWindow from the cond combination
for i = 1:ncond
    lst_stim_all{i} = find(s(:,i)==1);
end

for iBlk = 1:length(nDataBlks)
    for comb_inx = 1:size(cond_2_comb,1) % for each condition
        % get current combin.
        foo = cond_2_comb(comb_inx,:);

        for iRun = 1:length(yRuns)
            % get active measuremnt list for each run
            if isempty(mlActRuns{iRun})
                mlActRuns{iRun} = cell(length(nDataBlks),1);
            end
            ml = yRuns{iRun}(iBlk).GetMeasListSrcDetPairs('reshape');

            if isempty(mlActRuns{iRun}{iBlk})
                mlActRuns{iRun}{iBlk} = ones(size(ml,1),1);
            end
            mlAct = mlActRuns{iRun}{iBlk}(1:size(ml,1));

            % GetDataTimeSeries() extract data in old homer2 dimensions (time X Hb X channel)
            y = yRuns{iRun}(iBlk).GetDataTimeSeries('reshape');  % data matrix for run iRun, data block iBlk
            for hb = 1:3 % across HbO/HbR/HbT
                for iTrial = 1:size(lst_stim_all{foo(1)},1) % across trials
                    % Hb: # of time points X # of trials X # of runs X # of channels X HbO/HbR
                    Hb_peak1(:,iTrial,iRun,:,hb) = squeeze(y([lst_stim_all{foo(1)}(iTrial) + round(abs(hrfTimeWindow(1))*fq)]:[lst_stim_all{foo(1)}(iTrial) + round(hrfTimeWindow(2)*fq)],hb,:)); % get each trial
                end
                for iTrial = 1:size(lst_stim_all{foo(2)},1) % across trials
                    % Hb: # of time points X # of trials X # of runs X # of channels X HbO/HbR
                    Hb_peak2(:,iTrial,iRun,:,hb) = squeeze(y([lst_stim_all{foo(2)}(iTrial) + round(abs(hrfTimeWindow(1))*fq)]:[lst_stim_all{foo(2)}(iTrial) + round(hrfTimeWindow(2)*fq)],hb,:)); % get each trial
                end
            end
        end
    end

    % put together trials from all runs:
    Hb_peak_rs1 = reshape(Hb_peak1, size(Hb_peak1,1),  size(Hb_peak1,2)* size(Hb_peak1,3),  size(Hb_peak1,4),size(Hb_peak1,5));
    Hb_peak_rs2 = reshape(Hb_peak2, size(Hb_peak2,1),  size(Hb_peak2,2)* size(Hb_peak2,3),  size(Hb_peak2,4),size(Hb_peak2,5));

    % take the mean in time range hrfTimeWindow
    for hb = 1:3 % HbO/HbR/HbT
        for ch=1:size(Hb_peak_rs,3) % across channels
            MEAN_Hb_peak1(:,ch,hb)= nanmean(squeeze(Hb_peak_rs1(:,:,ch,hb)),1);
            MEAN_Hb_peak2(:,ch,hb)= nanmean(squeeze(Hb_peak_rs2(:,:,ch,hb)),1);

        end
    end

    % get stats
    if ~exist('pValuesS_cond')
        for ch = 1:size(MEAN_Hb_peak,2) % channels
                for hb = 1:3% HbO/HbR/HbT
                    [h,p,c,stats] = ttest2(MEAN_Hb_peak1(:,ch,hb),(MEAN_Hb_peak2(:,ch,hb)));
                    pValuesS_cond(hb,ch,comb_inx) = p;
                    % or                     pValuesS_cond(foo(1),foo(2),hb,ch) = p;

                    % 2) Pvalue SHOULD BE CONVERTED TO DATA CLASS IN THE RIGHT DIM AT THE END

                end
        end
    end
end
pValuesS_cond(:,find(mlAct==0),:) = NaN;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%*********************************************************
%% convertcmpsdp: convert SDP with complex data into one
%%                with real data by converting
%%
%%  C - sum_{k=1}^m yk*Ak psd
%%  to
%%  [CR,-CI] - sum ykR*[AkR,-AkI] psd
%%  [CI, CR]           [AkI, AkR]
%%
%%  ykI = 0 for k = 1:m
%%
%% [bblk,AAt,CC,bb] = convertcmpsdp(blk,A,C,b);
%%
%%*********************************************************

function [bblk,AAt,CC,bb,iscmp] = convertcmpsdp(blk,A,C,b)

m = length(b);
pp = size(A,1);
if (pp ~= size(blk,1))
    error('blk and A not compatible');
end
numblk = size(blk,1);
iscmp = zeros(numblk,m+1);
for p = 1:size(blk,1)
    len = size(A(p),2);
    for k = 1:len
        if ~isempty(A{p,k})
            iscmp(p,k) = 1-isreal(A{p,k});
        end
    end
    iscmp(p,m+1) = 1-isreal(C{p});
end
iscmp = norm(iscmp,'fro');
%%
if (iscmp == 0)
    %% data is real
    bblk = blk; AAt = A; CC = C; bb = b;
    return;
end
%%
bb = real(b);
bblk = cell(size(blk,1),2);
for p = 1:size(blk,1)
    pblk = blk(p,:);
    if (size(pblk{2},1) > size(pblk{2},2))
        pblk{2} = pblk{2}';
    end
    if strcmp(pblk{1},'s')
        ss = [0,cumsum(pblk{2})];
        ss2 = [0,cumsum(2*pblk{2})];
        n = sum(pblk{2});
        n2 = sum(pblk{2}.*(pblk{2}+1))/2;
        AR = cell(1,m); Ctmp = sparse(2*n,2*n);
        if (size(A{p},1)==n2 && size(A{p},2)==m);
            Atype = 1;
        elseif (size(A(p),1)==1 && size(A(p),2)==1);
            Atype = 2;
        else
            error('convertcmp: At is not properly coded');
        end
        for k = 0:m
            if (k == 0)
                Ak = C{p};
            else
                if (Atype == 1)
                    Ak = smat(pblk,A{p}(:,k),1);
                elseif (Atype == 2)
                    Ak = A{p,k};
                end
            end
            Atmp = sparse(2*n,2*n);
            if (length(pblk{2}) == 1)
                tmp = [real(Ak),-imag(Ak);  imag(Ak), real(Ak)];
                if (k==0)
                    Ctmp = tmp;
                else
                    Atmp = tmp;
                end
            else
                for j = 1:length(pblk{2})
                    idx = ss(j)+1: ss(j+1);
                    Akj = Ak(idx,idx);
                    tmp = [real(Akj),-imag(Akj);  imag(Akj), real(Akj)];
                    idx2 = ss2(j)+1: ss2(j+1);
                    if (k==0)
                        Ctmp(idx2,idx2) = tmp; %#ok
                    else
                        Atmp(idx2,idx2) = tmp; %#ok
                    end
                end
            end
            if (k==0);
                CC{p,1} = Ctmp; %#ok
            else
                AR{k} = Atmp;
            end
        end
        bblk{p,1} = 's'; bblk{p,2} = 2*pblk{2};
        AAt(p,1) = svec(bblk(p,:),AR); %#ok
    elseif strcmp(pblk{1},'q');
        error('SOCP block with complex data is currently not allowed');
    elseif strcmp(pblk{1},'l');
        if isreal(A{p}) && isreal(C{p})
            bblk(p,:) = blk(p,:);
            AAt{p,1} = A{p}; CC{p,1} = C{p}; %#ok
        else
            error('data for linear block must be real');
        end
    elseif strcmp(pblk{1},'u');
        if isreal(A{p}) && isreal(C{p})
            bblk(p,:) = blk(p,:);
            AAt{p,1} = A{p}; CC{p,1} = C{p}; %#ok
        else
            error('data for unrestricted block must be real');
        end
    end
end
%%*********************************************************


filename='Bridge_tetrahedra_coarse';
 ptype = 'MACRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'full';
cost = {'compliance';'perimeter'};
weights = [1, 0.1];
constraint = {'volumeConstraint'};
optimizer = 'IPOPT'; incrementFactor = 1;
filterType = 'P1';

nsteps = 5;
Vfrac_final = 0.05;
Perimeter_target = 1;
optimality_final = 1e-3;
constr_final =1e-3;

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


function [ output ] = tapas_rdcm_compute_signals(DCM, output, options)
% [ output ] = tapas_rdcm_compute_signals(DCM, output, options)
%
% Computes true and predicted signals
%
%   Input:
%   	DCM         - model structure
%       output      - model inversion results
%       options     - estimation options
%
%   Output:
%   	output      - model inversion results with model fits
%

% ----------------------------------------------------------------------
%
% Authors: Stefan Fraessle (stefanf@biomed.ee.ethz.ch), Ekaterina I. Lomakina
%
% Copyright (C) 2016-2022 Translational Neuromodeling Unit
%                         Institute for Biomedical Engineering
%                         University of Zurich & ETH Zurich
%
% This file is part of the TAPAS rDCM Toolbox, which is released under the
% terms of the GNU General Public License (GPL), version 3.0 or later. You
% can redistribute and/or modify the code under the terms of the GPL. For
% further see COPYING or <http://www.gnu.org/licenses/>.
%
% Please note that this toolbox is in an early stage of development. Changes
% are likely to occur in future releases.
%
% ----------------------------------------------------------------------

% true or measured signal
output.signal.y_source = DCM.Y.y(:);

% true (deterministic) signal / VBL signal
if strcmp(options.type,'s')

    % if signal should be computed
    if ( options.compute_signal )

        % noise-free signal
        DCMs = tapas_rdcm_generate(DCM, options, Inf);
        output.signal.y_clean = DCMs.Y.y(:);

        % compute the MSE of the noisy data
        output.residuals.y_mse_clean = mean((output.signal.y_source - output.signal.y_clean).^2);

    end

else

    % VBL predicted signal
    if ( isfield(DCM,'y') )
        output.signal.y_pred_vl     = DCM.y(:);
        output.residuals.y_mse_vl   = mean((output.signal.y_source - output.signal.y_pred_vl).^2);
    else
        output.residuals.y_mse_vl   = [];
    end
end

% store true or measured temporal derivative (in frequency domain)
yd_source_fft                           = output.temp.yd_source_fft;
yd_source_fft(~isfinite(yd_source_fft)) = 0;
output.signal.yd_source_fft             = yd_source_fft(:);

% if signal in time domain should be computed
if ( options.compute_signal )

    % get rDCM parameters
    DCM.Tp   = output.Ep;

    % no baseline for simulated data
    if ( strcmp(options.type,'s') )
        DCM.Tp.baseline = zeros(size(DCM.Tp.C,1),1);
    end

    % increase sampling rate
    r_dt     = DCM.Y.dt/DCM.U.dt;
    DCM.Y.dt = DCM.U.dt;

    % posterior probability (for sparse rDCM)
    if ( isfield(output,'Ip') )
        DCM.Tp.A = DCM.Tp.A .* output.Ip.A;
        DCM.Tp.C = DCM.Tp.C .* output.Ip.C;
    end

    % generate predicted signal (tapas_rdcm_generate)
    DCM_rDCM = tapas_rdcm_generate(DCM, options, Inf);

    % add the confounds to predicted time series
    for t = 1:size(DCM.Y.y,1)
        for r = 1:size(DCM.Y.y,2)
            DCM_rDCM.Y.y(t,r) = DCM_rDCM.Y.y(t,r) + DCM_rDCM.Tp.baseline(r,:) * DCM_rDCM.U.X0((1+r_dt*(t-1)),:)';
        end
    end

    % turn into vector
    output.signal.y_pred_rdcm = DCM_rDCM.Y.y(:);

end

% store predicted temporal derivative (in frequency domain)
yd_pred_rdcm_fft                = output.temp.yd_pred_rdcm_fft;
output.signal.yd_pred_rdcm_fft  = yd_pred_rdcm_fft(:);

% remove the temp structure
output = rmfield(output,'temp');

% asign the region names
if ( isfield(DCM.Y,'name') )
    output.signal.name = DCM.Y.name;
end

% compute the MSE of predicted signal
if ( options.compute_signal )
    output.residuals.y_mse_rdcm     = mean((output.signal.y_source - output.signal.y_pred_rdcm).^2);
    output.residuals.R_rdcm         = output.signal.y_source - output.signal.y_pred_rdcm;
end

% store the driving inputs
output.inputs.u     = DCM.U.u;
output.inputs.name  = DCM.U.name;
output.inputs.dt    = DCM.U.dt;

end


function [] = FinalOutput(CL, CDi, CD0, y_cp, geo, WingVolume, airfoildata, output)
% calculate score and other outputs, post to the GUI

q = 1/2*geo.density*geo.V^2;

%Determine the stall angles of attack for root and tip airfoils
alpha_r = (geo.i_r + geo.alpha)*180/pi;
chord_r = geo.c_r;
thick_r = str2num(geo.root(end-1:end));  %Determine thickness of root airfoil
Re_r = geo.V*geo.density*chord_r/geo.visc;
k = cell2mat(airfoildata{5}(geo.rootindex));
alpha_stall_r = k(1) + k(2)*log10(Re_r) + k(3)*log10(Re_r)^2;

alpha_t = (geo.i_r + geo.twist + geo.alpha)*180/pi;
chord_t = geo.c_r*geo.taper;
thick_t = str2num(geo.tip(end-1:end));  %#ok<ST2NM> %Determine thickness of tip airfoil
Re_t = geo.V*geo.density*chord_t/geo.visc;
k = cell2mat(airfoildata{5}(geo.tipindex));
alpha_stall_t = k(1) + k(2)*log10(Re_t) + k(3)*log10(Re_t)^2;

eta = (2*(1:geo.ns)-1)/(2*geo.ns);
chord = chord_r + eta*(chord_t-chord_r);
alpha = alpha_r + eta*(alpha_t-alpha_r);
alpha_stall = alpha_stall_r + eta*(alpha_stall_t-alpha_stall_r);
thick = thick_r + eta*(thick_t-thick_r);

counter = 0;    %Tracks the number of panels that are stalled
percentstalled = 0; %Tracks percentage of wing that is stalled
averagechord = 0; %Tracks average chord of stalled wing
averagealphapaststall = 0; %Tracks the average number of degrees past stall
averagethickness = 0; %Tracks the average thickness of the airfoil sections past stall
averagestallalpha = 0; %Tracks the average stall angle
for i = 1:geo.ns
    if alpha(i) > alpha_stall(i)
        counter = counter + 1;
        percentstalled = percentstalled + 1;
        averagechord = averagechord + chord(i);
        averagealphapaststall = averagealphapaststall + (alpha(i) - alpha_stall(i));
        averagethickness = averagethickness + thick(i);
        averagestallalpha = averagestallalpha + alpha_stall(i);
    end
end

if counter ~= 0 %Some part of the wing is stalled; prevents divide by zero
    percentstalled = percentstalled/geo.ns;
    averagechord = averagechord/counter;
    averagealphapaststall = averagealphapaststall/counter*pi/180;  %Convert to radians because stall model was developed in radians
    averagethickness = averagethickness/counter;
    averagestallalpha = averagestallalpha/counter;
end
%Determine lift while accounting for lift after the stall angle of attack
c = averagethickness/12;   %Thickness coefficient
d = 100*c;  %Determined by trial and error to closely model the shape and behavior of the lift curve
k = 400*c;
CL_stall = sum(CL.c+CL.alpha*averagestallalpha*pi/180);  %Average max lift coefficient
%The following equation is the result of modeling the lift
%coefficient of the airfoil after the stall angle of attack as a
%2nd order ODE with initial position of CL_stall and initial
%velocity of CL_alpha.  See Stall Model.nb for Mathematica
%derivation
if percentstalled == 0
    stallcorrection = 1;
else
    stallcorrection = exp(0.5*(-d-sqrt(d^2-4*k))*(averagealphapaststall))*(-2*CL.alpha-CL_stall*d+CL_stall*sqrt(d^2-4*k))/(2*sqrt(d^2-4*k))...
        +exp(0.5*(-d+sqrt(d^2-4*k))*(averagealphapaststall))*(2*CL.alpha+CL_stall*d+CL_stall*sqrt(d^2-4*k))/(2*sqrt(d^2-4*k));
end

CL = ((1-percentstalled)*(CL.c+CL.alpha*geo.alpha)+percentstalled*stallcorrection);

L = CL*q*geo.S;

Dind = CDi*q*geo.S;

%CD0 is profile drag of wing, S_Sref*Cfe is the zero-lift drag of the
%fuselage from section 2.9.1 of Anderson, Aircraft Performance and Design
%The sum of these two terms represents the total skin friction drag on the
%wing body or the zero-lift drag
Dprofile = (CD0 + geo.S_Sref*geo.cf)*q*geo.S;

Dtotal = Dind + Dprofile;  %Newton

BendMoment = -(y_cp.c+y_cp.alpha*geo.alpha)*L;

%Determine useful payload
Fuel_weight = geo.wingfuel*geo.fueldens*WingVolume*9.81;   %Fuel weight in N
Payload = L - geo.emptyweight - Fuel_weight;    %Useful payload in N

%Range equations from Aircraft Performance and Design
switch geo.engine
    case 'prop'
        Range = geo.propefficiency/geo.propSFC*L/Dtotal*log((geo.emptyweight+Fuel_weight)/geo.emptyweight);  %25% usable volume
        SFC = geo.propSFC;
    case 'jet'
        CD = CD0 + CDi;
        Range = 2/geo.jetTSFC*sqrt(2/(geo.S*geo.density)*CL/CD^2)*(sqrt(geo.emptyweight+Fuel_weight)-sqrt(geo.emptyweight));
        SFC = geo.jetTSFC;
    otherwise
        Range = 0;
        SFC = 0;
end

%Score function
Baseline_payload = 45000; %C130 maximum payload, Wikipedia
Cost_payload = 10000/400; %An extra 10000 lbf of lift is worth 1000 miles
Baseline_moment = 422000; %C130 moment from Wing Designer using C130 geometry
Cost_moment = 400000/10000; %Doubling the baseline moment incurs a penalty of 10000 miles
Baseline_airspeed = 292; %292 knots (C130 cruise), Wikipedia
Cost_airspeed = 10/100; %An extra 10 knots of cruising speed is worth 100 miles
Baseline_span = 132/3.28; %C130 wing span, Wikipedia
Cost_span = 20/3.28/2000; %An extra 20 feet incurs a penalty of 1200 miles
Score = Range/1609 + (Payload*0.22481-Baseline_payload)/Cost_payload - (BendMoment - Baseline_moment)/Cost_moment + ...
    (geo.V/0.5144 - Baseline_airspeed)/Cost_airspeed - (geo.b - Baseline_span)/Cost_span; %Convert range to miles; lift to lbf; airspeed to knots

	%Set output
set(output.bendmoment,'String',num2str(round(BendMoment)));
set(output.totaldrag,'String',num2str(round(Dtotal*0.22481*10)/10));%Convert to lbf
set(output.inddrag,'String',num2str(round(Dind*0.22481*10)/10));%Convert to lbf
set(output.profdrag,'String',num2str(round(Dprofile*0.22481*10)/10));%Convert to lbf
set(output.range,'String',num2str(round(Range/1609*10)/10));%Convert m to miles
set(output.volume,'String',num2str(round(WingVolume*35.315*100)/100));%Convert to ft^3
set(output.calctime,'String',num2str(etime(clock,geo.t0)));
set(output.lift,'String',num2str(round(L*0.22481)));  %Convert to lbf
set(output.fuelweight,'String',num2str(round(Fuel_weight*0.22481)));  %Convert to lbf
set(output.payload,'String',num2str(round(Payload*0.22481)));  %Convert to lbf

%Conditional formatting; if payload < requirements, font -> red, score -> 0
if (Payload*0.22481 < 45000) ||  (Range/1609 < 2360) %Baseline payload and range of C130, Wikipedia
    set(output.SCORE,'String','0');
else
    set(output.SCORE,'String',num2str(round(Score*10)/10));
end

if Payload*0.22481 < 45000
    set(output.payload,'ForegroundColor','red')
else
    set(output.payload,'ForegroundColor','black')
end

if Range/1609 < 2360
    set(output.range,'ForegroundColor','red')
else
    set(output.range,'ForegroundColor','black')
end


function [newphase,usedmask] = comp_filterbankconstphase(abss,tgrad,fgrad,NEIGH,posInfo,fc,mask,usephase,a,M,N,tol,phasetype)

%sets the mask for the heap integration and acts as a wrapper for
%the corresponding C-function

%% The actual phase construction
sMax = max(abss(:));
absthr = max(sMax)*tol;

if isempty(mask)
    usedmask= zeros(size(abss));
else
    usedmask = cell2mat(mask);
end

%phasetype = 0;
% % Build the phase
if isempty(mask)
     % s is real and positive
     newphase = comp_filterbankheapint(abss,tgrad,fgrad,NEIGH,posInfo,fc,a,M,N,tol(1),phasetype);

     % Find all small coefficients and set the mask
     bigenoughidx = abss>absthr(1);
     usedmask(bigenoughidx) = 1;
 else
     newphase=comp_filterbankmaskedheapint(abss,tgrad,fgrad,NEIGH,posInfo,fc,mask,a,M,N,tol(1),...
                                     phasetype,usephase);
     % Find all small coefficients in the unknown phase area
     missingidx = find(usedmask==0);
     bigenoughidx = abss(missingidx)>absthr(1);
     usedmask(missingidx(bigenoughidx)) = 1;
end
%
% % Do further tol
for ii=2:numel(tol)
     newphase=comp_filterbankmaskedheapint(abss,tgrad,fgrad,NEIGH,posInfo,fc,usedmask,a,M,N,tol(ii),...
                                     phasetype,newphase);
     missingidx = find(usedmask==0);
     bigenoughidx = abss(missingidx)>absthr(ii);
     usedmask(missingidx(bigenoughidx)) = 1;
end

% Convert the mask so it can be used directly for indexing
usedmask = logical(usedmask);
% Assign random values to coefficients below tolerance
zerono = numel(find(~usedmask));
newphase(~usedmask) = rand(zerono,1)*2*pi;


function YESNO = is(X,property,additional)
%IS Check property of variable.
%   d = IS(x,property) returns 1 if 'property' holds
%
%   Properties possible to test are: 'real', 'symmetric', 'hermitian',
%   'scalar', 'linear', 'bilinear','quadratic','sigmonial', 'homogeneous', 'integer', 'binary'

switch property
    case 'logic'
        YESNO = X.typeflag==12;
    case 'binary'
        YESNO = any(ismember(depends(X),yalmip('binvariables')));
    case 'integer'
        YESNO = any(ismember(depends(X),yalmip('intvariables')));
    case 'quantized'
        YESNO = all(ismember(depends(X),yalmip('quantvariables')));
    case 'real'
        YESNO = isreal(X);
    case 'complex'
        YESNO = ~isreal(X.basis);
    case 'interval'
        YESNO = isa(X.basis,'intval');
    case 'symmetric'
        YESNO = issymmetric(X);
    case 'hermitian'
        YESNO = ishermitian(X);
    case 'scalar'
        YESNO = prod(X.dim)==1;
    case 'compound'
        YESNO = any(ismember(getvariables(X),yalmip('extvariables')));
    case 'linear'
        variabletype = yalmip('variabletype');
        variabletype = variabletype(X.lmi_variables);
        YESNO = ~any(variabletype);
    case 'bilinear'
        variabletype = yalmip('variabletype');
        variabletype = variabletype(X.lmi_variables);
        YESNO  = all(variabletype<=1);
     case 'quadratic'
         variabletype = yalmip('variabletype');
         variabletype = variabletype(X.lmi_variables);
         YESNO = all(variabletype<=2);

    case 'LBQS'
        % Fast code for use in display etc.
        % Checks linearity, bilinearity etc in one call.
        quadratic = 0;
        bilinear  = 0;
        linear    = 0;
        sigmonial = 0;

        variabletype = yalmip('variabletype');
        variabletype = variabletype(X.lmi_variables);

        linear    = all(variabletype==0);
        bilinear  = all(variabletype<=1) && ~linear;
        quadratic = all(variabletype<=2) && ~bilinear;
        sigmonial = any(variabletype==4);

        YESNO = full([linear bilinear quadratic sigmonial]);

    case 'lpcone'
          base = X.basis;
          YESNO = all(base(:,1)==0); % No constant
          base = base(:,2:end);
          YESNO = YESNO && all(sum(base,2)==1);
          YESNO = YESNO && all(sum(base,1)==1);
          YESNO = YESNO && all(sum(base~=0,2)==1);
          YESNO = YESNO && all(sum(base~=0,1)==1);
          YESNO = full(YESNO);

    case 'shiftlpcone'
          base = X.basis;
          base = base(:,2:end);
          YESNO = all(sum(base,2)==1);
          YESNO = YESNO && all(sum(base,1)==1);
          YESNO = YESNO && all(sum(base~=0,2)==1);
          YESNO = YESNO && all(sum(base~=0,1)==1);
          YESNO = full(YESNO);

    case 'complexsdpcone'
        if isequal(X.conicinfo,[sqrt(-1) 0])
            YESNO = 1;
            return
        else
            YESNO = 0;
        end

    case 'realsdpcone'
        if isequal(X.conicinfo,[1 0])
            YESNO = 1;
            return
        else
            YESNO = 0;
        end

    case 'sdpcone'
        if isequal(X.conicinfo,[1 0]) || isequal(X.conicinfo,[sqrt(-1) 0])
            YESNO = 1;
            return
        end
        base = X.basis;
        n = X.dim(1);
        YESNO = full(issymmetric(X) && nnz(base)==n*n && all(sum(base,2)==1) && all(base(:,1)==0)) && length(X.lmi_variables)==n*(n+1)/2 && isreal(base);

        % Fixes bug #15
        if length(X.lmi_variables)>1
            if ~all(diff(X.lmi_variables)==1)
                YESNO=0;
                return;
            end
        end

    case 'shiftsdpcone'

        if isequal(X.conicinfo,[1 0])
            YESNO = 1;
            return
        elseif isequal(X.conicinfo,[1 1])
            YESNO = 1;
            return
        elseif  isequal(X.conicinfo,[sqrt(-1) 0])
            YESNO = 1;
            return
        elseif isequal(X.conicinfo,[1 1])
            YESNO = 1;
            return
        end

        % Fixes bug #15
        if length(X.lmi_variables)>1
            if ~all(diff(X.lmi_variables)==1)
                YESNO=0;
                return;
            end
        end

        base = X.basis;
        n = X.dim(1);
        base(:,1)=0;
        YESNO = full(issymmetric(X) && nnz(base)==n*n && all(sum(base,2)==1)) && length(X.lmi_variables)==n*(n+1)/2 && isreal(X);
        if YESNO
            % Possible case
            % FIX : Stupidly slow and complex
            [i,j,k] = find(base');
            Y = reshape(1:n^2,n,n);
            Y = tril(Y);
            Y = (Y+Y')-diag(sparse(diag(Y)));
            [uu,oo,pp] = unique(Y(:));
            YESNO = isequal(i,pp+1);
        end

    case 'complexshiftsdpcone'

        if isequal(X.conicinfo,[1 0])
            YESNO = 1;
            return
        elseif isequal(X.conicinfo,[1 1])
            YESNO = 1;
            return
        elseif  isequal(X.conicinfo,[sqrt(-1) 0])
            YESNO = 1;
            return
        elseif isequal(X.conicinfo,[1 1])
            YESNO = 1;
            return
        end

        % Fixes bug #15
        if length(X.lmi_variables)>1
            if ~all(diff(X.lmi_variables)==1)
                YESNO=0;
                return;
            end
        end

        base = X.basis;
        n = X.dim(1);
        base(:,1)=0;
        YESNO = 0;
        if full(issymmetric(X) && nnz(base)==n*n && all(sum(base,2)==1)) && length(X.lmi_variables)==n*(n+1)/2 && isreal(X)
            % Possible case
            % FIX : Stupidly slow and complex
            [i,j,k] = find(base');
            Y = reshape(1:n^2,n,n);
            Y = tril(Y);
            Y = (Y+Y')-diag(sparse(diag(Y)));
            [uu,oo,pp] = unique(Y(:));
            YESNO = isequal(i,pp+1);
        elseif ishermitian(X) && nnz(base)==n*(n+1) && length(X.lmi_variables)==n^2
            temp = createImagBasis(n);
            if isequal(temp,base)
                YESNO = 1;
            end
        end

    case 'socone'
        base = X.basis;
        n = X.dim(1);
        YESNO = X.dim(1)>1 && X.dim(2)==1 && length(X.lmi_variables)==n;
        if YESNO
            cb = base(:,1);
            vb = base(:,2:end);
            YESNO = YESNO && (nnz(cb)==0) && (nnz(vb-speye(n))==0);
        end

    case 'sigmonial'
          monomtable = yalmip('monomtable');
          monomtable = monomtable(getvariables(X),:);
          YESNO = any(find(any(0>monomtable,2) | any(monomtable-fix(monomtable),2)));

    case 'general'
        evalvariables = yalmip('extvariables');
        YESNO = ~isempty(intersect(getvariables(X),evalvariables));

    case 'nonlinear'
        YESNO = ~islinear(X);

    case 'homogeneous'
        [sqrList,CompressedList] = yalmip('nonlinearvariables');
        [LinearTerms,NonlinearVariables] = getvariables(X,'both');
        if isempty(NonlinearVariables)
            YESNO = nnz(getbasematrix(X,0))==0;
        else
            % No linear terms
            YESNO = isempty(LinearTerms);
            % No constant terms
            YESNO = YESNO && (nnz(getbasematrix(X,0))==0);
            % Largest degree+1
            maxdegree = sum(any(CompressedList(find(ismember(CompressedList,NonlinearVariables)),:),1));
            % All same degree
            YESNO = YESNO && all(all(CompressedList(find(ismember(CompressedList,NonlinearVariables)),2:maxdegree)>0));
        end

    case 'sos'
        YESNO = (X.typeflag==11);
    case 'kyp'
        YESNO = (X.typeflag==9);
    case 'gkyp'
        YESNO = (X.typeflag==40);

    case 'unitary'
        n = size(X.basis,1);
        YESNO = isequal(X.basis,[sparse(n,1,0) speye(n)]);

    otherwise
        error('Wrong input argument.');
end

YESNO = full(YESNO);


classdef prtClassConstant < prtClass

    properties (SetAccess=private)

        name = 'Constant' % Fisher Linear Discriminant
        nameAbbreviation = 'Constant'            % FLD
        isNativeMary = true;  % False
    end

    properties
        constant
    end

    methods
        % Allow for string, value pairs
        function self = prtClassConstant(varargin)
            self = prtUtilAssignStringValuePairs(self,varargin{:});
        end

    end

    methods (Access=protected, Hidden = true)

        function self = trainAction(self,ds)
            self.constant = mean(ds.getY);
        end

        function ds = runAction(self,ds)
            ds.X = repmat(self.constant,ds.nObservations,1);
        end

    end

end


% Compute the relative perceptual saliency (PS)
function E = Relative_PS(imgIR, imgTV)

E = PS(imgIR)/PS(imgTV);

end