function CompareCloneTool(varargin)
% function CompareCloneTool(varargin)
%
% A tool that takes a list of binary images and a corresponding list of rgb
% images and then lets the user click on sectors in any image. As the user
% clicks on a sector, the best fitted ellipse for that sector will be
% shown. If the user then clicks on another sector, the corresponding
% ellipse for that sector is displayed and the growth tensor that
% corresponds to the two ellipses is then calculated and shown in another
% figure.
%
% Inputs:
%
%  'bimgfilenames' - a cell array containing the full pathnames of the
%                    binary images (usually tif no compression).
%
%  'imgfilenames' - a cell array containing the full pathnames of the
%                   rgb images.
%
% Dr. Andrew I. Hanna, CMP & JIC, 2008.

error(nargchk(0,inf,nargin));
if checkSATDir(pwd) == 0
    fprintf('You are not in a valid SectorAnalysisToolbox Project directory\n');
    return;
end
data = parseargs(varargin);

% Open, move, and get the handles from the figure file.
ad.figMain = openfig(mfilename, 'reuse');
movegui(ad.figMain, 'center');
set(ad.figMain, 'Visible', 'on');
ad.handles = guihandles(ad.figMain);
set(ad.figMain, 'Color', get(ad.handles.panelA, 'BackgroundColor'));
set(ad.figMain, 'ResizeFcn', {@doResize});

ad = setupcallbacks(ad);
ad = initadstructure(ad, data);

ad.data.uitableh = uitable('Parent', ad.handles.tablepanel);

% Remove the save icon from the toolbar
%customtoolbar(ad.figMain);
setappdata(0,'CompareCloneToolData',ad);

updateSectorInfoList();
changeSectorA(ad.handles.sectorsA);
changeSectorB(ad.handles.sectorsB);
showMeanShape();
try
    uiwait(ad.figMain);
catch
    if ishandle(ad.figMain)
        delete(ad.figMain)
    end
end
value = 0;
return;
%%
function doResize(aa, evd)
updateSectorInfoList();
return

%%
function ad = setupcallbacks(ad)
% Set all the callback functions
set(ad.handles.sectorsA, 'callback', {@changeSectorA});
set(ad.handles.sectorsB, 'callback', {@changeSectorB});
set(ad.handles.compbtn, 'callback', {@compareSectors});
set(ad.handles.addbtn, 'callback', {@addCurrGTToList});
set(ad.handles.clearallbtn, 'callback', {@clearAll});
set(ad.handles.savebtn, 'callback', {@saveInfo});
set(ad.handles.loadbtn, 'callback', {@loadInfo});
return
%%
function ad = initadstructure(ad, data)

ad.pathnames.StagedDirString =  'Staged';
ad.data.sectorA = initdata();
ad.data.sectorB = initdata();
ad.data.dx = 6;
ad.data.dy = 8;
ad.data.basegrid.x = [];
ad.data.basegrid.y = [];
ad.data.meanshape = satio_load_mean_shape;
ad.data.meanshape  = cat(1, ad.data.meanshape , ad.data.meanshape (1,:));
ad.data.D = [];
ad.data.sector_info_cell = {};
ad.handles.gtaxes = -1;
ad.handles.sectorah = -1;
ad.handles.sectorbh = -1;

ad.data.ellipvec = {};
ad.data.linwidth = 2;
ad.data.sector_files = data.bimgfilenames;
ad.data.rgb_files = data.imgfilenames;
rgbfilenames = cell(1, length(ad.data.rgb_files));
for i=1:length(ad.data.rgb_files)
   [junk, rgbfilenames{i}] = fileparts(ad.data.rgb_files{i});
end
set(ad.handles.sectorsA, 'String', rgbfilenames);
set(ad.handles.sectorsB, 'String', rgbfilenames);
return
%%
function data = initdata()
data.pathname = '';
data.filename = '';
data.bwim = [];
data.im = [];
data.sector_info = [];
data.boundaries = {};
return
%%
function s = loadShape(imfilename)
s = [];
sfilename = fileparts(imfilename);
sfilename = [sfilename, filesep, 'edge_xy.mat'];
if ~exist(sfilename, 'file')
    return
end
s = load(sfilename);
if ~isfield(s, 'E')
    return;
