function [samples, logp, diagn] = hmc_nuts(f, theta0, opt)
%HMC_NUTS No-U-Turn Sampler (NUTS)
%
%  Description
%    [SAMPLES, LOGP, DIAGN] = HMC_NUTS(f, theta0, opt)
%    Implements the No-U-Turn Sampler (NUTS), specifically,
%    algorithm 6 from the NUTS paper (Hoffman & Gelman, 2011). Runs
%    opt.Madapt steps of burn-in, during which it adapts the step
%    size parameter epsilon, then starts generating samples to
%    return.
%
%    f(theta) should be a function that returns the log probability its
%    gradient evaluated at theta. I.e., you should be able to call
%    [logp grad] = f(theta).
%
%    opt.epsilon is a step size parameter.
%    opt.M       is the number of samples to generate.
%    opt.Madapt  is the number of steps of burn-in/how long to run
%                the dual averaging algorithm to fit the step size
%                epsilon. Note that there is no need to provide
%                opt.epsilon if doing adaptation.
%    opt.theta0  is a 1-by-D vector with the desired initial setting
%                of the parameters.
%    opt.delta   should be between 0 and 1, and is a target HMC
%                acceptance probability. Defaults to 0.8 if
%                unspecified.
%
%
%    The returned variable "samples" is an (M+Madapt)-by-D matrix
%    of samples generated by NUTS, including burn-in samples.
%
%    Note that when used from gp_mc, opt.M and opt.Madapt are both 0 or
%    1 (hmc_nuts returns only one sample to gp_mc). Number of epsilon
%    adaptations should be set in hmc options structure hmc_opt.nadapt, in
%    gp_mc(... ,'hmc_opt', hmc_opt).
%
%    The returned structure diagn includes step-size vector
%    epsilon, number of rejected samples and dual averaging
%    parameters so its possible to continue adapting step-size
%    parameter.

%      Copyright (c) 2011, Matthew D. Hoffman
%      Copyright (c) 2012, Ville Tolvanen
%      All rights reserved.
%

% Redistribution and use in source and binary forms, with or
% without modification, are permitted provided that the following
% conditions are met:
%
% Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
%
% Redistributions in binary form must reproduce the above copyright
% notice, this list of conditions and the following disclaimer in
% the documentation and/or other materials provided with the
% distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
% CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
% DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
% CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
% SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
% LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
% USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
% AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
% ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.

global nfevals;
nfevals = 0;

if ~isfield(opt, 'delta')
  delta = 0.8;
else
  delta = opt.delta;
end
if ~isfield(opt, 'M')
  M = 1;
else
  M = opt.M;
end
if ~isfield(opt, 'Madapt')
  Madapt = 0;
else
  Madapt = opt.Madapt;
end

diagn.rej = 0;
assert(size(theta0, 1) == 1);

D = length(theta0);
samples = zeros(M+Madapt, D);

[logp grad] = f(theta0);
samples(1, :) = theta0;

% Parameters to the dual averaging algorithm.
gamma = 0.05;
t0 = 10;
kappa = 0.75;
% Initialize dual averaging algorithm.
epsilonbar = 1;
Hbar = 0;

if isfield(opt, 'epsilon') && ~isempty(opt.epsilon)
  epsilon = opt.epsilon(end);

  % Hbar & epsilonbar are needed when doing adaptation of step-length
  if isfield(opt, 'Hbar') && ~isempty(opt.Hbar)
    Hbar = opt.Hbar;
  end
  if isfield(opt, 'epsilonbar') && ~isempty(opt.epsilonbar)
    epsilonbar=opt.epsilonbar;
  else
    epsilonbar=opt.epsilon;
  end
  mu = log(10*opt.epsilon(1));
else
  % Choose a reasonable first epsilon by a simple heuristic.
  epsilon = find_reasonable_epsilon(theta0, grad, logp, f);
  mu = log(10*epsilon);

  opt.epsilon = epsilon;
  opt.epsilonbar = epsilonbar;
  opt.Hbar = Hbar;
end

