function [c, s, b, g, smin, active_set] = thresholded_oasisAR2(y, g, sn, optimize_b,...
    optimize_g, decimate, maxIter, thresh_factor)
%% Infer the most likely discretized spike train underlying an AR(1) fluorescence trace
% Solves the sparse non-negative deconvolution problem
%  min 1/2|c-y|^2 + lam |s|_1 subject to s_t = c_t-g c_{t-1} >=s_min or =0

%% inputs:
%   y:  T*1 vector, One dimensional array containing the fluorescence intensities
%withone entry per time-bin.
%   g:  scalar, Parameter of the AR(1) process that models the fluorescence ...
%impulse response.
%   sn:  scalar, standard deviation of the noise distribution
%   optimize_b: bool, optimize baseline if True
%   optimize_g: integer, number of large, isolated events to consider for
%       optimizing g
%   decimate: int, decimation factor for estimating hyper-parameters faster
%       on decimated data
%   maxIter:  int, maximum number of iterations
%   active_set: npool x 4 matrix, warm stared active sets
%  thresh_factor: scalar, set the maximum thresh as thresh_factor*sn^2*T

%% outputs
%   c: T*1 vector, the inferred denoised fluorescence signal at each time-bin.
%   s: T*1 vector, discetized deconvolved neural activity (spikes)
%   b: scalar, fluorescence baseline
%   g: scalar, parameter of the AR(1) process
%   smin: scalar, minimum nonzero spike count
%   active_set: npool x 4 matrix, active sets

%% Authors: Pengcheng Zhou, Carnegie Mellon University, 2016
% ported from the Python implementation from Johannes Friedrich

%% References
% Friedrich J et.al., NIPS 2016, Fast Active Set Method for Online Spike Inference from Calcium Imaging

%% input arguments
y = reshape(y, [], 1);
T = length(y);

if ~exist('g', 'var') || isempty(g)
    g = estimate_time_constant(y, 2);
end
if ~exist('sn', 'var') || isempty(sn)
    sn = GetSn(y);
end
if ~exist('optimize_b', 'var') || isempty(optimize_b)
    optimize_b = false;
end
if ~exist('optimize_g', 'var') || isempty(optimize_g)
    optimize_g = 0;
end
if ~exist('decimate', 'var') || isempty(decimate)
    decimate = 1;
else
    decimate = max(1, round(decimate));
end
if ~exist('maxIter', 'var') || isempty(maxIter)
    maxIter = 10;
end
if ~exist('thresh_factor', 'var') || isempty(thresh_factor)
    thresh_factor = 1.0;
end

thresh = thresh_factor* sn * sn * T;
smin = 0;

% change parameters due to downsampling
if decimate>1
    decimate = 1;  %#ok<NASGU>
    disp('to be done');
    %     fluo = y;
    %     y = resample(y, 1, decimate);
    %     g = g^decimate;
    %     thresh = thresh / decimate / decimate;
    %     T = length(y);
end
g_converged = false;

%% optimize parameters
tol = 1e-4;
if ~optimize_b   %% don't optimize the baseline b
    %% initialization
    b = 0;
    [solution, spks, active_set] = oasisAR2(y, g, [], smin);

    %% iteratively update parameters lambda & g
    for miter=1:maxIter
        len_active_set = size(active_set, 1);

        res = y - solution;
        RSS = res' * res;

        % update g
        if and(optimize_g, ~g_converged);
            g0 = g;
            [solution, active_set, g, spks] = update_g(y, g, spks,smin);
            if abs(g-g0)/g0 < 1e-3 % g is converged
                g_converged = true;
            end
        end
%         g_converged = true;
        res = y - solution;
        RSS = res' * res;
        if or(RSS>thresh, sum(solution)<1e-9)  % constrained form has been found, stop
            break;
        else
            % update lam
            [smin, solution, spks, active_set] = update_smin(y, g, smin,...
                solution, spks, active_set, sqrt(thresh), max(spks));

            % no more change of the active set
            if size(active_set,1)==len_active_set
                break;
            end
        end
    end
else
    %% initialization
    b = quantile(y, 0.15);
    [solution, spks, active_set] = oasisAR2(y-b, g, [], smin);

    %% optimize the baseline b and dependends on the optimized g too
    g_converged = false;
    for miter=1:maxIter
           % update b and g

        res = y - solution - b;
        RSS = res' * res;
        len_active_set = size(active_set,1);

        if or(abs(RSS-thresh) < tol, sum(solution)<1e-9)
            break;
        else
            % update smin
            [smin, solution, spks, active_set] = update_smin(y-b, g, smin,...
                solution, spks, active_set, sqrt(thresh), max(spks));
            b = mean(y-solution);

            % update b and g
            if and(optimize_g, ~g_converged);
                g0 = g;
                [solution, active_set, g, spks] = update_g(y-b, g0, spks, smin);
                if abs(g-g0)/g0 < 1e-4;
                    g_converged = true;
                end
            end

        end
    end

end
c = solution;
s = spks;

%% nested functions
    function [smin, solution, spks, active_set] = update_smin(y, g, smin, solution, ...
            spks, active_set, thresh, s_max)
        %%estimate smin to match the thresholded RSS
        len_active_set = size(active_set, 1);
        sv = linspace(smin, s_max, min(9, len_active_set));
        ind_start = 1;
        ind_end = length(sv);

        while (ind_end-ind_start)>1
            ind = floor((ind_start+ind_end)/2);
            tmp_smin = sv(ind);
            [tmp_solution, tmp_spks, tmp_active_set] = oasisAR2(y, g, [], ...
                tmp_smin, [], [], active_set);
            sqRSS = norm(y-tmp_solution,2);
            if sqRSS<thresh % increase smin
                solution = tmp_solution;
                spks = tmp_spks;
                active_set = tmp_active_set;
                smin = tmp_smin;
                ind_start = ind;
            elseif sqRSS>thresh % decrease smin
                ind_end = ind;
            else
                break;
            end
        end
    end

end

%update the AR coefficient: g
function [c, active_set, g, s] = update_g(y, g, spks, smin)
%% inputs:
%   y:  T*1 vector, One dimensional array containing the fluorescence intensities
%withone entry per time-bin.
%   g: 2x1 vector, AR2 parameters
%   active_set: npools*4 matrix, previous active sets.
% smin: scalr, minimize size of nonzero spikes

%% outputs
%   c: T*1 vector
%   s: T*1 vector, spike train
%   active_set: npool x 4 matrix, active sets
%   g: scalar

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

%% initialization
s_th = quantile(spks(spks>1e-3), 0.25);
tsp = find(spks>=s_th);
tsp = reshape(tsp, 1, []);
time_p = find(conv2(double(spks<=s_th), ones(30,1), 'same')>0);
time_p = reshape(time_p,[],1);
y = reshape(y,[],1);    % fluorescence data
yp = y(time_p);
T = length(y);
tau_dr = ar2exp(g);
tau_d = tau_dr(1);
tau_r = tau_dr(2);

%% find the optimal g and get the warm started active_set
tau_d0 = tau_d;
tau_r0 = tau_r;
bnd_d = tau_d0 * [1/4, 4];
bnd_r = tau_r0 * [1/4, 4];
for m=1:10
    tau_r = fminbnd(@rss_taur, bnd_r(1), bnd_r(2));
    tau_d = fminbnd(@rss_taud, bnd_d(1), bnd_d(2));
    if and(abs(tau_d-tau_d0)/tau_d0 < 1e-4, abs(tau_r-tau_r0)/tau_r0 < 1e-4)
        break;
    else
        tau_d0 = tau_d;
        tau_r0 = tau_r;
    end
end

%% copute the optimal solution
g = exp2ar([tau_d, tau_r]);
[c,s,active_set] = oasisAR2(y, g, 0, smin);

%% nested functions

    function rss = rss_taur(tau_r)
        ht = (exp(-(1:T)/tau_d) - exp(-(1:T)/tau_r))/(tau_d-tau_r);
        ht(T) = 0;
        ind = bsxfun(@minus, time_p, tsp);
        ind(ind<=0) = T;
        V = ht(ind);

        % find the best value of st
        s = (V'*V)\(V'*yp);
        res = yp - V*s;
        rss = res' * res;
    end

    function rss = rss_taud(tau_d)
         ht = (exp(-(1:T)/tau_d) - exp(-(1:T)/tau_r))/(tau_d-tau_r);
        ht(T) = 0;
        ind = bsxfun(@minus, time_p, tsp);
        ind(ind<=0) = T;
        V = ht(ind);

        % find the best value of st
        s = (V'*V)\(V'*yp);
        res = yp - V*s;
        rss = res' * res;
    end
end


function ra=lpcar2ra(ar)
%LPCAR2RA Convert ar filter to inverse filter autocorrelation coefs. RA=(AR)

%      Copyright (C) Mike Brookes 1997
%      Version: $Id: lpcar2ra.m,v 1.4 2007/05/04 07:01:38 dmb Exp $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[nf,p1]=size(ar);
ra=zeros(nf,p1);
for i=1:p1
   ra(:,i)=sum(ar(:,1:p1+1-i).*ar(:,i:p1),2);
end


function Output = Bayesian_RPCAmcmc_MarkovDep(X0,Theta0,Row,Col,hyperpara,MCMCpara)
%Bayesian_RPCAmcmc_withMarkovDep: Bayesian robust principle component analysis
%implemented by MCMC, considering Markov dependency on the sparse term in time and space.
%
% Model: X0 = D*(Delta.*Z)*S + S2.*Z2 + E
% ----------------------------------------------------
%
%USAGE: Output = Bayesian_RPCAmcmc_withMarkovDep(X0,Theta0,Row,Col,hyperpara,MCMCpara)
%
%INPUT :
%   X0: P x N, input data matrix. For the video application, every column is a frame of the video.
%
%   Theta0: struct data including the initial parameters of the model. The parameters of the model are initialized as follows,
%         D = Theta0.D: P x K matrix as a dictionary for lowrank learning
%         S = Theta0.S: K x N coefficient matrix
%         Z = Theta0.Z: K x K diagnal binary matrix for rank learning
%         Delta = Theta0.Delta: K x K diagnal matrix for weighting Z.
%         Tao = Theta0.Tao: precision of Delta. Here we set Tao=1.
%         Pi = Theta0.Pi: K x 1 vector. Pi is the probability of Z=1.
%
%         gamma_epsi = Theta0.gamma_epsi:  scalar, precision of the noise. Here we assumed the noise is stationary.
%
%         S2 = Theta0.S2: P x N matrix for Sparse Component learning
%         Z2 = Theta0.Z2: P x N binary matrix for Sparse Component learning
%         gamma_s = Theta0.gamma_s: precision of the S2
%         Pi2 = Theta0.Pi2: P x N . Pi2 is the probability of Z2=1.
%         Note that Pi2 here is a matrix, different from the model structure in function Bayesian_RPCAmcmc.
%
%   Row and Col: Row and column of the video frame.
%
%   hyperpara: MCMC hyperparameters
%     hyperpara.a0: scalar, hyperparameter 1 for Pi [1/K or 1/150 if K<150]
%       hyperpara.b0: scalar, hyperparameter 2 for Pi [1-hyperpara.a0]
%       hyperpara.c0: scalar, hyperparameter 1 for Tao precision [1e-6]
%       hyperpara.d0: scalar, hyperparameter 2 for Tao precision [1e-6]
%       hyperpara.e0: scalar, hyperparameter 1 for nosie precision [1e-6]
%       hyperpara.f0: scalar, hyperparameter 2 for nosie precision [1e-6]
%       hyperpara.g0: scalar, hyperparameter 1 for S2 precision [1e-6]
%       hyperpara.h0: scalar, hyperparameter 2 for S2 precision [1e-6]
%       hyperpara.alpha0: scalar,hyperparameter 1 for Pi2 [0.01*N]
%       hyperpara.beta0: scalar,hyperparameter 2 for Pi2 [0.99*N]
%       hyperpara.alpha1: scalar,hyperparameter 3 for Pi2 [0.99*N]
%       hyperpara.beta1: scalar,hyperparameter 4 for Pi2 [0.01*N]
%
%
%   MCMCpara: MCMC parameters
%       MCMCpara.nBurnin: scalar, number of burnin iterations [2000]
%       MCMCpara.nCollect: scalar, number of collected samples [1000]
%
%OUTPUT:
%   Output: struct data.
%         Output.Lowrank_mean: P x N matrix, mean of the Lowrank Component.
%         Output.Lowrank_std: P x N matrix, std of the Lowrank Component.
%         Output.Sparse_mean: P x N matrix, mean of the Sparse Component.
%         Output.Sparse_std: P x N matrix, std of the Sparse Component.
%         Output.Gamma_epsi_mean: scalar, mean of the noise precision.
%         Output.Gamma_epsi_std: scalar, std of the noise precision.
%         Output.rankL_mean: scalar, mean of the estimated rank of the lowrank Component.
%         Output.rankL_std: scalar, std of the estimated rank of the lowrank Component.
%         Output.NumSparse_mean: scalar, mean of the estimated number of the Sparse Component.
%         Output.NumSparse_std: scalar, std of the estimated number of the Sparse Component.