end
s = s.E;
s = cat(1, s, s(1,:));
return
%%
function data = loadData(imfilename, bwfilename)
wh = waitbar(0, 'Loading...');
if exist(bwfilename, 'file')
    waitbar(0.2, wh);
    bwim = imread(bwfilename);
    sectorboundaries = bwboundaries(bwim);
    waitbar(0.3, wh);
    [sector_info] = sector_im2struct(sectorboundaries, 'AIH');
    data.sector_info = sector_info;
    waitbar(0.4, wh);
    %data.L = bwlabel(data.bwim);
end
waitbar(0.5, wh);
if exist(imfilename, 'file')
    data.im = imread(imfilename);
end
data.shape = loadShape(imfilename);
delete(wh);
return
%%
function changeSectorA(popup, evd)
ad = getappdata(0, 'CompareCloneToolData');
val = get(popup, 'Value');
data = loadData(ad.data.rgb_files{val}, ad.data.sector_files{val});
ad.data.sectorA = data;
setappdata(0, 'CompareCloneToolData', ad);
updateSectorA();
return

%%
function changeSectorB(popup, evd)
ad = getappdata(0, 'CompareCloneToolData');
val = get(popup, 'Value');
str = get(popup, 'String');
data = loadData(ad.data.rgb_files{val}, ad.data.sector_files{val});
ad.data.sectorB = data;
setappdata(0, 'CompareCloneToolData', ad);
updateSectorB();
return
%%
function showMeanShape()
ad = getappdata(0, 'CompareCloneToolData');
if isempty(ad.data.meanshape)
    return;
end
S = ad.data.meanshape;
S = cat(1, S, S(1,:));
plot(ad.handles.meanshapeaxes, S(:,2), S(:,1), '-o');
plotGrid();
axis(ad.handles.meanshapeaxes, 'image', 'ij');
return
%%
function plotGrid()
ad = getappdata(0, 'CompareCloneToolData');
if isempty(ad.data.meanshape)
    return;
end
S = ad.data.meanshape;
xrange = [min(S(:,2)), max(S(:,2))];
yrange = [min(S(:,1)), max(S(:,1))];
xind = linspace(xrange(1), xrange(2), ad.data.dx);
yind = linspace(yrange(1), yrange(2), ad.data.dy);
[x, y] = meshgrid(xind, yind);
ad.data.basegrid.x = x;
ad.data.basegrid.y = y;
hold(ad.handles.meanshapeaxes, 'on');
mesh(x, y, -1*ones(size(x)), 'Parent', ad.handles.meanshapeaxes);
setappdata(0, 'CompareCloneToolData', ad);
plotSectorAGrid();
plotSectorBGrid();
return
%%
function plotSectorAGrid()
ad = getappdata(0, 'CompareCloneToolData');
mh = plotSectorGrid(ad.data.sectorA.shape, ad.handles.sectorAaxes);
setappdata(0, 'CompareCloneToolData', ad);
return;
%%
function plotSectorBGrid()
ad = getappdata(0, 'CompareCloneToolData');
mh = plotSectorGrid(ad.data.sectorB.shape, ad.handles.sectorBaxes);
setappdata(0, 'CompareCloneToolData', ad);
return;
%%
function mh = plotSectorGrid(e, ah)
ad = getappdata(0, 'CompareCloneToolData');
mh = [];
if isempty(ad.data.basegrid.x) || isempty(ad.data.basegrid.y)
    return;
end
ecol = [1 1 1];
S = ad.data.meanshape;
x = ad.data.basegrid.x;
y = ad.data.basegrid.y;

t_lc = cp2tform(fliplr(e),fliplr(S),'linear conformal');
[x2, y2] = tforminv(t_lc, x(:), y(:)); 
x2 = reshape(x2, size(x));
y2 = reshape(y2, size(y));
mh = mesh(x2, y2, ones(size(x)), 'Parent', ah, 'FaceColor', 'none', 'EdgeColor', ecol, 'HitTest', 'off');
return
%%
function updateSectorA(popup, evd)
ad = getappdata(0, 'CompareCloneToolData');
cla(ad.handles.sectorAaxes);
if ~isempty(ad.data.sectorA.im)
    showImage(ad.data.sectorA.im, ad.handles.sectorAaxes);
end
if ~isempty(ad.data.sectorA.sector_info)
    ad.handles.sectorah = showSectors(ad.data.sectorA.sector_info, ad.handles.sectorAaxes);
end
if ~isempty(ad.data.sectorA.shape)
    ad.handles.shapeah = showShape(ad.data.sectorA.shape, ad.handles.sectorAaxes);