for m = 2:M+Madapt+1,
%     m
    % Resample momenta.
    r0 = randn(1, D);
    % Joint log-probability of theta and momenta r.
    joint = logp - 0.5 * (r0 * r0');
    % Resample u ~ uniform([0, exp(joint)]).
    % Equivalent to (log(u) - joint) ~ exponential(1).
    logu = joint - exprnd(1);
    % Initialize tree.
    thetaminus = samples(m-1, :);
    thetaplus = samples(m-1, :);
    rminus = r0;
    rplus = r0;
    gradminus = grad;
    gradplus = grad;
    % Initial height j = 0.
    j = 0;
    % If all else fails, the next sample is the previous sample.
    samples(m, :) = samples(m-1, :);
    % Initially the only valid point is the initial point.
    n = 1;
    rej = 0;
    % Main loop---keep going until the criterion s == 0.
    s = 1;
    while (s == 1)
        % Choose a direction. -1=backwards, 1=forwards.
        v = 2*(rand() < 0.5)-1;
        % Double the size of the tree.
        if (v == -1)
            [thetaminus, rminus, gradminus, tmp, tmp, tmp, thetaprime, gradprime, logpprime, nprime, sprime, alpha, nalpha] = ...
                build_tree(thetaminus, rminus, gradminus, logu, v, j, epsilon, f, joint);
        else
            [tmp, tmp, tmp, thetaplus, rplus, gradplus, thetaprime, gradprime, logpprime, nprime, sprime, alpha, nalpha] = ...
                build_tree(thetaplus, rplus, gradplus, logu, v, j, epsilon, f, joint);
        end
        % Use Metropolis-Hastings to decide whether or not to move to a
        % point from the half-tree we just generated.
        if ((sprime == 1) && (rand() < nprime/n))
          samples(m, :) = thetaprime;
          logp = logpprime;
          grad = gradprime;
        else
          rej = rej + 1;
        end
        % Update number of valid points we've seen.
        n = n + nprime;
        % Decide if it's time to stop.
        s = sprime && stop_criterion(thetaminus, thetaplus, rminus, rplus);
        % Increment depth.
        j = j + 1;
    end

    % Do adaptation of epsilon if we're still doing burn-in.
    eta = 1 / (length(opt.epsilon) + t0);
    Hbar = (1 - eta) * Hbar + eta * (delta - alpha / nalpha);
    if (m <= Madapt+1)
        epsilon = exp(mu - sqrt(m-1)/gamma * Hbar);
        eta = (length(opt.epsilon))^-kappa;
        epsilonbar = exp((1 - eta) * log(epsilonbar) + eta * log(epsilon));
    else
        epsilon = epsilonbar;
    end
    opt.epsilon(end+1) = epsilon;
    opt.epsilonbar = epsilonbar;
    opt.Hbar = Hbar;
    diagn.rej = diagn.rej + rej;
end

diagn.opt = opt;
end

function [thetaprime, rprime, gradprime, logpprime] = leapfrog(theta, r, grad, epsilon, f)
rprime = r + 0.5 * epsilon * grad;
thetaprime = theta + epsilon * rprime;
[logpprime, gradprime] = f(thetaprime);
rprime = rprime + 0.5 * epsilon * gradprime;
global nfevals;
nfevals = nfevals + 1;
end

function criterion = stop_criterion(thetaminus, thetaplus, rminus, rplus)
thetavec = thetaplus - thetaminus;
criterion = (thetavec * rminus' >= 0) && (thetavec * rplus' >= 0);
end

% The main recursion.
function [thetaminus, rminus, gradminus, thetaplus, rplus, gradplus, thetaprime, gradprime, logpprime, nprime, sprime, alphaprime, nalphaprime] = ...
                build_tree(theta, r, grad, logu, v, j, epsilon, f, joint0)
if (j == 0)
    % Base case: Take a single leapfrog step in the direction v.
    [thetaprime, rprime, gradprime, logpprime] = leapfrog(theta, r, grad, v*epsilon, f);
    joint = logpprime - 0.5 * (rprime * rprime');
    % Is the new point in the slice?
    nprime = logu < joint;
    % Is the simulation wildly inaccurate?
    sprime = logu - 1000 < joint;
    % Set the return values---minus=plus for all things here, since the
    % "tree" is of depth 0.
    thetaminus = thetaprime;
    thetaplus = thetaprime;
    rminus = rprime;
    rplus = rprime;
    gradminus = gradprime;
    gradplus = gradprime;
    % Compute the acceptance probability.
    alphaprime = min(1, exp(logpprime - 0.5 * (rprime * rprime') - joint0));
    nalphaprime = 1;
else
    % Recursion: Implicitly build the height j-1 left and right subtrees.
    [thetaminus, rminus, gradminus, thetaplus, rplus, gradplus, thetaprime, gradprime, logpprime, nprime, sprime, alphaprime, nalphaprime] = ...
                build_tree(theta, r, grad, logu, v, j-1, epsilon, f, joint0);
    % No need to keep going if the stopping criteria were met in the first
    % subtree.
    if (sprime == 1)
        if (v == -1)
            [thetaminus, rminus, gradminus, tmp, tmp, tmp, thetaprime2, gradprime2, logpprime2, nprime2, sprime2, alphaprime2, nalphaprime2] = ...
                build_tree(thetaminus, rminus, gradminus, logu, v, j-1, epsilon, f, joint0);
        else
            [tmp, tmp, tmp, thetaplus, rplus, gradplus, thetaprime2, gradprime2, logpprime2, nprime2, sprime2, alphaprime2, nalphaprime2] = ...
                build_tree(thetaplus, rplus, gradplus, logu, v, j-1, epsilon, f, joint0);
        end
        % Choose which subtree to propagate a sample up from.
        if (rand() < nprime2 / (nprime + nprime2))
            thetaprime = thetaprime2;
            gradprime = gradprime2;
            logpprime = logpprime2;
        end
        % Update the number of valid points.
        nprime = nprime + nprime2;
        % Update the stopping criterion.
        sprime = sprime && sprime2 && stop_criterion(thetaminus, thetaplus, rminus, rplus);
        % Update the acceptance probability statistics.
        alphaprime = alphaprime + alphaprime2;
        nalphaprime = nalphaprime + nalphaprime2;
    end
end
end

function epsilon = find_reasonable_epsilon(theta0, grad0, logp0, f)
epsilon = 0.1;
r0 = randn(1, length(theta0));
% Figure out what direction we should be moving epsilon.
[tmp, rprime, tmp, logpprime] = leapfrog(theta0, r0, grad0, epsilon, f);
acceptprob = exp(logpprime - logp0 - 0.5 * (rprime * rprime' - r0 * r0'));

% Here we presume that energy function returns NaN, if energy cannot be
% evaluated at the suggested hyperparameters so that we need smalled epsilon
if isnan(acceptprob)
  acceptprob=0;
end
a = 2 * (acceptprob > 0.5) - 1;
% Keep moving epsilon in that direction until acceptprob crosses 0.5.
while (acceptprob^a > 2^(-a))
    epsilon = epsilon * 2^a;
    [tmp, rprime, tmp, logpprime] = leapfrog(theta0, r0, grad0, epsilon, f);
    acceptprob = exp(logpprime - logp0 - 0.5 * (rprime * rprime' - r0 * r0'));
end
end


function [groups, orphans, R, C] = connectedComponents(model, type, figures, files)
% Assuming two reactions are connected if they share metabolites, calculates the connected components
% in the stoichiometric matrix, that is, the sets of reactions that share a set of metabolites
%
% USAGE:
%
%    [groups, orphans, R, C] = connectedComponents(model, type, figures)
%
% INPUT:
%    model:
%
% OPTIONAL INPUTS:
%    type:       {('allComponents'), 'largestComponent'}
%    figures:    Will generate plots of the grouping algorithm as it creates block diagonal
%                groups in from top left to bottom right in `W`.
%    files:      Indicator, whether several files containing indicator
%                matrices are generated.
% OUTPUTS:
%    groups:     a structure array (the number of distinct groups is length(groups)) with fields:
%
%                  * `groups(i).num_els` - number of reactions in group `i`.
%                  * `groups(i).block` - sub-block identity of group `i`.
%                  * `groups(i).elements` - reactions of W that are in group `i`.
%                  * `groups(i).degrees` - degrees of connection for each reaction in group `i`.
%    orphans:    elements of W that were not in any group, becasue they did not meet the constraints.
%    R:          reaction adjacency
%    C:          compound adjacency
%
% All components require:
% Connected Component Analysis on an Undirected Graph by Tristan Ursell
% http://www.mathworks.com/matlabcentral/fileexchange/35442-connected-component-analysis-on-an-undirected-graph.
%
% Largest component requires:
% gaimc : Graph Algorithms In Matlab Code by David Gleich
% http://www.mathworks.com/matlabcentral/fileexchange/24134-gaimc-graph-algorithms-in-matlab-code.
%
%  .. Author:
%        - Ronan Fleming, 2012
%        - Thomas Pfau May 2017, Speedup and addition of files indicator

if ~exist('type','var')
    type='allComponents';
end
if ~exist('figures','var')
    figures=0;
end
if ~exist('files','var')
    files=0;
end

model=findSExRxnInd(model);

%stoichiometric matrix
S=model.S;
%dont include exchange reactions
S(:,~model.SIntRxnBool)=0;

[m,n]=size(S);

%binary form
B=sparse(m,n);
B(S~=0)=1;

%Compound adjacency
C1=B*B';

%number of reactions a species participates in
nReactionsSpeciesParticipatesIn=diag(C1,0);

%take out connections by cofactors
[nReactionsSpeciesParticipatesInSorted,IX] = sort(nReactionsSpeciesParticipatesIn,'descend');
%model.mets(IX(1:80))

% %omit reactions connected by cofactors
% omitMet=false(m,1);
% for i=1:m
%     metAbbr=model.mets{i};
%     if strcmp(metAbbr(1:2),'h[')
%         omitMet(i)=1;
%         continue;
%     end
%     if strcmp(metAbbr(1:3),'k[')
%         omitMet(i)=1;
%         continue;
%     end
%     if length(metAbbr)>3
%         if strcmp(metAbbr(1:3),'pi[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:3),'cl[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:3),'o2[')
%             omitMet(i)=1;
%             continue;
%         end
%     end
%
%     if length(metAbbr)>4
%         if strcmp(metAbbr(1:4),'na1[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'h2o[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'co2[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'atp[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'adp[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'utp[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'gtp[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'gdp[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'amp[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'nad[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'fad[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'coa[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'ppi[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'nh4[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'ACP[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'thf[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:4),'crn[')
%             omitMet(i)=1;
%             continue;
%         end
%     end
%
%     if length(metAbbr)>5
%         if strcmp(metAbbr(1:5),'nadh[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:5),'fadh[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:5),'nadp[')
%             omitMet(i)=1;
%             continue;
%         end
%     end
%
%     if length(metAbbr)>6
%         if strcmp(metAbbr(1:6),'nadph[')
%             omitMet(i)=1;
%             continue;
%         end
%         if strcmp(metAbbr(1:6),'accoa[')
%             omitMet(i)=1;
%             continue;
%         end
%     end
%
% end
%
% %omit these metabolites
% B(omitMet,:)=0;

%Reaction adjacency
R1=B'*B;

%number of species in a reaction
nMolecularSpeciesInReaction=diag(R1,0);

R=R1;
%Set the diagonal to 0
R(logical(eye(size(R1,1)))) = 0;

if files
    R2=triu(R);
    fid=fopen('reactionAdjacencyOtherThanCofactors.txt','w');
    for j=1:n
        fprintf(fid,'%s\t',model.rxns{j});
    end
    fprintf(fid,'\n');
    for j=1:n
        fprintf(fid,'%s\t',model.rxns{j});
        for k=1:n
            fprintf(fid,'%u\t',full(R2(j,k)));
        end
        fprintf(fid,'\n');
    end
    fclose(fid);
end

C=C1;
%Set the diagonal to 0
C(logical(eye(size(C1,1)))) = 0;

if strcmp(type,'largestComponent')
    if ~exist('largest_component')
        error('Install gamic and add it to your path. (http://www.mathworks.com/matlabcentral/fileexchange/24134-gaimc-graph-algorithms-in-matlab-code)')
    end
    [Acc,p] = largest_component(R);
    degree=sum(Acc);
    groups(1).num_els=nnz(degree);
    groups(1).block='largest';
    groups(1).elements=find(p);
    groups(1).degrees=degree;
    orphans=[];
else
    if figures==1
        [groups,orphans]=graph_analysis(R,'plot',1);
    else
        [groups,orphans]=graph_analysis(R);
    end

end

if files
    fid=fopen('reactionsNotConnectedByAnything.txt','w');
    bool=model.SIntRxnBool;
    bool(groups.elements) = 0;
    for j=1:n
        if bool(j)
            fprintf(fid,'%s\n',model.rxns{j});
        end
    end
    fclose(fid);
end


function hf_out = lhs_operation_gpu(hf, samplesf, reg_filter, sample_weights)

% This is the left-hand-side operation in Conjugate Gradient

% Get sizes
num_features = length(hf);
filter_sz = zeros(num_features,2);
for k = 1:num_features
    filter_sz(k,:) = [size(hf{k},1), size(hf{k},2)];
end
[~, k1] = max(filter_sz(:,1));  % Index for the feature block with the largest spatial size
block_inds = 1:num_features;
block_inds(k1) = [];
output_sz = [size(hf{k1},1), 2*size(hf{k1},2)-1];

% Compute the operation corresponding to the data term in the optimization
% (blockwise matrix multiplications)
%implements: A' diag(sample_weights) A f

% sum over all features and feature blocks
sh = sum(bsxfun(@times, samplesf{k1}, hf{k1}), 3);    % assumes the feature with the highest resolution is first
pad_sz = cell(1,1,num_features);
for k = block_inds
    pad_sz{k} = (output_sz - [size(hf{k},1), 2*size(hf{k},2)-1]) / 2;

    sh(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end,1,:) = ...
        sh(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end,1,:) + sum(bsxfun(@times, samplesf{k}, hf{k}), 3);
end

% weight all the samples and take conjugate
sh = conj(bsxfun(@times,sample_weights,sh));

% multiply with the transpose
hf_out = cell(1,1,num_features);
hf_out{k1} = conj(sum(bsxfun(@times, sh, samplesf{k1}), 4));
for k = block_inds
    hf_out{k} = conj(sum(bsxfun(@times, sh(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end,1,:), samplesf{k}), 4));
end

% compute the operation corresponding to the regularization term (convolve
% each feature dimension with the DFT of w, and the tramsposed operation)
% add the regularization part
% hf_conv = cell(1,1,num_features);
for k = 1:num_features
    reg_pad = min(size(reg_filter{k},2)-1, size(hf{k},2)-1);

    % add part needed for convolution
    hf_conv = cat(2, hf{k}, conj(rot90(hf{k}(:, end-reg_pad:end-1, :), 2)));

    % do first convolution
    hf_conv = convn(hf_conv, reg_filter{k});

    % do final convolution and put toghether result
    hf_out{k} = hf_out{k} + convn(hf_conv(:,1:end-reg_pad,:), reg_filter{k}, 'valid');
end

end


 function inv1 = de_ftab_inv1(fit, s1, varargin)
%function inv1 = de_ftab_inv1(fit, s1, [options])
%|
%| Build object that does 1D inverse of BH function for 1st material component,
%| (usually water), for conventional "water only" beam-hardening correction.
%|
%| in
%|	fit	strum	initialized by de_ftab_fit()
%|	s1	[N]	s_1 sample values for building table (ftab.sls.sl{1})
%|
%| option
%|	'll'	1	which component (default: 1)
%|	'type'	char	'interp' cubic interpolation (default)
%|			'exp'	log(exp()) form - under development
%|	'show'	0|1	plot it?
%|
%| out
%|	inv1	strum
%|	methods:
%|		inv1.fun(hf1)	map log values into corrected values
%|			(corresponding to line-integral of material density)
%|		inv1.plot(fit)	show fit
%|
%| Copyright 2008-09-28, Jeff Fessler, University of Michigan

if nargin < 1, ir_usage, end
if nargin == 1 && streq(fit, 'test'), de_ftab_inv1_test, return, end

arg.show = false;
arg.type = 'interp'; % cubic interpolation
arg.ll = 1; % which material, one of {1, ..., LL}
arg = vararg_pair(arg, varargin);

% although we need only the 1D array of s1 values,
% fit.fmfun requires a [n1 1 LL] array.  here the other components are zero.
LL = fit.LL; % usually 1 anyway
sll = s1; sll(1,1,LL) = 0; % [n1 1 L]

% evaluate nonlinear BH function for each of the M spectra
f1 = fit.fmfun(sll); % [n1 1 M]
%f1 = squeeze(f1(:,1,:)); % [n1 M] % changed 2008-12-19
f1 = squeeze(f1); % [n1 M]

st.s1 = s1;
st.f1 = f1;

switch arg.type
case 'interp'
	inv1_fun = @de_ftab_inv1_interp;
case 'exp'
	st = de_ftab_inv1_exp_init(st, fit, arg);
	inv1_fun = @de_ftab_inv1_exp_eval;
otherwise
	fail('unknown type %s', arg.type)
end

meth = {'fun', inv1_fun, '(fh1 [N M]) -> [N M]';
	'plot', @de_ftab_inv1_plot, '(fit)'};

inv1 = strum(st, meth);

if arg.show && im
	inv1.plot(fit);
end

% de_ftab_inv1_exp_init()
function st = de_ftab_inv1_exp_init(st, fit, arg);

s1 = st.s1;
f1 = st.f1;

arg.fit0 = true; % todo
arg.fit0 = false;
arg.chat = true;
arg.thresh = 1e-16;
arg.nexp = 91;

y = exp(s1);
wt = ones(size(y)); % todo
Wh = spdiag(wt, 'nowarn');

MM = size(f1,2);
for mm=1:MM
	f_coef = fit.coef{mm};
	f_exp = fit.mac{mm}(:,1); % for ll=1 only
	emin = 1 / max(f_exp);
	emax = 1 / min(f_exp);
	inv_exp = linspace(emin, emax, arg.nexp)'; % [Ne 1] candidate exps
	Ab = exp(f1(:,mm) * inv_exp'); % [*Ns Ne] "over-complete" basis

	% initial coefficients for each candidate exponent
	if arg.fit0
		fder0 = fit.mac_eff(mm,1);
		inv_der0 = 1 / fder0;
		warg = {'inprodv', inv_exp' / inv_der0};
	else
		warg = {};
	end
	x = wls_simplex(Ab, y(:), Wh, [], warg{:}); % [Ne 1]

	if 1 % reduce to fewer essential terms
		ie = x > arg.thresh; % find key energies
		if arg.chat
			printm('%d coefficients of %d for m=%d', ...
				sum(ie), length(ie), mm)
		end
		inv_exp = inv_exp(ie);

		% final coefficients at key exponents
		if arg.fit0
			fder0 = fit.mac_eff(mm,1);
			inv_der0 = 1 / fder0;
			warg = {'inprodv', inv_exp' / inv_der0}; % shorter now
		else
			warg = {};
		end
		A = Ab(:,ie); % [*Ns Ne] final basis
		x = wls_simplex(A, y(:), Wh, [], warg{:}); % [Ne 1]
	end

	st.exp.coef{mm} = x; % [Ne 1]
	st.exp.exp{mm} = inv_exp;
end

% de_ftab_inv1_exp_eval()
function s1hat = de_ftab_inv1_exp_eval(st, fh1)

MM = size(st.f1,2);
dim = size(fh1);
fh1 = reshapee(fh1, [], MM); % [N M]
s1hat = zeros(size(fh1), 'single');
for mm=1:MM
	tmp = exp(fh1(:,mm) * st.exp.exp{mm}'); % [*N Ne]
	s1hat(:,mm) = log(tmp * st.exp.coef{mm}); % [*N 1]
end
s1hat = reshape(s1hat, dim);

warn 'untested'

% de_ftab_inv1_interp()
% inverse based on interpolation
function s1hat = de_ftab_inv1_interp(st, fh1)

s1 = st.s1;
f1 = st.f1;

MM = size(f1,2);
dim = size(fh1);
fh1 = reshapee(fh1, [], MM);
s1hat = zeros(size(fh1), 'single');
for mm=1:MM
	s1hat(:,mm) = interp1(f1(:,mm), s1, fh1(:,mm), 'pchip', 'extrap');
end
s1hat = reshape(s1hat, dim);

% de_ftab_inv1_plot()
function out = de_ftab_inv1_plot(st, fit)

if nargin ~= 2, fail 'need "fit" argument', end

s1 = st.s1;

s4 = max(s1);
s4 = linspace(-0.0*s4, 1.0*s4, 4*length(s1)+1)'; % [n4] fine sampling
LL = fit.LL;
MM = fit.MM;
sll = s4; sll(1,1,LL) = 0; % [n4 1 L]

f4 = fit.fmfun(sll); % [n4 1 M]
%f4 = squeeze(f4(:,1,:)); % [n4 M]
f4 = squeeze(f4); % [n4 M]

s4i = st.fun(f4); % [n4 M] one correction for each spectrum
err = s4i - repmat(s4, [1 MM]); % [n4 M]

clf, pl = @(n,m) subplot(200 + MM*10 + (n-1)*MM + m);
for mm=1:MM
	pl(1,mm)
	plot(s4, f4(:,mm), 'c-', s4i(:,mm), f4(:,mm), 'y:', ...
		s4, s4 * fit.mac_eff(mm), '--') % monenergetic line
	ir_legend({'true (fine)', 'fit', 'mono'})
	m = num2str(mm);
	axis tight, xlabel 's1', ylabel(['f' m]), title(['inv1 fit m=' m])

	pl(2,mm)
	plot(s4, err(:,mm), '.-')
	axis tight, xlabel 's1', ylabel(['err' m]), title 'inv1 error'
end
prompt

if nargout, out = []; end

% de_ftab_inv1_test()
function de_ftab_inv1_test
stype = 'ps1';
mtype = {'water', 'bone'};
xrs = xray_read_spectra(stype);
mas = xray_read_mac(mtype);
sls = de_ftab_sls;
fm = de_ftab_fm(sls.sll, mas.mac(xrs.en), xrs.Ide);
sl = sls.sl;
fit = de_ftab_fit(sl, fm, 'type', 'exp', 'mtype', mtype, 'show', 0);
itypes = {'exp', 'interp'};
for ii=1:length(itypes)
	itype = itypes{ii};
	inv1 = de_ftab_inv1(fit, sl{1}, 'type', itype);
%	inv1.fun([0 0])
	if im, inv1.plot(fit); end
end


function [ candidates, scores ] = sample_bing_windows( im, num_samples)
%SAMPLE_BING_WINDOWS Will generate equaly distributed windows in space,
%following Bing sizes
%   Bing uses 29 specific sizes, this method spread this sizes homogenously
%   inside the image
scores = [];
im_wh = [size(im, 2), size(im, 1)];

original_bing_window_sizes = [[512 512 ]; [256, 512 ]; [128, 512 ]; [64, 512 ]; ...
    [512, 256 ]; [256, 256 ]; [128, 256 ]; [64, 256 ]; [32, 256 ]; ...
    [512, 128 ]; [256, 128 ]; [128, 128 ]; [64, 128 ]; [32, 128 ]; [16, 128 ]; ...
    [512, 64 ]; [256, 64 ]; [128, 64 ]; [64, 64 ]; [32, 64 ]; [16, 64 ]; ...
    [128, 32 ]; [64, 32 ]; [32, 32 ]; [16, 32 ];  ...
    [64, 16 ]; [32, 16 ]; [16, 16 ]];

%original_bing_window_sizes = [[64, 128]; [32, 128 ]];

original_num_window_sizes = size(original_bing_window_sizes, 1);

bing_window_sizes = [];

% we filter window sizes to fit inside the image
for i=1:size(original_bing_window_sizes, 1),
    window_wh = original_bing_window_sizes(i, :);

    if(sum(window_wh < im_wh) == 2),
        bing_window_sizes = [bing_window_sizes; window_wh];
    else
        % the window is disregarded
    end

end

num_window_sizes = size(bing_window_sizes, 1);

assert(num_samples > num_window_sizes);

candidates = [];
if num_window_sizes ~= original_num_window_sizes,
    % we add one candidate that covers the whole image size
   candidates =  [0, 0, im_wh];
end

use_v0 = false;

if use_v0,
    % will have as many splits in x and y axis (non-square strides)

    sqrt_num_samples_size = floor(sqrt(num_samples / num_window_sizes));
    samples_per_size = sqrt_num_samples_size * sqrt_num_samples_size;
    assert(samples_per_size > 3);
    extra_samples = num_samples - (samples_per_size * num_window_sizes) - size(candidates, 1);
    delta_samples = ((sqrt_num_samples_size + 1) * (sqrt_num_samples_size + 1)) - samples_per_size;

    divisions_per_size = repmat(sqrt_num_samples_size, 1, num_window_sizes);

    start_extra_size_index = 6; % because we like 256x256 (and smaller)
    for i = start_extra_size_index:num_window_sizes,
        if extra_samples > delta_samples,
            divisions_per_size(i) = divisions_per_size(i) + 1;
            extra_samples = extra_samples - delta_samples;
        else
            fprintf('Added %i extra sizes\n', i - 1);
            break;
        end
    end

    for i = 1:num_window_sizes,

        num_divisions = divisions_per_size(i);
        window_wh = bing_window_sizes(i, :);
        x1 = 1;
        y1 = 1;
        x2 = im_wh(1) - window_wh(1);
        y2 = im_wh(2) - window_wh(2);

        assert(x2 > 1);
        assert(y2 > 1);

        [xx, yy] = meshgrid(linspace(x1, x2, num_divisions), ...
            linspace(y1, y2, num_divisions));
        top_left_xy = [xx(:) yy(:)];
        for j = 1:size(top_left_xy, 1),
            xy = top_left_xy(j, :);
            window = [xy, xy + window_wh];
            candidates = [candidates; window];
        end

    end

else
    % v1
    % will use square strides

    num_samples_per_size = floor(num_samples / num_window_sizes);

    stride_per_size = zeros(1, num_window_sizes);
    total_placed_samples = size(candidates, 1);
    for i = 1:num_window_sizes,

        window_wh = bing_window_sizes(i, :);
        x2 = im_wh(1) - window_wh(1);
        y2 = im_wh(2) - window_wh(2);

        assert(x2 > 0);
        assert(y2 > 0);

        block_area = (x2 * y2) / num_samples_per_size;
        stride = sqrt(block_area);
        assert(stride > 0);

        num_samples_placed = compute_num_samples_placed(im_wh, window_wh, stride);

        while(num_samples_placed > num_samples_per_size)
            stride = stride + 1; % larger stride, less placements
            num_samples_placed = compute_num_samples_placed(im_wh, window_wh, stride);
        end

        assert(num_samples_placed <= num_samples_per_size);

        total_placed_samples = total_placed_samples + num_samples_placed;
        assert(total_placed_samples <= num_samples);

        stride_per_size(i) = stride;
    end

    assert(total_placed_samples <= num_samples);

    sqrt_num_samples_size = floor(sqrt(num_samples / num_window_sizes));
    samples_per_size = sqrt_num_samples_size * sqrt_num_samples_size;
%     assert(samples_per_size > 3);
    assert(samples_per_size > 0);
    extra_samples = num_samples - total_placed_samples;
    assert(extra_samples >= 0);

    start_extra_size_index = 6; % because we like 256x256 (and smaller)
    for i = start_extra_size_index:num_window_sizes,

        window_wh = bing_window_sizes(i, :);
        stride = stride_per_size(i);

        num_samples_placed = compute_num_samples_placed(im_wh, window_wh, stride);

        new_stride = stride * 0.75;
        %new_stride = stride - 1;
        new_num_samples_placed = compute_num_samples_placed(im_wh, window_wh, new_stride);

        delta_samples = new_num_samples_placed - num_samples_placed;

        if extra_samples > delta_samples,
            stride_per_size(i) = new_stride;
            total_placed_samples = total_placed_samples + delta_samples;
            extra_samples = extra_samples - delta_samples;
        else
            fprintf('Added %i extra sizes\n', i - start_extra_size_index);
            break;
        end
    end

    if extra_samples > 0,
        fprintf('%i extra_samples remaining\n', extra_samples);
    end

    for i = 1:num_window_sizes,

        window_wh = bing_window_sizes(i, :);
        stride = stride_per_size(i);
        x1 = 1;
        y1 = 1;
        x2 = im_wh(1) - window_wh(1);
        y2 = im_wh(2) - window_wh(2);

        x_dots = x1 + (mod(x2 - x1, stride) / 2): stride : x2;
        y_dots = y1 + (mod(y2 - y1, stride) / 2): stride : y2;

        assert(x2 > 0);
        assert(y2 > 0);

        [xx, yy] = meshgrid(x_dots, y_dots);
        top_left_xy = [xx(:) yy(:)];
        for j = 1:size(top_left_xy, 1),
            xy = top_left_xy(j, :);
            window = [xy, xy + window_wh];
            candidates = [candidates; window];
        end

    end

    assert(size(candidates, 1) == total_placed_samples);
end

assert(size(candidates, 1) <= num_samples);
end

function [ret] = compute_num_samples_placed(im_wh, window_wh, stride)
x1 = 1;
y1 = 1;
x2 = im_wh(1) - window_wh(1);
y2 = im_wh(2) - window_wh(2);

x_dots = x1 + (mod(x2 - x1, stride) / 2): stride : x2;
y_dots = y1 + (mod(y2 - y1, stride) / 2): stride : y2;
num_samples_placed = size(x_dots, 2) * size(y_dots, 2);
ret = num_samples_placed;
end


function opts = getdata(dataformat)

for i = 1:200
  imshow(reshape(images(:,i),144,176),[]);
  pause(0.1);
end

if strcmp(dataformat,'surveillance-video-Hall')
    load Hall_airport_1000_1496_497_144_176_gray.mat;
    D = images(:,1:200); [n1,n2] = size(images); % imn1 = 144; imn2 = 176;
    opts.D = D; opts.mu = norm(D)/1.25;
    Xs = D; Ys = D;

elseif strcmp(dataformat,'surveillance-video-Campus-color')
%     load Campus_trees_1000_1993_994_128_160_gray.mat;
    load Campus_trees_1000_1996_997_128_160_R.mat; DR = images(:,181:500);
    load Campus_trees_1000_1995_996_128_160_G.mat; DG = images(:,181:500);
    load Campus_trees_1000_1994_995_128_160_B.mat; DB = images(:,181:500);
    D = [DR, DG, DB];
    [n1,n2] = size(D); % imn1 = 128; imn2 = 160;
    opts.D = D; opts.mu = norm(D)/1.25;
    Xs = D; Ys = D;
end

opts.Xs = Xs;  opts.Ys = Ys;
opts.n1 = n1; opts.n2 = n2;
opts.sigma = 1e-6; opts.maxitr = 500; opts.rho = 1/sqrt(n1);
opts.eta_mu = 2/3; opts.eta_sigma = 2/3;
opts.muf = 1e-6;
opts.sigmaf = 1e-6;
opts.epsilon = 1e-7;
opts.sv = 100;


function a = sqrt(a)
%SQRT         Gradient square root sqrt(a)
%

% written  10/16/98     S.M. Rump
% modified 10/14/00     S.M. Rump  use Tony's trick
% modified 04/04/04     S.M. Rump  set round to nearest for safety
%                                    accelaration for sparse input
% modified 04/06/05     S.M. Rump  rounding unchanged
% modified 09/28/08     S.M. Rump  check for rounding to nearest improved
% modified 10/08/08     S.M. Rump  improved sparse multiplication: not using intval data type
% modified 08/26/12     S.M. Rump  global variables removed
%

  e = 1e-30;
  if 1+e==1-e                           % fast check for rounding to nearest
    rndold = 0;
  else
    rndold = getround;
    setround(0)
  end

  N = getappdata(0,'INTLAB_GRADIENT_NUMVAR');

  wng = warning;
  warning off

  a.x = sqrt(a.x);
  % use full(a.x(:)): cures Matlab V6.0 bug
  % a=7; i=[1 1]; x=a(i), b=sparse(a); y=b(i)  yields row vector x but column vector y
  % ax is full anyway
  ax = 1./(2*full(a.x(:)));
  if issparse(a.dx)
    sizeax = size(a.dx,1);
    [ia,ja,sa] = find(a.dx);
    if isa(a.x,'intval')
      adx = times(ax(ia),sa,0);
      if adx.complex
        a.dx = intval( sparse(ia,ja,adx.mid,sizeax,N) , sparse(ia,ja,adx.rad,sizeax,N) , 'midrad' );
      else
        a.dx = intval( sparse(ia,ja,adx.inf,sizeax,N) , sparse(ia,ja,adx.sup,sizeax,N) , 'infsup' );
      end
    else
      a.dx = sparse(ia,ja,ax(ia).*sa,sizeax,N);
    end
  else
    a.dx = a.dx .* ax(:,ones(1,N));
  end

  warning(wng)

  if rndold
    setround(rndold)
  end


% Estimate spatial covariance matrix for sentences using a mask. The mask
% specifies speech presense probability at all time frequency locations,
% with a 1 means speech present and 0 means speech absent.
%
function curr_layer = F_MVDR_spatialCov(input_layer, curr_layer)
input = input_layer.a;
fs = curr_layer.fs;
freqBin = curr_layer.freqBin;
nFreqBin = length(freqBin);

[D,T,N] = size(input);
if isfield(curr_layer, 'noiseCovL2')
    noiseCovL2 = curr_layer.noiseCovL2;
else
    noiseCovL2 = 0;  % add noiseCovRegularization*\lambda*I to noise covariance, where \lambda is the maximum eigenvalue
end

D = D/2;
speechCov = input(1:D,:,:,:);
noiseCov = input(D+1:end,:,:,:);

dimTmp = size(speechCov,1) / nFreqBin;
nCh = sqrt(dimTmp);

speechCov = reshape(speechCov, nCh, nCh, nFreqBin, T, N);
noiseCov = reshape(noiseCov, nCh, nCh, nFreqBin, T, N);

speechCov_cell = num2cell(speechCov, [1 2]);       % convert to cell array and call cellfun for speed
noiseCov_cell = num2cell(noiseCov, [1 2]);

% add regularization
if noiseCovL2 > 0
    eig_val = cellfun(@GetEigVal, noiseCov_cell, 'UniformOutput', 0);
    eig_val = cell2mat(eig_val);
    noise_floor = eig_val(end,:,:,:,:) * noiseCovL2;
    noise_floor(:) = 100;
    % because our noise floor depends on noise covariance and network
    % parameters, it will not be able to pass through gradient check. This
    % is because we didn't consider this dependancy in the backpropagation.
    % But this should not have much effect on the training.
    noise_floor_cell = num2cell(noise_floor, 1);
    noiseCov_cell = cellfun(@DiagLoading, noiseCov_cell, noise_floor_cell, 'UniformOutput', 0);
end

ninv_x = cellfun(@(x,n) (inv( n )*x), speechCov_cell, noiseCov_cell, 'UniformOutput', 0);
lambda = cellfun(@(x) abs(trace(x)), ninv_x, 'UniformOutput', 0);
if 0    % only lambda
    weight = cellfun(@(x,y) ones(size(x,1),1)/y, ninv_x, lambda, 'UniformOutput', 0);
elseif 0    % no lambda
    weight = cellfun(@(x) x(:,1), ninv_x, 'UniformOutput', 0);
else
    weight = cellfun(@(x,y) x(:,1)/y, ninv_x, lambda, 'UniformOutput', 0);
end
output = cell2mat(weight);
output = permute(output, [3 1 2 4 5]);
output = reshape(output, nFreqBin*nCh, T, N);

curr_layer.a = output;
curr_layer.lambda = lambda;
curr_layer.phi_s = speechCov_cell;
curr_layer.phi_n = noiseCov_cell;
if noiseCovL2>0
    curr_layer.noise_floor = noise_floor_cell;
end
end

%%
function ev = GetEigVal(A)
[~,V] = eig(A);
ev = diag(V);
end

function B = DiagLoading(A, alpha)
D = size(A,1);
B = A + alpha * eye(D);
end


function [irf_record_allt,favar]=tvbvarirf2(beta_gibbs,D_record,It,Bu,IRFperiods,n,m,p,k,T,favar)

% Favar preliminaries
if favar.FAVAR==1
    signresX_index=[];
    npltX=favar.npltX;
    if npltX>0
        favar_FAVAR=1;
        plotX_index=favar.plotX_index;
    else
        favar_FAVAR=0;
        plotX_index=[];
    end
    %relevant loadings
    relLindex=[signresX_index;plotX_index];
    % reshape the L gibbs draws
    Lgibbs=reshape(favar.L_gibbs,size(favar.L,1),size(favar.L,2),It-Bu);
    Lgibbs=Lgibbs(relLindex,:,:);
else
    npltX=0;
    favar_FAVAR=0;
    Lgibbs=NaN;
end

% create the cell aray that will store the values from the simulations
irf_record_allt=cell(n,n);
favar.IRF.favar_irf_record_allt=cell(npltX,n);

% loop over sample periods
for tt=1:T
    % loop over iterations
    for jj=1:It-Bu
        % draw beta
        beta=beta_gibbs{tt}(:,jj);
        D=reshape(D_record(:,It-Bu),n,n);
        if favar_FAVAR==1
            Lg=squeeze(Lgibbs(:,:,It-Bu)); % this is different for IRFt4, we need to record the index there and adjust the case
        end
        [~,ortirfmatrix]=bear.irfsim(beta,D,n,m,p,k,IRFperiods);

        % if we have FAVAR restrictions we scale the ortirfmatrix from the previous step
            if favar_FAVAR==1
                favar_ortirfmatrix=[];
                % scale with loading
                for uu=1:npltX %over variables in X that we choose to plot
                    for mm=1:IRFperiods
                        for ll=1:n % over shocks
                            favar_ortirfmatrix(uu,ll,mm)=Lg(uu,:)*ortirfmatrix(:,ll,mm);
                        end
                    end
                end
            end

            % save
            for kk=1:n
                for ll=1:n
                    for mm=1:IRFperiods
                        irf_record_allt{kk,ll}(jj,mm,tt)=ortirfmatrix(kk,ll,mm);
                    end
                end
            end

            if favar_FAVAR==1
                for uu=1:npltX % loop over variables
                    for ll=1:n % loop over shocks
                        for mm=1:IRFperiods
                        favar.IRF.favar_irf_record_allt{uu,ll}(jj,mm,tt)=favar_ortirfmatrix(uu,ll,mm);
                        end
                    end
                end
            end
     end
end


close all;
clear all;
clc;

data_file_path = 'bin/mmv_phase_transition_snr_30db_s_16.mat';
options.export = true;
options.export_dir = 'bin';
options.export_name = 'mmv_snr_30_db_s_16';
options.chosen_ks = [2, 4, 8, 16, 32, 64];
options.subtitle = 'MMV, SNR=30dB s=16';
spx.pursuit.PhaseTransitionAnalysis.print_results(data_file_path, ...
    'CoSaMP', options);


% testing on new December 2016 price data

dataArray = csvread('results.csv');
prices = transpose(dataArray(:,2));
askVolume = dataArray(:,3);
bidVolume = dataArray(:,4);

prices = prices(1:2:end);
askVolume = askVolume(1:2:end);
bidVolume = bidVolume(1:2:end);

% estimate transaction fee at %1
[error,jinzhi,bank,buy,sell,proba] = brtrade(prices,bidVolume,askVolume, 1);

% set up plots
make_plots(prices, buy, sell, proba, bank, error);


function [tt]=tt_qreshape(tt,s,sz)

% Reshapes the cores of the input (Q)TT representation.
% s (scalar) is the number of mode indices in each core of the input representation;
% sz is a matrix of size d x s1, where d is the number of cores and s1 is the number of mode indices in each core of the output representation;
% sz(k,alpha) is the mode size of the alpha-th index in the k-th core of the output representation.
% k-th component of prod(sz,2) is the overall numbers of mode degrees of freedom of the k-th core of the output representation
%
% April 26, 2011
% Vladimir Kazeev
% vladimir.kazeev@gmail.com
% INM RAS
% Moscow, Russia
%

d=size(tt,1);
for k=1:d
	szk=size(tt{k});
	szk=[szk,ones(1,s)];
	szkr=szk(s+1:numel(szk));
	tt{k}=reshape(tt{k},[sz(k,:),szkr]);
end

return
end


function intlablogo(angle,screensaver)
%INTLABLOGO   Show INTLAB logo
%
%  intlablogo
%
%put cursor into figure and press
%
%  o  open
%  c  close
%  q  quit
%
%The call
%
%  intlablogo(angles)
%
%shows the dodecahedron in opening angles.
%

%The call
%   intlablogo([],1)
%generates a screensaver picture using
%  generate file: print -djpeg100 -zbuffer picturefile
%

% written  10/16/98     S.M. Rump
% modified 04/04/04     S.M. Rump  revision
% modified 10/13/05     S.M. Rump  name and fonts adapted
% modified 09/06/07     S.M. Rump  version number
% modified 06/24/08     S.M. Rump  screensaver
%

  if nargin<=1
    screensaver = 0;
  end

  psi1 = 10.8123169636;
  psi2 = 52.6226318594;

  for i=1:5
    P{i} = polar2rect(1,72*i,psi2);
    P{5+i} = polar2rect(1,72*i,psi1);
    P{10+i} = polar2rect(1,72*i-36,-psi1);
    P{15+i} = polar2rect(1,72*i-36,-psi2);
  end

  M = zeros(18,5,3);

  M(1,:,:) = [ P{ 1} P{ 5} P{10} .5*(P{10}+P{11}) .5*(P{1}+P{6}) ]';
  M(2,:,:) = [ P{ 1} P{ 2} P{ 3} P{ 4} P{ 5} ]';
  M(3,:,:) = [ P{ 5} P{ 4} P{ 9} P{15} P{10} ]';
  M(4,:,:) = [ P{ 3} P{ 8} P{14} P{ 9} P{ 4} ]';
  M(5,:,:) = [ P{10} P{15} .5*(P{15}+P{20}) .5*(P{10}+P{11}) P{10}]';
  M(6,:,:) = [ P{ 1} P{ 2} .5*(P{2}+P{7}) .5*(P{6}+P{1}) P{1}]';
  M(7,:,:) = [ P{15} P{ 9} P{14} .5*(P{14}+P{19}) .5*(P{20}+P{15}) ]';
  M(8,:,:) = [ P{2} P{3} P{8} .5*(P{8}+P{13}) .5*(P{2}+P{7}) ]';
  M(9,:,:) = [ P{8} P{14} .5*(P{14}+P{19}) .5*(P{8}+P{13}) P{8} ]';
  M(10:18,:,:) = -M(1:9,:,:);

  dil = .25*( P{14}+P{19} + P{20}+P{15} );
  for i=1:3
    M(:,:,i) = M(:,:,i) - dil(i);
  end
  phi = atan2(dil(2),dil(1));
  T = [ cos(phi) -sin(phi) 0 ; ...
      sin(phi)  cos(phi) 0 ; ...
      0          0     1 ];
  M = reshape( reshape(M,90,3)*T , 18,5,3 );
  Az = 23.75; El = 12.5;
  close

  % show a couple of angles
  if nargin~=0
    if ~isempty(angle)
      psi = angle(1);
      omegaold = 0;
      for omega=angle
        psi = omega-omegaold;
        M = showlogo(psi,M,screensaver);
        omegaold = omega;
        pause(0.05)
      end
      return
    end
  end

  % open/close by hand
  psi = 30;
  delta = 5;
  omega = psi;
  change = 1;

  while change
    clf
    M = showlogo(psi,M,screensaver);
    if screensaver
      print -djpeg100 -zbuffer picturefile
      close
      return
    end
    change = 0;

    if ~screensaver
      title( [ 'move cursor into window and press  "o"  or  "c"  or,  "q" for quit' ], ...
               'FontName','Sans Serif','Fontsize',10 );
    end
    shg
    waitforbuttonpress
    switch get(gcf,'CurrentCharacter')
      case 'o',
        if omega <= 180,
          psi = delta; omega = omega + delta;
        else
          psi = 0;
        end
        change = 1;
      case 'c',
        if omega >= delta
          psi = -delta; omega = omega - delta;
        else
          psi = 0;
        end
        change = 1;
    end
  end
  close

function M = showlogo(psi,M,screensaver)
% opens logo by angle psi from current setting
  clf
  axis off
  axis equal
  if screensaver
    M = 1.25*M;
    axis([-2.4 1.2 -1.5 2.1 -1 1.8])
  else
    axis([-1.5 1.5 -1.7 1.7 -.8 1.5])
  end
  axis manual
  hold on
  Az = 23.75; El = 12.5;
  view(Az,El)

  for i=10:18
    rand('state',0);
    fill3(M(i,:,1),M(i,:,2),M(i,:,3),rand(1,5,3));
  end

  psi_ = psi/180*pi;
  T = [ cos(psi_) 0 -sin(psi_) ; ...
      0     1      0      ; ...
      sin(psi_) 0  cos(psi_) ];
  M(1:9,:,:) = reshape( reshape(M(1:9,:,:),45,3)*T , 9,5,3 );

  for i=1:9
    rand('state',0);
    fill3(M(i,:,1),M(i,:,2),M(i,:,3),rand(1,5,3));
  end
  addtext(screensaver)
  hold off

function x = polar2rect(r,phi,psi)     % in degrees
  x = zeros(3,1);
  sigma = pi/180;
  phi = sigma*phi;
  psi = sigma*psi;
  x(1) = cos(phi).*cos(psi);
  x(2) = sin(phi).*cos(psi);
  x(3) = sin(psi);
  x = r*x;

function addtext(screensaver)
  if screensaver
    text(-1,-4  ,['INTLAB  -  INTerval LABoratory (Version ' intvalinit('version',0) ')'], ...
      'Fontsize',12, ...
      'FontName','MS Reference Sans Serif', ...
      'HorizontalAlignment','left');
    text(-.42,-5.2,'The Matlab toolbox for Reliable Computing  -  www.ti3.tuhh.de/rump', ...
      'Fontsize',10, ...
      'FontName','Arial', ...
      'HorizontalAlignment','left');
    text(-.36,-6.2,'Siegfried M. Rump, Institute for Reliable Computing, Hamburg University of Technology  ', ...
      'Fontsize',10, ...
      'FontName','Arial', ...
      'HorizontalAlignment','left');
  else
    text(-1,-4  ,['INTLAB  -  INTerval LABoratory (Version ' intvalinit('version',0) ')'], ...
      'Fontsize',17, ...
      'FontName','MS Reference Sans Serif', ...
      'HorizontalAlignment','left');
    text(-.1,-5.2,'The Matlab toolbox for Reliable Computing  -  www.ti3.tuhh.de/rump', ...
      'Fontsize',10, ...
      'FontName','Arial', ...
      'HorizontalAlignment','left');
    text(-.02,-6.2,'Siegfried M. Rump, Institute for Reliable Computing, Hamburg University of Technology  ', ...
      'Fontsize',10, ...
      'FontName','Arial', ...
      'HorizontalAlignment','left');
  end
  if ~screensaver
    str(1) =    {' x = hessianinit(xs);'};
    str(2) =     {' y = f(x);'};
    str(3) = {' xs = xs - y.hx\\y.dx'';'};
    text(-.5, 7.2,str, ...
      'HorizontalAlignment','right', ...
      'Fontsize',13, ...
      'FontName','Courier');
  end


function [pkx_final, cluster_final, LogL_final] = LCGMM(X, k, W, options)
% Local Consistent Gaussian Mixture Model (LCGMM)
%
% where
%   X
% Notation:
% X ... (nSmp x mFea)  observed data matrix
%       nSmp  ... number of samples
%       mFea  ... number of features
%
% K     ... number of clusters
% W     ... weight matrix of the affinity graph
%
% options ... Structure holding all settings
%
% You only need to provide the above four inputs.
%
% pkx ... P(z|x)
% R ... covariance matrix
% mu ... mean
%
%
% References:
% [1] Jialu Liu, Deng Cai, Xiaofei He, "Gaussian Mixture Model with
% Local Consistency", AAAI 2010.
% [2] Jialu Liu, "Notes on Local Consistent Gaussian Mixture Model(LCGMM)",
% Online available at http://relau.com/jialuliu/technical_notes/LCGMM.pdf
% [accessed 27-Dec-2011].
%
%   version 2.0 --Dec/2011
%   version 1.0 --Dec/2009
%
%   Written by Jialu Liu (remenberl AT gmail.com)
%              Deng Cai (dengcai AT gmail.com)
%
ZERO_OFFSET = 1e-200;

differror = 1e-7;
if isfield(options,'error')
    differror = options.error;
end

lambda = 0.1;
if isfield(options,'lambda')
    lambda = options.lambda;
end

nRepeat = 5;
if isfield(options,'nRepeat')
    nRepeat = options.nRepeat;
end

maxIter = 100;
if isfield(options,'maxIter')
    maxIter = options.maxIter;
end

minIterOrig = 5;
if isfield(options,'minIter')
    minIterOrig = options.minIter;
end
minIter = minIterOrig-1;

meanFitRatio = 0.1;
if isfield(options,'meanFitRatio')
    meanFitRatio = options.meanFitRatio;
end
meanFitControl = 1;
if isfield(options,'meanFitControl')
    meanFitControl = options.meanFitControl;
end

if ~isfield(options,'InitWay')
    options.InitWay = 'kmeans';
end

show = 0;
if isfield(options,'show')
    show = options.show;
end

debug = 0;
if isfield(options,'debug')
    debug = options.debug;
end

% init mixture
[nSmp mFea] = size(X);

if lambda > 0
    DCol = full(sum(W,2));
    D = spdiags(DCol,0,nSmp,nSmp);
    L = D - W;
end

[cluster,pkx,LogL] = GMM_init(X,k,options);
meanFit = LogL/10;

tryNo = 0;
selectInit = 1;
nIter = 0;
while tryNo < nRepeat
    tryNo = tryNo+1;
    maxErr = 1;
    retry = 0;
    while(maxErr > differror || maxErr==-1)
        % EM iteration
        alertFlag = 0;
        for kidx=1:k
            % compute pi
            cluster(kidx).pb = sum(pkx(:,kidx));
            if cluster(kidx).pb < 1e-20
                retry = 1;
                break;
            end
            % compute Tk
            if lambda > 0
                Tk = 1 - lambda * sum(bsxfun(@minus, pkx(:,kidx), pkx(:,kidx)') .* W, 2) ./ (pkx(:,kidx) + ZERO_OFFSET);
            else
                Tk = ones(nSmp, 1);
            end

            if min(Tk) < 0 && alertFlag == 0 && debug == 1
                alertFlag = 1;
                disp('The covariance matrix might not be positive semidefinate since lambda is too big such that some value of Tik is negative.');
            end

            % compute mean
            cluster(kidx).mu = ((pkx(:,kidx) .* Tk)' * X) / cluster(kidx).pb;

            % compute covariance matrix
            Y1 = X-repmat(cluster(kidx).mu,nSmp,1);
            Y2 = bsxfun(@times,sqrt(pkx(:,kidx) .* Tk), Y1);
            R = (Y2'*Y2) /cluster(kidx).pb;
            %for elemetns in Tk which are negative
            Y3 = bsxfun(@times,sqrt(pkx(:,kidx) .* (-(Tk<0) .* Tk)), Y1);
            R = R - 2 * (Y3'*Y3) /cluster(kidx).pb;

            %
            clear Y2;
            R = max(R,R');

            detR = det(R);
            if detR <= 0
                retry = 1;
                break;
            end

            cluster(kidx).cov = R;
            const = -(mFea*log(2*pi) + log(detR))/2;

            Y2 = R\Y1';
            Y2 = -Y2'/2;
            pkx(:,kidx) = dot(Y1,Y2,2)+const;
            clear Y1 Y2 R;
        end

        if retry
            break;
        end

        llmax=max(pkx,[],2);
        pkx =exp( pkx-repmat(llmax,1,k) );
        pkx = pkx.*repmat([cluster(:).pb],nSmp,1);
        ss = sum(pkx,2);
        llnew = sum(log(ss)+llmax);
        pkx = pkx./(repmat(ss,1,k));

        % compute new likelihood
        if lambda > 0
            llnew = llnew - sum(sum((log(pkx' + ZERO_OFFSET) * L).* pkx')) * lambda / 2;
        end

        LogL = [LogL llnew];
        %
        nIter = nIter + 1;

        meanFit = meanFitRatio*meanFit + (1-meanFitRatio)*llnew;
        maxErr = (llnew-meanFit)/meanFit;
        if show
            if length(LogL) > 1
                disp(['tryNo: ',num2str(tryNo),' Iteration: ',num2str(nIter),' LogL: ',num2str(LogL(end)),' deltaLogL: ',num2str(LogL(end)-LogL(end-1)),' maxErr:',num2str(maxErr)]);
            else
                disp(['tryNo: ',num2str(tryNo),' Iteration: ',num2str(nIter),' LogL: ',num2str(LogL(end)),' maxErr:',num2str(maxErr)]);
            end
        end
        if nRepeat > 1 && selectInit
            maxErr = 1;
        end
        if ~meanFitControl
            maxErr = 1;
        end
        if nIter > minIter
            if selectInit
                maxErr = 0;
            else
                if nIter >= maxIter
                    maxErr = 0;
                end
            end
        end
    end

    if retry && ~(tryNo == nRepeat && nIter >= nIter_final)
        tryNo = tryNo - 1;
        [cluster,pkx,LogL] = GMM_init(X,k,options);
        meanFit = LogL/10;
        nIter = 0;
        continue;
    end

    if tryNo == 1
        pkx_final = pkx;
        cluster_final = cluster;
        LogL_final = LogL;
        nIter_final = nIter;
    else
        if LogL(end) > LogL_final(end)
            pkx_final = pkx;
            cluster_final = cluster;
            LogL_final = LogL;
            nIter_final = nIter;
        end
    end

    if selectInit
        if tryNo < nRepeat
            [cluster,pkx,LogL] = GMM_init(X,k,options);
            meanFit = LogL/10;
            nIter = 0;
        else
            tryNo = tryNo - 1;
            selectInit = 0;
            pkx = pkx_final;
            cluster = cluster_final;
            LogL = LogL_final;
            nIter = nIter_final;
            meanFit = LogL(end)/10;
        end
    end
end

function [cluster,pkx,llnew] = GMM_init(X,k,options)
    ZERO_OFFSET = 1e-200;
    [nSmp, mFea] = size(X);
    if strcmpi(options.InitWay,'kmeans')
        kmeansres = litekmeans(X,k,'maxIter',10);
        residx = unique(kmeansres);
        for kidx=1:k
            smpidx = kmeansres==residx(kidx);
            cluster(kidx).mu = mean(X(smpidx,:),1);
            cluster(kidx).pb = 1/k;
        end
    else
        permutation = randperm(nSmp);
        nSmpClass = floor(nSmp/k);
        for kidx=1:k
            cluster(kidx).mu = mean(X(permutation((kidx-1)*nSmpClass+1:kidx*nSmpClass),:),1);
            cluster(kidx).pb = 1/k;
        end
    end

    R = (nSmp-1)*cov(X)/nSmp;
    R = max(R,R');

    % EM iteration

    pkx=zeros(nSmp,k);
    detR = det(R);
    if detR <= 0
        error('The covariance matrix is not positive definite. Use PCA to reduce the dimensions first!');
    end
    const = -(mFea*log(2*pi) +log(detR))/2;
    for kidx=1:k
        Y1=X-repmat(cluster(kidx).mu,nSmp,1);
        Y2 = R\Y1';
        Y2 = -Y2'/2;
        pkx(:,kidx) = dot(Y1,Y2,2)+const;
        clear Y1 Y2;
    end
    clear R;
    llmax=max(pkx,[],2);
    pkx =exp( pkx-repmat(llmax,1,k) );
    pkx = pkx.*repmat([cluster(:).pb],nSmp,1);
    ss = sum(pkx,2);
    llnew = sum(log(ss)+llmax);
    pkx = pkx./(repmat(ss,1,k));


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
% This is a testing environment for the files in the folder kernel/data
% 1. Based on data/contents, a list of required files is generated and it
%    is verified, that all files are present; additional files are listed.
% 2. All c-files are compiled.
% 3. All files are executed.
% 4. Check administrative modul Trafo.m
% 5. Transform certain 2D and 3D grids
%==============================================================================

FAIRcheckFiles(mfilename);

%% Test module trafo, start with syntax
trafo('reset','trafo','splineTransformation2D',...
  'p',[4,5],'omega',[1,1],'m',[6,40]);
trafo('disp');
[scheme,parameter] = trafo;
trafo('clear');
%% test 2D cases

omega  = [0,1,0,2];
m      = [6,7];
xc     = getCellCenteredGrid(omega,m);
center = (omega(2:2:end)+omega(1:2:end))'/2;

% initialize various transformations
trafos = {
  'affine2D',{},...
  'affine2Dsparse',{},...
  'rigid2D',{},...
  'rotation2D',{'c',center},...
  'translation2D',{},...
  'splineTransformation2D',{'p',[4,5],'omega',omega,'m',m},...
  'splineTransformation2Dsparse',{'p',[4,5],'omega',omega,'m',m}
  };

for k=2:length(trafos)/2,
  fprintf(2,'\n\n\ntest [ %s ] --- %d of %d\n',...
    trafos{2*k-1},k,length(trafos)/2)
  optn = trafos{2*k};
  trafo('reset','trafo',trafos{2*k-1},'debug','on',optn{:});
  trafo('disp');
  wc = trafo('w0');
  fctn = @(wc) trafo(wc,xc);
  checkDerivative(fctn,wc+randn(size(wc)),'fig',1+mod(k,2));
  title(trafo)
  builtin('pause',2);
end;

%% test 3D cases
omega = [0,1,0,2,0,3]; m = [6,7,8]; xc = getCellCenteredGrid(omega,m);
trafos = {
  'affine3D',{},...
  'affine3Dsparse',{},...
  'rigid3D',{},...
  'splineTransformation3Dsparse',{'p',[4,5,6],'omega',omega,'m',m},...
  'translation3D',{}
  };

for k=1:length(trafos)/2,
  fprintf('\n\n\ntest [ %s ] --- %d of %d\n',...
    trafos{2*k-1},k,length(trafos)/2)
  optn = trafos{2*k};
  trafo('reset','trafo',trafos{2*k-1},'debug','on',optn{:});
  trafo('disp');
  wc = trafo('w0');
  fctn = @(wc) trafo(wc,xc);
  checkDerivative(fctn,wc+randn(size(wc)),'fig',1+mod(k,2));
  title(trafo)
  builtin('pause',2);
end;

testEnd;
%==============================================================================


function img = imresizeAspect(img, maxSize)
% function img = imresizeAspect(img, maxSize)
% If image is larger than max size, reduce size, preserving aspect ratio of input.
%
% If size(input) = [y x] and maxSize = [yy xx],
% then size(output) is given by the following (where a=y/x)
%  if y<yy & x<xx  then [y x]
%  else if a<1 then [a*xx xx]
%  else [yy yy/a]

% For why we use bilinear,
% See http://nickyguides.digital-digest.com/bilinear-vs-bicubic.htm

if isempty(maxSize), return; end

[y x c] = size(img);
a= y/x;
yy = maxSize(1); xx = maxSize(2);
if y <= yy & x <= xx
  % no-op
else
  if a < 1
    img = imresize(img, ceil([a*xx xx]), 'bilinear');
  else
    img = imresize(img, ceil([yy yy/a]), 'bilinear');
  end
  fprintf('resizing from %dx%d to %dx%d\n', y, x, size(img,1), size(img,2));
end

%test
if 0
  maxSize = [240 320];
  %img = imread('C:\Images\Wearables\web_static_office\8.jpg');
  %img = imread('C:\Images\Wearables\web_static_office\billandkirsten.jpg');
  %img = imread('C:\Images\Wearables\web_static_street_april\p5.jpg');
  img = imread('C:\Images\Wearables\Database_static_street\art11.jpg');
  img2 = imresizeAspect(img, maxSize);
  figure(1); clf; imshow(img)
  figure(2); clf; imshow(img2)
  fprintf('%dx%d (%5.3f) to %dx%d (%5.3f)\n', ...
	  size(img,1), size(img,2), size(img,1)/size(img,2), ...
	  size(img2,1), size(img2,2), size(img2,1)/size(img2,2));
end


[T,Y]=ode45('F',[0 1],[0;1;-1])


% Copyright 2018 Marc René Schädler
%
% This file is part of the mobile hearing aid prototype project
% The the mobile hearing aid prototype project 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.
%
% The mobile hearing aid prototype project 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 the mobile hearing aid prototype project. If not, see http://www.gnu.org/licenses/.

function [feedback, range] = estimate_feedback(signal, fs, method)

if nargin < 3 || isempty(method)
  method = 'median';
end

signal = signal(1000:end-1000,:);
num_samples = size(signal,1);
max_samples = round(20.*fs./1000); % ~20 ms
max_range = round(3.*fs./1000); % ~3 ms
min_freq = fs./max_samples;

step_samples = round(0.1.*fs);
analysis_samples = round(0.5.*fs);
num_frames = floor((num_samples-analysis_samples)/step_samples);
fft_samples = 2.^nextpow2(2.*analysis_samples);

% Use only single precision
signal = single(signal);

% Function to calculate the ifft of a reduced spectrum which belongs to a real function
real_ifft = @(x) real(ifft([x;conj(x(end-1:-1:2))]));

if strcmp(method,'deconv')
  % Unsegmented reference implementation
  signal_fft = fft(signal);
  signal_fft(1:1+round(min_freq./fs.*size(signal,1)),3:4) = 0;
  signal_fft(1+end-round(min_freq./fs.*size(signal,1)):end,3:4) = 0;
  feedback = real(ifft(signal_fft(:,[3,4])./signal_fft(:,[1,2])));
  feedback_short = feedback_ref(1:max_samples,:);
else
  % Calculate feedback paths for each segment
  feedback_left_fft = zeros(num_frames,fft_samples./2+1,'single');
  feedback_right_fft = zeros(num_frames,fft_samples./2+1,'single');
  for i=1:num_frames
    start = 1+(i-1).*step_samples;
    stop = analysis_samples+(i-1).*step_samples;
    signal_fft = fft(signal(start:stop,:),fft_samples);
    feedback_left_fft(i,:) = signal_fft(1:end/2+1,3)./signal_fft(1:end/2+1,1);
    feedback_right_fft(i,:) = signal_fft(1:end/2+1,4)./signal_fft(1:end/2+1,2);
  end
end

switch(method)
  case 'median'
    % Function to calculate median of real and imaginary part independently
    cmedian = @(x) median(real(x))+1i.*median(imag(x));
    % Remove outliers and frequencies which dont "fit" into "max_range"
    feedback_left_fft_median = cmedian(feedback_left_fft);
    feedback_right_fft_median = cmedian(feedback_right_fft);
    feedback_left_fft_median(1:1+round(min_freq./fs.*fft_samples)) = 0;
    feedback_right_fft_median(1:1+round(min_freq./fs.*fft_samples)) = 0;
    feedback_left_median = real_ifft(feedback_left_fft_median(:));
    feedback_right_median = real_ifft(feedback_right_fft_median(:));
    feedback_left_median_short = feedback_left_median(1:max_samples);
    feedback_right_median_short = feedback_right_median(1:max_samples);
    feedback1 = single(feedback_left_median_short);
    feedback2 = single(feedback_right_median_short);
  case 'mean'
    % A variant using the mean instead of the median values
    feedback_left_fft_mean = mean(feedback_left_fft);
    feedback_right_fft_mean = mean(feedback_right_fft);
    feedback_left_fft_mean(1:1+round(min_freq./fs.*fft_samples)) = 0;
    feedback_right_fft_mean(1:1+round(min_freq./fs.*fft_samples)) = 0;
    feedback_left_mean = real_ifft(feedback_left_fft_mean(:));
    feedback_right_mean = real_ifft(feedback_right_fft_mean(:));
    feedback_left_mean_short = feedback_left_mean(1:max_samples);
    feedback_right_mean_short = feedback_right_mean(1:max_samples);
    feedback1 = single(feedback_left_mean_short);
    feedback2 = single(feedback_right_mean_short);
end

% Find level for first path
level1 = 0;
while diff(selectmain(feedback1,level1)) <= max_range
  level1 = level1 - 1;
end
level1 = level1 + 1;

% Find level for second path
level2 = 0;
while diff(selectmain(feedback2,level2)) <= max_range
  level2 = level2 - 1;
end
level2 = level2 + 1;

% Get corrsponding ranges ranges
range1 = selectmain(feedback1,level1)-1;
range2 = selectmain(feedback2,level2)-1;

feedback = [feedback1,feedback2];
range = [range1;range2];
end

function range = selectmain(in,level)
  % Dynamically select the window that covers the most energy

  min_level = 10.^(level/20);
  [~, maxidx] =  max(abs(in));
  start = find(abs(in)>min_level,1,'first');
  stop = find(abs(in)>min_level,1,'last');
  if isempty(start)
    start = maxidx;
  end
  if isempty(stop)
    stop = maxidx;
  end
  range = [start stop];
end


function dataout=modeBSS(nummics, numrefs, datain)
%
% Use Aux-IVA to solve dr, aec and separation.
% nummics:              no. of mic channels
% numrefs:              no. of reference channels
% datain:               input data
% dataout:              output data
%

%% perform stft
addpath('stft2');
% fft size
fftsize=512;
stftshift=fftsize/2;

M=nummics;
R=numrefs;
N=M;

Xtf=cell(M+R, 1);
for m=1:M+R
    Xtf{m}=stft(datain(:, m), stftshift, fftsize, false);
end
[K, T]=size(Xtf{1});

Ytf=cell(M, 1);
for m=1:M
    Ytf{m}=zeros(K, T);
end

%% params
% dr filter length
DR_FLEN=5;
% forgetting factor for bss
BF_FORGET=0.999;
% the shape parameter of the source prior
GAMMA=0.2;
%
% used to keep stable
%
VAR_BIAS=0.01;
STABLE_EPS=1e-3;
BF_DIAGLOAD=1e-6;

%% space for bss
% data buffer
fsize=M+R+M*DR_FLEN;
Bufdata=zeros(K, fsize);
% current mic backup
Miccurrent=zeros(K, M);

% the weighted correlation matrices
C1=cell(K, 1);
C2=cell(K, 1);
for k=1:K
    C1{k}=STABLE_EPS*eye(fsize, fsize);
    C2{k}=STABLE_EPS*eye(fsize, fsize);
end

% demixing matrices
Demix=cell(K, 1);
for k=1:K
    Demix{k}=eye(fsize, fsize);
end

%% perform iteration
for tau=1:T
    Bssout=zeros(K, M);

    %
    % shift in new data
    %
    % shift old mic data back
    Bufdata=circshift(Bufdata, M, 2);
    % shift in delayed mic data
    Bufdata(:, M+R+1:M+R+M)=Miccurrent;

    % mic data backup
    for m=1:M
        Miccurrent(:, m)=Xtf{m}(:, tau);
    end
    % current mic data
    Bufdata(:, 1:M)=Miccurrent;

    % shift in reference data
    for r=1:R
        Bufdata(:, M+r)=Xtf{M+r}(:, tau);
    end

    %
    % calculate nonlinearity
    %
    phi1=0;
    phi2=0;

    for k=1:K
        x=Bufdata(k, :).';
        y=Demix{k}*x;
        % output data
        Bssout(k, :)=y(1:M).';

        phi1=phi1+abs(y(1))^2;
        phi2=phi2+abs(y(2))^2;
    end

    phi1=(1-BF_FORGET)*(phi1+VAR_BIAS)^((GAMMA-2)/2);
    phi2=(1-BF_FORGET)*(phi2+VAR_BIAS)^((GAMMA-2)/2);

    % update the demixing matrices
    for k=1:K
        %
        % accumulate the weighted correlation
        %
        x=Bufdata(k, :).';
        C1{k}=BF_FORGET*C1{k}+phi1*(x*x');
        C2{k}=BF_FORGET*C2{k}+phi2*(x*x');

        %
        % update demixing matrix
        %
        H1=inv(Demix{k}*C1{k}+BF_DIAGLOAD*eye(fsize, fsize));
        w1=H1(:, 1);

        H2=inv(Demix{k}*C2{k}+BF_DIAGLOAD*eye(fsize, fsize));
        w2=H2(:, 2);

        D=eye(fsize, fsize);
        D(1, :)=w1';
        D(2, :)=w2';

        %
        % solve the scaling ambiguity
        %
        A=inv(D);

        if abs(A(1, 1))>=abs(A(2, 1))
            a1=A(1, 1);
        else
            a1=A(2, 1);
        end

        if abs(A(2, 2))>=abs(A(1, 2))
            a2=A(2, 2);
        else
            a2=A(1, 2);
        end

        D=eye(fsize, fsize);
        D(1, :)=a1*w1';
        D(2, :)=a2*w2';

        Demix{k}=D;
    end

    for m=1:M
        Ytf{m}(:, tau)=Bssout(:, m);
    end
end

%% perform istft and output signal
dataout=zeros(dataLength(T, stftshift, fftsize ), N);
for n=1:N
    dataout(:, n)=istft(Ytf{n}, stftshift, false);
end

end


function [mh,mS] = pred_coxphhs(gp, x, y, xt, varargin)
%PRED_COXPHHS  Return hazard and survival functions
%
%  Description
%    [H,S] = PRED_COXPHHS(GP,X,Y,XT)
%    Returns hazard and survival functions for the inputs XT. GP is the
%    Gaussian process structure, X and Y are the training inputs and
%    outputs.
%
% Copyright (c) 2012-2013 Ville Tolvanen, Aki Vehtari

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

ntime=size(gp.lik.xtime,1);
if iscell(gp)
  % prediction for GP_IA cell array
  nGP = numel(gp);
  mh=zeros(size(xt,1),ntime,nGP);
  mS=zeros(size(xt,1),ntime,nGP);
  P_TH=zeros(1,nGP);
  for i1=1:nGP
    % make prediction for each gp in cell array
    Gp=gp{i1};
    P_TH(:,i1) = Gp.ia_weight;
    [mh(:,:,i1), mS(:,:,i1)]=pred_coxphhs(Gp, x, y, xt, varargin{:});
    mh(:,:,i1)=P_TH(:,i1)*mh(:,:,i1);
    mS(:,:,i1)=P_TH(:,i1)*mS(:,:,i1);
  end
  % combine predictions
  mh=sum(mh,3);
  mS=sum(mS,3);
  return
elseif numel(gp.jitterSigma2)>1
  nmc=size(gp.jitterSigma2,1);
  mh=zeros(size(xt,1),ntime,nmc);
  mS=zeros(size(xt,1),ntime,nmc);
  for i1=1:nmc
    Gp = take_nth(gp,i1);
    [mh(:,:,i1), mS(:,:,i1)]=pred_coxphhs(Gp, x, y, xt, varargin{:});
  end
  % combine predictions
  mh=mean(mh,3);
  mS=mean(mS,3);
  return
end

[Ef1, Ef2, Covf] = pred_coxph(gp,x,y,xt, varargin{:});
nsamps = 10000;
if isfield(gp.lik, 'stratificationVariables')
  ind_str=gp.lik.stratificationVariables;
  ux=unique([x(:,ind_str); xt(:,ind_str)],'rows');
  nu=size(ux,1);
  for i1=1:size(ux,1)
    uind{i1}=find(xt(:,ind_str)==ux(i1,:));
  end
  nf1=ntime*nu;
else
  nf1=ntime;
end
sd=gp.lik.stime(2)-gp.lik.stime(1);

Sigm_tmp=Covf;
Sigm_tmp=(Sigm_tmp+Sigm_tmp')./2;
% f_star=mvnrnd(Ef1, Sigm_tmp(1:ntime,1:ntime), nsamps);
f_star=mvnrnd([Ef1;Ef2], Sigm_tmp, nsamps);

f1=f_star(:,1:nf1);
f2=f_star(:,(nf1+1):end);

la1=exp(f1);
eta2=exp(f2);

if ~isfield(gp.lik, 'stratificationVariables')
  hb=(la1'*sd);
  cumsumtmp=cumsum(hb)';
  for i1=1:size(eta2,2)
    mh(i1,:)=mean(bsxfun(@times,hb',eta2(:,i1)));
    Stime=exp(-bsxfun(@times,cumsumtmp,eta2(:,i1)));
    mS(i1,:)=mean(Stime);
  end
else
  for i2=1:length(uind)
    hb=(la1(:,(i2-1)*ntime+1:i2*ntime)'*sd);
    cumsumtmp=cumsum(hb)';
    for i1=1:size(uind{i2},1)
      ind=uind{i2}(i1);
      mh(ind,:)=mean(bsxfun(@times,hb',eta2(:,ind)));
      Stime=exp(-bsxfun(@times,cumsumtmp,eta2(:,ind)));
      mS(ind,:)=mean(Stime);
    end
  end
end

end


%IRECTIFY Rectify stereo image pair
%
% [OUT1,OUT2] = IRECTIFY(F, M, IM1, IM2) is a rectified pair of images
% corresponding to IM1 and IM2.  F (3x3) is the fundamental matrix relating
% the two views and M is a FeatureMatch object containing point correspondences
% between the images.
%
% [OUT1,OUT2,H1,H2] = IRECTIFY(F, M, IM1, IM2) as above but also returns
% the homographies H1 and H2 that warp IM1 to OUT1 and IM2 to OUT2 respectively.
%
% Notes::
% - The resulting image pair are epipolar aligned, equivalent to the view
%   if the two original camera axes were parallel.
% - Rectified images are required for dense stereo matching.
% - The effect of lense distortion is not removed, use the camera calibration
%   toolbox to unwarp each image prior to rectification.
% - The resulting images may have negative disparity.
% - Some output pixels may have no corresponding input pixels and will be
%   set to NaN.
%
% See also FeatureMatch, ISTEREO, HOMWARP, CentralCamera.

% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Machine Vision Toolbox for Matlab (MVTB).
%
% MVTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% MVTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with MVTB.  If not, see <http://www.gnu.org/licenses/>.

function [Img1_new, Img2_new, H12,H21] = irectify(F, m, Img1, Img2)
% http://se.cs.ait.ac.th/cvwiki/matlab:tutorial:rectification

F12 = F';

[rows,cols,depth] = size(Img1);

% Get homographies.

x1 = e2h( m.p1 );
x2 = e2h( m.p2 );

[H12,H21,bSwap] = rectify_homographies( F12, x1, x2, rows, cols );

[w1,off1] = homwarp(H12, Img1, 'full');
[w2,off2] = homwarp(H21, Img2, 'full');

% fix the vertical alignment of the images by padding
dy = off1(2) - off2(2);
if dy < 0
    w1 = ipad(w1, 'b', -dy);
    w2 = ipad(w2, 't', -dy);
else
    w1 = ipad(w1, 't', dy);
    w2 = ipad(w2, 'b', dy);
end

[w1,w2] = itrim(w1, w2);

if nargout == 0
    stdisp(w1, w2)
else
    Img1_new = w1;
    Img2_new = w2;
end

%-----------------------------------------------------------------------------

function [H1,H2,bSwap] = rectify_homographies( F, x1, x2, rows, cols )

  % F: a fundamental matrix

  % x1 and x2: corresponding points such that x1_i' * F * x2_i = 0

  % Initialize

  H1 = [];
  H2 = [];
  bSwap = 0;

  % Center of image

  cy = round( rows/2 );
  cx = round( cols/2 );

  % Fix F to be rank 2 to numerical accuracy

  [U,D,V] = svd( F );
  D(3,3) = 0;
  F = U*D*V';

  % Get epipole.  e12 is the epipole in image 1 for camera 2.

  e12 = null( F' );             % Epipole in image 1 for camera 2
  e21 = null( F );              % Epipole in image 2 for camera 1

  % Put epipoles in front of camera

  if e12 < 0, e12 = -e12; end;
  if e21 < 0, e21 = -e21; end;

  % Make sure the epipoles are inside the images

  check_epipoles_in_image( e12, e21, rows, cols );

  % Check that image 1 is to the left of image 2

%   if e12(1)/e12(3) < cx
%     fprintf( 1, 'Swapping left and right images...\n' );
%     tmp = e12;
%     e12 = e21;
%     e21 = tmp;
%     F = F';
%     bSwap = 1;
%   end;

  % Now we have
  % F' * e12 = 0,
  % F  * e21 = 0,

  % Let's get the rectifying homography Hprime for image 1 first

  Hprime = map_to_infinity( e12, cx, cy );
  e12_new = Hprime * e12;
  % Normalize Hprime so that Hprime*eprime = (1,0,0)'
  Hprime = Hprime / e12_new(1);
  e12_new = Hprime * e12;
  fprintf( 1, 'Epipole 1/2 mapped to infinity: (%g, %g, %g)\n', e12_new );

  % Get canonical camera matrices for F12 and compute H0, one possible
  % rectification homography for image 2

  [P,Pprime] = get_canonical_cameras( F );
  M = Pprime(:,1:3);
  H0 = Hprime * M;

  % Test that F12 is a valid F for P,Pprime

  test_p_f( P, Pprime, F );

  % Now we need to find H so that the epipolar lines match
  % each other, i.e., inv(H)' * l = inv(Hprime)' * lprime
  % and the disparity is minimized, i.e.,
  % min \sum_i d(H x_i, Hprime xprime_i)^2

  % Transform data initially according to Hprime (img 1) and H0 (img 2)

  x1hat = Hprime * x1;
  x1hat = x1hat ./ repmat( x1hat(3,:), 3, 1 );
  x2hat = H0 * x2;
  x2hat = x2hat ./ repmat( x2hat(3,:), 3, 1 );
  rmse_x = sqrt( mean( (x1hat(1,:) - x2hat(1,:) ).^2 ));
  rmse_y = sqrt( mean( (x1hat(2,:) - x2hat(2,:) ).^2 ));
  fprintf( 1, 'Before Ha, RMSE for corresponding points in Y: %g X: %g\n', ...
           rmse_y, rmse_x );

  % Estimate [ a b c ; 0 1 0 ; 0 0 1 ] aligning H, Hprime

  n = size(x1,2);
  A = [ x2hat(1,:)', x2hat(2,:)', ones(n,1) ];
  b = x1hat(1,:)';
  abc = A\b;
  HA = [ abc' ; 0 1 0 ; 0 0 1 ];
  H = HA*H0;
  x2hat = H * x2;
  x2hat = x2hat ./ repmat( x2hat(3,:), 3, 1 );
  rmse_x = sqrt( mean(( x1hat(1,:) - x2hat(1,:) ).^2 ));
  rmse_y = sqrt( mean(( x1hat(2,:) - x2hat(2,:) ).^2 ));
  fprintf( 1, 'After Ha, RMSE for corresponding points in Y: %g X: %g\n', ...
           rmse_y, rmse_x );

  % Return the homographies as appropriate

  if bSwap
    H1 = H;
    H2 = Hprime;
  else
    H1 = Hprime;
    H2 = H;
  end;

%-----------------------------------------------------------------------------

function check_epipoles_in_image( e1, e2, rows, cols )

  % Check whether given epipoles are in the image or not

  if abs( e1(3) ) < 1e-6 & abs( e2(3) ) < 1e-6, return; end;

  e1 = e1 / e1(3);
  e2 = e2 / e2(3);
  if ( e1(1) <= cols & e1(1) >= 1 & e1(2) <= rows & e1(2) >= 1 ) | ...
     ( e2(1) <= cols & e2(1) >= 1 & e2(2) <= rows & e2(2) >= 1 )
    err_msg = sprintf( 'epipole (%g,%g) or (%g,%g) is inside image', ...
                       e1(1:2), e2(1:2) );
    error( [ err_msg, ' -- homography does not work in this case!' ] );
  end;

%-----------------------------------------------------------------------------

function [P,Pprime] = get_canonical_cameras( F )

  % Get the "canonical" cameras for given fundamental matrix
  % according to Hartley and Zisserman (2004), p256, Result 9.14

  % But ensure that the left 3x3 submatrix of Pprime is nonsingular
  % using Result 9.15, that the general form is
  % [ skewsym( e12 ) * F + e12 * v', k * e12 ] where v is an arbitrary
  % 3-vector and k is an arbitrary scalar

  P = [ 1 0 0 0
        0 1 0 0
        0 0 1 0 ];

  e12 = null( F' );
  M = skew( e12 ) * F + e12 * [1 1 1];
  Pprime = [ M, e12 ];

%-----------------------------------------------------------------------------

function test_p_f( P, Pprime, F )

  % Test that camera matrices Pprime and P are consistent with
  % fundamental matrix F
  % Meaning  (Pprime*X)' * F * (P*X) = 0,  for all X in 3space

  % Get the epipole in camera 1 for camera 2

  C2 = null( P );
  eprime = Pprime * C2;

  % Construct F from Pprime, P, and eprime

  Fhat = skew( eprime ) * Pprime * pinv( P );

  % Check that it's close to F

  alpha = Fhat(:)\F(:);
  if norm( alpha*Fhat-F ) > 1e-10
    fprintf( 1, 'Warning: supplied camera matrices are inconsistent with F\n' );
  else
    fprintf( 1, 'Supplied camera matrices OK\n' );
  end;

%-----------------------------------------------------------------------------

function H = map_to_infinity( x, cx, cy )

  % Given a point and the desired origin (point of minimum projective
  % distortion), compute a homograph H = G*R*T taking the point to the
  % origin, rotating it to align with the X axis, then mapping it to
  % infinity.

  % First map cx,cy to the origin

  T = [ 1 0 -cx
        0 1 -cy
        0 0 1 ];
  x = T * x;

  % Now rotate the translated x to align with the X axis.

  cur_angle = atan2( x(2), x(1) );
  R = [ cos( -cur_angle ), -sin( -cur_angle ), 0
        sin( -cur_angle ),  cos( -cur_angle ), 0
                        0,                  0, 1 ];
  x = R * x;

  % Now the transformation G mapping x to infinity

  if abs( x(3)/norm(x) ) < 1e-6
      % It's already at infinity
      G = eye(3)
  else
      f = x(1)/x(3);
      G = [    1   0  0
               0   1  0
             -1/f  0  1 ];
  end;

  H = G*R*T;


function [GAmp,GTime]=GxRadial(p)

global VCtl;
global VObj;
global VVar;

t1Start=p.t1Start;
t2Middle=p.t2Middle;
t3Start=p.t3Start;
tRamp=p.tRamp;
Gx1Sign=p.Gx1Sign;
Gx2Sign=p.Gx2Sign;
Gx3Sign=p.Gx3Sign;

% 2D radial encoding
FOV = VCtl.FOVFreq; % choose FOVFreq as real FOV
Res = VCtl.ResFreq; % choose ResFreq as real resolution

switch VCtl.R_AngPattern
    case 'Linear'
       eval(['R_AngRange=' VCtl.R_AngRange ';']);
       AngInc = R_AngRange / VCtl.R_SpokeNum;
    case 'Golden'
       AngInc = 111.246 * (pi/180); % Golden-angle sample
end

GxAmp=(1/FOV)/((VObj.Gyro/(2*pi))*(1/VCtl.BandWidth));
tHalf=1/(2*(VObj.Gyro/(2*pi))*GxAmp*(FOV/Res));
[GAmp1,GTime1]=StdTrap(t1Start-tRamp,          ...
                       t1Start+tHalf+tRamp,    ...
                       t1Start,                          ...
                       t1Start+tHalf,                    ...
                       GxAmp*cos(AngInc * (VVar.PhaseCount - 1))*Gx1Sign,2,2,2);
[GAmp2,GTime2]=StdTrap(t2Middle+VCtl.TEAnchorTime-tHalf-tRamp, ...
                       t2Middle+VCtl.TEAnchorTime+tHalf+tRamp, ...
                       t2Middle+VCtl.TEAnchorTime-tHalf,               ...
                       t2Middle+VCtl.TEAnchorTime+tHalf,               ...
                       GxAmp*cos(AngInc * (VVar.PhaseCount - 1))*Gx2Sign,2,2,2);
[GAmp3,GTime3]=StdTrap(t3Start-tRamp,            ...
                       t3Start+tHalf+tRamp,      ...
                       t3Start,                          ...
                       t3Start+tHalf,                    ...
                       GxAmp*cos(AngInc * (VVar.PhaseCount - 1))*Gx3Sign,2,2,2);

GAmp=GAmp2;
GTime=GTime2;

if Gx1Sign~=0
    GAmp=[GAmp1, GAmp];
    GTime=[GTime1, GTime];
end

if Gx3Sign~=0
    GAmp=[GAmp, GAmp3];
    GTime=[GTime, GTime3];
end

[GTime,m,n]=unique(GTime);
GAmp=GAmp(m);

end


% Script to scale a phase map so that max = pi and min =-pi radians.
% Writes out scaled image prepended with 'sc'.
% Chloe Hutton 25/02/04
% SPM Update - 13/11/06
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Chloe Hutton
% $Id: pm_scale_phase.m 4446 2011-08-30 10:50:29Z guillaume $

V   = spm_vol(spm_select(1,'image','Select phase image to scale'));
vol = spm_read_vols(V);

mn   = min(vol(:));
mx   = max(vol(:));
svol = -pi+(vol-mn)*2*pi/(mx-mn);

% Output image struct
oV = struct(...
    'fname',   spm_file(V.fname,'prefix','sc'),...
    'dim',     V.dim(1:3),...
    'dt',      [4 spm_platform('bigend')],...
    'mat',     V.mat,...
    'descrip', 'Scaled phase');

spm_write_vol(oV,svol);


maxiter = 20;
restartProb = 0.50;
dim_drug = 100;
dim_prot = 400;

drugNets = {'Sim_mat_drug_drug', 'Sim_mat_drug_disease', 'Sim_mat_drug_se', 'Sim_mat_Drugs'};
proteinNets = {'Sim_mat_protein_protein', 'Sim_mat_protein_disease', 'Sim_mat_Proteins'};

tic
X = DCA(drugNets, dim_drug, restartProb, maxiter);
toc
tic
Y = DCA(proteinNets, dim_prot, restartProb, maxiter);
toc

dlmwrite(['../feature/drug_vector_d', num2str(dim_drug), '.txt'], X, '\t');
dlmwrite(['../feature/protein_vector_d', num2str(dim_prot), '.txt'], Y, '\t');


function matches_refined = refine_matches(...
    part, model, part_ind, model_ind, C_init, options)

F = part_ind;
G = model_ind;

k = options.k;

W = zeros(k);
for i=1:k
    for j=1:k
        slope = 1;
        direction = [1 slope];
        direction = direction./norm(direction);
        W(i,j) = exp(-0.03*sqrt(i.^2 + j.^2))*norm(cross([direction 0], [i,j, 0]-[1 1 0]));
    end
end
d=ones(1,k);
D = repmat(d,k,1);

mu1 = 1e-2; % diagonal mask
mu2 = 1e1; % orthogonality

for iter=1:options.refine_iters

    A = part.evecs'*part.S*F;
    B = model.evecs'*model.S*G;

    manifold = euclideanfactory(k,k);
    problem = {};

    problem.M = manifold;

    problem.cost = @(C) (...
        sum(sum((C*A-B).^2).^0.5) + ...
        mu1 * norm(C.*W,'fro')^2 + ...
        mu2 * (norm(C'*C,'fro')^2 - sum(diag(C'*C).^2) + sum((diag(C'*C) - d').^2) ));

    problem.egrad = @(C) (...
        norm_21_gradient(C,A,B) + ...
        mu1 * 2 * C.*W.*W + ...
        mu2 * 4*(C*C'*C - C.*D ));

    options.verbosity = 2;
%     options.maxiter = 5e3;
%     C_refined = conjugategradient(problem, C_init, options);
    options.maxiter = 3e2;
    C_refined = trustregions(problem, C_init, options);

%     figure,colormap(bluewhitered)
%     subplot(121),imagesc(C_init),colorbar,axis image
%     subplot(122),imagesc(C_refined),colorbar,axis image

    [matches_refined, ~] = flann_search(...
        model.evecs', ...
        C_refined*part.evecs', ...
        1, struct());

%     [matches_init, ~] = flann_search(...
%         model.evecs', ...
%         C_init*part.evecs', ...
%         1, struct());

%     colors = create_colormap(model,model);
%     figure
%     subplot(231), colormap(colors), plot_scalar_map(model, 1:model.n), axis off, view([0 90]), freeze_colors
%     subplot(232), colormap(colors(matches_init,:)), plot_scalar_map(part, 1:part.n), axis off, view([0 90]), freeze_colors
%     subplot(233), colormap(colors(matches_refined,:)), plot_scalar_map(part, 1:part.n), axis off, view([0 90])
%     subplot(234), colormap(colors), plot_scalar_map(model, 1:model.n), axis off, view([-180 -90]), freeze_colors
%     subplot(235), colormap(colors(matches_init,:)), plot_scalar_map(part, 1:part.n), axis off, view([-180 -90]), freeze_colors
%     subplot(236), colormap(colors(matches_refined,:)), plot_scalar_map(part, 1:part.n), axis off, view([-180 -90])

    C_init = C_refined;

    fps = fps_euclidean(part.VERT, 1e3, randi(part.n));
    F = sparse(fps, 1:length(fps), 1, part.n, length(fps));
    G = sparse(matches_refined(fps), 1:length(fps), 1, model.n, length(fps));

end

end


% lssep;
% separate close local minimizers
% and maybe add a few global points
%

nsep=0;

while nsep<nmin,
  % find intervals where the monotonicity behavior of both
  % adjacent intervals is opposite
  down=[flist(2:s)<flist(1:s-1)];
  sep= ( [1,1,down] & [0,up,0] & [down,1,1] );
  sep= sep | ( [1,1,up] & [0,down,0] & [up,1,1] );
  ind=find(sep);
  if isempty(ind), break; end;

  aa=0.5*(alist(ind)+alist(ind-1));	% interval midpoints
  if length(aa)>nloc,
    % select nloc best interval midpoints
    ff=min(flist(ind),flist(ind-1));
    [ff,ind]=sort(ff);
    aa=aa(ind(1:nloc));
  end;
  for alp=aa,
    if prt>2, disp(['separate minimizer at ',num2str(alp)]); end;
    % new function value
    falp=feval(func,data,x+alp*p);
    alist=[alist,alp];flist=[flist,falp];
    nsep=nsep+1;
    if nsep>=nmin, break; end;
  end;
  lssort;
end;

% instead of unnecessary separation, add some global points
for times=1:nmin-nsep,
  lsnew;			% extrapolation or split
end;


function [result_features]=back_find_low_node_para(result_dir,nSubj,k_times,nROI,w,cross_val,ttest_p,midw_lasso)

% This function aims to find features used in the classification, suitable
% for the SR,SLR,SGR,GSR,WSR,WSGR,SSGSR network construction method. And it is also
% suitable for the LOOCV or the 10-fold cross validation. The found
% features can be applied on the visualization software to present the
% important brain regions or links.
% Input:
%         result_dir: the directory you want to store all the result files;
%         nSubj: number of subjects;
%         k_times: times of 10-fold cross validation;
%         nROI: number of ROIs
%         w: weight of each selected features;
%         cross_val: loocv or 10-fold;
%         ttest_pm,midw_lasso: the feature selection indexes of ttest or
%         lasso;
%
% Output:
%        result_features: cell array, consisting of the averaged weight and occurrence of the features;

% Written by Zhen Zhou, zzstefan@email.unc.edu
% IDEA lab, https://www.med.unc.edu/bric/ideagroup
% Department of Radiology and BRIC, University of North Carolina at Chapel Hill

% clear all
% load SR_10_fold_middle.mat;
% load SR_loocv_middle.mat;
% cross_val='loocv';
% ttest_p=feature_index_ttest;
% midw_lasso=feature_index_lasso;
fprintf('Begin contributing feature identification\n');
if strcmpi(cross_val,'10-fold')
    for i=1:size(ttest_p,1)
        for j=1:size(ttest_p,2)
            tmp=find(ttest_p{i,j}<0.05);
            tmp_b{i,j}=find(midw_lasso{i,j});
            index=tmp(tmp_b{i,j});
            for k=1:length(index)
                [first{i,j,k}(1),first{i,j,k}(2)]=find_elements(nROI,index(k));
            end
        end
    end
elseif strcmpi(cross_val,'loocv')
    for i=1:length(ttest_p)
        tmp=find(ttest_p{i}<0.05);
        tmp_b{i}=find(midw_lasso{i});
        index=tmp(tmp_b{i});
        for k=1:length(index)
            [first{i,k}(1),first{i,k}(2)]=find_elements(nROI,index(k));
        end
    end
end

%first=cellfun(@(x) x',first,'UniformOutput',false);
temp=first(:);

[a1,b,c]=unique(cellfun(@char,temp,'un',0));
lo=histc(c,1:max(c));
loo=lo(:)>1;
out=[temp(b(loo)),num2cell(lo(loo))];
out(1,:)=[];

All_link=out(find(cell2mat(out(:,2))>0),1);%find all links which exists in any one  LOOCV fold
if strcmpi(cross_val,'10-fold')
    for j=1:length(All_link)
        weight=[];
        temp_index=cell2mat(cellfun(@(x)isequal(x,All_link{j}),first,'un',0));
        ind=find(temp_index);
        [A,B,C]=ind2sub(size(temp_index),ind);
        for k=1:length(A)
            weight=[weight,w{A(k),B(k)}(C(k))];
        end
        all_weight(j)=mean(weight);
    end
elseif strcmpi(cross_val,'loocv')
    for j=1:length(All_link)
        weight=[];
        temp_index=cell2mat(cellfun(@(x)isequal(x,All_link{j}),first,'un',0));
        [A,B]=find(temp_index);
        for k=1:length(A)
            weight=[weight,w{A(k)}(B(k))];
        end
        all_weight(j)=mean(weight);
    end
end

matrix_1=zeros(nROI,nROI);
matrix_2=zeros(nROI,nROI);
for m=1:size(out,1)
    matrix_1(out{m,1}(1),out{m,1}(2))=all_weight(m);
    matrix_1(out{m,1}(2),out{m,1}(1))=all_weight(m);
    matrix_2(out{m,1}(1),out{m,1}(2))=out{m,2};
    matrix_2(out{m,1}(2),out{m,1}(1))=out{m,2};
end
result_features{1}=matrix_1;

if strcmpi(cross_val,'loocv')
    matrix_2=matrix_2/nSubj;
elseif strcmpi(cross_val,'10-fold')
    matrix_2=matrix_2/(10*k_times);
end
result_features{2}=matrix_2;

figure('visible','off');
subplot(1,2,1);
imagesc(matrix_1);
colormap jet
colorbar
axis square
xlabel('ROI');
ylabel('ROI');
title('Averaged weight');

subplot(1,2,2);
imagesc(matrix_2);
colormap jet
colorbar
axis square
xlabel('ROI');
ylabel('ROI');
title('Normalized occurence');
print(gcf,'-r1000','-dtiff',char(strcat(result_dir,'/result_features_weigthAndOccurence.tiff')));

fprintf('End contributing feature identification\n');


function obj = createRaster(obj, varargin)
% CREATERASTER Create raster from point cloud.

% Input parsing ----------------------------------------------------------------

validRasterValue = {'average' 'linear' 'mask' 'plane'};

p = inputParser;
p.addParameter('CellSize'     , 1        , @(x) isnumeric(x) && x>0);
p.addParameter('RasterValue'  , 'average', @(x) any(strcmpi(x, validRasterValue)));
p.addParameter('SearchRadius' , 3        , @(x) isnumeric(x) && x>0); % for 'RasterValue' 'average' and 'plane'
p.parse(varargin{:});
p = p.Results;

% Start ------------------------------------------------------------------------

procHierarchy = {'POINTCLOUD' 'RASTER'};
msg('S', procHierarchy);
msg('I', procHierarchy, sprintf('Point cloud label = ''%s''', obj.label));
msg('I', procHierarchy, sprintf('IN: RasterValue = ''%s''', p.RasterValue));
msg('V', p.CellSize, 'IN: CellSize', 'Prec', 2);
if any(strcmpi(p.RasterValue, {'average' 'plane'}))
    msg('V', p.SearchRadius, 'IN: SearchRadius', 'Prec', 2);
end

% Create query points ----------------------------------------------------------

% Origin (lower left point) of points
lim.min = min(obj.X(obj.act,[1 2]));
% Round origin (raster maps have coincident cell centers if mod(100, p.CellSize) == 0)
lim.min = (floor(lim.min/100))*100;

% Find raster cells in which points lie (starts with 0/0 at lower left corner (o))
% +-----+-----+-----+
% + 1/0 | 1/1 | 1/2 |
% +-----+-----+-----+
% + 0/0 | 0/1 | 0/2 |
% o-----+-----+-----+
rowCol = [floor((obj.X(obj.act,1)-lim.min(1))/p.CellSize) ...
          floor((obj.X(obj.act,2)-lim.min(2))/p.CellSize)];

% Remove multiple points
rowCol = unique(rowCol, 'rows');

% Transformation of indices to coordinate system ('query points')
xq = lim.min(1)+p.CellSize/2+rowCol(:,1)*p.CellSize;
yq = lim.min(2)+p.CellSize/2+rowCol(:,2)*p.CellSize;

% Assign RasterValue -----------------------------------------------------------

% Moving average
if strcmpi(p.RasterValue, 'average')
    idxAct = find(obj.act);
    ns = createns(obj.X(idxAct,[1 2]));
    idxSearchRadius = ns.rangesearch([xq yq], p.SearchRadius);
    zq = cellfun(@(x) mean(obj.X(idxAct(x),3)), idxSearchRadius);
end

% Linear interpolation
if strcmpi(p.RasterValue, 'linear')
    F = scatteredInterpolant(obj.X(obj.act,1), obj.X(obj.act,2), obj.X(obj.act,3), 'linear', 'none');
    zq = F(xq, yq);
end

% Mask
if strcmpi(p.RasterValue, 'Mask')
    zq = 1;
end

% Moving planes
if strcmpi(p.RasterValue, 'plane')
    idxAct = find(obj.act);
    msg('S', {procHierarchy{:} 'BUILD 2D KD-TREE'});
    ns = createns(obj.X(idxAct,[1 2]));
    msg('E', {procHierarchy{:} 'BUILD 2D KD-TREE'});
    msg('S', {procHierarchy{:} 'NNSEARCH'});
    idxSearchRadius = ns.rangesearch([xq yq], p.SearchRadius);
    msg('E', {procHierarchy{:} 'NNSEARCH'});

    msg('S', {procHierarchy{:} 'PLANE INTERPOLATION'});
    for c = 1:numel(xq)

        x = obj.X(idxAct(idxSearchRadius{c}),1);
        y = obj.X(idxAct(idxSearchRadius{c}),2);
        z = obj.X(idxAct(idxSearchRadius{c}),3);

        xm = mean(x);
        ym = mean(y);
        zm = mean(z);

        C = cov([x-xm, y-ym, z-zm]);
        [V, ~] = eig(C);
        n = V(:,1);

        if numel(n) ~= 3
            zq(c) = NaN;
        else
            zq(c) = zm - (n(1)*(xq(c)-xm) + n(2)*(yq(c)-ym)) / n(3);
        end

    end
    msg('E', {procHierarchy{:} 'PLANE INTERPOLATION'});

end

% Create GeoTiff ---------------------------------------------------------------

% Size of data array
sizeA = max(rowCol)-min(rowCol)+1;

% World matrix
W = [p.CellSize           0 min(xq)
              0 -p.CellSize max(yq)];

% Create spatialref.MapRasterReference object for GeoTiff
R = maprasterref(W, [sizeA(2) sizeA(1)]); % cols -> x, rows -> y

% Initialize data array with noData values
A = NaN(sizeA);

% Linear indices
idxLin = sub2ind(size(A), rowCol(:,1)-min(rowCol(:,1))+1, ...
                          rowCol(:,2)-min(rowCol(:,2))+1);

% Set data values
A(idxLin) = zq;

% Transform A, so that element 1,1 is upper, left corner (min(xq), max(yq))
A = flipud(A');

% Raster reduction point
if strcmpi(p.RasterValue, 'mask')
    RedPoi = [obj.redPoi(1) obj.redPoi(2) 0]; % no height reduction
else
    RedPoi = obj.redPoi;
end

% Add grid object to pointCloud object
obj.raster = raster({A R}, ...
                    obj.label, ...
                    'RedPoi', RedPoi);

% End --------------------------------------------------------------------------

msg('E', procHierarchy);

% 4Debug -----------------------------------------------------------------------

% save2('n:\Dropbox\Matlab\Scripts\2013_05\testgrid.xyz', [xq yq zeros(numel(xq),1)], '%.3f %.3f %.3f\n');

end


function [A, b, x, ProbInfo] = PRblurdefocus(varargin)
% PRblurdefocus Image deblurring problem with a defocus point spread function
%
% [A, b, x, ProbInfo] = PRblurdefocus
% [A, b, x, ProbInfo] = PRblurdefocus(n)
% [A, b, x, ProbInfo] = PRblurdefocus(n, options)
% [A, b, x, ProbInfo] = PRblurdefocus(options)
%
% Input:
%  n      -  size of the image. Can be either a scalar n (in this case
%            the size is n x n) or a vector [nrow, ncol] (in this case the
%            size is (nrow x ncol).
%            Default: n = 256.
%  options - Structure containing the following optional fields:
%    trueImage  : test image of size n, of type numeric, 2-D only,
%                 or character string indicating
%                 'pattern1'  : geometrical image
%                 'pattern2'  : geometrical image
%                 'ppower'    : random image with patterns of nonzero pixels
%                 'smooth'    : very smooth image
%                 'dot2'      : two small Gaussian shaped dots, e.g., a
%                               binary star
%                 'dotk'      : n/2 small Gaussian shaped dots, e.g., stars
%                               (placement is random, reset using rng(0))
%                 'satellite' : satellite test image
%                 'hst'       : image of the Hubble space telescope
%                 Default: 'hst'.
%                 This image is then stored in the output vector x.
%    BlurLevel  : If choosing one of the built-in PSFs, this sets the
%                 severity of the blur to one of the following:
%                 'mild'
%                 'medium'
%                 'severe'
%                 Default is 'medium'
%    BC         : Specify boundary condition:
%                 'zero'
%                 'periodic'
%                 'reflective' (or 'neumann' or 'reflexive')
%                 Default: 'reflective'
%                 Note that in this case an extended (or padded) test image
%                 is blurred using 'zero' boundary conditions, and then the
%                 central subimage of size n is extracted from the exact and
%                 the blurred image. No inverse crime is committed,
%                 i.e., A*x ~= b.
%    CommitCrime: To get an exact system Ax = b (i.e., commit the inverse
%                 crime), set this to:
%                 'on'
%                 Default is 'off' (do not commit the inverse crime).
%
% Output:
%  A        - blurring matrix (psfMatrix class)
%  b        - blurred vector (i.e., blurred image with stacked columns)
%  x        - image vector, i.e., exact (unknown) image with stacked columns
%  ProbInfo - structure whose fields contain information about problem:
%               problemType : kind of test problem generated
%                              (in this case: 'deblurring')
%                xType       : solution type (in this case 'image2D')
%                bType       : data type (in this case 'image2D')
%                xSize       : size of image x
%                bSize       : size of image b
%                psf         : point spread function
%
% See also: PRblur, PRblurgauss, PRblurmotion, PRblurrotation,
% PRblurshake, PRblurspeckle, PRdiffusion, PRinvinterp2, PRnmr,
% PRseismic, PRspherical, PRtomo, PRnoise, PRshowb, PRshowx, fspecial

% Silvia Gazzola, University of Bath
% Per Christian Hansen, Technical University of Denmark
% James G. Nagy, Emory University
% April, 2018.

% This file is part of the IR Tools package and is distributed under the
% 3-Clause BSD License. A separate license file should be provided as part
% of the package.

% Set default values for options.
defaultopt = struct('trueImage', 'hst', 'BlurLevel', 'medium', ...
    'BC', 'reflective', 'CommitCrime', 'off');

% If input is 'defaults,' return the default options in X
if nargin == 1 && nargout <= 1 && strcmp(varargin,'defaults')
    A = defaultopt;
    return;
end

% Check for acceptable number of optional input arguments
switch length(varargin)
    case 0
        n = []; options = [];
    case 1
        if isa(varargin{1}, 'double')
            n = varargin{1}; options = [];
        else
            n = []; options = varargin{1};
        end
    case 2
        if isa(varargin{1}, 'double')
            n = varargin{1}; options = varargin{2};
        else
            n = varargin{2}; options = varargin{1};
        end
    otherwise
        error('Too many input parameters')
end

if isempty(options)
    options = defaultopt;
end

options = PRset(defaultopt, options);
options = PRset(options, 'PSF', 'defocus');
[A, b, x, ProbInfo] = PRblur(n, options);


function [Hkt, cx, cy, Wxk] = loglikGaPreadparamWfix(x,qqq)
% [Hkt, cx, cy, Wxk] = loglikGaPreadparam(varargin);

sigpsf = qqq{2};  %std deviation of the PSF gaussian approx
peval =  qqq{5}; %parameters
% Hkt_linear=x(1:end-peval.ncomp*2); % intensities
% cx=x(end-peval.ncomp*2+1:end-peval.ncomp); %x-coordinates of the centers
% cy=x(end-peval.ncomp+1:end); % y-coordinates of the centers
% Hkt_linear=qqq{6}; % intensities
Hkt_linear=x; % intensities
cx= qqq{6};
cy= qqq{7};

sigpsf_vec=repmat(sigpsf,peval.ncomp,1); %all psfs same sigma

% this is anoying as it depends when the simulation was performed/... grr
cxy_vec=[cx'+1, cy'+1]; %different notation of the dip_image/new version
% cxy_vec=[cx'+0.5, cy'+0.5]; %different notation of the dip_image/old version
a_vec=1./(sigpsf_vec.^2*2*pi); % all normalised to 1

Hkt=reshape(Hkt_linear, peval.ncomp, peval.nt);
% generate PSFs from given parameters:
Wxkpix=gauss2dmultislice([peval.nx, peval.ny, peval.ncomp], cxy_vec, sigpsf_vec, a_vec);
Wxkpix=normalizePSF(Wxkpix); %normalize PSFs to 1
Wxk=reshape(Wxkpix,peval.nx*peval.ny, peval.ncomp);
end

function Wnorm=normalizePSF(W)
sw=size(W);
if numel(sw)<3 %if ncomp=1...
    sw(3) = 1;
end
Wr=reshape(W, sw(1)*sw(2),sw(3));
q=squeeze(sum(Wr,1));
Wrnorm=Wr./repmat(q,sw(1)*sw(2),1);
Wnorm=reshape(Wrnorm,sw(1), sw(2), sw(3));
end