function stat = ft_statfun_bayesfactor(cfg, dat, design)

% FT_STATFUN_BAYESFACTOR computes the Bayes factor for a H0 of the data in two
% conditions having the same mean, versus H1 of the data having different means. This
% function supports both unpaired and paired designs and assumes flat priors.
%
% Lee and Wagenmakers (2013) provide these guidelines for its interpretation
%   IF B10 IS...    THEN YOU HAVE...
%     > 100           Extreme evidence for H1
%     30 – 100        Very strong evidence for H1
%     10 – 30         Strong evidence for H1
%     3 – 10          Moderate evidence for H1
%     1 – 3           Anecdotal evidence for H1
%     1               No evidence
%     1/3 – 1         Anecdotal evidence for H0
%     1/3 – 1/10      Moderate evidence for H0
%     1/10 – 1/30     Strong evidence for H0
%     1/30 – 1/100    Very strong evidence for H0
%     < 1/100         Extreme evidence for H0
%
% Use this function by calling one of the high-level statistics functions as
%   [stat] = ft_timelockstatistics(cfg, timelock1, timelock2, ...)
%   [stat] = ft_freqstatistics(cfg, freq1, freq2, ...)
%   [stat] = ft_sourcestatistics(cfg, source1, source2, ...)
% with the following configuration option:
%   cfg.statistic = 'ft_statfun_bayesfactor'
%
% The experimental design is specified as:
%   cfg.ivar  = independent variable, row number of the design that contains the labels of the conditions to be compared (default=1)
%   cfg.uvar  = optional, row number of design that contains the labels of the units-of-observation, i.e. subjects or trials (default=2)
%
% The labels for the independent variable should be specified as the number 1 and 2.
% The labels for the unit of observation should be integers ranging from 1 to the
% total number of observations (subjects or trials).
%
% The cfg.uvar option is only needed for paired data, you should leave it empty
% for non-paired data.
%
% See https://www.statisticshowto.datasciencecentral.com/bayes-factor-definition/ for some background.
%
% See also FT_TIMELOCKSTATISTICS, FT_FREQSTATISTICS or FT_SOURCESTATISTICS

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

% ensure that the required toolbox dependency is on the path
ft_hastoolbox('bayesFactor', 1);

% set the defaults
cfg.ivar = ft_getopt(cfg, 'ivar', 1);
cfg.uvar = ft_getopt(cfg, 'uvar', []); % default is empty, which means non-paired

if isempty(cfg.uvar)
  sel1 = find(design(cfg.ivar,:)==1); % select replications that belong to condition 1
  sel2 = find(design(cfg.ivar,:)==2); % select replications that belong to condition 2
  n1 = length(sel1);
  n2 = length(sel2);

  x1 = dat(:,sel1);
  x2 = dat(:,sel2);

  nchan = size(x1, 1);
  bf10  = nan(nchan, 1);
  prob  = nan(nchan, 1);
  ci_lo = nan(nchan, 1);
  ci_hi = nan(nchan, 1);
  tstat = nan(nchan, 1);
  diff  = mean(x1, 2) - mean(x2, 2); % this is the raw effect size

  for i=1:nchan
    [bf10(i), prob(i), CI, stats] = bf.ttest2(x1(i,:), x2(i,:));
    ci_lo(i) = CI(1);
    ci_hi(i) = CI(2);
    tstat(i) = stats.tstat;
  end

else
  subj = unique(design(cfg.uvar,:)); % it can also be paired over trials

  n = length(subj);
  sel1 = nan(size(subj));
  sel2 = nan(size(subj));
  for i=1:n
    sel1(i) = find(design(cfg.uvar,:)==subj(i) & design(cfg.ivar,:)==1);
    sel2(i) = find(design(cfg.uvar,:)==subj(i) & design(cfg.ivar,:)==2);
  end
  x1 = dat(:,sel1);
  x2 = dat(:,sel2);

  nchan = size(x1, 1);
  bf10  = nan(nchan, 1);
  prob  = nan(nchan, 1);
  ci_lo = nan(nchan, 1);
  ci_hi = nan(nchan, 1);
  tstat = nan(nchan, 1);
  diff  = mean(x1 - x2, 2); % this is the raw effect size

  for i=1:nchan
    [bf10(i), prob(i), CI, stats] = bf.ttest(x1(i,:) - x2(i,:));
    ci_lo(i) = CI(1);
    ci_hi(i) = CI(2);
    tstat(i) = stats.tstat;
  end

end % if uvar

% return the results for all channel-time-frequency points, for all voxels, or for all source locations
stat.bf10  = bf10(:);
stat.prob  = prob(:);
stat.diff  = diff(:);
stat.ci_lo = ci_lo(:);
stat.ci_hi = ci_hi(:);
stat.tstat = tstat(:);


function [logp, yhat, res] = tapas_logrt_linear_whatworld(r, infStates, ptrans)
% Calculates the log-probability of log-reaction times y (in units of log-ms) according to the
% linear log-RT model developed with Louise Marshall and Sven Bestmann
%
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2014 Christoph Mathys, UZH & ETHZ
%
% This file is part of the HGF toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

% Transform zetas to their native space
be0  = ptrans(1);
be1  = ptrans(2);
be2  = ptrans(3);
be3  = ptrans(4);
ze   = exp(ptrans(5));

% Initialize returned log-probabilities, predictions,
% and residuals as NaNs so that NaN is returned for all
% irregualar trials
n = size(infStates,1);
logp = NaN(n,1);
yhat = NaN(n,1);
res  = NaN(n,1);

% Weed irregular trials out from responses and inputs
y = r.y(:,1);
y(r.irr) = [];

u = r.u(:,1);
u(r.irr) = [];

% Extract trajectories of interest from infStates
mu1hat = squeeze(infStates(:,1,:,:,1));
mu1    = squeeze(infStates(:,1,:,:,3));
mu2    = squeeze(infStates(:,2,:,:,3));
sa2    = squeeze(infStates(:,2,:,:,4));
mu3    = squeeze(infStates(:,3,1,1,3));

% Surprise
% ~~~~~~~~

% mu1 contains the actually occurring transition -> multiply with
% mu1hat to get probability of that transition (other elements are
% zero)
otp    = mu1.*mu1hat; % observed transition probabilities (3-dim)
otps3  = sum(otp, 3, 'omitnan');      % sum over 3rd dim
otps23 = sum(otps3, 2, 'omitnan');    % sum over 2nd dim

surp = -log(otps23);
surp(r.irr) = [];

% Expected uncertainty
% ~~~~~~~~~~~~~~~~~~~~
euo    = mu1.*sa2;    % expected uncertainty of observed transition (3-dim)
euos3  = sum(euo, 3, 'omitnan');      % sum over 3rd dim
euos23 = sum(euos3, 2, 'omitnan');    % sum over 2nd dim

to     = mu1.*mu2;    % tendency of observed transition (3-dim)
tos3   = sum(to, 3, 'omitnan');       % sum over 3rd dim
tos23  = sum(tos3, 2, 'omitnan');     % sum over 2nd dim

eu = tapas_sgm(tos23,1).*(1-tapas_sgm(tos23,1)).*euos23; % transform down to 1st level
eu(r.irr) = [];

% Unexpected uncertainty
% ~~~~~~~~~~~~~~~~~~~~~~
ueu = tapas_sgm(tos23,1).*(1-tapas_sgm(tos23,1)).*exp(mu3); % transform down to 1st level
ueu(r.irr) = [];

% Calculate predicted log-reaction time
% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
logrt = be0 +be1.*surp +be2.*eu +be3.*ueu;

% Calculate log-probabilities for non-irregular trials
% Note: 8*atan(1) == 2*pi (this is used to guard against
% errors resulting from having used pi as a variable).
reg = ~ismember(1:n,r.irr);
logp(reg) = -1/2.*log(8*atan(1).*ze) -(y-logrt).^2./(2.*ze);
yhat(reg) = logrt;
res(reg) = y-logrt;

return;


function [rotationAngle,X,Y,finalImage,errors,finalOriginalImage] = ...
            alignTwoImages(image1,image2,angleGuess,spacing,...
                    fractionalPixelAccuracy,noRotation,originalImage)
%alignTwoImages rotationally and translationally aligns an image with a
%background image
%
%   Input variables:
%
%       image1 -> background image
%       image2 -> image to be aligned
%       angleGuess -> initial guess to eliminate 180 degree degeneracy
%       spacing -> angular spacing in Radon transform
%       fractionalPixelAccuracy -> accuracy of translational alignment
%       noRotation -> true if only translational alignment used
%       originalImage -> full version of image2 (optional)
%
%
%   Output variables:
%
%       rotationAngle -> rotational alignment angle
%       X, Y -> translational alignment values (in pixels)
%       finalImage -> aligned version of image2
%       errors -> errors in alignment
%       finalOriginalImage -> aligned version of originalImage (optional)
%
%
% (C) Gordon J. Berman, 2014
%     Princeton University

    if nargin < 3 || isempty(angleGuess) == 1
        angleGuess = 0;
    else
        angleGuess = mod(angleGuess,360);
    end

    angleGuess = angleGuess*pi/180;

    if nargin < 4 || isempty(spacing) == 1
        spacing = .5;
    end
    N = 180/spacing;

    if nargin < 5 || isempty(fractionalPixelAccuracy) == 1
        fractionalPixelAccuracy = .25;
    end

    if nargin < 6 || isempty(noRotation)
        noRotation = false;
    end

    if nargin < 7
        originalImage = [];
        finalOriginalImage = [];
    end

    errors = zeros(2,1);

    s = size(image1);

    if ~noRotation

        thetas = linspace(0, 180-spacing, N);

        %Find fft of the Radon transform
        F1 = abs(fft(radon(image1, thetas)));
        F2 = abs(fft(radon(image2, thetas)));

        %Find the index of the correlation peak
        correlation = sum(fft2(F1) .* fft2(F2));
        peaks = real(ifft(correlation));
        peakIndex = find(peaks==max(peaks));

        if length(peakIndex) > 1
            peakIndex = peakIndex(1);
        end

        %Find rotation angle via quadratic interpolation
        if (peakIndex~=1) && (peakIndex ~= N)
            p=polyfit(thetas((peakIndex-1):(peakIndex+1)),peaks((peakIndex-1):(peakIndex+1)),2);
            rotationAngle = -.5*p(2)/p(1);
            errors(1) = polyval(p,rotationAngle);
        else
            if peakIndex == 1
                p = polyfit([thetas(end)-180,thetas(1),thetas(2)],peaks([N,1,2]),2);
                rotationAngle = -.5*p(2)/p(1);
                errors(1) = polyval(p,rotationAngle);
                if rotationAngle < 0
                    rotationAngle = 180 + rotationAngle;
                end
            else
                p = polyfit([thetas(end-1),thetas(end),180+thetas(1)],peaks([N-1,N,1]),2);
                rotationAngle = -.5*p(2)/p(1);
                errors(1) = polyval(p,rotationAngle);
                if rotationAngle >= 180
                    rotationAngle = rotationAngle - 180;
                end
            end
        end

        %Check to see if rotation angle is in the correct direction
        rA = rotationAngle*pi/180;
        test = dot([cos(rA),sin(rA)],[cos(angleGuess),sin(angleGuess)]);
        if test < 0
            rotationAngle = mod(rotationAngle-180,360);
        end
        rotationAngle = mod(rotationAngle,360);
        toRotate = mod(-rotationAngle,360);

        %Rotate Image & Crop to original Size
        rotatedImage = imrotate(image2,toRotate,'crop');

    else

        rotationAngle = mod(angleGuess,360);
        toRotate = mod(-rotationAngle,360);
        rotatedImage = imrotate(image2,toRotate,'crop');

    end

    % Take 2D FFT of each image
    F1 = fft2(image1);
    F2 = fft2(rotatedImage);

    shifts = dftregistration(F1,F2,round(1/fractionalPixelAccuracy));
    X = shifts(4);
    Y = shifts(3);

    errors(2) = shifts(1);

    T = maketform('affine',[1 0 0 ;0 1 0;X Y 1]);
    if nargout > 3
        finalImage = imtransform(rotatedImage,T,'XData',[1 s(2)],'YData',[1 s(1)]);
    end

    if isempty(originalImage) == 0
        rotatedImage2 = imrotate(originalImage,toRotate,'crop');
        finalOriginalImage = imtransform(rotatedImage2,T,'XData',[1 s(2)],'YData',[1 s(1)]);
    end


function varargout = tps(varargin)
% VL_TPS  Compute the thin-plate spline basis
%   PHI=VL_TPS(X1,X2,Y) returns the basis PHI of a thin-plate spline
%   (TPS) defined on the domain X1,X2 with control points Y.
%
%   X1 and X2 are MxN matrices specifying the grid vertices.  When
%   warping images, these usually correspond to image pixels.
%
%   Y is a 2xK matrix specifying the control points, one per
%   column. Ofthen Y is a subset of the domain X1,X2, but this is not
%   required.
%
%   PHI is a (K+3)xNxM matrix, with one layer per basis element. Each
%   basis element is a function of the domain X1,X2.
%
%   [PHI,S] = VL_TPS(X1,X2,Y) additionally returns the stiffness matrix S
%   of the TPS.
%
%   See also: VL_WTPS(), VL_HELP().
[varargout{1:nargout}] = vl_tps(varargin{:});