end
setappdata(0, 'CompareCloneToolData', ad);
compareSectors(ad.handles.compbtn);
plotSectorAGrid();
return
%%
function sh = showShape(shape, ah)
sh = plot(ah, shape(:,2), shape(:,1), '-o');
return
%%
% function adjustTransValue(slider, evd)
% ad = getappdata(0, 'CompareCloneToolData');
% % if ishandle(ad.handles.sectorah)
% %     set(ad.handles.sectorah, 'AlphaData', get(slider, 'Value'));
% % end
% % if ishandle(ad.handles.sectorbh)
% %     set(ad.handles.sectorbh, 'AlphaData', get(slider, 'Value'));
% % end
% setappdata(0, 'CompareCloneToolData', ad);
% return
%%
function updateSectorB(popup, evd)
ad = getappdata(0, 'CompareCloneToolData');
cla(ad.handles.sectorBaxes);
if ~isempty(ad.data.sectorB.im)
    showImage(ad.data.sectorB.im, ad.handles.sectorBaxes);
end

if ~isempty(ad.data.sectorB.sector_info)
    ad.handles.sectorah = showSectors(ad.data.sectorB.sector_info, ad.handles.sectorBaxes);
end
if ~isempty(ad.data.sectorB.shape)
    ad.handles.shapebh = showShape(ad.data.sectorB.shape, ad.handles.sectorBaxes);
end
setappdata(0, 'CompareCloneToolData', ad);
compareSectors(ad.handles.compbtn);
plotSectorBGrid();
return
%%
function imh = showSectors(sectors, ah)
ad = getappdata(0, 'CompareCloneToolData');
imh = [];
hold(ah, 'on');
imh = [];
for i=1:length(sectors)
    gt = sectors(i).growthTensor;
    mu = sectors(i).Centroid;
    imh = cat(1, imh, gtlib_plotGrowthTensor('growth_tensor', gt, 'offset', mu, 'Parent', ah, 'linewidth', ad.data.linwidth));
end
%im = uint8(im*255);
%im = repmat(im, [1 1 3]);
%imh = imagesc(im, 'Parent', ah, 'HitTest', 'off');
%set(imh, 'AlphaData', transval);
axis(ah, 'image', 'ij');
return
%%
function showImage(im, ah)
imagesc(im, 'Parent', ah, 'HitTest', 'off');
axis(ah, 'image', 'ij');
return
%%
function saveInfo(btn, evd)
ad = getappdata(0, 'CompareCloneToolData');
sector_info = ad.data.sector_info_cell;
[filename, pathname] = uiputfile('*.xls', 'Save as...');
if isequal(filename,0) || isequal(pathname,0)
    disp('User pressed cancel')
    return;
end
SUCCESS = xlswrite([pathname, filesep, filename],sector_info);
return
%%
function loadInfo(btn, evd)
ad = getappdata(0, 'CompareCloneToolData');
[filename, pathname] = uigetfile('*.xls', 'Load...', [pwd, filesep]);
if isequal(filename,0) || isequal(pathname,0)
    disp('User pressed cancel')
    return;
end
[num, txt, raw] = xlsread([pathname, filesep, filename]);
ad.data.sector_info_cell = raw;
setappdata(0, 'CompareCloneToolData', ad);
updateSectorInfoList();
return
%%
function clearAll(btn, evd)
ad = getappdata(0, 'CompareCloneToolData');
ad.data.sector_info_cell = {};
setappdata(0, 'CompareCloneToolData', ad);
updateSectorInfoList();
%%
function addCurrGTToList(btn, evd)
ad = getappdata(0, 'CompareCloneToolData');
if isempty(ad.data.D)
    return;
end
sector_info = ad.data.sector_info_cell;
deltaSt = 20;
growthrates = growthParameters2GrowthRates(ad.data.D, deltaSt);

[R, C] = size(sector_info);
if R==0
    R = 1;
    sector_info{1, 1} = 'Smaj';
    sector_info{1, 2} = 'Smin';
    sector_info{1, 3} = 'Sarea';
    sector_info{1, 4} = 'Kmaj';
    sector_info{1, 5} = 'Kmin';
    sector_info{1, 6} = 'Karea';
    sector_info{1, 7} = 'Kanis';
    sector_info{1, 8} = 'Rmaj';
    sector_info{1, 9} = 'Rmin';
    sector_info{1, 10} = 'Rarea';
    sector_info{1, 11} = 'Dmaj';
    sector_info{1, 12} = 'Dmin';
    sector_info{1, 13} = 'Darea';
    sector_info{1, 14} = 'theta';
