classdef anisotropicdiffusion < TTeMPS_op_laplace
    % Class for anisotropic diffusion operator with tridiagonal diffusion matrix
    %
    %       [ 1 a 0     ...0 ]
    %       [ a 1 a 0    ..0 ]
    %   D = [ 0 a 1 a 0  ..0 ]
    %       [  ..   .. . .   ]
    %       [ 0 ... .. 0 a 1 ]
    %
    %

    %   TTeMPS Toolbox.
    %   Michael Steinlechner, 2013-2016
    %   Questions and contact: michael.steinlechner@epfl.ch
    %   BSD 2-clause license, see LICENSE.txt

    properties
        L
        D
        % precomputed spectral decomp of 1D Laplace:

    end

    methods

        function A = update_properties( A );

            A.rank = [1,  3*ones(1, length(A.U)-1), 1];  % the TT rank is always three for such Laplace-like tensors
            size_col_ = cellfun( @(y) size(y,1), A.U);
            A.size_col = size_col_ ./ (A.rank(1:end-1).*A.rank(2:end));
            A.size_row = cellfun( @(y) size(y,2), A.U);
            A.order = length( A.size_row );
        end
    end

    methods( Access = public )

        function A = anisotropicdiffusion( n, d, alpha )

            if ~exist('alpha', 'var')
                alpha = 0.25;
            end

            one = ones(n,1);
            q = linspace( -10, 10, n)';
            h = abs(q(2) - q(1));
            L = -spdiags( [one, -2*one, one], [-1 0 1], n, n) / (h^2);

            % superclass constructor
            A = A@TTeMPS_op_laplace( L, d );
            % precompute eigenvalue information and exponential for use in local
            A = initialize_precond( A );
            % preconditioner:
            A.L = L;

			[A.V_L, A.E_L] = eig(full(A.L));
            A.E_L = diag(A.E_L);

            A.D = spdiags( [-one,one], [-1,1], n, n ) / (2*h);
            I = speye( n, n );

            e1 = sparse( 1, 1, 1, 3, 1 );
            e2 = sparse( 2, 1, 1, 3, 1 );
            e3 = sparse( 3, 1, 1, 3, 1 );

            l_mid = sparse( 3, 1, 1, 9, 1 );                % e_3
            b_mid = sparse( 6, 1, 1, 9, 1 );                % e_6
            m_mid = sparse( [1;9], [1;1], [1;1], 9, 1 );    % e_1 + e_9
            c_mid = sparse( 2, 1, 1, 9, 1 );                % e_2

            A.U = cell( 1, d );
            A.U{1} = kron( A.L, e1 ) + kron( 2*alpha*A.D, e2 ) + kron( I, e3);
            A_mid = kron( A.L, l_mid ) + kron( 2*alpha*A.D, b_mid ) + kron( I, m_mid) + kron( A.D, c_mid );
            for i=2:d-1
                A.U{i} = A_mid;
            end
            A.U{d} = kron( I, e1 ) + kron( A.D, e2 ) + kron( A.L, e3);

            A = update_properties( A );

        end

        function expB = constr_precond_inner( A, X, mu )

            n = size(A.L, 1);
            sz = [X.rank(mu), X.size(mu), X.rank(mu+1)]

            B1 = zeros( X.rank(mu) );
            % calculate B1 part:
            for i = 1:mu-1
                % apply L to the i'th core
                tmp = X;
                Xi = matricize( tmp.U{i}, 2 );
                Xi = A.L*Xi;
                tmp.U{i} = tensorize( Xi, 2, [X.rank(i), n, X.rank(i+1)] );
                B1 = B1 + innerprod( X, tmp, 'LR', mu-1);
            end

            B3 = zeros( X.rank(mu+1) );
            % calculate B3 part:
            for i = mu+1:A.order
                tmp = X;
                Xi = matricize( tmp.U{i}, 2 );
                Xi = A.L*Xi;
                tmp.U{i} = tensorize( Xi, 2, [X.rank(i), n, X.rank(i+1)] );
                B3 = B3 + innerprod( X, tmp, 'RL', mu+1);
            end

            [V1,e1] = eig(B1);
            e1 = diag(e1);
            [V3,e3] = eig(B3);
            e3 = diag(e3);

            lmin = min(e1) + min(A.E_L) + min(e3);
            lmax = max(e1) + max(A.E_L) + max(e3);

            R = lmax/lmin

            [omega, alpha] = load_coefficients( R );

            k = 3;
            omega = omega/lmin;
            alpha = alpha/lmin;

            expB = cell(3,k);

            for i = 1:k
                expB{1,i} = omega(i) * V1*diag( exp( -alpha(i)*e1 ))*V1';    % include omega in first part
                expB{2,i} = A.V_L*diag( exp( -alpha(i)*A.E_L ))*A.V_L';
                expB{3,i} = V3*diag( exp( -alpha(i)*e3 ))*V3';
            end
        end

        function expB = constr_precond_outer( A, X, mu1, mu2 )

            n = size(A.L, 1);

            B1 = zeros( X.rank(mu1) );
            % calculate B1 part:
            for i = 1:mu1-1
                % apply L to the i'th core
                tmp = X;
                Xi = matricize( tmp.U{i}, 2 );
                Xi = A.L*Xi;
                tmp.U{i} = tensorize( Xi, 2, [X.rank(i), n, X.rank(i+1)] );
                B1 = B1 + innerprod( X, tmp, 'LR', mu1-1);
            end

            B3 = zeros( X.rank(mu2+1) );
            % calculate B3 part:
            for i = mu2+1:A.order
                tmp = X;
                Xi = matricize( tmp.U{i}, 2 );
                Xi = A.L*Xi;
                tmp.U{i} = tensorize( Xi, 2, [X.rank(i), n, X.rank(i+1)] );
                B3 = B3 + innerprod( X, tmp, 'RL', mu2+1);
            end

            [V1,e1] = eig(B1);
            e1 = diag(e1);
            [V3,e3] = eig(B3);
            e3 = diag(e3);

            lmin = min(e1) + 2*min(A.E_L) + min(e3);
            lmax = max(e1) + 2*max(A.E_L) + max(e3);

            R = lmax/lmin

            [omega, alpha] = load_coefficients( R );

            k = 3;
            omega = omega/lmin;
            alpha = alpha/lmin;

            expB = cell(4,k);

            for i = 1:k
                expB{1,i} = omega(i) * V1*diag( exp( -alpha(i)*e1 ))*V1';    % include omega in first part
                expB{2,i} = A.V_L*diag( exp( -alpha(i)*A.E_L ))*A.V_L';
                expB{3,i} = A.V_L*diag( exp( -alpha(i)*A.E_L ))*A.V_L';
                expB{4,i} = V3*diag( exp( -alpha(i)*e3 ))*V3';
            end
        end

        function P = constr_precond( A, k )

            d = A.order;

            lmin = d*min(A.E_L);
            lmax = d*max(A.E_L);

            R = lmax/lmin

            %  http://www.mis.mpg.de/scicomp/EXP_SUM/1_x/1_xk07_2E2
            %  0.0133615547183825570028305575534521842940   {omega[1]}
            %  0.0429728469424360175410925952177443321034   {omega[2]}
            %  0.1143029399081515586560726591147663100401   {omega[3]}
            %  0.2838881266934189482611071431161775535656   {omega[4]}
            %  0.6622322841999484042811198458711174907876   {omega[5]}
            %  1.4847175320092703810050463464342840325116   {omega[6]}
            %  3.4859753729916252771962870138366952232900   {omega[7]}
            %  0.0050213411684266507485648978019454613531   {alpha[1]}
            %  0.0312546410994290844202411500801774835168   {alpha[2]}
            %  0.1045970270084145620410366606112262388706   {alpha[3]}
            %  0.2920522758702768403556507270657505159761   {alpha[4]}
            %  0.7407504784499061527671195936939341208927   {alpha[5]}
            %  1.7609744335543204401530945069076494746696   {alpha[6]}
            %  4.0759036969145123916954953635638503328664   {alpha[7]}

            if k == 3
                [omega, alpha] = load_coefficients( R );

            elseif k == 7
                omega = [0.0133615547183825570028305575534521842940 0.0429728469424360175410925952177443321034 0.1143029399081515586560726591147663100401,...
                         0.2838881266934189482611071431161775535656 0.6622322841999484042811198458711174907876 1.4847175320092703810050463464342840325116,...
                         3.4859753729916252771962870138366952232900];
                alpha = [0.0050213411684266507485648978019454613531 0.0312546410994290844202411500801774835168 0.1045970270084145620410366606112262388706,...
                         0.2920522758702768403556507270657505159761 0.7407504784499061527671195936939341208927 1.7609744335543204401530945069076494746696,...
                         4.0759036969145123916954953635638503328664];
            else
                error('Unknown rank specified. Choose either k=3 or k=7');
            end

            omega = omega/lmin;
            alpha = alpha/lmin;

            % careful: all cores assumed to be of same size
            E = reshape( expm( -alpha(1) * A.L), [1, A.size_row(2), A.size_col(2), 1]);
            P = omega(1)*TTeMPS_op( repmat({E},1,d) );
            for i = 2:k
                E = reshape( expm( -alpha(i) * A.L), [1, A.size_row(2), A.size_col(2), 1]);
                P = P + omega(i)*TTeMPS_op( repmat({E},1,d) );
            end

        end

    end

end


function cvx_optval = lambda_sum_largest( x, k )

%LAMBDA_SUM_LARGEST   Internal cvx version.

narginchk(2,2);
n = size( x, 1 );
if ndims( x ) > 2 || n ~= size( x, 2 ), %#ok

    error( 'First input must be a square matrix.' );

elseif ~isnumeric( k ) || numel( k ) ~= 1 || ~isreal( k ),

    error( 'Second input must be a constant real scalar.' );

elseif cvx_isconstant( x ),

    cvx_optval = cvx( lambda_max( cvx_constant( x ), k ) );

elseif ~cvx_isaffine( x ),

    error( 'Discipliend convex programming error:\n    LAMBDA_SUM_LARGEST is convex and nonmonotonic, so its input must be affine.' );

elseif k <= 0,

    cvx_optval = 0;

elseif k >= size( x, 1 ),

    cvx_optval = trace( x );

else

    S = [];
    cvx_begin
        variable S(n,n) symmetric
        S == semidefinite(n); %#ok
        minimize( k * lambda_max( x - S ) + trace( S ) );
    cvx_end

end

% Copyright 2005-2016 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function bario = calcBario(DSO3,ori,tetra)
% compute bariocentric coordinates for an orientation
%
% Input
%  DSO3  -
%  ori   - @orientation
%  tetra - indices to tetrahegons
%
% Output
%  bario - bariocentric coordinates
%

% compute vertices
vertices = DSO3.subSet(DSO3.tetra(tetra,:));

% translate everything such that ori becomes the identity
vertices = repmat(inv(ori(:)),1,4) .* reshape(vertices,[],4);

% and project to fundamental region
vertices = reshape(project2FundamentalRegion(vertices),[],4);

% project to three dimensional space
xyz = vertices.Rodrigues;

% compute bariocentic coordinates
bario = calcZeroBario(xyz(:,1),xyz(:,2),xyz(:,3),xyz(:,4));

end


function [tmpl, cord] = sample_pos(frame, p, out_size, random, num_scale)
    %% sample positive samples with different scales and translations

    len = (p(3)+p(4)) / 2;
    for iter = 1 : 2
        for i = 1 : num_scale
            context_scale = 0.5 * (i);
            translationX = randi(floor(len / 2 * context_scale)) - 1;
            translationY = randi(floor(len / 2 * context_scale)) - 1;
            if randi(2) == 1
                translationX = -translationX;
            end
            if randi(2) == 1
                translationY = -translationY;
            end
            if random == 0
                translationX = 0;
                translationY = 0;
            end
            p_sample = [p(1) + translationX, p(2) + translationY, p(3) + len * context_scale, p(4) + len * context_scale];
            crop_img = im_crop(frame, p_sample);
            scale_height = size(crop_img,1) / out_size;
            scale_width = size(crop_img,2) / out_size;
            center_x = (1+out_size) / 2 - translationX / scale_width;
            center_y = (1+out_size) / 2 - translationY / scale_height;
            x1 = floor(center_x - (p(3) / 2 ) / scale_width);
            y1 = floor(center_y - (p(4) / 2 ) / scale_height);
            x2 = ceil(center_x + (p(3) / 2 ) / scale_width);
            y2 = ceil(center_y + (p(4) / 2 ) / scale_height);
            %minus 1 for numeric reasons
            cord(iter * num_scale - num_scale + i, :) = [x1, y1, x2, y2] - 1 ;
            crop_img = imresize(crop_img, [out_size, out_size], 'Antialiasing', false);
            tmpl(:,iter * num_scale - num_scale + i) = crop_img(:);
        end
    end