gammaln(0.1) - 2.2527126517342059598697
gammaln(0.6) - .39823385806923489961685
gammaln(0.7) - .26086724653166651438573
gammaln(1.0)
gammaln(2.0)
gammaln(3.4) - 1.0923280598027415674947
gammaln(4.0) - 1.791759469228055000812477
gammaln(8.0) - 8.525161361065414300165531
gammaln(64.0) - 201.00931639928152667928
gammaln(256.0) - 1161.71210111840065079
if gammaln(0) ~= Inf
  error('gammaln(0) should be Inf');
end
if ~isnan(gammaln(-1))
  error('gammaln(-1) should be NaN');
end
if gammaln(Inf) ~= Inf
  error('gammaln(Inf) should be Inf');
end
% should be NaN?
gammaln(-Inf)
if ~isnan(gammaln(NaN))
  error('gammaln(NaN) should be NaN');
end


function phi = basis_brick27 ( n, p )

%*****************************************************************************80
%
%% BASIS_BRICK20: BRICK20 basis functions at natural coordinates.
%
%  Discussion:
%
%        8----19---7
%       /|         /
%     20 |   26   /|
%     /          / |
%    5----17----6  |
%    |   |      |  |
%    |  16---24-|-15
%    |  /|      | /|
%    |25 |  27  |23|        t
%    |/         |/ |        |   s
%   13----22---14  |        |  /
%    |   |      |  |        | /
%    |   |      |  |        |/
%    |   4--11--|--3        0---------r
%    |  /       | /
%    | 12   21  |10
%    |/         |/
%    1----9-----2
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 March 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of evaluation points.
%
%    Input, real P(3,N), natural coordinates of evaluation points.
%
%    Output, real PHI(27,N), the basis function values.
%
  rm(1:n) = p(1,1:n) + 1.0;
  rz(1:n) = p(1,1:n);
  rp(1:n) = p(1,1:n) - 1.0;

  sm(1:n) = p(2,1:n) + 1.0;
  sz(1:n) = p(2,1:n);
  sp(1:n) = p(2,1:n) - 1.0;

  tm(1:n) = p(3,1:n) + 1.0;
  tz(1:n) = p(3,1:n);
  tp(1:n) = p(3,1:n) - 1.0;

  phi(1,1:n)  =         rz .* rp       .* sz .* sp       .* tz .* tp / 8.0;
  phi(2,1:n)  =   rm .* rz             .* sz .* sp       .* tz .* tp / 8.0;
  phi(3,1:n)  =   rm .* rz       .* sm .* sz             .* tz .* tp / 8.0;
  phi(4,1:n)  =         rz .* rp .* sm .* sz             .* tz .* tp / 8.0;
  phi(5,1:n)  =         rz .* rp       .* sz .* sp .* tm .* tz       / 8.0;
  phi(6,1:n)  =   rm .* rz             .* sz .* sp .* tm .* tz       / 8.0;
  phi(7,1:n)  =   rm .* rz       .* sm .* sz       .* tm .* tz       / 8.0;
  phi(8,1:n)  =         rz .* rp .* sm .* sz       .* tm .* tz       / 8.0;

  phi(9,1:n)  = - rm       .* rp       .* sz .* sp       .* tz .* tp / 4.0;
  phi(10,1:n) = - rm .* rz       .* sm       .* sp       .* tz .* tp / 4.0;
  phi(11,1:n) = - rm       .* rp .* sm .* sz             .* tz .* tp / 4.0;
  phi(12,1:n) = -       rz .* rp .* sm       .* sp       .* tz .* tp / 4.0;
  phi(13,1:n) = -       rz .* rp       .* sz .* sp .* tm       .* tp / 4.0;
  phi(14,1:n) = - rm .* rz             .* sz .* sp .* tm       .* tp / 4.0;
  phi(15,1:n) = - rm .* rz       .* sm .* sz       .* tm       .* tp / 4.0;
  phi(16,1:n) = -       rz .* rp .* sm .* sz       .* tm       .* tp / 4.0;
  phi(17,1:n) = - rm       .* rp       .* sz .* sp .* tm .* tz       / 4.0;
  phi(18,1:n) = - rm .* rz       .* sm       .* sp .* tm .* tz       / 4.0;
  phi(19,1:n) = - rm       .* rp .* sm .* sz       .* tm .* tz       / 4.0;
  phi(20,1:n) = -       rz .* rp .* sm       .* sp .* tm .* tz       / 4.0;

  phi(21,1:n) =   rm       .* rp .* sm       .* sp       .* tz .* tp / 2.0;
  phi(22,1:n) =   rm       .* rp       .* sz .* sp .* tm       .* tp / 2.0;
  phi(23,1:n) =   rm .* rz       .* sm       .* sp .* tm       .* tp / 2.0;
  phi(24,1:n) =   rm       .* rp .* sm .* sz       .* tm       .* tp / 2.0;
  phi(25,1:n) =         rz .* rp .* sm       .* sp .* tm       .* tp / 2.0;
  phi(26,1:n) =   rm       .* rp .* sm       .* sp .* tm .* tz       / 2.0;

  phi(27,1:n) = - rm       .* rp .* sm       .* sp .* tm       .* tp;

  return
end


function alpha = backtracking_line_search_prox(problem, w, alpha, rho)
% This is a proximal backtracking algorithm.
%
% Inputs:
%       problem     function (cost/grad/hess)
%       w      current point
%       alpha       current stepsize
%       rho         shrink constant (<1)
% Output:
%       alpha       new stepsize
%
% References:
%
%
% This file is part of SGDLibrary.
%
% Created by H.Kasai on Nov. 19, 2018.
%
%   F(x) := f(x) + g(x);

    w0 = w;

    %% f0
    % calculate f0
%     F0 = problem.calculate_cost(w0);
%     reg0 = problem.calculate_reg(w0);
%     g0 = problem.lambda * reg0;
%     f0 = F0 - g0;
    f0 = problem.differentiable_cost(w0);

    % calculate g0
    grad0 = problem.full_grad(w0);

    % w = w - alpha * grads0
    w_out = w0 - alpha * grad0;

    % prox
    w_out = problem.prox(w_out, alpha);

    %% f1
    fk = problem.differentiable_cost(w_out);

    diff = w_out - w0;

    while fk > f0 + grad0'*diff + 1/(2*alpha) * (diff'*diff)
        alpha = rho * alpha;

        % w = w - alpha * grads0
        w_out = w0 - alpha * grad0;

        % prox
        w_out = problem.prox(w_out, alpha);

        %% fk
        fk = problem.differentiable_cost(w_out);
        diff = w_out - w0;

    end

%     while fk >= f0 + grad_f(x)'*z + (0.5/step)*norm(z,2)^2
%         lambda = rho * step;
%         z = prox(x - lambda*grad_f(x),lambda*g);
%     end

end


function scores = iForestAnomaly(X, t, psi)
%iForestAnomaly Use the path length to calculate the anomaly score
%   X: a m by n matrix, each row is a data point
%   t: the number of trees to construct
%   psi: the sub-sampling size

forest = iForest(X, t, psi);

[m ~] = size(X);
scores = zeros(m, 1);
for i=1:m
    x = X(i, :);
    for tree=forest
        path_length = 0;
        treenode = tree;
        while ~strcmp(class(treenode), 'iTreeLeaf')
            if treenode.compare(x)
                treenode = treenode.Right;
            else
                treenode = treenode.Left;
            end
            path_length = path_length + 1;
        end
        scores(i) = scores(i) + path_length + adjustment(treenode.Size);
    end
    scores(i) = 2^(-scores(i) / length(forest) / adjustment(m));
end
end

function value=adjustment(n)
%The average path length of an unsuccessful BST search
    if n<=1
        value = 0;
    else
        value = 2 * (log(n-1)+0.5772156649) - 2*(n-1) / n;
    end
end


function c=pfilt(f,g,varargin)
%PFILT  Apply filter with periodic boundary conditions
%   Usage:  h=pfilt(f,g);
%           h=pfilt(f,g,a,dim);
%
%   `pfilt(f,g)` applies the filter *g* to the input *f*. If *f* is a
%   matrix, the filter is applied along each column.
%
%   `pfilt(f,g,a)` does the same, but downsamples the output keeping only
%   every a'th sample (starting with the first one).
%
%   `pfilt(f,g,a,dim)` filters along dimension dim. The default value of
%   [] means to filter along the first non-singleton dimension.
%
%   The filter *g* can be a vector, in which case the vector is treated
%   as a zero-delay FIR filter.
%
%   The filter *g* can be a cell array. The following options are
%   possible:
%
%     * If the first element of the cell array is the name of one of the
%       windows from |firwin|, the whole cell array is passed onto
%       |firfilter|.
%
%     * If the first element of the cell array is `'bl'`, the rest of the
%       cell array is passed onto |blfilter|.
%
%     * If the first element of the cell array is `'pgauss'`, `'psech'`,
%       the rest of the parameters is passed onto the respective
%       function. Note that you do not need to specify the length *L*.
%
%   The coefficients obtained from filtering a signal *f* by a filter *g* are
%   defined by
%
%   ..          L-1
%      c(n+1) = sum f(l+1) * g(an-l+1)
%               l=0
%
%   .. math:: c\left(n+1\right)=\sum_{l=0}^{L-1}f\left(l+1\right)g\left(an-l+1\right)
%
%   where $an-l$ is computed modulo $L$.
%
%   See also: pconv

% Assert correct input.
if nargin<2
  error('%s: Too few input parameters.',upper(mfilename));
end;

definput.import={'pfilt'};
definput.keyvals.a=1;
definput.keyvals.dim=[];
[flags,kv,a,dim]=ltfatarghelper({'a','dim'},definput,varargin);

[f,L,Ls,W,dim,permutedsize,order]=assert_sigreshape_pre(f,[],dim,upper(mfilename));

[g,info] = comp_fourierwindow(g,L,upper(mfilename));

outIsReal = isreal(f) &&...
              (isfield(g,'h') && isreal(g.h) && ~(isfield(g,'fc') && g.fc~=0) || isfield(g,'H') && g.realonly);

asan = comp_filterbank_a(a,1);
g = comp_filterbank_pre({g},a,L,kv.crossover);

c = comp_filterbank(f,g,a);
c = c{1};

permutedsize(1)=size(c,1);

c=assert_sigreshape_post(c,dim,permutedsize,order);

if outIsReal
   c = real(c);
end


function [a,ass] = bipartiteMatchingIntProg(dst, nmatches)
% BIPARTITEMATCHINGINTPROG Use binary integer programming (linear objective) to solve for optimal linear assignment
% function a = bipartiteMatchingIntProg(dst)
% a(i) = best matching column for row i
%
% This gives the same result as bipartiteMatchingHungarian.
%
% function a = bibpartiteMatchingIntProg(dst, nmatches)
% only matches the specified number (must be <= min(size(dst))).
% This can be used to allow outliers in both source and target.
%
% For details, see Marciel & Costeira, "A global solution to sparse correspondence
% problems", PAMI 25(2), 2003

if nargin < 2, nmatches = []; end

[p1 p2] = size(dst);
p1orig = p1; p2orig = p2;
dstorig = dst;

if isempty(nmatches) % no outliers allowed  (modulo size difference)
  % ensure matrix is square
  m = max(dst(:));
  if p1<p2
    dst = [dst; m*ones(p2-p1, p2)];
  elseif p1>p2
    dst = [dst  m*ones(p1, p1-p2)];
  end
end
[p1 p2] = size(dst);

c = dst(:); % vectorize cost matrix

% row-sum: ensure each column sums to 1
A2 = kron(eye(p2), ones(1,p1));
b2 = ones(p2,1);

% col-sum: ensure each row sums to 1
A3 = kron(ones(1,p2), eye(p1));
b3 = ones(p1,1);

if isempty(nmatches)
  % enforce doubly  stochastic
  A = [A2; A3];
  b = [b2; b3];
  Aineq = zeros(1, p1*p2);
  bineq = 0;
else
  nmatches = min([nmatches, p1, p2]);
  Aineq = [A2; A3];
  bineq = [b2; b3]; % row and col sums <= 1
  A = ones(1,p1*p2);
  b = nmatches; % total num matches = b (otherwise get degenerate soln)
end

ass = bintprog(c, Aineq, bineq, A, b);
ass = reshape(ass, p1, p2);

a = zeros(1, p1orig);
for i=1:p1orig
  ndx = find(ass(i,:)==1);
  if ~isempty(ndx) & (ndx <= p2orig)
    a(i) = ndx;
  end
end


function pass = test_mean( )
% Test MEAN()

tol = 1000*chebfunpref().cheb2Prefs.chebfun2eps;

g = diskfun();
pass(1) = isempty(mean(g));

%%
g = diskfun(@(x,y) 0*x+1);
pass(2) = ( norm(mean(g)-.5) < tol ); %this direction includes measure on disk
pass(3) = ( norm(mean(g,2)-1)<tol );

g = diskfun(@(t,r) r.^2.*sin(2*t), 'polar');
pass(4) = ( norm(mean(g)-chebfun(@(t) .25*sin(2*t), [-pi pi], 'trig') ) < tol );
pass(5) = ( norm(mean(g,2)) < tol);

g = diskfun( @(x,y) exp(-10*x.^2-10*y.^2));
pass(6) = ( abs(sum(sum(g)) - sum2(g)) < tol );
end