end
sector_info{R+1, 1} = growthrates.Smaj;
sector_info{R+1, 2} = growthrates.Smin;
sector_info{R+1, 3} = growthrates.Sarea;
sector_info{R+1, 4} = growthrates.Kmaj;
sector_info{R+1, 5} = growthrates.Kmin;
sector_info{R+1, 6} = growthrates.Karea;
sector_info{R+1, 7} = growthrates.Kanis;
sector_info{R+1, 8} = growthrates.Rmaj;
sector_info{R+1, 9} = growthrates.Rmin;
sector_info{R+1, 10} = growthrates.Rarea;
sector_info{R+1, 11} = growthrates.Dmaj;
sector_info{R+1, 12} = growthrates.Dmin;
sector_info{R+1, 13} = growthrates.Darea;
sector_info{R+1, 14} = growthrates.theta;
ad.data.sector_info_cell = sector_info;
setappdata(0, 'CompareCloneToolData', ad);
updateSectorInfoList();
return
%%
function updateSectorInfoList()
ad = getappdata(0, 'CompareCloneToolData');
sector_info = ad.data.sector_info_cell;
S = cell(size(sector_info,1),1);

delete(ad.data.uitableh);
set(ad.handles.tablepanel, 'Units', 'pixels');

pos = get(ad.handles.tablepanel, 'Pos');
pos(1:2) = 1;

ad.data.uitableh = uitable('Parent', ad.handles.tablepanel, 'ColumnNames',  {sector_info{1, :}}, 'Data', sector_info,  'Position', pos);

    
% set(ad.data.uitableh, 'ColumnName', sector_info{1, :});
% 
% 
% 
%     S{1} = sprintf('%0.6s  %0.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s', ...
%        sector_info{1, 1},sector_info{1, 2},sector_info{1, 3},sector_info{1, 4}, ...
%        sector_info{1, 5},sector_info{1, 6},sector_info{1, 7},sector_info{1, 8}, ...
%        sector_info{1, 9},sector_info{1, 10},sector_info{1, 11},sector_info{1, 12}, ...
%        sector_info{1, 13}, sector_info{1, 14});
% for i=2:size(sector_info,1)
% 
%     str = sprintf('%.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s  %.6s', ...
%         num2str(sector_info{i, 1}), num2str(sector_info{i, 2}), num2str(sector_info{i, 3}), num2str(sector_info{i, 4}), ...
%         num2str(sector_info{i, 5}), num2str(sector_info{i, 6}), num2str(sector_info{i, 7}), num2str(sector_info{i, 8}), ...
%         num2str(sector_info{i, 9}), num2str(sector_info{i, 10}), num2str(sector_info{i, 11}), num2str(sector_info{i, 12}), ...
%         num2str(sector_info{i, 13}), num2str(sector_info{i, 14}));
%     
%   
%     S{i} = str;
% 
% end
% set(ad.handles.sector_info_txt, 'String', S);
setappdata(0, 'CompareCloneToolData', ad);
%%
function compareSectors(btn, evd)
ad = getappdata(0, 'CompareCloneToolData');
if get(btn, 'Value')==1
    set(ad.handles.sectorAaxes, 'ButtonDownFcn', {@sectorAClicked});
    set(ad.handles.sectorBaxes, 'ButtonDownFcn', {@sectorBClicked});
else
    set(ad.handles.sectorAaxes, 'ButtonDownFcn', '');
    set(ad.handles.sectorBaxes, 'ButtonDownFcn', '');
end
setappdata(0, 'CompareCloneToolData', ad);
%%
function ind = findClosestEllipse(pt, sectors, rad)
ind = [];

centroids = [sectors.Centroid];
centroids = reshape(centroids, 2, length(centroids)/2)';
N = size(centroids,1);
d = sqrt(sum((centroids - ones(N,1)*pt).^2,2));
[val, ind] = min(d);

if val<rad
    ind = ind(1);
else
    ind = [];
end


return
%%
function sectorAClicked(ah, evd)
ad = getappdata(0, 'CompareCloneToolData');
if isempty(ad.data.sectorA.sector_info)
    return;
end
pt = get(ah, 'CurrentPoint');
pt = round(pt(1,1:2));
ind = findClosestEllipse(pt, ad.data.sectorA.sector_info, Inf);