end


function [Xhat,XXstar] = computeStateResponses(XX,ehmm,Gamma,states)

regressed = sum(ehmm.train.Sind==1,1)>0;
K = size(Gamma,2); np = size(XX,2); ndim = size(ehmm.train.S,1);

if nargin < 4 || isempty(states), states = 1:K+1; end

Gamma = [Gamma prod(1-Gamma,2) ];
Gamma = rdiv(Gamma,sum(Gamma,2));

XXstar = zeros(size(XX,1),np * length(states));
ind = false((K+1)*np,1);

for ik = 1:length(states)
    k = states(ik);
    XXstar(:,(1:np) + (ik-1)*np) = bsxfun(@times, XX, Gamma(:,k));
    ind( (1:np) + (k-1)*np) = true;
end

Xhat = zeros(size(XX,1),ndim);
for n = find(regressed)
    Xhat(:,n) = XXstar * ehmm.state_shared(n).Mu_W(ind);
end

end


function v = setdiff(v1,v2,varargin)
% remove vectors v2 from a set of vectors v1
%
% Syntax
%   v = setdiff(v1,v2)
%   v = setdiff(v1,v2,'antipodal')
%
% Input
%  v1, v2 - @vector3d
%
% Output
%  v - vector3d
%
% Options
%  antipodal - include antipodal symmetry
%

isEqu = isnull(dot_outer(v1,v2,varargin{:}) - reshape(sqrt(dot(v1,v1)),[],1) * reshape(sqrt(dot(v2,v2)),1,[]),1e-3);

v = v1.subSet(~any(isEqu,2));


function f = neglogsigmoid_fh(w)
% This is a factory for a function handle to an MV2DF, which represents
% the vectorization of the logsigmoid function. The mapping is, in
% MATLAB-style code:
%
%   y = log(sigmoid(w)) = log(1./1+exp(-w)) = -log(1+exp(-w))
%
% Inputs:
%   m: the number of inputs to each individual logsumexp calculation.
%   direction: 1 sums down columns, or 2 sums accross rows.
%   w: optional, if ssupplied
%
% Outputs:
%   f: a function handle to the MV2DF described above.
%
% see: MV2DF_API_DEFINITION.readme

if nargin==0
    test_this();
    return;
end

f = vectorized_function([],@(x)F0(x));

if exist('w','var') && ~isempty(w)
    f = f(w);
end

end

function [y,f1] = F0(x)
logp1 = -neglogsigmoid(x);
logp2 = -neglogsigmoid(-x);
y = -logp1;
f1 = @() F1(logp1,logp2);
end

function [J,f2,linear] = F1(logp1,logp2)
linear = false;
J = -exp(logp2);
f2 = @(dx) F2(dx,logp1,logp2);
end

function h = F2(dx,logp1,logp2)
h = dx.*exp(logp1+logp2);
end

function test_this()
n = 10;
f = neglogsigmoid_fh([]);
x = randn(n,1);
test_MV2DF(f,x);
end


%% Script: Illustrate use of FanChart function

clear all; clc;

% Generate artifical history and forecasts
T=18; % number of historical observations
H=12; % number of forecast periods
fore=randn(H,100);
for h=1:H
   fore(h,:)=(fore(h,:).*h)./200;
end
hist=.1.*randn(T,1);

% Call fan chart function
FanChart(fore,hist,'Jun2009',6);


function [Yest, results] = lle(Y, ssub, rr, ACTIVE_PX)
%% approximate the background with locally-linear embedding
%% inputs:
%   Y: d1*d2*T 3D matrix, video data
%   rr: scalar, average neuron size
%   ssub: spatial downsampling factor
%   ACTIVE_PX:  indicators of pixels to be approximated

%% outputs:
%   Yest: d1*d2*T 3D matrix, reconstructed video data
%   results: struct variable {weights, ssub}
%       weights: d1*d2 cell, each element is a 2*J matrix. Row 1 has the indice of the
%       ring neighbors and row 2 has the corresponding weights.
%       ssub:    scalar, spatial downsampling factor

%% Author: Pengcheng Zhou, Carnegie Mellon University,2016

%% input arguments
[d1, d2, T] = size(Y);

% center the fluorescence intensity by its mean
Ymean = mean(Y, 3);
Y = Y - bsxfun(@minus, Ymean, ones(1, 1, T));

% average neuron size
if ~exist('rr', 'var')|| isempty(rr)
    rr = 15;
end
% spatial downsampling
if ~exist('ssub', 'var') || isempty(ssub)
    ssub = 1;
end

%downsample the data
if ssub>1
    Y = imresize(Y, 1./ssub);
    [d1s, d2s, ~] = size(Y);
    rr = round(rr/ssub)+1;
else
    d1s = d1;
    d2s = d2;
end

% pixels to be approximated
if exist('ACTIVE_PX', 'var') && ~isempty(ACTIVE_PX)
    ACTIVE_PX = reshape(double(ACTIVE_PX), d1, d2);
    ACTIVE_PX = (imresize(ACTIVE_PX, 1/ssub)>0);
    ind_px = find(ACTIVE_PX(:));  % pixels to be approxiamted
else
    ind_px = (1:(d1s*d2s));
end

%% determine neibours of each pixel
c_shift = (-rr:rr);
r_shift = round(sqrt(rr^2-c_shift.^2));
c_shift = [c_shift, c_shift(2:end)];
r_shift = [-r_shift, r_shift(2:end)];

[csub, rsub] = meshgrid(1:d2s, 1:d1s);
csub = reshape(csub, [], 1);
rsub = reshape(rsub, [], 1);
csub = bsxfun(@plus, csub, c_shift);
rsub = bsxfun(@plus, rsub, r_shift);
% remove neighbors that are out of boundary
ind = or(or(csub<1, csub>d2s), or(rsub<1, rsub>d1s));
csub(ind) = nan;
rsub(ind) = nan;
% options = optimoptions('lsqlin','Algorithm','active-set', 'Display', 'none');

%% run approximation
 gamma = 0.001; % add regularization