%--------------------------------------------------------------------------
% References:
% X. Ding, L. He and L. Carin, Bayesian Robust Principal Component Analysis, submitted to IEEE Trans. Image Processing (2010)
%
% Xinghao Ding, Lihan He, ECE, Duke University
% Created: Apr. 12, 2010,
% Last change: Aug. 2, 2010.
%--------------------------------------------------------------------------

% ---------------------
% check input arguments
% ---------------------

% P -- Dimension of the data vector
% N -- Number of samples
[P,N] = size(X0);
% K -- the largest possible rank
K = size(Theta0.D,2);

if nargin<6
    MCMCpara.nBurnin=100;
    MCMCpara.nCollect=100;
end
if nargin<5
    % Hyperparameters
    if K<150
        hyperpara.a0 = 1/150;
    else
        hyperpara.a0 = 1/K;
    end
    hyperpara.b0 = 1-hyperpara.a0;
    hyperpara.c0 = 1e-6;
    hyperpara.d0 = 1e-6;
    hyperpara.e0 = 1e-6;
    hyperpara.f0 = 1e-6;
    hyperpara.g0 = 1e-6;
    hyperpara.h0 = 1e-6;
    hyperpara.alpha0 = 0.01*N;
    hyperpara.beta0 = 0.99*N;
    hyperpara.alpha1 = 0.99*N;
    hyperpara.beta1 = 0.01*N;

end

if isempty(hyperpara)
    % P -- Dimension of the data vector
    % N -- Number of samples
    [P,N] = size(X0);
    % K -- the largest possible rank
    K = size(Theta0.D,2);

    % Hyperparameters
    if K<150
        hyperpara.a0 = 1/150;
    else
        hyperpara.a0 = 1/K;
    end
    hyperpara.b0 = 1-hyperpara.a0;
    hyperpara.c0 = 1e-6;
    hyperpara.d0 = 1e-6;
    hyperpara.e0 = 1e-6;
    hyperpara.f0 = 1e-6;
    hyperpara.g0 = 1e-6;
    hyperpara.h0 = 1e-6;
    hyperpara.alpha0 = 0.01*N;
    hyperpara.beta0 = 0.99*N;
    hyperpara.alpha1 = 0.99*N;
    hyperpara.beta1 = 0.01*N;
end

if isempty(MCMCpara)
   MCMCpara.nBurnin=100;
    MCMCpara.nCollect=100;
end

a0 = hyperpara.a0;
b0 = hyperpara.b0;
c0 = hyperpara.c0;
d0 = hyperpara.d0;
e0 = hyperpara.e0;
f0 = hyperpara.f0;
g0 = hyperpara.g0;
h0 = hyperpara.h0;
alpha0 = hyperpara.alpha0;
beta0 =  hyperpara.beta0;
alpha1 = hyperpara.alpha1;
beta1 =  hyperpara.beta1;

D = Theta0.D;
S = Theta0.S;
Z = Theta0.Z;
Delta = Theta0.Delta;
Tao = Theta0.Tao;
Pi = Theta0.Pi;
gamma_epsi = Theta0.gamma_epsi;
S2 = Theta0.S2;
Z2 = Theta0.Z2;
gamma_s = Theta0.gamma_s;
Pi2 = Theta0.Pi2;

Lowrank_Comp = zeros(P,N);
Sparse_Comp = zeros(P,N);