%id = ad.data.sectorA.L(pt(2), pt(1));
if ~isempty(ind)
   % [gt, mu] = label2GT(ad.data.sectorA.L==id);
   gt = ad.data.sectorA.sector_info(ind);
   mu = gt.Centroid;
    plotGT(ah, gt, mu);
    if length(ad.data.ellipvec)<3
        ad.data.ellipvec = cat(2, ad.data.ellipvec, gt);
    end
end
setappdata(0, 'CompareCloneToolData', ad);
if length(ad.data.ellipvec)==2
    compareEllipses();
end
%%
function sectorBClicked(ah, evd)
ad = getappdata(0, 'CompareCloneToolData');
if isempty(ad.data.sectorB.sector_info)
    return;
end
pt = get(ah, 'CurrentPoint');
pt = round(pt(1,1:2));
ind = findClosestEllipse(pt, ad.data.sectorB.sector_info, Inf);

if ~isempty(ind)
   gt = ad.data.sectorB.sector_info(ind);
    plotGT(ah, gt, gt.Centroid);
    if length(ad.data.ellipvec)<3
        ad.data.ellipvec = cat(2, ad.data.ellipvec, gt);
    end
end
setappdata(0, 'CompareCloneToolData', ad);
if length(ad.data.ellipvec)==2
        compareEllipses();
end
%%
function compareEllipses()
ad = getappdata(0, 'CompareCloneToolData');
ellipses = ad.data.ellipvec;
E1 = ellipses{1}.growthTensor;
E2 = ellipses{2}.growthTensor;
[smax1, smin1, theta1] = gtlib_growthTensor2Params(E1);
[smax2, smin2, theta2] = gtlib_growthTensor2Params(E2);
ungrow_smax = smax2/smax1;
ungrow_smin = smin2/smin1;
ad.data.D = gtlib_growthParams2Tensor(ungrow_smax, ungrow_smin, theta2);


D2 = zeros(3,3);
D2(1:2, 1:2) = E2(1:2,1:2)*inv(E1(1:2,1:2));
% keep it symmetric
%D2 = (D2 + D2')/2;

D2*E1
E2
ad.data.D = D2;

%[U, S, V] = svd(D2);
%[a, b, c] = gtlib_growthTensor2Params(D2)

ad.data.ellipvec = {};
setappdata(0, 'CompareCloneToolData', ad);
plotDiffGT();
return
%%
function plotDiffGT()
ad = getappdata(0, 'CompareCloneToolData');
if ~ishandle(ad.handles.gtaxes)
    figh = figure;
    set(figh, 'Position', [0 100 300 300]);
    ad.handles.gtaxes = gca;
end
ah = ad.handles.gtaxes;
gt = ad.data.D;
cla(ah); 
gtlib_plotGrowthTensor('growth_tensor', gt, 'colour', 'g', 'Parent',ah , 'linewidth', 3);
[smax, smin, theta] = gtlib_growthTensor2Params(gt);
axis(ah, 'image', 'ij');
t = sprintf('Gmax: %3.3f, Gmin: %3.3f, Theta: %3.3f', smax, smin, theta);
fprintf('%s\n', t);
title(ah, t, 'FontSize', 8);
setappdata(0, 'CompareCloneToolData', ad);
return
%%
%function [gt, mu] = label2GT(B)
%[x, y] = find(B >0);
%X = [y, x];
%mu = mean(X);
%gt = fitGrowthTensor(X);
%return
%%
function plotGT(ah, gt, pt)
ad = getappdata(0, 'CompareCloneToolData');
hold(ah, 'on');
col = rand(1,3);
col = [0 1 1];
gtlib_plotGrowthTensor('growth_tensor', gt.growthTensor, 'offset', pt, 'colour', col, 'linewidth', ad.data.linwidth);
return
%%
function data = parseargs(varargin)
varargin = varargin{1};

if mod(length(varargin),2) ~= 0
    % input args have not com in pairs, woe is me
    error(['Arguments to ', mfilename, ' must come param/value in pairs.'])
end
data.bimgfilenames = {};
data.imgfilenames = {};
for i=1:2:length(varargin)
    switch lower(varargin{i})
        case 'bimgfilenames'
            data.bimgfilenames = varargin{i+1};
        case 'imgfilenames'
            data.imgfilenames = varargin{i+1};
        otherwise
            error(['Unknown parameter name passed to ', mfilename, '.  Name was ' varargin{i}])
    end
end
if length(data.bimgfilenames) ~= length(data.imgfilenames)
    error('Number of binary images must match number of rgb images');
end
if isempty(data.bimgfilenames)
    error('Number of binary images must be >0');
end
return;