Y = reshape(Y, d1s*d2s, []);
Yest = zeros(size(Y));
weights = cell(d1s, d2s);
for m=1:length(ind_px)
    px = ind_px(m);
    ind_nhood = sub2ind([d1s,d2s], rsub(px, :), csub(px, :));
    ind_nhood(isnan(ind_nhood)) = [];
    J = length(ind_nhood);

    G = bsxfun(@minus, Y(ind_nhood, 1:3:end), Y(px, 1:3:end));
    w = (G*G'+gamma*sum(G(:).^2)*eye(J))\ones(length(ind_nhood), 1);
    w = w/sum(w);
%     w = lsqlin(Y(ind_nhood,:)', Y(px,:)', [], [], ones(1, J), ...
%         1, ones(J, 1)*0, ones(J, 1)*3/J, [], options); % weights have box constraints [min_w, max_w]
    Yest(px, :) = w'*Y(ind_nhood, :);
    weights{px} = [ind_nhood; w'];
end
results.weights = weights;
results.ssub = ssub;

ind = 1:(d1s*d2s);
ind(ind_px) = [];
if ~isempty(ind)
    temp = imfilter(Y, ones(3, 3)/9, 'replicate');
    Yest(ind, :) = temp(ind, :); % without approximation
end
Yest = reshape(Yest, d1s, d2s, []);

    %% return the result
if ssub>1 %up sampling
    Yest = imresize(Yest, [d1, d2]);
end

clear Y;
Ybaseline = Ymean - median(Yest, 3);
Yest = bsxfun(@plus, Yest, Ybaseline);


function [model,delta] = getPredictors(stimList, HRF,nsess,varargin)
% function [model,delta] = getPredictorsOddEven(stimList, HRF, nsess,[downsample factor])
%
% Build predictors and delta functions, given a condition function or delta
% function and either a convolution matrix or vector.
%
% IMPORTANT: The intercept in this function is added.
%
% stimList: condition function or delta function
% HRF:      hemodynamic response function, or convolution matrix (columns
%           are HRF)
% [downsamp]    takes every nth element of the design matrix
%
%
%inputs:
% 1     a col. vector of stimulus conditions OR a delta function matrix
% 2	    an HRF vector sampled at the frequency of the stimulus vector, OR
%	    a convolution matrix H
% 3     Number of sessions (must be a divisor of the stimList length)
%
%outputs:
% 1     a n x 2 matrix of regressors (cols) for each condition
% 2     a n x k delta matrix with onsets
%
% Tor Wager, last modified 2/22/04 to center predictors
%            modified to optionally take H convolution matrix as input
%            in place of HRF vector.  See convmtx.m (Buracas,mseq toolbox)
%
% stimList can be condition function e.g., [1 3 2 4 3 2 1]' or
% delta matrix (n x k), n samples and k conditions, e.g., [1 0 0 0 1 0 1]'
%
% Resampling: the default N in matlab resample has built-in antialiasing,
% but may not be good for fmri designs!  The appropriate downsampling
% is expected to be res*TR (res is units of samples/s), but we use 0
% because the model will depend on the analysis method used, and this is
% the most veridical approach.  With N = 0, every ith sample is used, where
% i is the downsampling factor you input.  Popular choices are 16*TR (for
% onsets2delta.m), using the SPM default res of 16.
% Delta is NOT resampled.
%
% example: TR = 2, 16 samples per second in hi-res delta dhr
% [tmp,d] = downsample_delta(dhr,16*2); X=getPredictors(d,hrf);

model = [];

% build odd/even session list
div = size(stimList,1) ./ nsess;
if div ~= round(div), error('The stimList length must be divisible by nsess!'),end
tmp = repmat([ones(div,1); 2*ones(div,1)],ceil(nsess./2),1);
odde = tmp(1:size(stimList,1));

if min(size(stimList)) > 1 % delta matrix

    delta = stimList;
    odde = repmat(odde,1,size(delta,2));
    delta = [delta delta];
    odde = [odde==1 odde==2];
    delta = delta .* odde;

    if min(size(HRF)) == 1
        for i = 1:size(delta,2)
            model(:,i) = conv(delta(:,i), HRF);
        end
    end

else

    for i = 1:max(stimList(:,1)) % condition function

        delta(:,i) = (stimList == i) & odde==1;
        d2(:,i) = (stimList == i) & odde==2;

        if min(size(HRF)) == 1
            model(:,i) = conv(delta(:,i), HRF);
            model2(:,i) = conv(d2(:,i), HRF);
        end

    end

    delta = [delta d2];
    model = [model model2];
end

if min(size(HRF)) > 1 % convolution matrix
    model = HRF * delta;
end

model = model(1:size(stimList,1),:);      	% eliminate extra values

% downsample, if necessary
if length(varargin) > 1
    model = model(1:varargin{1}:end,:); % equivalent to resample(X,1,varargin{1},0)
end

model = model - repmat(mean(model),size(model,1),1);    % center predictors

return


%==========================================================================
%
%   Active contour with Chen-Vese Method
%   for image segementation
%
%   Implemented by Yue Wu (yue.wu@tufts.edu)
%   Tufts University
%   Feb 2009
%   http://sites.google.com/site/rexstribeofimageprocessing/
%
%   all rights reserved
%   Last update 02/26/2009
%--------------------------------------------------------------------------
%   Usage of varibles:
%   input:
%       I           = any gray/double/RGB input image
%       mask        = initial mask, either customerlized or built-in
%       num_iter    = total number of iterations
%       mu          = weight of length term
%       method      = submethods pick from ('chen','vector','multiphase')
%
%   Types of built-in mask functions
%       'small'     = create a small circular mask
%       'medium'    = create a medium circular mask
%       'large'     = create a large circular mask
%       'whole'     = create a mask with holes around
%       'whole+small' = create a two layer mask with one layer small
%                       circular mask and the other layer with holes around
%                       (only work for method 'multiphase')
%   Types of methods
%       'chen'      = general CV method
%       'vector'    = CV method for vector image
%       'multiphase'= CV method for multiphase (2 phases applied here)
%
%   output:
%       phi0        = updated level set function
%
%--------------------------------------------------------------------------
%
% Description: This code implements the paper: "Active Contours Without
% Edges" by Chan and Vese for method 'chen', the paper:"Active Contours Without
% Edges for vector image" by Chan and Vese for method 'vector', and the paper
% "A Multiphase Level Set Framework for Image Segmentation Using the
% Mumford and Shah Model" by Chan and Vese.
%
%--------------------------------------------------------------------------
% Deomo: Please see HELP file for details
%==========================================================================

function [seg, phi0]= chenvese(I,mask,num_iter,mu,method)

%%
%-- Default settings
%   length term mu = 0.2 and default method = 'chan'
if(~exist('mu','var'))
    mu=0.2;
end

if(~exist('method','var'))
    method = 'chan';
end

%-- End default settings

%%
%-- Initializations on input image I and mask
%  resize original image
row=size(I,1);
col=size(I,2);
s = 200./min(size(I,1),size(I,2)); % resize scale
if s<1
    I = imresize(I,s);
end

%   auto mask settings
if ischar(mask)
    switch lower (mask)
        case 'small'
            mask = maskcircle2(I,'small');
        case 'medium'
            mask = maskcircle2(I,'medium');
        case 'large'
            mask = maskcircle2(I,'large');
        case 'whole'
            mask = maskcircle2(I,'whole');
            %mask = init_mask(I,30);
        case 'whole+small'
            m1 = maskcircle2(I,'whole');
            m2 = maskcircle2(I,'small');
            mask = zeros(size(I,1),size(I,2),2);
            mask(:,:,1) = m1(:,:,1);
            mask(:,:,2) = m2(:,:,2);
        otherwise
            error('unrecognized mask shape name (MASK).');
    end
else
    if s<1
        mask = imresize(mask,s);
    end
    if size(mask,1)>size(I,1) || size(mask,2)>size(I,2)
        error('dimensions of mask unmathch those of the image.')
    end
    switch lower(method)
        case 'multiphase'
            if  (size(mask,3) == 1)
                error('multiphase requires two masks but only gets one.')
            end
    end

end

switch lower(method)
    case 'chan'
        if size(I,3)== 3
            P = rgb2gray(uint8(I));
            P = double(P);
        elseif size(I,3) == 2
            P = 0.5.*(double(I(:,:,1))+double(I(:,:,2)));
        else
            P = double(I);
        end
        layer = 1;

    case 'vector'
        s = 200./min(size(I,1),size(I,2)); % resize scale
        I = imresize(I,s);
        mask = imresize(mask,s);
        layer = size(I,3);
        if layer == 1
            display('only one image component for vector image')
        end
        P = double(I);

    case 'multiphase'
        layer = size(I,3);
        if size(I,1)*size(I,2)>200^2
            s = 200./min(size(I,1),size(I,2)); % resize scale
            I = imresize(I,s);
            mask = imresize(mask,s);
        end

        P = double(I);  %P store the original image
    otherwise
        error('!invalid method')
end
%-- End Initializations on input image I and mask

%%
%--   Core function
switch lower(method)
    case {'chan','vector'}
        %-- SDF
        %   Get the distance map of the initial mask

        mask = mask(:,:,1);
        phi0 = bwdist(mask)-bwdist(1-mask)+im2double(mask)-.5;
        %   initial force, set to eps to avoid division by zeros
        force = eps;
        %-- End Initialization

        %-- Display settings
        figure();
        subplot(2,2,1); imshow(I); title('Input Image');
        subplot(2,2,2); contour(flipud(phi0), [0 0], 'r','LineWidth',1); title('initial contour');
        subplot(2,2,3); title('Segmentation');
        %-- End Display original image and mask

        %-- Main loop
        for n=1:num_iter
            inidx = find(phi0>=0); % frontground index
            outidx = find(phi0<0); % background index
            force_image = 0; % initial image force for each layer
            for i=1:layer
                L = im2double(P(:,:,i)); % get one image component
                c1 = sum(sum(L.*Heaviside(phi0)))/(length(inidx)+eps); % average inside of Phi0
                c2 = sum(sum(L.*(1-Heaviside(phi0))))/(length(outidx)+eps); % verage outside of Phi0
                force_image=-(L-c1).^2+(L-c2).^2+force_image;
                % sum Image Force on all components (used for vector image)
                % if 'chan' is applied, this loop become one sigle code as a
                % result of layer = 1
            end

            % calculate the external force of the image
            force = mu*kappa(phi0)./max(max(abs(kappa(phi0))))+1/layer.*force_image;

            % normalized the force
            force = force./(max(max(abs(force))));

            % get stepsize dt
            dt=0.5;

            % get parameters for checking whether to stop
            old = phi0;
            phi0 = phi0+dt.*force;
            new = phi0;
            indicator = checkstop(old,new,dt);
%             if n==1
%                 figure;
%                 showphi(I,phi0,n);
%             end
%

            % intermediate output

            if(mod(n,20) == 0)
                showphi(I,phi0,n);
            end;
            if indicator % decide to stop or continue
                showphi(I,phi0,n);

                %make mask from SDF
                seg = phi0<=0; %-- Get mask from levelset
                if s<1
                    seg = imresize(seg,[row col]);
                end

                subplot(2,2,4); imshow(seg); title('Global Region-Based Segmentation');

                return;
            end
        end;
        showphi(I,phi0,n);

        %make mask from SDF
        seg = phi0<=0; %-- Get mask from levelset

        subplot(2,2,4); imshow(seg); title('Global Region-Based Segmentation');
    case 'multiphase'
        %-- Initializations
        %   Get the distance map of the initial masks
        mask1 = mask(:,:,1);
        mask2 = mask(:,:,2);
        phi1=bwdist(mask1)-bwdist(1-mask1)+im2double(mask1)-.5;%Get phi1 from the initial mask 1
        phi2=bwdist(mask2)-bwdist(1-mask2)+im2double(mask2)-.5;%Get phi1 from the initial mask 2

        %-- Display settings
        figure();
        subplot(2,2,1);
        if layer ~= 1
            imshow(I); title('Input Image');
        else
            imagesc(P); axis image; colormap(gray);title('Input Image');
        end
        subplot(2,2,2);
        hold on
        contour(flipud(mask1),[0,0],'r','LineWidth',2.5);
        contour(flipud(mask1),[0,0],'x','LineWidth',1);
        contour(flipud(mask2),[0,0],'g','LineWidth',2.5);
        contour(flipud(mask2),[0,0],'x','LineWidth',1);
        title('initial contour');
        hold off
        subplot(2,2,3); title('Segmentation');
        %-- End display settings

        %Main loop
        for n=1:num_iter
            %-- Narrow band for each phase
            nb1 = find(phi1<1.2 & phi1>=-1.2); %narrow band of phi1
            inidx1 = find(phi1>=0); %phi1 frontground index
            outidx1 = find(phi1<0); %phi1 background index

            nb2 = find(phi2<1.2 & phi2>=-1.2); %narrow band of phi2
            inidx2 = find(phi2>=0); %phi2 frontground index
            outidx2 = find(phi2<0); %phi2 background index
            %-- End initiliazaions on narrow band

            %-- Mean calculations for different partitions
            %c11 = mean (phi1>0 & phi2>0)
            %c12 = mean (phi1>0 & phi2<0)
            %c21 = mean (phi1<0 & phi2>0)
            %c22 = mean (phi1<0 & phi2<0)

            cc11 = intersect(inidx1,inidx2); %index belong to (phi1>0 & phi2>0)
            cc12 = intersect(inidx1,outidx2); %index belong to (phi1>0 & phi2<0)
            cc21 = intersect(outidx1,inidx2); %index belong to (phi1<0 & phi2>0)
            cc22 = intersect(outidx1,outidx2); %index belong to (phi1<0 & phi2<0)

            f_image11 = 0;
            f_image12 = 0;
            f_image21 = 0;
            f_image22 = 0; % initial image force for each layer

            for i=1:layer
                L = im2double(P(:,:,i)); % get one image component

                if isempty(cc11)
                    c11 = eps;
                else
                    c11 = mean(L(cc11));
                end

                if isempty(cc12)
                    c12 = eps;
                else
                    c12 = mean(L(cc12));
                end

                if isempty(cc21)
                    c21 = eps;
                else
                    c21 = mean(L(cc21));
                end

                if isempty(cc22)
                    c22 = eps;
                else
                    c22 = mean(L(cc22));
                end

                %-- End mean calculation

                %-- Force calculation and normalization
                % force on each partition

                f_image11=(L-c11).^2.*Heaviside(phi1).*Heaviside(phi2)+f_image11;
                f_image12=(L-c12).^2.*Heaviside(phi1).*(1-Heaviside(phi2))+f_image12;
                f_image21=(L-c21).^2.*(1-Heaviside(phi1)).*Heaviside(phi2)+f_image21;
                f_image22=(L-c22).^2.*(1-Heaviside(phi1)).*(1-Heaviside(phi2))+f_image22;
            end

            % sum Image Force on all components (used for vector image)
            % if 'chan' is applied, this loop become one sigle code as a
            % result of layer = 1

            % calculate the external force of the image

            % curvature on phi1
            curvature1 = mu*kappa(phi1);
            curvature1 = curvature1(nb1);
            % image force on phi1
            fim1 = 1/layer.*(-f_image11(nb1)+f_image21(nb1)-f_image12(nb1)+f_image22(nb1));
            fim1 = fim1./max(abs(fim1)+eps);

            % curvature on phi2
            curvature2 = mu*kappa(phi2);
            curvature2 = curvature2(nb2);
            % image force on phi2
            fim2 = 1/layer.*(-f_image11(nb2)+f_image12(nb2)-f_image21(nb2)+f_image22(nb2));
            fim2 = fim2./max(abs(fim2)+eps);

            % force on phi1 and phi2
            force1 = curvature1+fim1;
            force2 = curvature2+fim2;
            %-- End force calculation

            % detal t
            dt = 1.5;

            old(:,:,1) = phi1;
            old(:,:,2) = phi2;

            %update of phi1 and phi2
            phi1(nb1) = phi1(nb1)+dt.*force1;
            phi2(nb2) = phi2(nb2)+dt.*force2;

            new(:,:,1) = phi1;
            new(:,:,2) = phi2;

            indicator = checkstop(old,new,dt);

            if indicator
                showphi(I, new, n);
                %make mask from SDF
                seg11 = (phi1>0 & phi2>0); %-- Get mask from levelset
                seg12 = (phi1>0 & phi2<0);
                seg21 = (phi1<0 & phi2>0);
                seg22 = (phi1<0 & phi2<0);

                se = strel('disk',1);
                aa1 = imerode(seg11,se);
                aa2 = imerode(seg12,se);
                aa3 = imerode(seg21,se);
                aa4 = imerode(seg22,se);
                seg = aa1+2*aa2+3*aa3+4*aa4;
                if s<1
                    seg = imresize(seg,[row col]);
                end
                subplot(2,2,4); imagesc(seg);axis image;title('Global Region-Based Segmentation');

                return
            end
            % re-initializations
            phi1 = reinitialization(phi1, 0.6);%sussman(phi1, 0.6);%
            phi2 = reinitialization(phi2, 0.6);%sussman(phi2,0.6);

            %intermediate output
            if(mod(n,20) == 0)
                phi(:,:,1) = phi1;
                phi(:,:,2) = phi2;
                showphi(I, phi, n);
            end;
        end;
        phi(:,:,1) = phi1;
        phi(:,:,2) = phi2;
        showphi(I, phi, n);
        %make mask from SDF
        seg11 = (phi1>0 & phi2>0); %-- Get mask from levelset
        seg12 = (phi1>0 & phi2<0);
        seg21 = (phi1<0 & phi2>0);
        seg22 = (phi1<0 & phi2<0);

        se = strel('disk',1);
        aa1 = imerode(seg11,se);
        aa2 = imerode(seg12,se);
        aa3 = imerode(seg21,se);
        aa4 = imerode(seg22,se);
        seg = aa1+2*aa2+3*aa3+4*aa4;
        %seg = bwlabel(seg);
        subplot(2,2,4); imagesc(seg);axis image;title('Global Region-Based Segmentation');

end
if s<1
    seg = imresize(seg,[row col]);
end
end


function rVectECEF = getrVectEcefFromLatLongAlt(lat, long, alt, bodyInfo)
    r = bodyInfo.radius + alt;

    x = r.*cos(lat).*cos(long);
    y = r.*cos(lat).*sin(long);
    z = r.*sin(lat);

    rVectECEF = [x(:)';y(:)';z(:)'];
end


% op_freqshift.m
% Jamie Near, McGill University 2014.
%
% USAGE:
% out=op_freqshift(in,f);
%
% DESCRIPTION:
% Apply a frequency shift to the input spectrum by 'f' Hz.
%
% INPUTS:
% in     = input data in matlab structure format.
% f      = frequency shift to apply (in Hz).
%
% OUTPUTS:
% out    = Output following frequency shift.

function out=op_freqshift(in,f);

% if in.dims.coils>0
%     error('ERROR:  Can not operate on data with multilple coils!  ABORTING!!')
% end
% if in.dims.averages>0
%     error('ERROR:  Can not operate on data with multiple averages!  ABORTING!!');
% end
% if in.dims.subSpecs>0
%     error('ERROR:  Can not operate on data with multiple Subspecs!  ABORTING!!');
% end

t=repmat(in.t',[1 in.sz(2:end)]);

fids=in.fids.*exp(-1i*t*f*2*pi);

%re-calculate Specs using fft
specs=fftshift(ifft(fids,[],in.dims.t),in.dims.t);

%plot(in1.ppm,combinedSpecs);

%FILLING IN DATA STRUCTURES
out=in;
out.fids=fids;
out.specs=specs;

%FILLING IN THE FLAGS
out.flags=in.flags;


function varargout = sp_gen(varargin)
%
%
% sp_gen is a GUI for generating Spirals.
%
%A. Select the plane that will be parallel to the spiral
%B. Select the type of spiral:
%You can choose from Archimedean,Logarithmic,Fermat,Hyperbolic,Lituus,Spherical and Polynomial Spirals.
%you can see the equations used for the selected spiral, and change the parameters.
%C. Select the normal component of the spiral. Note that this feature is
%not available for the spherical spirals.
%D. Add thickness to the spiral. This will provide volume and will give you
%the possibility to generate surfaces. Note that this feature is not
%available for the polynomial spirals.
%E. Generate and export spiral variables to the workspace.
%
%%%%%%BUGS
%
%I am aware of the surface bug. This is clearly visible in the spherical
%spiral, but also in the other spirals if you play with the normal
%component.This is caused because the surface twists around itself. I
%provide a partial correction, in function 'generate_thickness' in the 'if'
%statement in lines 1128-1130.
%
% If anybody comes with a solution to this or finds other bugs, please post
% on File EXchange.
%
%
%Created by Katelouzos Ioannis.

gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @sp_gen_OpeningFcn, ...
                   'gui_OutputFcn',  @sp_gen_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before sp_gen is made visible.
function sp_gen_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to sp_gen (see VARARGIN)

% Choose default command line output for sp_gen
handles.output = hObject;
handles.plane=[0 0 1];
vr=[[1 0;-1 0;0 1;0 -1]*null([0 0 1])';0 0 0];
fc=[1 5 3;2 5 3;2 5 4;1 4 5];
fv.vertices=vr;
fv.faces=fc;
handles.fv=fv;
handles.xpl=zeros(3,3);
handles.ypl=zeros(3,3);
handles.zpl=zeros(3,3);
handles.surface=0;
handles.scloud=0;
handles.cloud=0;
handles.cerchi=[0;0;0];
handles.oct=zeros(8,3);
handles.spiral=zeros(3,1);
% Update handles structure
guidata(hObject, handles);

% UIWAIT makes sp_gen wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = sp_gen_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

% --- Executes on selection change in spiral_type.
function spiral_type_Callback(hObject, eventdata, handles)
% hObject    handle to spiral_type (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
val=(get(hObject,'Value'));
zz=(get(handles.zcomp,'Value'));
switch val
    case 1
        set(handles.text15,'String','r = a + b * theta');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','on');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 2
        set(handles.text15,'String','r = a * exp( b * theta )');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','on');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 3
        set(handles.text15,'String','r = +- sqrt( theta )');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','off');
        set(handles.beta,'Enable','off');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 4
        set(handles.text15,'String','r = a / theta');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','off');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 5
        set(handles.text15,'String','r = sqrt( 1 / theta )');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','off');
        set(handles.beta,'Enable','off');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');

        end
    case 6
        set(handles.text15,'String','x=cos(t)cos(c) y=sin(t)cos(c)  z=-sin(c) c=atan(a*t)');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','off');
        set(handles.zcomp,'Enable','off');
        set(handles.c,'Enable','off');
        set(handles.d,'Enable','off');
        set(handles.e,'Enable','off');
        set(handles.f,'Enable','off');
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
    otherwise
        set(handles.text15,'String','curvature = f(curve length) k=a*s^4+b*s^3+g*s^2+h*s+i');
        set(handles.g,'Enable','on');
        set(handles.h,'Enable','on');
        set(handles.i,'Enable','on');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','on');
        set(handles.zcomp,'Enable','on');
        set(handles.thick,'Enable','off');
        set(handles.surfface,'Enable','off');
        if zz~=1
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
        end

end
guidata(hObject, handles);
% Hints: contents = get(hObject,'String') returns spiral_type contents as cell array
%        contents{get(hObject,'Value')} returns selected item from spiral_type

% --- Executes during object creation, after setting all properties.
function spiral_type_CreateFcn(hObject, eventdata, handles)
% hObject    handle to spiral_type (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function Xeq_Callback(hObject, eventdata, handles)
% hObject    handle to Xeq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
pl=handles.plane;
x=str2double(get(hObject,'String'));
if pl(3)==0 && pl(2)==0, x=1;
set(hObject,'String','1');
end
handles.plane(1)=x;
handles=refresh_plane(handles);
guidata(hObject, handles);
% Hints: get(hObject,'String') returns contents of Xeq as text
%        str2double(get(hObject,'String')) returns contents of Xeq as a double

% --- Executes during object creation, after setting all properties.
function Xeq_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Xeq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
handles.plane(1)=str2double(get(hObject,'String'));
guidata(hObject, handles);
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function Yeq_Callback(hObject, eventdata, handles)
% hObject    handle to Yeq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
pl=handles.plane;
x=str2double(get(hObject,'String'));
if pl(1)==0 && pl(3)==0, x=1;
set(hObject,'String','1');
end
handles.plane(2)=x;
handles=refresh_plane(handles);
guidata(hObject, handles);
% Hints: get(hObject,'String') returns contents of Yeq as text
%        str2double(get(hObject,'String')) returns contents of Yeq as a double

% --- Executes during object creation, after setting all properties.
function Yeq_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Yeq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
handles.plane(2)=str2double(get(hObject,'String'));
guidata(hObject, handles);
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function Zeq_Callback(hObject, eventdata, handles)
% hObject    handle to Zeq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of Zeq as text
%        str2double(get(hObject,'String')) returns contents of Zeq as a double
pl=handles.plane;
x=str2double(get(hObject,'String'));
if pl(1)==0 && pl(2)==0, x=1;
set(hObject,'String','1');
end
handles.plane(3)=x;
handles=refresh_plane(handles);
guidata(hObject, handles);

% --- Executes during object creation, after setting all properties.
function Zeq_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Zeq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
handles.plane(3)=str2double(get(hObject,'String'));
guidata(hObject, handles);
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in show_plane.
function show_plane_Callback(hObject, eventdata, handles)
% hObject    handle to show_plane (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles=refresh_plane(handles);
guidata(hObject, handles);
% Hint: get(hObject,'Value') returns toggle state of show_plane

function thick_Callback(hObject, eventdata, handles)
% hObject    handle to thick (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
x=str2double(get(hObject,'String'));
if x<0;
set(hObject,'String','0');
end
guidata(hObject, handles);
% Hints: get(hObject,'String') returns contents of thick as text
%        str2double(get(hObject,'String')) returns contents of thick as a double

% --- Executes during object creation, after setting all properties.
function thick_CreateFcn(hObject, eventdata, handles)
% hObject    handle to thick (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function lengt_Callback(hObject, eventdata, handles)
% hObject    handle to lengt (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of lengt as text
%        str2double(get(hObject,'String')) returns contents of lengt as a double

x=str2double(get(hObject,'String'));
pr=str2double(get(handles.precision,'String'));
if x<=2*pr;
pr=str2double(get(handles.precision,'String'));
set(hObject,'String',sprintf('%g', pr*2));
end
guidata(hObject, handles);

% --- Executes during object creation, after setting all properties.
function lengt_CreateFcn(hObject, eventdata, handles)
% hObject    handle to lengt (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function h=refresh_plane(handles)
cpos=get(handles.axes1,'CameraPosition');
pl=handles.plane;
 vr=[[1 0;-1 0;0 1;0 -1;1 1; 1 -1;-1 -1;-1 1]*null(pl)';0 0 0];
fv.vertices=vr;
xpl=[vr(8,1) vr(3,1) vr(5,1);vr(2,1) vr(9,1) vr(1,1);vr(7,1) vr(4,1) vr(6,1)];
ypl=[vr(8,2) vr(3,2) vr(5,2);vr(2,2) vr(9,2) vr(1,2);vr(7,2) vr(4,2) vr(6,2)];
zpl=[vr(8,3) vr(3,3) vr(5,3);vr(2,3) vr(9,3) vr(1,3);vr(7,3) vr(4,3) vr(6,3)];
handles.xpl=xpl;
handles.ypl=ypl;
handles.zpl=zpl;
spir=handles.spiral;

if isempty(find(spir));
    mm=1;
else mm=max(max(abs(spir)));
end
xpl=xpl.*mm/2;
ypl=ypl.*mm/2;
zpl=zpl.*mm/2;
plot3(spir(1,:),spir(2,:),spir(3,:));
hold on;
if get(handles.show_plane,'Value')==1
    mesh(xpl,ypl,zpl,'FaceAlpha',0.1,'FaceColor','g','EdgeAlpha',0.5,'EdgeColor','k');
end
set(handles.axes1,'CameraPosition',cpos);
set(handles.axes1,'DataAspectRatio',[1 1 1]);
set(get(handles.axes1,'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(handles.axes1,'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(handles.axes1,'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
h=handles;

% --- Executes on button press in export_internal.
function export_internal_Callback(hObject, eventdata, handles)
% hObject    handle to export_internal (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
cloud=handles.cloud;
assignin('base','Spiral_IntCloud',cloud);

% --- Executes on button press in show_scloud.
function show_scloud_Callback(hObject, eventdata, handles)
% hObject    handle to show_scloud (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
set(handles.export_scloud,'BackgroundColor',[0 1 0]);
set(handles.export_scloud,'Enable','on');
H=figure(2);
title('Surface Cloud Ordinary','Color','b','FontWeight','bold');
oct=handles.oct;
hold on;
for it=1:length(oct(1,1,:))
    plot3(oct(:,1,it),oct(:,2,it),oct(:,3,it),'.');
end
set(get(H,'CurrentAxes'),'DataAspectRatio',[1 1 1]);
set(get(get(H,'CurrentAxes'),'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
H=figure(3);
title('Surface Cloud Random','Color','b','FontWeight','bold');
scloud=gen_scloud(handles,oct);
handles.scloud=scloud;
hold on;
plot3(scloud(:,1),scloud(:,2),scloud(:,3),'.');
set(get(H,'CurrentAxes'),'DataAspectRatio',[1 1 1]);
set(get(get(H,'CurrentAxes'),'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
guidata(hObject, handles);

% --- Executes on button press in show_surface.
function show_surface_Callback(hObject, eventdata, handles)
% hObject    handle to show_surface (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
set(handles.export_surface,'BackgroundColor',[0 1 0]);
set(handles.export_surface,'Enable','on');
H=figure(4);

oct=handles.oct;
C = permute(cat(1, oct, oct(1,:,:)),[3,1,2]);
xsurf=squeeze(C(:,:,1));
ysurf=squeeze(C(:,:,2));
zsurf=squeeze(C(:,:,3));
surface.x=xsurf;
surface.y=ysurf;
surface.z=zsurf;
handles.surface=surface;
mesh(xsurf,ysurf,zsurf,'FaceAlpha',0.1,'FaceColor','g','EdgeAlpha',0.5,'EdgeColor','k');
title('Surface','Color','b','FontWeight','bold');
set(get(H,'CurrentAxes'),'DataAspectRatio',[1 1 1]);
set(get(get(H,'CurrentAxes'),'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'ZLabel'),'String','Z','Color','r','FontWeight','bold');
guidata(hObject, handles);

% --- Executes on button press in show_internal.
function show_internal_Callback(hObject, eventdata, handles)
% hObject    handle to show_internal (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
set(handles.export_internal,'BackgroundColor',[0 1 0]);
set(handles.export_internal,'Enable','on');
H=figure(1);
title('Internal Cloud','Color','b','FontWeight','bold');
oct=handles.oct;

cloud=gen_cloud(handles,oct);
handles.cloud=cloud;
hold on;
plot3(cloud(:,1),cloud(:,2),cloud(:,3),'.');
set(get(H,'CurrentAxes'),'DataAspectRatio',[1 1 1]);
set(get(get(H,'CurrentAxes'),'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(get(H,'CurrentAxes'),'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
guidata(hObject, handles);

% --- Executes on button press in export_scloud.
function export_scloud_Callback(hObject, eventdata, handles)
% hObject    handle to export_scloud (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
oct=handles.oct;
scloud=handles.scloud;
B = permute(oct,[1 3 2]);
ou = reshape(B,length(oct(:,1,1))*size(oct,3),3);
assignin('base','Spiral_SurCloud_ord',ou);
assignin('base','Spiral_SurCloud_rand',scloud);

% --- Executes on button press in export_surface.
function export_surface_Callback(hObject, eventdata, handles)
% hObject    handle to export_surface (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
surface=handles.surface;
assignin('base','Spiral_Surface',surface);

% --- Executes on button press in export_line.
function export_line_Callback(hObject, eventdata, handles)
% hObject    handle to export_line (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
assignin('base','Spiral_line',handles.spiral);

% --- Executes on button press in gen_spiral.
function gen_spiral_Callback(hObject, eventdata, handles)
% hObject    handle to gen_spiral (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
cpos=get(handles.axes1,'CameraPosition');
stype=get(handles.spiral_type,'Value');
alpha=str2double(get(handles.alpha,'String'));
beta=str2double(get(handles.beta,'String'));
c=str2double(get(handles.c,'String'));
d=str2double(get(handles.d,'String'));
e=str2double(get(handles.e,'String'));
f=str2double(get(handles.f,'String'));
g=str2double(get(handles.g,'String'));
h=str2double(get(handles.h,'String'));
i=str2double(get(handles.i,'String'));
thick=str2double(get(handles.thick,'String'));
pr=str2double(get(handles.precision,'String'));
lengt=str2double(get(handles.lengt,'String'));
theta=0:pr:lengt*pi;
switch stype
    case 1
        r=alpha+beta*theta;
    case 2
        r=alpha*(exp(beta*theta));
    case 3
        r=sqrt(theta);
        r2=-r;
    case 4
        r=alpha./theta;
    case 5
        r=sqrt(1./theta);
    case 6
        t=-lengt:pr:lengt;
        c=atan(alpha*t);
        x=cos(t).*cos(c);
        y=sin(t).*cos(c);
        z=-sin(c);
        [theta,r]=cart2pol(x,y);
    otherwise
        if alpha>0
            l=sqrt(lengt);
            p=pr^2;
        else
            l=lengt;
            p=pr;
        end
        [x y]=curv2cart(alpha,beta,g,h,i,l,p,handles);
        [theta,r]=cart2pol(x,y);
end
zc=(get(handles.zcomp,'Value'));
if stype~=6
switch zc
    case 1
        z=zeros(1,length(theta));
    case 2
        z=c*r.^d+e*theta.^f;
    case 3
        z = c*sin(r.*d) + e*sin(theta.*f);
    case 4
        z = c*exp(d*r) + e*exp(f*theta);
    otherwise
        z = c*log(r).^d + e*log(theta).^f;
end
end
if stype==4 || stype==5
    theta=theta(end:-1:2);
    r=r(end:-1:2);
    z=z(end:-1:2);
end
[x,y]=pol2cart(theta,r);
spiral=[x;y;z];
if stype==3
    [x2,y2]=pol2cart(theta,r2);
    z2=-z;
    spiral=[fliplr(x2) x(2:end);fliplr(y2) y(2:end);fliplr(z2) z(2:end)];
end
pl=handles.plane;
rotate= vrrotvec([0 0 1],pl);
rm = vrrotvec2mat(rotate);
spir=rm*spiral;
nnn=sum(spir,1);
w=nnn==nnn;
w=find(w==0);
spir(:,w)=[];
handles.spiral=spir;
if ~isempty(find(spir))
    refresh_plane(handles);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   cerchiles generation
hold on;
if thick>0
    if stype==1 || stype==2 || stype ==6 ||stype==4 ||stype==5
        [cerchi oct]=generate_thickness(1,handles);
    elseif stype==3
        [cerchi oct]=generate_thickness(2,handles);
    else %stype==7
        cerchi=[0;0;0];
        oct=zeros(8,3);
    end
handles.cerchi=cerchi;
handles.oct=oct;
end
end
set(handles.axes1,'CameraPosition',cpos);
set(handles.axes1,'DataAspectRatio',[1 1 1]);
set(get(handles.axes1,'XLabel'),'String','X','Color','r','FontWeight','bold');
set(get(handles.axes1,'YLabel'),'String','Y','Color','r','FontWeight','bold');
set(get(handles.axes1,'ZLabel'),'String','Z','Color','r','FontWeight','bold');
hold off;
if stype ~= 7 && thick >0
set(handles.show_internal,'BackgroundColor',[0 1 0]);
set(handles.show_internal,'Enable','on');
set(handles.show_scloud,'BackgroundColor',[0 1 0]);
set(handles.show_scloud,'Enable','on');
set(handles.show_surface,'BackgroundColor',[0 1 0]);
set(handles.show_surface,'Enable','on');
set(handles.export_line,'BackgroundColor',[0 1 0]);
set(handles.export_line,'Enable','on');
set(handles.export_internal,'BackgroundColor',[1 0 0]);
set(handles.export_internal,'Enable','off');
set(handles.export_scloud,'BackgroundColor',[1 0 0]);
set(handles.export_scloud,'Enable','off');
set(handles.export_surface,'BackgroundColor',[1 0 0]);
set(handles.export_surface,'Enable','off');
else
    set(handles.show_internal,'BackgroundColor','r');
set(handles.show_internal,'Enable','off');
set(handles.show_scloud,'BackgroundColor','r');
set(handles.show_scloud,'Enable','off');
set(handles.show_surface,'BackgroundColor','r');
set(handles.show_surface,'Enable','off');
set(handles.export_line,'BackgroundColor',[0 1 0]);
set(handles.export_line,'Enable','on');
set(handles.export_internal,'BackgroundColor','r');
set(handles.export_internal,'Enable','off');
set(handles.export_scloud,'BackgroundColor','r');
set(handles.export_scloud,'Enable','off');
set(handles.export_surface,'BackgroundColor','r');
set(handles.export_surface,'Enable','off');
end
guidata(hObject, handles);

function alpha_Callback(hObject, eventdata, handles)
% hObject    handle to alpha (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of alpha as text
%        str2double(get(hObject,'String')) returns contents of alpha as a double

% --- Executes during object creation, after setting all properties.
function alpha_CreateFcn(hObject, eventdata, handles)
% hObject    handle to alpha (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function beta_Callback(hObject, eventdata, handles)
% hObject    handle to beta (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of beta as text
%        str2double(get(hObject,'String')) returns contents of beta as a double

% --- Executes during object creation, after setting all properties.
function beta_CreateFcn(hObject, eventdata, handles)
% hObject    handle to beta (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in zcomp.
function zcomp_Callback(hObject, eventdata, handles)
% hObject    handle to zcomp (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
val=(get(hObject,'Value'));
switch val
    case 1
        set(handles.text20,'String','z = 0');
        set(handles.c,'Enable','off');
        set(handles.d,'Enable','off');
        set(handles.e,'Enable','off');
        set(handles.f,'Enable','off');
    case 2
        set(handles.text20,'String','z = c*r^d + e*theta^f');
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
    case 3
        set(handles.text20,'String','z = c*sin(r*d) + e*sin(theta*f)');
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
    case 4
        set(handles.text20,'String','z = c*exp(d*r) + e*exp(f*theta)');
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
    otherwise
        set(handles.text20,'String','z = c*log(r)^d + e*log(theta)^f');
        set(handles.c,'Enable','on');
        set(handles.d,'Enable','on');
        set(handles.e,'Enable','on');
        set(handles.f,'Enable','on');
end
guidata(hObject, handles);
% Hints: contents = get(hObject,'String') returns zcomp contents as cell array
%        contents{get(hObject,'Value')} returns selected item from zcomp

% --- Executes during object creation, after setting all properties.
function zcomp_CreateFcn(hObject, eventdata, handles)
% hObject    handle to zcomp (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function e_Callback(hObject, eventdata, handles)
% hObject    handle to e (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of e as text
%        str2double(get(hObject,'String')) returns contents of e as a double

% --- Executes during object creation, after setting all properties.
function e_CreateFcn(hObject, eventdata, handles)
% hObject    handle to e (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function f_Callback(hObject, eventdata, handles)
% hObject    handle to f (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of f as text
%        str2double(get(hObject,'String')) returns contents of f as a double

% --- Executes during object creation, after setting all properties.
function f_CreateFcn(hObject, eventdata, handles)
% hObject    handle to f (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function c_Callback(hObject, eventdata, handles)
% hObject    handle to c (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of c as text
%        str2double(get(hObject,'String')) returns contents of c as a double

% --- Executes during object creation, after setting all properties.
function c_CreateFcn(hObject, eventdata, handles)
% hObject    handle to c (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function d_Callback(hObject, eventdata, handles)
% hObject    handle to d (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of d as text
%        str2double(get(hObject,'String')) returns contents of d as a double

% --- Executes during object creation, after setting all properties.
function d_CreateFcn(hObject, eventdata, handles)
% hObject    handle to d (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function g_Callback(hObject, eventdata, handles)
% hObject    handle to g (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of g as text
%        str2double(get(hObject,'String')) returns contents of g as a double

% --- Executes during object creation, after setting all properties.
function g_CreateFcn(hObject, eventdata, handles)
% hObject    handle to g (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function h_Callback(hObject, eventdata, handles)
% hObject    handle to h (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of h as text
%        str2double(get(hObject,'String')) returns contents of h as a double

% --- Executes during object creation, after setting all properties.
function h_CreateFcn(hObject, eventdata, handles)
% hObject    handle to h (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function i_Callback(hObject, eventdata, handles)
% hObject    handle to i (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of i as text
%        str2double(get(hObject,'String')) returns contents of i as a double

% --- Executes during object creation, after setting all properties.
function i_CreateFcn(hObject, eventdata, handles)
% hObject    handle to i (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function [xo yo]=curv2cart(a,b,c,d,e,l,p,handles)
set(handles.timebar_text,'Visible','on','String','Generating Spiral');
drawnow update
s=0:p:l;
s2=-s;
x1=zeros(1,length(s));
y1=zeros(1,length(s));
x2=zeros(1,length(s));
y2=zeros(1,length(s));
k=a*s.^4+b*s.^3+c*s.^2+d*s+e;
k2=a*s2.^4+b*s2.^3+c*s2.^2+d*s2+e;
x1(2)=s(2);
y1(2)=0;
x2(2)=s2(2);
y2(2)=0;
perc=(length(s)*2-4)/100;
ls=length(s)-2;
for i=3:(length(s))
    sss=sprintf('Genetaring Spiral...%3.1f %%', i/perc);
    set(handles.timebar_text,'String',sss);
    drawnow update
    dth=k(i)*s(2);
    cth=(x1(i-1)-x1(i-2))/norm([x1(i-1) y1(i-1)]-[x1(i-2) y1(i-2)]);
    sth=(y1(i-1)-y1(i-2))/norm([x1(i-1) y1(i-1)]-[x1(i-2) y1(i-2)]);
    if sth>=0
        scorr=1;
    else scorr=-1;
    end
    newth=dth+scorr*acos(cth);
    xx=cos(newth);
    yy=sin(newth);
    x1(i)=(xx*s(2))+x1(i-1);
    y1(i)=(yy*s(2))+y1(i-1);
end

for i=3:(length(s))
    sss=sprintf('Genetaring Spiral...%3.1f %%', (i+ls)/perc);
    set(handles.timebar_text,'String',sss);
    drawnow update
    dth=k2(i)*s2(2);
    cth=(x2(i-1)-x2(i-2))/norm([x2(i-1) y2(i-1)]-[x2(i-2) y2(i-2)]);
    sth=(y2(i-1)-y2(i-2))/norm([x2(i-1) y2(i-1)]-[x2(i-2) y2(i-2)]);
    if sth>=0
        scorr=1;
    else scorr=-1;
    end
    newth=dth+scorr*acos(cth);
    xx=cos(newth);
    yy=sin(newth);
    x2(i)=(xx*s(2))+x2(i-1);
    y2(i)=(yy*s(2))+y2(i-1);
end
set(handles.timebar_text,'Visible','off');
xo=[fliplr(x2) x1];
yo=[fliplr(y2) y1];

function precision_Callback(hObject, eventdata, handles)
% hObject    handle to precision (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
x=str2double(get(hObject,'String'));
l=str2double(get(handles.lengt,'String'));
if x<=0
    set(hObject,'String','0.1');
    x=0.1;
elseif x>1
    set(hObject,'String','1');
    x=1;
end
    if l<=2*x
        set(hObject,'String',sprintf('%g', l/2));
    end

guidata(hObject, handles);

% Hints: get(hObject,'String') returns contents of precision as text
%        str2double(get(hObject,'String')) returns contents of precision as a double

% --- Executes during object creation, after setting all properties.
function precision_CreateFcn(hObject, eventdata, handles)
% hObject    handle to precision (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in clear.
function clear_Callback(hObject, eventdata, handles)
% hObject    handle to clear (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
        set(handles.text20,'String','z = 0');
        set(handles.c,'Enable','off');
        set(handles.d,'Enable','off');
        set(handles.e,'Enable','off');
        set(handles.f,'Enable','off');
        set(handles.text15,'String','r = a + b * theta');
        set(handles.g,'Enable','off');
        set(handles.h,'Enable','off');
        set(handles.i,'Enable','off');
        set(handles.alpha,'Enable','on');
        set(handles.beta,'Enable','on');
        set(handles.zcomp,'Enable','on');
        set(handles.spiral_type,'Value',1);
        set(handles.zcomp,'Value',1);
        set(handles.thick,'Enable','on');
        set(handles.surfface,'Enable','on');
handles.plane=[0 0 1];
set(handles.Xeq,'String','0');
set(handles.Yeq,'String','0');
set(handles.Zeq,'String','1');
vr=[[1 0;-1 0;0 1;0 -1]*null([0 0 1])';0 0 0];
fc=[1 5 3;2 5 3;2 5 4;1 4 5];
fv.vertices=vr;
fv.faces=fc;
handles.fv=fv;
handles.cerchi=[0;0;0];
handles.oct=zeros(8,3);
handles.surface=0;
handles.scloud=0;
handles.cloud=0;
handles.spiral=zeros(3,1);
set(handles.show_internal,'BackgroundColor','r');
set(handles.show_internal,'Enable','off');
set(handles.show_scloud,'BackgroundColor','r');
set(handles.show_scloud,'Enable','off');
set(handles.show_surface,'BackgroundColor','r');
set(handles.show_surface,'Enable','off');
set(handles.export_line,'BackgroundColor','r');
set(handles.export_line,'Enable','off');
set(handles.export_internal,'BackgroundColor','r');
set(handles.export_internal,'Enable','off');
set(handles.export_scloud,'BackgroundColor','r');
set(handles.export_scloud,'Enable','off');
set(handles.export_surface,'BackgroundColor','r');
set(handles.export_surface,'Enable','off');
guidata(hObject, handles);
refresh_plane(handles);
guidata(hObject, handles);

function [cerchi oct]=generate_thickness(a,handles)
surfface=str2double(get(handles.surfface,'String'));
stype=get(handles.spiral_type,'Value');
thick=str2double(get(handles.thick,'String'));
spir=handles.spiral;
set(handles.timebar_text,'Visible','on','String','Generating Thickness');
drawnow update;
if a==1
cerchi=[[0;0;0] spir(:,2:end)-spir(:,1:end-1)];
start=2;
else cerchi=spir(:,2:(end+1)/2)-spir(:,1:(end+1)/2-1);
    start=1;
end
oct=zeros(surfface,3,length(cerchi));
perc=(length(cerchi)-1)/100;
    for it=start:length(cerchi)
        sss=sprintf('Genetaring Thickness...%3.1f %%', it/perc);
        set(handles.timebar_text,'String',sss);
        drawnow update;
        cerc=cerchi(:,it);
        mm=norm(cerc)*thick;
        nullity=(null(cerc'))';
        if dot(cerc,[1 0 0])>0
            nullity=[-1 0;0 1]*nullity;
        end
        vects=gen_polygon(handles,surfface,mm);
        piu=zeros(3,surfface);
        piu=bsxfun(@plus,piu,spir(:,it));
        oct(:,:,it)=vects*nullity+piu';
    end
if a==2
    oct(:,:,end)=oct(:,:,end)-vects*nullity/2;
    cerchi=[cerchi fliplr(-cerchi)];
    oct= cat(3, oct, flipdim(-oct,3));
end
if stype==6
    piu=zeros(3,surfface);
    piu=bsxfun(@plus,piu,spir(:,1));
    oct(:,:,1)=piu';
    piu=zeros(3,surfface);
    piu=bsxfun(@plus,piu,spir(:,end));
    oct(:,:,end)=piu';
end

for it=start:length(cerchi)
    plot3(oct(:,1,it),oct(:,2,it),oct(:,3,it));
end
set(handles.timebar_text,'Visible','off');

function surfface_Callback(hObject, eventdata, handles)
% hObject    handle to surfface (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of surfface as text
%        str2double(get(hObject,'String')) returns contents of surfface as a double
x=floor(str2double(get(hObject,'String')));
if x<4;
x=4;
end
sss=sprintf('%d', x);
set(hObject,'String',sss);
guidata(hObject, handles);

% --- Executes during object creation, after setting all properties.
function surfface_CreateFcn(hObject, eventdata, handles)
% hObject    handle to surfface (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function vects=gen_polygon(handles,surfface,mm)
div=0:2*pi/surfface:2*pi-2*pi/surfface;
vects=[cos(div')*mm sin(div')*mm];

function scloud=gen_scloud(handles,oct)
set(handles.timebar_text,'Visible','on','String','Generating Thickness');
drawnow update;
faces=length(oct(:,1,1))-1;
perc=(length(oct(1,1,:))-1)*faces/100;
oct=cat(1, oct, oct(1,:,:));
pl=1;
scloud=zeros(2*perc*100,3);
for slength=1:length(oct(1,1,:))-1
for polygon=1:faces
    it=(slength-1)*faces+polygon;
    sss=sprintf('Genetaring Surface Cloud...%3.1f %%', it/perc);
        set(handles.timebar_text,'String',sss);
        drawnow update;
p1=oct(polygon,:,slength);
p2=oct(polygon+1,:,slength);
p3=oct(polygon+1,:,slength+1);
p4=oct(polygon,:,slength+1);
p=[p1;p2;p3;p4];
[or,in]=min([norm(p1);norm(p2);norm(p3);norm(p4)]);
p=circshift(p,-in+1);
dx=p(2,:)-p(1,:);
dy=p(4,:)-p(1,:);
x1=p(1,:)/2+dx*rand;
y1=p(1,:)/2+dy*rand;
pp1=x1+y1;
x2=p(1,:)/2+dx*rand;
y2=p(1,:)/2+dy*rand;
pp2=x2+y2;
scloud(pl,:)=pp1;
pl=pl+1;
scloud(pl,:)=pp2;
pl=pl+1;
end
end

function cloud=gen_cloud(handles,oct)
set(handles.timebar_text,'Visible','on','String','Generating Internal Cloud');
drawnow update;
faces=length(oct(:,1,1));
perc=(length(oct(1,1,:)))*faces/100;
oct=cat(1, oct, oct(1,:,:));
pl=1;
j=2;    % j*faces is the number of points in every spital slice
pp=zeros(j*perc*100,3);

for slength=1:length(oct(1,1,:))-1
for polygon=1:faces-1
    it=(slength-1)*faces+polygon;
    sss=sprintf('Genetaring Internal Cloud...%3.1f %%', it/perc);
        set(handles.timebar_text,'String',sss);
        drawnow update;
    apenanti=mod(floor(faces/2)+polygon+1,faces);
    if apenanti==0,apenanti=faces;end
p1=oct(polygon+1,:,slength);
p2=oct(polygon,:,slength);
p3=oct(apenanti,:,slength);
p4=oct(apenanti,:,slength+1);
p5=oct(polygon+1,:,slength+1);
p6=oct(polygon,:,slength+1);
p=[p1;p2;p3;p4;p5;p6];

dy=p2-p1;
dz=p3-p1;
dx=p5-p1;

for k=1:j
dyp=dy*rand;
dxp=dx*rand;
dzn=norm(dy-dyp)*norm(dz)/norm(dy);
dzp=dz./norm(dz)*rand*dzn;
pp(pl,:)=p(1,:)+dzp+dxp+dyp;
pl=pl+1;
end
end
end
cloud=pp;


function [rc,fval,it] = ARfil(im,xm,rcinit,lagmax,p)

nobs = length(xm);

opties = optimset('Display','off','TolX',.001/sqrt(nobs),'TolFun',.0001);

[rc_tan,fval,exitflag,output]= fminunc('ARMA_MLfit',tan(.5*pi*rcinit),opties,im,xm,lagmax,p);
rc = 2/pi*atan(rc_tan);
it = output.iterations;


function [A,b,Aeq,beq] = row2gen(Ain,rl,ru)
%ROW2GEN Convert Linear A with Row Bounds to Linear Inequality & Equality Constraints
%   [A,b,Aeq,beq] = row2gen(A,rl,ru)

%   Copyright (C) 2012 Jonathan Currie (I2C2)

if(isempty(Ain))
    A = []; b = []; Aeq = []; beq = [];
    return;
elseif(isempty(ru))
    error('You must supply Ain, rl and ru!');
end
if(isempty(rl))
    rl = -Inf(size(ru)); %default
end
%Transpose as Required
if(size(rl,2) > 1)
    rl = rl';
end
if(size(ru,2) > 1)
    ru = ru';
end

%Indices
eq = rl == ru; neq = ~eq;
ile = isfinite(ru) & neq;
ige = isfinite(rl) & neq;

%Ineq
A = [ Ain(ile,:);
     -Ain(ige,:)];
b = [ ru(ile);
     -rl(ige)];
%Eq
if(any(eq))
    Aeq = Ain(eq,:); beq = ru(eq);
else
    Aeq = []; beq = [];
end


function [x,y,xy,mv,mp,bound] = mg_cavity_domain(nc,grid_type)
%mg_cavity_domain   square cavity Q2 grid generator for GMG
%   [x,y,xy,mv,mp,bound] = mg_cavity_domain(nc,grid_type)
%   input
%          nc           grid level indicator
%          grid_type    1 for uniform, 2 for stretched
%   output
%          grid-defining data
%
%   IFISS function: HCE; 24 January 2004.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage

%   modelled after IFISS function cavity_domain, adapted for GMG
n=2^nc; np=n/2; nq=n/4;
% y-direction
if grid_type==2
   hmax=nc/(2^(nc+1));
   x1=-1;x2=-2*hmax;x3=2*hmax;x4=1;nx1=2^(nc-1)-1;nx2=2;nx3=2^(nc-1)-1;
   y1=-1;y2=-2*hmax;y3=2*hmax;y4=1;ny1=2^(nc-1)-1;ny2=2;ny3=2^(nc-1)-1;
   y=subint(y1,y2,y3,y4,ny1,ny2,ny3);
   stretch=(y(3)-y(2))/(y(2)-y(1));
   x=y;
else
   yy=[1/np:1/np:1];
   ypos=[0,yy];
   yneg=-yy(length(yy):-1:1);
   y=[yneg,ypos]';
   x=y;
end
%
%% compute biquadratic element coordinates
nvtx=(n+1)*(n+1);
[X,Y]=meshgrid(x,y);
xx=reshape(X',nvtx,1);
yy=reshape(Y',nvtx,1);
xy=[xx(:),yy(:)];
%
kx = 1;
ky = 1;
mel=0;
for j=1:np
   for i=1:np
      mref=(n+1)*(ky-1)+kx;
      pref=(np+1)*(j-1)+i;
      mel=mel+1;
      nvv(1) = mref;
      nvv(2) = mref+2;
      nvv(3) = mref+2*n+4;
      nvv(4) = mref+2*n+2;
      nvv(5) = mref+1;
      nvv(6) = mref+n+3;
      nvv(7) = mref+2*n+3;
      nvv(8)=  mref+n+1;
      nvv(9)=  mref+n+2;
      npp(1) = pref;
      npp(2) = pref+1;
      npp(3) = pref+np+2;
      npp(4) = pref+np+1;
      mv(mel,1:9)=nvv(1:9);
      mp(mel,1:4)=npp(1:4);
      kx = kx + 2;
   end
   ky = ky + 2;
   kx = 1;
end

%% compute boundary vertices and edges
% four boundary edges
k1=find( xy(:,2)==-1  );
e1=[]; for k=1:mel, if any(mv(k,5)==k1), e1=[e1,k]; end, end
ef1=ones(size(e1));
%
k2=find( xy(:,1)==1 & xy(:,2)<1   & xy(:,2) >-1);
e2=[]; for k=1:mel, if any(mv(k,6)==k2), e2=[e2,k]; end, end
ef2=2*ones(size(e2));
%
k3=find( xy(:,2)==1  );
e3=[]; for k=1:mel, if any(mv(k,7)==k3), e3=[e3,k]; end, end
ef3=3*ones(size(e3));
%
k4=find( xy(:,1)==-1 & xy(:,2)<1   & xy(:,2) >-1);
e4=[]; for k=1:mel, if any(mv(k,8)==k4), e4=[e4,k]; end, end
ef4=4*ones(size(e4));
%
bound=sort([k1;k2;k3;k4]);
mbound=[e1',ef1';e2',ef2';e3',ef3';e4',ef4'];


function mldate = x2mdate(xlsdate, type)
% X2MDATE provides a simple method to convert between excel dates and MATLAB dates.
%
% USAGE:
%   [MLDATE] = x2mdate(XLSDATE)
%   [MLDATE] = x2mdate(XLSDATE, TYPE)
%
% INPUTS:
%   XLSDATE   - A scalar or vector of Excel dates.
%   TYPE      - [OPTIONAL] A scalar or vector of the same size as XLSDATE that describes the Excel
%                 basedate.  Can be either 0 or 1.  If 0 (default), the base date of Dec-31-1899 is
%                 used.  If 1, the base date is Jan 1, 1904.
%
% OUTPUTS:
%   MLDATE    - A vector with the same size as XLSDATE consisting of MATLAB dates.
%
% EXAMPLE:
%   XLSDATE = [35000 40000 41000];
%   MLDATE  = x2mdate(XLSDATE);
%   datestr(MLDATE)
%       28-Oct-1995
%       06-Jul-2009
%       01-Apr-2012
%
% COMMENTS:
%   This is a reverse engineered clone of the MATLAB function x2mdate and should behave the same.
%   You only need it if you do not have the financial toolbox installed.
%
% See also C2MDATE

% Copyright: Kevin Sheppard
% kevin.sheppard@economics.ox.ac.uk
% Revision: 1    Date: 10/27/2006

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Validation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin==1
    type=0;
end

if any(ischar(xlsdate))
    error('XLSDATE must be numeric')
end

if ndims('xlsdate')~=2 &&  min(size(type))~=1
    error('XLSDATE must be a T by 1 or 1 by T vector');
end

if nargin>1
    if nargin>2
        error('1 or 2 inputs only');
    end
    if min(size(type))~=1 || ndims(type)~=2
        error('TYPE must be either a scalar or a vector conformable to xlsdate');
    end
    if max(size(type))~=1
        if max(size(type))~=max(size(xlsdate))
            error('TYPE must be either a scalar or a vector conformable to xlsdate');
        end
    end
    if any(~ismember(type,[0 1]))
        error('TYPE must be either 0 or 1.')
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Validation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if isscalar(type)
    type=type*ones(size(xlsdate));
end
type = logical(type);

mldate=zeros(size(xlsdate));
mldate(~type) = xlsdate(~type) + datenum('30-Dec-1899') ;
mldate(type) = xlsdate(type) + datenum('1-Jan-1904') ;


% Demo: on-line design optimization for DCM of fMRI data.
% This demo simplifies the network identification of Friston et al. (2003).
% In brief, photic input enters V1, which is reciprocally connected to V5.
% The goal of the experiment is to assess whether attention modulates the
% feedforward connection from V1 to V5. This is addressed using Bayesian
% model comparison given fMRI data (i.e. model 1: attention modulates the
% V1->V5 connection; model 2: no modulatory effect). Within the session,
% each block consists of 16 seconds of stimulation and 16 of rest. The
% on-line design optimization consists in deciding, before each block,
% whether we modulate subjects' attention. This is done by comparing the
% design efficiency  of two canonical block designs (i.e. with and without
% attentional modulation).
% NB: the procedure is adaptative, because it updates the posterior on
% unknown model parameters after each block. This is why the design
% efficiency inceases across time.

close all
clear variables

% Basic settings
n_t = 16; % number of time samples per block
nblocks = 10; % number of blocks
nreg = 2; % number of regions
TR = 3e0; % sampling period (in sec)
microDT = 5e-2; % micro-time resolution (in sec)
f_fname = @f_DCMwHRF;
g_fname = @g_HRF3;

% construct atomic designs
nu = 2;
u1 = [0,ones(1,floor(n_t/2))];
u1(end:n_t) = 0;
u2 = zeros(1,n_t);
u = {[u1;u2];[u1;u1]}; % u{1}/u{2}: w/wo attentinal modulation

nm = 2; % # candidate models (see below)
truemodel = 1; % index of true model (which generates the data)

% model 1: u_att modulates connection from V1 to V5
A = [0 1
    1 0];
B{1} = zeros(nreg,nreg);
B{2} = zeros(nreg,nreg);
B{2}(2,1) = 1;
C = [1 0
     0 0];
D{1} = [0 0
    0 0];
D{2} = zeros(nreg,nreg);
D{3} = zeros(nreg,nreg);
[o4design{1},dim{1}] = getOptions4dcm(A,B,C,D,TR,microDT,n_t,1,1,1);

% model 1: no modulatory effect of attention
A = [0 1
    1 0];
nreg = size(A,1);
B{1} = zeros(nreg,nreg);
B{2} = zeros(nreg,nreg);
C = [1 0
     0 0];
D{1} = [0 0
    0 0];
D{2} = zeros(nreg,nreg);
D{3} = zeros(nreg,nreg);
[o4design{2},dim{2}] = getOptions4dcm(A,B,C,D,TR,microDT,n_t,1,1,1);

o4design{truemodel}.verbose = 0;

% simu parameters
t_A = exp([ -0.5
            -0.5
            ]);
t_Aself = -0;
t_B{1} = [];
t_B{2} = exp([ -0.5 ]);
t_C = exp([ -0.5 ]);
t_D{1} = [];
t_D{2} = [];
theta = zeros(dim{truemodel}.n_theta,1);
phi = zeros(dim{truemodel}.n_phi,1);
theta(o4design{truemodel}.inF.indA) = t_A;
for i=1:nu
    theta(o4design{truemodel}.inF.indB{i}) = t_B{i};
end
theta(o4design{truemodel}.inF.indC) = t_C;
alpha = Inf; % state noise precision
sigma = 5e-1; % measurement noise precision
x0 = zeros(dim{truemodel}.n,1); % initial conditions

% prepare graphics & montoring variables
hf = figure('color',[1 1 1]);
ha = subplot(3,2,1,'parent',hf,'nextplot','add','xlim',[1 nblocks+1]);
xlabel(ha,'time (blocks)')
ylabel(ha,'design efficiency')
ha2 = subplot(3,2,3,'parent',hf,'nextplot','add','xlim',[1 n_t*nblocks]);
xlabel(ha2,'time (scans)')
ylabel(ha2,'BOLD signal')
ha3 = subplot(3,2,2,'parent',hf,'nextplot','add','xlim',[1 nblocks+1]);
xlabel(ha3,'time (blocks)')
ylabel(ha3,'log p(y|m_1) -log p(y|m_2)')
e = zeros(2,1);
Y = zeros(dim{truemodel}.p,n_t*nblocks);
U = zeros(2,n_t*nblocks);
F = zeros(2,nblocks);
eb = zeros(1,nblocks);
vb = zeros(1,nblocks);

% on-line experiment

for tt=1:nblocks

    % 1- find best design given current information
    fprintf(1,'\n')
    fprintf(1,['-- Optimizing design (block ',num2str(tt),')...'])
    fprintf(1,'\n')
    for i=1:length(u) %loops over experimental designs
        fprintf(1,['- Candidate design #',num2str(i),'...'])
        fprintf(1,'\n')
        [e(i,tt)] = VBA_designEfficiency(f_fname,g_fname,dim,o4design,u{i},'models');
    end
    [em,ind] = max(e(:,tt));
    U(:,(tt-1)*n_t+1:tt*n_t) = u{ind};
    fprintf(1,['Optimizing design (block ',num2str(tt),')...  OK.'])
    fprintf(1,'\n')
    plot(ha,tt,e(1,tt)','ro')
    plot(ha,tt,e(2,tt)','go')
    legend(ha,{'u_{att} = off','u_{att} = on'},'Location','southeast','Orientation','horizontal')

    % 2- simulate BOLD response to chosen design under true model
    fprintf(1,['-- Simulating data (block ',num2str(tt),')...  '])
    [y,x,x0,eta,ee] = VBA_simulate (n_t,f_fname,g_fname,theta,phi,u{ind},alpha,sigma,o4design{truemodel},x0);
    Y(:,(tt-1)*n_t+1:tt*n_t) = y;
    x0 = x(:,end);

    try
        set(pl(1), 'XData', 1 : tt*n_t);
        set(pl(1), 'YData', [get(pl(1), 'YData') y(1,:)]);
        set(pl(2), 'XData', 1 : tt*n_t);
        set(pl(2), 'YData', [get(pl(2), 'YData') y(2,:)]);
    catch
        pl(1) = plot(ha2,1:n_t,y(1,:),'m');
        pl(2) = plot(ha2,1:n_t,y(2,:),'b');
    end
    legend(ha2,{'V1','V5'},'Location','southeast','Orientation','horizontal')
    fprintf(1,[' OK.'])
    fprintf(1,'\n')
    drawnow

    % 3- invert both models given new piece of dataset
    % NB: priors for the next block are updated to current posterior
    fprintf(1,['-- VB (block ',num2str(tt),'):   inverting model       '])
    for j=1:length(o4design)
        fprintf(1,repmat('\b',1,6))
        fprintf(1,[num2str(j),'/',num2str(length(o4design)),'...'])
        o4design{j}.DisplayWin = 0;
        o4design{j}.verbose = 0;
        [posterior,out] = VBA_NLStateSpaceModel(y,u{ind},f_fname,g_fname,dim{j},o4design{j});
        o4design{j}.priors = posterior;
        o4design{j}.priors.muX0 = posterior.muX(:,end);
        o4design{j}.priors.SigmaX0 = posterior.SigmaX.current{end};
        if tt > 1
            F(j,tt) = out.F + F(j,tt-1);
        else
            F(j,tt) = out.F;
        end
        OUT(j,tt).out = out;
        OUT(j,tt).posterior = posterior;
    end
    plot(ha3,tt,F(1,tt)-F(2,tt),'k*')

    eb(tt) = OUT(1,tt).posterior.muTheta(OUT(1,tt).out.options.inF.indB{2});
    vb(tt) = OUT(1,tt).posterior.SigmaTheta(OUT(1,tt).out.options.inF.indB{2},OUT(1,tt).out.options.inF.indB{2});

    fprintf(1,repmat('\b',1,24))
    fprintf(1,[' OK.'])
    fprintf(1,'\n')

end

ha4 = subplot(3,2,4,'parent',hf,'nextplot','add','xlim',[0 nblocks+1]);
xlabel(ha4,'time (blocks)')
ylabel(ha4,'modulatory effect')
plotUncertainTimeSeries(eb',1.96^2*vb',[],ha4)
hold(ha4,'on')
plot(ha4,[0,nblocks+1],[t_B{2},t_B{2}],'g--')

ha5 = subplot(3,2,5,'parent',hf);
imagesc(U,'parent',ha5)
title(ha5,'chosen (online) design')
xlabel(ha5,'time (scans)')
hold(ha5,'on')
plot(get(ha5,'xlim'),[1.5 1.5],'k')
set(ha5,'ytick',[1,2],'yticklabel',{'u1','u2'})
colormap(flipud(bone))

% invert full datasets at once
n_t = size(Y,2);
B{2}(2,1) = 1; % add modulatory effect (true model)
[OPT,DIM] = getOptions4dcm(A,B,C,D,TR,microDT,n_t,1,1,1);
[posterior,out] = VBA_NLStateSpaceModel(Y,U,f_fname,g_fname,DIM,OPT);


function [W,result] = IHR(Ws,npos,gama,afa,yuzhi)
global eta;
global TrainSetX;
global TestSetX;
global TestSetY;
global kneighbor_testp;

global W0;
global s11;
global w1;
global index1;
W0 = Ws;
w1 = Ws;

tempsum1 = 0;
for i=1:size(TestSetX,2)
    tempKN = kneighbor_testp(i,:);
    tempTuples = TestSetX(:,tempKN);
    s1 = w1'*tempTuples;
    p1 = 1./(1 + exp(-s1));
    tempsum1 = tempsum1 + (sum(p1)/size(kneighbor_testp,2)-1/(1+exp(-w1'*TestSetX(:,i))))^2;
end

tempsum2 = 0;
for i=1:size(TestSetX,2)
    tempsum2 = tempsum2 + (1/(1+exp(-w1'*TestSetX(:,i))) - 0.5)^2;
end

s1 = w1'*TestSetX;
p1 = 1./(1 + exp(-s1));

f = ((w1)'*(w1))+afa*tempsum1/size(TestSetX,2)-gama*tempsum2/size(TestSetX,2)+eta*(sum(p1)-npos)^2/size(TestSetX,2); %07-12-31
fprintf('initial value...%g\n',f);
index1 = 0;

result(1,1) = getResult(p1,TestSetY);
ff(1,1) = f;
warning off;
while index1 < 100

    temp11 = zeros(size(TestSetX,1),1);
    s11 = zeros(size(TestSetX,1),1);
    for i=1:size(TestSetX,2)
        tempKN = kneighbor_testp(i,:);
        tempTuples = TestSetX(:,tempKN);
        s1 = w1'*tempTuples;
        p1 = 1./(1 + exp(-s1));
        tmp_p1 = sum(p1)/size(kneighbor_testp,2)-1/(1+exp(-w1'*TestSetX(:,i)));
        p2 = exp(-s1)./((1 + exp(-s1)).^2);
        for k = 1:size(kneighbor_testp,2)
            temp11 = temp11 + tempTuples(:,k)*p2(1,k);
        end
        temp11 = temp11/size(kneighbor_testp,2) - (exp(-w1'*TestSetX(:,i))/(1+exp(-w1'*TestSetX(:,i)))^2)*TestSetX(:,i);
        s11 = s11 + 2*tmp_p1*temp11;
    end
    s11 = afa*s11/size(TestSetX,2); %

    s12 = zeros(size(TestSetX,1),1);
    for i = 1:size(TestSetX,2)
        s12 = s12 + 2*gama*(1/(1+exp(-w1'*TestSetX(:,i))) - 0.5)*((exp(-w1'*TestSetX(:,i)))/(1+exp(-w1'*TestSetX(:,i)))^2)*TestSetX(:,i);
    end
    s12 = s12/size(TestSetX,2);

    s1 = w1'*TestSetX;
    p1 = 1./(1 + exp(-s1));
    tmps13 = 2*eta*(sum(p1)-npos)*(exp(-w1'*TestSetX)./(1+exp(-w1'*TestSetX)).^2);
    s13 = sum(scale_cols(TestSetX,tmps13),2);
    s13 = s13/size(TestSetX,2);

    if [s11-s12+s13+2*(w1)]'*[s11-s12+s13+2*(w1)] < yuzhi^2
        break;
    end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if index1 == 0
        d0 = -s11+s12-s13-2*(w1);
    end
    if index1 > 0
        afa0 = ([s11-s12+s13+2*(w1)]'*[s11-s12+s13+2*(w1)-temp_s11-temp_s12])/([temp_s11+temp_s12]'*[temp_s11+temp_s12]);
        d1 = [-s11+s12-s13-2*(w1)] + afa0*d0;
        d0 = d1;
    end

    temp_s11 = s11;
    temp_s12 = -s12+s13+2*(w1);

    s11 = d0;

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    beta = 0;

    options = optimset('LargeScale','on');
    [x,fval] = fminunc(@objfun,beta,options);

    beta = x;
    if beta == 0
        break;
    end
    w1 = w1 + beta*d0;

    tempsum1 = 0;
    for i=1:size(TestSetX,2)
        tempKN = kneighbor_testp(i,:);
        tempTuples = TestSetX(:,tempKN);
        s1 = w1'*tempTuples;
        p1 = 1./(1 + exp(-s1));
        tempsum1 = tempsum1 + (sum(p1)/size(kneighbor_testp,2)-1/(1+exp(-w1'*TestSetX(:,i))))^2;
    end

    tempsum2 = 0;
    for i=1:size(TestSetX,2)
        tempsum2 = tempsum2 + (1/(1+exp(-w1'*TestSetX(:,i))) - 0.5)^2;
    end

    s1 = w1'*TestSetX;
    p1 = 1./(1 + exp(-s1));

    f = ((w1)'*(w1))+afa*tempsum1/size(TestSetX,2)-gama*tempsum2/size(TestSetX,2)+eta*(sum(p1)-npos)^2/size(TestSetX,2); %07-12-31

    s1 = w1'*TestSetX;
    p1 = 1./(1 + exp(-s1));
    index1 = index1+1;
    result(1,index1+1) = getResult(p1,TestSetY);
    ff(1,index1+1) = f;

    fprintf('iterating...%g value : %g...the accuracy:%g\n',index1,f,getResult(p1,TestSetY));

end
W = w1;


function hmm = updatePCAparam (hmm,Gammasum,XXGXX,Tfactor,rangeK)

K = hmm.K; ndim = hmm.train.ndim;
if nargin < 5 || isempty(rangeK), rangeK = 1:K; end
if nargin < 4, Tfactor = 1; end
p = hmm.train.lowrank;

for k = rangeK

    % unlike Bishop's mixture of PCA, we don't have a mean vector per state here
    v = hmm.Omega.Gam_rate / hmm.Omega.Gam_shape;
    W = hmm.state(k).W.Mu_W; % posterior dist of the precision matrix
    S = XXGXX{k};% / Gammasum(k);
    %regterm = diag(hmm.state(k).beta.Gam_shape ./ hmm.state(k).beta.Gam_rate);
    SW = S * W;
    M = W'*W + v*eye(p);

    % W
    iS_W = v*eye(p) + M\W'*SW / Gammasum(k);
    S_W = inv(iS_W);
    hmm.state(k).W.Mu_W = SW * S_W / Gammasum(k);
    for n = 1:ndim
        hmm.state(k).W.iS_W(n,:,:) = iS_W;
        hmm.state(k).W.S_W(n,:,:) = S_W;
    end

    % Omega
    Wnew = hmm.state(k).W.Mu_W;
    omega_i = mean(diag(S - SW * (M \ Wnew')));
    % replace
    hmm.Omega.Gam_rate = hmm.Omega.Gam_rate - hmm.Omega.Gam_rate_state(k);
    hmm.Omega.Gam_shape = hmm.Omega.Gam_shape - hmm.Omega.Gam_shape_state(k);
    hmm.Omega.Gam_rate_state(k) = 0.5 * Tfactor * omega_i;
    hmm.Omega.Gam_shape_state(k) = 0.5  * Tfactor * Gammasum(k);
    hmm.Omega.Gam_rate = hmm.Omega.Gam_rate + hmm.Omega.Gam_rate_state(k);
    hmm.Omega.Gam_shape = hmm.Omega.Gam_shape + hmm.Omega.Gam_shape_state(k);

    % prior beta
    %hmm.state(k).beta.Gam_shape = hmm.state(k).prior.beta.Gam_shape + 0.5 * ndim;
    %hmm.state(k).beta.Gam_rate = hmm.state(k).prior.beta.Gam_rate + ...
    %    sum(hmm.state(k).W.Mu_W.^2) + ...
    %    diag(permute(sum(hmm.state(k).W.S_W,1),[2 3 1]))';

end

end


function output = ...
  SynthesizeSpeech(spectrum_envelope, source)
% Synthesize speech from harmonic information
%
% output = ...
%  SynthesizeSpeech(spectrum_envelope, source)
%
% Arguments
% spectrum_envelope: structure with following fields
%   harmonic_power_dB: Harmonics level in dB
%   sampling_frequency: sampling frequency 9Hz)
% source: structure with following fields
%   f0: fundamental frequency (Hz)
%   aperiodicity_matrix: residual level in dB (Has to be calibrated)
%   vuv : voiced/unvoiced indicator of each frame: 1: voiced
%
% Return value
%   output : synthesized signal

% Copyright 2016 Google Inc. All Rights Reserved
% Author: hidekik@google.com (Hideki Kawahara)

% check input and prepare information for synthesis
narginchk(2, 2);
tx = source.frame_time;
f0 = source.f0;
fs = source.sampling_frequency;
harmonic_level = spectrum_envelope.harmonic_power_dB;
harmonic_deviation = source.aperiodicity_matrix;
unvoiced_frame = double(source.vuv < 0.5);
[event_index, event_locations, f0i] = CalculateEventLocations(tx, fs, f0);
unvoiced_sample = ...
  interp1(tx, double(unvoiced_frame), event_locations, 'linear', 'extrap');
harmonics_level_at_event = ...
  interp1(tx, harmonic_level', event_locations, 'linear', 'extrap')';
harmonics_deviation_at_event = ...
  StabilizeHarmonicDeviations(tx, harmonic_deviation, event_locations);
output = ...
  SynthesizeByEventBasedMethod(event_index, event_locations,...
  harmonics_level_at_event, ...
  harmonics_deviation_at_event, fs, f0i, ...
  unvoiced_sample);
end


% TD | CP-APR | PARAFAC/CP decomposition solved by Alternating Poisson Regression
% process_video('TD', 'CP-APR', 'dataset/demo.avi', 'output/demo_CP-APR.avi');

r = 10;
A = double(T);
L = double(cp_apr(T,r));
S = A - L;