function MW_src = perform_histogram_matching_wavelet(MW_src,MW_tgt, Jmin, options)

% perform_histogram_matching_wavelet - match the histogram of a wavelet transform
%
% Matching of wavelet coefficients only:
%   options.dotransform=0
%   MW_src = perform_histogram_matching_wavelet(MW_src,MW_tgt,Jmin,options);
% Matching of image + wavelet coefficients:
%   options.dotransform=1
%   M_src = perform_histogram_matching_wavelet(M_src,M_tgt,Jmin,options);
%
%   Match the spacial histogram of the image and the histogram of each
%   wavelet sub-band.
%
%   Works also for color images.
%
%   You can set options.use_histomatching=0 if you want to equalize the
%   kurtosis and skewness of subbands and not their histograms
%   (works well for natural images).
%
%   Copyright (c) 2004 Gabriel Peyr?

if nargin>=4
    if ~isstruct(options)
        error('options should be a structure.');
    end
end

options.null = 0;
dotransform = getoptions(options, 'dotransform', 1);
niter_synthesis = getoptions(options, 'niter_synthesis', 1);

if nargin<3
    Jmin = 3;
end

if niter_synthesis>1
    options.niter_synthesis = 1;
    for i=1:niter_synthesis
        MW_src = perform_histogram_matching_wavelet(MW_src,MW_tgt, Jmin, options);
    end
    return;
end

if size(MW_src,3)==3
    options.color_mode = 'pca';
    [MW_src,options.ColorP] = change_color_mode(MW_src,+1,options);
    [MW_tgt,options.ColorP] = change_color_mode(MW_tgt,+1,options);
    for i=1:size(MW_src,3)
        MW_src(:,:,i) = perform_histogram_matching_wavelet(MW_src(:,:,i),MW_tgt(:,:,i),Jmin, options);
    end
    [MW_src,options.ColorP] = change_color_mode(MW_src,-1,options);
    return;
end

if size(MW_src,3)>1
	for i=1:size(MW_src,3)
        MW_src(:,:,i) = perform_histogram_matching_wavelet(MW_src(:,:,i),MW_tgt(:,:,i),Jmin, options);
    end
    return;
end

% for spacial histogram, do not consider absval
options.absval = 0;
options.rows = 0;
options.cols = 0;

if dotransform == 1
    % perform image extension
    n1 = size(MW_src,1);
    n2 = size(MW_tgt,1);
    n = max(n1,n2);
    n = 2^( ceil(log2(n)) );
    MW_src = perform_image_extension(MW_src,n);
    MW_tgt = perform_image_extension(MW_tgt,n);
    options.wavelet_type = 'biorthogonal_swapped';
    options.wavelet_vm = 4;
    % perform spacial matching
    MW_src = perform_matching(MW_src, MW_tgt, options);
    % compute transform
    MW_src = perform_wavelet_transform(MW_src, Jmin, +1, options);
    MW_tgt = perform_wavelet_transform(MW_tgt, Jmin, +1, options);
    % perform coefficients matching
    options.dotransform = 0;
    MW_src = perform_histogram_matching_wavelet(MW_src,MW_tgt,Jmin, options);
    % undo transforms
    MW_src = perform_wavelet_transform(MW_src, Jmin, -1, options);
    MW_tgt = perform_wavelet_transform(MW_tgt, Jmin, -1, options);
    % perform spacial matching
    MW_src = perform_matching(MW_src, MW_tgt, options);
    MW_src = MW_src(1:n1,1:n1);
    return;
end

if size(MW_src,1)~=size(MW_tgt,1)
    error('Wavelets coefficients should be of the same size.');
end

mm = size(MW_src);
Jmax = log2(mm)-1;

for j=Jmax:-1:Jmin
    for q=1:3
        [selx,sely] = compute_quadrant_selection(j,q);
        MW_src(selx,sely) = match_statistics(MW_src(selx,sely), MW_tgt(selx,sely), options);
    end
end

% match low scales
selx = 1:2^Jmin; sely = 1:2^Jmin;
MW_src(selx,sely) = perform_matching(MW_src(selx,sely), MW_tgt(selx,sely), options);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function x = perform_matching(x,y, options)

% x = perform_histogram_matching(x,y, options);
x = perform_histogram_equalization(x,y, options);

function M = perform_image_extension(M,n)

m = size(M,1);
k = n-m;
while k>size(M,1)
    M = perform_image_extension(M,size(M,1)*2);
    k = k - size(M,1)/2;
end
M = [M; M(end:-1:end-k+1,:)];
M = [M, M(:,end:-1:end-k+1)];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function x = match_statistics(x,y, options)

options.null = 0;
if isfield(options, 'use_histomatching')
    use_histomatching = options.use_histomatching;
else
    use_histomatching = 1;
end

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

if use_histomatching
    options.absval = 1;
    x = perform_matching(x, y, options);
else
    x = perform_kurtosis_equalization(x,y);
end


function [skinDetection,faceIm,skinImB_3] = selectFaceTemplateManualHueSaturationSelection(skinDetection, Im)

hueSatMapResolution     = 500;

xyCoor = round([min(skinDetection.bboxPolygon(1:2:end)) min(skinDetection.bboxPolygon(2:2:end)) max(skinDetection.bboxPolygon(1:2:end)) max(skinDetection.bboxPolygon(2:2:end))]);
xyCoor(xyCoor<1) = 1;

if length(size(Im)) == 3
    faceIm = Im(xyCoor(2):xyCoor(4),xyCoor(1):xyCoor(3),:);
else
    faceIm = Im(xyCoor(2):xyCoor(4),xyCoor(1):xyCoor(3));
end

% reset face sectors
faceGridVal = zeros(skinDetection.nFaceSectors,skinDetection.nFaceSectors);
faceGridVal(:) = 1:skinDetection.nFaceSectors^2;

% Divide face region in face sectors and rotate depending on the angle of the face
boxSize         = round(sqrt((skinDetection.bboxPolygon(4)-skinDetection.bboxPolygon(2))^2+(skinDetection.bboxPolygon(3)-skinDetection.bboxPolygon(1))^2))-1;
faceGridVal     = imrotate(imresize(faceGridVal,[boxSize boxSize],'Method','Nearest'),atand((skinDetection.bboxPolygon(4)-skinDetection.bboxPolygon(2))/(skinDetection.bboxPolygon(1)-skinDetection.bboxPolygon(3))));
if size(faceIm,1) > size(faceGridVal,1) | size(faceIm,2) > size(faceGridVal,2)
    if length(size(Im)) == 3
        faceIm      = faceIm(1:size(faceGridVal,1),1:size(faceGridVal,2),:);
    else
        faceIm      = faceIm(1:size(faceGridVal,1),1:size(faceGridVal,2));
    end
    faceGridVal = faceGridVal(1:size(faceIm,1),1:size(faceIm,2));
else
    faceGridVal = faceGridVal(1:size(faceIm,1),1:size(faceIm,2));
end
faceIm = double(faceIm);

if skinDetection.firstTimeDetected==1 & skinDetection.nTimesDetected ==1 ;  % only first time when face is detected

    % Select HSV skin color
    hsvChannels = rgb2hsv(faceIm);
    huemap = hsvChannels(:,:,1);
    satmap = hsvChannels(:,:,2);
    intmap = hsvChannels(:,:,3);

    figure();
    subplot(2,2,1)
    imshow(uint8(faceIm));

    subplot(2,2,2)
    imagesc(huemap);
    colormap('jet')
    colorbar
    axis off

    subplot(2,2,3);
    hist(huemap(:),linspace(0,1,256));
    title('Hue Histogram')

    subplot(2,2,4);
    hist(satmap(:),linspace(0,1,256));
    title('Saturation Histogram')

    R = satmap(:);
    TH = huemap(:)*2*pi;

    % make polar plot of colors in image
    [X,Y] = pol2cart(TH,R);

    imSize = hueSatMapResolution;
    tempHueIm = zeros(imSize,imSize);
    tempSatIm = zeros(imSize,imSize);
    tempIntIm = zeros(imSize,imSize);

    Xn = round(X*(imSize/2-1)+imSize/2+1);
    Yn = round(Y*(imSize/2-1)+imSize/2+1);
    zeroCoor = imSize/2;

    % fill maps
    tempHueIm((Xn-1).*imSize+Yn) = huemap(:);
    tempSatIm((Xn-1).*imSize+Yn) = satmap(:);
    tempIntIm((Xn-1).*imSize+Yn) = intmap(:);

    colorspaceIm = reshape([tempHueIm tempSatIm tempIntIm],size(tempIntIm,1),size(tempIntIm,1),3);
    colorspaceIm = hsv2rgb(colorspaceIm);

    dontstop = 1;
    while dontstop

        figure(999);
        imshow(uint8(colorspaceIm));
        hold on
        plot(zeroCoor,zeroCoor,'go');
        title({'Select the wedge range of skin colors by clicking '; 'the left mouse button at top left and bottom right corner'});
        drawnow;

        pause(1);

        xi = [];
        yi = [];
        for i = 1:2
            [xi(i), yi(i)] = ginput(1);

            % draw selection point
            plot(xi(i),yi(i),'gx');

            % draw red line showing the edges of the wedges
            plot(linspace(zeroCoor,imSize,2),polyval(polyfit([zeroCoor xi(i)],[zeroCoor yi(i)],1),linspace(zeroCoor,imSize,2)),'r')

            drawnow;
        end
        [TH,R] = cart2pol(xi-zeroCoor,yi-zeroCoor);

        for i = 1:2

            % draw green line
            plot(linspace(xi(1),xi(2),2),polyval(polyfit([zeroCoor xi(i)],[zeroCoor yi(i)],1),linspace(xi(1),xi(2),2)),'g')
            [xic,yic] = pol2cart(linspace(TH(1),TH(2),10),zeros(1,10)+R(i));

            plot(xic+zeroCoor,yic+zeroCoor,'g')
        end
        drawnow;
        hold off

        [~,R] = cart2pol((xi-zeroCoor-1)/(imSize/2-1),(yi-zeroCoor-1)/(imSize/2-1));

        % recompute range of skin color hue and saturation values
        TH(TH<=0) = TH(TH<=0)+2*pi;
        TH = TH./(2*pi);

        disp(['Range of selected hue values: ' num2str(TH)]);
        disp(['Range of selected saturation values: ' num2str(R)]);

        if R(1) >= R(2)
            error('Radius of second point should be larger than first point!');
        end

%         skinDetection.skinImB = huemap>TH(1) & satmap>R(1) & satmap<R(2) | huemap<TH(2) & satmap>R(1) & satmap<R(2);

        if TH(1) > TH(2)
            skinDetection.skinImB = huemap>TH(1) & huemap<=1 & satmap>R(1) & satmap<R(2) | huemap<TH(2) & huemap>=0 & satmap>R(1) & satmap<R(2);
        elseif TH(1) < TH(2)
            skinDetection.skinImB = huemap>TH(1) & huemap<TH(2) & satmap>R(1) & satmap<R(2);
        else
            skinDetection.skinImB = satmap>R(1) & satmap<R(2);
        end

        selectIm = faceIm;
        selectIm(reshape(repmat(~skinDetection.skinImB,1,3),size(faceIm,1),size(faceIm,2),3)) = NaN;

        h = figure(998);
        imshow(uint8(selectIm))
        hold on
        text(10,10,['Selected hue range: ' num2str(TH)],'Color','g')
        text(10,40,['Selected saturation range: ' num2str(R)],'Color','g')
        title('Press "A" for accept, press "R" to reject and reselect skin colors');
        drawnow;
        hold off

        keyspressed = [];

        k=0;
        while ~k
            k = waitforbuttonpress;
            currkey = get(gcf,'currentcharacter');
            if strcmp(currkey,'a') | strcmp(currkey,'r')
                k = 1;
            else
                k = 0;
            end
        end

        if strcmp(currkey,'a')
            dontstop = 0;
        else
            close(h);
        end
    end

    skinDetection.TH = TH;
    skinDetection.R = R;

end

if mod(skinDetection.f,skinDetection.calcFrameRate) & skinDetection.calcFrameRate > 1 | skinDetection.calcFrameRate==1

    % Select HSV skin color
    hsvChannels = rgb2hsv(faceIm);
    huemap = hsvChannels(:,:,1);
    satmap = hsvChannels(:,:,2);
    intmap = hsvChannels(:,:,3);

    if skinDetection.TH(1) > skinDetection.TH(2)
        skinDetection.skinImB = huemap>skinDetection.TH(1) & huemap<=1 & satmap>skinDetection.R(1) & satmap<skinDetection.R(2) | huemap<skinDetection.TH(2) & huemap>=0 & satmap>skinDetection.R(1) & satmap<skinDetection.R(2);
    elseif skinDetection.TH(1) < skinDetection.TH(2)
        skinDetection.skinImB = huemap>skinDetection.TH(1) & huemap<skinDetection.TH(2) & satmap>skinDetection.R(1) & satmap<skinDetection.R(2);
    else
        skinDetection.skinImB = satmap>skinDetection.R(1) & satmap<skinDetection.R(2);
    end
end

if size(skinDetection.skinImB,1)~=size(faceGridVal,1) | size(skinDetection.skinImB,2)~=size(faceGridVal,2)
    skinDetection.skinImB = imresize(skinDetection.skinImB,[size(faceGridVal,1) size(faceGridVal,2)]);
end

for gridIdx = 1:skinDetection.nFaceSectors^2 % check which grid sectors have enough skin detected
    if sum(faceGridVal(:)==gridIdx & skinDetection.skinImB(:))/sum(faceGridVal(:)==gridIdx) > skinDetection.fracPixelsPresent;
        skinDetection.skinImB(faceGridVal(:)==gridIdx) = 1;
    else
        skinDetection.skinImB(faceGridVal(:)==gridIdx) = 0;
    end
end

skinImB_3   = repmat(skinDetection.skinImB,1,1,3);


function[varargout]=makefigs_gulftransfer(str)
%MAKEFIGS_TRANSFER Makes all figures for Lilly and Elipot (2021).
%
%   This function makes all figures for
%
%        Lilly, J. M. and S. Elipot (2021). A unifying perspective on
%            transfer function solutions to the unsteady Ekman problem.
%            Fluids, 6 (2): 85, 1--36.
%
%   This may take a while as some of the plots are computationally
%   intensive.
%   __________________________________________________________________
%   This is part of JLAB --- type 'help jlab' for more information
%   (C) 2021 J.M. Lilly --- type 'help jlab_license' for details

if nargin==0
  str='noprint';
end

if strcmp(str,'--f')
     makefigs_gulfdrifters('noprint');return
end

%This is where you want things to be printed to
dirname='/Users/lilly/Desktop/Dropbox/Projects/transfer/theory/figures';