for iter=1:(MCMCpara.nBurnin+MCMCpara.nCollect)

    X = X0-D*diag(Delta.*Z)*S-S2.*Z2;

    %---------------------------------------------------------------
    % Low-rank component sampling
    %---------------------------------------------------------------

    for k=1:K
        Tao(k) =1;
        X = X+ Delta(k)*Z(k)*D(:,k)*S(k,:);

        %Sample D----------------------------------------------------------
        sigma_Dk = 1/(gamma_epsi*(Delta(k)).^2*Z(k)*(S(k,:)*S(k,:)')+P);
        mu_Dk = gamma_epsi*sigma_Dk* (Delta(k))*Z(k)*X*S(k,:)';
        D(:,k) = mu_Dk + randn(P,1)*sqrt(sigma_Dk);
        %clear sigma_Dk mu_D
        %------------------------------------------------------------------

        %Sample S----------------------------------------------------------

        Dk = D(:,k);
        sigS1 = 1/(1 + gamma_epsi*Z(k)*(Dk'*Dk)*(Delta(k)).^2);
        muS1 = gamma_epsi*sigS1*Z(k)*Delta(k)*D(:,k)'*X;
        S(k,:) = randn(1,N)*sqrt(sigS1) + muS1;
        %------------------------------------------------------------------

        %Sample Delta(k)
        sig_Delta = 1/(Tao(k)+gamma_epsi*(Dk'*Dk)*(S(k,:)*S(k,:)'));
        mu_Delta = gamma_epsi*sig_Delta*D(:,k)'*X*S(k,:)';
        if Z(k) ==1
            %Delta(k) = randn(1)*sqrt(sig_Delta)+mu_Delta;
            Delta(k) = normrnd(mu_Delta,sqrt(sig_Delta));
        else
            %Delta(k) = randn(1);
            Delta(k) =  normrnd(0,sqrt(1/Tao(k)));
        end
        %------------------------------------------------------------------

%        %Sample Z---------------------------------------------------------
        Sk = S(k,:);
        Dk = D(:,k);
        temp =  - 0.5*gamma_epsi*(Delta(k)).^2*(Dk'*Dk)*(Sk*Sk') + gamma_epsi*Delta(k)*Dk'*(X*S(k,:)');
        p1 = exp(temp)*Pi(k);
        p0 = 1-Pi(k);
        Z(k) = rand > p0/(p0+p1);
        %------------------------------------------------------------------

%       %Clappsed Gibbs Sample Z
%         tmpz = log(Pi(k)+eps) - log(1-Pi(k)+eps) + 0.5*log(sig_Delta) + (mu_Delta^2)/(2*sig_Delta) + 0.5*log(Tao(k));
%         if rand < 1/(1+exp(-tmpz))
%             Z(k) = 1; Delta(k) = normrnd(mu_Delta,sqrt(sig_Delta));
%         else
%             Z(k) = 0; Delta(k) =  normrnd(0,sqrt(1/Tao(k)));
%         end

        %sample Pi--------------------------------------------------
        ai = a0 + Z(k);
        bi = b0 + 1 - Z(k);
        Pi(k) =betarnd(ai,bi);
        %------------------------------------------------------------------

        %sample Tao
%         if Z(k) ==1
%             c1 =c0+1/2;
%             d1 =d0 + 0.5*(Delta(k)).^2;
%             Tao(k) = gamrnd(c1,1./d1);
%         else
%             Tao(k) = 1;
%         end
        %------------------------------------------------------------------

        X = X - Delta(k)*Z(k)*D(:,k)*S(k,:);
    end

    %---------------------------------------------------------------
    % Sparse component sampling
    %---------------------------------------------------------------

    X = X + S2.*Z2;

    % Sample S2
    sig_S2 = 1./(gamma_s + gamma_epsi*Z2);
    mu_S2 = gamma_epsi*sig_S2.*Z2.*X;
    S2 = randn(P,N).*sqrt(sig_S2)+mu_S2;

    % Sample Z2
    temp =  exp(-0.5*gamma_epsi*(S2.^2-2*S2.*X));
%     p1 = repmat(Pi2,[1,N]).*temp;
%     p0 = repmat(1- Pi2,[1,N]);
    p1 = Pi2.*temp;
    p0 = 1- Pi2;
    Z2 = rand(P,N)>p0./(p1+p0);

    X = X - S2.*Z2;

    %sample gamma_s
    g1 = g0 + 0.5*P*N;
    tempS2 = S2.*S2;
    h1 = h0 + 0.5*sum(tempS2(:));
    gamma_s = gamrnd(g1,1/h1);

    %Sample Pi2
%     sumZ2 = sum(Z2,2);
%     a2 = a1 + sumZ2;
%     b2 = b1 + N -sumZ2;
%     Pi2 = betarnd(a2,b2);

    %h = fspecial('average');
    h = [0.1,0.1,0.1;0.1,0.2,0.1;0.1,0.1,0.1];
    for n = 1:N
        temp1 = reshape(Z2(:,n),[Row,Col]);
        temp2 = imfilter(double(temp1),h)>0.6;
        tempZ2(:,n) = reshape(temp2,[Row*Col,1]);
    end

    a2 = alpha0 +Z2(:,1);
    b2 = beta0 + 1 - Z2(:,1);
    Pi2(:,1) = betarnd(a2,b2);

    for t = 2:N
%         a2 = alpha0*(~Z2(:,t-1))+alpha1*(Z2(:,t-1)) +Z2(:,t);
%         b2 = beta0*(~Z2(:,t-1))+beta1*(Z2(:,t-1)) +1 - Z2(:,t);
%         a2 = alpha0*(~(Z2(:,t-1).*tempZ2(:,t-1)))+alpha1*(Z2(:,t-1).*tempZ2(:,t-1)) +Z2(:,t);
%         b2 = beta0*(~(Z2(:,t-1).*tempZ2(:,t-1)))+beta1*(Z2(:,t-1).*tempZ2(:,t-1)) +1 - Z2(:,t);
%         a2 = alpha0*(~(tempZ2(:,t-1)))+alpha1*(tempZ2(:,t-1)) +Z2(:,t);
%         b2 = beta0*(~(tempZ2(:,t-1)))+beta1*(tempZ2(:,t-1)) +1 - Z2(:,t);
          a2 = alpha0*(~(tempZ2(:,t)))+alpha1*(tempZ2(:,t)) +Z2(:,t);
          b2 = beta0*(~(tempZ2(:,t)))+beta1*(tempZ2(:,t)) +1 - Z2(:,t);

%         a2 = alpha0*(~(tempZ2(:,t-1).*tempZ2(:,t)))+alpha1*(tempZ2(:,t-1).*tempZ2(:,t)) +Z2(:,t);
%         b2 = beta0*(~(tempZ2(:,t-1).*tempZ2(:,t)))+beta1*(tempZ2(:,t-1).*tempZ2(:,t)) +1 - Z2(:,t);

%         a2 = alpha0*(~(Z2(:,t-1).*tempZ2(:,t)))+alpha1*(Z2(:,t-1).*tempZ2(:,t)) +Z2(:,t);
%         b2 = beta0*(~(Z2(:,t-1).*tempZ2(:,t)))+beta1*(Z2(:,t-1).*tempZ2(:,t)) +1 - Z2(:,t);

        Pi2(:,t) = betarnd(a2,b2);
    end

    %---------------------------------------------------------------
    % noise component sampling
    %---------------------------------------------------------------

    %Sample gamma_epsi
    e1 = e0 + 0.5*P*N;
    f1 = f0 + 0.5*sum(sum(X.^2));
    gamma_epsi = gamrnd(e1,1./f1);

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

    % Collect samples
    if iter>MCMCpara.nBurnin
        ii = ceil(iter-MCMCpara.nBurnin);

%         Lowrank_Comp(:,:,ii) = D*diag(Delta.*Z)*S;
%         Sparse_Comp(:,:,ii) = S2.*Z2;
        Lowrank_Comp = Lowrank_Comp + D*diag(Delta.*Z)*S;
        Sparse_Comp = Sparse_Comp + S2.*Z2;

        Gamma_epsi(ii) = gamma_epsi;
        tmpRank(ii) = length(find(Z~=0));
        %tmpNumSparse(ii) = length(find(Sparse_Comp(:,:,ii)~=0));
        %mse_rec(iter) = sum(sum((X0-Lowrank_Comp{ii}-Sparse_Comp{ii}).^2))/(P*N);
    end

end

% Output.Lowrank_mean = mean(Lowrank_Comp,3);
% Output.Lowrank_std = std(Lowrank_Comp,0,3);
% Output.Sparse_mean = mean(Sparse_Comp,3);
% Output.Sparse_std = std(Sparse_Comp,0,3);
Output.Lowrank_mean = Lowrank_Comp/MCMCpara.nCollect;
Output.Sparse_mean = Sparse_Comp/MCMCpara.nCollect;
Output.Gamma_epsi_mean = mean(Gamma_epsi);
Output.Gamma_epsi_std = std(Gamma_epsi);
Output.rankL_mean = mean(tmpRank);
Output.rankL_std = std(tmpRank);
% Output.NumSparse_mean = mean(tmpNumSparse);
% Output.NumSparse_std = std(tmpNumSparse);
end


function [MFCC] = VAD_MFCC(wave,Fs)

%% Extracts MFCC features from the speech signal

frameL=30;
frameshift=10;

Nfft=1024;

Start=1;
Stop=round(frameL/1000*Fs);
Shift=round(frameshift/1000*Fs);
Ind=1;
Win=blackman(Stop);
Es=[];

wave=filter([1 -0.97],1,wave);

while Stop<length(wave)
    Seg=wave(Start:Stop);
    Seg=Seg.*Win;

    Spec=fft(Seg,Nfft);

    mfcc = hspec2fwcep(abs(Spec(1:end/2+1)), Fs, 12);

    MFCC(Ind,:)=mfcc;

    Start=Start+Shift;
    Stop=Stop+Shift;
    Ind=Ind+1;
end

for i = 1 : 13
    MFCC( :, i ) = MFCC( : , i ) - mean(MFCC( : , i));
end

MFCC=MFCC';


function [seg,glo]=snrseg(s,r,fs,m,tf)
%SNRSEG Measure segmental and global SNR [SEG,GLO]=(S,R,FS,M,TF)
%
%Usage: (1) seg=snrseg(s,r,fs);                  % s & r are noisy and clean signal
%       (2) seg=snrseg(s,r,fs,'wz');             % no VAD or inerpolation used ['Vq' is default]
%       (3) [seg,snr]=snrseg(s,r,fs,'Vq',0.03);  % 30 ms frames
%
% Inputs:    s  test signal
%            r  reference signal
%           fs  sample frequency (Hz)
%            m  mode [default = 'V']
%                 w = No VAD - use whole file
%                 v = use sohn VAD to discard silent portions
%                 V = use P.56-based VAD to discard silent portions [default]
%                 a = A-weight the signals
%                 b = weight signals by BS-468
%                 q = use quadratic interpolation to remove delays +- 1 sample
%                 z = do not do any alignment
%                 p = plot results
%           tf  frame increment [0.01]
%
% Outputs: seg = Segmental SNR in dB
%          glo = Global SNR in dB (typically 7 dB greater than SNR-seg)
%
% This function compares a noisy signal, S, with a clean reference, R, and
% computes the segemntal signal-to-noise ratio (SNR) in dB. The signals,
% which must be of the same length, are split into non-overlapping frames
% of length TF (default 10 ms) and the SNR of each frame in dB is calculated.
% The segmental SNR is the average of these values, i.e.
%         SEG = mean(10*log10(sum(Ri^2)/sum((Si-Ri)^2))
% where the mean is over frames and the sum runs over one particular frame.
% Two optional modifications can be made to this basic formula:
%
%    (a) Frames are excluded if there is no significant energy in the R
%        signal. The idea is to limit the calculation to frames in which
%        speech is active. By default, the voicebox function "activlev" is
%        used to detect the inactive frames (the 'V' mode option).
%
%    (b) In each frame independently, the reference signal is shifted by up
%        to +- 1 sample to find the alignment than minimizes the noise
%        component (S-R)^2. This shifting accounts for small misalignments
%        and/or sample frequency differences between the two signals. For
%        larger shifts, you can use the voicebox function "sigalign".
%        Accurate alignemnt is especially important at high SNR values.
%
% If no M argument is specified, both these modifications will be applied;
% this is equivalent to specifying M='Vq'.

% Bugs/suggestions
% (1) Optionally restrict the bandwidth to the smaller of the two
%     bandwidths either with an extra parameter or automatically determined

%      Copyright (C) Mike Brookes 2011
%      Version: $Id: snrseg.m,v 1.4 2011/07/08 08:12:34 dmb Exp $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if nargin<4 || ~ischar(m)
    m='Vq';
end
if nargin<5 || ~numel(tf)
    tf=0.01; % default frame length is 10 ms
end
snmax=100;  % clipping limit for SNR

% filter the input signals if required

if any(m=='a')  % A-weighting
    [b,a]=stdspectrum(2,'z',fs);
    s=filter(b,a,s);
    r=filter(b,a,r);
elseif any(m=='b') %  BS-468 weighting
    [b,a]=stdspectrum(8,'z',fs);
    s=filter(b,a,s);
    r=filter(b,a,r);
end

mq=~any(m=='z');
nr=min(length(r), length(s));
kf=round(tf*fs); % length of frame in samples
ifr=kf+mq:kf:nr-mq; % ending sample of each frame
ifl=ifr(end);
nf=numel(ifr);
rf=sum(reshape(r(mq+1:ifl).^2,kf,nf),1);
ef=sum(reshape((s(mq+1:ifl)-r(mq+1:ifl)).^2,kf,nf),1);
if mq
    efm=sum(reshape((s(3:ifl+1)-r(2:ifl)).^2,kf,nf),1);
    efp=sum(reshape((s(1:ifl-1)-r(2:ifl)).^2,kf,nf),1);
    efa=0.5*(efp+efm)-ef;
    efb=0.5*(efp-efm);
    efmk=(abs(efb)<2*efa) & (efa>0); % mask for frames with a valid minimum
    if any(efmk)
        ef(efmk)=ef(efmk)-0.25*efb(efmk).^2./efa(efmk);
    end
    ef=min(min(ef,efm),efp);
end

em=ef==0; % mask for zero noise frames
rm=rf==0; % mask for zero reference frames
snf=10*log10((rf+rm)./(ef+em));
snf(rm)=-snmax;
snf(em)=snmax;

% select the frames to include

if any(m=='w')
    vf=ones(1,nf); % include all frames
elseif any(m=='v');
    vs=vadsohn(r,fs,'na');
    nvs=length(vs);
    [vss,vix]=sort([ifr'; vs(:,2)]);
    vjx=zeros(nvs+nf,5);
    vjx(vix,1)=(1:nvs+nf)'; % sorted position
    vjx(1:nf,2)=vjx(1:nf,1)-(1:nf)'; % prev VAD frame end (or 0 or nvs+1 if none)
    vjx(nf+1:end,2)=vjx(nf+1:end,1)-(1:nvs)'; % prev snr frame end (or 0 or nvs+1 if none)
    dvs=[vss(1)-mq; vss(2:end)-vss(1:end-1)];  % number of samples from previous frame boundary
    vjx(:,3)=dvs(vjx(:,1)); % number of samples from previous frame boundary
    vjx(1:nf,4)=vs(min(1+vjx(1:nf,2),nvs),3); % VAD result for samples between prev frame boundary and this one
    vjx(nf+1:end,4)=vs(:,3); % VAD result for samples between prev frame boundary and this one
    vjx(1:nf,5)=1:nf; % SNR frame to accumulte into
    vjx(vjx(nf+1:end,2)>=nf,3)=0;  % zap any VAD frame beyond the last snr fram
    vjx(nf+1:end,5)=min(vjx(nf+1:end,2)+1,nf); % SNR frame to accumulate into
    vf=full(sparse(1,vjx(:,5),vjx(:,3).*vjx(:,4),1,nf))>kf/2; % accumulate into SNR frames and compare with threshold
else  % default is 'V'
    [lev,af,fso,vad]=activlev(r,fs);    % do VAD on reference signal
    vf=sum(reshape(vad(mq+1:ifl),kf,nf),1)>kf/2; % find frames that are mostly active
end
seg=mean(snf(vf));
glo=10*log10(sum(rf(vf))/sum(ef(vf)));

if ~nargout || any (m=='p')
    subplot(311);
    plot((1:length(s))/fs,s);
    ylabel('Signal');
    title(sprintf('SNR = %.1f dB, SNR_{seg} = %.1f dB',glo,seg));
    axh(1)=gca;
    subplot(312);
    plot((1:length(r))/fs,r);
    ylabel('Reference');
    axh(2)=gca;
    subplot(313);
    snv=snf;
    snv(~vf)=NaN;
    snu=snf;
    snu(vf>0)=NaN;
    plot([1 nr]/fs,[glo seg; glo seg],':k',((1:nf)*kf+(1-kf)/2)/fs,snv,'-b',((1:nf)*kf+(1-kf)/2)/fs,snu,'-r');
    ylabel('Frame SNR');
    xlabel('Time (s)');
    axh(3)=gca;
    linkaxes(axh,'x');
end


%filename='test2d_micro';
filename = 'MicroQuad';
ptype = 'MICRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'circleInclusion';
cost={'chomog_alphabeta'};
weights=[1];
constraint = {'volumeConstraint'};
constraint_case = 'EQUALITY';
%incrementFactor = 1;
designVariable = 'Density';
%designVariable = 'LevelSet';
filterType = 'PDE';
fracRadius = 0.51;
%optimizer = 'IPOPT';
optimizer = 'DualNestedInPrimal';
%optimizer = 'AlternatingPrimalDual';

optimizerUnconstrained = 'PROJECTED GRADIENT';
line_search_initiator = 'INCREASING LAST STEP';
incrementFactor = 1.95;

%optimizerUnconstrained = 'SLERP';

nsteps = 1;
Vfrac_final = 0.4;
Perimeter_target=1;
optimality_final = 0.2*1e-3;
constr_final =1e-12;

Vfrac_initial = 0.8;
optimality_initial = 0.2*1e-3;
constr_initial = 1e-12;

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

%Micro
epsilon_isotropy_initial=1e-1;
epsilon_isotropy_final = 1e-3;
micro.alpha =[1 1 0]';
micro.beta =[1 1 0]';

%nsteps = 10;

% For all tests
plotting = true;
printing = true;
monitoring = true;
monitoring_interval = 1;
maxiter = 200;


function [mi] = yd2mi(yd)
% Convert length from yards to miles.
% Chad Greene 2012
mi = yd*0.0005681818181818;


function [F1c,F2c,F1,F2,C1,C2,VT]=truncatedOctahedronMesh(varargin)

% function [F1c,F2c,F1,F2,C1,C2,VT]=truncatedOctahedronMesh(r,nCopies)
% ------------------------------------------------------------------------
%
%
%
% Kevin Mattheus Moerman
% gibbon.toolbox@gmail.com
%
% 2019/02/08 Created
% 2019/10/13
% ------------------------------------------------------------------------

%% Parse input

switch nargin
    case 1
        r=varargin{1};
        nCopies=2;
    case 2
        r=varargin{1};
        nCopies=varargin{2};
end

if isempty(nCopies)
    nCopies=2;
end

if numel(nCopies)==1
    nCopies=nCopies*ones(1,3);
end

%%
%Get truncated octahedron
[Fs,Vs,~]=truncatedOctahedron(r);
Fs1=Fs{1}; %hexagon faces
Fs2=Fs{2}; %quadrilateral faces

%Rotate
[R,~]=euler2DCM([0 0 0.25*pi]); %Define rotation
Vs=Vs*R; %Rotate coordinates

%Derive face centre points for offsets
% Vn=patchCentre(Fs,Vs);
Xi=Vs(:,1); Yi=Vs(:,2); Zi=Vs(:,3);
Vn=[mean(Xi(Fs2),2) mean(Yi(Fs2),2) mean(Zi(Fs2),2)];

%%
nTotal=prod(nCopies); %Total number of copies
offsetDirs=[1 2 6]; %Offset direction N.B. varying these affects the offsets/signs below

%Create cell indices for vertices
indC=ones(size(Vs,1),1)*(1:1:nTotal);
indC=indC(:);
[I,J,K] = ind2sub(nCopies,indC);
I=I-1; J=J-1; K=K-1;

%Create cell indices for quad faces
indF1=ones(size(Fs1,1),1)*(1:1:nTotal);
indF1=indF1(:);
indF1=(indF1-1);

indF2=ones(size(Fs2,1),1)*(1:1:nTotal);
indF2=indF2(:);
indF2=(indF2-1);

%Defining the quad faces matrix
F1=repmat(Fs1,nTotal,1)+size(Vs,1).*indF1(:,ones(1,size(Fs1,2)));
F2=repmat(Fs2,nTotal,1)+size(Vs,1).*indF2(:,ones(1,size(Fs2,2)));

%Defining offsets
sK=iseven(K); %Shift is adjusted according to z coordinate to create a "cube"
D1=I*2*Vn(offsetDirs(1),:)+(sK*Vn(offsetDirs(1),:)); % X offsets
D2=J*2*Vn(offsetDirs(2),:)+(sK*Vn(offsetDirs(2),:)); % Y offsets
D3=K*Vn(offsetDirs(3),:); % Z offsets

D=D1+D2+D3;

%Defining vertices matrix
VT=repmat(Vs,nTotal,1)+D;

%Merge points
[F1,VT,~,ind2]=mergeVertices(F1,VT);
F2=ind2(F2);

C1=indF1+1; %Index or color number
C2=indF2+1; %Index or color number

%Split up face matrix in to cell groups
F1c=mat2cell(F1,size(Fs1,1)*ones(1,nTotal),size(Fs1,2));
F2c=mat2cell(F2,size(Fs2,1)*ones(1,nTotal),size(Fs2,2));

end

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


function [outexpdir] = ConvertMWTContour2Trx(experiment_name,rootoutputdir,varargin)

%% set parameters

% default parameters
rootdatadir = '/groups/branson/home/bransonk/behavioranalysis/code/Jdetect/data/larvae_mwt/rawdata';
contourext = 'outline';
trxfilestr = 'trx.mat';
perframedirstr = 'perframe';
MINDT = .001;
pxpermm = 11.111;
maxlength_mm = 5;
DEBUG = false;
makesoftlink = true;

[rootdatadir,contourext,trxfilestr,perframedirstr,DEBUG,maxlength_mm,pxpermm,makesoftlink] = ...
  myparse(varargin,...
  'rootdatadir',rootdatadir,...
  'contourext',contourext,...
  'trxfilestr',trxfilestr,...
  'perframedirstr',perframedirstr,...
  'debug',DEBUG,...
  'maxlength',maxlength_mm,...
  'pxpermm',pxpermm,...
  'makesoftlink',makesoftlink);

maxlength_px = ceil(maxlength_mm * pxpermm);

%% names of files

% find contour files for each trajectory
files = dir(fullfile(rootdatadir,[experiment_name,'.*.',contourext]));
contournames = {};
ids = [];
for i = 1:numel(files),
  match = regexp(files(i).name,['\.(\d+)\.',contourext,'$'],'tokens','once');
  if isempty(match),
    continue;
  end
  contournames{end+1} = fullfile(rootdatadir,files(i).name);
  ids(end+1) = str2double(match{1});
end

if isempty(contournames),
  error('Could not find any contours matching the pattern %s.*.%s',fullfile(rootdatadir,experiment_name),contourext);
end

ncontours = numel(contournames);

%% put all the contours into one trx file

% read everthing in from the contour files
alltimestamps = {};
trx = [];
arena = struct('x',nan,'y',nan,'r',nan);
for i = 1:ncontours,

  trk = struct('id',ids(i),'xcontour',{{}},'ycontour',{{}});
  timestamps = [];
  fid = fopen(contournames{i},'r');
  j = 1;
  while true,
    s = fgetl(fid);
    if ~ischar(s),
      break;
    end
    d = sscanf(s,'%f');
    if numel(d) < 3,
      warning('Contour line %s length < 3, skipping this line',s);
      continue;
    end
    if mod(numel(d),2) ~= 1,
      warning('Contour line %s length is not odd, skipping this line',s);
      continue;
    end
    d = d';
    timestamp = d(1);
    x = d(2:2:end-1);
    y = d(3:2:end);
    trk.xcontour{j} = x;
    trk.ycontour{j} = y;
    timestamps(j) = timestamp;
    j = j + 1;
  end
  fclose(fid);
  trk.arena = arena;
  alltimestamps{i} = timestamps;
  trx = structappend(trx,trk);
end

% make all the timestamps agree with each other
timestamps = union(alltimestamps{:});
dts = diff(timestamps);
% sanity check to look for rounding errors
if any(dts < MINDT),
  error('Rounding error check failed: there are timestamps < %f apart',MINDT);
end
t0s = cellfun(@(x) x(1), alltimestamps);
t1s = cellfun(@(x) x(end), alltimestamps);
fps = nanmean(dts);
for i = 1:ncontours,
  trx(i).firstframe = find(t0s(i) >= timestamps,1);
  trx(i).endframe = find(t1s(i) >= timestamps,1,'last');
  trx(i).off = 1 - trx(i).firstframe;
  % sanity check to make sure this matches the number of frames
  n = trx(i).endframe - trx(i).firstframe + 1;
  if numel(trx(i).xcontour) ~= n,
    error('Number of frames check failed: Number of frames of contour data does not match start and end timestamps');
  end
  trx(i).dt = dts(trx(i).firstframe:trx(i).endframe-1);
  trx(i).nframes = n;
  trx(i).fps = fps;
end

%% fit ellipses

[XGRID,YGRID] = meshgrid(0:maxlength_px-1,0:maxlength_px-1);

for i = 1:ncontours,

  trx(i).x = nan(1,trx(i).nframes);
  trx(i).y = nan(1,trx(i).nframes);
  trx(i).x_mm = nan(1,trx(i).nframes);
  trx(i).y_mm = nan(1,trx(i).nframes);
  trx(i).a = nan(1,trx(i).nframes);
  trx(i).b = nan(1,trx(i).nframes);
  trx(i).a_mm = nan(1,trx(i).nframes);
  trx(i).b_mm = nan(1,trx(i).nframes);
  trx(i).theta = nan(1,trx(i).nframes);
  trx(i).theta_mm = nan(1,trx(i).nframes);

  for t = 1:trx(i).nframes,

    % create an image
    xc = round(trx(i).xcontour{t}*pxpermm);
    yc = round(trx(i).ycontour{t}*pxpermm);
    minx = min(xc);
    maxx = max(xc);
    miny = min(yc);
    maxy = max(yc);
    nx = maxx-minx+1;
    ny = maxy-miny+1;
    bw = [inpolygon(XGRID(1:ny,1:nx),YGRID(1:ny,1:nx),[xc,xc(1)]-minx,[yc,yc(1)]-miny);false(maxlength_px-ny,nx)];

    % fit an ellipse
    x = XGRID(bw)+minx;
    y = YGRID(bw)+miny;
    mux = nanmean(x);
    muy = nanmean(y);
    S = cov([x,y],1);
    [a,b,theta] = cov2ell(S);
    % try and make theta be as continuous as possible
    if t > 1,
      dsame = abs(modrange(trx(i).theta(t-1)-theta,-pi,pi));
      dflip = abs(modrange(trx(i).theta(t-1)-theta+pi,-pi,pi));
      if dflip < dsame,
        theta = modrange(theta+pi,-pi,pi);
      end
    end

    % store quarter-major, quarter-minor axes
    a = a/2;
    b = b/2;
    mux_mm = mux / pxpermm;
    muy_mm = muy / pxpermm;
    a_mm = a / pxpermm;
    b_mm = b / pxpermm;
    trx(i).x(t) = mux_mm;
    trx(i).y(t) = muy_mm;
    trx(i).x_mm(t) = mux_mm;
    trx(i).y_mm(t) = muy_mm;
    trx(i).a(t) = a_mm;
    trx(i).b(t) = b_mm;
    trx(i).a_mm(t) = a_mm;
    trx(i).b_mm(t) = b_mm;
    trx(i).theta(t) = theta;
    trx(i).theta_mm(t) = theta;

    if DEBUG,
      hold off;
      plot(trx(i).xcontour{t},trx(i).ycontour{t},'k.-');
      hold on;
      drawellipse(trx(i).x(t),trx(i).y(t),trx(i).theta(t),trx(i).a(t)*2,trx(i).b(t)*2,'r');
      axis equal;
      title(num2str(t));
      drawnow;
    end

  end

end

%% plot the trajectories

if DEBUG,

nframes = numel(timestamps);
colors = jet(ncontours)*.7;
for t = 1:nframes,
  hold off;
  for i = 1:ncontours,
    if t > trx(i).endframe || t < trx(i).firstframe,
      continue;
    end
    j = t + trx(i).off;
    plot(trx(i).xcontour{j},trx(i).ycontour{j},'.-','color',colors(i,:));
    hold on;
    drawellipse(trx(i).x(j),trx(i).y(j),trx(i).theta(j),trx(i).a(j)*2,trx(i).b(j)*2,'color','r');
  end
  axis equal;
  drawnow;
end

end

%% create output directory

% make sure the root output directory exists
if ~exist(rootoutputdir,'dir'),
  mkdir(rootoutputdir);
end

% create the experiment directory
outexpdir = fullfile(rootoutputdir,experiment_name);
if ~exist(outexpdir,'dir'),
  mkdir(outexpdir);
end

%% create the trx file

outmatname = fullfile(outexpdir,trxfilestr);
save(outmatname,'trx');

%% copy over the contour files
for i = 1:ncontours,
  [~,basename] = myfileparts(contournames{i});
  outcontourname = fullfile(outexpdir,basename);
  if isunix && makesoftlink,
    cmd = sprintf('ln -s %s %s',contournames{i},outcontourname);
    unix(cmd);
  else
    [success,msg] = copyfile(contournames{i},outcontourname);
    if ~success,
      error('Error copying file %s to %s: %s',moviename,outmoviename,msg);
    end
  end
end

%% save the per-frame features
perframedir = fullfile(outexpdir,perframedirstr);
if ~exist(perframedir,'dir'),
  mkdir(perframedir);
end

% to do: save choreography's per-frame features


function [r0,u0,p0] = Euler_IC1d(x,input)
% Load the IC of a classical 2D Riemann Problem configuration.
% By Manuel Diaz 2012.10.24.
% In the notation we take advantage of the matlab array notation as follows
%
% prop = [prop_left , prop_right]
%
% Notation:
% u   = Velocity in x direction
% p   = Pressure
% rho = Density
% r   = Fugacity
% E   = Enerty
% t   = temperature
%
% Based on:
% http://wonka.physics.ncsu.edu/pub/VH-1/testpage/ and
% http://sitemaker.umich.edu/anand/files/riemann_shock-tube.pdf
% See also my routine CFD/Riemann.m to compute exact solutions.
%
%% Initial Physical Properties per case:
switch input
    case{1} % Configuration 1, Sod's Problem
        fprintf('Case 1: Sods problem \n');
        p   = [1    0.1  ];
        u   = [0.75 0    ];
        rho = [1    0.125];

    case{2} % Configuration 2, Left Expansion and right strong shock
        fprintf('Case 2: Left Expansion and right strong shock \n');
        p   = [1000 0.1  ];
        u   = [0    0    ];
        rho = [3    2    ];

    case{3} % Configuration 3, Right Expansion and left strong shock
        fprintf('Case 3: Right Expansion and left strong shock \n');
        p   = [7    10   ];
        u   = [0    0    ];
        rho = [1    1    ];

    case{4} % Configuration 4, Double Shock
        fprintf('Case 4: Double Shock \n');
        p   = [450  45   ];
        u   = [20   -6   ];
        rho = [6    6    ];

    case{5} % Configuration 5, Double Expansion
        fprintf('Case 5: Double Expansion \n');
        p   = [40   40   ];
        u   = [-2   2    ];
        rho = [1    2.5  ];

    case{6} % Configuration 6, Cavitation
        fprintf('Case 6: Cavitation \n');
        p   = [0.4  0.4  ];
        u   = [-20  20   ];
        rho = [1    1    ];

    otherwise
        error('Available cases: 1, 2, 3, 4, 5 and 6');

end
% Print
fprintf('\n');
fprintf('density (L): %1.3f\n',rho(1));
fprintf('velocity(L): %1.3f\n',u(1));
fprintf('Presure (L): %1.3f\n',p(1));
fprintf('\n');
fprintf('density (R): %1.3f\n',rho(2));
fprintf('velocity(R): %1.3f\n',u(2));
fprintf('Presure (R): %1.3f\n',p(2));
fprintf('\n');

%% Load Selected case Initial condition:
% number of points required
 nx = length(x);

% Parameters of regions dimensions
x_middle = ceil(nx/2);
l_1 = 1:x_middle; l_2 = x_middle+1:nx;

% Pre-Allocate variables
r0 = zeros(1,nx);
u0 = zeros(1,nx);
p0 = zeros(1,nx);

% Initial Condition for our 2D domain
% Fugacity
r0(l_1) = rho(1); % region 1
r0(l_2) = rho(2); % region 2
% Velovity in x
u0(l_1) = u(1); % region 1
u0(l_2) = u(2); % region 2
% temperature
p0(l_1) = p(1); % region 1
p0(l_2) = p(2); % region 2


function product_rule ( list_filename, quad_filename )

%*****************************************************************************80
%
%% MAIN is the main program for PRODUCT_RULE.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 May 2007
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n');
  fprintf ( 1, 'PRODUCT_RULE\n');
  fprintf ( 1, '  MATLAB version\n');
  fprintf ( 1, '\n');
  fprintf ( 1, '  Create a multidimensional product rule\n');
  fprintf ( 1, '  as a product of distinct 1D integration rules.\n');
%
%  Get the list filename.
%
  if ( nargin < 1 )

    fprintf ( 1, '\n' );
    fprintf ( 1, 'PRODUCT_RULE:\n' );
    list_filename = input ( '  Enter the name of the file listing the factors.' );

  end
%
%  Get the product file prefix.
%
  if ( nargin < 2 )

    fprintf ( 1, '\n' );
    fprintf ( 1, 'PRODUCT_RULE:\n' );
    quad_filename = input ( '  Enter the product file prefix to use.' );

  end
%
%  Count the items in the list file.
%
  list_num = file_row_count ( list_filename );
%
%  Determine the spatial dimension and number of points in the product.
%
  dim_num = list_num;
  point_num = product_rule_size ( list_filename, list_num );
%
%  Allocate the product items.
%
  x(1:dim_num,1:point_num) = 0.0;
  w(1:point_num) = 1.0;
  r(1:dim_num,1:2) = 0.0;

  list_unit = fopen ( list_filename, 'rt' );

  if ( list_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'PRODUCT_RULE - Fatal error!\n' );
    fprintf ( 1, '  Nonzero value of IOS while opening list file.\n' );
    error ( 'PRODUCT_RULE - Fatal error!' );
  end
%
%  Read the factor information and apply it.
%
  for dim = 1 : dim_num

    quad_1d_filename = fgetl ( list_unit );

    quad_x_1d_filename = strcat ( quad_1d_filename, '_x.txt' );
    quad_w_1d_filename = strcat ( quad_1d_filename, '_w.txt' );
    quad_r_1d_filename = strcat ( quad_1d_filename, '_r.txt' );
%
%  Read the X file.
%
    [ dim_num_1d, point_num_1d ] = r8mat_header_read ( quad_x_1d_filename );

    if ( dim_num_1d ~= 1 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'PRODUCT_RULE - Fatal error!\n' );
      fprintf ( 1, '  The 1D quadrature abscissa file should have exactly\n' );
      fprintf ( 1, '  one value on each line.\n' );
      error ( 'PRODUCT_RULE - Fatal error!' );
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Number of points in 1D rule = %d\n', point_num_1d );

    x_1d = r8mat_data_read ( quad_x_1d_filename, dim_num_1d, point_num_1d );
%
%  Read the W file.
%
    [ dim_num_1d, point_num_1d2 ] = r8mat_header_read ( quad_w_1d_filename );

    if ( dim_num_1d ~= 1 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'PRODUCT_RULE - Fatal error!\n' );
      fprintf ( 1, '  The 1D quadrature weight file should have exactly\n' );
      fprintf ( 1, '  one value on each line.\n' );
      error ( 'PRODUCT_RULE - Fatal error!' );
    end

    if ( point_num_1d2 ~= point_num_1d )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'PRODUCT_RULE - Fatal error!\n' );
      fprintf ( 1, '  The 1D quadrature weight file should have exactly\n' );
      fprintf ( 1, '  the same number of lines as the abscissa file.\n' );
      error ( 'PRODUCT_RULE - Fatal error!' );
    end

    w_1d = r8mat_data_read ( quad_w_1d_filename, dim_num_1d, point_num_1d );
%
%  Read the R file.
%
    [ dim_num_1d, point_num_1d2 ] = r8mat_header_read ( quad_r_1d_filename );

    if ( dim_num_1d ~= 1 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'PRODUCT_RULE - Fatal error!\n' );
      fprintf ( 1, '  The 1D quadrature region file should have exactly\n' );
      fprintf ( 1, '  one value on each line.\n' );
      error ( 'PRODUCT_RULE - Fatal error!' );
    end

    if ( point_num_1d2 ~= 2 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'PRODUCT_RULE - Fatal error!\n' );
      fprintf ( 1, '  The 1D quadrature region file should have exactly\n' );
      fprintf ( 1, '  two lines.\n' );
      error ( 'PRODUCT_RULE - Fatal error!' );
    end

    r_1d = r8mat_data_read ( quad_r_1d_filename, 1, 2 );
%
%  Update the X, W, and R of the product rule.
%
    x = r8vec_direct_product ( dim, point_num_1d, x_1d, dim_num, point_num, x );

    w = r8vec_direct_product2 ( dim, point_num_1d, w_1d, dim_num, point_num, w );

    r(dim,1) = r_1d(1);
    r(dim,2) = r_1d(2);

  end

  fclose ( list_unit );
%
%  Write the product rule.
%
  quad_x_filename = strcat ( quad_filename, '_x.txt' );
  quad_w_filename = strcat ( quad_filename, '_w.txt' );
  quad_r_filename = strcat ( quad_filename, '_r.txt' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Creating product quadrature rule X file = "%s".\n', ...
    quad_x_filename );

  r8mat_write ( quad_x_filename, dim_num, point_num, x );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Creating product quadrature rule W file = "%s".\n', ...
    quad_w_filename );

  r8mat_write ( quad_w_filename, 1, point_num, w );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Creating product quadrature rule R file = "%s".\n', ...
    quad_r_filename );

  r8mat_write ( quad_r_filename, dim_num, 2, r );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'PRODUCT_RULE:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function column_num = file_column_count ( input_file_name )

%*****************************************************************************80
%
%% FILE_COLUMN_COUNT counts the columns in the first line of a file.
%
%  Discussion:
%
%    The file is assumed to be a simple text file.
%
%    Most lines of the file are presumed to consist of COLUMN_NUM words,
%    separated by spaces.  There may also be some blank lines, and some
%    comment lines, which have a "#" in column 1.
%
%    The routine tries to find the first non-comment non-blank line and
%    counts the number of words in that line.
%
%    If all lines are blanks or comments, it goes back and tries to analyze
%    a comment line.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 February 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the name of the file.
%
%    Output, integer COLUMN_NUM, the number of columns in the file.
%
  FALSE = 0;
  TRUE = 1;
%
%  Open the file.
%
  input_unit = fopen ( input_file_name );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_COLUMN_COUNT - Error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', input_file_name );
    error ( 'FILE_COLUMN_COUNT - Error!' );
  end
%
%  Read one line, but skip blank lines and comment lines.
%  Use FGETL so we drop the newline character!
%
  got_one = FALSE;

  while ( 1 )

    line = fgetl ( input_unit );

    if ( line == -1 )
      break;
    end

    if ( s_len_trim ( line ) == 0 )

    elseif ( line(1) == '#' )

    else
      got_one = TRUE;
      break;
    end

  end

  fclose ( input_unit );

  if ( got_one == FALSE )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_COLUMN_COUNT - Warning!\n' );
    fprintf ( 1, '  The file does not seem to contain any data.\n' );
    column_num = -1;
    return;
  end

  column_num = s_word_count ( line );

  return
end
function row_num = file_row_count ( input_file_name )

%*****************************************************************************80
%
%% FILE_ROW_COUNT counts the number of row records in a file.
%
%  Discussion:
%
%    Each input line is a "RECORD".
%
%    The records are divided into three groups:
%
%    * BLANK LINES (nothing but blanks)
%    * COMMENT LINES (begin with a '#')
%    * DATA RECORDS (anything else)
%
%    The value returned by the function is the number of data records.
%
%    By the way, if the MATLAB routine FGETS is used, instead of
%    FGETL, then the variable LINE will include line termination
%    characters, which means that a blank line would not actually
%    have zero characters.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 December 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the name of the input file.
%
%    Output, integer ROW_NUM, the number of rows found.
%
  input_unit = fopen ( input_file_name );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_ROW_COUNT - Error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', input_file_name );
    error ( 'FILE_ROW_COUNT - Error!' );
  end

  blank_num = 0;
  comment_num = 0;
  row_num = 0;

  record_num = 0;

  while ( 1 )

    line = fgetl ( input_unit );

    if ( line == -1 )
      break;
    end

    record_num = record_num + 1;
    record_length = s_len_trim ( line );

    if ( record_length <= 0 )
      blank_num = blank_num + 1;
    elseif ( line(1) == '#' )
      comment_num = comment_num + 1;
    else
      row_num = row_num + 1;
    end

  end

  fclose ( input_unit );

  return
end
function point_num = product_rule_size ( list_filename, list_num )

%*****************************************************************************80
%
%% PRODUCT_RULE_SIZE returns the size of a product rule of distinct factors.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 May 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string LIST_FILENAME, a file containing a list
%    of prefixes defining quadrature rules.
%
%    Input, integer LIST_NUM, the number of prefixes in the file.
%
%    Output, integer POINT_NUM, the number of points in the product rule.
%
  point_num = 1;

  list_unit = fopen ( list_filename, 'rt' );

  if ( list_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'PRODUCT_RULE_SIZE - Fatal error!\n' );
    fprintf ( 1, '  Nonzero value of IOS while opening list file.\n' );
    error ( 'PRODUCT_RULE_SIZE - Fatal error!' );
  end

  for list = 1 : list_num

    quad_1d_filename = fgetl ( list_unit );

    quad_x_1d_filename = strcat ( quad_1d_filename, '_x.txt' );

    [ dim_num_1d, point_num_1d ] = r8mat_header_read ( quad_x_1d_filename );

    point_num = point_num * point_num_1d;

  end

  fclose ( list_unit );

  return
end
function table = r8mat_data_read ( input_filename, m, n )

%*****************************************************************************80
%
%% R8MAT_DATA_READ reads data from an R8MAT file.
%
%  Discussion:
%
%    An R8MAT is an array of R8's.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 January 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Input, integer M, N, the number of rows and columns of data.
%
%    Output, real TABLE(M,N), the point coordinates.
%
  table = zeros ( m, n );
%
%  Build up the format string for reading M real numbers.
%
  string = ' ';

  for i = 0 : m
    string = strcat ( string, ' %f' );
  end

  input_unit = fopen ( input_filename );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_DATA_READ - Error!\n' );
    fprintf ( 1, '  Could not open the file.\n' );
    error ( 'R8MAT_DATA_READ - Error!' );
  end

  i = 0;

  while ( i < n )

    line = fgets ( input_unit );

    if ( line == -1 )
      break;
    end

    if ( line(1) == '#' )

    elseif ( s_len_trim ( line ) == 0 )

    else

      [ x, count ] = sscanf ( line, string );

      if ( count == m )
        i = i + 1;
        table(1:m,i) = x(1:m);
      end

    end

  end

  fclose ( input_unit );

  return
end
function [ m, n ] = r8mat_header_read ( input_filename )

%*****************************************************************************80
%
%% R8MAT_HEADER_READ reads the header from an R8MAT file.
%
%  Discussion:
%
%    An R8MAT is an array of R8's.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Output, integer M, the spatial dimension.
%
%    Output, integer N, the number of points.
%
  m = file_column_count ( input_filename );

  if ( m <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data columns in\n' );
    fprintf ( 1, '  the file %s.\n', input_filename );
  end

  n = file_row_count ( input_filename );

  if ( n <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data rows in\n' );
    fprintf ( 1, '  the file %s\n', input_filename );
  end

  return
end
function r8mat_write ( output_filename, m, n, table )

%*****************************************************************************80
%
%% R8MAT_WRITE writes an R8MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 August 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, real TABLE(M,N), the points.
%

%
%  Open the file.
%
  output_unit = fopen ( output_filename, 'wt' );

  if ( output_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_WRITE - Error!\n' );
    fprintf ( 1, '  Could not open the output file.\n' );
    error ( 'R8MAT_WRITE - Error!' );
  end
%
%  Write the data.
%
%  For smaller data files, and less precision, try:
%
%     fprintf ( output_unit, '  %14.6f', table(i,j) );
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %24.16f', table(i,j) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

  return
end
function x = r8vec_direct_product ( factor_index, factor_order, ...
  factor_value, factor_num, point_num, x )

%*****************************************************************************80
%
%% R8VEC_DIRECT_PRODUCT creates a direct product of R8VEC's.
%
%  Discussion:
%
%    To explain what is going on here, suppose we had to construct
%    a multidimensional quadrature rule as the product of K rules
%    for 1D quadrature.
%
%    The product rule will be represented as a list of points and weights.
%
%    The J-th item in the product rule will be associated with
%      item J1 of 1D rule 1,
%      item J2 of 1D rule 2,
%      ...,
%      item JK of 1D rule K.
%
%    In particular,
%      X(J) = ( X(1,J1), X(2,J2), ..., X(K,JK))
%    and
%      W(J) = W(1,J1) * W(2,J2) * ... * W(K,JK)
%
%    So we can construct the quadrature rule if we can properly
%    distribute the information in the 1D quadrature rules.
%
%    This routine carries out that task.
%
%    Another way to do this would be to compute, one by one, the
%    set of all possible indices (J1,J2,...,JK), and then index
%    the appropriate information.  An advantage of the method shown
%    here is that you can process the K-th set of information and
%    then discard it.
%
%  Example:
%
%    Rule 1:
%      Order = 4
%      X(1:4) = ( 1, 2, 3, 4 )
%
%    Rule 2:
%      Order = 3
%      X(1:3) = ( 10, 20, 30 )
%
%    Rule 3:
%      Order = 2
%      X(1:2) = ( 100, 200 )
%
%    Product Rule:
%      Order = 24
%      X(1:24) =
%        ( 1, 10, 100 )
%        ( 2, 10, 100 )
%        ( 3, 10, 100 )
%        ( 4, 10, 100 )
%        ( 1, 20, 100 )
%        ( 2, 20, 100 )
%        ( 3, 20, 100 )
%        ( 4, 20, 100 )
%        ( 1, 30, 100 )
%        ( 2, 30, 100 )
%        ( 3, 30, 100 )
%        ( 4, 30, 100 )
%        ( 1, 10, 200 )
%        ( 2, 10, 200 )
%        ( 3, 10, 200 )
%        ( 4, 10, 200 )
%        ( 1, 20, 200 )
%        ( 2, 20, 200 )
%        ( 3, 20, 200 )
%        ( 4, 20, 200 )
%        ( 1, 30, 200 )
%        ( 2, 30, 200 )
%        ( 3, 30, 200 )
%        ( 4, 30, 200 )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer FACTOR_INDEX, the index of the factor being processed.
%    The first factor processed must be factor 1%
%
%    Input, integer FACTOR_ORDER, the order of the factor.
%
%    Input, real FACTOR_VALUE(FACTOR_ORDER), the factor values
%    for factor FACTOR_INDEX.
%
%    Input, integer FACTOR_NUM, the number of factors.
%
%    Input, integer POINT_NUM, the number of elements in the direct product.
%
%    Input, real X(FACTOR_NUM,POINT_NUM), the elements of the
%    direct product, which are built up gradually.
%
%    Output, real X(FACTOR_NUM,POINT_NUM), the elements of the
%    direct product, updated by the latest factor.
%
%  Local Parameters:
%
%    Local, integer START, the first location of a block of values to set.
%
%    Local, integer CONTIG, the number of consecutive values to set.
%
%    Local, integer SKIP, the distance from the current value of START
%    to the next location of a block of values to set.
%
%    Local, integer REP, the number of blocks of values to set.
%
  persistent contig;
  persistent rep;
  persistent skip;

  if ( factor_index == 1 )
    contig = 1;
    skip = 1;
    rep = point_num;
    x(1:factor_num,1:point_num) = 0.0;
  end

  rep = rep / factor_order;
  skip = skip * factor_order;

  for j = 1 : factor_order

    start = 1 + ( j - 1 ) * contig;

    for k = 1 : rep
      x(factor_index,start:start+contig-1) = factor_value(j);
      start = start + skip;
    end

  end

  contig = contig * factor_order;

  return
end
function w = r8vec_direct_product2 ( factor_index, factor_order, ...
  factor_value, factor_num, point_num, w )

%*****************************************************************************80
%
%% R8VEC_DIRECT_PRODUCT2 creates a direct product of R8VEC's.
%
%  Discussion:
%
%    To explain what is going on here, suppose we had to construct
%    a multidimensional quadrature rule as the product of K rules
%    for 1D quadrature.
%
%    The product rule will be represented as a list of points and weights.
%
%    The J-th item in the product rule will be associated with
%      item J1 of 1D rule 1,
%      item J2 of 1D rule 2,
%      ...,
%      item JK of 1D rule K.
%
%    In particular,
%      X(J) = ( X(1,J1), X(2,J2), ..., X(K,JK))
%    and
%      W(J) = W(1,J1) * W(2,J2) * ... * W(K,JK)
%
%    So we can construct the quadrature rule if we can properly
%    distribute the information in the 1D quadrature rules.
%
%    This routine carries out that task for the weights W.
%
%    Another way to do this would be to compute, one by one, the
%    set of all possible indices (J1,J2,...,JK), and then index
%    the appropriate information.  An advantage of the method shown
%    here is that you can process the K-th set of information and
%    then discard it.
%
%  Example:
%
%    Rule 1:
%      Order = 4
%      W(1:4) = ( 2, 3, 5, 7 )
%
%    Rule 2:
%      Order = 3
%      W(1:3) = ( 11, 13, 17 )
%
%    Rule 3:
%      Order = 2
%      W(1:2) = ( 19, 23 )
%
%    Product Rule:
%      Order = 24
%      W(1:24) =
%        ( 2 * 11 * 19 )
%        ( 3 * 11 * 19 )
%        ( 4 * 11 * 19 )
%        ( 7 * 11 * 19 )
%        ( 2 * 13 * 19 )
%        ( 3 * 13 * 19 )
%        ( 5 * 13 * 19 )
%        ( 7 * 13 * 19 )
%        ( 2 * 17 * 19 )
%        ( 3 * 17 * 19 )
%        ( 5 * 17 * 19 )
%        ( 7 * 17 * 19 )
%        ( 2 * 11 * 23 )
%        ( 3 * 11 * 23 )
%        ( 5 * 11 * 23 )
%        ( 7 * 11 * 23 )
%        ( 2 * 13 * 23 )
%        ( 3 * 13 * 23 )
%        ( 5 * 13 * 23 )
%        ( 7 * 13 * 23 )
%        ( 2 * 17 * 23 )
%        ( 3 * 17 * 23 )
%        ( 5 * 17 * 23 )
%        ( 7 * 17 * 23 )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer FACTOR_INDEX, the index of the factor being processed.
%    The first factor processed must be factor 1.
%
%    Input, integer FACTOR_ORDER, the order of the factor.
%
%    Input, real FACTOR_VALUE(FACTOR_ORDER), the factor values for
%    factor FACTOR_INDEX.
%
%    Input, integer FACTOR_NUM, the number of factors.
%
%    Input, integer POINT_NUM, the number of elements in the direct product.
%
%    Output, real W(POINT_NUM), the elements of the
%    direct product, updated by the latest factor.
%
%  Local Parameters:
%
%    Local, integer START, the first location of a block of values to set.
%
%    Local, integer CONTIG, the number of consecutive values to set.
%
%    Local, integer SKIP, the distance from the current value of START
%    to the next location of a block of values to set.
%
%    Local, integer REP, the number of blocks of values to set.
%
  persistent contig;
  persistent rep;
  persistent skip;

  if ( factor_index == 1 )
    contig = 1;
    skip = 1;
    rep = point_num;
    w(1:point_num) = 1.0;
  end

  rep = rep / factor_order;
  skip = skip * factor_order;

  for j = 1 : factor_order

    start = 1 + ( j - 1 ) * contig;

    for k = 1 : rep
      w(start:start+contig-1) = w(start:start+contig-1) * factor_value(j);
      start = start + skip;
    end

  end

  contig = contig * factor_order;

  return
end
function len = s_len_trim ( s )

%*****************************************************************************80
%
%% S_LEN_TRIM returns the length of a character string to the last nonblank.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 June 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string to be measured.
%
%    Output, integer LEN, the length of the string up to the last nonblank.
%
  len = length ( s );

  while ( 0 < len )
    if ( s(len) ~= ' ' )
      return
    end
    len = len - 1;
  end

  return
end
function word_num = s_word_count ( s )

%*****************************************************************************80
%
%% S_WORD_COUNT counts the number of "words" in a string.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 January 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string to be examined.
%
%    Output, integer WORD_NUM, the number of "words" in the string.
%    Words are presumed to be separated by one or more blanks.
%
  FALSE = 0;
  TRUE = 1;

  word_num = 0;
  s_length = length ( s );

  if ( s_length <= 0 )
    return;
  end

  blank = TRUE;

  for i = 1 : s_length

    if ( s(i) == ' ' )
      blank = TRUE;
    elseif ( blank == TRUE )
      word_num = word_num + 1;
      blank = FALSE;
    end

  end

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end


function r = r(kernel)

% R
%
% This method returns an upper bound on
%
%    R > k(x1, x1) - k(x1, x2)
%
% for arbitrary x1 and x2.  For a Gaussian radial basis kernel R = 1.

%
% File        : @rbf/r.m
%
% Date        : Friday 7th July 2000
%
% Author      : Dr Gavin C. Cawley
%
% Description : Part of an object-oriented implementation of Vapnik's Support
%               Vector Machine, as described in [1].
%
% References  : [1] V.N. Vapnik,
%                   "The Nature of Statistical Learning Theory",
%                   Springer-Verlag, New York, ISBN 0-387-94559-8,
%                   1995.
%
% History     : 07/07/2000 - v1.00
%               12/09/2000 - v1.01 minor improvements to comments and help
%                                  messages
%
% Copyright   : (c) Dr Gavin C. Cawley, July 2000
%
%    This program is free software; you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation; either version 2 of the License, or
%    (at your option) any later version.
%
%    This program is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with this program; if not, write to the Free Software
%    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
%

r = 1.0;

% bye bye...


function [stiffness]=assemble(stiffness,k,index)
%----------------------------------------------------------
%  Purpose:
%     Assembly of element matrices into the system matrix
%
%  Synopsis:
%     [stiffness]=assemble(stiffness,k,index)
%
%  Variable Description:
%     stiffness - system matrix
%     k  - element matri
%     index - d.o.f. vector associated with an element
%-----------------------------------------------------------

 edof = length(index);
 for i=1:edof
   ii=index(i);
     for j=1:edof
       jj=index(j);
         stiffness(ii,jj)=stiffness(ii,jj)+k(i,j);
     end
 end


function visualizeCellsRadial2D(phi)
%VISUALIZECELLS plots the values of cell variable phi
%
% SYNOPSIS:
%
%
% PARAMETERS:
%
%
% RETURNS:
%
%
% EXAMPLE:
%
% SEE ALSO:
%

% Written by Ali A. Eftekhari
% See the license file

L = phi.domain.cellcenters.x(end);
x = [phi.domain.facecenters.x(1); phi.domain.cellcenters.x; phi.domain.facecenters.x(end)];
y = [phi.domain.facecenters.y(1); phi.domain.cellcenters.y; phi.domain.facecenters.y(end)];
[TH,R] = meshgrid(y, x);
[X,Y] = pol2cart(TH,R);
h = polar([0 2*pi], [0 L]);
delete(h);
hold on
pcolor(X,Y,phi.value)
colorbar
hold off


function [qt] = gal2qt(gal)
% Convert volume from US liquid gallons to US liquid quarts.
% Chad Greene 2012
qt = gal*4;


function jed2 = jed_to_next_noon ( jed1 )

%*****************************************************************************80
%
%% JED_TO_NEXT_NOON converts a JED to the JED of the next noon.
%
%  Discussion:
%
%    This is primarily to make a fair test of the weekday routines,
%    which have trouble when the JED is at midnight.
%
%    Note that noon corresponds to an integral JED value.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 June 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real JED1, the Julian Ephemeris Date.
%
%    Output, real JED2, the Julian Ephemeris Date
%    of the next noon.
%
  jed2 = round ( jed1 );
%
%  The integer part of JED1 is one of the two integers that
%  bracket JED1.  If it's the smaller one (which it should
%  be as long as JED1 is positive), make it the bigger one.
%
%  This correctly leaves undisturbed cases where JED1 is
%  already an integer, and where JED1 is negative (which
%  is not a case we expect to occur often).
%
  if ( jed2 < jed1 )
    jed2 = jed2 + 1.0;
  end

  return
end


%% Theory of Misorientations
%
%%
% Misorientation describe the relative orientation of two crystal with
% respect to each other. Those crystal may be of the same phase or of
% different phases. Misorientation are used to describe

%% Grain Exchange Symmetry

%%
% Misorientation describes the relative orientation of two grains with
% respect to each other. Important concepts are twinnings and
% CSL (coincidence site lattice) misorientations. To illustrate this
% concept at a practical example let us first import some Magnesium EBSD
% data.

mtexdata twins silent

% use only proper symmetry operations
ebsd('M').CS = ebsd('M').CS.properGroup;

% compute grains
grains = calcGrains(ebsd('indexed'),'threshold',5*degree);
CS = grains.CS; % extract crystal symmetry

%%
% Next we plot the grains together with their mean orientation and
% highlight grain 74 and grain 85

plot(grains,grains.meanOrientation,'micronbar','off')

hold on
plot(grains([74,85]).boundary,'edgecolor','w','linewidth',2)
hold off

text(grains([74,85]),{'1','2'})

%%
% After extracting the mean orientation of grain 74 and 85

ori1 = grains(74).meanOrientation;
ori2 = grains(85).meanOrientation;

%%
% we may compute the misorientation angle between both orientations by

angle(ori1, ori2) ./ degree

%%
% Note that the misorientation angle is computed by default modulo crystal
% symmetry, i.e., the angle is always the smallest angles between all
% possible pairs of symmetrically equivalent orientations. In our example
% this means that symmetrisation of one orientation has no impact on the
% angle

angle(ori1, ori2.symmetrise) ./ degree

%%
% The misorientation angle neglecting crystal symmetry can be computed by

angle(ori1, ori2.symmetrise,'noSymmetry')./ degree

%%
% We see that the smallest angle indeed coincides with the angle computed
% before.

%% Misorientations
% Remember that both orientations ori1 and ori2 map crystal coordinates
% onto specimen coordinates. Hence, the product of an inverse orientation
% with another orientation transfers crystal coordinates from one crystal
% reference frame into crystal coordinates with respect to another crystal
% reference frame. This transformation is called misorientation

mori = inv(ori1) * ori2

%%
% In the present case the misorientation describes the coordinate transform
% from the reference frame of grain 85 into the reference frame of crystal
% 74. Take as an example the plane {11-20} with respect to the grain 85.
% Then the plane in grain 74 which alignes parallel to this plane can be
% computed by

round(mori * Miller(1,1,-2,0,CS))

%%
% Conversely, the inverse of mori is the coordinate transform from crystal
% 74 to grain 85.

round(inv(mori) * Miller(2,-1,-1,0,CS))

%% Coincident lattice planes
% The coincidence between major lattice planes may suggest that the
% misorientation is a twinning misorientation. Lets analyse whether there
% are some more alignments between major lattice planes.

%m = Miller({1,-1,0,0},{1,1,-2,0},{1,-1,0,1},{0,0,0,1},CS);
m = Miller({1,-1,0,0},{1,1,-2,0},{-1,0,1,1},{0,0,0,1},CS);

% cycle through all major lattice planes
close all
for im = 1:length(m)
  % plot the lattice planes of grains 85 with respect to the
  % reference frame of grain 74
  plot(mori * m(im).symmetrise,'MarkerSize',10,...
    'DisplayName',char(m(im)),'figSize','large','noLabel','upper')
  hold all
end
hold off

% mark the corresponding lattice planes in the twin
mm = round(unique(mori*m.symmetrise,'noSymmetry'),'maxHKL',6);
annotate(mm,'labeled','MarkerSize',5,'figSize','large','textAboveMarker')

% show legend
legend({},'location','SouthEast','FontSize',13);

%%
% we observe an almost perfect match for the lattice planes {11-20} to
% {-2110} and {1-101} to {-1101} and good coincidences for the lattice
% plane {1-100} to {0001} and {0001} to {0-661}. Lets compute the angles
% explicitly

angle(mori * Miller(1,1,-2,0,CS),Miller(2,-1,-1,0,CS)) / degree
angle(mori * Miller(1,0,-1,-1,CS),Miller(1,-1,0,1,CS)) / degree
angle(mori * Miller(0,0,0,1,CS) ,Miller(1,0,-1,0,CS),'noSymmetry') / degree
angle(mori * Miller(1,1,-2,2,CS),Miller(1,0,-1,0,CS)) / degree
angle(mori * Miller(1,0,-1,0,CS),Miller(1,1,-2,2,CS)) / degree

%% Twinning misorientations
% Lets define a misorientation that makes a perfect fit between the {11-20}
% lattice planes and between the {10-11} lattice planes

mori = orientation.map(Miller(1,1,-2,0,CS),Miller(2,-1,-1,0,CS),...
  Miller(-1,0,1,1,CS),Miller(-1,1,0,1,CS))

% the rotational axis
round(mori.axis)

% the rotational angle
mori.angle / degree

%%
% and plot the same figure as before with the exact twinning
% misorientation.

% cycle through all major lattice planes
close all
for im = 1:length(m)
  % plot the lattice planes of grains 85 with respect to the
  % reference frame of grain 74
  plot(mori * m(im).symmetrise,'MarkerSize',10,...
    'DisplayName',char(m(im)),'figSize','large','noLabel','upper')
  hold all
end
hold off

% mark the corresponding lattice planes in the twin
mm = round(unique(mori*m.symmetrise,'noSymmetry'),'maxHKL',6);
annotate(mm,'labeled','MarkerSize',5,'figSize','large')

% show legend
legend({},'location','NorthWest','FontSize',13);

%% Highlight twinning boundaries
% It turns out that in the previous EBSD map many grain boundaries have a
% misorientation close to the twinning misorientation we just defined. Lets
% Lets highlight those twinning boundaries

% consider only Magnesium to Magnesium grain boundaries
gB = grains.boundary('Mag','Mag');

% check for small deviation from the twinning misorientation
isTwinning = angle(gB.misorientation,mori) < 5*degree;

% plot the grains and highlight the twinning boundaries
plot(grains,grains.meanOrientation,'micronbar','off')
hold on
plot(gB(isTwinning),'edgecolor','w','linewidth',2)
hold off

%%
% From this picture we see that large fraction of grain boudaries are
% twinning boundaries. To make this observation more evident we may plot
% the boundary misorientation angle distribution function. This is simply
% the angle distribution of all boundary misorientations and can be
% displayed with

close all
plotAngleDistribution(gB.misorientation)

%%
% From this we observe that we have about 50 percent twinning boundaries.
% Analogously we may also plot the axis distribution

plotAxisDistribution(gB.misorientation,'contour')

%%
% which emphasises a strong portion of rotations about the (-12-10) axis.

%% Phase transitions
% Misorientations may not only be defined between crystal frames of the
% same phase. Lets consider the phases Magnetite and Hematite.

CS_Mag = loadCIF('Magnetite')
CS_Hem = loadCIF('Hematite')

%%
% The phase transition from Magnetite to Hematite is described in
% literature by {111}_m parallel {0001}_h and {-101}_m parallel {10-10}_h
% The corresponding misorientation is defined in MTEX by

Mag2Hem = orientation.map(...
  Miller(1,1,1,CS_Mag),Miller(0,0,0,1,CS_Hem),...
  Miller(-1,0,1,CS_Mag),Miller(1,0,-1,0,CS_Hem))

%%
% Assume a Magnetite grain with orientation

ori_Mag = orientation.byEuler(0,0,0,CS_Mag)

%%
% Then we can compute all variants of the phase transition by

symmetrise(ori_Mag) * inv(Mag2Hem)

%%
% and the corresponding pole figures by

plotPDF(symmetrise(ori_Mag) * inv(Mag2Hem),...
  Miller({1,0,-1,0},{1,1,-2,0},{0,0,0,1},CS_Hem))


function [b1, b2] = isManifoldMesh(varargin)
%ISMANIFOLDMESH Check whether the input mesh may be considered as manifold.
%
%   B = isManifoldMesh(V, F)
%   B = isManifoldMesh(V, E, F)
%   Checks if the specified mesh is a manifold. When mesh is a manifold,
%   all edges are connected to either 2 or 1 faces.
%
%   [B, HASBORDER] = isManifoldMesh(V, E, F)
%   Also checks whether the mesh contains border faces. Border faces
%   contains at least one edge which is ajacent to only one face.
%
%   Example
%     [V, F] = createOctahedron;
%     isManifoldMesh(V, F)
%     ans =
%       logical
%        1
%
%   See also
%     meshes3d, ensureManifoldMesh, trimMesh

% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2019-01-31,    using Matlab 9.5.0.944444 (R2018b)
% Copyright 2019 INRA - Cepia Software Platform.

vertices = varargin{1};
faces = varargin{2};

% compute edge to vertex array
if nargin == 3
    edges = faces;
    faces = varargin{3};
else
    % compute edge to vertex array
    edges = meshEdges(faces);
end

% compute face to edge indices array
% as a nFaces-by-3 array (each face connected to exactly three edges)
faceEdgeInds = meshFaceEdges(vertices, edges, faces);

% compute number of faces incident each edge
edgeFaces = trimeshEdgeFaces(faces);
edgeFaceDegrees = sum(edgeFaces > 0, 2);

% for each face, concatenate the face degree of each edge
faceEdgeDegrees = zeros(size(faces, 1), 3);
for iFace = 1:size(faces, 1)
    edgeInds = faceEdgeInds{iFace};
    faceEdgeDegrees(iFace, :) = edgeFaceDegrees(edgeInds);
end

regFaces = sum(ismember(faceEdgeDegrees, [1 2]), 2) == 3;
innerFaces = sum(faceEdgeDegrees == 2, 2) == 3;
borderFaces = regFaces & ~innerFaces;

% check if mesh is manifold: all faces are either regular or border
b1 = all(regFaces);

% check if some faces are border
b2 = any(borderFaces);


classdef GradientVariationExperiment < handle

    properties (Access = public)
        backgroundMesh
        boundaryMesh
        levelSet
        regularizedPerimeter
        domainLength
    end

    properties (Access = private)
        iMesh
        inputFile
        levelSetParams
    end

    methods (Access = public)

        function obj = GradientVariationExperiment(cParams)
            obj.init(cParams)
            obj.createBackgroundAndBoundaryMesh();
            obj.computeDomainLength();
            obj.createLevelSet();
            obj.createRegularizedPerimeters();
        end

    end

    methods (Access = protected)

        function init(obj,cParams)
            obj.inputFile      = cParams.inputFile;
            obj.iMesh          = cParams.iMesh;
            obj.levelSetParams = cParams.levelSetParams;
        end

        function createBackgroundAndBoundaryMesh(obj)
            s.inputFile = obj.inputFile;
            s.isBackgroundMeshRectangularBox = true;
            mCreator = BackgroundAndBoundaryMeshCreatorFromInputFile(s);
            obj.backgroundMesh = mCreator.backgroundMesh;
            obj.boundaryMesh = mCreator.boundaryMesh;
        end

        function createLevelSet(obj)
            s = obj.levelSetParams;
            s.coord      = obj.backgroundMesh.coord;
            s.ndim       = obj.backgroundMesh.ndim;
            lsCreator = LevelSetCreator.create(s);
            obj.levelSet = lsCreator.getValue();
        end

        function computeDomainLength(obj)
            x = obj.backgroundMesh.coord;
            d = max(x(:,1)) - min(x(:,1));
            obj.domainLength = d;
        end

        function createRegularizedPerimeters(obj)
            s.inputFile        = obj.inputFile;
            s.backgroundMesh   = obj.backgroundMesh;
            s.scale            = 'MACRO';
            s.designVariable   = obj.levelSet;
            s.outputFigureName = ['SmoothedCircleMesh',num2str(obj.iMesh)];
            s.plotting         = false;
            s.printing         = false;
            s.capturingImage   = false;
            s.isRobinTermAdded = true;
            s.perimeterType    = 'perimeterInterior';
            rPerimeter = RegularizedPerimeterComputer(s);
            rPerimeter.compute();
            obj.regularizedPerimeter = rPerimeter;
        end

    end

end


% test_cgal_tri_fillholes.m

% Author: Ramon Casero <rcasero@gmail.com>
% Copyright © 2013 University of Oxford
% Version: 0.1.0
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see
% <http://www.gnu.org/licenses/>.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Basic
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% empty mesh
[tri, n] = cgal_tri_fillholes([], [])

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Cube with one missing triangle
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% create a surface mesh that is a cube
x = [
    0 0 0
    0 0 1
    0 1 0
    0 1 1
    1 0 0
    1 0 1
    1 1 0
    1 1 1
    ];

tri = [
     1     3     5
     2     1     5
     2     3     1
     4     3     2
     6     2     5
     4     2     6
     7     6     5
     3     7     5
     4     7     3
     8     6     7
     4     8     7
     4     6     8
     ];

% plot mesh
hold off
trisurf(tri, x(:,1), x(:,2), x(:,3))
axis([0 1 0 1 0 1])

% make a hole by removing one of the triangles
tri2 = tri;
tri2(6, :) = [];

% plot mesh
hold off
trisurf(tri2, x(:,1), x(:,2), x(:,3))
axis([0 1 0 1 0 1])

% fill hole
[tri2, n] = cgal_tri_fillholes(tri2, x);
disp(['Number of holes filled = ' num2str(n)])

% check that the hole has been filled (expected result, and empty matrix)
setdiff(sort(tri, 2), sort(tri2, 2), 'rows')

% plot mesh
hold off
trisurf(tri2, x(:,1), x(:,2), x(:,3))
axis([0 1 0 1 0 1])

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Cube with two triangles that form the upper face missing
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% create a surface mesh that is a cube
x = [
    0 0 0
    0 0 1
    0 1 0
    0 1 1
    1 0 0
    1 0 1
    1 1 0
    1 1 1
    ];

tri = [
     1     3     5
     2     1     5
     2     3     1
     4     3     2
     6     2     5
     4     2     6
     7     6     5
     3     7     5
     4     7     3
     8     6     7
     4     8     7
     4     6     8
     ];

% plot mesh
hold off
trisurf(tri, x(:,1), x(:,2), x(:,3))
axis([0 1 0 1 0 1])

% make a hole by removing one of the triangles
tri2 = tri;
tri2([6 12], :) = [];

% plot mesh
hold off
trisurf(tri2, x(:,1), x(:,2), x(:,3))
axis([0 1 0 1 0 1])

% fill hole
[tri2, n] = cgal_tri_fillholes(tri2, x);
disp(['Number of holes filled = ' num2str(n)])

% check that the hole has been filled (expected result, and empty matrix)
setdiff(sort(tri, 2), sort(tri2, 2), 'rows')

% plot mesh
hold off
trisurf(tri2, x(:,1), x(:,2), x(:,3))
axis([0 1 0 1 0 1])

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Cube with two holes (missing two triangles)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% create a surface mesh that is a cube
x = [
    0 0 0
    0 0 1
    0 1 0
    0 1 1
    1 0 0
    1 0 1
    1 1 0
    1 1 1
    ];

tri = [
     1     3     5
     2     1     5
     2     3     1
     4     3     2
     6     2     5
     4     2     6
     7     6     5
     3     7     5
     4     7     3
     8     6     7
     4     8     7
     4     6     8
     ];

% plot mesh
hold off
trisurf(tri, x(:,1), x(:,2), x(:,3))
axis([0 1 0 1 0 1])

% make a hole by removing one of the triangles
tri2 = tri;
tri2([1 6], :) = [];

% plot mesh
hold off
trisurf(tri2, x(:,1), x(:,2), x(:,3))
axis([0 1 0 1 0 1])

% fill hole
[tri2, n] = cgal_tri_fillholes(tri2, x);
disp(['Number of holes filled = ' num2str(n)])

% check that the hole has been filled (expected result, and empty matrix)
setdiff(sort(tri, 2), sort(tri2, 2), 'rows')

% plot mesh
hold off
trisurf(tri2, x(:,1), x(:,2), x(:,3))
axis([0 1 0 1 0 1])


%
%      JAWAHARLAL NEHRU TECHNOLOGICAL UNIVERSITY
%
%
%
%

clear;
clc;
clear all;
close all;
display('           ');
display('           ');

display('           ');
display('               SOME EXPERIMENTS ON IMAGE DENOISING USING WAVELETS ');

display('           ');
display('           ');
display('         RAJA RAO           ');

display('           ');
display('           ');

display('select the image');

display('           1:lena.png');
display('           2:barbara.png');
display('           3:boat.png');
display('           4:house.png');
display('           5:peppers256.png');
display('           6:cameraman.jpg');
display('           ');
display('           7:hyderabad.png');
display('           8:friendgray.jpg');
display('           ');

ss1=input('enter your choice:   ');
switch ss1
    case 1
       f=imread('lena.png');
       %f=imread('babu.jpg');
    case 2
        f=imread('barbara.png');
    case 3
        f=imread('boat.png');
    case 4
        f=imread('house.png');
        case 5
        f=imread('peppers256.png');
    case 6
        f=imread('cameraman.jpg');
    case 7
        f=imread('hyderabad512.png');
    case 8
        f=imread('friendgray.jpg');
end

subplot(2,2,1), imshow(f);title('original image');

display('enter the type of noise:');
display('    1    for salt & pepper');
display('    2    for gaussian');
display('    3    for poisson');
display('    4    for speckle');

ud=input('enter the value:');

switch ud
    case 1
        display('enter the % of noise(Ex:0.2)');
        ud1=input('pls enter:     ');
        g=imnoise(f,'salt & pepper',ud1);
    case 2

%f=imread('peppers256.png');
%subplot(2,2,1),imshow(f);
display('enter the noise varience:  ');
va=input('enter between 0.01 to 0.09:   ');
g=imnoise(f,'gaussian',0,va);
    case 3
       % display('enter the % of noise(Ex:0.2)');
        %ud1=input('pls enter:     ');
        g=imnoise(f,'poisson');
        case 4
        display('enter the varience of noise(Ex:0.02)');
        ud1=input('pls enter:     ');
        g=imnoise(f,'speckle',ud1);

end
%g=imnoise(f,'salt & pepper',01);
subplot(2,2,2),imshow(g);title('noisy image');

%[ca,ch,cv,cd] = dwt2(g,'db2');
%c=[ca ch;cv cd];
%subplot(2,2,3),imshow(uint8(c));

x=g;
% Use wdencmp for image de-noising.
% find default values (see ddencmp).
[thr,sorh,keepapp] = ddencmp('den','wv',x);
display('');
display('select wavelet');
display('enter 1 for haar wavelet');
display('enter 2 for db2 wavelet');
display('enter 3 for db4 wavelet');
display('enter 4 for sym wavelet');
display('enter 5 for sym wavelet');
display('enter 6 for bior wavelet');
display('enter 7 for bior wavelet');
display('enter 8 for mexh wavelet');
display('enter 9 for coif  wavelet');
display('enter 10 for meyr wavelet');
display('enter 11 for morl wavelet');
display('enter 12 for  rbio wavelet');
display('press any key to quit');
display('');

ww=input('enter your choice:    ');
switch ww
    case 1
        wv='haar';
    case 2
        wv='db2';
    case 3
        wv='db4' ;
    case 4
        wv='sym2'
    case 5
        wv='sym4';
    case 6
        wv='bior1.1';
    case 7
       wv='bior6.8';
    case 8
        wv='mexh';
    case 9
        wv='coif5';
    case 10
        wv='dmey';
    case 11
        wv='mor1';
    case 12
        wv='jpeg9.7';
    otherwise
        quit;
end
display('');
display('enter 1 for soft thresholding');
display('enter 2 for hard thresholding');
display('enter 3 for bayes soft thresholding');
sorh=input('sorh:   ');

display('enter the level of decomposition');
level=input(' enter 1 or 2 :    ');

switch sorh
    case 1
        sorh='s';
        xd = wdencmp('gbl',x,wv,level,thr,sorh,keepapp);
    case 2
        sorh='h';
        xd = wdencmp('gbl',x,wv,level,thr,sorh,keepapp);
    case 3
        %%%%%%%%%%%%%%%%%%%%%
       % clear all;
%close all;
%clc;

%Denoising using Bayes soft thresholding

%Note: Figure window 1 displays the original image, fig 2 the noisy img
%fig 3 denoised img by bayes soft thresholding

%Reading the image
%pic=imread('elaine','png');
pic=f;
%figure, imagesc(pic);colormap(gray);

%Define the Noise Variance and adding Gaussian noise
%While using 'imnoise' the pixel values(0 to 255) are converted to double in the range 0 to 1
%So variance also has to be suitably converted
sig=15;
V=(sig/256)^2;
npic=g;
%npic=imnoise(pic,'gaussian',0,V);
%figure, imagesc(npic);colormap(gray);

%Define the type of wavelet(filterbank) used and the number of scales in the wavelet decomp
filtertype=wv;
levels=level;

%Doing the wavelet decomposition
[C,S]=wavedec2(npic,levels,filtertype);

st=(S(1,1)^2)+1;
bayesC=[C(1:st-1),zeros(1,length(st:1:length(C)))];
var=length(C)-S(size(S,1)-1,1)^2+1;

%Calculating sigmahat
sigmahat=median(abs(C(var:length(C))))/0.6745;

for jj=2:size(S,1)-1
    %for the H detail coefficients
    coefh=C(st:st+S(jj,1)^2-1);
    thr=bayes(coefh,sigmahat);
    bayesC(st:st+S(jj,1)^2-1)=sthresh(coefh,thr);
    st=st+S(jj,1)^2;

    % for the V detail coefficients
    coefv=C(st:st+S(jj,1)^2-1);
    thr=bayes(coefv,sigmahat);
    bayesC(st:st+S(jj,1)^2-1)=sthresh(coefv,thr);
    st=st+S(jj,1)^2;

    %for Diag detail coefficients
    coefd=C(st:st+S(jj,1)^2-1);
    thr=bayes(coefd,sigmahat);
    bayesC(st:st+S(jj,1)^2-1)=sthresh(coefd,thr);
    st=st+S(jj,1)^2;
end

%Reconstructing the image from the Bayes-thresholded wavelet coefficients
bayespic=waverec2(bayesC,S,filtertype);
xd=bayespic;
%Displaying the Bayes-denoised image
%figure, imagesc(uint8(bayespic));colormap(gray);
display('IEEE TRANSACTIONS ON IMAGE PROCESSING, VOL. 9, NO. 9, SEPTEMBER 2000');

display('IEEE TRANSACTIONS ON IMAGE PROCESSING, VOL. 9, NO. 9, SEPTEMBER 2000');
display('Adaptive Wavelet Thresholding for Image Denoising and Compression');
display('S. Grace Chang, Student Member, IEEE, Bin Yu, Senior Member, IEEE, and Martin Vetterli, Fellow, IEEE');

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

end

%sorh=sorh;
% de-noise image using global thresholding option.

%f=imread('peppers256.png');
[c,s]=wavefast(g,level,wv);
subplot(2,2,3),wave2gray(c,s,8);title('decomposed structure');

subplot(2,2,4),xd=uint8(xd);
imshow(xd);title('denoised image');
%subplot(2,2,4),sub=f-xd;
%sub=abs(1.2*sub);
%imshow(im2uint8(sub));title('difference image');
ff=im2double(f);xdd=im2double(xd);
display('      ');
display('      ');
display('reference: To calcullate signal to noise ratio');
display('Makoto Miyahara');
display('"Objective Picture Quality Scale (PQS) for Image Coding"');
display('IEEE Trans. on Comm., Vol 46, No.9, 1998.');
display('      ');
display('      ');
snr=wpsnr(ff,xdd)

display('      ');
display('      ');
mse=compare11(ff,xdd)


function [ft3] = mi32ft3(mi3)
% Convert volume from cubic miles to cubic feet.
% Chad Greene 2012
ft3 = mi3*147197952000;


function [g, gdata, gprior] = rbfgrad(net, x, t)
%RBFGRAD Evaluate gradient of error function for RBF network.
%
%	Description
%	G = RBFGRAD(NET, X, T) takes a network data structure NET together
%	with a matrix X of input vectors and a matrix T of target vectors,
%	and evaluates the gradient G of the error function with respect to
%	the network weights (i.e. including the hidden unit parameters). The
%	error function is sum of squares. Each row of X corresponds to one
%	input vector and each row of T contains the corresponding target
%	vector. If the output function is 'NEUROSCALE' then the gradient is
%	only computed for the output layer weights and biases.
%
%	[G, GDATA, GPRIOR] = RBFGRAD(NET, X, T) also returns separately  the
%	data and prior contributions to the gradient. In the case of multiple
%	groups in the prior, GPRIOR is a matrix with a row for each group and
%	a column for each weight parameter.
%
%	See also
%	RBF, RBFFWD, RBFERR, RBFPAK, RBFUNPAK, RBFBKP
%

%	Copyright (c) Ian T Nabney (1996-2001)

% Check arguments for consistency
switch net.outfn
case 'linear'
   errstring = consist(net, 'rbf', x, t);
case 'neuroscale'
   errstring = consist(net, 'rbf', x);
otherwise
   error(['Unknown output function ', net.outfn]);
end
if ~isempty(errstring);
  error(errstring);
end

ndata = size(x, 1);

[y, z, n2] = rbffwd(net, x);

switch net.outfn
case 'linear'

   % Sum squared error at output units
   delout = y - t;

   gdata = rbfbkp(net, x, z, n2, delout);
   [g, gdata, gprior] = gbayes(net, gdata);

case 'neuroscale'
   % Compute the error gradient with respect to outputs
   y_dist = sqrt(dist2(y, y));
   D = (t - y_dist)./(y_dist+diag(ones(ndata, 1)));
   temp = y';
   gradient = 2.*sum(kron(D, ones(1, net.nout)) .* ...
      (repmat(y, 1, ndata) - repmat((temp(:))', ndata, 1)), 1);
   gradient = (reshape(gradient, net.nout, ndata))';
   % Compute the error gradient
   gdata = rbfbkp(net, x, z, n2, gradient);
   [g, gdata, gprior] = gbayes(net, gdata);
otherwise
   error(['Unknown output function ', net.outfn]);
end


%DEMOIMSHAPES2D Display various 2D demo shapes
%
%   output = demoShapes2d(input)
%
%   Example
%   demoImShapes
%
%   See also
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-06-29,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

%% initialisations

% generate cubic images
lx = 1:100;
ly = 1:100;

% choose a center not aligned with the grid
center = [50+sqrt(2)-1 50+sqrt(3)-1];

angles = [...
    0; ...
    10; ...
    30; ...
    45];

%% Disc

% sphere is defined by center and radius
disc = [center 40];

% generation of 3D image
img = discreteDisc(lx, ly, disc);

% display image
f = figure;
imshow(~img);

% decorate
title('Disc, radius=40');

%% Ellipse

figure;
for i = 1:4
    % sphere is defined by center and radius
    ellipse = [center 40 20 angles(i)];

    % generation of 3D image
    img = discreteEllipse(lx, ly, ellipse);

    % display image
    subplot(2, 2, i);
    imshow(~img);

    % decorate
    title(sprintf('Ellipse, Th=%02d', angles(i)));
end

%% Square

figure;
for i = 1:4
    % sphere is defined by center and radius
    square = [center 60 angles(i)];

    % generation of 3D image
    img = discreteSquare(lx, ly, square);

    % display image
    subplot(2, 2, i);
    imshow(~img);

    % decorate
    title(sprintf('Square, Th=%02d', angles(i)));
end

%% Rectangle

figure;
for i = 1:4
    % sphere is defined by center and radius
    rect = [center 60 30 angles(i)];

    % generation of 3D image
    img = discreteRectangle(lx, ly, rect);

    % display image
    subplot(2, 2, i);
    imshow(~img);

    % decorate
    title(sprintf('Rectangle, Th=%02d', angles(i)));
end

%% Capsule

figure;
for i = 1:4
    % sphere is defined by center and radius
    [dx dy] = pol2cart(deg2rad(angles(i)), 30);
    caps = [center-[dx dy] center+[dx dy] 15];

    % generation of 3D image
    img = discreteCapsule(lx, ly, caps);

    % display image
    subplot(2, 2, i);
    imshow(~img);

    % decorate
    title(sprintf('Capsule, Th=%02d', angles(i)));
end

%% Egg

figure;
for i = 1:4
    % egg defined by a center, a size and an angle
    egg = [center 30 angles(i)];

    % generation of 3D image
    img = discreteEgg(lx, ly, egg);

    % display image
    subplot(2, 2, i);
    imshow(~img);

    % decorate
    title(sprintf('Egg, Th=%02d', angles(i)));
end

%% Trefoil

figure;
for i = 1:4
    % trefoil defined by a center, two radii and an angle
    trefoil = [center 40 15 angles(i)];

    % generation of 3D image
    img = discreteTrefoil(lx, ly, trefoil);

    % display image
    subplot(2, 2, i);
    imshow(~img);

    % decorate
    title(sprintf('Trefoil, Th=%02d', angles(i)));
end

%% Starfish

figure;
for i = 1:4
    % starfish defined by a center, two radii and an angle
    starfish = [center 40 20 angles(i)];

    % generation of 3D image
    img = discreteStarfish(lx, ly, starfish);

    % display image
    subplot(2, 2, i);
    imshow(~img);

    % decorate
    title(sprintf('Starfish, Th=%02d', angles(i)));
end