function [feaNew] = SRDAtest(fea, model)
% SRDAtest: Spectral Regression Discriminant Analysis Testing
%               SRDAtest uses SRDA as a dimensionality reduction tool.
%
%       [feaNew,elapse] = SRDAtest(fea, model);
%
%             Input:
%
%               fea     - data matrix. Each row is a data point.
%             model     - model trained by SRKDAtrain.m
%
%             Output:
%
%             feaNew    - The data in the c-1 SRDA subspace, where c is the
%                         number of classes.
%
%    Examples:
%
%
% See also SRDAtrain, SRDApredict, SR, SR_caller
%
%Reference:
%
%   [1] Deng Cai, Xiaofei He and Jiawei Han, "SRDA: An Efficient Algorithm for
%   Large Scale Discriminant Analysis" IEEE Transactions on Knowledge and
%   Data Engineering, vol. 20, no. 1, pp. 1-12, January, 2008.
%
%   [2] Deng Cai, "Spectral Regression: A Regression Framework for
%   Efficient Regularized Subspace Learning", PhD Thesis, Department of
%   Computer Science, UIUC, 2009.
%
%
%   version 3.0 --Jan/2012
%   version 2.0 --December/2011
%   version 1.0 --May/2006
%
%   Written by Deng Cai (dengcai AT gmail.com)
%

if ~strcmp(model.TYPE,'SRDA')
    error('model does not match!');
end

if model.LARs
    feaNew = cell(length(model.LassoCardi),1);
    for i = 1:length(model.LassoCardi)
        feaNew{i} = fea*model.projection{i};
    end
else
    feaNew = fea*model.projection;
end


function C = fdct_wrapping(x, is_real, finest, nbscales, nbangles_coarse)

% fdct_wrapping.m - Fast Discrete Curvelet Transform via wedge wrapping - Version 1.0
%
% Inputs
%   x           M-by-N matrix
%
% Optional Inputs
%   is_real     Type of the transform
%                   0: complex-valued curvelets
%                   1: real-valued curvelets
%               [default set to 0]
%   finest      Chooses one of two possibilities for the coefficients at the
%               finest level:
%                   1: curvelets
%                   2: wavelets
%               [default set to 2]
%   nbscales    number of scales including the coarsest wavelet level
%               [default set to ceil(log2(min(M,N)) - 3)]
%   nbangles_coarse
%               number of angles at the 2nd coarsest level, minimum 8,
%               must be a multiple of 4. [default set to 16]
%
% Outputs
%   C           Cell array of curvelet coefficients.
%               C{j}{l}(k1,k2) is the coefficient at
%                   - scale j: integer, from finest to coarsest scale,
%                   - angle l: integer, starts at the top-left corner and
%                   increases clockwise,
%                   - position k1,k2: both integers, size varies with j
%                   and l.
%               If is_real is 1, there are two types of curvelets,
%               'cosine' and 'sine'. For a given scale j, the 'cosine'
%               coefficients are stored in the first two quadrants (low
%               values of l), the 'sine' coefficients in the last two
%               quadrants (high values of l).
%
% See also ifdct_wrapping.m, fdct_wrapping_param.m
%
% By Laurent Demanet, 2004

X = fftshift(fft2(ifftshift(x)))/sqrt(prod(size(x)));
[N1,N2] = size(X);
if nargin < 2, is_real = 0; end;
if nargin < 3, finest = 2; end;
if nargin < 4, nbscales = ceil(log2(min(N1,N2)) - 3); end;
if nargin < 5, nbangles_coarse = 16; end;

% Initialization: data structure
nbangles = [1, nbangles_coarse .* 2.^(ceil((nbscales-(nbscales:-1:2))/2))];
if finest == 2, nbangles(nbscales) = 1; end;
C = cell(1,nbscales);
for j = 1:nbscales
    C{j} = cell(1,nbangles(j));
end;

% Loop: pyramidal scale decomposition
M1 = N1/3;
M2 = N2/3;
if finest == 1,

    % Initialization: smooth periodic extension of high frequencies
    bigN1 = 2*floor(2*M1)+1;
    bigN2 = 2*floor(2*M2)+1;
    equiv_index_1 = 1+mod(floor(N1/2)-floor(2*M1)+(1:bigN1)-1,N1);
    equiv_index_2 = 1+mod(floor(N2/2)-floor(2*M2)+(1:bigN2)-1,N2);
    X = X(equiv_index_1,equiv_index_2);
        % Invariant: equiv_index_1(floor(2*M1)+1) == (N1 + 2 - mod(N1,2))/2
        % is the center in frequency. Same for M2, N2.
    window_length_1 = floor(2*M1) - floor(M1) - 1 - (mod(N1,3)==0);
    window_length_2 = floor(2*M2) - floor(M2) - 1 - (mod(N2,3)==0);
        % Invariant: floor(M1) + floor(2*M1) == N1 - (mod(M1,3)~=0)
        % Same for M2, N2.
    coord_1 = 0:(1/window_length_1):1;
    coord_2 = 0:(1/window_length_2):1;
    [wl_1,wr_1] = fdct_wrapping_window(coord_1);
    [wl_2,wr_2] = fdct_wrapping_window(coord_2);
    lowpass_1 = [wl_1, ones(1,2*floor(M1)+1), wr_1];
    if mod(N1,3)==0, lowpass_1 = [0, lowpass_1, 0]; end;
    lowpass_2 = [wl_2, ones(1,2*floor(M2)+1), wr_2];
    if mod(N2,3)==0, lowpass_2 = [0, lowpass_2, 0]; end;
    lowpass = lowpass_1'*lowpass_2;
    Xlow = X .* lowpass;

    scales = nbscales:-1:2;

else

    M1 = M1/2;
    M2 = M2/2;
    window_length_1 = floor(2*M1) - floor(M1) - 1;
    window_length_2 = floor(2*M2) - floor(M2) - 1;
    coord_1 = 0:(1/window_length_1):1;
    coord_2 = 0:(1/window_length_2):1;
    [wl_1,wr_1] = fdct_wrapping_window(coord_1);
    [wl_2,wr_2] = fdct_wrapping_window(coord_2);
    lowpass_1 = [wl_1, ones(1,2*floor(M1)+1), wr_1];
    lowpass_2 = [wl_2, ones(1,2*floor(M2)+1), wr_2];
    lowpass = lowpass_1'*lowpass_2;
    hipass = sqrt(1 - lowpass.^2);
    Xlow_index_1 = ((-floor(2*M1)):floor(2*M1)) + ceil((N1+1)/2);
    Xlow_index_2 = ((-floor(2*M2)):floor(2*M2)) + ceil((N2+1)/2);
    Xlow = X(Xlow_index_1, Xlow_index_2) .* lowpass;
    Xhi = X;
    Xhi(Xlow_index_1, Xlow_index_2) = Xhi(Xlow_index_1, Xlow_index_2) .* hipass;
    C{nbscales}{1} = fftshift(ifft2(ifftshift(Xhi)))*sqrt(prod(size(Xhi)));
    if is_real, C{nbscales}{1} = real(C{nbscales}{1}); end;

    scales = (nbscales-1):-1:2;