%/*************************************************************************
%basic figure of transfer function
rho=1027;
fc=1e-4;
omega=[-8.5:.01:8.5]*fc;
z=[0:.1:50]';
zo=20;
delta=20;zo=20;h=50;mu=delta.^2./zo;
G1=rho.*fc.*windtrans(omega*24*3600,z,fc*24*3600,delta,mu,inf);
G2=rho.*fc.*windtrans(omega*24*3600,z,fc*24*3600,delta,mu,50);
G1(~isfinite(G1))=1e6;
[ommat,zmat]=meshgrid(omega,z);
zeta=2*sqrt(2)*frac(zo,delta).*sqrt((1+zmat./zo).*abs(1+ommat./fc));

%str='Transfer Function Magnitude (m^2s/kg)';
str='Log10 Transfer Function Magnitude (m^{-1})';

figure,
clf
subplot(1,2,1),contourf(omega./fc,z,log10(abs(G1))',-10:.1:6),nocontours,flipy,hold on
text(-8,48,'(a)','color','w')
subplot(1,2,2),contourf(omega./fc,z,log10(abs(G2))',-10:.1:6),nocontours,flipy,hold on
text(-8,48,'(b)','color','w')

for i=1:2
    subplot(1,2,i)
    caxis([-4 -1]),hlines(20,'0.5k:'),%vlines(-1,'w'),
    %hlines([10 40],'2w')
    if i==1
        hlines([10 40],'0.5D')
    else
        hlines([40],'0.5D')
    end
    xtick([-10:2:10])
    ylabel('Depth (m)')
    xlabel('Nondimensional Frequency $\omega/|f|$','interpreter','latex')
    %contour(omega./fc,z,zeta,[4 7],'w','linewidth',2)
    contour(omega./fc,z,zeta,[4 7.5],'w')
end
subplot(1,2,1)
text(-1,5,'I','color',[1 1 1],'HorizontalAlignment','center')
text(-1,25,'IV','color',[1 1 1],'HorizontalAlignment','center')
text(-1,45,'VII','color',[1 1 1],'HorizontalAlignment','center')
text(2,5,'II','color',[1 1 1]*0,'HorizontalAlignment','center')
text(-4,5,'II','color',[1 1 1]*0,'HorizontalAlignment','center')
text(1,25,'V','color',[1 1 1]*0,'HorizontalAlignment','center')
text(-3,25,'V','color',[1 1 1]*0,'HorizontalAlignment','center')
text(0.4,45,'VIII','color',[1 1 1]*0,'HorizontalAlignment','center')
text(-2.4,45,'VIII','color',[1 1 1]*0,'HorizontalAlignment','center')
text(5.5,5,'III','color',[1 1 1]*0,'HorizontalAlignment','center')
text(-7.5,5,'III','color',[1 1 1]*0,'HorizontalAlignment','center')
text(5.5,25,'VI','color',[1 1 1]*0,'HorizontalAlignment','center')
text(-7.5,25,'VI','color',[1 1 1]*0,'HorizontalAlignment','center')
text(5.5,45,'IX','color',[1 1 1],'HorizontalAlignment','center')
text(-7.5,45,'IX','color',[1 1 1],'HorizontalAlignment','center')

subplot(1,2,2)
%text(-1,5,'I-$h$','color',[1 1 1],'HorizontalAlignment','center')
text(-1,25,'IV-$h$','color',[1 1 1],'HorizontalAlignment','center')
text(-1,45,'VII-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
%text(2,5,'II-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
%text(-4,5,'II-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
text(1,25,'V-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
text(-3,25,'V-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
text(0.4,45,'VIII-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
text(-2.4,45,'VIII-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
%text(5.5,5,'III-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
%text(-7.5,5,'III-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
text(5.5,25,'VI-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
text(-7.5,25,'VI-$h$','color',[1 1 1]*0,'HorizontalAlignment','center')
text(5.5,45,'IX-$h$','color',[1 1 1],'HorizontalAlignment','center')
text(-7.5,45,'IX-$h$','color',[1 1 1],'HorizontalAlignment','center')

ha=packfig(1,2,'col');
axes(ha(1)),%ylim([0 62]),ytick([0:10:50])
hc=colorbar('SouthOutside');
hc.Label.String=str;
pos1=get(ha(1),'position');
pos2=get(ha(2),'position');
pos=get(hc,'position');%pos(4)=pos(4)/2;
%set(hc,'position',[pos(1)+0.195 pos(2) pos(3) pos(4)])
set(hc,'position',[pos(1)+0.195 pos(2)+.02 pos(3) pos(4)/2])
set(ha(2),'position',[pos2(1) pos1(2) pos2(3) pos1(4)])
set(ha(1),'position',pos1)
fontsize 10 10 9 8
set(gcf,'paperposition',[1 1 10 6])
if strcmp(str,'print')
    jprint(dirname,'transferfunctionschematic')
end
% %--------------------------------------------------------------------------
% %Green's function
% rho=1027;
% fc=1e-4;
% %omega=[-100:.01:100]*fc;
% omega=[-1000:.01:1000]*fc;
% z=[0:.1:49.9]';
% zo=20;
% delta=20;zo=20;h=50;mu=delta.^2./zo;
% %G1=rho.*fc.*windtrans(omega*24*3600,z,fc*24*3600,delta,mu,inf);
% G2=rho.*fc.*windtrans(omega*24*3600,z,fc*24*3600,delta,mu,50);
% g1=ifft(ifftshift(G1,1));
% g2=ifft(ifftshift(G2,1));
%
% figure,
% jpcolor(1:1e4,z,log10(abs(g2(1:1e4,:)))'),caxis([-7 -3.5]),flipy,hold on
% contour(1:1e4,z,real(g2(1:1e4,:))',[0 0],'k')
%\*************************************************************************

%/*************************************************************************
%basic figure of transfer function, flower version
rho=1027;
fc=1e-4;
omega=[-8.5:.01:8.5]*fc;
z=[0:5:45]';
zo=20;
delta=20;zo=20;h=50;mu=delta.^2./zo;
lnomega=logspace(2,100,10000);
omega=[-fliplr(lnomega) -100:.1:-8.6 -8.5:.001:-1-0.005 -1-0.005:1e-7:-1+0.005  -1+0.005:0.001 :8.5 8.6:.1:100 lnomega]*fc;

G1=rho.*abs(fc).*windtrans(omega*24*3600,z,fc*24*3600,delta,mu,inf);
G2=rho.*abs(fc).*windtrans(omega*24*3600,z,fc*24*3600,delta,mu,50);
figure
clf,
subplot(1,2,1)
hl=plot(G1);hold on,linestyle(hl,'0.5D'),
hl=plot(G1(:,1)); linestyle(hl,'2k')
hl=plot(G1(:,end));linestyle(hl,'2k--')
subplot(1,2,2)
hl=plot(G2);hold on,linestyle(hl,'0.5D'),
hl=plot(G2(:,1)); linestyle(hl,'2k')
hl=plot(G2(:,end));linestyle(hl,'2k--')
for i=1:2
    subplot(1,2,i)
    axis square, axis equal
    if i==1
        axis([-.1 1.5 -.8 .8]),
        xtick([-0.8:.2:1.6])
        text(1.35,0.7,['(' setstr(96+i) ')'])
    elseif i==2
        axis([-.01 .13 -.07 .07])
        text(0.117,0.06,['(' setstr(96+i) ')'])
    end

    vlines(0,'0.5k:'),hlines(0,'0.5k:')
    xlabel('Real Part of $\widetilde G(\omega,z)$ (m$^{-1}$)','interpreter','latex')%(Dimensionless)')
    ylabel('Imaginary Part of $\widetilde G(\omega,z)$ (m$^{-1}$)','interpreter','latex')% (Dimensionless)')
    %xtick([-.4:.2:1.2]),ytick([-.6:.2:.6])
end
set(gcf,'paperposition',[1 1 10 5])
if strcmp(str,'print')
    jprint(dirname,'schematicflowers')
end
%\*************************************************************************

%/*************************************************************************
%green's functions for schematic
rho=1027;
fc=1e-4;
%omega=[-100:.0001:100]*fc;
omega=[-10000:.01:10000]*fc;
z=[0:1/2:49.5]';
zo=20;
delta=20;zo=20;h=50;mu=delta.^2./zo;

[G1,G2]=vzeros(length(omega),length(z));

%z=[0:5:45]';
parfor i=1:length(z)
    i
%   G1(:,i)=rho.*abs(fc).*windtrans(omega*24*3600,z(i),fc*24*3600,delta,mu,inf);
    G2(:,i)=rho.*abs(fc).*windtrans(omega*24*3600,z(i),fc*24*3600,delta,mu,50);
end
G2(:,end+1)=1e-16+0*G2(:,end);
z=[z;50];
%g1=ifft(ifftshift(G1,1));
g2=ifft(ifftshift(G2,1));
g2=g2./maxmax(abs(g2));

%fc=2 pi rad/ 10^4 seconds
%fN= 2 pi rad
%dt= 1/2 seconds
%Tf = 2 pi / fc = 10^4 seconds
t=[1:size(g2,1)]'*frac(1,2)./10^4;

figure
ii=1:40000;
subplot(3,1,1)
contourf(t(ii),z,log10(abs(g2(ii,:)))',[-10:.1:0]);nocontours,hold on,flipy
contour(t(ii),z,log10(abs(g2(ii,:)))',[-12:1:0],'w');
hlines(z(1:10:end),'0.2D')
hlines(z(1),'2k')
hlines(z(end-10),'2k--')
%contour(t(ii),z,real(g2(ii,:))',[0 0],'k:');
caxis([-5.5 -1.5]),ylim([-.01 49.999]),xlim([0 2]),xtick([0:.25:2])
vlines(0.25005+[0:1/2:2],'0.25k:')
ylabel('Depth (m)')
text(1.875,2.5,'(a)','color','k')
subplot(3,1,2)
h=plot(t(ii),real(g2(ii,1:10:end))*1000);ylim(1000*[-.009 .009]+1000*0.005)
linestyle(h,'0.5D'),linestyle(h(1),'2k'),linestyle(h(end-1),'2k--')
ylabel('Real Part of $g(t,z)$ ($\times 1000 / \mathrm{max}\{g\}$)','interpreter','latex')
text(1.875,12.7,'(b)','color','k')
hold on,vlines(0.25005+[0:1/2:2],'0.25k:'),xtick([0:.25:2])
%h=plot(t(ii),abs(g2(ii,1:10:end))*1000);
subplot(3,1,3)
h=plot(t(ii),imag(g2(ii,1:10:end))*1000);ylim(1000*[-.009 .009])
linestyle(h,'0.5D'),linestyle(h(1),'2k'),linestyle(h(end-1),'2k--')
ylabel('Imaginary Part of $g(t,z)$ ($\times 1000 / \mathrm{max}\{g\}$)','interpreter','latex')
xlabel('Time (Inertial Periods $2\pi / f$)','interpreter','latex')
text(1.875,8,'(c)','color','k')
hold on,vlines(0.25005+[0:1/2:2],'0.25k:'),xtick([0:.25:2])
packfig(3,1)

set(gcf,'paperposition',[1 1 5 10])
if strcmp(str,'print')
    jprint(dirname,'greensfunction')
end
%\*************************************************************************

if 0
%/*************************************************************************
%green's functions for schematic
rho=1027;
fc=1e-4;
%omega=[-100:.0001:100]*fc;
omega=[-10000:.01:10000]*fc;
z=[0:1/2:49.5]';
delta=20;zo=20;h=50;mu=delta.^2./zo;
delta=10;zo=10;h=50;mu=delta.^2./zo;

[G1,G2]=vzeros(length(omega),length(z));

%z=[0:5:45]';
parfor i=1:length(z)
    i
   % G1(:,i)=rho.*abs(fc).*windtrans(omega*24*3600,z(i),fc*24*3600,delta,mu,inf);
    G2(:,i)=rho.*abs(fc).*windtrans(omega*24*3600,z(i),fc*24*3600,delta,mu,50);
end
%G1(~isfinite(G1))=0;
G2(:,end+1)=1e-16+0*G2(:,end);
z=[z;50];
%g1=ifft(ifftshift(G1,1));
g2=ifft(ifftshift(G2,1));
g2=g2./maxmax(abs(g2));

%fc=2 pi rad/ 10^4 seconds
%fN= 2 pi rad
%dt= 1/2 seconds
%Tf = 2 pi / fc = 10^4 seconds
t=[1:size(g2,1)]'*frac(1,2)./10^4;

clf
ii=1:40000;
subplot(3,1,1)
contourf(t(ii),z,log10(abs(g2(ii,:)))',[-12:.1:0]);nocontours,hold on,flipy
contour(t(ii),z,log10(abs(g2(ii,:)))',[-12:1/2:0],'w');
hlines(z(1:10:end),'0.2D'),hlines(z(1),'2k'),hlines(z(end-10),'2k--')
%contour(t(ii),z,real(g2(ii,:))',[0 0],'k:');
caxis([-5.5 -1.5]),ylim([-.01 49.999]),xlim([0 2]),xtick([0:.25:2])
vlines(0.25005+[0:1/2:2],'0.25k:')
ylabel('Depth (m)')
text(1.875,2.5,'(a)','color','k')
subplot(3,1,2)
h=plot(t(ii),real(g2(ii,1:10:end))*1000);ylim(1000*[-.009 .009]+1000*0.005-1.5)
linestyle(h,'0.5D'),linestyle(h(1),'2k'),linestyle(h(end-1),'2k--')
ylabel('Real Part of $g(t,z)$ ($\times 10^3 / \mathrm{max}\{g\}$)','interpreter','latex')
text(1.875,12.7-1.5,'(b)','color','k')
hold on,vlines(0.25005+[0:1/2:2],'0.25k:'),xtick([0:.25:2])
%h=plot(t(ii),abs(g2(ii,1:10:end))*1000);
subplot(3,1,3)
h=plot(t(ii),imag(g2(ii,1:10:end))*1000);ylim(1000*[-.009 .009])
linestyle(h,'0.5D'),linestyle(h(1),'2k'),linestyle(h(end-1),'2k--')
ylabel('Imaginary Part of $g(t,z)$ ($\times 10^3 / \mathrm{max}\{g\}$)','interpreter','latex')
text(1.875,8,'(c)','color','k')
hold on,vlines(0.25005+[0:1/2:2],'0.25k:'),xtick([0:.25:2])
xlabel('Time (Inertial Periods $2\pi / f$)','interpreter','latex')
% subplot(4,1,4)
% %gke=5*fliplr(log10(cumsum(squared(fliplr(g2)),2)));
% gke=5*log10(cumsum(squared(g2),2));
% contourf(t(ii),z,gke(ii,:)',[-50:.5:0]);nocontours,hold on,flipy
% contour(t(ii),z,gke(ii,:)',[-50:5:0],'w');
% hlines(z(1:10:end),'0.2D'),hlines(z(1),'2k'),hlines(z(end-10),'2k--')
% caxis([-40 -5]),ylim([-.01 49.999]),xlim([0 2]),xtick([0:.25:2])
% vlines(0.25005+[0:1/2:2],'0.25k:')
% text(1.875,2.5,'(d)','color','k')
% %ylabel('Kinetic Energy $\int_{-h}^z |g(t,x)|^2 \mathrm{d}x$')
% ylabel('Kinetic Energy $\int_{0}^z |g(t,x)|^2 \mathrm{d}x$')
% xlabel('Time (Inertial Periods $2\pi / f$)','interpreter','latex')
% packfig(4,1)
%set(gcf,'paperposition',[1 1 5 13])

packfig(3,1)
set(gcf,'paperposition',[1 1 5 10])
if strcmp(str,'print')
    jprint(dirname,'greensfunction_broader')
end
%\*************************************************************************
end

%/*************************************************************************
%illustration of problems with overflow
log10delta=linspace(-1,4,100);
log10mu=linspace(-7,4,100);
h=100;
%h=1000;
%h=1e6;
%h=1e8;
fc=1e-4;

Gi1=vzeros(length(log10mu),length(log10delta));
Gi2=vzeros(length(log10mu),length(log10delta));
Gi3=vzeros(length(log10mu),length(log10delta));
Gi4=vzeros(length(log10mu),length(log10delta));
%f=0;
f=2.*fc*24*3600;
%f=fc*24*3600*0.99;
%f=fc*24*3600*8;
tic
for i=1:length(log10mu)
    i
    for j=1:length(log10delta)
     Gi1(i,j)=windtrans(f,15,fc*24*3600,10.^log10delta(j),10.^log10mu(i),h,'two');
     Gi2(i,j)=windtrans(f,15,fc*24*3600,10.^log10delta(j),10.^log10mu(i),h,'far');
     Gi3(i,j)=windtrans(f,15,fc*24*3600,10.^log10delta(j),10.^log10mu(i),h,'general');
     Gi4(i,j)=windtrans(f,15,fc*24*3600,10.^log10delta(j),10.^log10mu(i),h,'expansion');
    end
end
%etime1=toc
%etime2=toc

figure,
clf
subplot(1,3,1),contourf(log10delta,log10mu,log10(abs(Gi3)),[-200:.1:0]),nocontours,hold on
contour(log10delta,log10mu,log10(abs(Gi3)),[-200:10:0],'w'),caxis([-12 maxmax(log10(abs(Gi1)))])
hc=colorbar('South');
hc.Label.String='Log10 Magnitude at $\omega = -2f$';
hc.Label.Interpreter='latex';
pos=get(hc,'position');
set(hc,'position',[pos(1)+pos(1)/10 pos(2) pos(3)+pos(1)/10 pos(4)/2])
subplot(1,3,2),contourf(log10delta,log10mu,log10(abs(Gi1)),[-200:.1:0]),nocontours,hold on
contour(log10delta,log10mu,log10(abs(Gi1)),[-200:10:0],'w'),caxis([-12 maxmax(log10(abs(Gi1)))])
subplot(1,3,3),contourf(log10delta,log10mu,log10(abs(Gi2-Gi4)./abs(Gi4)),[-14:.1:0]),nocontours,hold on
caxis([-14 -3])
hc2=colorbar('North');
hc2.Label.String='Log10 Fractional Error at $\omega = -2f$';
hc2.Label.Interpreter='latex';
pos2=get(hc2,'position');
set(hc2,'position',[pos2(1)-pos2(1)/28 pos2(2)-0.03 pos2(3)+pos(1)/10 pos2(4)/2])

[demat,mumat]=meshgrid(10.^log10delta,10.^log10mu);
for i=1:3
    subplot(1,3,i),%contour(log10delta,log10mu,log10(abs(Gi1-Gi2)./abs(Gi1)),[-3.4 -3.4],'k','linewidth',2)
    text(3.5,3.7,['(' setstr(96+i) ')'],'color','k')
    xlim([-1 3.99])
    axis equal,xlim([-1 3.99]),ylim([-5 4])
    ylabel('Log10 Madsen Depth $\mu$ (m)','interpreter','latex')
    xlabel('Log10 Ekman Depth $\delta$ (m)','interpreter','latex')
    %contour(log10delta,log10mu,log10(demat./mumat*2*sqrt(2)*sqrt(3)),[1 1]*3,'color',[1 1 1]*0.6,'linewidth',2)
    contour(log10delta,log10mu,log10(demat./mumat*2*sqrt(2)*sqrt(3)),[1 1]*2.9,'color',[1 1 1]*0.6,'linewidth',2)
end
packfig(1,3,'columns')
set(hc,'position',[pos(1)+pos(1)/10 pos(2)+.1 pos(3)+pos(1)/10 pos(4)/2])
set(hc2,'position',[pos2(1)-pos2(1)/28 pos2(2)-0.03-.07 pos2(3)+pos(1)/10 pos2(4)/2])
%set(gcf,'paperposition',[1 1 11 5])
set(gcf,'paperposition',[1 1 11 8])
if strcmp(str,'print')
    jprint(dirname,'overflowproblem')
end
%\*************************************************************************

%/*************************************************************************
%symmetry plots
rho=1027;
%log10delta=linspace(-1,4,101);
%log10mu=linspace(-7,4,100);
log10delta=linspace(-4,4,201);
log10mu=linspace(-8,4,200);
%h=10000;
h=[16 1e2 1e3 1e4 1e5 1e6];
%h=[15.01 15.1 16 26 1e2 1e3 1e4 1e5 1e6];
fc=1e-4;

[demat,mumat]=meshgrid(10.^log10delta,10.^log10mu);
zomat=demat.^2./mumat;

A=zeros(size(demat,1),size(demat,2),length(h));
A0=zeros(size(demat,1),size(demat,2),length(h));
for i=1:length(h)
    A(:,:,i)=frac(2,mumat).*log(frac(1+h(i)./zomat,1+15./zomat));
    A0(:,:,i)=frac(2,mumat).*log(1+h(i)./zomat);
end

%Gf=vzeros(length(log10mu),length(log10delta),length(h));
%Gf0=vzeros(length(log10mu),length(log10delta),length(h));
% for i=1:length(log10mu)
%     i
%     parfor j=1:length(log10delta)
%         for k=1:6
%           Gf(i,j,k)=rho.*fc.*windtrans(-fc*24*3600,15,fc*24*3600,10.^log10delta(j),10.^log10mu(i),h(k));
%          Gf0(i,j,k)=rho.*fc.*windtrans(-fc*24*3600,0,fc*24*3600,10.^log10delta(j),10.^log10mu(i),h(k));
%         end
%     end
% end
% maxmax(abs(A-Gf))
% maxmax(abs(A0-Gf0))
% jpcolor(log10(abs(A(:,:,1)-Gf(:,:,1))./A(:,:,1)))
% %these agree to the numerical noise level

omega=[-3:.001:1]*fc;
log10zo=[-12:.1:12]';
ii=1:10:length(log10zo);

clear dei mui dei0 mui0 dei1 mui1
zo=10.^log10zo;
for j=1:length(h)
    dei{j,1}=sqrt(frac(2*zo,1).*log(frac(1+h(j)./zo,1+15./zo)));
    mui{j,1}=dei{j}.^2./zo;
    dei1{j,1}=sqrt(frac(2*zo,10).*log(frac(1+h(j)./zo,1+15./zo)));
    mui1{j,1}=dei1{j}.^2./zo;
    dei0{j,1}=sqrt(frac(2*zo,1).*log(frac(1+h(j)./zo,1)));
    mui0{j,1}=dei0{j}.^2./zo;
end
%--------------------------------------------------------------------------
figure,
clf
contourf(log10delta,log10mu,log10(A(:,:,3)),[-10:.1:10]),nocontours,hold on
contour(log10delta,log10mu,log10(A(:,:,3)),[0 0 ],'k','linewidth',1.5)
contour(log10delta,log10mu,log10(A(:,:,3)),[-10:1:10],'k','linewidth',0.5)
contour(log10delta,log10mu,log10(zomat),[-20:20],'w','linewidth',0.5)
contour(log10delta,log10mu,log10(zomat),[0 0],'w','linewidth',1.5)
plot(log10(dei{3}(1:10:end)),log10(mui{3}(1:10:end)),'ko','markerfacecolor','k','markersize',4)
caxis([-4.7 7.3]),axis equal,ylim([-7 4]),xlim([-4 4]),
ylabel('Log10 Madsen Depth $\mu$ (m)','interpreter','latex')
xlabel('Log10 Ekman Depth $\delta$ (m)','interpreter','latex')
hc=colorbar('SouthOutside');
hc.Label.String='Log10 Inertial Amplitude A (m$^{-1}$)';
hc.Label.Interpreter='latex';
hc.Ticks=[-4:1:8];
set(gcf,'paperposition',[1 1 4*1.5 5*1.5])
%text(-0.92,3.7,'M'),text(3.8,-6.8,'E')
text(-3.925,3.7,'M'),text(3.7,-6.8,'E','color','w')
if strcmp(str,'print')
    jprint(dirname,'deltamuplane')
end
%--------------------------------------------------------------------------
%figure,cellplot(dec,muc)
%figure,cellplot(dec0,muc0)
omega=[-100:.1:-8.6 -8.5:.001:-1-0.005 -1-0.005:1e-7:-1+0.005  -1+0.005:0.001:8.5 8.6:.1:100]*fc;
%omega=[-1e4:10:-1000 -1000:1:-100 -100:.1:-8.6 -8.5:.001:-1-0.005 -1-0.005:1e-7:-1+0.005  -1+0.005:0.001 :8.5 8.6:.1:100 100:1:1000 1000:10:1e4]*fc;
G=nan*zeros(length(omega),length(ii),length(h));
[Gm,Ge,Gminf,Geinf]=vzeros(length(omega),length(h));
%G0=nan*zeros(length(omega),length(ii),length(h));
%G1=nan*zeros(length(omega),length(ii),length(h));
for j=1:size(G,3)
    j
   Gm(:,j)=rho.*abs(fc).*windtrans(omega*24*3600,15,fc*24*3600,0,mui{j}(1),h(j));
   Ge(:,j)=rho.*abs(fc).*windtrans(omega*24*3600,15,fc*24*3600,dei{j}(end),0,h(j));
   parfor k=1:length(ii)
        k
        G(:,k,j)=rho.*abs(fc).*windtrans(omega*24*3600,15,fc*24*3600,dei{j}(ii(k)),mui{j}(ii(k)),h(j));
         %G1(:,k,j)=rho.*abs(fc).*windtrans(omega*24*3600,15,fc*24*3600,dei1{j}(ii(k)),mui1{j}(ii(k)),h(j));
        %G0(:,k,j)=rho.*abs(fc).*windtrans(omega*24*3600,0,fc*24*3600,dei0{j}(ii(k)),mui0{j}(ii(k)),h(j));
    end
end
%--------------------------------------------------------------------------
figure
clf
%[~,jj]=min(abs(omega));
for j=1:size(G,3)
    subplot(2,3,j)
    hl=plot(G(:,:,j));axis equal, axis square
    axis([-.3 1 -.65 .65]*1.05),vlines(0,'0.5k:'),hlines(0,'0.5k:')
    linestyle(hl,'0.5D')
    hl=plot(G(:,1,j));linestyle(hl,'2k--')
    hl=plot(G(:,end,j));linestyle(hl,'2k')
    hl=plot(Ge(:,j));linestyle(hl,'0.5w')
    hl=plot(Gm(:,j));linestyle(hl,'0.5k')
    text(0.9,0.59,['(' setstr(96+j) ')'])
%    xlabel('Real Part of Transfer Function (m^2s / kg)')%(Dimensionless)')
%    ylabel('Imaginary Part of Transfer Function (m^2s / kg)')% (Dimensionless)')
    xlabel('Real Part of $\widetilde G(\omega,15$ m$)$ (m$^{-1}$)','interpreter','latex')%(Dimensionless)')
    ylabel('Imaginary Part of $\widetilde G(\omega,15$ m$)$ (m$^{-1}$)','interpreter','latex')% (Dimensionless)')
    xtick([-.4:.2:1.2]),ytick([-.6:.2:.6])
    %plot(G(jj,:,j),'ko','markerfacecolor','k','markersize',4)
end
packfig(2,3)
set(gcf,'paperposition',[1 1 9.4 6])
fontsize 10 10 9 9
if strcmp(str,'print')
    jprint(dirname,'similarflowers')
end
%%check invariance
%figure,plot(G(:,:,1)),hold on,plot(G1(:,:,1)/10,'r')
%figure,plot(G(:,:,end)),hold on,plot(G1(:,:,end)/10,'r')
% %--------------------------------------------------------------------------
% figure
% clf
% for j=1:size(Gf,3)
%     subplot(2,3,j)
%     hl=plot(omega./fc,abs(G(:,2:end-1,j)));hold on
%     axis([-1.99 0 1.001*1e-4 1.25]),ylog
%     linestyle(hl,'0.5D')
%     hl=plot(omega./fc,abs(G(:,1,j)));
%     linestyle(hl,'2k')
%     hl=plot(omega./fc,abs(G(:,end,j)));
%     linestyle(hl,'2k--')
%     ylabel('Log10 Magnitude of $G(\omega,15$ m$)$','interpreter','latex')
%     xlabel('Nondimensional Frequency $\omega/f$','interpreter','latex')
%     text(-.17,0.8,['(' setstr(96+j) ')'])
%     xtick([-2:.5:0])
%     vlines(-1,'0.5k:')
% end
% packfig(2,3)
% set(gcf,'paperposition',[1 1 9*1.25 5*1.25])
% jprint(dirname,'similarmagnitudes')
% %--------------------------------------------------------------------------
% figure
% clf
% for j=1:size(Gf,3)
%     subplot(2,3,j)
%     hl=plot(omega./fc,(360/2/pi)*unwrap(angle(G(:,2:end-1,j))));hold on
%     axis([-1.99 0 -179.9 180]),
%     linestyle(hl,'0.5D')
%     hl=plot(omega./fc,(360/2/pi)*unwrap(angle(G(:,1,j))));
%     linestyle(hl,'2k')
%     hl=plot(omega./fc,(360/2/pi)*unwrap(angle(G(:,end,j))));
%     linestyle(hl,'2k--')
%     ylabel('Angle of $G(\omega,15$ m$) (degrees) $','interpreter','latex')
%     xlabel('Nondimensional Frequency $\omega/f$','interpreter','latex')
%     %text(-.17,0.8,['(' setstr(96+j) ')'])
%     xtick([-2:.5:0])
%     vlines(-1,'0.5k:')
% end
% packfig(2,3)
% set(gcf,'paperposition',[1 1 9*1.25 5*1.25])
% jprint(dirname,'similarphases')
%--------------------------------------------------------------------------
% figure
% clf
% for j=1:size(Gf0,3)
%     subplot(2,3,j)
%     hl=plot(G0(:,2:end-1,j));axis equal, axis square
%     axis([-.05 1.05 -.505 .505]),vlines(0,'0.5k:'),hlines(0,'0.5k:')
%     linestyle(hl,'0.5D'),
%     hl=plot(G0(:,end,j)); linestyle(hl,'2k')
%     hl=plot(G0(:,1,j));linestyle(hl,'2k--')
%     text(0.9,0.44,['(' setstr(96+j) ')'])
%     xlabel('Real Part of $G(\omega,0$ m$)$','interpreter','latex')%(Dimensionless)')
%     ylabel('Imaginary Part of $G(\omega,0$ m$)$','interpreter','latex')% (Dimensionless)')
%     xtick([-.4:.2:1.2]),ytick([-.6:.2:.6])
% end
% packfig(2,3)
% set(gcf,'paperposition',[1 1 9.4 6])
% jprint(dirname,'similarflowers0')
lnomega=logspace(2,100,10000);
omega=[-fliplr(lnomega) -100:.1:-8.6 -8.5:.001:-1-0.005 -1-0.005:1e-7:-1+0.005  -1+0.005:0.001 :8.5 8.6:.1:100 lnomega]*fc;
G0=vzeros(length(omega),length(ii));
Gm0=rho.*abs(fc).*windtrans(omega*24*3600,0,fc*24*3600,0,mui0{3}(1),h(3));
Ge0=rho.*abs(fc).*windtrans(omega*24*3600,0,fc*24*3600,dei0{3}(end),0,h(3));
%Gm0=rho.*abs(fc).*windtrans(omega*24*3600,1e-10,fc*24*3600,0,mui0{3}(ii(end)),h(3));
%Ge0=rho.*abs(fc).*windtrans(omega*24*3600,0,fc*24*3600,dei0{3}(ii(1)),0,h(3));
%zeta=2*sqrt(2)*frac(zo,delta).*sqrt(abs(1+ommat./fc));

for k=1:length(ii)
    k
    G0(:,k)=rho.*abs(fc).*windtrans(omega*24*3600,0,fc*24*3600,dei0{3}(ii(k)),mui0{3}(ii(k)),h(3));
 %   G1(:,k)=rho.*abs(fc).*windtrans(omega*24*3600,0,fc*24*3600,dei0{3}(ii(k)),mui0{3}(ii(k)),h(1));
end
figure
clf
hl=plot(G0);axis equal, axis square
axis([-.05 1.05 -.505 .505]),vlines(0,'0.5k:'),hlines(0,'0.5k:')
linestyle(hl,'0.5D'),
hl=plot(G0(:,1)); linestyle(hl,'2k--')
hl=plot(G0(:,end)); linestyle(hl,'2k')
hl=plot(Ge0); linestyle(hl,'0.5w')
hl=plot(Gm0);linestyle(hl,'0.5k')
%text(0.9,0.44,['(' setstr(96+j) ')'])
xlabel('Real Part of $\widetilde G(\omega,0$ m$)$ (m$^{-1}$)','interpreter','latex')%(Dimensionless)')
ylabel('Imaginary Part of $\widetilde G(\omega,0$ m$)$ (m$^{-1}$)','interpreter','latex')% (Dimensionless)')
xtick([-.4:.2:1.2]),ytick([-.6:.2:.6])
set(gcf,'paperposition',[1 1 4 4])
plot(2*h(3)/squared(dei0{3}(end)),0,'wo','markerfacecolor','k')
fontsize 10 10 9 9
if strcmp(str,'print')
    jprint(dirname,'similarflowers0')
end


function [vout, rout] = fitC13Data(v0, expdata, model, majorIterationLimit)
%
% USAGE:
%
%    [vout, rout] = fitC13Data(v0, expdata, model, majorIterationLimit)
%
% INPUTS:
%    v0:                     It will automatically be converted to alpha by solving `N*alpha = v`;
%                            if `v0` is a matrix then it is assumed to be a multiple start situation and
%                            `vout` will also have this size.
%    expdata:                either a data structure or a cell array of structures, in
%                            which case it is assumed that you wan to fit the sum of the scores
%    model:                  model structure
%
% OPTIONAL INPUT:
%    majorIterationLimit:    max number of iterations solver is allowed to take. Default = 1000
%
% OUTPUTS:
%    vout:                   reflects size of `v0`, result of NLPsolution
%    rout:                   cell, result of NLPsolution

if nargin < 4
    majorIterationLimit = 1000;
end
diffInterval = 1e-5;         %gradient step size.
method = 1; % 2 = in terms of v.  % 1 in terms of alpha
printLevel = 3; %3 prints every iteration.  1 does a summary.  0 = silent.

if method == 1
    if ~isfield(model, 'N')
       model.N = null(full(model.S));
       display('model.N should be defined');
       pause;
    end

    x0 = model.N\v0; % back substitute

    % safety check:
    if (max(abs(model.S*v0))> 1e-6)
        display('v0 not quite in null space');
        pause;
    end
    if(max(abs(model.N*x0 - v0)) > 1e-6)
        max(abs(model.N*x0 - v0))
        display('null basis is weird');
        pause;
    end

    % set up problem
    nalpha = size(model.N, 2);
    x_L = -1000*ones(nalpha,1);
    x_U = 1000*ones(nalpha,1);
    [A, b_L, b_U] = defineLinearConstraints(model, method);
elseif method == 2
    x0 = v0; % back substitute
    [A, x_L, x_U] = defineLinearConstraints(model, method);
    b_L = zeros(size(A,1),1);
    b_U = zeros(size(A,1),1);
else
    display('error'); pause;
end

numpoints = size(x0,2);
vout = zeros(size(v0));
rout = cell(numpoints, 1);

for k = 1:numpoints
    x_0 = x0(:,k);
    NLPproblem.objFunction = 'errorComputation2';
    NLPproblem.gradFunction = 'errorComputation2_grad';
    NLPproblem.lb = x_L;
    NLPproblem.ub = x_U;
    NLPproblem.name = 'c13fitting';
    NLPproblem.x0 = x_0;
    NLPproblem.A = A;
    NLPproblem.b_L = b_L;
    NLPproblem.b_U = b_U;
    NLPproblem.user.expdata = expdata;
    NLPproblem.user.model = model;
    NLPproblem.user.useparfor = true;
    NLPproblem.user.diff_interval = diffInterval;
    NLPproblem.osense = 1;

    NLPproblem.PriLevOpt = 1;
    cnan = ( method == 2);

    NLPsolution = solveCobraNLP(NLPproblem, 'checkNaN', cnan, 'printLevel', printLevel, 'iterationLimit', majorIterationLimit, 'logFile', 'minimize_SNOPT.txt');

    if method == 1
        vout(:,k) = model.N*NLPsolution.full;
    else
        vout(:,k) = NLPsolution.full;
    end
    rout{k} = NLPsolution;
end
return


classdef nme_load3p < mp.nm_element & mp.form_acp

%   MATPOWER
%   Copyright (c) 2021-2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

%     properties
%     end     %% properties

    methods
        function name = name(obj)
            name = 'load3p';
        end

        function np = np(obj)
            np = 3;     %% this is a 3 port element
        end

        function obj = build_params(obj, nm, dm)
            build_params@mp.nm_element(obj, nm, dm);    %% call parent
            dme = obj.data_model_element(dm);

            %% constant complex power demand
            pd = [dme.pd1 dme.pd2 dme.pd3];
            qd = pd .* tan(acos( [dme.pf1 dme.pf2 dme.pf3] ));

            obj.s = pd(:) + 1j * qd(:);
        end
    end     %% methods
end         %% classdef


% This demo Will show how to reconstruct real data.
%
% We will reconstruct the so-called SophiaBeads dataset, where a bunch of
% "balls" are put in a Nikon ?-CT machine.
%
% The data can be downloaded at:
% https://zenodo.org/record/16474
%
% And the codes can be downloaded at:
% http://zenodo.cern.ch/record/16539
%
% The SophiaBeads codes and dataset ARE NOT part of TIGRE toolbox, and are
% not licensed under the BSD license, be aware.
%
% Additionally, if you use the dataset or the codes, they have each of them
% their own bilbiography, that you need to reference, as per their own
% requirements.

% cite as:

% citeme('SophiaBeads data')
% citeme('SophiaBeads code')

%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
% This file is part of the TIGRE Toolbox
%
% Copyright (c) 2015, University of Bath and
%                     CERN-European Organization for Nuclear Research
%                     All rights reserved.
%
% License:            Open Source under BSD.
%                     See the full license at
%                     https://github.com/CERN/TIGRE/blob/master/LICENSE
%
% Contact:            tigre.toolbox@gmail.com
% Codes:              https://github.com/CERN/TIGRE/
% Coded by:           Ander Biguri
%--------------------------------------------------------------------------

%% How to run this code:
%
% 1.- Download both the code and the data (any size you prefer).
%
% 2.- Open SophiaBeads.m in the codes and replace pathname and filename (in
%     lines 13-14 by the data path and name you chosen
%
% 3.- In line 27 add the followinh code:     break;
%
% 4.- Run SophiaBeads.m
%
% 5.- Without clearing the variables, come to this code and run it.
%
%

% from sophiabeads to TIGRE
geo.DSD = geom.d_sd;
geo.DSO = abs(geom.source.x);

% Detector parameters
geo.nDetector=[geom.dets.ny;geom.dets.nz];
geo.dDetector=[mean(diff(geom.dets.y)); mean(diff(geom.dets.z))];
geo.sDetector=geo.nDetector.*geo.dDetector;

% Image parameters
geo.nVoxel=geom.voxels.';  % this is the datasheets standard size, but its
% very big size and most ocmputers will not be able to run it. We redefine
% it in the next line, but feel free to use the original
geo.nVoxel=[500 500 200].';
geo.sVoxel=[geom.voxel_size.*geom.voxels].';
geo.dVoxel=geo.sVoxel./geo.nVoxel;

% Offsets
geo.offOrigin=[0,0,0].';
geo.offDetector=[0; 0];

% Auxiliary
geo.accuracy=0.5;
geo.mode='cone';
geo.COR=geom.source.y;

% Angles
angles=-geom.angles.';

data=reshape(data,1564,1564,size(angles,2));
data=permute(data,[2 1 3]);

%% Now use any algorithms you want

% example:
% beadsSART=SART(data,geo,angles,15);
beadsCGLS=CGLS(data,geo,angles,15);
ImgASD_POCS_20=OS_ASD_POCS(data,geo,angles,50,...
'TViter',2,'maxL2err',0.5,'alpha',0.002,'alpha_red',0.2,... % these are very important
'lambda',1,'lambda_red',0.99,'Ratio',1,'Verbose',true);
% plotImg([beadsSART beadsCGLS],'Dim','Z','Step',1)


function f = replaceBoundaryRoots(f)
%REPLACEBOUNDARYROOTS  Replace boundary roots of a SINGFUN.
%  F = REPLACEBOUNDARYROOTS(F) returns a SINGFUN which has both exponents less
%  than 1 by absorbing the integer part of any boundary exponents larger than 1
%  into its smoothPart.
%
% See also EXTRACTBOUNDARYROOTS.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% Grab the exponents:
exps = get(f, 'exponents');

% Grab the indice for exponents larger or equal to 1:
ind = ( exps >= 1 );

% Both exponents are less than 1:
if ( ~any( ind ) )
    return
end

% Sort out the new exponents and the order of the boundary roots which need to
% be absorbed into the smoothPart:
newExps = exps;
newExps(ind) = exps(ind) - floor(exps(ind));
pow = exps - newExps;

% Compute the factor from function roots:
mult = singfun.constructSmoothPart(@(x) (x+1).^pow(1).*(1-x).^pow(2), [], []);
f.smoothPart = f.smoothPart.*mult;

% Update the exponents:
f.exponents = newExps;

end


function index_test02 ( )

%*****************************************************************************80
%
%% INDEX_TEST02 tests INDEX01, INDEX10, INDEX12 and INDEX21.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 November 2012
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'INDEX_TEST02\n' );
  fprintf ( 1, '  For a 2D array,\n' );
  fprintf ( 1, '  INDEX01 column indexes with zero base,\n' );
  fprintf ( 1, '  INDEX10 row indexes with zero base,\n' );
  fprintf ( 1, '  INDEX12 column indexes with unit base,\n' );
  fprintf ( 1, '  INDEX21 row indexes with unit base.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '                Min   Index     Max\n' );
  fprintf ( 1, '\n' );

  i_min = 1;
  i = 3;
  i_max = 5;
  j_min = 1;
  j = 2;
  j_max = 4;
  fprintf ( 1, '  2D Index:  %3d%3d  %3d%3d  %3d%3d\n', ...
    i_min, j_min, i, j, i_max, j_max );

  value = index01 ( i_min, i, i_max, j_min, j, j_max );
  index_min = 0;
  index_max = index_min + ( i_max - i_min + 1 ) * ( j_max - j_min + 1 ) - 1;
  fprintf ( 1, '  INDEX01:   %6d  %6d  %6d\n', ...
    index_min, value, index_max );

  value = index10 ( i_min, i, i_max, j_min, j, j_max );
  index_min = 0;
  index_max = index_min + ( i_max - i_min + 1 ) * ( j_max - j_min + 1 ) - 1;
  fprintf ( 1, '  INDEX10:   %6d  %6d  %6d\n', ...
    index_min, value, index_max );

  value = index12 ( i_min, i, i_max, j_min, j, j_max );
  index_min = 1;
  index_max = index_min + ( i_max - i_min + 1 ) * ( j_max - j_min + 1 ) - 1;
  fprintf ( 1, '  INDEX12:   %6d  %6d  %6d\n', ...
    index_min, value, index_max );

  value = index21 ( i_min, i, i_max, j_min, j, j_max );
  index_min = 1;
  index_max = index_min + ( i_max - i_min + 1 ) * ( j_max - j_min + 1 ) - 1;
  fprintf ( 1, '  INDEX21:   %6d  %6d  %6d\n', ...
    index_min, value, index_max );

  return
end


% demo for binary data classification

close all
clear variables

dim.p = 32;
dim.n_t = 1;
dim.n_phi = 16;
dim.n_theta = 0;
dim.n = 0;

g_fname = @g_classif;
options.sources = struct('type',1 ,'out', 1); % one binomial observation;
options.priors.muPhi = zeros(dim.n_phi,1);
options.priors.SigmaPhi = 1e0*eye(dim.n_phi);
options.isYout = zeros(dim.p,1);
options.DisplayWin = 0;
options.verbose = 0;

Nmcmc = 64;
p = cell(2,2,Nmcmc);
o = cell(2,2,Nmcmc);
F = zeros(2,2,Nmcmc);
ner = zeros(2,2,Nmcmc); % proportion of correct predictions
mner = zeros(2,Nmcmc); % maximum performance rate

fprintf(1,['MCMC simulations... ']);
fprintf(1,'%6.2f %%',0)

for ii=1:Nmcmc
    options.inG.X = randn(dim.n_phi-1,dim.p);
    for i=1:2
        % simulate data with and without real mapping
        phi = (2-i)*randn(dim.n_phi,1);
        [y,x,x0,eta,e] = VBA_simulate (dim.n_t,[],g_fname,[],phi,[],[],[],options);
        g = y-e;
        g = g>0.5; % denoised data
        mner(i,ii) = sum(g.*y + (1-g).*(1-y))./dim.p; % max performance rate
        for j=1:2
            % invert model with and without the 2nd half of the data
            options.isYout(dim.p/2:dim.p) = 2-j;
            [p{j,i,ii},o{j,i,ii}] = VBA_NLStateSpaceModel(y,[],[],g_fname,dim,options);
            F(j,i,ii) = o{j,i,ii}.F - VBA_LMEH0(y,o{j,i,ii}.options);
            % proportion of correct predictions on 2nd half of the data
            gx = o{j,i,ii}.suffStat.gx(dim.p/2:dim.p);
            g0 = y(dim.p/2:dim.p);
            ner(j,i,ii) = sum(gx.*g0 + (1-gx).*(1-g0))./(dim.p/2);
        end

    end

    fprintf(1,repmat('\b',1,8))
    fprintf(1,'%6.2f %%',100*ii/Nmcmc)

end

fprintf(1,repmat('\b',1,8))
fprintf(' OK.')
fprintf('\n')

hf = figure('color',[1 1 1]);
pos = get(hf,'position');
set(hf,'position',pos.*[1 1 1.5 1]);
test = {'test','train'};
data = {'half dataset','full dataset'};
model = {'H1','H0'};
ylim = [0;0];

for j=1:2

    ha(j,1) = subplot(2,2,(j-1)*2+1,'parent',hf);
    mr = squeeze(mean(ner(j,:,:),3));
    vr = squeeze(var(ner(j,:,:),[],2)./Nmcmc);
    plotUncertainTimeSeries(mr',vr',[],ha(j,1));
    set(ha(j,1),'xlim',[0,3],'xtick',[1,2],'xticklabels',model)
    xlabel(ha(j,1),'type of simulated data')
    ylabel(ha(j,1),['P[correct prediction]'])
    title(ha(j,1),test{j})
    box(ha(j,1),'off')
    hold(ha(j,1),'on')
    plot(ha(j,1),[0,3],[0.5,0.5],'r--')
    mmr = mean(mner,2);
    plot(ha(j,1),[1,2],mmr,'go')

    ha(j,2) = subplot(2,2,(j-1)*2+2,'parent',hf);
    dF = F(j,:,:);
    mdF = squeeze(mean(dF,3));
    vdF = squeeze(var(dF,[],3)./Nmcmc);
    plotUncertainTimeSeries(mdF',vdF',[],ha(j,2));
    set(ha(j,2),'xlim',[0,3],'xtick',[1,2],'xticklabels',model)
    xlabel(ha(j,2),'type of simulated data')
    ylabel(ha(j,2),['log p(y|H1) - log p(y|H0)'])
    title(ha(j,2),'evidence for a mapping')
    box(ha(j,2),'off')
    title(ha(j,2),data{j})

    ylim(1) = min([ylim(1),get(ha(j,2),'ylim')]);
    ylim(2) = max([ylim(2),get(ha(j,2),'ylim')]);
end

for j=1:2
    set(ha(j,2),'ylim',ylim)
end

VBA_getSubplots ();


classdef TestLDA
    %TestLDA

    methods (Static)
        function test_1
            % data
            X = [randn(50,5)-1; randn(50,5)+1];
            labels = [ones(50,1)*1; ones(50,1)*2];
            [N,d] = size(X);

            % LDA
            lda = cv.LDA();
            lda.compute(X, labels);
            evals = lda.eigenvalues;
            evecs = lda.eigenvectors;
            ncomponents = numel(evals);

            assert(isvector(evals) && ismatrix(evecs));
            assert(isequal(size(evecs), [d ncomponents]))

            % project/reconstruct
            if ncomponents == 1
                % avoid edge case when only 1 component was chosen
                return
            end
            A = randn(40,d);
            Z = lda.project(A);
            AA = lda.reconstruct(Z);
            assert(isequal(size(Z), [size(A,1) ncomponents]))
            assert(isequal(size(AA), size(A)));
        end

        function test_2
            X = randn(50,4);
            labels = randi([1 3], [50 1]);
            lda = cv.LDA('NumComponents',2);
            lda.compute(X, labels)
            assert(numel(lda.eigenvalues) == 2);
            assert(size(lda.eigenvectors,2) == 2);
        end

        function test_3
            X = randn(50,4);
            k = 3;
            mn = mean(X);
            [V,~] = eig(cov(bsxfun(@minus,X,mn)));

            P = cv.LDA.subspaceProject(V(:,1:k), mn, X);
            validateattributes(P, {'double'}, {'size',[50 k]});

            R = cv.LDA.subspaceReconstruct(V(:,1:k), mn, P);
            validateattributes(R, {'double'}, {'size',[50 4]});
        end

        function test_error_1
            try
                cv.LDA('foobar');
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


function T = EinsteinSum(varargin)
% tensor multiplication according to Einstein summation convention
%
% Description
% This function computes a tensor product according to Einstein summation
% convention
%
% Syntax
%   % sumation against dimension 1 and 2
%   C = EinsteinSum(E,[1 -1 2 -2],v,-1,v,-2)
%
%   eps = EinsteinSum(C,[-1 1 -2 2],sigma,[-1 -2])
%
% Input
%  T1,T2 - @tensor
%  dimT1 - vector of indices giving the summation order in tensor 1
%  dimT2 - vector of indices giving the summation order in tensor 2
%
% Output
%  T - @tensor
%
% See also
%

% TODO: check for correct symmetries !!!

global useBSXFUN;

M1 = 1; dimT1 = [];
T = varargin{1};

% for each tensor in varargin
iv = 1;
while iv < length(varargin) && ~ischar(varargin{iv})

  % take new vector from varargin
  M2 = varargin{iv};
  dimT2 = varargin{iv+1};
  iv = iv+2;

  % convert to double
  if isa(M2,'tensor')
    M2 = M2.M;
  elseif isa(M2,'quaternion')
    M2 = matrix(M2);
  elseif isa(M2,'vector3d')
    M2 = double(M2);
    M2 = permute(M2,[3 1 2]);
  end

  %
  if length(dimT2) > 1 && sum(dimT2<0)>1 && max(accumarray(-dimT2(dimT2<0).',1)>1)
    [M2,dimT2] = innerSum(M2,dimT2);
  end

  % reorder T1 such that [-rDel ... -3 -2 -1  1 2 3 .. rOut x x x]
  rOut = max([0,dimT1,dimT2]);
  rDel = -min([0,dimT1,dimT2]);
  rExt = max([0,ndims(M1) - length(dimT1), ndims(M2) - length(dimT2)]);

  % new order of dimensions for tensor 1
  dimT1(dimT1>0) = dimT1(dimT1>0) - 1;  % we should start with zero to avoid the cap
  exp1 = 1:rOut + rDel; exp1(dimT1 + rDel + 1) = []; % dimensions in reserve
  order1 = [dimT1 + rDel + 1,...  the tensor components
    rOut + rDel + (1:rExt),...    none tensor components
    exp1];

  % new order of dimensions for tensor 2
  dimT2(dimT2>0) = dimT2(dimT2>0) - 1; % we should start with zero to avoid the cap
  exp2 = 1:rOut + rDel; exp2(dimT2 + rDel + 1) = []; % dimensions in reserve
  order2 = [dimT2 + rDel + 1,...  the tensor components
    rOut + rDel + (1:rExt),...    none tensor components
    exp2];

  M1 = ipermute(M1,order1);
  M2 = ipermute(M2,order2);

  if useBSXFUN
    M1 = bsxfun(@times, M1, M2);
  else
    M1 = M1 .* M2;
  end

  % setup dimT1
  dimT1 = [-rDel:-1,1:rOut];

end

% sum over the dimensions to be removed
if useBSXFUN
  for d = 1:rDel, M1 = sum(M1,d); end
else
  if rDel>0, M1 = sum(M1,1:rDel); end
end

% and remove these leading dimensions
s = size(M1);
M1 = reshape(M1,[s(rDel+1:end) 1 1]);

% rank 0 tensor should become double
if rOut == 0
  T = M1;
elseif strcmp(class(T),'tensor') || check_option(varargin(iv:end),'keepClass')
  T.M = M1;
  T.rank = rOut;
else
  T = tensor(M1,T.CS,'noCheck','rank',rOut,varargin{iv:end});
end

end

%%
function [M,ind] = innerSum(M,ind)

% find indices to be summed
[a,b] = findDouble(ind);

if isempty(a), return;end

ind([a,b]) = [];

% remember size of matrix
sM = size(M);
sM([a,b]) = [];

% make a,b the first two dimensions
order = 1:max([ndims(M) a b]);
order([a b]) = [];
order = [a b order];
M = permute(M,order);

% reduces multiple remove dimensions to one
M = reshape(M,3^numel(a),3^numel(b),[]);

% sum along the diagonal of the first two dimensions
N = zeros(1,1,size(M,3));
for l = 1:3^numel(a)
  N = N + M(l,l,:);
end

% reshape back
M = reshape(N,[sM 1 1]);

end

%%
function [a,b] = findDouble(x)

%if length(x) <= 1 || all(x>=0) || sum(x<0)<2 || max(accumarray(-x(x<0).',1))<2
%  a = [];
%  b = [];
%  return;
%end

d = bsxfun(@minus,x,x') == 0 & bsxfun(@times,x<0,x'<0);
d = d & ~tril(ones(size(d)));
[a,b] = find(d);
a = a'; b = b';

end


function DEM_demo_song_priors
% Demo for a bird songs: In this example, we simulate local field potential
% using the prediction error from the song-bird example below. We look at
% these responses under natural stimuli and after removing the second
% level of the hierarchy to show it is necessary for veridical perception.
% We then repeat but omitting dynamical priors by forsaking generalised
% coordinates
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: DEM_demo_song_priors.m 6030 2014-05-31 13:09:24Z karl $

% hierarchical non-linear generative model (dynamic & chaotic)
%==========================================================================

% timing
%--------------------------------------------------------------------------
N        = 128;                      % length of stimulus (bins)
dt       = 1/64;                     % time bin (seconds)

% correlations
%--------------------------------------------------------------------------
M(1).E.s = 1;
M(1).E.K = exp(-2);

% level 1
%--------------------------------------------------------------------------
% P(1): Prandtl number
% P(2): 8/3
% P(3): Rayleigh number

P        = [10; 8/3];
x        = [0.9; 0.8; 30];
f        = '[-P(1) P(1) 0; (v(1) - 4 - x(3)) -1 0; x(2) 0 -P(2)]*x/16;';
M(1).f   = f;
M(1).g   = inline('x([2 3])','x','v','P');
M(1).x   = x;
M(1).pE  = P;
M(1).V   = exp(1);
M(1).W   = exp(8);

% level 2
%--------------------------------------------------------------------------
P        = [10; 8/3];
x        = [0.9; 0.8; 30];
f        = '[-P(1) P(1) 0; (32 - x(3)) -1 0; x(2) 0 -P(2)]*x/128;';
M(2).f   = f;
M(2).g   = inline('x(3)','x','v','P');
M(2).x   = x;
M(2).pE  = P;
M(2).V   = exp(8);
M(2).W   = exp(8);

% create data
%==========================================================================

% create innovations & add causes
%--------------------------------------------------------------------------
DEM      = spm_DEM_generate(M,N);

% DEM estimation and display
%==========================================================================
DEM.M(1).x = [1; 1; 8];
DEM.M(2).x = [1; 1; 8];

% canoncial DEM
%--------------------------------------------------------------------------
DEMc   = DEM;

% without second level
%==========================================================================
DEMa   = DEM;
DEMa.M = DEMa.M(1);

% without generlised coordinates
%==========================================================================
DEMb   = DEM;
DEMb.M(1).E.n = 1;

% deconvolve
%--------------------------------------------------------------------------
DEMa   = spm_DEM(DEMa);
DEMb   = spm_DEM(DEMb);
DEMc   = spm_DEM(DEMc);

% show songs and prediction error (ERP)
%==========================================================================
spm_DEM_qU(DEMc.qU,DEMc.pU)
colormap('pink')

% Sonograms
%--------------------------------------------------------------------------
subplot(3,2,5)
spm_DEM_play_song(DEMc.pU ,N*dt);
title('simulus','Fontsize',18)
axis square

subplot(3,2,6)
spm_DEM_play_song(DEMc.qU ,N*dt);
title('percept','Fontsize',18)
axis square
drawnow

% Sonograms
%--------------------------------------------------------------------------
spm_figure('GetWin','Figure 1');
clf, colormap('pink')

subplot(3,2,1)
spm_DEM_play_song(DEMc.qU ,N*dt);
title('percept (right click on image)','Fontsize',16)

subplot(3,2,3)
spm_DEM_play_song(DEMa.qU,N*dt);
title('no structural priors','Fontsize',16)

subplot(3,2,5)
spm_DEM_play_song(DEMb.qU,N*dt);
title('no dynamical priors','Fontsize',16)

% LFPs
%--------------------------------------------------------------------------
subplot(3,2,2)
spm_DEM_EEG(DEMc,dt,[1 2],1);
title('LFP','Fontsize',16)

subplot(3,2,4)
spm_DEM_EEG(DEMa,dt,[1 2],1);
title('LFP','Fontsize',16)

subplot(3,2,6)
spm_DEM_EEG(DEMb,dt,[1 2],1);
title('LFP','Fontsize',16)
drawnow, disp(' '),disp('Click sonograms to play songs'),disp(' ')


%########################################################################
%
%   - PPGI Toolbox -
%   A MATLAB toolbox for Photoplethysmography Imaging (PPGI)
%
% Author   : Christian S. Pilz
% Company  : The Nature of Space of Time
% Date     : 07.05.2019
%
% Contact  : cpi@partofthestars.com
% Web Page : www.partofthestars.com
%
% Version  : beta0.1
%
%########################################################################
%
%	bandpass_filter.m:
%
% Description:
%
%   A  MATLAB class to bandpass filter signals
%

classdef bandpass_filter
    properties
        fs_;
        low_;
        high_;
        low_a_;
        low_b_;
        high_a_;
        high_b_;
    end

   methods

       function obj = bandpass_filter(fs,low,high)

          if nargin > 0
             if isnumeric(fs)
                obj.fs_ = fs;
                obj.low_ = high;
                obj.high_ = low;

                fNorm = obj.low_ / (obj.fs_/2);
                [obj.low_b_,obj.low_a_] = butter(3, fNorm, 'low');

                fNorm = obj.high_ / (obj.fs_/2);
                [obj.high_b_,obj.high_a_] = butter(3, fNorm, 'high');
             else
                error('fs must be numeric')
             end
          end

       end

       function signal_f = get(obj,signal)
           signal_f = filtfilt(obj.low_b_, obj.low_a_, signal);
           signal_f = filtfilt(obj.high_b_, obj.high_a_, signal_f);
       end
   end
end


%+========================================================================+
%|                                                                        |
%|            This script uses the GYPSILAB toolbox for Matlab            |
%|                                                                        |
%| COPYRIGHT : Matthieu Aussal (c) 2017-2018.                             |
%| PROPERTY  : Centre de Mathematiques Appliquees, Ecole polytechnique,   |
%| route de Saclay, 91128 Palaiseau, France. All rights reserved.         |
%| LICENCE   : This program is free software, distributed in the hope that|
%| it will be useful, but WITHOUT ANY WARRANTY. Natively, you can use,    |
%| redistribute and/or modify it under the terms of the GNU General Public|
%| License, as published by the Free Software Foundation (version 3 or    |
%| later,  http://www.gnu.org/licenses). For private use, dual licencing  |
%| is available, please contact us to activate a "pay for remove" option. |
%| CONTACT   : matthieu.aussal@polytechnique.edu                          |
%|             francois.alouges@polytechnique.edu                         |
%| WEBSITE   : www.cmap.polytechnique.fr/~aussal/gypsilab                 |
%|                                                                        |
%| Please acknowledge the gypsilab toolbox in programs or publications in |
%| which you use it.                                                      |
%|________________________________________________________________________|
%|   '&`   |                                                              |
%|    #    |   FILE       : nrtDomRegularize2D.m                          |
%|    #    |   VERSION    : 0.50                                          |
%|   _#_   |   AUTHOR(S)  : Matthieu Aussal                               |
%|  ( # )  |   CREATION   : 25.11.2018                                    |
%|  / 0 \  |   LAST MODIF : 25.11.2018                                    |
%| ( === ) |   SYNOPSIS   : Singular kernel regularization (in debug mode)|
%|  `---'  |                                                              |
%+========================================================================+

% Cleaning
clear all
close all
clc

% Gypsilab path
run('../../addpathGypsilab.m')

% Parameters
N   = 1e2;
gss = 3;

% Spherical mesh
circle = mshCircle(N,1);

% Square mesh
square = mshSquare(2*N,[3 3]);

% Graphical representation
figure
plot(circle)
hold on
plot(square,'w')
axis equal
alpha(0.5)

% Domain
sigma = dom(circle,gss);

% Finite elements
u = fem(circle,'P0');
v = fem(circle,'P1');

% Gren kernel
Gxy      = @(X,Y) femGreenKernel(X,Y,'[log(r)]',[]);
dyGxy{1} = @(X,Y) femGreenKernel(X,Y,'grady[log(r)]1',[]);
dyGxy{2} = @(X,Y) femGreenKernel(X,Y,'grady[log(r)]2',[]);
dyGxy{3} = @(X,Y) femGreenKernel(X,Y,'grady[log(r)]3',[]);

% Single radiation P0
M  = integral(square.vtx,sigma,Gxy,u);
Mr = regularize(square.vtx,sigma,'[log(r)]',u);
norm(M+Mr,'inf')

% Double radiation P0
M  = integral(square.vtx,sigma,dyGxy,ntimes(u));
Mr = regularize(square.vtx,sigma,'grady[log(r)]',ntimes(u));
norm(M+Mr,'inf')

% Single radiation P1
M  = integral(square.vtx,sigma,Gxy,v);
Mr = regularize(square.vtx,sigma,'[log(r)]',v);
norm(M+Mr,'inf')

% Single layer P0
M  = integral(sigma,sigma,u,Gxy,u);
Mr = regularize(sigma,sigma,u,'[log(r)]',u);
norm(M+Mr,'inf')

% Double layer P0
M  = integral(sigma,sigma,u,dyGxy,ntimes(u));
Mr = regularize(sigma,sigma,u,'grady[log(r)]',ntimes(u));
norm(M+Mr,'inf')

% Single layer P1
M  = integral(sigma,sigma,u,Gxy,v);
Mr = regularize(sigma,sigma,u,'[log(r)]',v);
norm(M+Mr,'inf')

% Hypersingular P1
M  = integral(sigma,sigma,ntimes(u),Gxy,ntimes(v));
Mr = regularize(sigma,sigma,ntimes(u),'[log(r)]',ntimes(v));
norm(M+Mr,'inf')

M  = integral(sigma,sigma,nxgrad(u),Gxy,nxgrad(v));
Mr = regularize(sigma,sigma,nxgrad(u),'[log(r)]',nxgrad(v));
norm(M+Mr,'inf')

disp('~~> Michto gypsilab !')


function [Population,FrontNo,d2] = EnvironmentalSelection(Population,RPSet,N)
% The environmental selection of RPD-NSGA-II

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    %% Normalization
    PopObj = Population.objs;
    Fmin   = min(PopObj,[],1);
    Fmax   = max(PopObj,[],1);
    PopObj = (PopObj-repmat(Fmin,size(PopObj,1),1))./repmat(Fmax-Fmin,size(PopObj,1),1);

    %% Association
    normP   = sqrt(sum(PopObj.^2,2));
    Cosine  = 1 - pdist2(PopObj,RPSet,'cosine');
    d1      = repmat(normP,1,size(RPSet,1)).*Cosine;
    d2      = repmat(normP,1,size(RPSet,1)).*sqrt(1-Cosine.^2);
    [d2,RP] = min(d2,[],2);
    d1      = d1((1:length(RP))'+(RP-1)*length(RP));

    %% Favor extreme solutions
    ND              = find(NDSort(PopObj,1)==1);
    [~,Extreme]     = max(PopObj(ND,:),[],1);
    d1(ND(Extreme)) = 0;
    d2(ND(Extreme)) = 0;

    %% Non-RPD-dominated sorting
    [FrontNo,MaxFNo] = NRPDDSort(PopObj,d1,d2,RP,N);
    Next = FrontNo < MaxFNo;

    %% Select the solutions in the last front
    Last     = find(FrontNo==MaxFNo);
    [~,Rank] = sort(d2(Last));
    Next(Last(Rank(1:N-sum(Next)))) = true;

    %% Population for next generation
    Population = Population(Next);
    FrontNo    = FrontNo(Next);
    d2         = d2(Next);
end

function [FrontNo,MaxFNo] = NRPDDSort(PopObj,d1,d2,RP,nSort)
% Non-RPD-dominated sorting (based on deductive sort)

    [N,M]   = size(PopObj);
    FrontNo = inf(1,N);
    MaxFNo  = 0;
    while sum(FrontNo<inf) < min(nSort,N)
        MaxFNo = MaxFNo + 1;
        Sorted = FrontNo ~= inf;
        D      = Sorted;
        for i = 1 : N
            if ~D(i)
                for j = i+1 : N
                    if ~D(j)
                        domi = 0;
                        for m = 1 : M
                            if PopObj(i,m) < PopObj(j,m)
                                if domi == -1
                                    domi = 0;
                                    break;
                                else
                                    domi = 1;
                                end
                            elseif PopObj(i,m) > PopObj(j,m)
                                if domi == 1
                                    domi = 0;
                                    break;
                                else
                                    domi = -1;
                                end
                            end
                        end
                        % The definition of dominance is modified here
                        % since the one in the original paper is
                        % questionable
                        if domi == 0 && RP(i)==RP(j)
                            if d1(i)+5*d2(i) < d1(j)+5*d2(j)
                            	domi = 1;
                            elseif d1(i)+5*d2(i) > d1(j)+5*d2(j)
                            	domi = -1;
                            end
                        end
                        if domi == 1
                            D(j) = true;
                        elseif domi == -1
                            D(i) = true;
                            break;
                        end
                    end
                end
                if ~D(i)
                    FrontNo(i) = MaxFNo;
                end
            end
        end
    end
end


function out = forces_moments_wing(x, delta, wind, ~, p_drone, p_physics)

% FORCES_MOMENTS - Computes the forces and moments acting on the UAV.
%
% Inputs:
%   x     - state variables
%   delta - actuators values (angles,...)
%   wind  - wind parameters
%   P     - general parameters
% Outputs:
%   out
%       F     - forces
%       M     - moments
%       Va    - airspeed
%       alpha - angle of attack
%       beta  - sideslip angle
%       wind  - wind vector in the inertial frame
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Variables and Inputs
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% UAV velocity wrt inertial frame in body frame
v_xyz      = x(4:6);

% Euler angles
phi         = x(7);
theta       = x(8);
psi         = x(9);

% Rotation rates
p           = x(10);
q           = x(11);
r           = x(12);

% Actuators fixed-wing
de = delta(1); % delta elevator
da = delta(2); % delta aileron
dr = delta(3); % delta rudder
dt = delta(4); % delta thrust

Rbi = Rb2i(phi,theta,psi);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Wind computation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

ws_ned  = wind(1:3);  % steady wind in NED frame
wg_xyz  = wind(4:6);  % gusts along body xyz axis

% Gust in NED frame = Rib * gust in Body frame
wg_ned = Rbi * wg_xyz;

% Wind in NED = steady in NED + gust in NED
w_ned = ws_ned + wg_ned;
wn = w_ned(1);
we = w_ned(2);
wd = w_ned(3);

%Steady wind in body (xyz) frame
Rib = Rbi';
ws_xyz = Rib * ws_ned;

% Wind in body frame
w_xyz = ws_xyz + wg_xyz;

% Compute air data wrt the inertial frame, in the body frame
va_xyz = v_xyz - w_xyz;
vax = va_xyz(1);
vay = va_xyz(2);
vaz = va_xyz(3);

% Airspeed norm (=V_inifity)
Va = norm(va_xyz);

if vax ~= 0
    alpha = atan2(vaz, vax);
else
    alpha = 0;
end

if Va ~=0
    beta = asin(vay / Va);
else
    beta = 0;
end

%   Relabel
ca = cos(alpha);
sa = sin(alpha);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%     Compute forces on fixed wing
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%   Aerodynamic coefficients in function of alpha
%       Lift and Drag Coefficients
CL = p_drone.CL0 + p_drone.CL_alpha * alpha;
CD = p_drone.CD0 + p_drone.CD_alpha * alpha;

%       Lift and Drag expressed in body frame
Cx     = - CD * ca       + CL * sa;
Cx_q   = - p_drone.CD_q * ca   + p_drone.CL_q  * sa;
Cx_de  = - p_drone.CD_de * ca  + p_drone.CL_de * sa;
Cz     = - CD * sa       - CL * ca;
Cz_q   = - p_drone.CD_q  * sa  - p_drone.CL_q  * ca;
Cz_de  = - p_drone.CD_de * sa  - p_drone.CL_de * ca;

% Weight
weight = p_drone.mass * p_physics.gravity * [-sin(theta);...
    cos(theta) * sin(phi);...
    cos(theta) * cos(phi)];

% Aerodynamic forces
p_dyn = 0.5 * p_physics.rho * Va^2;

if Va ~= 0
    kc = 0.5*p_drone.c/Va;
    kb = 0.5*p_drone.b/Va;
else
    kc = 0;
    kb = 0;
end

f_drag = p_dyn * p_drone.S_wing * ...
    [Cx + Cx_q*kc*q + Cx_de*de; ...
    p_drone.CY0 + p_drone.CY_beta*beta + p_drone.CY_p*kb*p + p_drone.CY_r*kb*r + p_drone.CY_da*da + p_drone.CY_dr*dr;...
    Cz + Cz_q*kc*q + Cz_de*de];

% Thrust force
f_thrust = 0.5*p_physics.rho*p_drone.S_prop*p_drone.C_prop*...
    [(p_drone.k_motor*dt)^2-Va^2; 0; 0];

% Total force = Weight + Aerodynamic forces + Thrust force
f_tot = weight + f_drag + f_thrust;

% Compute torques on drone
torque_aerodyn = p_dyn * p_drone.S_wing * ...
    [p_drone.b*(p_drone.Cl0 + p_drone.Cl_beta*beta + p_drone.Cl_p*kb*p + p_drone.Cl_r*kb*r + p_drone.Cl_da*da + p_drone.Cl_dr*dr);...
    p_drone.c*(p_drone.Cm0 + p_drone.Cm_alpha*alpha + p_drone.Cm_q*kc*q + p_drone.Cm_de*de);...
    p_drone.b*(p_drone.Cn0 + p_drone.Cn_beta*beta + p_drone.Cn_p*kb*p + p_drone.Cn_r*kb*r + p_drone.Cn_da*da + p_drone.Cn_dr*dr)];

% Thrust torque
%   Relabel thrust coefficients
torque_thrust = [-p_drone.k_TP*(p_drone.k_omega*dt)^2; 0; 0];

% Total torque
torque_tot = torque_aerodyn + torque_thrust;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%     Create output
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

out = [f_tot; torque_tot; Va; alpha; beta; wn; we; wd];

end


function pde = elli3DcircIntf3HM(am,ap,bm,bp,kappa,r1,r2,n1,n2)
%% USAGE: polynomial solution for Poisson equation
%  Last Modified: 02/21/2020 by Xu Zhang

%% PDE Structure
pde = struct('intf',@intf,...
    'exactu1',@exactu1,'exactu2',@exactu2,'exactu3',@exactu3,...
    'um1',@um1,'um2',@um2,'um3',@um3,'up1',@up1,'up2',@up2,'up3',@up3,...
    'Dxu',@Dxu,'Dxum',@Dxum,'Dxup',@Dxup,'Dyu',@Dyu,...
    'Dyum',@Dyum,'Dyup',@Dyup,'Dzu',@Dzu,'Dzum',@Dzum,'Dzup',@Dzup,...
    'f1',@f1,'f2',@f2,'f3',@f3,...
    'fm1',@fm1,'fm2',@fm2,'fm3',@fm3,...
    'fp1',@fp1,'fp2',@fp2,'fp3',@fp3,...
    'A',@A,'Am',@Am,'Ap',@Ap,'one',@one,...
    'B',@B,'Bm',@Bm,'Bp',@Bp);

pde.am = am;
pde.ap = ap;
pde.bm = bm;
pde.bp = bp;
pde.kappa = kappa;
%% interface function
    function u = intf(x,y,z)
        u = (x.^2 + y.^2 + z.^2).^(1/2)/r1-1;
    end

%% exact solution
    function u = exactu1(x,y,z)
        u = um1(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = up1(x(id),y(id),z(id));
    end
    function u = exactu2(x,y,z)
        u = um2(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = up2(x(id),y(id),z(id));
    end
    function u = exactu3(x,y,z)
        u = um3(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = up3(x(id),y(id),z(id));
    end
    function u = um1(x,y,z)
        u = (x + n1*uker1(x,y,z).*(y-z))/am;
    end
    function u = um2(x,y,z)
        u = (y + n1*uker1(x,y,z).*(z-x))/am;
    end
    function u = um3(x,y,z)
        u = (z + n1*uker1(x,y,z).*(x-y))/am;
    end
    function u = up1(x,y,z)
        u = (x + n2*uker1(x,y,z).*uker2(x,y,z).*(y-z))/ap;
    end
    function u = up2(x,y,z)
        u = (y + n2*uker1(x,y,z).*uker2(x,y,z).*(z-x))/ap;
    end
    function u = up3(x,y,z)
        u = (z + n2*uker1(x,y,z).*uker2(x,y,z).*(x-y))/ap;
    end
    function u = uker1(x,y,z)
        u = r1^2 - (x.^2 + y.^2 + z.^2);
    end
    function u = uker2(x,y,z)
        u = r2^2 - (x.^2 + y.^2 + z.^2);
    end
%% Boundary Function
    function u = gD1(x,y,z)
        u = exactu1(x,y,z);
    end
    function u = gD2(x,y,z)
        u = exactu2(x,y,z);
    end
    function u = gD3(x,y,z)
        u = exactu3(x,y,z);
    end
%% Derivative of the exact solution
    function u = Dxu(x,y,z)
        u = Dxum(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Dxup(x(id),y(id),z(id));
    end
    function u = Dyu(x,y,z)
        u = Dyum(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Dyup(x(id),y(id),z(id));
    end
    function u = Dzu(x,y,z)
        u = Dzum(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Dzup(x(id),y(id),z(id));
    end
    function u = Dxum(x,y,z)
        u = -2*n1/am*(x.*y+x.*z-y.^2-z.^2 + uker1(x,y,z));
    end
    function u = Dyum(x,y,z)
        u = -2*n1/am*(y.*z+x.*y-z.^2-x.^2 + uker1(x,y,z));
    end
    function u = Dzum(x,y,z)
        u = -2*n1/am*(x.*z+y.*z-x.^2-y.^2 + uker1(x,y,z));
    end
    function u = Dxup(x,y,z)
        u = -2*n2*uker2(x,y,z)./ap.*(x.*y+x.*z-y.^2-z.^2 + uker1(x,y,z)) - ...
            2*n2*uker1(x,y,z).*(x.*y+x.*z - y.^2-z.^2)/ap;
    end
    function u = Dyup(x,y,z)
        u = -2*n2*uker2(x,y,z)./ap.*(y.*z+x.*y-z.^2-x.^2 + uker1(x,y,z)) - ...
            2*n2*uker1(x,y,z).*(y.*z+x.*y - x.^2-z.^2)/ap;
    end
    function u = Dzup(x,y,z)
        u = -2*n2*uker2(x,y,z)./ap.*(x.*z+y.*z-x.^2-y.^2 + uker1(x,y,z)) - ...
            2*n2*uker1(x,y,z).*(x.*z+y.*z - x.^2-y.^2)/ap;
    end

%% right hand side function
    function u = f1(x,y,z)
        u = fm1(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = fp1(x(id),y(id),z(id));
    end
    function u = f2(x,y,z)
        u = fm2(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = fp2(x(id),y(id),z(id));
    end
    function u = f3(x,y,z)
        u = fm3(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = fp3(x(id),y(id),z(id));
    end

    function u = fm1(x,y,z)
        u = -10*n1*(z-y)- kappa*bm*um1(x,y,z);
    end
    function u = fm2(x,y,z)
        u = -10*n1*(x-z) - kappa*bm*um2(x,y,z);
    end
    function u = fm3(x,y,z)
        u = -10*n1*(y-x) - kappa*bm*um3(x,y,z);
    end
    function u = fp1(x,y,z)
        u = -10*n2*uker2(x,y,z).*(z-y) +8*n2*(z.^3-y.^3+z.*y.^2+z.*x.^2-y.*x.^2-y.*z.^2) -...
             10*n2*uker1(x,y,z).*(z-y) - kappa*bp*up1(x,y,z);
    end
    function u = fp2(x,y,z)
        u = -10*n2*uker2(x,y,z).*(x-z) +8*n2*(x.^3-z.^3+x.*z.^2+x.*y.^2-z.*y.^2-z.*x.^2) -...
             10*n2*uker1(x,y,z).*(x-z) - kappa*bp*up2(x,y,z);
    end
    function u = fp3(x,y,z)
        u = -10*n2*uker2(x,y,z).*(y-x) +8*n2*(y.^3-x.^3+y.*x.^2+y.*z.^2-x.*z.^2-x.*y.^2) -...
             10*n2*uker1(x,y,z).*(y-x) - kappa*bp*up3(x,y,z);
    end

%% Diffusion coefficient function
    function u = A(x,y,z)
        u = Am(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Ap(x(id),y(id),z(id));
    end
    function u = Am(x,y,z)
        u = am*ones(size(x));
    end
    function u = Ap(x,y,z)
        u = ap*ones(size(x));
    end

%% Mass coefficient function
    function u = B(x,y,z)
        u = Bm(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Bp(x(id),y(id),z(id));
    end
    function u = Bm(x,y,z)
        u = bm*ones(size(x));
    end
    function u = Bp(x,y,z)
        u = bp*ones(size(x));
    end

%% Other function
    function u = one(x,y,z)
        u = ones(size(x));
    end
end


function mdf = calcMDF(mori,varargin)
% computes an MDF from individuel orientations or misorientations
%
% The function *calcMDF* applies one of the following algorithms to compute
% an MDF from a list of orientations.
%
% # direct kernel density estimation
% # kernel density estimation via Fourier series
% # Bingham estimation
%
% Syntax
%
%   % use kernel density estimation with a 10 degree kernel
%   mori = grains.boundary.misorientation
%   mdf = calcMDF(mori,'halfwidth',10*degree)
%
%   % compute an uncorrelated MDF
%   mdf = calcMDF(grains('phase1').meanorientation)
%
%   % use grain area as weights for the orientations
%   mdf = calcMDF(grains('phase1').meanOrientation,'weights',grains('phase1').diameter)
%
%   % use a specific kernel
%   psi = SO3AbelPoissonKernel('halfwidth',10*degree)
%   mdf = calcMDF(mori,'kernel',psi)
%
%   % compute the MDF as a Fourier series of order 16
%   mdf = calcMDF(mori,'order',16)
%
% Input
%  ori  - @orientation
%  mori - misorientation
%
% Output
%  mdf - @SO3Fun
%
% Options
%  weights    - list of weights for the orientations
%  halfwidth  - halfwidth of the kernel function
%  resolution - resolution of the grid where the MDF is approximated
%  kernel     - @SO3Kernel function (default -- SO3 de la Valee Poussin kernel)
%  order      - order up to which Fourier coefficients are calculated
%
% Flags
%  silent           - no output
%  exact            - no approximation to a corser grid
%  Fourier          - force Fourier method
%  Bingham          - model bingham mdf
%  noFourier        - no Fourier method
%
% See also
% orientation/calcFourierMDF orientation/calcKernelMDF orientation/calcBinghamMDF ebsd_demo EBSD2mdf EBSDSimulation_demo

warning('The command calcODF is depreciated! Please use calcDensity instead.')

% if orientations have been specified
if isa(mori.SS,'specimenSymmetry')

  % compute an ODF first
  odf1 = calcFourierODF(mori,varargin{:});

  if nargin > 1 && isa(varargin{1},'orientation')

    % maybe a second ODF is needed
    odf2 = calcFourierODF(varargin{1},varargin{:});

    % compute the MDF
    mdf = calcMDF(odf1,odf2);

  else

    % compute the MDF
    mdf = calcMDF(odf1);

  end

  return
end

if check_option(varargin,'antipoal') && mori.CS == mori.SS
  mori = [mori(:);inv(mori(:))];
end

mdf = calcODF(mori,'halfwidth',7.5*degree,varargin{:});


function LR_chi2=drxlr_get_lrt(y,mu)
% compute the likelihood ratio test
% written by Issam El Naqa
%
% Copyright 2010, Joseph O. Deasy, on behalf of the DREES development team.
%
% This file is part of the Dose Response Explorer System (DREES).
%
% DREES development has been led by:  Issam El Naqa, Aditya Apte, Gita Suneja, and Joseph O. Deasy.
%
% DREES has been financially supported by the US National Institutes of Health under multiple grants.
%
% DREES is distributed under the terms of the Lesser GNU Public License.
%
%     This version of DREES 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.
%
% DREES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with DREES.  If not, see <http://www.gnu.org/licenses/>.

seps = sqrt(eps);
n=length(y);
n1=sum(y); n0=sum(1-y);
Ls=n1*log(n1)+n0*log(n0)-n*log(n); % saturated
L=sum(y.*log(mu+seps)+(1-y).*log(1-mu+seps)); % fitted
LR_chi2=2*(L-Ls); % follows centered chi2 stats
return


function [ ap, ipvt, info ] = chpfa ( ap, n )

%*****************************************************************************80
%
%% CHPFA factors a complex hermitian packed matrix.
%
%  Discussion:
%
%    To solve A*X = B, follow CHPFA by CHPSL.
%
%    To compute inverse(A)*C, follow CHPFA by CHPSL.
%
%    To compute determinant(A), follow CHPFA by CHPDI.
%
%    To compute inertia(A), follow CHPFA by CHPDI.
%
%    To compute inverse(A), follow CHPFA by CHPDI.
%
%  Packed storage:
%
%    The following program segment will pack the upper
%    triangle of a hermitian matrix.
%
%      k = 0
%      do j = 1, n
%        do i = 1, j
%          k = k + 1
%          ap(k) = a(i,j)
%        end
%      end
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 May 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Jim Bunch, Cleve Moler, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979,
%    ISBN13: 978-0-898711-72-1,
%    LC: QA214.L56.
%
%  Parameters:
%
%    Input, complex AP(N*(N+1)/2); the packed form
%    of a hermitian matrix.  The columns of the upper triangle are
%    stored sequentially in a one-dimensional array.
%
%    Input, integer N, the order of the matrix.
%
%    Output, complex AP(N*(N+1)/2); a block diagonal matrix and the
%    multipliers which were used to obtain it stored in packed form.
%    The factorization can be written A = U*D*hermitian(U) where U is a
%    product of permutation and unit upper triangular matrices, hermitian(U)
%    is the conjugate transpose of U, and D is block diagonal with 1 by 1
%    and 2 by 2 blocks.
%
%    Output, integer IPVT(N), the pivot indices.
%
%    Output, integer INFO.
%    0, normal value.
%    K, if the K-th pivot block is singular.  This is not an error condition
%    for this subroutine, but it does indicate that CHPSL or CHPDI may divide
%    by zero if called.
%

%
%  Initialize.
%
%  ALPHA is used in choosing pivot block size.
%
  alpha = ( 1.0 + sqrt ( 17.0 ) ) / 8.0;

  info = 0;
%
%  Main loop on K, which goes from N to 1.
%
  k = n;
  ik = ( n * ( n - 1 ) ) / 2;

  while ( 1 )
%
%  Leave the loop if K = 0 or K = 1.
%
    if ( k == 0 )
      break
    end

    if ( k == 1 )
      ipvt(1) = 1;
      if ( cabs1 ( ap(1) ) == 0.0 )
        info = 1;
      end
      break
    end
%
%  This section of code determines the kind of
%  elimination to be performed.  When it is completed,
%  KSTEP will be set to the size of the pivot block, and
%  SWAP will be set to TRUE if an interchange is
%  required.
%
    km1 = k - 1;
    kk = ik + k;
    absakk = cabs1 ( ap(kk) );
%
%  Determine the largest off-diagonal element in column K.
%
    imax = icamax ( k-1, ap(ik+1:ik+k-1), 1 );
    imk = ik + imax;
    colmax = cabs1 ( ap(imk) );

    if ( alpha * colmax <= absakk )

      kstep = 1;
      swap = 0;
%
%  Determine the largest off-diagonal element in row IMAX.
%
    else

      rowmax = 0.0;
      im = ( imax * ( imax - 1 ) ) / 2;
      imj = im + 2 * imax;

      for j = imax + 1 : k
        rowmax = max ( rowmax, cabs1 ( ap(imj) ) );
        imj = imj + j;
      end

      if ( imax ~= 1 )
        jmax = icamax ( imax-1, ap(im+1:im+imax-1), 1 );
        jmim = jmax + im;
        rowmax = max ( rowmax, cabs1 ( ap(jmim) ) );
      end

      imim = imax + im;

      if ( alpha * rowmax <= cabs1 ( ap(imim) ) )
        kstep = 1;
        swap = 1;
      elseif ( alpha * colmax * ( colmax / rowmax ) <= absakk )
        kstep = 1;
        swap = 0;
      else
        kstep = 2;
        swap = ( imax ~= km1 );
      end

    end
%
%  Column K is zero.  Set INFO and iterate the loop.
%
    if ( max ( absakk, colmax ) == 0.0 )
      ipvt(k) = k;
      info = k;
      ik = ik - ( k - 1 );
      if ( kstep == 2 )
        ik = ik - ( k - 2 );
      end
      k = k - kstep;
      continue
    end

    if ( kstep ~= 2 )
%
%  1 x 1 pivot block.
%
      if ( swap )

        temp             = ap(im+1:im+imax);
        ap(im+1:im+imax) = ap(ik+1:ik+imax);
        ap(ik+1:ik+imax) = temp;

        imj = ik + imax;

        for jj = imax : k
          j = k + imax - jj;
          jk = ik + j;
          t       = conj ( ap(jk) );
          ap(jk)  = conj ( ap(imj) );
          ap(imj) = t;
          imj = imj - ( j - 1 );
        end

      end
%
%  Perform the elimination.
%
      ij = ik - ( k - 1 );
      for jj = 1 : km1
        j = k - jj;
        jk = ik + j;
        mulk = -ap(jk) / ap(kk);
        t = conj ( mulk );
        ap(ij+1:ij+j) = ap(ij+1:ij+j) + t * ap(ik+1:ik+j);
        ijj = ij + j;
        ap(ijj) = real ( ap(ijj) );
        ap(jk) = mulk;
        ij = ij - ( j - 1 );
      end
%
%  Set the pivot array.
%
      if ( swap )
        ipvt(k) = imax;
      else
        ipvt(k) = k;
      end
%
%  2 x 2 pivot block.
%
    else

      km1k = ik + k - 1;
      ikm1 = ik - ( k - 1 );

      if ( swap )

        temp                 = ap(im+1:im+imax);
        ap(im+1:im+imax)     = ap(ikm1+1:ikm1+imax);
        ap(ikm1+1:ikm1+imax) = temp;

        imj = ikm1 + imax;

        for jj = imax : km1
          j = km1 + imax - jj;
          jkm1 = ikm1 + j;
          t        = conj ( ap(jkm1) );
          ap(jkm1) = conj ( ap(imj) );
          ap(imj)  = t;
          imj = imj - ( j - 1 );
        end

        t        = ap(km1k);
        ap(km1k) = ap(imk);
        ap(imk)  = t;

      end
%
%  Perform the elimination.
%
      km2 = k - 2;

      if ( km2 ~= 0 )

        ak = ap(kk) / ap(km1k);
        km1km1 = ikm1 + k - 1;
        akm1 = ap(km1km1) / conj ( ap(km1k) );
        denom = 1.0 - ak * akm1;
        ij = ik - ( k - 1 ) - ( k - 2 );

        for jj = 1 : km2
          j = km1 - jj;
          jk = ik + j;
          bk = ap(jk) / ap(km1k);
          jkm1 = ikm1 + j;
          bkm1 = ap(jkm1) / conj ( ap(km1k) );
          mulk = ( akm1 * bk - bkm1 ) / denom;
          mulkm1 = ( ak * bkm1 - bk ) / denom;
          t = conj ( mulk );
          ap(ij+1:ij+j) = ap(ij+1:ij+j) + t * ap(ik+1:ik+j);
          t = conj ( mulkm1 );
          ap(ij+1:ij+j) = ap(ij+1:ij+j) + t * ap(ikm1+1:ikm1+j);
          ap(jk) = mulk;
          ap(jkm1) = mulkm1;
          ijj = ij + j;
          ap(ijj) = real ( ap(ijj) );
          ij = ij - ( j - 1 );
        end

      end
%
%  Set the pivot array.
%
      if ( swap )
        ipvt(k) = -imax;
      else
        ipvt(k) = 1 - k;
      end

      ipvt(k-1) = ipvt(k);

    end

    ik = ik - ( k - 1 );
    if ( kstep == 2 )
      ik = ik - ( k - 2 );
    end

    k = k - kstep;

  end

  return
end


function S=test(x)
% Edgar & Himmelblau, 1988
% x0 = [1, 2]'
% xo = [0, 0]'
% S(xo) = 0

S=4*x(1).^2-2.*x(1).*x(2)+x(2).^2;


function vardist = vardistCreate(X, Q, type, constraint)

% VARDISTCREATE description.

% VARGPLVM

%
% creates the structure of the variational distirbution over the latent
% values in the GP-LVM
%
% The variational distribution is assumed to be factorized over the
% the latent variables. Each factor each a Gaussain N(x_n|mu_n,S_n)
% with a diagonal covariance matrix
%
% The structure of the vardist is similar to the structure of a kernel

if nargin == 3
    constraint = optimiDefaultConstraint('positive');
else
    constraint = 'identity';
end

vardist.type = 'vardist';
vardist.vartype = type;

vardist.numData = size(X,1);
vardist.latentDimension = Q;
vardist.nParams = 2*vardist.numData*vardist.latentDimension;
%  number of training points
N = size(X,1);

vardist.transforms(1).index = [(N*Q+1):vardist.nParams];
vardist.transforms(1).type = constraint;

% initialize the parameters
vardist.means  = X;
vardist.covars = 0.1*ones(N,Q) + 0.001*randn(N,Q);
vardist.covars(vardist.covars<0.05) = 0.05;
%vardist.covars = (eps^2)*ones(size(vardist.covars));
%vardist.means = randn(N,Q);
%pmeans = randn(Q,N);
%pcovars = randn(Q,N);
%params = [pmeans(:)' pcovars(:)'];
%vardist = vardistExpandParam(vardist, params);


function [S2G, r]= refine(S2G)
% refine S2Grid
%
% Input
%  S2G - @S2Grid
%
% Output
%  S2G - @S2Grid with half the resolution

S2G.opt.resolution = S2G.opt.resolution / 2;
S2G.thetaGrid = refine(S2G.thetaGrid);
for i=1:length(S2G.rhoGrid)
  S2G.rhoGrid(2*i-1) = refine(S2G.rhoGrid(i));
end

theta = double(S2G.thetaGrid);
for i = 2:2:GridLength(S2G.thetaGrid)

  % construct full circle
  nrho= max(round(sin(theta(i)) * 2*pi/S2G.res),1);
  rho = (0:nrho-1)*2*pi/nrho;

  % take only those that are close to existing ones
  d = min(dist_outer(S2G.rhoGrid(i-1),rho));
  if i+1 <= length(theta)
    d = min(d,min(dist_outer(S2G.rhoGrid(i+1),rho)));
  end

  rho = rho(sin(theta(i-1))*d < S2G.res*1.5);
  S2G.rhoGrid(i) = S1Grid(rho,...
    getMin(S2G.rhoGrid(i-1)),getMax(S2G.rhoGrid(i-1)),check_option(S2G.rhoGrid(i-1)));

end

[S2G.x,S2G.y,S2G.z] = double(calcGrid(S2G.thetaGrid,S2G.rhoGrid));

end


%% Anaylsis_MI
clear all; clc; close all;
%% initialization
DATADIR = 'WHERE\IS\DATA';
%% MI
MIDATA = 'EEG_MI.mat';
STRUCTINFO = {'EEG_MI_train', 'EEG_MI_test'};
SESSIONS = {'session1', 'session2'};
TOTAL_SUBJECTS = 54;
FS=100;

%% PERFORMANCE PARAMETERS
params = { 'task',{'mi_off','mi_on'}; ...
    'channel_index', [8:11 13:15 18:21 33:41]; ...
    'band', [8 30]; ...
    'time_interval', [1000 3500]; ...
    'CSPFilter', 2; ...
    };

% for MI_cv
Niteration = 10;
% for CSSP
tau=[0.01:0.01:0.15]*1000;
% for FBCSP
filterbank = [4 8;8 12;12 16;16 20;20 24;24 28;28 32;32 36;36 40];
NUMfeat = 4;
% for BSSFO
bssfo_param = {'init_band', [4 40]; ...
    'numBands', 30; ...
    'numIteration', 10; ...
    'mu_band', [7 15]; ...
    'beta_band', [14 30]; ...
    };
%% validation
for sessNum = 1:length(SESSIONS)
    session = SESSIONS{sessNum};
    fprintf('\n%s validation\n',session);
    for subNum = 1:TOTAL_SUBJECTS
        subject = sprintf('s%d',subNum);
        fprintf('LOAD %s ...\n',subject);

        data = importdata(fullfile(DATADIR,session,subject,MIDATA));

        CNT{1} = prep_resample(data.(STRUCTINFO{1}), FS,{'Nr', 0});
        CNT{2} = prep_resample(data.(STRUCTINFO{2}), FS,{'Nr', 0});

        ACC.MI_cv(subNum,sessNum) = mi_performance(CNT,params,Niteration);
        ACC.MI_off2on(subNum,sessNum) = mi_performance_off2on(CNT,params);
        ACC.MI_CSSP(subNum,sessNum) = cssp_off2on(CNT,params,tau);
        ACC.MI_FBCSP(subNum,sessNum) = fbcsp_off2on(CNT,params,filterbank,NUMfeat);
        ACC.MI_BSSFO(subNum,sessNum) = bssfo_off2on(CNT,params,bssfo_param);

        fprintf('CSP_crsval = %f\n',ACC.MI_cv(subNum,sessNum));
        fprintf('CSP = %f\n',ACC.MI_off2on(subNum,sessNum));
        fprintf('CSSP = %f\n',ACC.MI_CSSP(subNum,sessNum));
        fprintf('FBCSP = %f\n',ACC.MI_FBCSP(subNum,sessNum));
        fprintf('BSSFO = %f\n',ACC.MI_BSSFO(subNum,sessNum));
        clear CNT
    end
end


function pde = elli3DcircIntf2(am,ap,bm,bp,r,x0,y0,z0,a11,a12,a)
%% USAGE: polynomial solution for Poisson equation
%  Last Modified: 02/21/2020 by Xu Zhang

%% PDE Structure
pde = struct('intf',@intf,...
    'exactu1',@exactu1,'exactu2',@exactu2,'exactu3',@exactu3,...
    'um1',@um1,'um2',@um2,'um3',@um3,'up1',@up1,'up2',@up2,'up3',@up3,...
    'Dxu',@Dxu,'Dxum',@Dxum,'Dxup',@Dxup,'Dyu',@Dyu,...
    'Dyum',@Dyum,'Dyup',@Dyup,'Dzu',@Dzu,'Dzum',@Dzum,'Dzup',@Dzup,...
    'f1',@f1,'f2',@f2,'f3',@f3,...
    'fm1',@fm1,'fm2',@fm2,'fm3',@fm3,...
    'fp1',@fp1,'fp2',@fp2,'fp3',@fp3,...
    'A',@A,'Am',@Am,'Ap',@Ap,'one',@one,...
    'B',@B,'Bm',@Bm,'Bp',@Bp);

pde.am = am;
pde.ap = ap;
pde.bm = bm;
pde.bp = bp;
%% interface function
    function u = intf(x,y,z)
        u = ((x-x0).^2 + (y-y0).^2 + (z-z0).^2).^(1/2)/r-1;
    end

%% exact solution
    function u = exactu1(x,y,z)
        u = um1(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = up1(x(id),y(id),z(id));
    end
    function u = exactu2(x,y,z)
        u = um2(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = up2(x(id),y(id),z(id));
    end
    function u = exactu3(x,y,z)
        u = um3(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = up3(x(id),y(id),z(id));
    end
    function u = um1(x,y,z)
        u1 = uker1(x,y,z).*(x-x0);
        u2 = uker2(x,y,z);
        u = (u1 + u2)/bm;
    end
    function u = um2(x,y,z)
        u1 = uker1(x,y,z).*(y-y0);
        u2 = uker2(x,y,z);
        u = (u1 + u2)/bm;
    end
    function u = um3(x,y,z)
        u1 = uker1(x,y,z).*(z-z0);
        u2 = uker2(x,y,z);
        u = (u1 + u2)/bm;
    end
    function u = up1(x,y,z)
        u1 = uker1(x,y,z).*(x-x0);
        u2 = uker2(x,y,z);
        u = (u1 + u2)/bp;
    end
    function u = up2(x,y,z)
        u1 = uker1(x,y,z).*(y-y0);
        u2 = uker2(x,y,z);
        u = (u1 + u2)/bp;
    end
    function u = up3(x,y,z)
        u1 = uker1(x,y,z).*(z-z0);
        u2 = uker2(x,y,z);
        u = (u1 + u2)/bp;
    end
    function u = uker1(x,y,z)
        u = nthroot((x-x0).^2 + (y-y0).^2 + (z-z0).^2 - r^2,a11);
        u = u.^a12;
    end
    function u = uker2(x,y,z)
        u = ((x-x0).^2 + (y-y0).^2 + (z-z0).^2 - r^2).^a;
    end
%% Boundary Function
    function u = gD1(x,y,z)
        u = exactu1(x,y,z);
    end
    function u = gD2(x,y,z)
        u = exactu2(x,y,z);
    end
    function u = gD3(x,y,z)
        u = exactu3(x,y,z);
    end
%% Derivative of the exact solution
    function u = Dxu(x,y,z)
        u = Dxum(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Dxup(x(id),y(id),z(id));
    end
    function u = Dyu(x,y,z)
        u = Dyum(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Dyup(x(id),y(id),z(id));
    end
    function u = Dzu(x,y,z)
        u = Dzum(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Dzup(x(id),y(id),z(id));
    end
    function u = Dxum(x,y,z)
        u = (Duker(x,y,z).*(y-y0)*2 - Duker(x,y,z).*(z-z0)*2)/bm;
    end
    function u = Dyum(x,y,z)
        u = (Duker(x,y,z).*(z-z0)*2 - Duker(x,y,z).*(x-x0)*2)/bm;
    end
    function u = Dzum(x,y,z)
        u = (Duker(x,y,z).*(x-x0)*2 - Duker(x,y,z).*(y-y0)*2)/bm;
    end
    function u = Dxup(x,y,z)
        u = (Duker(x,y,z).*(y-y0)*2 - Duker(x,y,z).*(z-z0)*2)/bp;
    end
    function u = Dyup(x,y,z)
        u = (Duker(x,y,z).*(z-z0)*2 - Duker(x,y,z).*(x-x0)*2)/bp;
    end
    function u = Dzup(x,y,z)
        u = (Duker(x,y,z).*(x-x0)*2 - Duker(x,y,z).*(y-y0)*2)/bp;
    end

    function u = Duker(x,y,z)
        u = a*((x-x0).^2 + (y-y0).^2 + (z-z0).^2 - r^2).^(a-1);
    end

%% right hand side function
    function u = f1(x,y,z)
        u = fm1(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = fp1(x(id),y(id),z(id));
    end
    function u = f2(x,y,z)
        u = fm2(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = fp2(x(id),y(id),z(id));
    end
    function u = f3(x,y,z)
        u = fm3(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = fp3(x(id),y(id),z(id));
    end

    function u = fm1(x,y,z)
        xh = x-x0; yh = y-y0; zh = z-z0;
        u = (-4*Duker(x,y,z) + DDuker(x,y,z).*(xh.*(yh+zh)-yh.^2-zh.^2)) + bm*um1(x,y,z);
    end
    function u = fm2(x,y,z)
        xh = x-x0; yh = y-y0; zh = z-z0;
        u = (-4*Duker(x,y,z) + DDuker(x,y,z).*(yh.*(xh+zh)-xh.^2-zh.^2)) + bm*um2(x,y,z);
    end
    function u = fm3(x,y,z)
        xh = x-x0; yh = y-y0; zh = z-z0;
        u = (-4*Duker(x,y,z) + DDuker(x,y,z).*(zh.*(xh+yh)-xh.^2-yh.^2)) + bm*um3(x,y,z);
    end
    function u = fp1(x,y,z)
        xh = x-x0; yh = y-y0; zh = z-z0;
        u = (-4*Duker(x,y,z) + DDuker(x,y,z).*(xh.*(yh+zh)-yh.^2-zh.^2)) + bp*up1(x,y,z);
    end
    function u = fp2(x,y,z)
        xh = x-x0; yh = y-y0; zh = z-z0;
        u = (-4*Duker(x,y,z) + DDuker(x,y,z).*(yh.*(xh+zh)-xh.^2-zh.^2)) + bp*up2(x,y,z);
    end
    function u = fp3(x,y,z)
        xh = x-x0; yh = y-y0; zh = z-z0;
        u = (-4*Duker(x,y,z) + DDuker(x,y,z).*(zh.*(xh+yh)-xh.^2-yh.^2)) + bp*up3(x,y,z);
    end

    function u = DDuker(x,y,z)
        u = a*(a-1)*((x-x0).^2 + (y-y0).^2 + (z-z0).^2 - r^2).^(a-2);
    end

%% Diffusion coefficient function
    function u = A(x,y,z)
        u = Am(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Ap(x(id),y(id),z(id));
    end
    function u = Am(x,y,z)
        u = am*ones(size(x));
    end
    function u = Ap(x,y,z)
        u = ap*ones(size(x));
    end

%% Mass coefficient function
    function u = B(x,y,z)
        u = Bm(x,y,z);
        id = intf(x,y,z) > 0;
        u(id) = Bp(x(id),y(id),z(id));
    end
    function u = Bm(x,y,z)
        u = bm*ones(size(x));
    end
    function u = Bp(x,y,z)
        u = bp*ones(size(x));
    end

%% Other function
    function u = one(x,y,z)
        u = ones(size(x));
    end
end


function [Simil3]=fuzzysimil3(A,B)

PA=(A(1)+2*A(2)+2*A(3)+A(4))/6;
PB=(B(1)+2*B(2)+2*B(3)+B(4))/6;
dAB=abs(PA-PB);
Simil3=1/(1+dAB);


%% Mixture of linear regression
close all; clear
d = 1;
k = 2;
n = 500;
[X,y] = mixLinRnd(d,k,n);
plot(X,y,'.');
[label,model,llh] = mixLinReg(X, y, k);
plotClass([X;y],label);
figure
plot(llh);
[y_,z,p] = mixLinPred(model,X,y);
figure;
plotClass([X;y],label);


function [words, k] = feature_color(I, I_type, opts)
% Clusters RGB values of pixels into words of a dictionary using kmeans.

I_lin = reshape(I, size(I,1)*size(I,2), 3);

if opts.load_color_dict
    % sets color_dict
    switch I_type
        case 'rgb'
            load('dicts/rgb_dict_k150');
        case 'nrgb'
            load('dicts/nrgb_dict_k150');
        case 'opp'
            load('dicts/opp_nocut_dict_k150');
            %load('dicts/opp_dict_k150');
        case 'hsv'
            load('dicts/hsv_dict_k150');
    end
    words = vl_ikmeanspush(I_lin', color_dict);
    k = size(color_dict, 2); % number of clusters
else % generate color dictionary for the image
    error('It is recommended to load a color dictionary.');
    k = 50; % number of clusters
    [color_dict, words] = vl_ikmeans(I_lin', k); % integer k-means clustering
    %[color_dict, color_words] = vl_ikmeans(I_lin', k, 'Method', 'elkan'); % integer k-means clustering
    %save('car_color_dict', 'color_dict'); % create example color dictionary
end

words = words(:); % transpose. Using (:) instead of ' to emphasize that the words variable for each feature has the same format

% Visualize color clustering
% color_dict = uint8(color_dict);
% Ic = color_dict(:,words')';
% Ic = reshape(Ic, size(I,1), size(I,2), 3);
% imshow(Ic);

% Shows that there is no indexing error
% words(1:20)
% words = reshape(words, size(I,1), size(I,2));
% image(words) % pixels in correct places, original image distinguishable
% words2 = words(:); % this reverses the above reshape...
% words2(1:20) % ... because this is equal to above words(1:20)