function y = perform_waveatoms_transform(x,dir, options)

% perform_waveatoms_transform - interface to WaveAtom transform
%
%   y = perform_waveatoms_transform(x,dir, options);
%
%   The waveatom toolbox can be downloaded from
%       http://www.waveatom.org/
%
%   Copyright (c) 2007 Gabriel Peyre

options.null = 0;
issym = getoptions(options, 'issym', 0);
force_real = getoptions(options, 'force_real', 1);

if dir==1
    d = nb_dims(x);
else
    if iscell(x)
        d = nb_dims(x{1});
    else
        d = nb_dims(x);
    end
end

pat = 'p'; tp = 'ortho';
if d==1
    if dir==1
        if issym
            y = fatom1sym(x,pat,[1 1]);
        else
            y = fwa1(x,pat,tp);
        end
    else
        if issym
            y = iatom1sym(x,pat,[1 1]);
        else
            y = iwa1(x,pat,tp);
        end
    end
else
    if dir==1
        if issym
            y = fwa2sym(x,pat,[1 1]);
        else
            y = fwa2(x,pat,tp);
        end
    else
        if issym
            y = iwa2sym(x,pat,[1 1]);
        else
            y = iwa2(x,pat,tp);
        end
    end
end

if force_real && dir==-1
    y = real(y);
end

function c = fwa2(x,pat,tp)
% fwa2 - 2D forward wave atom transform
% -----------------
% INPUT
% --
% x is a real N-by-N matrix. N is a power of 2.
% --
% pat specifies the type of frequency partition which satsifies
% parabolic scaling relationship. pat can either be 'p' or 'q'.
% --
% tp is the type of tranform.
% 	'ortho': orthobasis
% 	'directional': real-valued frame with single oscillation direction
% 	'complex': complex-valued frame
% -----------------
% OUTPUT
% --
% c is a cell array which contains the wave atom coefficients. If
% tp=='ortho', then c{j}{m1,m2}(n1,n2) is the coefficient at scale j,
% frequency index (m1,m2) and spatial index (n1,n2). If
% tp=='directional', then c{j,d}{m1,m2}(n1,n2) with d=1,2 are the
% coefficients at scale j, frequency index (m1,m2) and spatial index
% (n1,n2). If tp=='complex', then c{j,d}{m1,m2)(n1,n2) with d=1,2,3,4
% are the coefficients at scale j, frequency index (m1,m2) and spatial
% index (n1,n2).
% -----------------
% Written by Lexing Ying and Laurent Demanet, 2007

if( ismember(tp, {'ortho','directional','complex'})==0 | ismember(pat, {'p','q','u'})==0 )    error('wrong');  end