end;
for j = scales,

    M1 = M1/2;
    M2 = M2/2;
    window_length_1 = floor(2*M1) - floor(M1) - 1;
    window_length_2 = floor(2*M2) - floor(M2) - 1;
    coord_1 = 0:(1/window_length_1):1;
    coord_2 = 0:(1/window_length_2):1;
    [wl_1,wr_1] = fdct_wrapping_window(coord_1);
    [wl_2,wr_2] = fdct_wrapping_window(coord_2);
    lowpass_1 = [wl_1, ones(1,2*floor(M1)+1), wr_1];
    lowpass_2 = [wl_2, ones(1,2*floor(M2)+1), wr_2];
    lowpass = lowpass_1'*lowpass_2;
    hipass = sqrt(1 - lowpass.^2);
    Xhi = Xlow;                 % size is 2*floor(4*M1)+1 - by - 2*floor(4*M2)+1
    Xlow_index_1 = ((-floor(2*M1)):floor(2*M1)) + floor(4*M1) + 1;
    Xlow_index_2 = ((-floor(2*M2)):floor(2*M2)) + floor(4*M2) + 1;
    Xlow = Xlow(Xlow_index_1, Xlow_index_2);
    Xhi(Xlow_index_1, Xlow_index_2) = Xlow .* hipass;
    Xlow = Xlow .* lowpass;     % size is 2*floor(2*M1)+1 - by - 2*floor(2*M2)+1

    % Loop: angular decomposition
    l = 0;
    nbquadrants = 2 + 2*(~is_real);
    nbangles_perquad = nbangles(j)/4;
    for quadrant = 1:nbquadrants
        M_horiz = M2 * (mod(quadrant,2)==1) + M1 * (mod(quadrant,2)==0);
        M_vert = M1 * (mod(quadrant,2)==1) + M2 * (mod(quadrant,2)==0);
        if mod(nbangles_perquad,2),
            wedge_ticks_left = round((0:(1/(2*nbangles_perquad)):.5)*2*floor(4*M_horiz) + 1);
            wedge_ticks_right = 2*floor(4*M_horiz) + 2 - wedge_ticks_left;
            wedge_ticks = [wedge_ticks_left, wedge_ticks_right(end:-1:1)];
        else
            wedge_ticks_left = round((0:(1/(2*nbangles_perquad)):.5)*2*floor(4*M_horiz) + 1);
            wedge_ticks_right = 2*floor(4*M_horiz) + 2 - wedge_ticks_left;
            wedge_ticks = [wedge_ticks_left, wedge_ticks_right((end-1):-1:1)];
        end;
        wedge_endpoints = wedge_ticks(2:2:(end-1));         % integers
        wedge_midpoints = (wedge_endpoints(1:(end-1)) + wedge_endpoints(2:end))/2;
                % integers or half-integers

        % Left corner wedge
        l = l+1;
        first_wedge_endpoint_vert = round(2*floor(4*M_vert)/(2*nbangles_perquad) + 1);
        length_corner_wedge = floor(4*M_vert) - floor(M_vert) + ceil(first_wedge_endpoint_vert/4);
        Y_corner = 1:length_corner_wedge;
        [XX,YY] = meshgrid(1:(2*floor(4*M_horiz)+1),Y_corner);
        width_wedge = wedge_endpoints(2) + wedge_endpoints(1) - 1;
        slope_wedge = (floor(4*M_horiz) + 1 - wedge_endpoints(1))/floor(4*M_vert);
        left_line = round(2 - wedge_endpoints(1) + slope_wedge*(Y_corner - 1));
                                                            % integers
        [wrapped_data, wrapped_XX, wrapped_YY] = deal(zeros(length_corner_wedge,width_wedge));
        first_row = floor(4*M_vert)+2-ceil((length_corner_wedge+1)/2)+...
            mod(length_corner_wedge+1,2)*(quadrant-2 == mod(quadrant-2,2));
        first_col = floor(4*M_horiz)+2-ceil((width_wedge+1)/2)+...
            mod(width_wedge+1,2)*(quadrant-3 == mod(quadrant-3,2));
                % Coordinates of the top-left corner of the wedge wrapped
                % around the origin. Some subtleties when the wedge is
                % even-sized because of the forthcoming 90 degrees rotation
        for row = Y_corner
            cols = left_line(row) + mod((0:(width_wedge-1))-(left_line(row)-first_col),width_wedge);
            admissible_cols = round(1/2*(cols+1+abs(cols-1)));
            new_row = 1 + mod(row - first_row, length_corner_wedge);
            wrapped_data(new_row,:) = Xhi(row,admissible_cols) .* (cols > 0);
            wrapped_XX(new_row,:) = XX(row,admissible_cols);
            wrapped_YY(new_row,:) = YY(row,admissible_cols);
        end;
        slope_wedge_right = (floor(4*M_horiz)+1 - wedge_midpoints(1))/floor(4*M_vert);
        mid_line_right = wedge_midpoints(1) + slope_wedge_right*(wrapped_YY - 1);
                % not integers in general
        coord_right = 1/2 + floor(4*M_vert)/(wedge_endpoints(2) - wedge_endpoints(1)) * ...
            (wrapped_XX - mid_line_right)./(floor(4*M_vert)+1 - wrapped_YY);
        C2 = 1/(1/(2*(floor(4*M_horiz))/(wedge_endpoints(1) - 1) - 1) + 1/(2*(floor(4*M_vert))/(first_wedge_endpoint_vert - 1) - 1));
        C1 = C2 / (2*(floor(4*M_vert))/(first_wedge_endpoint_vert - 1) - 1);
        wrapped_XX((wrapped_XX - 1)/floor(4*M_horiz) + (wrapped_YY-1)/floor(4*M_vert) == 2) = ...
            wrapped_XX((wrapped_XX - 1)/floor(4*M_horiz) + (wrapped_YY-1)/floor(4*M_vert) == 2) + 1;
        coord_corner = C1 + C2 * ((wrapped_XX - 1)/(floor(4*M_horiz)) - (wrapped_YY - 1)/(floor(4*M_vert))) ./ ...
            (2-((wrapped_XX - 1)/(floor(4*M_horiz)) + (wrapped_YY - 1)/(floor(4*M_vert))));
        wl_left = fdct_wrapping_window(coord_corner);
        [wl_right,wr_right] = fdct_wrapping_window(coord_right);
        wrapped_data = wrapped_data .* (wl_left .* wr_right);

        switch is_real
            case 0
                wrapped_data = rot90(wrapped_data,-(quadrant-1));
                C{j}{l} = fftshift(ifft2(ifftshift(wrapped_data)))*sqrt(prod(size(wrapped_data)));
            case 1
                wrapped_data = rot90(wrapped_data,-(quadrant-1));
                x = fftshift(ifft2(ifftshift(wrapped_data)))*sqrt(prod(size(wrapped_data)));
                C{j}{l} = sqrt(2)*real(x);
                C{j}{l+nbangles(j)/2} = sqrt(2)*imag(x);
        end;

        % Regular wedges
        length_wedge = floor(4*M_vert) - floor(M_vert);
        Y = 1:length_wedge;
        first_row = floor(4*M_vert)+2-ceil((length_wedge+1)/2)+...
            mod(length_wedge+1,2)*(quadrant-2 == mod(quadrant-2,2));
        for subl = 2:(nbangles_perquad-1);
            l = l+1;
            width_wedge = wedge_endpoints(subl+1) - wedge_endpoints(subl-1) + 1;
            slope_wedge = ((floor(4*M_horiz)+1) - wedge_endpoints(subl))/floor(4*M_vert);
            left_line = round(wedge_endpoints(subl-1) + slope_wedge*(Y - 1));
            [wrapped_data, wrapped_XX, wrapped_YY] = deal(zeros(length_wedge,width_wedge));
            first_col = floor(4*M_horiz)+2-ceil((width_wedge+1)/2)+...
                mod(width_wedge+1,2)*(quadrant-3 == mod(quadrant-3,2));
            for row = Y
                cols = left_line(row) + mod((0:(width_wedge-1))-(left_line(row)-first_col),width_wedge);
                new_row = 1 + mod(row - first_row, length_wedge);
                wrapped_data(new_row,:) = Xhi(row,cols);
                wrapped_XX(new_row,:) = XX(row,cols);
                wrapped_YY(new_row,:) = YY(row,cols);
            end;
            slope_wedge_left = ((floor(4*M_horiz)+1) - wedge_midpoints(subl-1))/floor(4*M_vert);
            mid_line_left = wedge_midpoints(subl-1) + slope_wedge_left*(wrapped_YY - 1);
            coord_left = 1/2 + floor(4*M_vert)/(wedge_endpoints(subl) - wedge_endpoints(subl-1)) * ...
                (wrapped_XX - mid_line_left)./(floor(4*M_vert)+1 - wrapped_YY);
            slope_wedge_right = ((floor(4*M_horiz)+1) - wedge_midpoints(subl))/floor(4*M_vert);
            mid_line_right = wedge_midpoints(subl) + slope_wedge_right*(wrapped_YY - 1);
            coord_right = 1/2 + floor(4*M_vert)/(wedge_endpoints(subl+1) - wedge_endpoints(subl)) * ...
                (wrapped_XX - mid_line_right)./(floor(4*M_vert)+1 - wrapped_YY);
            wl_left = fdct_wrapping_window(coord_left);
            [wl_right,wr_right] = fdct_wrapping_window(coord_right);
            wrapped_data = wrapped_data .* (wl_left .* wr_right);
            switch is_real
                case 0
                    wrapped_data = rot90(wrapped_data,-(quadrant-1));
                    C{j}{l} = fftshift(ifft2(ifftshift(wrapped_data)))*sqrt(prod(size(wrapped_data)));
                case 1
                    wrapped_data = rot90(wrapped_data,-(quadrant-1));
                    x = fftshift(ifft2(ifftshift(wrapped_data)))*sqrt(prod(size(wrapped_data)));
                    C{j}{l} = sqrt(2)*real(x);
                    C{j}{l+nbangles(j)/2} = sqrt(2)*imag(x);
            end;
        end;

        % Right corner wedge
        l = l+1;
        width_wedge = 4*floor(4*M_horiz) + 3 - wedge_endpoints(end) - wedge_endpoints(end-1);
        slope_wedge = ((floor(4*M_horiz)+1) - wedge_endpoints(end))/floor(4*M_vert);
        left_line = round(wedge_endpoints(end-1) + slope_wedge*(Y_corner - 1));
        [wrapped_data, wrapped_XX, wrapped_YY] = deal(zeros(length_corner_wedge,width_wedge));
        first_row = floor(4*M_vert)+2-ceil((length_corner_wedge+1)/2)+...
            mod(length_corner_wedge+1,2)*(quadrant-2 == mod(quadrant-2,2));
        first_col = floor(4*M_horiz)+2-ceil((width_wedge+1)/2)+...
            mod(width_wedge+1,2)*(quadrant-3 == mod(quadrant-3,2));
        for row = Y_corner
            cols = left_line(row) + mod((0:(width_wedge-1))-(left_line(row)-first_col),width_wedge);
            admissible_cols = round(1/2*(cols+2*floor(4*M_horiz)+1-abs(cols-(2*floor(4*M_horiz)+1))));
            new_row = 1 + mod(row - first_row, length_corner_wedge);
            wrapped_data(new_row,:) = Xhi(row,admissible_cols) .* (cols <= (2*floor(4*M_horiz)+1));
            wrapped_XX(new_row,:) = XX(row,admissible_cols);
            wrapped_YY(new_row,:) = YY(row,admissible_cols);
        end;
        slope_wedge_left = ((floor(4*M_horiz)+1) - wedge_midpoints(end))/floor(4*M_vert);
        mid_line_left = wedge_midpoints(end) + slope_wedge_left*(wrapped_YY - 1);
        coord_left = 1/2 + floor(4*M_vert)/(wedge_endpoints(end) - wedge_endpoints(end-1)) * ...
            (wrapped_XX - mid_line_left)./(floor(4*M_vert) + 1 - wrapped_YY);
        C2 = -1/(2*(floor(4*M_horiz))/(wedge_endpoints(end) - 1) - 1 + 1/(2*(floor(4*M_vert))/(first_wedge_endpoint_vert - 1) - 1));
        C1 = -C2 * (2*(floor(4*M_horiz))/(wedge_endpoints(end) - 1) - 1);
        wrapped_XX((wrapped_XX - 1)/floor(4*M_horiz) == (wrapped_YY - 1)/floor(4*M_vert)) = ...
            wrapped_XX((wrapped_XX - 1)/floor(4*M_horiz) == (wrapped_YY - 1)/floor(4*M_vert)) - 1;
        coord_corner = C1 + C2 * (2-((wrapped_XX - 1)/(floor(4*M_horiz)) + (wrapped_YY - 1)/(floor(4*M_vert)))) ./ ...
            ((wrapped_XX - 1)/(floor(4*M_horiz)) - (wrapped_YY - 1)/(floor(4*M_vert)));
        wl_left = fdct_wrapping_window(coord_left);
        [wl_right,wr_right] = fdct_wrapping_window(coord_corner);

        wrapped_data = wrapped_data .* (wl_left .* wr_right);
        switch is_real
            case 0
                wrapped_data = rot90(wrapped_data,-(quadrant-1));
                C{j}{l} = fftshift(ifft2(ifftshift(wrapped_data)))*sqrt(prod(size(wrapped_data)));
            case 1
                wrapped_data = rot90(wrapped_data,-(quadrant-1));
                x = fftshift(ifft2(ifftshift(wrapped_data)))*sqrt(prod(size(wrapped_data)));
                C{j}{l} = sqrt(2)*real(x);
                C{j}{l+nbangles(j)/2} = sqrt(2)*imag(x);
        end;

        if quadrant < nbquadrants, Xhi = rot90(Xhi); end;
    end;
end;

% Coarsest wavelet level
C{1}{1} = fftshift(ifft2(ifftshift(Xlow)))*sqrt(prod(size(Xlow)));
if is_real == 1,
    C{1}{1} = real(C{1}{1});
end;


function alpha = formatAngle(alpha)
%FORMATANGLE  Ensure an angle value is comprised between 0 and 2*PI
%   ALPHA2 = formatAngle(ALPHA)
%   ALPHA2 is the same as ALPHA modulo 2*PI and is positive.
%
%   Example:
%   formatAngle(5*pi)
%   ans =
%       3.1416
%
%   See also
%   vectorAngle, lineAngle
%
% ------
% Author: David Legland
% e-mail: david.legland@nantes.inra.fr
% Created: 2008-03-10,    using Matlab 7.4.0.287 (R2007a)
% Copyright 2008 INRA - BIA PV Nantes - MIAJ Jouy-en-Josas.

% HISTORY
% 2010-03-31 deprecate and replace by function 'normalizeAngle'

% deprecation warning
warning('geom2d:deprecated', ...
    '''formatAngle'' is deprecated, use ''normalizeAngle'' instead');

alpha = mod(alpha, 2*pi);
alpha(alpha<0) = 2*pi + alpha(alpha<0);


function y = mean_nan(x)

count = sum(~isnan(x));
x(find(isnan(x)))=0;
y = sum(x)./count;


function CODEWORD = RS_ENC(INFO,n,k,g,field)

%CODEWORD = RS_ENC(INFO,n,k,g,field)
%
% m  is the number of bits of each symbol
% n = 2^m-1 => the number of symbols transmitted
% k = the number of code symbols that is going to be codes to a n symbol message
% t = the number of errors that can be found + corrected

%Tripple-error-correcting Reed-Solomon code with symbols from GF(2^4)
% Lin & Costello p.175 and article: Reed_Solomon Codes by Joel Sylvester

%generator polynomial

%field = gftuple([-1:2^m-2]', m, 2);

%p = 2; m = 4;
%primpoly = [0 0 -Inf -Inf 0];
%field = gftuple([-1:p^m-2]',primpoly,p);

%Lin + Costello, p.171

%Encoder (Article)
%shift codeword by X^(n-k)
for ii = 1:n-k
    shiftpol(ii) = -Inf;
end
%shiftpol(n-k+1) = 0;
shiftcode = [shiftpol INFO];

%divide shifted codeword by g(x)
[Q, R] = GFDECONV(shiftcode, g, field);

while length(R) < n-k
    R = [R -inf];
end

CODEWORD = [R INFO];

%CODWORD = gfconv(CODEWORD,0,field);

for i =1:n
    if CODEWORD(i) == -1
        CODEWORD(i) = -Inf;
    end
end


function [MW] = Btuph2MW(Btuph)
% Convert power from British thermal units per hour to megawatts.
% Chad A. Greene 2012
MW = Btuph*2.930710702e-7;


% Copyright (C) 2012 Quan Wang <wangq10@rpi.edu>,
% Signal Analysis and Machine Perception Laboratory,
% Department of Electrical, Computer, and Systems Engineering,
% Rensselaer Polytechnic Institute, Troy, NY 12180, USA
%
% You are free to use this software for academic purposes if you cite our paper:
% Quan Wang, Kim L. Boyer,
% The active geometric shape model: A new robust deformable shape model and its applications,
% Computer Vision and Image Understanding, Volume 116, Issue 12, December 2012, Pages 1178-1194,
% ISSN 1077-3142, 10.1016/j.cviu.2012.08.004.
%
% For commercial use, please contact the authors.

function GI = gaussianBlur(I,s)
%%  perform Gaussian blur
%   I: input image
%   s: standard deviation
%   GI: blurred image

M = gaussianMask(1,s);
if max(size(M))==0
    GI=I;
    return;
end
M = M/sum(sum(M));   % normalize the gaussian mask
GI=I;
for i=1:(2*s+1)
    GI=BoundMirrorExpand(GI);
end
GI = conv2(GI,M,'same');
for i=1:(2*s+1)
    GI=BoundMirrorShrink(GI);
end


function dat=func_ar(dat, order, varargin)
% func_ar (Feature extraction) :
%
% This function calculates the autoregression(AR) parameter.
%
% Example:
% [out] = func_ar(dat, 7, {'method','arburg'})
%
% Returs:
%     dat    - Data structure, segmented
%     order  - Order of AR setting
% Option: models for obtatining AR parameter
%     method - 'aryule'(default), 'arburg', 'arcov', 'armcov'
%

opt=opt_cellToStruct(varargin{:});
opt=struct('method',opt.method);

if isempty(dat)
    warning('[OpenBMI] Warning! data is empty.');
end

if isempty(order)
    warning('[OpenBMI] Order is not exist.');
end

if isempty(opt.method) %method selection
   opt.method='aryule';
end

[T, nEvents , nChans]= size(dat.x);

temp_ar= [];
for i= 1:nChans*nEvents,
  ar= feval(opt.method, dat.x(:,i), order);
  temp_ar(:,i)= ar(2:end)';
end

dat.x= temp_ar;


function [HP, LP] = sample_patches(im, patch_size, patch_num, upscale)

if size(im, 3) == 3,
    hIm = rgb2gray(im);
else
    hIm = im;
end

% generate low resolution counter parts
lIm = imresize(hIm, 1/upscale, 'bicubic');
lIm = imresize(lIm, size(hIm), 'bicubic');
[nrow, ncol] = size(hIm);

x = randperm(nrow-2*patch_size-1) + patch_size;
y = randperm(ncol-2*patch_size-1) + patch_size;

[X,Y] = meshgrid(x,y);

xrow = X(:);
ycol = Y(:);

if patch_num < length(xrow),
    xrow = xrow(1:patch_num);
    ycol = ycol(1:patch_num);
end

patch_num = length(xrow);

hIm = double(hIm);
lIm = double(lIm);

H = zeros(patch_size^2,     length(xrow));
L = zeros(4*patch_size^2,   length(xrow));

% compute the first and second order gradients
hf1 = [-1,0,1];
vf1 = [-1,0,1]';

lImG11 = conv2(lIm, hf1,'same');
lImG12 = conv2(lIm, vf1,'same');

hf2 = [1,0,-2,0,1];
vf2 = [1,0,-2,0,1]';

lImG21 = conv2(lIm,hf2,'same');
lImG22 = conv2(lIm,vf2,'same');

for ii = 1:patch_num,
    row = xrow(ii);
    col = ycol(ii);

    Hpatch = hIm(row:row+patch_size-1,col:col+patch_size-1);

    Lpatch1 = lImG11(row:row+patch_size-1,col:col+patch_size-1);
    Lpatch2 = lImG12(row:row+patch_size-1,col:col+patch_size-1);
    Lpatch3 = lImG21(row:row+patch_size-1,col:col+patch_size-1);
    Lpatch4 = lImG22(row:row+patch_size-1,col:col+patch_size-1);

    Lpatch = [Lpatch1(:),Lpatch2(:),Lpatch3(:),Lpatch4(:)];
    Lpatch = Lpatch(:);

    HP(:,ii) = Hpatch(:)-mean(Hpatch(:));
    LP(:,ii) = Lpatch;
end


function [f,p] = spm_DEM_basis(x,v,P)
% evaluates a parameterized set of basis functions
% problem
% FORMAT [f,p] = spm_DEM_basis(x,v,P)
%
% x   - hidden states
% v   - causal inputs
% P   - parameters
%
% f   - f(x)
% p   - p(i)
%
% returns:
%   f = sum(P(i)*B(x,i))
%   P = p/sum(p)
%
% where B(x,i) are basis functions
%
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_DEM_basis.m 3140 2009-05-21 18:38:17Z karl $

% basis set
%--------------------------------------------------------------------------
try, basis; catch, basis = 'radial'; end

% evaluate basis functions
%==========================================================================
switch basis

    case{'radial'}

        % Gaussian basis functions
        %------------------------------------------------------------------
        X = linspace(-2,2,length(P));
        W = 4*log(2)/(X(2) - X(1))^2;
        for i = 1:length(P)
            p(:,i) = exp(-W*(x - X(i)).^2);
        end
        f = (p*P(:))./sum(p,2);

    case{'spline'}

        % Natural spline
        %------------------------------------------------------------------
        X = linspace(-2,2,length(P));
        f = spline(X,P,x);

    case{'poly'}

        % Polynomial basis set
        %------------------------------------------------------------------
        f     = 0;
        for i = 1:length(P.p)
            B = x.^(i - 1);
            f = f + P.p(i)*B;
        end

    case{'dct'}

        % Discrete cosine basis set
        %------------------------------------------------------------------
        f     = 0;
        for i = 1:length(P.p)
            B = cos(i*pi*x/2);
            f = f + P.p(i)*B;
        end
end

f = spm_vec(f);


function [S,m,psi] = ComputeStokesQuad(HH,HV,VH,VV,SmoothSize)
%COMPUTESTOKESQUAD: Alpha/Entropy approximation for quad pol data (used
%Stokes for dual so we're keeping the name for consistency)

%Pauli basis
P_11 = fastrunmean(abs(HH+VV).*abs(HH+VV),[SmoothSize SmoothSize],'mean');
P_22 = fastrunmean(abs(HH-VV).*abs(HH-VV),[SmoothSize SmoothSize],'mean');
P_33 = fastrunmean(abs(HV-VH).*abs(HV-VH),[SmoothSize SmoothSize],'mean');

%span is the trace of the Pauli basis
S = P_11 + P_22 + P_33;

N_11 = P_11./S;
N_22 = P_22./S;
N_33 = P_33./S;

Frob = sqrt(N_11.*N_11 + N_22.*N_22 + N_33.*N_33);
m = 1.5*(1-Frob.*Frob);
psi = acosd(sqrt(N_11));
%psi = (pi/2)*(1-N_11);

end


function [offsetsRows, offsetsCols, distances] = templateMatchingIntegralImage(row,...
    col,patchSize, searchWindowSize, image)
% This function should for each possible offset in the search window
% centred at the current row and col, save a value for the offsets and
% patch distances, e.g. for the offset (-1,-1)
% offsetsX(1) = -1;
% offsetsY(1) = -1;
% distances(1) = 0.125;

% The distance is simply the SSD over patches of size patchSize between the
% 'template' patch centred at row and col and a patch shifted by the
% current offset

% This time, use the integral image method!
% NOTE: Use the 'computeIntegralImage' function developed earlier to
% calculate your integral images
% NOTE: Use the 'evaluateIntegralImage' function to calculate patch sums

image = double(image);
[rows columns d] = size(image);

% The intialization is the same as the TemplateMatching in the naive case
delta = floor(patchSize/2);
delta_window = floor(searchWindowSize/2);

distances = zeros(1,searchWindowSize*searchWindowSize);
offsetsRows = zeros(1,searchWindowSize*searchWindowSize);
offsetsCols = zeros(1,searchWindowSize*searchWindowSize);
distances_index = 1;

% I store all my integral images in a Cell Array
integralImagesCell = cell(searchWindowSize, searchWindowSize);

% all the possible offsets are all the possible combinations of indices in
% thesearch window
    for row_searchWindow = -delta_window:delta_window
        for column_searchWindow = -delta_window:delta_window

            xOffset = row_searchWindow;
            yOffset = column_searchWindow;

            % HOW WE CAN SHIFT THE IMAGE
            % CASE ONE -- AFFINE TRANFSORMATION
            %T = maketform('affine', [1 0 0; 0 1 0; yOffset xOffset  1]);
            %shifted_image = imtransform(image, T,'XData',[1 size(image,2)],'YData',[1 size(image,1)]);

            % CASE TWO -- CIRCULAR SHIFT
            %shifted_image = circshift(image , [xOffset,yOffset]);

            %TRANSLATE THE IMAGE
            shifted_image = imtranslate(image,[yOffset, xOffset]);

            % Let's compute the integral image for the difference squared of the
            % two images (how I compute the integral image is explained in
            % the method "computeIntegralImage").
            integral_image = computeIntegralImage((double(shifted_image-image)).^2, false);

            % Store the result, note the cell has no negative indices
            integralImagesCell{xOffset+delta_window+1, yOffset+delta_window+1} = integral_image;

            %NOTE : we can also store the integral images ina matrix or in a
            %       dictionary
            %c([num2str(xOffset) ' ' num2str(yOffset)]) = integral_image;
            %integralImages(:,:, index:index+2) = integral_image;

        end
    end

    start_rows = max(row-delta_window, 1+delta);
    end_rows = min(row+delta_window, rows-delta);
    start_columns = max(col-delta_window, 1+delta);
    end_columns = min(col+delta_window, columns-delta);

            for row_searchWindow = start_rows : end_rows
                for column_searchWindow = start_columns : end_columns

                    % SOME DEBUG CODE
                    %disp('###################');
                    %disp(row_searchWindow-delta);
                    %disp(column_searchWindow);
                    %disp(delta);
                    %disp(column_searchWindow-delta);
                    %disp(column_searchWindow+delta);

                    xOffset = row_searchWindow - row;
                    yOffset = column_searchWindow - col;

                    % Get the corresponding integral image at the two
                    % offsets
                    integral_image = integralImagesCell{xOffset+delta_window+1, yOffset+delta_window+1};

                    % compute the distance between the two patches
                    distance = evaluateIntegralImage(integral_image, row_searchWindow, column_searchWindow, delta);

                    % Store the results
                    distances(distances_index) = distance;
                    offsetsRows(distances_index) = xOffset;
                    offsetsCols(distances_index) = yOffset;
                    distances_index = distances_index + 1;
                end
            end

end


% adjustcylinder() - Adjust 3d object coordinates to match a pair of points
%
% Usage:
%   >> [x y z] = adjustcylinder( x, y, z, pos1, pos2);
%
% Inputs:
%  x,y,z      - 3-D point coordinates
%  pos1       - position of first point [x y z]
%  pos2       - position of second point [x y z]
%
% Outputs:
%  x,y,z      - updated 3-D point coordinates
%
% Author: Arnaud Delorme, CNL / Salk Institute, 30 Mai 2003

% Copyright (C) 2003 Arnaud Delorme
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (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, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function [x, y, z] = adjustcylinder2( h, pos1, pos2);

    % figure; plot3(x(2,:),y(2,:),z(2,:)); [ x(2,:)' y(2,:)' z(2,:)']

    % stretch z coordinates to match for vector length
    % ------------------------------------------------
    dist = sqrt(sum((pos1-pos2).^2));
    z = get(h, 'zdata');
    zrange = max(z(:)) - min(z(:));
    set(h, 'zdata', get(h, 'zdata') /zrange*dist);

    % rotate in 3-D to match vector angle [0 0 1] -> vector angle)
    % only have to rotate in the x-z and y-z plane
    % --------------------------------------------
    vectrot = [ pos2(1)-pos1(1) pos2(2)-pos1(2) pos2(3)-pos1(3)];
    [thvect phivect] = cart2sph( vectrot(1), vectrot(2), vectrot(3) );

    rotate(h, [0 0 1], thvect/pi*180, [0 0 0]);
    rotate(h, [thvect+pi/2 0]/pi*180, (pi/2-phivect)/pi*180, [0 0 0]);

    x = get(h, 'xdata') + pos1(1);
    y = get(h, 'ydata') + pos1(2);
    z = get(h, 'zdata') + pos1(3);

    set(h, 'xdata', x);
    set(h, 'ydata', y);
    set(h, 'zdata', z);
    return;


function [ i, j, S ] = pendulumDF( y )
%pendulumDF Jacobian of the pendulum equations.

    g = 1;
    m = 1;
    l = 1;

    it = [ 1  3         3          2  4         4         5      5      5      5];
    jt = [ 3  5         1          4  5         2         1      2      3      4 ];
    S = [1  -y(1,1)/m -y(5,1)/m  1  -y(2,1)/m -y(5,1)/m y(3,1) y(4,1) y(1,1) y(2,1) ];
    i = it;
    j = jt;

end


function value = daub2_condition ( n )

%*****************************************************************************80
%
%% DAUB2_DETERMINANT returns the L1 condition of the DAUB2 matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 January 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%
%    Output, real VALUE, the L1 condition.
%
  c0 = sqrt ( 2.0 ) / 2.0;
  c1 = sqrt ( 2.0 ) / 2.0;

  a_norm = abs ( c0 ) + abs ( c1 );
  b_norm = a_norm;
  value = a_norm * b_norm;

  return
end


function K=compute_permutation_constraint4(V)

% Copyright (C) <2007>  <Francesc Moreno-Noguer, Vincent Lepetit, Pascal Fua>
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the version 3 of the GNU General Public License
% as published by the Free Software Foundation.
%
% 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/>.
%
% Francesc Moreno-Noguer, CVLab-EPFL, September 2007.
% fmorenoguer@gmail.com, http://cvlab.epfl.ch/~fmoreno/

%[B11,B12,...,B33]=lambda1*v1+lambda2*v2+lambda3*v3

N=size(V,2); %dimension of the kernel
n=4; %dimension of Bij
idx=[1 2 3 4; 2 5 6 7; 3 6 8 9; 4 7 9 10];

%1.-Generation of the first set of equations Bii.Bjj=Bij.Bii  (n(n-1)/2 eqs).
nrowsK=n*(n-1)/2+n*(n-1)*n/2;
ncolsK=N*(N+1)/2;
K=zeros(nrowsK,ncolsK);

t=1;
for i=1:n
    for j=i+1:n
        offset=1;
        for a=1:N
            for b=a:N
                if a==b
                    K(t,offset)=V(idx(i,i),a)*V(idx(j,j),a)-V(idx(i,j),a)*V(idx(i,j),a);
                else
                    K(t,offset)=V(idx(i,i),a)*V(idx(j,j),b)-V(idx(i,j),a)*V(idx(i,j),b)+...
                                V(idx(i,i),b)*V(idx(j,j),a)-V(idx(i,j),b)*V(idx(i,j),a);
                end
                offset=offset+1;
            end

        end
        t=t+1;
        %fprintf('t:%d\t offset:%d\n',t,offset);
    end
end

for k=1:n
    for j=k:n
        for i=1:n
            if (i~=j & i~=k)
                offset=1;
                for a=1:N
                    for b=a:N
                        if a==b
                            K(t,offset)=V(idx(i,j),a)*V(idx(i,k),a)-V(idx(i,i),a)*V(idx(j,k),a);
                        else
                            K(t,offset)=V(idx(i,j),a)*V(idx(i,k),b)-V(idx(i,i),a)*V(idx(j,k),b)+...
                                        V(idx(i,j),b)*V(idx(i,k),a)-V(idx(i,i),b)*V(idx(j,k),a);
                        end
                        offset=offset+1;
                    end

                end
                t=t+1;
                %fprintf('t:%d\t offset:%d\n',t,offset);
            end
        end
    end
end


%% GMWB Script for GPUs
% This script is adapted from the code for the MathWorks webinar "Modeling
% Variable Annuities with MATLAB" found at:
%
% http://www.mathworks.com/matlabcentral/fileexchange/26960-modeling-variable-annuities-with-matlab
%
% It is designed to highlight some of the coding considerations that must
% be addressed if one wishes to move such an analysis from a CPU
% environment onto a GPU.
%
% Original: Yi Wang, MathWorks, 2010
% Adapted: Michael Weidman, Quantitative Support Services, Ltd., 2013

%% 1. Set Parameters and Load Data

annualFee               = 0.005;
riskFreeRate            = 0.05;
annualWithdrawalRate    = 0.07;
nYears                  = 20;

nTrials                 = 1e5;

% Investment Portfolio
Ticker = {'MMM', 'AA', 'AXP', 'T', 'BAC', 'BA', 'CAT', 'CVX', 'CSCO', 'KO'};

% Range for historical data
FromDate    = '01/01/2000';
ToDate      = '01/01/2010';
Period      = 'm'; % Monthly data

% Assume we're holding 10 shares of each stock in our portfolio
Holdings = 10*ones(length(Ticker), 1);

TimeSeries = getEquityData(Ticker, FromDate, ToDate, Period);

dispResults('header')

%% 2. Price GMWB I: Original Code

tic

assetPrice = simAssetPrice_orig(TimeSeries, Period, nYears, nTrials);

[AccountVal, PayoutVal, FeeVal] = calcValuePayoutAndFees_orig( ...
    Holdings, assetPrice, annualWithdrawalRate, annualFee);

toc1 = toc;

cost = pvvar(mean(PayoutVal, 2), riskFreeRate);
fee = pvvar(mean(FeeVal, 2), riskFreeRate);
probRuin = calcProbRuin(AccountVal);

dispResults('Original', cost, fee, probRuin, toc1)

%% 3. Price GMWB II: Vectorized Code, GPU

tic

assetPrice = simAssetPrice_orig(TimeSeries, Period, nYears, nTrials);

HoldingsG               = gpuArray(Holdings);
assetPriceG             = gpuArray(assetPrice);
annualWithdrawalRateG   = gpuArray(annualWithdrawalRate);
annualFeeG              = gpuArray(annualFee);

[AccountValG, PayoutValG, FeeValG] = calcValuePayoutAndFees_GPU( ...
    HoldingsG, assetPriceG, annualWithdrawalRateG, annualFeeG);

AccountVal  = gather(AccountValG);
PayoutVal   = gather(PayoutValG);
FeeVal      = gather(FeeValG);

toc1 = toc;

cost = pvvar(mean(PayoutVal, 2), riskFreeRate);
fee = pvvar(mean(FeeVal, 2), riskFreeRate);
probRuin = calcProbRuin(AccountVal);

dispResults('Vectorized, GPU', cost, fee, probRuin, toc1)

%% 4. Price GMWB III: Vectorized Code, CPU

tic

assetPrice = simAssetPrice_orig(TimeSeries, Period, nYears, nTrials);

[AccountVal, PayoutVal, FeeVal] = calcValuePayoutAndFees_VEC( ...
    Holdings, assetPrice, annualWithdrawalRate, annualFee);

toc1 = toc;

cost = pvvar(mean(PayoutVal, 2), riskFreeRate);
fee = pvvar(mean(FeeVal, 2), riskFreeRate);
probRuin = calcProbRuin(AccountVal);

dispResults('Vectorized, CPU', cost, fee, probRuin, toc1)

%% 5. Price GMWB IV: GPU for RNG, Vectorized CPU for rest

tic

assetPriceG = simAssetPrice_2GPU(TimeSeries, Period, nYears, nTrials);
assetPrice = gather(assetPriceG);

[AccountVal, PayoutVal, FeeVal] = calcValuePayoutAndFees_VEC( ...
    Holdings, assetPrice, annualWithdrawalRate, annualFee);

toc1 = toc;

cost = pvvar(mean(PayoutVal, 2), riskFreeRate);
fee = pvvar(mean(FeeVal, 2), riskFreeRate);
probRuin = calcProbRuin(AccountVal);

dispResults('Best: GPU & CPU', cost, fee, probRuin, toc1)

%% 6. Price GMWB V: CPU only with new RNG and Vectorized code
% This optional section confirms that the GPU + CPU method in the previous
% section is the fastest: Using the GPU to generate random numbers should
% be slightly faster that this (CPU-only) section.

tic

assetPrice = simAssetPrice_2(TimeSeries, Period, nYears, nTrials);

[AccountVal, PayoutVal, FeeVal] = calcValuePayoutAndFees_VEC( ...
    Holdings, assetPrice, annualWithdrawalRate, annualFee);

toc1 = toc;

cost = pvvar(mean(PayoutVal, 2), riskFreeRate);
fee = pvvar(mean(FeeVal, 2), riskFreeRate);
probRuin = calcProbRuin(AccountVal);

dispResults('2nd Best: CPU-only', cost, fee, probRuin, toc1)


function test_failed=test_fbwarped_framebounds
test_failed = 0;
Ls = 44100;
fs = 44100;
fmax = fs/2;
bins = 1;
fac = [1,7/8,3/4,5/8,1/2];

eigstol = 1e-4;
eigsmaxit = 100;

pcgmaxit = 150;
pcgtol = 1e-4;

warpfun = cell(4,1);
invfun = cell(4,1);

% ERBlet warping
 warpfun{3} = @freqtoerb;
 invfun{3} = @erbtofreq;
% constant-Q warping
 warpfun{4} = @(x) 10*log(x);
 invfun{4} = @(x) exp(x/10);
% sqrt-warping
 warpfun{2} = @(x) sign(x).*((1+abs(x)).^(1/2)-1);
 invfun{2} = @(x) sign(x).*((1+abs(x)).^2-1);
% Linear warping
 warpfun{1} = @(x) x/100;
 invfun{1} = @(x) 100*x;

 fmin = [0,0,0,50];

A = zeros(4,length(fac));
B = ones(4,length(fac));
red = A;

for jj = 1:4
    [g,a,fc,L]=warpedfilters(warpfun{jj},invfun{jj},fs,fmin(jj),fmax,bins,Ls,'bwmul',1.5,'fractional','complex');

    gf=filterbankresponse(g,a,Ls); framebound_ratio = max(gf)/min(gf);
    disp(['Painless system frame bound ratio: ', num2str(framebound_ratio)]);

    for kk = 1:length(fac)
        %[jj,kk]
        atemp = a;
        idx = [2:length(fc)/2,length(fc)/2+2:length(fc)];
        atemp(idx,2) = ceil(atemp(idx,2).*fac(kk));
        red(jj,kk) = sum(atemp(:,2)./atemp(:,1));

        [g,asan]=filterbankwin(g,atemp,L,'normal');
        gtemp=comp_filterbank_pre(g,asan,L,10);
        gtemp{1}.H = gtemp{1}.H.*sqrt(fac(kk));
        gtemp{length(fc)/2+1}.H = gtemp{length(fc)/2+1}.H.*sqrt(fac(kk));

        F = frame('filterbank',gtemp,asan,numel(gtemp));
        [A(jj,kk),B(jj,kk)] = framebounds(F,Ls,'tol',eigstol,'pcgtol',pcgtol,'maxit',eigsmaxit,'pcgmaxit',pcgmaxit);

     end
end

disp('This is a ratio B/A. Rows - warping sunction, Cols - redundancy compared to te minimal painless case')
B./A


function [logp, yhat, res] = tapas_condhalluc_obs(r, infStates, ptrans)
% Calculates the log-probability of response y=1 under the unit-square sigmoid model
%
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2015-2016 Christoph Mathys, TNU, UZH & ETHZ
%
% This file is part of the HGF toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

% Transform beta to its native space
be = exp(ptrans(1));

% Initialize returned log-probabilities as NaNs so that NaN is
% returned for all irregualar trials
n = size(infStates,1);
logp = NaN(n,1);
yhat = NaN(n,1);
res  = NaN(n,1);

% Check input format
if size(r.u,2) ~= 2
    error('tapas:hgf:CondHalluc:InputsIncompatible', 'Inputs incompatible with condhalluc_obs observation model. See tapas_condhalluc_obs_config.m.')
end

% Get true-positive rate corresponding to stimuli
tp = r.u(:,2);

% Weed irregular trials out
mu1hat = infStates(:,1,1);
mu1hat(r.irr) = [];
y = r.y(:,1);
y(r.irr) = [];
tp(r.irr) = [];

% Calculate belief x using Bayes' theorem
x = tp.*mu1hat./(tp.*mu1hat + (1-mu1hat).^2);

% Belief is mu1hat in trials where there is no tone
x(find(tp==0)) = mu1hat(find(tp==0));

% Calculate log-probabilities for non-irregular trials
reg = ~ismember(1:n,r.irr);
logp(reg) = -log(1+exp(-be.*(2.*x-1).*(2.*y-1)));
yhat(reg) = x;
res(reg) = (y-x)./sqrt(x.*(1-x));

return;


function e = mgVcyclefracLap1d(A,r,pde,square,h,s,option)

global mA

%% Setting
if ~isfield('option','smootherType')
    smootherType = option.smootherType;
else
    smootherType = 3;
end
if ~isfield('option','smootherstep')
    smoothingstep = option.smoothingstep;
else
    smoothingstep = 3;
end
if ~exist('smootherType','var'), smootherType = 3; end
% mapping parameter
if s == 0.5
    gamma = 1;
else
    gamma = 3/(2*s)+0.1;
end

%% line smoothing
N = length(r);
rold = r;
x0 = square(1); x1 = square(2);
y0 = square(3); y1 = square(4);
nx = (x1-x0)/h+1;  % number of grid points in x-direction
ny = (y1-y0)/h+1;  % number of grid points in x-direction
% 1D vector to 2D matrix
r2d = reshape(r,ny,nx);
e = zeros(N,1);
e2d = reshape(e,ny,nx);
% index for Red-Black smoothing
nodeidx = reshape(1:N,ny,nx);
redidx = 2:2:nx-1;
blackidx = 3:2:nx-2;
rlinear = nodeidx(:,redidx);
blinear = nodeidx(:,blackidx);
for it = 1:smoothingstep
    switch smootherType
        case 0
            e = e + tril(A)\r;
            r = rold - A*e;
            e2d = reshape(e,ny,nx);
        case 1
            for k = 2:nx-1 % only update interiori lines
                % form residual
                idx = (k-1)*ny+1:k*ny;  % the end nodes is included?
                de = A(idx,idx)\r2d(:,k);
                e2d(:,k) = e2d(:,k) + de;
                r2d(:,k) = 0;  % exact solve
                if k<nx-1   % update right column
                    r2d(:,k+1) = r2d(:,k+1) - A(idx+ny,idx)*de;
                end
                if k>2    % update left column
                % for left-to-right ordering, the left r(idx-ny) is zero
                    r2d(:,k-1) = - A(idx-ny,idx)*de;
                end
            end
        case 2 % weighted Jacobi
            for k = 2:nx-1
                % form residual
                idx = (k-1)*ny+1:k*ny;
                de = A(idx,idx)\r(idx);
                e(idx) = e(idx) + 0.25*de;
            end
            r = rold - A*e;
        case 3 % red-black block Gauss-Seidel
            idx = ny+1:2*ny;
            % 1: red lines
            de = A(idx,idx)\r2d(:,redidx);
            e2d(:,redidx) = e2d(:,redidx) + de;
            % update residual
            r2d(:,redidx) = 0;
            r2d(:,blackidx) = r2d(:,blackidx)-reshape(A(blinear,rlinear)*de(:),ny,length(blackidx));
            % previous r2d(:,blackidx) = 0;
            % 2: black lines
            de = A(idx,idx)\r2d(:,blackidx);
            e2d(:,blackidx) = e2d(:,blackidx) + de;
            % update residual
            r2d(:,blackidx) = 0;
            r2d(:,redidx) = -reshape(A(rlinear,blinear)*de(:),ny,length(redidx));
            % previous r2d(:,redidx) = 0;
    end
end

%% Transfer operator
% prolongation and restriction in x-direction
Ix = prolongation1d(log2(nx-1)-1);
Rx = Ix';
% prolongation and restriction in y-direction
nxc = (nx - 1)/2 + 1;
nyc = (ny - 1)/2 + 1;
% geometric quantity
My = ny - 1;
Tyf = ((0:My)'/My).^gamma*(y1-y0) + y0;
hf = diff(Tyf);
Myc = nyc - 1;
Tyc = ((0:Myc)'/Myc).^gamma*(y1-y0) + y0;
hc = diff(Tyc);
jc = 2:nyc-1;  % interiori points in the coarse grid
j = 2*jc-1;  % index of coarse points in the fine grids
alpha = zeros(1,nyc);
beta = zeros(1,nyc);
alpha(jc) = hf(j)./hc(jc);
beta(jc) = hf(j-1)./hc(jc-1);
alpha(1) = 1-beta(2);
jc = 2:(nyc-1);
jf = 2*jc-1;  % index of coarse points in the fine grids
% due to the Neumann boundary condition, 1 is included
ii = [1 jf 2 jf+1 jf-1];
jj = [1 jc 1 jc jc];
ss = [ones(1,nyc-1) alpha(1:nyc-1) beta(2:nyc-1)];
Iy = sparse(ii,jj,ss,ny,nyc);
Ry = Iy';

%% Restriction
% 1D vector to 2D matrix
% r2d = reshape(r,ny,nx);
rc2d = Ry*r2d*Ix;
rc = rc2d(:);

%% Coarse grid correction
% option.solver = 'none';
% [u,eqn] = fracLap1d(square,2*h,pde,option);
level = -log2(h);
Ac = mA{level-1};
fixedNode = [1:nyc (2:nxc-1)*nyc (nxc-1)*nyc+(1:nyc)];
isBdNode = false(length(rc),1);
isBdNode(fixedNode) = true;
freeNode = find(~isBdNode);
if level <= 3
    ec = zeros(length(rc),1);
    ec(freeNode) = Ac(freeNode,freeNode)\rc(freeNode);
else
    ec = mgVcyclefracLap1d(Ac,rc,pde,square,2*h,s,option);
end

%% Prolongation
% 1D vector to 2D matrix
ec2d = reshape(ec,nyc,nxc);
e2d = e2d + Iy*ec2d*Rx;
e = e2d(:);
% update residual when e updated. remember we are solving Ae = rold.
r = rold - A*(e2d(:));
r2d = reshape(r,ny,nx);

%% Post-smoothing
for it = 1:smoothingstep
    switch smootherType
        case 0 % pointwise G-S smoothing
            e = e + triu(A)\r;
            r = rold - A*e;
            e2d = reshape(e,ny,nx);
        case 1
            for k = nx-1:-1:2
                % form residual
                idx = (k-1)*ny+1:k*ny;
                de = A(idx,idx)\r2d(:,k);
                e2d(:,k) = e2d(:,k) + de;
                r2d(:,k) = 0;
                if k < nx-1   % update right column
                % for right-to-left ordering, the right r(idx+ny) is zero
                    r2d(:,k+1) = - A(idx+ny,idx)*de;
                end
                if k>2    % update previous column
                    r2d(:,k-1) = r2d(:,k-1) - A(idx-ny,idx)*de;
                end
            end
        case 2 % weighted Jacobi
            for k = 1:nx
                % form residual
                idx = (k-1)*ny+1:k*ny;
                de = A(idx,idx)\r(idx);
                e(idx) = e(idx) + 0.25*de;
            end
            r = rold - A*e;
        case 3 % red-black block Gauss-Seidel
            idx = ny+1:2*ny;
            % 1: red lines
            de = A(idx,idx)\r2d(:,redidx);
            e2d(:,redidx) = e2d(:,redidx) + de;
            % update residual
            r2d(:,redidx) = 0;
            r2d(:,blackidx) = r2d(:,blackidx)-reshape(A(blinear,rlinear)*de(:),ny,length(blackidx));
            % previous r2d(:,blackidx) = 0;
            % 2: black lines
            de = A(idx,idx)\r2d(:,blackidx);
            e2d(:,blackidx) = e2d(:,blackidx) + de;
            % update residual
            r2d(:,blackidx) = 0;
            r2d(:,redidx) = -reshape(A(rlinear,blinear)*de(:),ny,length(redidx));
            % previous r2d(:,redidx) = 0;
    end
end
e = e2d(:);


function [gal] = oz2gal(oz)
% Convert volume from US liquid ounces to US liquid gallons.
% Chad Greene 2012
gal = oz/128;


function [Vo, Ro, No, V] = generate_syntheticdata(F, N, K, noise_level, rho)
% Function to generate synthetic dataset
%
% This file is part of NMFLibrary.
%
% Created by H.Kasai
%
% Change log:
%
%

%
%     % Vo
%     W = randn(F,K);
%     W = max(W, 0);
%     W = min(W, 1);
%
%     H = randn(K,N);
%     H = max(H, 0);
%     H = min(H, 1);
%
%     Vo = W * H;
%
%     % noise
     No = noise_level*randn(F,N);
%
%     % add outlier
%     [V, Ro] = add_outlier(rho, F, N, Vo);
%
%     % V
%     V = V + No;
%     %V = max(V, 0);
%     %V = min(V,1);

    %
    sigma2 = 1 / sqrt(K);
    HN = makedist('Normal', 'mu', 0, 'sigma', sqrt(sigma2));
    Vo_n = random(HN, F, N);
    Vo = abs(Vo_n) ;
    Vo = min(Vo, 1);

    nu = rho;
    nu_tilda = 0.1;
    I = nu * N;
    card = nu_tilda * F;
    Ro = zeros(F,N);
    if rho > 0
        for i = 1 : N
            n_before = 0;
            if i < I
                for f = 1 : card
                    c = randi(F);
                     Ro(c,i) =  1 + (1+1)*rand(1, 1);
                     n = nnz(Ro(:,i));
                     if n_before == n
                         f = f - 1;
                     end
                     n_before = n;
                end

            end
        end
    end

    % V
    V = Vo + Ro + No;
    %V = max(V, 0);
    %V = min(V,1);

    index = find(V<0);
    V(index) = 0;

end


function C=makeSymbolicStiffnessTensor(opt)

C=sym(zeros([3 3 3 3]));
I=eye(3,3);
II1=dyadicProduct(I,I,1);
II3=dyadicProduct(I,I,3);

for i=1:3;
    for j=1:3;
        for k=1:3;
            for l=1:3;
                cvar=['c',num2str(i),num2str(j),num2str(k),num2str(l)];

                C(i,j,k,l)=sym(cvar);

            end;
        end;
    end;
end;

switch opt
    case 'iso'
        L=(II1+II3)==0;
    case 'transiso'

    case'ortho'

    case'full'
        L=false(size(C));
    case 'empty'
        L=true(size(C));
end
C(L)=0;

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/>.


% This is material illustrating the methods from the book
% Financial Modelling  - Theory, Implementation and Practice with Matlab
% source
% Wiley Finance Series
% ISBN 978-0-470-74489-5
%
% Date: 02.05.2012
%
% Authors:  Joerg Kienitz
%           Daniel Wetterau
%
% Please send comments, suggestions, bugs, code etc. to
% kienitzwetterau_FinModelling@gmx.de
%
% (C) Joerg Kienitz, Daniel Wetterau
%
% Since this piece of code is distributed via the mathworks file-exchange
% it is covered by the BSD license
%
% This code is being provided solely for information and general
% illustrative purposes. The authors will not be responsible for the
% consequences of reliance upon using the code or for numbers produced
% from using the code.

function y = sabrtmax(asabr,b,r,nsabr,f,fbar,eps)
% calclates the maximum time for the sabr approximation formula
% to be valid (see Risk paper by Doust)

    a = asabr / eps;
    n = nsabr / eps;

    zF = f^(1-b)/asabr/(1-b);
    zFbar = fbar.^(1-b)/asabr/(1-b);

    fav = sqrt(f*fbar);
    gamma1 = b./fav;
    gamma2 = b*(b-1)./fav.^2;

    kH = 0.125 * (2*gamma2-gamma1.^2)*a^2.*fav.^(2*b) ...
        + 0.75 * r*n*a*gamma1.*fav.^b ...
        + 0.125*(2-3*r^2)*n^2;

    z = zF - zFbar;
    integral = (f^(1-b)-fbar.^(1-b)) / (1-b);

    xz = 1/nsabr *log((sqrt(1-2*nsabr*r*z+nsabr^2*z.^2)-r+nsabr*z)/(1-r));
    if f==fbar
       y = 12 ./(eps^2*8 * kH);
    else
       y = 12 ./(eps^2*(8 * kH + a^2*(log(f./fbar)./integral .* (z./xz)).^2));
    end
end


function se3mat = VecTose3(V)
% *** CHAPTER 3: RIGID-BODY MOTIONS ***
% Takes a 6-vector (representing a spatial velocity).
% Returns the corresponding 4x4 se(3) matrix.
% Example Input:
%
% clear; clc;
% V = [1; 2; 3; 4; 5; 6];
% se3mat = VecTose3(V)
%
% Output:
% se3mat =
%     0    -3     2     4
%     3     0    -1     5
%    -2     1     0     6
%     0     0     0     0

se3mat = [VecToso3(V(1: 3)), V(4: 6); 0, 0, 0, 0];
end


%[2009]-"Text feature selection using ant colony optimization"

% (9/12/2020)

function ACO = jAntColonyOptimization(feat,label,opts)
% Parameters
tau   = 1;      % pheromone value
eta   = 1;      % heuristic desirability
alpha = 1;      % control pheromone
beta  = 0.1;    % control heuristic
rho   = 0.2;    % pheromone trail decay coefficient

if isfield(opts,'N'), N = opts.N; end
if isfield(opts,'T'), max_Iter = opts.T; end
if isfield(opts,'tau'), tau = opts.tau; end
if isfield(opts,'alpha'), alpha = opts.alpha; end
if isfield(opts,'beta'), beta = opts.beta; end
if isfield(opts,'rho'), rho = opts.rho; end
if isfield(opts,'eta'), eta = opts.eta; end

% Objective function
fun = @jFitnessFunction;
% Number of dimensions
dim = size(feat,2);
% Initial Tau & Eta
tau = tau * ones(dim,dim);
eta = eta * ones(dim,dim);
% Pre
fitG = inf;
fit  = zeros(1,N);

curve = inf;
t = 1;
% Iterations
while t <= max_Iter
	% Reset ant
	X = zeros(N,dim);
	for i = 1:N
    % Random number of features
    num_feat = randi([1,dim]);
    % Ant start with random position
    X(i,1)   = randi([1,dim]);
    k        = [];
    if num_feat > 1
      for d = 2:num_feat
        % Start with previous tour
        k      = [k(1:end), X(i, d-1)];
        % Edge/Probability Selection (2)
        P      = (tau(k(end),:) .^ alpha) .* (eta(k(end),:) .^ beta);
        % Set selected position = 0 probability (2)
        P(k)   = 0;
        % Convert probability (2)
        prob   = P ./ sum(P(:));
        % Roulette Wheel selection
        route  = jRouletteWheelSelection(prob);
        % Store selected position to be next tour
        X(i,d) = route;
      end
    end
  end
  % Binary
  X_bin = zeros(N,dim);
  for i = 1:N
    % Binary form
    ind           = X(i,:);
    ind(ind == 0) = [];
    X_bin(i,ind)  = 1;
  end
  % Fitness
  for i = 1:N
    % Fitness
    fit(i) = fun(feat,label,X_bin(i,:),opts);
    % Global update
    if fit(i) < fitG
      Xgb  = X(i,:);
      fitG = fit(i);
    end
  end
%---// [Pheromone update rule on tauK] //
  tauK = zeros(dim,dim);
  for i = 1:N
    % Update Phromones
    tour = X(i,:);
    tour(tour == 0) = [];
    % Number of features
    len_x = length(tour);
    tour  = [tour(1:end), tour(1)];
    for d = 1:len_x
      % Feature selected on graph
      x = tour(d);
      y = tour(d + 1);
      % Update delta tau k on graph (3)
      tauK(x,y) = tauK(x,y) + (1 / (1 + fit(i)));
    end
  end
%---// [Pheromone update rule on tauG] //
  tauG = zeros(dim,dim);
  tour = Xgb;
  tour(tour == 0) = [];
  % Number of features
  len_g = length(tour);
  tour  = [tour(1:end), tour(1)];
  for d = 1:len_g
    % Feature selected on graph
    x = tour(d);
    y = tour(d + 1);
    % Update delta tau G on graph
    tauG(x,y) = 1 / (1 + fitG);
  end
%---// Evaporate pheromone // (4)
  tau = (1 - rho) * tau + tauK + tauG;
  % Save
  curve(t) = fitG;
  fprintf('\nIteration %d Best (ACO)= %f',t,curve(t))
  t = t + 1;
end
% Select features based on selected index
Sf = Xgb;
Sf(Sf == 0) = [];
sFeat = feat(:,Sf);
% Store results
ACO.sf = Sf;
ACO.ff = sFeat;
ACO.nf = length(Sf);
ACO.c  = curve;
ACO.f  = feat;
ACO.l  = label;
end

%// Roulette Wheel Selection //
function Index = jRouletteWheelSelection(prob)
% Cummulative summation
C = cumsum(prob);
% Random one value, most probability value [0~1]
P = rand();
% Roulette wheel
for i = 1:length(C)
	if C(i) > P
    Index = i;
    break;
  end
end
end


function cMap = imfConsistency(mu, refIdx, consistencyThres)

[s1, s2, s3] = size(mu);
cMap = zeros(s1, s2, s3);
cMap(:,:,refIdx) = ones(s1, s2);

refMu = mu(:,:,refIdx);
N = 256;
for i = 1 : s3
    if i ~= refIdx
          cMu  = imhistmatch(mu(:,:,i), refMu, N);
          diff = abs(cMu - refMu);
          cMap(:,:,i) = diff <= consistencyThres;
    end
end


function [gnodes, gedges] = relativeNeighborhoodGraph(points)
%RELATIVENEIGHBORHOODGRAPH Relative Neighborhood Graph of a set of points
%
%   [NODES, EDGES] = relativeNeighborhoodGraph(POINTS)
%   EDGES = relativeNeighborhoodGraph(POINTS)
%
%   The Relative Neighborhood Graph (RNG) is a subgraph of the Delaunay
%   Triangulation computed from the same set of points. The Gabriel graph
%   and the euclidean minimal spanning tree (EMST) are subgraphs of the
%   RNG.
%
%   Example
%     nodes = rand(100, 2) * 100;
%     edges = relativeNeighborhoodGraph(nodes);
%     figure; drawGraph(nodes, edges);
%
%   See also
%     gabrielGraph, euclideanMST
%

% ------
% Author: David Legland
% e-mail: david.legland@nantes.inra.fr
% Created: 2016-03-02,    using Matlab 8.6.0.267246 (R2015b)
% Copyright 2016 INRA - Cepia Software Platform.

% first compute Delaunay triangulation to reduce further computations
DT = delaunayTriangulation(points);
E = edges(DT);

% compute edge lengths
nEdges = size(E, 1);
edgeLengths = zeros(nEdges, 1);
for i = 1:nEdges
    edgeLengths(i) = distancePoints(points(E(i,1),:), points(E(i,2),:));
end

% identify indices of faces attached to each vertex
vertexFaces = vertexAttachments(DT);

% iterate over edges to check if the should be kept
keepEdge = true(nEdges, 1);
for iEdge = 1:nEdges
    iVertex1 = E(iEdge, 1);
    iVertex2 = E(iEdge, 2);
    vertex1 = points(iVertex1, :);
    vertex2 = points(iVertex2, :);

    % compute indices of faces containing one of the two vertices
    inds = [vertexFaces{iVertex1} vertexFaces{iVertex2}];
    localFaces = DT.ConnectivityList(inds, :);

    % compute indices of vertices is the first neighborhood of the edge
    inds = unique(localFaces);
    inds(ismember(inds, [iVertex1 iVertex2])) = [];

    % compute max of distances to both original vertices
    dists1 = distancePoints(vertex1, points(inds, :));
    dists2 = distancePoints(vertex2, points(inds, :));
    distsMax = max(dists1, dists2);

    % keep edge if all points are outside the "lunule" defined by the edge
    if edgeLengths(iEdge) > min(distsMax)
        keepEdge(iEdge) = false;
    end
end

% filter edges
gedges = E(keepEdge, :);

% format output
gnodes = points;
if nargin == 1
    gnodes = gedges;
end


function Y = LSA(X, nLowVec)

k = nLowVec;

[Y,~,~] = svds(X,k);

end


% Calculate arena coverage (the amount of space an animal has covered during experiment)
%
% Calculates arena coverage.
%
%  USAGE
%   coverage = analyses.arenaCoverage(pos, binWidth, shape, dimensions)
%   pos         Position samples, matrix of size at least Nx2. Format is either [t x] or [t x y].
%   binWidth    Width of horizontal and vertical bins in cm. If only one value is provided, then
%               the same bin width is used in both directions.
%   shape       Arena shape, integer. One of the values of bntConstants.ArenaShape.
%   dimensions  Vector of arena dimensions, the actual number of elements depends on arena shape.
%
%   coverage    Arena coverage, float in range [0..100].
%
function coverage =  arenaCoverage(pos, binWidth, shape, dimensions)
    inp = inputParser;

    checkPosDimensions = @(x) size(x, 2) >= 2;
    checkBinWidth = @(x) helpers.isdvector(x, '>=0') && length(x) <= 2;
    checkShape = @(x) ismember(x, helpers.ArenaShape.allShapes());
    checkDims = @(x) helpers.isdvector(x, '>=0') && (x(1) > 0);

    addRequired(inp, 'pos', checkPosDimensions);
    addRequired(inp, 'binWidth', checkBinWidth);
    addRequired(inp, 'shape', checkShape);
    addRequired(inp, 'dimensions', checkDims);

    parse(inp, pos, binWidth, shape, dimensions);

    t = pos(:, 1);
    x = pos(:, 2);
    if size(pos, 2) > 2
        y = pos(:, 3);
    else
        y = [];
    end

    binWidthX = binWidth(1);
    if length(binWidth) == 1
        binWidthY = binWidthX;
    else
        binWidthY = binWidth(2);
    end

    % filter out points that lie outside arena. This is important for circles
    % because they do not fully cover all the bins.
    if shape == bntConstants.ArenaShape.Circle
        radius = dimensions(1)/2;
        ind = sqrt(x.^2 + y.^2) > radius;
        x(ind) = nan;
        y(ind) = nan;
    end

    limitsX = [-dimensions(1)/2 dimensions(1)/2];
    [xBinned, nBinsX, edgesX] = helpers.bin(x, limitsX, binWidthX);
    nBins = nBinsX;

    if ~isempty(y)
        if length(dimensions) == 1
            if shape == bntConstants.ArenaShape.Track
                yLength = 1;
            else
                yLength = dimensions(1);
            end
        else
            if shape == bntConstants.ArenaShape.Track && dimensions(2) == 0
                yLength = 1;
            else
                yLength = dimensions(2);
            end
        end

        limitsY = [-yLength/2 yLength/2];
        [yBinned, nBinsY, edgesY] = helpers.bin(y, limitsY, binWidthY);
        nBins = [nBinsX nBinsY];
    end

    dt = diff(t);
    dt(end+1) = dt(end);

    if isempty(y)
        occupancy = general.accumulate(xBinned, dt, nBinsX)';
    else
        occupancy = general.accumulate([xBinned yBinned], dt, nBins)';
    end

    switch shape
        case bntConstants.ArenaShape.Circle
            radius = dimensions(1)/2;
            radiusBin = ceil(radius / binWidthX) + 1;

            halfSize = ceil(size(occupancy)/2);
            [rr, cc] = meshgrid(1:nBinsX, 1:nBinsY);

            distMap = sqrt((cc - halfSize(2)).^2 + (rr - halfSize(1)).^2); % each element is the distance
                                                % from the middle of the map to current point
            outerCircle = distMap >= radiusBin;
            distMap(outerCircle) = nan;

            numBins = sum(sum(isfinite(distMap)));
            coverage = (length(find(occupancy > 0)) / numBins) * 100;
        otherwise
            coverage = length(find(occupancy > 0)) / prod(nBins) * 100;
    end
end


function output = F_inner_product(input_layers)

input1 = input_layers{1}.a;
input2 = input_layers{2}.a;

output = sum(input1 .* input2);

end


function dat= proc_subtractMovingAverage(dat, ms, varargin)
%PROC_SUBTRACTMOVINGAVERAGE - Subtract moving average (high-pass) filter
%
%Usage:
% DAT= proc_subtractMovingAverage(DAT, MSEC, <METHOD='causal'>)
%
%Input:
% DAT    - data structure of continuous or epoched data
% MSEC   - length of interval in which the moving average is
%          to be calculated, unit [msec].
% METHOD - 'centered' or 'causal' (default).
%
%Output:
% DAT    - updated data structure

% Author(s): Benjamin Blankertz

misc_checkType(dat, 'STRUCT(x fs)');
misc_checkType(ms, '!DOUBLE[1]');

nSamples = round(ms*dat.fs/1000);
sx= size(dat.x);
xa= procutil_movingAverage(dat.x(:,:), nSamples, varargin{:});
dat.x= dat.x - reshape(xa, sx);


classdef matRad_EUD < DoseObjectives.matRad_DoseObjective
% matRad_EUD Implements a penalized equivalent uniform dose objective
%   See matRad_DoseObjective for interface description
%
% References
%   -
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Copyright 2020 the matRad development team.
%
% This file is part of the matRad project. It is subject to the license
% terms in the LICENSE file found in the top-level directory of this
% distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part
% of the matRad project, including this file, may be copied, modified,
% propagated, or distributed except according to the terms contained in the
% LICENSE file.
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    properties (Constant)
        name = 'EUD';
        parameterNames = {'EUD^{ref}', 'k'};
        parameterTypes = {'dose','numeric'};
    end

    properties
        parameters = {0, 3.5};
        penalty = 1;
    end

    methods
        function obj = matRad_EUD(penalty,eudRef, eudExponent)
            %If we have a struct in first argument
            if nargin == 1 && isstruct(penalty)
                inputStruct = penalty;
                initFromStruct = true;
            else
                initFromStruct = false;
                inputStruct = [];
            end

            %Call Superclass Constructor (for struct initialization)
            obj@DoseObjectives.matRad_DoseObjective(inputStruct);

            %now handle initialization from other parameters
            if ~initFromStruct
                if nargin >= 3 && isscalar(eudExponent)
                    obj.parameters{2} = eudExponent;
                end

                if nargin >= 2 && isscalar(eudRef)
                    obj.parameters{1} = eudRef;
                end

                if nargin >= 1 && isscalar(penalty)
                    obj.penalty = penalty;
                end
            end
        end

        %% Calculates the Objective Function value
        function fDose = computeDoseObjectiveFunction(obj,dose)
            % get exponent for EUD
            k = obj.parameters{2};

            % calculate power sum
            powersum = sum(dose.^k);

            %Calculate objective

            %This check is not needed since dose is always positive
            %if powersum > 0
            fDose = obj.penalty * (nthroot(powersum/numel(dose),k) - obj.parameters{1})^2;
            %end
        end

        %% Calculates the Objective Function gradient
        function fDoseGrad  = computeDoseObjectiveGradient(obj,dose)
            % get exponent for EUD
            k = obj.parameters{2};

            %numerical stability
            dose(dose == 0) = 0.001;

            % calculate power sum
            powersum = sum(dose.^k);

            %This check is not needed since dose is always positive
            %if powersum > 0

            %derivatives = nthroot(1/numel(dose),k) * powersum^((1-k)/k) * (dose.^(k-1));
            fDoseGrad = 2 * obj.penalty * nthroot(1/numel(dose),k) * powersum^((1-k)/k) * (dose.^(k-1)) .* (nthroot(powersum/numel(dose),k) - obj.parameters{1});
            %end
            if any(~isfinite(fDoseGrad)) % check for inf and nan for numerical stability
                error(['EUD computation failed. Reduce exponent to resolve numerical problems.']);
            end
        end
    end

end


function x = vecpostproc(x, a)
% VECPOSTPROC is post-processing of a D-dimensional vector.
%
%   V = vecpostproc(V) outputs L2 normalized vector:
%     V = V ./ L2NORM(V);
%
%   V = vecpostproc(V, A) outputs L2 and power-law normalized vector:
%     V = SIGN(X) .* ABS(X) .^ A;
%     V = V ./ L2NORM(V);
%
% Authors: F. Radenovic, G. Tolias, O. Chum. 2017.

    if ~exist('a'), a = 1; end
    x = replacenan (l2_normalize (powerlaw (x, a)));

function x = l2_normalize(x)
    l = sqrt(sum(x.^2));
    x = bsxfun(@rdivide,x,l);
    x = replacenan(x);

function x = powerlaw (x, a)
	if a == 1, return; end
	x = sign (x) .* abs(x)  .^ a;

function y = replacenan (x, v)
	if ~exist ('v')
	  v = 0;
	end
	y = x;
	y(isnan(x)) = v;


function y = minter_xls(Y,x,z,ta,sc,f,type,d,flax1,flax2)
% PURPOSE: Interface via Excel Link for multivariate temporal disaggregation
% -----------------------------------------------------------------------
% SYNTAX: y = minter_xls(Y,x,z,ta,sc,f,type,d,flax1,flax2);
% -----------------------------------------------------------------------
% INPUT
%           SELECTION OF THE METHOD
%
% Common parameters:
%        ta: type of disaggregation
%            ta=1 ---> sum (flow)
%            ta=2 ---> average (index)
%            ta=3 ---> last element (stock) ---> interpolation
%            ta=4 ---> first element (stock) ---> interpolation
%        sc: number of high frequency data points for each low frequency data point
%            sc= 4 ---> annual to quarterly
%            sc=12 ---> annual to monthly
%            sc= 3 ---> quarterly to monthly
%
% Specific parameters:
%
% ==> Rossi:
%        opMethod = type: preliminary univariate disaggregation = 1
%            = 1 ---> Fernandez
%            = 2 ---> Chow-Lin
%            = 3 ---> Litterman
%        In all cases, estimation is performed by Maximum Likelihood
%
% ==> Denton:
%        d: objective function to be minimized: volatility of ...
%            d=0 ---> levels
%            d=1 ---> first differences
%            d=2 ---> second differences
%
% ==> di Fonzo:
%        type: model for the innovations
%            = 0 ---> white noise
%            = 1 ---> random walk
%
% INPUT DATA:
%         Y : NxM
%         x : nxMM
%         z : nxnz
%
% -----------------------------------------------------------------------
% OUTPUT: y: nxi
%       i=M  brief --> only temporally disaggregated series (all procedures)
%       i=2M detailed --> temporally disaggregated series + standard errors of estimates
%                  Available for Di Fonzo.
% -----------------------------------------------------------------------
% LIBRARY: rossi, denton, difonzo

% written by:
% Ana Abad(*) & Enrique M. Quilis(**)
%   (*) National Statistical Institute
%   (**) Macroeconomic Research Department
%        Ministry of Economy and Competitiveness
%        <enrique.quilis@mineco.es>

% Version 2.2 (January, 2013)

% -----------------------------------------------------------------------
% SELECTION OF THE METHOD

switch flax1
case 1
   % Rossi
   opMethod = type;
   res = rossi(Y,x,z,ta,sc,opMethod,1);
case 2
   % Denton
   op1 = 1; %Additive variant
   res = denton(Y,x,z,ta,sc,d,op1);
case 3
   % di Fonzo
   res = difonzo(Y,x,z,ta,sc,type,f);
end

% -----------------------------------------------------------------------
% SELECTION OF OUTPUT

 switch flax2
     case 0
         % Brief output
         y = res.y;
     case 1
         % Normal output
         switch res.meth
             case {'Multivariate Denton','Multivariate Rossi'}
                 y = res.y;
             case {'Multivariate Di Fonzo'}
                  y   = [res.y res.d_y];
          end
 end