if(strcmp(tp, 'ortho')==1)
    %---------------------------------------------------------
    N = size(x,1);
    H = N/2;
    lst = freq_pat(H,pat);
    %------------------
    f = fft2(x) / sqrt(prod(size(x)));
    A = N;
    c = cell(length(lst),1);
    %------------------
    for s=1:length(lst)
        nw = length(lst{s});
        c{s} = cell(nw,nw);
        for I=0:nw-1
            for J=0:nw-1
                if(lst{s}(I+1)==0 & lst{s}(J+1)==0)
                    c{s}{I+1,J+1} = [];
                else
                    B = 2^(s-1);
                    D = 2*B;
                    Ict = I*B;      Jct = J*B; %starting position in freq
                    if(mod(I,2)==0)
                        Ifm = Ict-2/3*B;        Ito = Ict+4/3*B;
                    else
                        Ifm = Ict-1/3*B;        Ito = Ict+5/3*B;
                    end
                    if(mod(J,2)==0)
                        Jfm = Jct-2/3*B;        Jto = Jct+4/3*B;
                    else
                        Jfm = Jct-1/3*B;        Jto = Jct+5/3*B;
                    end
                    res = zeros(D,D);
                    for id=0:1
                        if(id==0)
                            Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                        else
                            Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                        end
                        for jd=0:1
                            if(jd==0)
                                Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                            else
                                Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                            end
                            res(mod(Idx,D)+1,mod(Jdx,D)+1) = res(mod(Idx,D)+1,mod(Jdx,D)+1) + conj( Icf.'*Jcf ) .* f(mod(Idx,A)+1,mod(Jdx,A)+1);
                        end
                    end
                    c{s}{I+1,J+1} = ifft2(res) * sqrt(prod(size(res)));
                end
            end
        end
    end

elseif(strcmp(tp, 'directional')==1)
    %---------------------------------------------------------
    N = size(x,1);
    H = N/2;
    lst = freq_pat(H,pat);
    %------------------
    f = fft2(x) / sqrt(prod(size(x)));
    A = N;
    c1 = cell(length(lst),1);
    c2 = cell(length(lst),1);
    %------------------
    for s=1:length(lst)
        nw = length(lst{s});
        c1{s} = cell(nw,nw);
        c2{s} = cell(nw,nw);
        for I=0:nw-1
            for J=0:nw-1
                if(lst{s}(I+1)==0 & lst{s}(J+1)==0)
                    c1{s}{I+1,J+1} = [];
                    c2{s}{I+1,J+1} = [];
                else
                    B = 2^(s-1);
                    D = 2*B;
                    res = zeros(D,D);
                    Ict = I*B;      Jct = J*B; %starting position in freq
                    if(mod(I,2)==0)
                        Ifm = Ict-2/3*B;        Ito = Ict+4/3*B;
                    else
                        Ifm = Ict-1/3*B;        Ito = Ict+5/3*B;
                    end
                    if(mod(J,2)==0)
                        Jfm = Jct-2/3*B;        Jto = Jct+4/3*B;
                    else
                        Jfm = Jct-1/3*B;        Jto = Jct+5/3*B;
                    end

                    res = zeros(D,D);
                    Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                    Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                    res(mod(Idx,D)+1,mod(Jdx,D)+1) = res(mod(Idx,D)+1,mod(Jdx,D)+1) + conj( Icf.'*Jcf ) .* f(mod(Idx,A)+1,mod(Jdx,A)+1);
                    Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                    Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                    res(mod(Idx,D)+1,mod(Jdx,D)+1) = res(mod(Idx,D)+1,mod(Jdx,D)+1) + conj( Icf.'*Jcf ) .* f(mod(Idx,A)+1,mod(Jdx,A)+1);
                    c1{s}{I+1,J+1} = ifft2(res) * sqrt(prod(size(res)));

                    res = zeros(D,D);
                    Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                    Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                    res(mod(Idx,D)+1,mod(Jdx,D)+1) = res(mod(Idx,D)+1,mod(Jdx,D)+1) + conj( Icf.'*Jcf ) .* f(mod(Idx,A)+1,mod(Jdx,A)+1);
                    Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                    Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                    res(mod(Idx,D)+1,mod(Jdx,D)+1) = res(mod(Idx,D)+1,mod(Jdx,D)+1) + conj( Icf.'*Jcf ) .* f(mod(Idx,A)+1,mod(Jdx,A)+1);
                    c2{s}{I+1,J+1} = ifft2(res) * sqrt(prod(size(res)));
                end
            end
        end
    end
    c = [c1 c2];

elseif(strcmp(tp, 'complex')==1)
    %---------------------------------------------------------
    N = size(x,1);
    H = N/2;
    lst = freq_pat(H,pat);
    %------------------
    f = fft2(x) / sqrt(prod(size(x)));
    A = N;
    c1 = cell(length(lst),1);
    c2 = cell(length(lst),1);
    c3 = cell(length(lst),1);
    c4 = cell(length(lst),1);
    %------------------
    for s=1:length(lst)
        nw = length(lst{s});
        c1{s} = cell(nw,nw);
        c2{s} = cell(nw,nw);
        c3{s} = cell(nw,nw);
        c4{s} = cell(nw,nw);
        for I=0:nw-1
            for J=0:nw-1
                if(lst{s}(I+1)==0 & lst{s}(J+1)==0)
                    c1{s}{I+1,J+1} = [];
                    c2{s}{I+1,J+1} = [];
                    c3{s}{I+1,J+1} = [];
                    c4{s}{I+1,J+1} = [];
                else
                    B = 2^(s-1);
                    D = 2*B;
                    res = zeros(D,D);
                    Ict = I*B;      Jct = J*B; %starting position in freq
                    if(mod(I,2)==0)
                        Ifm = Ict-2/3*B;        Ito = Ict+4/3*B;
                    else
                        Ifm = Ict-1/3*B;        Ito = Ict+5/3*B;
                    end
                    if(mod(J,2)==0)
                        Jfm = Jct-2/3*B;        Jto = Jct+4/3*B;
                    else
                        Jfm = Jct-1/3*B;        Jto = Jct+5/3*B;
                    end

                    res = zeros(D,D);
                    Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                    Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                    res(mod(Idx,D)+1,mod(Jdx,D)+1) = res(mod(Idx,D)+1,mod(Jdx,D)+1) + conj( Icf.'*Jcf ) .* f(mod(Idx,A)+1,mod(Jdx,A)+1);
                    c1{s}{I+1,J+1} = ifft2(res) * sqrt(prod(size(res)));

                    res = zeros(D,D);
                    Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                    Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                    res(mod(Idx,D)+1,mod(Jdx,D)+1) = res(mod(Idx,D)+1,mod(Jdx,D)+1) + conj( Icf.'*Jcf ) .* f(mod(Idx,A)+1,mod(Jdx,A)+1);
                    c2{s}{I+1,J+1} = ifft2(res) * sqrt(prod(size(res)));

                    res = zeros(D,D);
                    Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                    Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                    res(mod(Idx,D)+1,mod(Jdx,D)+1) = res(mod(Idx,D)+1,mod(Jdx,D)+1) + conj( Icf.'*Jcf ) .* f(mod(Idx,A)+1,mod(Jdx,A)+1);
                    c3{s}{I+1,J+1} = ifft2(res) * sqrt(prod(size(res)));

                    res = zeros(D,D);
                    Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                    Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                    res(mod(Idx,D)+1,mod(Jdx,D)+1) = res(mod(Idx,D)+1,mod(Jdx,D)+1) + conj( Icf.'*Jcf ) .* f(mod(Idx,A)+1,mod(Jdx,A)+1);
                    c4{s}{I+1,J+1} = ifft2(res) * sqrt(prod(size(res)));
                end
            end
        end
    end
    c = [c1 c2 c3 c4];
end

function x = iwa2(c,pat,tp)
% iwa2 - 2D inverse wave atom transform
% -----------------
% INPUT
% --
% c is a cell array which contains the wave atom coefficients. If
% tp=='ortho', then c{j}{m1,m2}(n1,n2) is the coefficient at scale j,
% frequency index (m1,m2) and spatial index (n1,n2). If
% tp=='directional', then c{j,d}{m1,m2}(n1,n2) with d=1,2 are the
% coefficients at scale j, frequency index (m1,m2) and spatial index
% (n1,n2). If tp=='complex', then c{j,d}{m1,m2)(n1,n2) with d=1,2,3,4
% are the coefficients at scale j, frequency index (m1,m2) and spatial
% index (n1,n2).
% --
% pat specifies the type of frequency partition which satsifies
% parabolic scaling relationship. pat can either be 'p' or 'q'.
% --
% tp is the type of tranform.
% 	'ortho': orthobasis
% 	'directional': real-valued frame with single oscillation direction
% 	'complex': complex-valued frame
% -----------------
% OUTPUT
% --
% x is a real N-by-N matrix. N is a power of 2.
% -----------------
% Written by Lexing Ying and Laurent Demanet, 2007

if( ismember(tp, {'ortho','directional','complex'})==0 | ismember(pat, {'p','q','u'})==0 )    error('wrong');  end

if(strcmp(tp, 'ortho')==1)
    %---------------------------------------------------------
    T = 0;
    for s=1:length(c)
        nw = length(c{s});
        for I=1:nw
            for J=1:nw
                T = T + prod(size(c{s}{I,J}));
            end
        end
    end
    N = sqrt(T);
    H = N/2;
    lst = freq_pat(H,pat);
    A = N;
    f = zeros(A,A);
    %------------------
    for s=1:length(lst)
        nw = length(lst{s});
        for I=0:nw-1
            for J=0:nw-1
                if(~isempty(c{s}{I+1,J+1}))
                    B = 2^(s-1);
                    D = 2*B;
                    Ict = I*B;      Jct = J*B; %starting position in freq
                    if(mod(I,2)==0)
                        Ifm = Ict-2/3*B;        Ito = Ict+4/3*B;
                    else
                        Ifm = Ict-1/3*B;        Ito = Ict+5/3*B;
                    end
                    if(mod(J,2)==0)
                        Jfm = Jct-2/3*B;        Jto = Jct+4/3*B;
                    else
                        Jfm = Jct-1/3*B;        Jto = Jct+5/3*B;
                    end
                    res = fft2(c{s}{I+1,J+1}) / sqrt(prod(size(c{s}{I+1,J+1}))); %res = zeros(D,D);
                    for id=0:1
                        if(id==0)
                            Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                        else
                            Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                        end
                        for jd=0:1
                            if(jd==0)
                                Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                            else
                                Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                            end
                            f(mod(Idx,A)+1,mod(Jdx,A)+1) = f(mod(Idx,A)+1,mod(Jdx,A)+1) + ( Icf.'*Jcf ) .* res(mod(Idx,D)+1,mod(Jdx,D)+1);
                        end
                    end
                end
            end
        end
    end
    %------------------
    x = ifft2(f) * sqrt(prod(size(f)));

elseif(strcmp(tp, 'directional')==1)
    %---------------------------------------------------------
    c1 = c(:,1);
    c2 = c(:,2);

    T = 0;
    for s=1:length(c1)
        nw = length(c1{s});
        for I=1:nw
            for J=1:nw
                T = T + prod(size(c1{s}{I,J}));
            end
        end
    end
    N = sqrt(T);
    H = N/2;
    lst = freq_pat(H,pat);
    A = N;
    f = zeros(A,A);
    %------------------
    for s=1:length(lst)
        nw = length(lst{s});
        for I=0:nw-1
            for J=0:nw-1
                if(~isempty(c1{s}{I+1,J+1}))
                    B = 2^(s-1);
                    D = 2*B;
                    Ict = I*B;      Jct = J*B; %starting position in freq
                    if(mod(I,2)==0)
                        Ifm = Ict-2/3*B;        Ito = Ict+4/3*B;
                    else
                        Ifm = Ict-1/3*B;        Ito = Ict+5/3*B;
                    end
                    if(mod(J,2)==0)
                        Jfm = Jct-2/3*B;        Jto = Jct+4/3*B;
                    else
                        Jfm = Jct-1/3*B;        Jto = Jct+5/3*B;
                    end

                    res = fft2(c1{s}{I+1,J+1}) / sqrt(prod(size(c1{s}{I+1,J+1}))); %res = zeros(D,D);
                    Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                    Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                    f(mod(Idx,A)+1,mod(Jdx,A)+1) = f(mod(Idx,A)+1,mod(Jdx,A)+1) + ( Icf.'*Jcf ) .* res(mod(Idx,D)+1,mod(Jdx,D)+1);
                    Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                    Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                    f(mod(Idx,A)+1,mod(Jdx,A)+1) = f(mod(Idx,A)+1,mod(Jdx,A)+1) + ( Icf.'*Jcf ) .* res(mod(Idx,D)+1,mod(Jdx,D)+1);

                    res = fft2(c2{s}{I+1,J+1}) / sqrt(prod(size(c2{s}{I+1,J+1}))); %res = zeros(D,D);
                    Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                    Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                    f(mod(Idx,A)+1,mod(Jdx,A)+1) = f(mod(Idx,A)+1,mod(Jdx,A)+1) + ( Icf.'*Jcf ) .* res(mod(Idx,D)+1,mod(Jdx,D)+1);
                    Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                    Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                    f(mod(Idx,A)+1,mod(Jdx,A)+1) = f(mod(Idx,A)+1,mod(Jdx,A)+1) + ( Icf.'*Jcf ) .* res(mod(Idx,D)+1,mod(Jdx,D)+1);
                end
            end
        end
    end
    x = ifft2(f) * sqrt(prod(size(f)));

elseif(strcmp(tp, 'complex')==1)
    %---------------------------------------------------------
    c1 = c(:,1);
    c2 = c(:,2);
    c3 = c(:,3);
    c4 = c(:,4);

    T = 0;
    for s=1:length(c1)
        nw = length(c1{s});
        for I=1:nw
            for J=1:nw
                T = T + prod(size(c1{s}{I,J}));
            end
        end
    end
    N = sqrt(T);
    H = N/2;
    lst = freq_pat(H,pat);
    A = N;
    f = zeros(A,A);
    %------------------
    for s=1:length(lst)
        nw = length(lst{s});
        for I=0:nw-1
            for J=0:nw-1
                if(~isempty(c1{s}{I+1,J+1}))
                    B = 2^(s-1);
                    D = 2*B;
                    Ict = I*B;      Jct = J*B; %starting position in freq
                    if(mod(I,2)==0)
                        Ifm = Ict-2/3*B;        Ito = Ict+4/3*B;
                    else
                        Ifm = Ict-1/3*B;        Ito = Ict+5/3*B;
                    end
                    if(mod(J,2)==0)
                        Jfm = Jct-2/3*B;        Jto = Jct+4/3*B;
                    else
                        Jfm = Jct-1/3*B;        Jto = Jct+5/3*B;
                    end

                    res = fft2(c1{s}{I+1,J+1}) / sqrt(prod(size(c1{s}{I+1,J+1}))); %res = zeros(D,D);
                    Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                    Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                    f(mod(Idx,A)+1,mod(Jdx,A)+1) = f(mod(Idx,A)+1,mod(Jdx,A)+1) + ( Icf.'*Jcf ) .* res(mod(Idx,D)+1,mod(Jdx,D)+1);

                    res = fft2(c2{s}{I+1,J+1}) / sqrt(prod(size(c2{s}{I+1,J+1}))); %res = zeros(D,D);
                    Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                    Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                    f(mod(Idx,A)+1,mod(Jdx,A)+1) = f(mod(Idx,A)+1,mod(Jdx,A)+1) + ( Icf.'*Jcf ) .* res(mod(Idx,D)+1,mod(Jdx,D)+1);

                    res = fft2(c3{s}{I+1,J+1}) / sqrt(prod(size(c3{s}{I+1,J+1}))); %res = zeros(D,D);
                    Idx = [ceil(Ifm):floor(Ito)];      Icf = kf_rt(Idx/B*pi, I);
                    Jdx = [ceil(-Jto):floor(-Jfm)];      Jcf = kf_lf(Jdx/B*pi, J);
                    f(mod(Idx,A)+1,mod(Jdx,A)+1) = f(mod(Idx,A)+1,mod(Jdx,A)+1) + ( Icf.'*Jcf ) .* res(mod(Idx,D)+1,mod(Jdx,D)+1);

                    res = fft2(c4{s}{I+1,J+1}) / sqrt(prod(size(c4{s}{I+1,J+1}))); %res = zeros(D,D);
                    Idx = [ceil(-Ito):floor(-Ifm)];      Icf = kf_lf(Idx/B*pi, I);
                    Jdx = [ceil(Jfm):floor(Jto)];      Jcf = kf_rt(Jdx/B*pi, J);
                    f(mod(Idx,A)+1,mod(Jdx,A)+1) = f(mod(Idx,A)+1,mod(Jdx,A)+1) + ( Icf.'*Jcf ) .* res(mod(Idx,D)+1,mod(Jdx,D)+1);
                end
            end
        end
    end
    x = ifft2(f) * sqrt(prod(size(f)));
end

function lst = freq_pat(H,pat)
% freq_pat.m - generate frequency partition
%
% input:
%   H:    half length of the frequency span, H needs to be greater than 16
%   pat:  type of frequency partition which satsifies parabolic scaling relationship
%         equal to 'p' or 'q'
%
% output:
%   lst:  data representing the partition of frequency
%
% Written by Lexing Ying and Laurent Demanet, 2006

if(H<16)    error('H needs to be at least 16');  end

if(    pat=='p') %parabolic scaling by lexing
    len = ceil(log2(H)/2)+1;
    lst = cell(len,1);
    lst{1} = [1 1];    lst{2} = [0 1];    lst{3} = [0 1 1 1];
    cnt = 16;
    idx = 3;    rad = 4;
    while(cnt<H)
        old = cnt;
        lst{idx} = [lst{idx} 1 1];
        cnt = cnt + 2*rad;
        idx = idx+1;
        rad = 2*rad;
        trg = min(4*old,H);
        lst{idx} = [zeros(1,cnt/rad), ones(1,(trg-cnt)/rad)];
        cnt = trg;
    end
elseif(pat=='q') %parabolic scaling by laurent
    len = floor(log2(H)/2)+1;
    lst = cell(len,1);
    lst{1} = [1 1];    lst{2} = [0 1 1 1];
    cnt = 8;
    idx = 2;      rad = 2;
    while(cnt<H)
        old = cnt;
        lst{idx} = [lst{idx} 1 1];
        cnt = cnt + 2*rad;
        idx = idx+1;
        rad = 2*rad;
        trg = min(4*old,H);
        lst{idx} = [zeros(1,cnt/rad), ones(1,(trg-cnt)/rad)];
        cnt = trg;
    end
elseif(pat=='u')
    len = ceil(log2(H)/2)+1; %uniform partitioning
    lst = cell(len,1);
    B = 2^(len-1);
    lst{end} = ones(1,H/B);
else
    error('wrong pat');
end

function r = kf_rt(w,n)
% kf_rt.m - right bump
%
% Written by Lexing Ying and Laurent Demanet, 2006

r = zeros(size(w));
an = pi/2*(n+1/2);
en = (-1)^n;
en1 = (-1)^(n+1);

r = exp(-i*w/2) .* ( exp(i*an)*g(en*(w-pi*(n+1/2))) );

function r = g(w)
% g.m - 'g' function Villemoes's construction
%
% Written by Lexing Ying and Laurent Demanet, 2006
r = zeros(size(w));
gd = w<5*pi/6 & w>-7*pi/6;
r(gd) = abs(sf(w(gd)-3*pi/2));

%----------------------------------------------------------------------
function r = sf(w)
r = zeros(size(w));

aw = abs(w);
r(aw<=2*pi/3) = 0;

gd = aw>=2*pi/3 & aw<=4*pi/3;
r(gd) = 1/sqrt(2) * hf(w(gd)/2+pi);

gd = aw>=4*pi/3 & aw<=8*pi/3;
r(gd) = 1/sqrt(2) * hf(w(gd)/4);

r(aw>8*pi/2) = 0;

function r = hf(w)
w = mod(w+pi,2*pi) - pi;
r = zeros(size(w));
w = abs(w);

r = sqrt(2) * cos(pi/2 * beta(3*w/pi-1));
r(w<=pi/3) = sqrt(2);
r(w>=2*pi/3) = 0;

function r = beta(x)
r = x.^4 .*(35-84*x + 70*x.^2 -20*x.^3);

function r = kf_lf(w,n)
% kf_lf.m - left bump
%
% Written by Lexing Ying and Laurent Demanet, 2006

r = zeros(size(w));
an = pi/2*(n+1/2);
en = (-1)^n;
en1 = (-1)^(n+1);

r = exp(-i*w/2) .* ( exp(-i*an)*g(en1*(w+pi*(n+1/2))) );

function res = fwa2sym(x,pat,tp)
% fwa2sym - 2D forward wave atom transform (symmetric version)
% -----------------
% INPUT
% --
% x is a real N-by-N matrix. N is a power of 2.
% --
% pat specifies the type of frequency partition which satsifies
% parabolic scaling relationship. pat can either be 'p' or 'q'.
% --
% tp is the type of tranform.
% 	'ortho': orthobasis
% 	'directional': real-valued frame with single oscillation direction
% 	'complex': complex-valued frame
% -----------------
% OUTPUT
% --
% res is an array containing all the wave atom coefficients. If
% tp=='ortho', then res is of size N-by-N. If tp=='
% If tp=='directional', then res is of size N-by-N-by-2. If tp=='complex',
% then res is of size N-by-N-by-4.
% -----------------
% Written by Lexing Ying and Laurent Demanet, 2007

if( ismember(tp, {'ortho','directional','complex'})==0 | ismember(pat, {'p','q','u'})==0 )    error('wrong');  end

call = fwa2(x,pat,tp);
N = size(x,1);
res = zeros(N,N,size(call,2));

for i=1:size(call,2)
    c = call(:,i);
    y = zeros(N,N);
    for s=1:length(c)
        D = 2^s;
        nw = length(c{s});
        for I=0:nw-1
            for J=0:nw-1
                if(~isempty(c{s}{I+1,J+1}))
                    y( I*D+[1:D], J*D+[1:D] ) = c{s}{I+1,J+1};
                end
            end
        end
    end
    res(:,:,i) = y;
end

function x = iwa2sym(res,pat,tp)
% iwa2sym - 2D inverse wave atom transform (symmetric version)
% -----------------
% INPUT
% --
% res is an array containing all the wave atom coefficients. If
% tp=='ortho', then res is of size N-by-N. If tp=='
% If tp=='directional', then res is of size N-by-N-by-2. If tp=='complex',
% then res is of size N-by-N-by-4.
% --
% pat specifies the type of frequency partition which satsifies
% parabolic scaling relationship. pat can either be 'p' or 'q'.
% --
% tp is the type of tranform.
% 	'ortho': orthobasis
% 	'directional': real-valued frame with single oscillation direction
% 	'complex': complex-valued frame
% -----------------
% OUTPUT
% --
% x is a real N-by-N matrix. N is a power of 2.
% -----------------
% Written by Lexing Ying and Laurent Demanet, 2007

if( ismember(tp, {'ortho','directional','complex'})==0 | ismember(pat, {'p','q','u'})==0 )    error('wrong');  end

N = size(res,1);
H = N/2;
lst = freq_pat(H,pat);
red = size(res,3);

call = cell(length(lst),red);
for i=1:red
    y = res(:,:,i);
    c = cell(length(lst),1);
    for s=1:length(lst)
        B = 2^(s-1);    D = 2*B;
        nw = length(lst{s});
        c{s} = cell(nw,nw);
        for I=0:nw-1
            for J=0:nw-1
                if(lst{s}(I+1)==0 & lst{s}(J+1)==0)
                    c{s}{I+1,J+1} = [];
                else
                    c{s}{I+1,J+1} = y( I*D+[1:D], J*D+[1:D] );
                end
            end
        end
    end
    call(:,i) = c;
end
x = iwa2(call,pat,tp);


function [y,zo]=v_filterbank(b,a,x,gd)
%V_FILTERBANK appply v_filterbank to a signal: [y,zo]=(b,a,x,gd)
%
% Inputs:
%    b    numerator coefficients, one row per filter
%    a    denominator coefficients, one row per filter
%    x    input signal
%    gd   group delay of each filter in samples [default=0]. The filter
%         outputs will be advanced to compensate for the group delays.
%         Alternatively, this input can be the zo output from a previous call.
%
% Outputa:
%    y    output signals, one column per filter
%    zo   output filter state

%      Copyright (C) Mike Brookes 2009-2010
%      Version: $Id: v_filterbank.m 10865 2018-09-21 17:22:45Z dmb $
%
%   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=size(b,1);           % number of filters
nz=max(size(b,2),size(a,2))-1;  % size of state  needed
zzo=zeros(nz,nf);
nx=length(x);           % number of input samples
xx=x(:);
if nargin<4 || ~numel(gd)
    gd=zeros(nf,1);
end
if isstruct(gd)
    zi=gd.zzo;          % get filter state
    qd=gd.qd;
    sd=qd(2)-qd(1);     % number of output samples we need to save
    qd(3)=qd(3)+nx;
    rd=gd.rd;
    yy=zeros(nx+sd,nf);
    yy(1:sd,:)=gd.sy;
    for i=1:nf
        [yy(sd+1:end,i),zzo(:,i)]=filter(b(i,:),a(i,:),xx,zi(:,i));
    end
else
    qd=zeros(1,3);      % [min-delay max-delay #samples]
    rd=round(gd);
    qd(1)=min(rd);
    qd(2)=max(rd);      % find the largest delay
    qd(3)=nx;           % number of filtered samples
    sd=qd(2)-qd(1);     % number of output samples we need to save
    yy=zeros(nx+sd,nf);
    for i=1:nf
        [yy(sd+1:end,i),zzo(:,i)]=filter(b(i,:),a(i,:),xx);
    end
end
ny=max(0,min(nx,qd(3)-qd(2)));    % numer of output samples
y=zeros(ny,nf);
if ny>0
    for i=1:nf
        off=rd(i)-qd(1);
        y(:,i)=yy(off+1:off+ny,i);
    end
end
if nargout>1
    zo.zzo=zzo;  % filter state
    zo.qd=qd;    % offsets
    zo.rd=rd; % rounded group delays
    zo.sy=yy(end-sd+1:end,:);  % save old outputs
end
if ~nargout   % plot pseudo spectrogram
    ng=300;         % target number of columns in image
    kd=max(1,floor(ny/ng));     % decimation factor
    jm=floor(ny/kd);  % % number f frames
yd=reshape(sum(reshape(y(1:kd*jm,:).^2,kd,nf*jm),1),jm,nf)/kd;
    ydm=max(yd(:));
    imagesc((1:jm)*kd+qd(3)-ny-(kd-1)/2,1:nf,10*log10(max(yd,ydm/1e4))');
    axis('xy');
    colorbar;
    v_cblabel('dB');
    xlabel('Sample Number');
    ylabel('Filter Channel');
    title('Filterbank output');
end


function [in] = dm2in(dm)
% Convert length from decimeters to inches.
% I've still never used a decimeter.  Who uses this unit?
% Chad A. Greene 2012
in = dm/.254;


function max_index = r8vec_max_abs_index ( n, a )

%*****************************************************************************80
%
%% R8VEC_MAX_ABS_INDEX: index of the maximum absolute value in an R8VEC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 April 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in the array.
%
%    Input, real A(N), the array.
%
%    Output, integer MAX_INDEX, the index of the entry of
%    maximum absolute value.
%
  if ( n <= 0 )

    max_index = -1;

  else

    max_index = 1;

    for i = 2 : n
      if ( abs ( a(max_index) ) < abs ( a(i) ) )
        max_index = i;
      end
    end

  end

  return
end


function f=crand(p1,p2);
%CRAND   Random complex numbers for testing.
%   Usage: f=tester_crand(p1,p2);

f=rand(p1,p2)-.5+i*(rand(p1,p2)-.5);


function lik = lik_gaussiansmt(varargin)
%LIK_GAUSSIANSMT  Create a Gaussian scale mixture likelihood structure
%                 with priors producing approximation of the Student's t
%
%  Description
%    LIK = LIK_GAUSSIANSMT('ndata',N,'PARAM1',VALUE1,'PARAM2,VALUE2,...)
%    creates a scale mixture noise covariance function structure
%    (with priors producing approximation of the Student's t) in
%    which the named parameters have the specified values. Any
%    unspecified parameters are set to default values. Obligatory
%    parameter is 'ndata', which tells the number of data points,
%    that is, number of mixture components.
%
%    LIK = LIK_GAUSSIANSMT(LIK,'PARAM1',VALUE1,'PARAM2,VALUE2,...)
%    modify a covariance function structure with the named
%    parameters altered with the specified values.
%
%    Parameters for the Gaussian scale mixture approximation of the
%    Student's t
%      sigma2    - Variances of the mixture components.
%                  The default is 1 x ndata vector of 0.1s.
%      U         - Part of the parameter expansion, see below.
%                  The default is 1 x ndata vector of 1s.
%      tau2      - Part of the parameter expansion, see below.
%                  The default is 0.1.
%      alpha     - Part of the parameter expansion, see below.
%                  The default is 0.5.
%      nu        - Degrees of freedom. The default is 4.
%      nu_prior  - Prior for nu. The default is prior_fixed().
%      gibbs     - Whether Gibbs sampling is 'on' (default) or 'off'.
%
%    Parametrisation and non-informative priors for alpha and tau
%    are same as in Gelman et. al. (2004) page 304-305:
%      y-E[y] ~ N(0, alpha^2 * U),
%      where U = diag(u_1, u_2, ..., u_n)
%          u_i ~ Inv-Chi^2(nu, tau^2)
%
%    The parameters of this likelihood can be inferred only by
%    Gibbs sampling by calling GP_MC.
%
%    If degrees of freedom nu is given a prior (other than
%    prior_fixed), it is sampled using slice sampling within Gibbs
%    sampling with limits [0,128].
%
%  See also
%    GP_SET, PRIOR_*, LIK_*

% Copyright (c) 1998,1999,2010 Aki Vehtari
% Copyright (c) 2007-2010 Jarno Vanhatalo

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

  ip=inputParser;
  ip.FunctionName = 'LIK_GAUSSIANSMT';
  ip.addOptional('lik', [], @isstruct);
  ip.addParamValue('ndata',[], @(x) isscalar(x) && x>0 && mod(x,1)==0);
  ip.addParamValue('sigma2',[], @(x) isvector(x) && all(x>0));
  ip.addParamValue('U',[], @isvector);
  ip.addParamValue('tau2',0.1, @isscalar);
  ip.addParamValue('alpha',0.5, @isscalar);
  ip.addParamValue('nu',4, @isscalar);
  ip.addParamValue('nu_prior',[], @(x) isstruct(x) || isempty(x));
  ip.addParamValue('censored',[], @(x) isstruct);
  ip.addParamValue('gibbs','on', @(x) ismember(x,{'on' 'off'}));
  ip.parse(varargin{:});
  lik=ip.Results.lik;

  if isempty(lik)
    init=true;
    lik.type = 'Gaussian-smt';
  else
    if ~isfield(lik,'type') || ~isequal(lik.type,'Gaussian-smt')
      error('First argument does not seem to be a valid likelihood function structure')
    end
    init=false;
  end

  % Initialize parameters
  if init || ~ismember('ndata',ip.UsingDefaults)
    ndata = ip.Results.ndata;
    lik.ndata=ndata;
    lik.r = zeros(ndata,1);
  end
  if isempty(ndata)
    error('NDATA has to be defined')
  end
  if init || ~ismember('sigma2',ip.UsingDefaults)
    sigma2=ip.Results.sigma2;
    if isempty(sigma2)
      lik.sigma2 = repmat(0.1,ndata,1);
    else
      if (size(sigma2,1) == lik.ndata && size(sigma2,2) == 1)
        lik.sigma2 = sigma2;
      else
        error('The size of sigma2 has to be NDATAx1')
      end
    end
    lik.sigma2 = sigma2;
  end
  if init || ~ismember('U',ip.UsingDefaults)
    U=ip.Results.U;
    if isempty(U)
      lik.U = ones(ndata,1);
    else
      if size(U,1) == lik.ndata
        lik.U = U;
      else
        error('the size of U has to be NDATAx1')
      end
    end
  end
  if init || ~ismember('tau2',ip.UsingDefaults)
    lik.tau2=ip.Results.tau2;
  end
  if init || ~ismember('alpha',ip.UsingDefaults)
    lik.alpha=ip.Results.alpha;
  end
  if init || ~ismember('nu',ip.UsingDefaults)
    lik.nu=ip.Results.nu;
  end
  if init || ~ismember('censored',ip.UsingDefaults)
    censored=ip.Results.censored;
    if ~isempty(censored)
      lik.censored = censored{1};
      yy = censored{2};
      if lik.censored(1) >= lik.censored(2)
        error('lik_gaussiansmt -> if censored model is used, the limits must be given in increasing order.')
      end

      imis1 = [];
      imis2 = [];
      if lik.censored(1) > -inf
        imis1 = find(yy<=lik.censored(1));
      end
      if lik.censored(1) < inf
        imis2 = find(yy>=lik.censored(2));
      end
      lik.cy = yy([imis1 ; imis2])';
      lik.imis = [imis1 ; imis2];
    end
  end
  % Initialize prior structure
  lik.p=[];
  lik.p.sigma=[];
  if init || ~ismember('nu_prior',ip.UsingDefaults)
    lik.p.nu=ip.Results.nu_prior;
  end
  % using Gibbs or not
  if init || ~ismember('gibbs',ip.UsingDefaults)
    lik.gibbs = ip.Results.gibbs;
  end
  if init
    % Set the function handles to the subfunctions
    lik.fh.pak = @lik_gaussiansmt_pak;
    lik.fh.unpak = @lik_gaussiansmt_unpak;
    lik.fh.lp = @lik_gaussiansmt_lp;
    lik.fh.lpg = @lik_gaussiansmt_lpg;
    lik.fh.cfg = @lik_gaussiansmt_cfg;
    lik.fh.trcov  = @lik_gaussiansmt_trcov;
    lik.fh.trvar  = @lik_gaussiansmt_trvar;
    lik.fh.gibbs = @lik_gaussiansmt_gibbs;
    lik.fh.recappend = @lik_gaussiansmt_recappend;
  end

end

function [w,s] = lik_gaussiansmt_pak(lik)
  w = []; s = {};
end

function [lik, w] = lik_gaussiansmt_unpak(lik, w)

end

function lp =lik_gaussiansmt_lp(lik)
  lp = 0;
end

function lpg  = lik_gaussiansmt_lpg(lik)
  lpg = [];
end

function DKff  = lik_gaussiansmt_cfg(lik, x, x2)
  DKff = [];
end

function C = lik_gaussiansmt_trcov(lik, x)
%LIK_GAUSSIANSMT_TRCOV  Evaluate training covariance matrix
%                    corresponding to Gaussian noise
%  Description
%    C = LIK_GAUSSIANSMT_TRCOV(GP, TX) takes in covariance function
%    of a Gaussian process GP and matrix TX that contains
%    training input vectors. Returns covariance matrix C. Every
%    element ij of C contains covariance between inputs i and j
%    in TX. This subfunction is needed only in Gaussian likelihoods.
%
%  See also
%    LIK_GAUSSIANSMT_COV, LIK_GAUSSIANSMT_TRVAR, GP_COV, GP_TRCOV

  [n, m] =size(x);
  n1=n+1;

  if n ~= lik.ndata
    error(['lik_gaussiansmt -> _trvar: The training variance can be evaluated'...
           '      only for training data.                                 '])
  end

  C = sparse(1:n, 1:n, lik.sigma2, n, n);
end

function C = lik_gaussiansmt_trvar(lik, x)
%LIK_GAUSSIANSMT_TRVAR  Evaluate training variance vector
%                    corresponding to Gaussian noise
%
%  Description
%    C = LIK_GAUSSIANSMT_TRVAR(LIK, TX) takes in covariance function
%    of a Gaussian process LIK and matrix TX that contains
%    training inputs. Returns variance vector C. Every
%    element i of C contains variance of input i in TX. This
%    subfunction is needed  only in Gaussian likelihoods.
%
%
%  See also
%    LIK_GAUSSIANSMT_COV, GP_COV, GP_TRCOV

  [n, m] =size(x);
  if n ~= lik.ndata
    error(['lik_gaussiansmt -> _trvar: The training variance can be evaluated'...
           '      only for training data.                                 '])
  end
  C = lik.sigma2;

end

function [lik, y] = lik_gaussiansmt_gibbs(gp, lik, x, y)
%LIK_GAUSSIANSMT_GIBBS  Function for sampling the sigma2's
%
%  Description
%    Perform Gibbs sampling for the scale mixture variances. This
%    function is likelihood specific.

  [n,m] = size(x);

  % Draw a sample of the mean of y. Its distribution is
  % f ~ N(K*inv(C)*y, K - K*inv(C)*K')
  switch gp.type
    case 'FULL'
      sampy = gp_rnd(gp, x, y, x);
    case 'FIC'
      sampy = gp_rnd(gp, x, y, x, 'tstind', 1:n);
    case {'PIC' 'PIC_BLOCK'}
      sampy = gp_rnd(gp, x, y, x, 'tstind', gp.tr_index);
  end
  % Calculate the residual
  r = y-sampy;

  U = lik.U;
  t2 = lik.tau2;
  alpha = lik.alpha;
  nu = lik.nu;
  rss2=alpha.^2.*U;

  % Perform the gibbs sampling (Gelman et.al. (2004) page 304-305)
  % Notice that 'sinvchi2rand' is parameterized as in Gelman et. al.
  U=sinvchi2rand(nu+1, (nu.*t2+(r./alpha).^2)./(nu+1));
  shape = n*nu./2;                               % These are parameters...
  invscale = nu.*sum(1./U)./2;                   % used in Gelman et al
  t2=gamrnd(shape, 1./invscale);                 % Notice! The matlab parameterization is different
  alpha2=sinvchi2rand(n,mean(r.^2./U));
  rss2=alpha2.*U;
  if ~isempty(lik.p.nu)
    % Sample nu using Gibbs sampling
    pp = lik.p.nu;
    opt=struct('nomit',4,'display',0,'method','doubling', ...
               'wsize',4,'plimit',5,'unimodal',1,'mmlimits',[0; 128]);
    nu=sls(@(nu) (-sum(sinvchi2_lpdf(U,nu,t2))-pp.fh.lp(nu, pp)),nu,opt);
  end
  lik.sigma2 = rss2;
  lik.U = U;
  lik.tau2 = t2;
  lik.alpha = sqrt(alpha2);
  lik.nu = nu;
  lik.r = r;
  if isfield(lik, 'censored')
    imis1 = [];
    imis2 = [];
    if lik.censored(1) > -inf
      imis1 = find(y<=lik.censored(1));
      y(imis1)=normrtrand(sampy(imis1),alpha2*U(imis1),lik.censored(1));
    end

    if lik.censored(1) < inf
      imis2 = find(y>=lik.censored(2));
      y(imis2)=normltrand(sampy(imis2),alpha2*U(imis2),lik.censored(2));
    end
    lik.cy = y([imis1 ; imis2]);
  end
end

function reccf = lik_gaussiansmt_recappend(reccf, ri, lik)
%RECAPPEND  Record append
%
%  Description
%    RECCF = LIK_GAUSSIANSMT_RECAPPEND(RECCF, RI, LIK)
%    takes a likelihood record structure RECCF, record
%    index RI and likelihood structure LIK with the
%    current MCMC samples of the parameters. Returns
%    RECCF which contains all the old samples and the
%    current samples from LIK . This subfunction is
%    needed when using MCMC sampling (gp_mc).
%
%  See also
%    GP_MC and GP_MC -> RECAPPEND

  if nargin == 2
    % Initialize the record
    reccf.type = 'Gaussian-smt';
    lik.ndata = [];

    % Initialize parameters
    reccf.sigma2 = [];

    % Set the function handles
    reccf.fh.pak = @lik_gaussiansmt_pak;
    reccf.fh.unpak = @lik_gaussiansmt_unpak;
    reccf.fh.lp = @lik_gaussiansmt_lp;
    reccf.fh.lpg = @lik_gaussiansmt_lpg;
    reccf.fh.cfg = @lik_gaussiansmt_cfg;
    reccf.fh.cov = @lik_gaussiansmt_cov;
    reccf.fh.trcov  = @lik_gaussiansmt_trcov;
    reccf.fh.trvar  = @lik_gaussiansmt_trvar;
    reccf.fh.gibbs = @lik_gaussiansmt_gibbs;
    reccf.fh.recappend = @lik_gaussiansmt_recappend;
  else
    % Append to the record
    reccf.ndata = lik.ndata;
    gpp = lik.p;

    % record noiseSigma
    reccf.sigma2(ri,:)=lik.sigma2;
    if ~isempty(lik.nu)
      reccf.nu(ri,:)=lik.nu;
      reccf.U(ri,:) = lik.U;
      reccf.tau2(ri,:) = lik.tau2;
      reccf.alpha(ri,:) = lik.alpha;
      reccf.r(ri,:) = lik.r;
    end
    if isfield(lik, 'censored')
      reccf.cy(ri,:) = lik.cy';
    end
  end
end


function [ pos ] = scoremap_to_coord( p, locations, crop, locref )

if nargin < 4
    locref = [];
end

scale_factor = p.scale_factor;
stride = p.stride;
half_stride = stride/2;
locref_scale = p.locref_scale;

crd = (locations-1)*stride;
if p.res_net
    crd = crd + half_stride;
end
if ~isempty(locref)
    crd = crd + squeeze(locref)*locref_scale;
end
pos = bsxfun(@plus, crd/scale_factor, double(crop(1:2)-1));

end


k=0;
while k<4
	k=k+1;
	B(k)=k.^2
end


function [f, df] = func_split_spcp(x,Y,params,errFcn)
% [f, df] = func_split_spcp(x,Y,params,errFunc)
% [errHist] = func_split_spcp();
% [S] = func_split_spcp(x,Y,params,'S');
%
% Compute function and gradient of split-SPCP objective
%
%   lambda_L/2 (||U||_F^2 + ||V||_F^2) + phi(U,V)
%
% where
%
%   phi(U,V) = min_S .5|| U*V' + S - Y ||_F^2 + lambda_S ||S||_1.

persistent errHist

if nargin==0
   f = errHist;
   errHist = [];
   return;
end

if nargin<3, params=[]; end
m   = params.m;
n   = params.n;
k   = params.k;
lambdaL = params.lambdaL;
lambdaS = params.lambdaS;
useGPU  = params.gpu;

U = reshape(x(1:m*k),m,k);
V = reshape(x(m*k+1:m*k+n*k),n,k);

L   = U*V';
LY = vec(Y-L);

soft_thresh  = @(LY,lambdaS) sign(LY).*max(abs(LY) - lambdaS,0);
S = soft_thresh(LY,lambdaS);
if nargout==1
    f = S;
    return;
end
SLY = reshape(S-LY,m,n);

fS = norm(SLY,'fro')^2/2 + lambdaS*norm(S(:),1);

f = lambdaL/2*(norm(U,'fro')^2 + norm(V,'fro')^2) + fS;

if nargout > 1

    if useGPU
        df = gpuArray.zeros(m*k + n*k,1);
    else
        df = zeros(m*k + n*k,1);
    end

    df(1:m*k) = vec(lambdaL*U) + vec((SLY)*V);
    df(m*k+1:m*k+n*k) = vec(lambdaL*V) + vec((SLY)'*U);

end

errHist(end+1,1) = toc;
errHist(end,2) = gather(f);

if ~isempty(errFcn)
    errHist(end,3) = errFcn(x);
end

tic;

end

function out = setOpts( params, field, default )
    if ~isfield( params, field )
        params.(field)    = default;
    end
    out = params.(field);
    params    = rmfield( params, field ); % so we can do a check later
end


function X = cell2mat_ov_sum(I,xx_s,xx_f,yy_s,yy_f,zz_s,zz_f,overlap,sz,Bs)

% converts a cell array to a matrix when the cell elements overlap
% INPUTS:
% I:            cell array
% grid_size:    true size of each element
% overlap:      amount of overlap in each direction
% d1:           number of rows of matrix
% d2:           number of columns of matrix

% OUTPUT:
% X:            output matrix

% Written by Eftychios A. Pnevmatikakis, Simons Foundation, 2016

if nargin < 10 || isempty(Bs)
    Bs = cellfun(@(x) ones(size(x)), I,'un',0);
end
X = zeros([sz,size(I{1,1},length(sz)+1)]);
B = zeros(size(X));
if length(sz) == 2; sz(3) = 1; end

for i = 1:length(xx_f)
    for j = 1:length(yy_f)
        for k = 1:length(zz_f)
            extended_grid = [max(xx_s(i)-overlap(1),1),min(xx_f(i)+overlap(1),sz(1)),max(yy_s(j)-overlap(2),1),min(yy_f(j)+overlap(2),sz(2)),max(zz_s(k)-overlap(3),1),min(zz_f(k)+overlap(3),sz(3))];
            %W = construct_weights([xx_s(i),xx_f(i),yy_s(j),yy_f(j),zz_s(k),zz_f(k)],extended_grid)';
            Xtemp = zeros(size(I{i,j,k}));
            Btemp = Xtemp;
            ind = ~isnan(I{i,j,k});
            Xtemp(ind) = Bs{i,j,k}(ind).*I{i,j,k}(ind);
            Btemp(ind) = Bs{i,j,k}(ind);
            %X(extended_grid(1):extended_grid(2),extended_grid(3):extended_grid(4),extended_grid(5):extended_grid(6)) = X(extended_grid(1):extended_grid(2),extended_grid(3):extended_grid(4),extended_grid(5):extended_grid(6)) + Bs{i,j,k}.*I{i,j,k};
            %B(extended_grid(1):extended_grid(2),extended_grid(3):extended_grid(4),extended_grid(5):extended_grid(6)) = B(extended_grid(1):extended_grid(2),extended_grid(3):extended_grid(4),extended_grid(5):extended_grid(6)) + Bs{i,j,k}.*(I{i,j,k}~=0);
            X(extended_grid(1):extended_grid(2),extended_grid(3):extended_grid(4),extended_grid(5):extended_grid(6)) = X(extended_grid(1):extended_grid(2),extended_grid(3):extended_grid(4),extended_grid(5):extended_grid(6)) + Xtemp;
            B(extended_grid(1):extended_grid(2),extended_grid(3):extended_grid(4),extended_grid(5):extended_grid(6)) = B(extended_grid(1):extended_grid(2),extended_grid(3):extended_grid(4),extended_grid(5):extended_grid(6)) + Btemp;
        end
    end
end

X = X./B;
%X(isnan(X))=0;


function[mat,xmid,ymid]=twodhist(varargin)
%TWODHIST  Two-dimensional histogram.
%   __________________________________________________________________
%
%   *|* twodhist.png --- Histogram of the global drifter dataset.
%   Type 'jhelp twodhist' to view this image. *|*
%   __________________________________________________________________
%
%   MAT=TWODHIST(X,Y,XBIN,YBIN) where X and Y are arrays of the same
%   length, creates a two-dimensional histogram MAT with bin edges
%   specified by XBIN and YBIN.
%
%   If XBIN and YBIN are length N and M, respectively, then MAT is of
%   size M-1 x N-1.  XBIN and YBIN must be monotonically increasing.
%
%   [MAT,XMID,YMID]=TWODHIST(...) optionally returns the midpoints XMID
%   and YMID of the bins.
%
%   TWODHIST, TWODSTATS, and TWODMED are three related functions for
%   computing statistics as a function two variables using very fast
%   algorithms that avoid any loops through efficient use of indexing.
%
%   X and Y can also be cell arrays of numerical arrays, in which case
%   all data values are concatented prior to finding the histogram.
%   __________________________________________________________________
%
%   Automatic bin calculation
%
%   TWODHIST can compute appropriate bins internally.
%
%   [MAT,XMID,YMID]=TWODIST(X,Y,N) uses N bins in the X and Y directions,
%   linearly spaced between the minimum and maximum values, and returns the
%   bin midpoints in XMID and YMID.  MAT is N-1 x N-1.
%
%   [MAT,XMID,YMID]=TWODIST(X,Y,[XMIN XMAX],[YMIN YMAX],N) similarly uses N
%   bins, linearly spaced between the designated X and Y values.
%   __________________________________________________________________
%
%   Algorithms
%
%   By default, TWODHIST now works with an internal call to Matlab's
%   HISTCOUNTS2 function, available as of Matlab 2015b.  This is much
%   faster than the previous algorithm.
%
%   If HISTCOUNTS2 is not available, TWODHIST uses loopless algorithm that
%   is in turn much faster than an explicit loop.  TWODHIST(...,'jlab')
%   uses this algorithm, while TWODHIST(...,'slow') uses the explicit loop.
%   These options are mostly used for testing purposes.
%   __________________________________________________________________
%
%   Parallelization
%
%   TWODHIST(...,'parallel') parallelizes the computation using the fast
%   algorithm together with SPMD.  This requires that Matlab's Parallel
%   Computing Toolbox be installed.  While TWODHIST is already very fast,
%   parallelization may be useful for extremely large datasets.
%   __________________________________________________________________
%
%   See also TWODMED, TWODSTATS.
%
%   'twodhist --f' generates the sample figure shown above.
%   'twodhist --t' runs some tests.
%
%   Usage: [mat,xmid,ymid]=twodhist(x,y,N);
%          [mat,xmid,ymid]=twodhist(x,y,[xmin xmax],[ymin ymax],N);
%          mat=twodhist(x,y,xbin,ybin);
%          [mat,xmid,ymid]=twodhist(x,y,xbin,ybin,'parallel');
%   __________________________________________________________________
%   This is part of JLAB --- type 'help jlab' for more information
%   (C) 2004--2015 J.M. Lilly --- type 'help jlab_license' for details

%   Additional output
%
%   [MAT,XMID,YMID,INDEX]=TWODHIST(X,Y,...) also returns INDEX, an array of
%   the same size as X and Y giving the index into the matrix MAT
%   corresponding to each (X,Y) data point.
%   __________________________________________________________________

if strcmpi(varargin,'--t')
   twodhist_test;return
elseif strcmpi(varargin,'--f')
   type makefigs_twodhist
   makefigs_twodhist;
   return
end

parstr='serial';
str='histcounts2';

xdata=varargin{1};
ydata=varargin{2};

if iscell(xdata)
    [xdata,ydata]=cell2col(xdata,ydata);
end
if ~isreal(xdata)||~isreal(ydata)
    error('X and Y must be real-valued.');
end
if ~aresame(size(xdata),size(ydata))
     error('X and Y should have the same size.')
end
vcolon(xdata,ydata);

bool=isfinite(xdata)&isfinite(ydata);
xdata=xdata(bool);
ydata=ydata(bool);

for i=1:2
    if ischar(varargin{end})
        if strcmpi(varargin{end}(1:3),'ser')||strcmpi(varargin{end}(1:3),'par')
            parstr=varargin{end};
        else
            str=varargin{end};
        end
        varargin=varargin(1:end-1);
    end
end

if strcmpi(str(1:3),'his')&&(exist('histcounts2')~=2)
    str='jlab';
    disp('HISTCOUNTS2 not found; reverting to former JLAB algorithm.')
end

if strcmpi(parstr(1:3),'par')
    if exist('parpool')~=2
        disp('Sorry, parallel algorithm requires the Parallel Computing Toolbox.')
        disp('Defaulting to the serial algorithm.')
        str='serial';
    end
end

if length(varargin)==4
    xbin=varargin{3};
    ybin=varargin{4};
elseif length(varargin)==3
    N=varargin{3};
    xbin=linspace(minmin(xdata),maxmax(xdata),N);
    ybin=linspace(minmin(ydata),maxmax(ydata),N);
elseif length(varargin)==5
    N=varargin{5};
    xbin=linspace(varargin{3}(1),varargin{3}(2),N);
    ybin=linspace(varargin{4}(1),varargin{4}(2),N);
end

xbin=xbin(:);
ybin=ybin(:);
if any(diff(xbin)<0)
  error('XBIN must be monotonically increasing')
end
if any(diff(ybin)<0)
  error('YBIN must be monotonically increasing')
end

%Exclude points which are obviously outside of the domain
bool=xdata<xbin(end)&xdata>xbin(1)&ydata<ybin(end)&ydata>ybin(1);
xdata=xdata(bool);
ydata=ydata(bool);

if ~isempty(xdata)
    if strcmpi(parstr(1:3),'ser')
        mat=twodhist_one(xdata,ydata,xbin,ybin,str);
    elseif strcmpi(parstr(1:3),'par')
        %Parallel Algorithm
        disp('TWODHIST employing parallel algorithm.')
        pool=gcp;
        Nworkers=pool.NumWorkers;
        N=length(xdata);
        M=floor(N/Nworkers);
        spmd
            %Determine the data to send to each worker
            if labindex<Nworkers
                spmdindex=(labindex-1)*M+1:labindex*M;
            else
                %A few leftover time series go to the last worker
                spmdindex=(labindex-1)*M+1:N;
            end
            mati=twodhist_one(xdata(spmdindex),ydata(spmdindex),xbin,ybin,str);
        end
        mat=zeros(size(mati{1}));
        for i=1:length(mati)
            mat=mat+mati{i};
        end
    end
else
    disp('Warning: No valid data in specified region.')
    mat=0*oprod(ybin(1:end-1),xbin(1:end-1));
end

if nargout>1
  xmid=(xbin+vshift(xbin,1,1))./2;
  xmid=xmid(1:end-1);
end
if nargout>2
  ymid=(ybin+vshift(ybin,1,1))./2;
  ymid=ymid(1:end-1);
end

function[mat]=twodhist_one(xdata,ydata,xbin,ybin,str)

if strcmpi(str(1:3),'his')
    mat=histcounts2(xdata,ydata,xbin,ybin)';
elseif strcmpi(str(1:3),'jla')
    mat=twodhist_jlab(xdata,ydata,xbin,ybin);
elseif strcmpi(str(1:3),'slo')
    mat=twodhist_slow(xdata,ydata,xbin,ybin);
end

function[mat]=twodhist_jlab(xdata,ydata,xbin,ybin)

[xnum,xi,xmid]=bindata(xbin,xdata);
[ynum,yi,ymid]=bindata(ybin,ydata);

mat=zeros([length(ybin)-1,length(xbin)-1]);
index=nan*zeros(size(xdata));

nani=(~isnan(xnum)&~isnan(ynum));

if sum(nani(:))>0
    index(nani)=sub2ind([length(ybin)-1,length(xbin)-1],ynum(nani),xnum(nani));
    [indexsorted,sorter]=sort(index(nani));
    [L,ia]=blocklen(indexsorted);
    mat(indexsorted(ia))=L(ia);
end

function[mat]=twodhist_slow(xdata,ydata,xbin,ybin)
mat=zeros(length(ybin),length(xbin));
[xbinb,ybinb]=vshift(xbin,ybin,1,1);
for i=1:length(xbin)
    for j=1:length(ybin)
        mat(j,i)=length(find(xdata>xbin(i)&xdata<=xbinb(i)&...
            ydata>ybin(j)&ydata<=ybinb(j)));
    end
end
mat=mat(1:end-1,:);
mat=mat(:,1:end-1);

function[]=twodhist_test
L=10000;
xdata=3*abs(rand(L,1));
ydata=3*abs(rand(L,1));
xbin=(0:.1:2);
ybin=(0:.2:2);
tic;
mat1=twodhist(xdata,ydata,xbin,ybin);
dt1=toc;
tic
mat2=twodhist(xdata,ydata,xbin,ybin,'slow');
dt2=toc;
bool=aresame(mat1,mat2,1e-10);
reporttest('TWODHIST fast vs. slow algorithm',bool)
%disp(['TWODHIST fast algorithm was ' num2str(dt2./dt1) ' times faster than direct algorithm.'])

if exist('parpool')==2
    mat3=twodhist(xdata,ydata,xbin,ybin,'parallel');
    bool=aresame(mat1,mat3,1e-10);
    reporttest('TWODHIST fast vs. parallel algorithm',bool)
end

xdata=-3*abs(rand(L,1));
ydata=-3*abs(rand(L,1));
xbin=(-2:.1:0);
ybin=(-2:.2:0);
mat1=twodhist(xdata,ydata,xbin,ybin);
mat2=twodhist(xdata,ydata,xbin,ybin,'slow');
bool=aresame(mat1,mat2,1e-10);
reporttest('TWODHIST fast vs. slow algorithm, negative bins',bool)

xdata=randn(L,1);
ydata=randn(L,1);
xbin=(-2:.1:2);
ybin=(-2:.2:2);
mat1=twodhist(xdata,ydata,xbin,ybin);
mat2=twodhist(xdata,ydata,xbin,ybin,'slow');
bool=aresame(mat1,mat2,1e-10);
reporttest('TWODHIST fast vs. slow algorithm, crossing zero',bool)

L=10000;
xdata=3*abs(rand(L,1));
ydata=3*abs(rand(L,1));
xbin=(0:.1:2);
ybin=(0:.2:2);
tic;
mat1=twodhist(xdata,ydata,xbin,ybin);
dt1=toc;
tic
mat2=twodhist(xdata,ydata,xbin,ybin,'slow');
dt2=toc;
bool=aresame(mat1,mat2,1e-10);
reporttest('TWODHIST fast vs. slow algorithm',bool)

if exist('histcounts2')==2
    xdata=randn(L,1);
    ydata=randn(L,1);
    xbin=(-2:.1:2);
    ybin=(-2:.2:2);
    tic;mat1=twodhist(xdata,ydata,xbin,ybin,'histcounts2');toc;
    tic;mat2=twodhist(xdata,ydata,xbin,ybin,'jlab');toc;
    bool=aresame(mat1,mat2,1e-10);
    reporttest('TWODHIST JLAB vs. HISTCOUNTS algorithm, crossing zero',bool)
end


function femIF = genNedIFEM3DFace(mesh,fem,femI)
%% Usage: Generate Quadrature Information on Interface Faces Used in PPIFEM
%         Each interface face (triangle) is cut into 3 small triangles
%            A1                A1
%           D  E      or      E  D         equivalent
%          A2  A3            A3   A2
%
%          p = [A1;D;E;A2;A3];
%          t = [1 2 3; 2 3 4; 3 4 5]
%
% femIF.tL --- global index of left element
% femIF.tR --- global index of right element
% femIF.basL --- 3*nfi-4-4 matrix basis functions of left elem on small tri
% femIF.basR --- 3*nfi-4-4 matrix basis functions of right elem on small tri
% femIF.gx --- Gaussian x nodes on small tri
% femIF.gy --- Gaussian y nodes on small tri
% femIF.gz --- Gaussian z nodes on small tri
% femIF.gw --- Gaussian weights on small tri (3 Gaussian pt for linear IFEM)
% femIF.area --- Areas of all small tri
% femIF.normal --- unit normal vector of each small tri

% Last Modified by Xu Zhang 08/07/2020
%%
nfI = -min(mesh.fLoc); % number of interface faces
intFID = find(mesh.fLoc<0);
nfIB = size(find(mesh.f_t(intFID,2)==0),1); % # of interface faces on Boundary
nfII = nfI - nfIB; % # of internal interface faces: two tetra share it L&R
tL = zeros(3*nfII,6); tR = zeros(3*nfII,6);
tIntfLID = zeros(3*nfII,1); tIntfRID = zeros(3*nfII,1);
basL = zeros(3*nfII,6,6); basR = zeros(3*nfII,6,6);
gx = zeros(3*nfII,3); gy = zeros(3*nfII,3); gz = zeros(3*nfII,3);
A = zeros(3*nfII,1); normal = zeros(3*nfII,3);

tB = zeros(3*nfIB,6); basB = zeros(3*nfIB,6,6);
gxB = zeros(3*nfIB,3); gyB = zeros(3*nfIB,3); gzB = zeros(3*nfIB,3);
AB = zeros(3*nfIB,1); normalB = zeros(3*nfIB,3);

id = 0; idB = 0;
for i = 1:nfI
    %% Form small triangular partition on the interface face
    fID = intFID(i); % face index
    f_e = mesh.f_e(fID,:); % three surrounding edge index
    idE = find(mesh.eLoc(f_e)<0); % find index of two interface edges
    tmp = [mesh.e(f_e(idE(1)),:), mesh.e(f_e(idE(2)),:)];
    nd1 = sum(tmp) - sum(unique(tmp)); % the node of two interface edges
    nd2 = sum(mesh.e(f_e(idE(1)),:)) - nd1;
    nd3 = sum(mesh.e(f_e(idE(2)),:)) - nd1;
    p = [mesh.p(nd1,:); mesh.eIntP(-mesh.eLoc(f_e(idE(1))),:); ...
        mesh.eIntP(-mesh.eLoc(f_e(idE(2))),:); mesh.p(nd2,:); mesh.p(nd3,:)];
    t = [1 2 3; 2 3 4; 3 4 5];

    %% gx gy gz on a triangle with 3 internal point, accurate upto pd = 2
    X1 = p(t(:,1),:);  X2 = p(t(:,2),:);   X3 = p(t(:,3),:);
    G = zeros(3,9);  w1 = 2/3;  w2 = 1/6; % see gaussPtri.m
    G(:,[1,4,7]) = w1*X1 + w2*(X2+X3);
    G(:,[2,5,8]) = w1*X2 + w2*(X1+X3);
    G(:,[3,6,9]) = w1*X3 + w2*(X1+X2);

    %% triangle area on three-dimension.
    x1 = X1(:,1);  y1 = X1(:,2);   z1 = X1(:,3);
    x2 = X2(:,1);  y2 = X2(:,2);   z2 = X2(:,3);
    x3 = X3(:,1);  y3 = X3(:,2);   z3 = X3(:,3);
    AT = 1/2*(((x1-x3).*(y2-y1) - (x1-x2).*(y3-y1)).^2 + ...
        ((y1-y3).*(z2-z1) - (y1-y2).*(z3-z1)).^2 + ...
        ((z1-z3).*(x2-x1) - (z1-z2).*(x3-x1)).^2).^(1/2);

    %% Left and Right Element
    tIDL = mesh.f_t(fID,1); % element index of left element
    tIDR = mesh.f_t(fID,2); % element index of right element
    if tIDR > 0 % Internal Face
        tIDLi = -mesh.tLoc(tIDL); % intf elem index of left element
        tIDRi = -mesh.tLoc(tIDR); % intf elem index of right element

        %% Determine piece
        nd1ID = mesh.pLoc(nd1); tLp = femI.plusPC(tIDLi); tRp = femI.plusPC(tIDRi);
        if (nd1ID < 0 && tLp == 1) || (nd1ID > 0 && tLp == 2)
            basL(id+1,:,:) = femI.bas2(tIDLi,:,:);
            basL(id+2,:,:) = femI.bas1(tIDLi,:,:);
            basL(id+3,:,:) = femI.bas1(tIDLi,:,:);
        elseif (nd1ID < 0 && tLp == 2) || (nd1ID > 0 && tLp == 1)
            basL(id+1,:,:) = femI.bas1(tIDLi,:,:);
            basL(id+2,:,:) = femI.bas2(tIDLi,:,:);
            basL(id+3,:,:) = femI.bas2(tIDLi,:,:);
        end
        if (nd1ID < 0 && tRp == 1) || (nd1ID > 0 && tRp == 2)
            basR(id+1,:,:) = femI.bas2(tIDRi,:,:);
            basR(id+2,:,:) = femI.bas1(tIDRi,:,:);
            basR(id+3,:,:) = femI.bas1(tIDRi,:,:);
        elseif (nd1ID < 0 && tRp == 2) || (nd1ID > 0 && tRp == 1)
            basR(id+1,:,:) = femI.bas1(tIDRi,:,:);
            basR(id+2,:,:) = femI.bas2(tIDRi,:,:);
            basR(id+3,:,:) = femI.bas2(tIDRi,:,:);
        end

        gx(id+1:id+3,:) = G(:,1:3);
        gy(id+1:id+3,:) = G(:,4:6);
        gz(id+1:id+3,:) = G(:,7:9);

        A(id+1:id+3,:) = AT;
        normal(id+1:id+3,:) = repmat(mesh.f_norm(fID,:),3,1);

        %% tL and tR, use locID, b/c index on interface cell is different
        temp = fem.g2ldof(tIDL,:);
        %temp1 = temp(femI.elocIDvec(tIDLi,:));
        tL(id+1:id+3,:) = repmat(temp,3,1);
        tIntfLID(id+1:id+3,:) = tIDL;

        temp = fem.g2ldof(tIDR,:);
        %temp2 = temp(femI.elocIDvec(tIDRi,:));
        tR(id+1:id+3,:) = repmat(temp,3,1);
        tIntfRID(id+1:id+3,:) = tIDR;
        id = id+3;

    elseif tIDR == 0 % Boundary Face
        tIDLi = -mesh.tLoc(tIDL); % intf elem index of left element

        %% Determine piece: only one element.
        nd1ID = mesh.pLoc(nd1); tLp = femI.plusPC(tIDLi);
        if (nd1ID < 0 && tLp == 1) || (nd1ID > 0 && tLp == 2)
            basB(idB+1,:,:) = femI.bas2(tIDLi,:,:);
            basB(idB+2,:,:) = femI.bas1(tIDLi,:,:);
            basB(idB+3,:,:) = femI.bas1(tIDLi,:,:);
        elseif (nd1ID < 0 && tLp == 2) || (nd1ID > 0 && tLp == 1)
            basB(idB+1,:,:) = femI.bas1(tIDLi,:,:);
            basB(idB+2,:,:) = femI.bas2(tIDLi,:,:);
            basB(idB+3,:,:) = femI.bas2(tIDLi,:,:);
        end

        gxB(idB+1:idB+3,:) = G(:,1:3);
        gyB(idB+1:idB+3,:) = G(:,4:6);
        gzB(idB+1:idB+3,:) = G(:,7:9);

        AB(idB+1:idB+3,:) = AT;
        normalB(idB+1:idB+3,:) = repmat(mesh.f_norm(fID,:),3,1);

        %% tB use locID, b/c index on interface cell is different
        temp = fem.t(tIDL,:);
        temp1 = temp(femI.locID(tIDLi,:));
        tB(idB+1:idB+3,:) = repmat(temp1,3,1);
        idB = idB+3;
    end
end

femIF = struct('tL',tL,'tR',tR,'tB',tB,'basL',basL,'basR',basR,'basB',basB, ...
    'gx',gx,'gy',gy,'gz',gz,'gxB',gxB,'gyB',gyB,'gzB',gzB,'area',A,'areaB',AB,...
    'gw',[1/3;1/3;1/3],'normal',normal,'normalB',normalB,'tIntfLID',tIntfLID,...
    'tIntfRID',tIntfRID);


function [U2] = mle_lam1(X,phi2,v1,PP,PnP,n,T);
%
%
% this function calculates the maximum likelihood function U2
% (lambda) with 1 Fourier harmonic
%
b=phi2+X(1)*sin(n/T+X(2));
mb=kron(b,v1);   % produces a matrix with identical lines
A=PnP.*log(mb);
B=PP.*mb;
%
U2=sum(sum(A))-sum(sum(B));
U2=-U2;


function [ops, stat, res] = fast_clustering_with_neuropil(ops, U, Sv)

U =  reshape(U, [], size(U,ndims(U)));
iplane = ops.iplane;

for i = 1:size(U,2)
  U(:,i) = U(:,i)  * Sv(i).^.5;
end
U = U';
[nSVD, Npix] = size(U);
%% clustering options
Ly = numel(ops.yrange);
Lx = numel(ops.xrange);

ops.Nk0 = floor(sqrt(ops.Nk0))^2;

Nk      = ops.Nk0;
nsqrt = round(sqrt(Nk));

xs = repmat(round(linspace(1, nsqrt, Lx)), Ly, 1);
ys = repmat(round(linspace(1, nsqrt, Ly))', 1, Lx);
iclust = xs + (ys-1) * nsqrt;

clear xs ys

niter   = ops.niterclustering;

% xs = repmat(1:Lx, Ly, 1);
% ys = repmat((1:Ly)', 1, Lx);
%
% randx = rand(1, Nk) * Lx;
% randy = rand(1, Nk) * Ly;
%
% dx = repmat(xs(:), 1, Nk) - repmat(randx, numel(xs(:)), 1);
% dy = repmat(ys(:), 1, Nk) - repmat(randy, numel(ys(:)), 1);
%
% dxy = dx.^2 + dy.^2;
% [~, iclust] = min(dxy, [], 2);
%%
% clear dx dy

if ops.ShowCellMap
    figure( 'Units', 'pixels', 'position', [100 100 900 900])
    colormap('hsv')
    axes('position', [.05 .05 .925 .925])
    set(gcf, 'Color', 'w')
end

r   = rand(1, Nk);
Sat = ones(Ly, Lx);

err = zeros(niter,1);
ops.meanV = gather(sum(Sv)/(Ly*Lx));

Nk = ops.Nk0;
Nkiter = round(linspace(ops.Nk0, ops.Nk, niter-2));
Nkiter(end+1:(niter+1)) = ops.Nk;

%%
M = .0001 * ones(1, Npix, 'single');

ison = true(Nk,1);
%
nBasis = 10;

xc = linspace(1, Lx, nBasis);
yc = linspace(1, Ly, nBasis);
yc = yc';
xs = 1:Lx;
ys = 1:Ly;

sigx = 4*(Lx - 1)/nBasis;
sigy = 4*(Ly - 1)/nBasis;

S = zeros(Ly, Lx, nBasis, nBasis, 'single');
for kx = 1:nBasis
    for ky = 1:nBasis
        cosx = 1+cos(2*pi*(xs - xc(kx))/sigx);
        cosy = 1+cos(2*pi*(ys - yc(ky))/sigy);
        cosx(abs(xs-xc(kx))>sigx/2) = 0;
        cosy(abs(ys-yc(ky))>sigy/2) = 0;

        S(:, :,ky, kx) = cosy' * cosx;
    end
end
S = reshape(S, [], nBasis^2);
S = normc(S);

%%
% nBasis = 0;
% S = zeros(Npix, nBasis^2);

StS = S' * S;
StU = S' * U';
LtL = zeros(Nk, Nk, 'single');
LtU = zeros(Nk, nSVD, 'single');
LtS = zeros(Nk, nBasis^2, 'single');
Ireg = diag([ones(Nk,1); zeros(nBasis^2,1)]);

tic
for k = 1:niter
    for i = 1:Nk
        ix = find(iclust==i);
        if numel(ix)==0
            LtU(i,:) = 0;
            LtL(i,i) = 0;
            LtS(i,:) = 0;
        else
            LtU(i,:) = M(ix) * U(:, ix)';
            LtL(i,i) = sum(M(ix).^2);
            LtS(i,:) = M(ix) * S(ix, :);
        end
    end
    %
    covL = [LtL LtS; LtS' StS];
    LtXS = [LtU; StU];

    Lam = (covL + 1e-4 * Ireg) \ LtXS;

    vs = normc(Lam(1:Nk, :)');
    neuropil = Lam(Nk + [1:nBasis^2], :)' * S';

    xs = vs' * (U - neuropil);

    [M, iclust] = max(xs,[],1);
    if 1
        %---------------------------------------------%
        xs(iclust + (0:Nk:numel(xs)-1)) = 0;
        [M2, iclust2] = max(abs(xs),[],1);

        dM = M - M2;
        indrem = Nkiter(k) - Nkiter(k+1);
        dMk = 0*ones(Nk,1);
        icl = cell(Nk,1);
        for j = 1:Nk
            icl{j} = iclust==j;
            if ~isempty(icl{j})
                dMk(j) = sum(dM(icl{j}));
            end
        end

        vlk = zeros(Nk, 1);
        vlk(~ison) = Inf;
        while indrem>0
            [Xmin, imin]          = min(dMk + vlk);
            if isinf(Xmin)
                Nkiter(k+1) = sum(ison);
                break;
            end
            newi               = iclust2(icl{imin});
            iclust(icl{imin})  = newi;
            M(icl{imin})       = M2(icl{imin});
            dMk(unique(newi))  = Inf;
            dMk(imin)          = Inf;
            dMk(unique(iclust(iclust2==imin))) ...
                = Inf;

            ison(imin) = 0;
            indrem             = indrem - 1;
        end
    end
    %---------------------------------------------%

    err(k) = sum(M(:));

    if (rem(k,10)==1 || k==niter) && ops.ShowCellMap
        %%
        lam = M;
        for i = 1:Nk
            ix = find(iclust==i);
            nT0 = numel(ix);
            if nT0>0
                vM = lam(ix);
%                 vM = vM/sum(vM.^2)^.5;
                lam(ix) = vM;
            end
        end
%         V = max(0, min(10 * reshape(lam, Ly, Lx), 1));
        V = max(0, min(.5 * reshape(lam, Ly, Lx)/mean(lam(:)), 1));
        H = reshape(r(iclust), Ly, Lx);
        rgb_image = hsv2rgb(cat(3, H, Sat, V));
        imagesc(rgb_image)
        axis off
        drawnow
        fprintf('explained variance is %2.6f time %2.2f \n', err(k), toc)
    end

end

lam = M;
for i = 1:Nk
    ix = find(iclust==i);

    nT0 = numel(ix);
    if nT0>0
        vM = lam(ix);
        lam(ix) = vM/sum(vM.^2)^.5;
    end
end

%%
newindx = cumsum(ison);
iclust  = newindx(iclust);
Nk      = numel(unique(iclust));
%
clear res

res.iclust  = iclust;
res.M       = M;
res.S       = S;
res.covL    = covL + 1e-4 * Ireg;
res.lambda  = lam;

%
res.Ly  = Ly;
res.Lx  = Lx;
stat    = get_stat(res);

if ~exist(ops.ResultsSavePath, 'dir')
    mkdir(ops.ResultsSavePath)
end
save(sprintf('%s/F_%s_%s_plane%d_Nk%d.mat', ops.ResultsSavePath, ...
    ops.mouse_name, ops.date, iplane, Nk),  'ops', 'res', 'stat')

%%
% sk = skewness(F,[],2);
% [~, isk] = sort(sk, 'descend');
% clf
% for i = 1:20
%    plot(5*i + zscore(F(isk(i), :)))
%    hold all
% end
% axis tight


report_this_filefun(mfilename('fullpath'));

re = []
for i = min(newt2.Magnitude):0.1:max(newt2.Magnitude)-0.5
    i
    l = newt2.Magnitude >= i;
    [bv magco stan av me,  mer] =  bvalcalc(newt2(l,:));
    re = [re ; i bv me];
end

figure
pl = plot(re(:,1),re(:,3),'b')
set(pl,'LineWidth',2.5)
hold on
pl = plot(re(:,1),re(:,2),':r')
set(pl,'LineWidth',2.5)
set(gca,'box','on',...
    'SortMethod','childorder','TickDir','out','FontWeight',...
    'bold','FontSize',ZmapGlobal.Data.fontsz.m,'Linewidth',1.2)

le =legend('-b','b(L2)','ro','b(maxli)');
grid
xlabel('Magnitude')
ylabel('b-value')


function [pred,model,prob] = mdlTrans_tsvm(Xl,Yl,Xu,param)
%Wrapper of Transducive SVM
%
%	This is a model-level semi-supervised (transductive) learning
% algorithm. It may be used as a baseline to other domain adaptation
% methods.
% Application scope:
%	+ partially labeled data
%	+ label type: classification

% Xl:	labeled X
% Yl:	labels of Xl, should be a vector containing class indices starting from 1
% Xu:	unlabeled X
%
% param: Struct of hyper-parameters, please see the first cell of this
%	program ("default parameters") for details. You can set parameter p to
%	x by setting param.p = x. For parameters that are not set, default
%	values will be used.

% pred : predicted labels for Xu
% prob : the confidence of pred
% model: model. For multi-class problems, one-vs-all strategy will be used
%	and model{i} is the model for class i
%
%	The svm-light toolbox and matlab interface can be obtained from
% http://svmlight.joachims.org/ and https://github.com/sods/svml
% ref: T. Joachims, "Transductive inference for text classification using
% support vector machines," 1999
%
% Copyright 2016 Ke YAN, Tsinghua Univ. http://yanke23.com , xjed09@gmail.com

svmlPath = 'svml-master';
addpath(svmlPath)

%% default parameters
% please find the details and other parameters in function svml
t = 2;
c = 1;
g = .001;
TransPosFrac = nan; % Fraction of unlabeled examples to be classified into
					% the positive class. If nan, we will estimate it using
					% Xu
defParam

%% train the classifier and predict
X = [Xl;Xu];
nTest = size(Xu,1);

nCls = max(Yl);
if nCls > 2
	warning('currently using one-vs-all strategy on TSVM, one-vs-one may be better.');
	prob = nan(nTest,nCls);

	for iCls = 1:nCls
		Y1 = Yl==iCls;
		Y1 = (Y1-.5)*2;% {0,1} to {-1,+1}
		if isnan(TransPosFrac)
			TransPosFrac = nnz(Yl==iCls)/length(Yl);
		end

		net = svml('', 'Kernel', t, 'C', c, 'KernelParam',g,'TransPosFrac',TransPosFrac,...
			'ExecPath',svmlPath,'Verbosity',0);
		Y1 = [Y1;zeros(nTest,1)]; % label 0 for the unlabeled samples
		net = svmltrain(net, X, Y1);
		prob(:,iCls) = svmlfwd(net, Xu);
		model{iCls} = net;
	end
	[~,pred] = max(prob,[],2);

else
	Y1 = (Yl-1.5)*2;
	if isnan(TransPosFrac)
		TransPosFrac = nnz(Y1==1)/length(Y1);
	end

	net = svml('', 'Kernel', t, 'C', c, 'KernelParam',g,'TransPosFrac',TransPosFrac,...
		'ExecPath',svmlPath,'Verbosity',0);
	Y1 = [Y1;zeros(nTest,1)];
	net = svmltrain(net, X, Y1);
	prob = svmlfwd(net, Xu);
	pred = sign(prob)/2+1.5;
	model = net;
end

end

%   Accepted options are:
%   Field      SVM light option  Range, description
%   'Verbosity'      -v       {0 .. 3}, default value 1
%                             Verbosity level
%   'Regression'     -z       {0, 1}, default value 0
%                             Switch between regression [1] and
%                             classification [0]
%   'C'              -c       (0, Inf), default value (avg. x*x)^-1
%                             Trade-off between error and margin
%   'TubeWidth'      -w       (0, Inf), default value 0.1
%                             Epsilon width of tube for regression
%   'CostFactor'     -j       (0, Inf), default value 1
%                             Cost-Factor by which training errors on
%                             positive examples outweight errors on
%                             negative examples
%   'Biased'         -b       {0, 1}, default value 1
%                             Use biased hyperplane x*w+b0 [1] instead of
%                             unbiased x*w0 [0]
%   'RemoveIncons'   -i       {0, 1}, default value 0
%                             Remove inconsistent training examples and
%                             retrain
%   'ComputeLOO'     -x       {0, 1}, default value 0
%                             Compute leave-one-out estimates [1]
%   'XialphaRho'     -o       )0, 2), default value 1.0
%                             Value of rho for XiAlpha-estimator and for
%                             pruning leave-one-out computation
%   'XialphaDepth'   -k       {0..100}, default value 0
%                             Search depth for extended XiAlpha-estimator
%   'TransPosFrac'   -p       (0..1), default value ratio of
%                             positive and negative examples in the
%                             training data. Fraction of unlabeled
%                             examples to be classified into the positive
%                             class
%   'Kernel'         -t       {0..4}, default value 1
%                             Type of kernel function:
%                             0: linear
%                             1: polynomial (s a*b+c)^d
%                             2: radial basis function exp(-gamma ||a-b||^2)
%                             3: sigmoid tanh(s a*b + c)
%                             4: user defined kernel from kernel.h
%   'KernelParam'    -d, -g, -s, -r, -u
%                             Depending on the kernel, this vector
%                             contains [d] for polynomial kernel, [gamma]
%                             for RBF, [s, c] for tanh kernel, string for
%                             user-defined kernel
%   'MaximumQP'      -q       {2..}, default value 10
%                             Maximum size of QP-subproblems
%   'NewVariables'   -n       {2..}, default value is the value chosen
%                             for 'MaximumQP'. Number of new variables
%                             entering the working set in each
%                             iteration. Use smaller values to prevent
%                             zig-zagging
%   'CacheSize'      -m       (5..Inf), default value 40.
%                             Size of cache for kernel evaluations in MB
%   'EpsTermin'      -e       (0..Inf), default value 0.001
%                             Allow that error for termination criterion
%                             [y [w*x+b] - 1] < eps
%   'ShrinkIter'     -h       {5..Inf}, default value 100.
%                             Number of iterations a variable needs to be
%                             optimal before considered for shrinking
%   'ShrinkCheck'    -f       {0, 1}, default value 1
%                             Do final optimality check for variables
%                             removed by shrinking. Although this test is
%                             usually positive, there is no guarantee
%                             that the optimum was found if the test is
%                             omitted.
%   'TransLabelFile' -l       String. File to write predicted labels of
%                             unlabeled examples into after transductive
%                             learning.
%   'AlphaFile'      -a       String. Write all alphas to this file after
%                             learning (in the same order as in the
%                             training set).


function  [yout, nfe] = mmid1(y, dy, xs, htot, nstep, odefun, la, kb, kk0)
% mmid.m is the algoritm for a 'modified midpoint' step in the Bulirsch-Stoer method
% for solving ode's, see W Press ea.in "Numerical Recipes" (1994) p723. This version
% is for parallel processing, see odeintp.m and mmid.m
%
% inputs : at xs(1..np) the dependent variable vector y(1..nv,1..np) and its derivative dy(1..nv,1..np)
% are input, also the total step htot(1..np) to be made  and the number of substeps used (nstep),
% a client function for calculating the derivatives (odefun) with some additional
% parameters la, kb(1..np), kk0 that are used only by odefun.
%
% output : the estimated vector for the next step yout(1..nv, 1..np) and number of function evaluations (nfe)

% D Vangheluwe 8 mrt 2005, revised 2 may 2005
% remark 1 : we did not take nv = number of variables as input argument as this can also
%   be obtained from the length of vector y or dy.

nv = size(y,1);
nfe = 0;
h = htot/nstep;
ym = y;
hm = repmat(h, nv, 1);
yn = y + hm .* dy;
x = xs + h;
yout = feval(odefun, x, y, la, kb, kk0);
nfe = nfe + 1;
h2 = 2 * hm;
for i = 2: nstep
   swap = ym + h2 .* yout;
   ym = yn;
   yn = swap;
   x = x + h;
   yout = feval(odefun, x, yn, la, kb, kk0);
   nfe = nfe + 1;
end
yout = 0.5 * (ym + yn + hm .* yout);
return


%Copyright (c) October,15 2008 by Varsha Hedau, UIUC.  All rights reserved.
function [Xpnts2,Vote2,VoteArr2] = RemoveRedundantPoints(Xpnts,Vote,VoteArr,w,h)

%%%%% remove redundant points %%%%%%
currid=1;
done=0;
Xpnts2=Xpnts;
Vote2=Vote;
VoteArr2=VoteArr;

while size(Xpnts,1)>0
    Xpnts2(currid,:) = Xpnts(1,:);
    Vote2(currid) = Vote(1);
    VoteArr2(:,currid) = VoteArr(:,1);
    currid=currid+1;
    dists = (Xpnts(1,1)-Xpnts(:,1)).^2 + ...
        (Xpnts(1,2)-Xpnts(:,2)).^2;
    if sqrt((Xpnts(1,1)-w)^2+(Xpnts(1,2)-h)^2)/sqrt((w/2)^2+(h/2)^2) < 1
        thres=10;
    else
        thres=20*(sqrt((Xpnts(1,1)-w)^2+(Xpnts(1,2)-h)^2)/sqrt((w/2)^2+(h/2)^2));
    end
    inds=find(dists>thres);
    Xpnts = Xpnts(inds,:);
    Vote = Vote(inds,:);
    VoteArr = VoteArr(:,inds);
end
Xpnts2 = Xpnts2(1:currid-1,:);
Vote2 = Vote2(1:currid-1);
VoteArr2 = VoteArr2(:,1:currid-1);

return;


function box = scimat_box(scimat, m, a)
% SCIMAT_BOX  Compute tight box around SCIMAT segmentation.
%
% X = scimat_box(SCIMAT, M, A)
%
%   This function finds the vertices of a box tangent to the edges of a
%   segmentation. The box can be vertical or have any other orientation.
%
%   SCIMAT is a struct with the segmentation (see "help scimat" for
%   details).
%
%   X is a (3, 8)-matrix with the coordinates of the box vertices.
%
%   M is a 3-vector with the coordinates of the rotation centre. By
%   default, M=[0 0 0].
%
%   A is a (3, 3)-rotation matrix, in case the data has to be rotated
%   before computing the box. By default, A is the identity matrix and no
%   rotation is performed. To be consistent with the ITK (Insight Toolkit)
%   convention, the A matrix has to be the "backwards transformation", i.e.
%   A is the rotation from output to input voxel coordinates.
%
%   The "backwards transformation" is the transpose of the forward
%   transformation.

% Author: Ramon Casero <rcasero@gmail.com>
% Copyright © 2010,2014 University of Oxford
% Version: 0.2.1
%
% 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/>.

% check arguments
narginchk(1, 3);
nargoutchk(0, 1);

% default
if (nargin < 2 || isempty(m))
    m = [0 0 0];
end
if (nargin < 3 || isempty(a))
    a = eye(3); % identity matrix
end

% remove the dummy dimension
scimat = scimat_squeeze(scimat);

% get hold of all the points in the segmentation mask

% extract linear indices of voxels in the segmentation
idx = find(scimat.data);

% get volume size
sz = size(scimat.data);

% convert linear index to multiple subscripts
[ir, ic, iz] = ind2sub(sz, idx);

% convert indices to real world coordinates and make column vectors
x = scimat_index2world([ir, ic, iz], scimat)';

% to make the interface consistent, we ask the user to input the backwards
% rotation (whenever we input the scimat volume, backwards rotation;
% whenever we input points, forwards rotation). But actually, we are going
% to operate on points, so we need to get the forwards rotation
a = a';

% avoid unnecessary operations if rotation is identity matrix
if all(all(a ~= eye(3)))

    % move points to centre of rotation
    for I = 1:3
        x(I, :) = x(I, :) - m(I);
    end

    % rotate real world coordinates
    x = a * x;

end

% find the limits of the data
minx = min(x, [], 2);
maxx = max(x, [], 2);

% create the box vertices
box = [...
    minx ...
    [minx(1) maxx(2) minx(3)]' ...
    [maxx(1) maxx(2) minx(3)]' ...
    [maxx(1) minx(2) minx(3)]' ...
    [minx(1) minx(2) maxx(3)]' ...
    [minx(1) maxx(2) maxx(3)]' ...
    maxx ...
    [maxx(1) minx(2) maxx(3)]' ];

if all(all(a ~= eye(3)))

    % undo rotation of vertices
    box = a' * box;

    % move vertices back from centre of rotation
    for I = 1:3
        box(I, :) = box(I, :) + m(I);
    end
end


function [node,elem,bdFlag,HB,tree] = bisect(node,elem,markedElem,bdFlag)
%% BISECT bisect a 2-D triangulation.
%
% [node,elem] = BISECT(node,elem,markedElem) refine the current
% triangulation by bisecting marked elements and minimal neighboring
% elements to get a conforming and shape regular triangulation. Newest
% vertex bisection is implemented. markedElem is a vector containing the
% indices of elements to be bisected. It could be a logical vector of
% length size(elem,1).
%
% [node,elem,bdFlag] = BISECT(node,elem,markedElem,bdFlag) returns the
% updated bdFlag after the bisection. It will be used for PDEs with mixed
% boundary conditions.
%
% [node,elem,bdFlag,HB,tree] = BISECT(node,elem,markedElem,bdFlag)
% returns HB and tree arrays.
%
% - HB(:,1:3) is a hierarchical basis structure for nodes, where
%   HB(:,1) is the global index of new added nodes, and HB(:,2:3) the
%   global indices of two parent nodes of new added nodes. HB is usful
%   for the interpolation between two grids; see also nodeinterpolate.
%
% - tree(:,1:3) stores the binary tree of the refinement. tree(:,1) is the
%   index of the parent element in the coarse mesh and tree(:,2:3) are two
%   children indices in the fine mesh. tree is useful for the interpolation
%   of elementwise function; see eleminterpolate.
%
% Example
%
%      node = [0,0; 1,0; 1,1; 0,1];
%      elem = [2,3,1; 4,1,3];
%      figure(1); subplot(1,3,1); showmesh(node,elem);
%      [node,elem] = bisect(node,elem,'all');
%      figure(1); subplot(1,3,2); showmesh(node,elem);
%      bdFlag = setboundary(node,elem,'Dirichlet','all','Neumann','y==1');
%      [node,elem,bdFlag] = bisect(node,elem,[1 4],bdFlag);
%      figure(1); subplot(1,3,3); showmesh(node,elem);
%
% See also bisect3, coarsen, coarsen3, nodeinterpolate, eleminterpolate.
%
% Reference page in Help browser
% ifem meshdoc
% ifem bisectdoc

% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

%% Set up
HB = []; tree = [];
if ~exist('bdFlag','var'), bdFlag = []; end
if ~exist('markedElem','var'), markedElem = (1:size(elem,1))'; end
if isempty(markedElem), return; end
if strcmp(markedElem,'all'), markedElem = (1:size(elem,1))'; end
if islogical(markedElem), markedElem = find(markedElem); end

%% Construct auxiliary data structure
T = auxstructure(elem);
neighbor = T.neighbor; elem2edge = T.elem2edge; edge = T.edge;
clear T;
%[neighbor,elem2edge,edge] = auxstructurec(int32(elem));
N = size(node,1); NT = size(elem,1); NE = size(edge,1);

%% Add new nodes
isCutEdge = false(NE,1);
while sum(markedElem)>0
    isCutEdge(elem2edge(markedElem,1)) = true;
    refineNeighbor = neighbor(markedElem,1);
    markedElem = refineNeighbor(~isCutEdge(elem2edge(refineNeighbor,1)));
end
edge2newNode = zeros(NE,1,'uint32');
edge2newNode(isCutEdge) = N+1:N+sum(isCutEdge);
HB = zeros(sum(isCutEdge),3,'uint32');
HB(:,1) = edge2newNode(isCutEdge);
HB(:,[2 3]) = edge(isCutEdge,[1 2]);
node(HB(:,1),:) = (node(HB(:,2),:) + node(HB(:,3),:))/2;

%% Refine marked elements
Nb = 0; tree = zeros(3*NT,3,'uint32');
for k = 1:2
    t = find(edge2newNode(elem2edge(:,1))>0);
    newNT = length(t);
    if (newNT == 0), break; end
    L = t;
    R = NT+1:NT+newNT;
    p1 = elem(t,1); p2 = elem(t,2); p3 = elem(t,3);
    p4 = edge2newNode(elem2edge(t,1));
    elem(L,:) = [p4, p1, p2];
    elem(R,:) = [p4, p3, p1];
	if nargin==4 && ~isempty(bdFlag) % Refine boundary edges
   		bdFlag(R,[1 3]) = bdFlag(t,[2 1]);
   		bdFlag(L,[1 2]) = bdFlag(t,[3 1]);
        bdFlag(L,3) = 0;
    else
        bdFlag = [];
	end
    tree(Nb+1:Nb+newNT,1) = L;
    tree(Nb+1:Nb+newNT,2) = L;
    tree(Nb+1:Nb+newNT,3) = R;
    elem2edge(L,1) = elem2edge(t,3);
    elem2edge(R,1) = elem2edge(t,2);
    NT = NT + newNT;
    Nb = Nb + newNT;
end
tree = tree(1:Nb,:);


%%
% This routine etsimates the b-value of a curve automatically
%  The b-valkue curve is differenciated and the point
%  of maximum curvature marked. The b-value will be calculated
%  using this point and the point half way toward the high
%  magnitude end of the b-value curve.
%
%  THIS IS RUN AUTOMATICALLY FROM MIN_OMORI1
%
%%

global cluscat mess bfig backcat xt3 bvalsum3  bval aw bw t1 t2 t3 t4;
global  ttcat n teb t0b cua b1 n1 b2 n2  ew si  S mrt bvalsumhold b;
global selt magco bvml avml bvls avls bv;
global hndl2 inpr1;
think

%report_this_filefun(mfilename('fullpath'));

maxmag = ceil(10*max(newt2.Magnitude))/10;
mima = min(newt2.Magnitude);
if mima > 0 ; mima = 0 ; end

% number of mag units
nmagu = (maxmag*10)+1;

bval = zeros(1,nmagu);
bvalsum = zeros(1,nmagu);
bvalsum3 = zeros(1,nmagu);

%%
%
% bval contains the number of events in each bin
% bvalsum is the cum. sum in each bin
% bval2 is number events in each bin, in reverse order
% bvalsum3 is reverse order cum. sum.
% xt3 is the step in magnitude for the bins == .1
%
%%

[bval,xt2] = hist(newt2.Magnitude,(mima:0.1:maxmag));
bvalsum = cumsum(bval); % N for M <=
bval2 = bval(length(bval):-1:1);
bvalsum3 = cumsum(bval(length(bval):-1:1));    % N for M >= (counted backwards)
xt3 = (maxmag:-0.1:mima);

backg_ab = log10(bvalsum3);

%%
% Estimate the b value -- based on one of 5 methods
%
% calculates max likelihood b value(bvml) && WLS(bvls)
%
%%

Nmin = 10;
bvs=newt2;
b=newt2;

% set DEFAULT to run using best of option
inpr1 = 5;

%% enough events??
if length(bvs) >= Nmin

    %%
    % calculation based on best combination of 90% and 95% probability -- default
    %%

    %            if inpr1 == 5
    mcperc_ca3;
    if isnan(Mc95) == 0
        magco = Mc95;
    elseif isnan(Mc90) == 0
        magco = Mc90;
    else
        [bv magco stan av me mer me2,  pr] =  bvalca3(bvs,1,1);
    end
    l = bvs(:,6) >= magco-0.05;
    if length(bvs(l)) >= Nmin
        %              [bvls magco0 stanls avls me mer me2,  pr] =  bvalca3(bvs(l,:),2,2);
        [mea bvml stanml avml ] =  bmemag(b(l,:));
    else
        bv = nan; bv2 = nan; magco = nan; av = nan; av2 = nan;
    end

end


function [nodes, edges] = createTestGraph03(varargin)
%CREATETESTGRAPH03  One-line description here, please.
%
%   output = createTestGraph03(input)
%
%   Example
%   [nodes edges] = createTestGraph03
%
%   See also
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-05-18,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

nodes = [ ...
     30 10; ...
     10 30; ...
     80 30; ...
     30 50; ...
     60 50; ...
    100 50; ...
     10 70; ...
     80 70; ...
     30 90; ...
     60 90; ...
    100 90; ...
    130 90];

edges = [...
    1 2; ...
    2 4; ...
    3 5; ...
    3 6; ...
    4 5; ...
    4 7; ...
    5 8; ...
    6 8; ...
    7 9; ...
    8 10; ...
    8 11; ...
    9 10; ...
    11 12];


classdef SpectrumAnalyzer
    properties
        fs = 16000;
        nCh = 1;
        nFFT = 512;
        nBin = 257;
        frameSize = 400;
        frameShift = 160;
        frameOverlap = 240;
        frameRate = 100;
        window = 'hamming';
        doDithering = 1;
        doDCRemoval = 0;
        useGPU = 0;
    end

    methods
        function obj = SpectrumAnalyzer(fs, nCh)
            obj.fs = fs;
            if nargin<2
                obj.nCh = 1;
            else
                obj.nCh = nCh;
            end
        end

        function spec = Analyze(obj, data)
            spec = sfft_multi(data, obj.frameSize, obj.frameShift, obj.nFFT, obj.window, obj.doDCRemoval, obj.useGPU, obj.doDithering);
            spec = spec(1:obj.nBin,:,:);
        end

        function wav = Synthesize(obj, complexSpectrum)
            [nBin,D2,D3] = size(complexSpectrum);
            if D2>1 && D3>1     % if both D2 and D3 > 1, assume D2 is the number of channels, while D3 is the number of frames (same format as sfft_multi).
                complexSpectrum = permute(complexSpectrum, [1 3 2]);
            end
            for i=1:size(complexSpectrum,3)
                data = squeeze(complexSpectrum(:,:,i));
                data(obj.nFFT/2+2:obj.nFFT,:) = conj(data(obj.nFFT/2:-1:2,:));
                xi = real(ifft(data));
                wav(:,i) = obj.ola(xi);
            end
        end

        function output = DisplaySpectrogramFromWav(obj,wav, newFigure, doCMN, channelSelector)
            if nargin<3; newFigure = 1; end
            if newFigure; figure; end
            if nargin<4; doCMN = 0; end
            if nargin>=5
                data = obj.Analyze(wav(:,channelSelector));
            else
                data = obj.Analyze(wav);
            end
            data = data(1:obj.nBin,:,:);

            [nBin, nCh, nFr] = size(data);
            if doCMN==0
                displayMatrix = log(abs(reshape(data, nBin*nCh, nFr)));
            elseif doCMN == 1
                displayMatrix = CMN(log(abs(reshape(data, nBin*nCh, nFr)))')';
            end
            imagesc(displayMatrix);
            if nargout>0
                output = displayMatrix;
            end
        end

        function output = DisplaySpectrogram(obj,data, newFigure, doCMN)
            if nargin<3; newFigure = 1; end
            if newFigure; figure; end
            if nargin<4; doCMN = 0; end
            [nBin, nCh, nFr] = size(data);
            if doCMN==0
                displayMatrix = log(abs(reshape(data, nBin*nCh, nFr)));
            elseif doCMN == 1
                displayMatrix = CMN(log(abs(reshape(data, nBin*nCh, nFr)))')';
            end
            imagesc(displayMatrix);
            if nargout>0
                output = displayMatrix;
            end
        end
    end

    methods (Access = protected)
        function xfinal = ola(obj, xi)
            nFr = size(xi,2);
            k=1;
            xfinal=zeros(nFr*obj.frameShift,1);
            x_old = zeros(obj.frameOverlap,1);
            for j=1:nFr
                xfinal(k:k+obj.frameOverlap-1) = x_old + xi(1:obj.frameOverlap,j);
                x_old = xi(1+obj.frameShift:obj.frameSize,j);
                k = k + obj.frameShift;
            end
        end
    end
end


function prior = truncatedGammaPriorParamInit(prior)

% TRUNCATEDGAMMAPRIORPARAMINIT Truncated gamma prior model's parameter initialisation.
% FORMAT
% DESC initialises the parameters of the truncated gamma prior with some
% default parameters.
% ARG prior : prior structure to be initialised.
% RETURN prior : prior structure with initial values in place.
%
% SEEALSO : priorCreate
%
% COPYRIGHT : Neil D. Lawrence, 2004, 2005, 2006
%
% COPYRIGHT : Antti Honkela, 2013

% PRIOR

prior.a = 1e-6;
prior.b = 1e-6;
prior.lbound = 0;
prior.ubound = 1;

prior.transforms.index = [1 2];
prior.transforms.type = optimiDefaultConstraint('positive');
prior.nParams = 2;
prior.isBounded = 1;


function rmPlotMap (v,  saveFlag, method, fieldname, prf_size, fieldRange)
% rmPlotMap (v, fieldname, saveFlag, prf_size, fieldRange)
%
%   Purpose:
%       Visualize the responses within an ROI in stimulus-referred space.
%       The stimulus referred space is created via a retinotopic model,
%       which gives an x, y, and sigma value to each voxel. The responses
%       come from the current scan - it does not need to be the scan used
%       to make the pRF model. The model of each voxel's RF is then scaled
%       to the current scan's  map. The models from all the maps are then
%       added together and plotted as figure in stimulus space.
%
%   Note: works only in Gray view
%
%
%
%   INPUT
%       v:           mrVista view structure
%       fieldname:   'ph', 'co', 'amp', or 'map': the parameter used to
%                           scale the RF plot
%       saveFlag:    boolean (if true, then save the plot as a jpg)
%       prf_size:    boolean (if true, use prf sigma to generate RFs,
%                           if false assume fixed size for all pRFs)
%       fieldRange:  deg (size of visual field to plot)
%
%
%
%   6/19/2008: JW wrote it, adpating from KA's rmPlotCoverage
%   7/3/2008:  Divided the image at each point by the total pRF coverage of
%              that point in space. This puts the image in  % signal units.
%

% Check the arguments and set defaults
if ieNotDefined('v'), v = getCurView; end
if ieNotDefined('fieldname'), fieldname = v.ui.displayMode; end
if ieNotDefined('saveFlag'), saveFlag = true;  end
if ieNotDefined('prf_size'), prf_size = 'from model';  end
if ieNotDefined('fieldRange'), fieldRange = 15;  end % deg
if ieNotDefined('nSamples'), nSamples = 75;  end
if ieNotDefined('normResponses'), normResponses = true;  end
if ieNotDefined('method'), method = 0; end %0 = sum

if isequal(saveFlag, 'dialog')
	% get parameters from a dialog
	[prf_size method normResponses fieldRange nSamples saveFlag ok] = rmPlotMapParams;
    if ~ok, return; end
end

% Get pRF model
try
    rmModel   = viewGet(v,'rmSelectedModel');
    rmfname   = viewGet(v,'rmfile');
    [foo,rmfname,foo,foo] = fileparts(rmfname);
catch
    error('Need to load retModel into curent view');
end

% Get ROI
try
    ROIcoords = getCurROIcoords(v);
    ROIname = v.ROIs(v.selectedROI).name;
catch
    error('Need to select ROI in GUI')
end

% Get scan
curScan = getCurScan(v);

% If cothresh is set in GUI, use it to restrict ROI
try
    co  = getCurDataROI(v,'co',curScan,ROIcoords);
    cothresh = viewGet(v, 'cothresh');
    ROIcoords = ROIcoords(:, co > cothresh);
end

nVoxels = size(ROIcoords,2);

% Get the map
curData  = getCurDataROI(v,fieldname,curScan,ROIcoords);

% Get X, Y, and sigma for each voxel
[tmp1 tmp2 indices] = intersectCols(ROIcoords, v.coords);
clear tmp1 tmp2;
subSize = rmModel.sigma.major(indices);
subX = rmModel.x0(indices);
subY = rmModel.y0(indices);
% if prf_size is false, then make all pRFs the same size, instead of using
%   the fitted sigmas.
if strcmp(prf_size, 'equal for every voxel')
   subSize=ones(size(subSize))*0.5;
end

% Set up stimulus-referred visual field
x = linspace(-fieldRange,fieldRange,nSamples);
[X,Y] = meshgrid(x,x);
mask = makecircle(size(X,1));

% Build pRF for each voxel:
%all_models = rfGaussian2d(single(X(:)),single(Y(:)),...
%    single(subSize),single(subSize),single(0), single(subX),single(subY));

% Plot the total coverage of the RF.
RFcov = zeros(nSamples^2,1);
for ii = 1:nVoxels
    thisModel = rfGaussian2d(single(X(:)),single(Y(:)),...
    single(subSize(ii)),single(subSize(ii)),single(0), single(subX(ii)),single(subY(ii)));
    if method == 0,
        RFcov = RFcov + thisModel;
    else
        RFcov = max(RFcov, thisModel);
    end
end

RFcov = reshape(RFcov,[1 1].*sqrt(numel(RFcov)));

h = figure;
subplot(2,1,1)
imagesc (X(1,:),Y(:,1),RFcov .* mask);
colorbar
axis equal tight;
title([ROIname, ', Visual field coverage (sum)']);

% Plot the current map in stimulus-referred space
%   (This is the main point of the function)
RF = zeros(nSamples^2,1);
for ii = 1:nVoxels
    thisModel = rfGaussian2d(single(X(:)),single(Y(:)),...
        single(subSize(ii)),single(subSize(ii)),single(0), single(subX(ii)),single(subY(ii)));
    RF = RF + thisModel * curData(ii);
end
% convert RF model from 1D to 2D
RF = reshape(RF,[1 1].*sqrt(numel(RF)));

% divide the movie by the coverage map to normalize (approximatley) to % signal
if normResponses == true, RF = RF ./ RFcov; end

%set color range
imMax = max(max(RF(:)), -min(RF(:)));
imMin = -imMax;

% plotting
figure(h);
headerStr = [ROIname,', ', fieldname, ', scan', num2str(curScan) ];
subplot(2,1,2)
imagesc(X(1,:),Y(:,1),RF .* mask, [imMin imMax])
colorbar
axis equal tight;
title(headerStr);
xlabel(rmfname);

% saving
if saveFlag,
    fname = [headerStr,  '.jpg'];
    saveas(gcf, fname)
end

return

% /------------------------------------------------------------------/ %

% /------------------------------------------------------------------/ %
function [prf_size method normResponses fieldRange nSamples saveFlag ok] = rmPlotMapParams;
%% dialog to get parameters for rmPlotParam.
dlg(1).fieldName = 'prf_size';
dlg(end).style = 'listbox';
dlg(end).list = {'from model', 'equal for every voxel'};
dlg(end).string = 'pRF sigma';
dlg(end).value = 1;

dlg(end+1).fieldName = 'fieldRange';
dlg(end).style = 'number';
dlg(end).string = 'Visual Field Range (deg)?';
dlg(end).value = '20';

dlg(end+1).fieldName = 'nSamples';
dlg(end).style = 'number';
dlg(end).string = 'Num Samples?';
dlg(end).value = '75';

dlg(end+1).fieldName = 'normResponses';
dlg(end).style = 'number';
dlg(end).string = 'Normalize responses to visual field coverage?';
dlg(end).value = '1';

dlg(end+1).fieldName = 'method';
dlg(end).style = 'number';
dlg(end).string = 'Use sum (0) or max (1) for pRF coverage map?';
dlg(end).value = 0;

dlg(end+1).fieldName = 'saveFlag';
dlg(end).style = 'checkbox';
dlg(end).string = 'Save Image?';
dlg(end).value = 0;

[resp ok] = generalDialog(dlg, mfilename);
if ~ok
	disp('User Aborted.')
    prf_size = 0;
    method = 0;
    normResponses = 0;
    fieldRange = 0;
    nSamples = 0;
    saveFlag = 0;
    return;
end

prf_size = resp.prf_size;
method = resp.method;
normResponses = resp.normResponses;
fieldRange = resp.fieldRange;
nSamples = resp.nSamples;
saveFlag = resp.saveFlag;

return


%% Start the RL GUI
clear all;
addpath(genpath('./'))

%% Create grid world

gw_options = [];
gw_options.dims = [15,15];
grid_world = Grid_world(gw_options);

%% Create reward

r_options               = [];
r_options.x_goal        = [10,10];
r_options.x_bad         = rl_reward_firepit( 'central_pit' );

r_options.type           = 'discrete';
r_options.r_goal         =   10; % reward for reaching the goal.
r_options.r_pit          =   -10; % reward for falling into a pit.
r_options.r_step         =     -1; % reward for each time step.

r_options.grid_world    = grid_world;

reward                  = Reward_gridworld(r_options);

% Discrete reward function

reward_f                = @(s,x)reward_grid_world_goal(s,x,reward.s_goal,reward.s_bad,reward.r_goal,reward.r_pit,reward.r_step);

% Continuous reward function

%beta                    = 0.1;                          %  (s,x,beta,       s_goal,          x_goal  ,        x_bad,           r_bad,        r_goal)
%reward_fc               = @(s,x)reward_grid_world_continuous(s,x,beta, reward.s_goal,  reward.x_goal  ,  reward.s_bad,  reward.r_pit,  reward.r_goal);

%% Select agents starting position.

agent_pos               = [2,2];

%% Open GUI
global speed;
speed = 0.5;
hOut    = rl_demo_gui(grid_world,reward,agent_pos,reward_f);
handles = hOut{2};