function HierarchyBuilder(arg)
if strcmp(arg, 'init')
    %close all;
    % Open the GUI for display
    fig = openfig(mfilename, 'reuse');
    % Generate a structure of handles to pass to callbacks, and store
    Data.handles = guihandles(fig);
    Data.handles.figMain = fig;
    Data.handles.PointModelTemplate = PointModelTemplate;
    Data.handles.dat.plotH = [];
    Data.handles.dat.currentSubsetNumber = 0;
    Data.handles.workingDir = pwd;
    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
    guidata(fig, Data);
else
    Data = guidata(gcbo);
    switch arg
        case 'ToggleLoops'
            Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);

        case 'SaveTemplate'
            [Data.handles] = SaveTemplate(Data.handles);
        case 'LoadTemplate'
            [Data.handles] = LoadTemplate(Data.handles);
        case 'SelectTemplateImage'
            [filename, pathname] = uigetfile({'*.JPG; *.jpg', 'JPEG Files (*.JPG, *.jpg)'}, 'Select the Template Image', [Data.handles.workingDir]);
            if isequal(filename,0) | isequal(pathname,0)
                disp('User pressed cancel')
            else
                Data.handles.dat.currentSubsetNumber = 0;
                Data.handles.dat.currentLoop = [];
                Data.handles.PointModelTemplate = PointModelTemplate;
                Data.handles.PointModelTemplate = set(Data.handles.PointModelTemplate, 'image', imread([pathname, filesep, filename]));
                imagesc(get(Data.handles.PointModelTemplate, 'image'), 'HitTest', 'off'); axis image;
                Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
                Data.handles.PointModelTemplate = set(Data.handles.PointModelTemplate, 'imageName', filename);
                Data.handles.PointModelTemplate = set(Data.handles.PointModelTemplate, 'imageDir', pathname);
                set(Data.handles.imageDirTxt, 'String', pathname);
                set(Data.handles.imageNameTxt, 'String', filename);
                if (length(get(Data.handles.PointModelTemplate, 'subsets'))>0)
                    set(Data.handles.subsetList, 'String', get_subsetString(get(Data.handles.PointModelTemplate, 'subsets')));
                else
                    set(Data.handles.subsetList, 'String', '0');
                end

            end
        case 'AddToSubset'
            switch get(Data.handles.addToSubsetBtn, 'value')
                case 0
                    set(Data.handles.figMain, 'Pointer', 'Arrow');
                    set(Data.handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
                    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
                case 1
                    set(Data.handles.figMain, 'Pointer', 'cross');
                    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Add To Subset Mode');
                    % First initialise button click function
                    set(Data.handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' AddSubsetPoint']);
            end
        case 'AddSubsetPoint'
            if  Data.handles.dat.currentSubsetNumber > 0
                pts = get(Data.handles.PointModelTemplate, 'pts');
                subsets = get(Data.handles.PointModelTemplate, 'subsets');


                CurrentPoint = get(Data.handles.mainAxes, 'CurrentPoint');
                                distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
                nearestPoint = find(distances == min(distances));
                nearestPoint = nearestPoint(1);
                subset = subsets{Data.handles.dat.currentSubsetNumber};
                if length(find(subset==nearestPoint))==0
                    subset = [subset, nearestPoint];
                end

                subsets{Data.handles.dat.currentSubsetNumber} = subset;


                Data.handles.PointModelTemplate = set(Data.handles.PointModelTemplate, 'subsets', subsets);
                if (length(get(Data.handles.PointModelTemplate, 'subsets'))>0)
                    %set(Data.handles.subsetList, 'String', get_subsetString(get(Data.handles.PointModelTemplate, 'subsets')));
                else
                    set(Data.handles.subsetList, 'String', '0');
                end
                Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);

            end
        case 'DeleteFromSubset'
            switch get(Data.handles.delFromSubsetBtn, 'value')
                case 0
                    set(Data.handles.figMain, 'Pointer', 'Arrow');
                    set(Data.handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
                    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
                     set(Data.handles.subsetList, 'String', get_subsetString(get(Data.handles.PointModelTemplate, 'subsets')));
                    set(Data.handles.subsetList, 'value', Data.handles.dat.currentSubsetNumber);
                case 1
                    set(Data.handles.figMain, 'Pointer', 'cross');
                    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Delete From Subset Mode');
                    % First initialise button click function
                    set(Data.handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' DeleteSubsetPoint']);
            end
        case 'DeleteSubsetPoint'
            Data.handles.PointModelTemplate;
            if  Data.handles.dat.currentSubsetNumber > 0
                pts_orig = get(Data.handles.PointModelTemplate, 'pts');
                subsets = get(Data.handles.PointModelTemplate, 'subsets');

                pts = pts_orig(:, subsets{Data.handles.dat.currentSubsetNumber});

                CurrentPoint = get(Data.handles.mainAxes, 'CurrentPoint');
                distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
                nearestPoint = find(distances == min(distances));
                nearestPoint = nearestPoint(1);
                p = pts(:, nearestPoint)';
                distances = sqrt((pts_orig(1,:) - p(1)).^2+ (pts_orig(2,:) - p(2)).^2);
                nearestPoint = find(distances == min(distances));
                nearestPoint = nearestPoint(1);
                subset = subsets{Data.handles.dat.currentSubsetNumber};
                ind = find(subset == nearestPoint);
                subset(ind) = [];
                subsets{Data.handles.dat.currentSubsetNumber} = subset;
                
                
                Data.handles.PointModelTemplate = set(Data.handles.PointModelTemplate, 'subsets', subsets);
                if (length(get(Data.handles.PointModelTemplate, 'subsets'))>0)
                    set(Data.handles.subsetList, 'String', get_subsetString(get(Data.handles.PointModelTemplate, 'subsets')));
                else
                    set(Data.handles.subsetList, 'String', '0');
                end
                Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);

            end
        case 'DeleteSubset'
            if  Data.handles.dat.currentSubsetNumber > 0
                subsets = get(Data.handles.PointModelTemplate, 'subsets');
                subsets(Data.handles.dat.currentSubsetNumber) = [];
                Data.handles.PointModelTemplate = set(Data.handles.PointModelTemplate, 'subsets', subsets);
                if (length(get(Data.handles.PointModelTemplate, 'subsets'))>0)
                    set(Data.handles.subsetList, 'String', get_subsetString(get(Data.handles.PointModelTemplate, 'subsets')));
                else
                    set(Data.handles.subsetList, 'String', '0');
                end
                Data.handles.dat.currentSubsetNumber = Data.handles.dat.currentSubsetNumber -1;
                if Data.handles.dat.currentSubsetNumber>0
                                set(Data.handles.subsetList, 'value', Data.handles.dat.currentSubsetNumber);
                end
                Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);

            end
        case 'DefineSubset'
            switch (get(Data.handles.insertPointBtn, 'value'))
                case 0
                    set(Data.handles.insertPointBtn, 'String', 'Create Subset')
                    set(Data.handles.figMain, 'Pointer', 'Arrow');
                    set(Data.handles.figMain, 'WindowButtonDownFcn', '', 'WindowButtonMotionFcn' , '', 'WindowButtonUpFcn', '', 'KeyPressFcn', '', 'BackingStore','on');
                    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Please Choose an Operation');
                    set(Data.handles.subsetList, 'String', get_subsetString(get(Data.handles.PointModelTemplate, 'subsets')));
                    %set(Data.handles.subsetList, 'value', Data.handles.dat.currentSubsetNumber);

                case 1
                    set(Data.handles.insertPointBtn, 'String', 'End Subset')
                    set(Data.handles.figMain, 'Pointer', 'crosshair');
                    set(Data.handles.txtCurrentStatus, 'ForegroundColor', 'blue','String', 'Insert Landmark Mode');
                    % First initialise button click function
                    Data.handles.dat.currentSubsetNumber = length(get(Data.handles.PointModelTemplate, 'subsets')) + 1;
                    Data.handles.dat.currentSubset = [];
                    set(Data.handles.figMain, 'BackingStore', 'off', 'WindowButtonDownFcn', [mfilename, ' SelectPoint']);
            end
        case 'SelectPoint'
            pts = get(Data.handles.PointModelTemplate, 'pts');
            CurrentPoint = get(Data.handles.mainAxes, 'CurrentPoint');
            distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
            nearestPoint = find(distances == min(distances));
            nearestPoint = nearestPoint(1);
                            if length(find(Data.handles.dat.currentSubset==nearestPoint))==0
                    Data.handles.dat.currentSubset = [Data.handles.dat.currentSubset, nearestPoint];
                            end
            subsets = get(Data.handles.PointModelTemplate, 'subsets');
            subsets{Data.handles.dat.currentSubsetNumber} = Data.handles.dat.currentSubset;
            Data.handles.PointModelTemplate =  set(Data.handles.PointModelTemplate, 'subsets', subsets);
            Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
        case 'UpdateSubsetFromList'
            subsets = get(Data.handles.PointModelTemplate, 'subsets');
            if length(subsets)>0
                Data.handles.dat.currentSubsetNumber = get(Data.handles.subsetList, 'value');
                Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);

            end
        case 'UpdateSubset'
            if (get(Data.handles.delFromSubsetBtn, 'value')==0) &  (get(Data.handles.addToSubsetBtn, 'value')==0)
                if Data.handles.dat.currentSubsetNumber >0
                                        set(Data.handles.subsetList, 'String', get_subsetString(get(Data.handles.PointModelTemplate, 'subsets')));

                set(Data.handles.subsetList, 'value', Data.handles.dat.currentSubsetNumber);
                end
                pts = get(Data.handles.PointModelTemplate, 'pts');
                if (size(pts, 2)>0)
                    subsets = get(Data.handles.PointModelTemplate, 'subsets');
                    CurrentPoint = get(Data.handles.mainAxes, 'CurrentPoint');
                    distances = sqrt((pts(1,:) - CurrentPoint(1,1)).^2+ (pts(2,:) - CurrentPoint(1,2)).^2);
                    nearestPoint = find(distances == min(distances));
                    nearestPoint = nearestPoint(1);
                    Data.handles.dat.currentSubsetNumber = 0;
                    for l = 1:length(subsets)
                        subset = subsets{l};
                        ind = find(subset == nearestPoint);
                        if ~isempty(ind)
                            Data.handles.dat.currentSubsetNumber = l;
                        end
                    end
                    Data.handles.dat.plotH = PlotTemplate(Data.handles.mainAxes, Data.handles.PointModelTemplate, Data.handles, Data.handles.dat.plotH);
                end
            end
        case 'Done'
            delete(Data.handles.figMain);
            Data.handles = rmfield(Data.handles, 'figMain');
        otherwise
            error('Unknown Option in Relaxation Toolbox');
    end
    if isfield(Data.handles, 'figMain')
        guidata(Data.handles.figMain, Data);
    end
end
%%%%%%%%%%%%%%%%%%%%%%%%%
%
% function [string] = get_subsetString(subsets)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%
function [string] = get_subsetString(subsets)
if length(subsets)>0
    for s = 1:length(subsets)
        string{s} = num2str(s);
    end
else
    string = '0';
end
%%%%%%%%%%%%%%%%%%%%%%
%
%
%  PlotTemplate(A, template)
%
%%%%%%%%%%%%%%%%%%%%%%
function [plotH] = PlotTemplate(A, template, handles, plotH)
if(any(plotH))
    delete(plotH);
    plotH = [];
end
I = get(template, 'image');
pts = get(template, 'pts');
pri = get(template, 'primaries');
loops = get(template, 'loops');

subsets = get(template, 'subsets');
closedloops = get(template, 'closedloops');
if isempty(closedloops)
    closedloops = 0;
end
axes(A); hold(A, 'on');

if (size(pts, 2) > 0)
    plotH(length(plotH)+1) = plot(pts(1, :), pts(2,:), '.r', 'MarkerSize', 20, 'HitTest', 'off');    
    plotH(length(plotH)+1) = plot(pts(1, :), pts(2,:), 'o', 'MarkerSize', 7, 'LineWidth', 1.5, 'MarkerEdgeColor', [1 1 1], 'HitTest', 'off');

    
end
if (length(pri)>0)
    plotH(length(plotH)+1) = plot(pts(1, pri), pts(2,pri), '.g', 'MarkerSize', 20, 'HitTest', 'off');
end
if get(handles.showLoopsChk, 'value')
    for i=1:length(loops)
        looppts = pts(:, loops{i});
        if (closedloops(i)==1)
            looppts = [looppts, looppts(:, 1)];
        end
        if (size(looppts,2)>0)
            plotH(length(plotH)+1) = plot(looppts(1, :), looppts(2,:), 'r', 'LineWidth', 1.5,  'HitTest', 'off');
        end
    end
end
if (handles.dat.currentSubsetNumber > 0)
    subset_pts = pts(:, subsets{handles.dat.currentSubsetNumber});
    if (size(subset_pts, 2)>0)
        plotH(length(plotH)+1) = plot(subset_pts(1,:), subset_pts(2,:), 'o', 'MarkerFaceColor', [1 1 0], 'MarkerEdgeColor', [0 1 1], 'LineWidth', 2, 'MarkerSize', 10, 'HitTest', 'off');
    end
end
for i=1:size(pts, 2)
    plotH(length(plotH)+1) = text(pts(1, i), pts(2,i), num2str(i), 'Color', 'k', 'HitTest', 'off');
end
axis(A, 'image');
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  cut_string   //splits directory names so you can see the beginning and
%                   //the end
%%%%%%%%%%%%%%%%%%%%%%
function [s] = cut_string(s)
if (length(s)>83)
    s = [s(1:40), '...', s(end-40:end)];
end
%%%%%%%%%%%%%%%%%%%%%%
%
%  Load Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = LoadTemplate(handles)
[filename, pathname] = uigetfile('*.temp_dat', 'Pick a File', [handles.workingDir]);
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    template = load([pathname, filename], '-mat');
    handles.PointModelTemplate = template.PointModelTemplate;
    handles.dat.plotH = [];
    handles.dat.currentSubsetNumber = 0;

    cla(handles.mainAxes);
    imagesc(get(handles.PointModelTemplate, 'image'), 'HitTest', 'off'); axis image;
    handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
    handles.workingDir = pathname;
    set(handles.imageDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'imageDir')));
    set(handles.imageNameTxt, 'String', get(handles.PointModelTemplate, 'imageName'));
    set(handles.templateDirTxt, 'String', cut_string(get(handles.PointModelTemplate, 'direc')));
    set(handles.templateNameTxt, 'String', get(handles.PointModelTemplate, 'name'));
    set(handles.subsetList, 'String', get_subsetString(get(handles.PointModelTemplate, 'subsets')));

end
return;
%%%%%%%%%%%%%%%%%%%%%%
%
%  Save Template    //Pretty Obvious
%
%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SaveTemplate(handles)
[filename, pathname] = uiputfile('*.temp_dat', 'Pick a File', [handles.workingDir, filesep, get(handles.PointModelTemplate, 'name')]);
if isequal(filename,0) | isequal(pathname,0)
    disp('User pressed cancel')
else
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'name', filename);
    handles.PointModelTemplate = set(handles.PointModelTemplate, 'direc', pathname);
    PointModelTemplate = handles.PointModelTemplate;
    save([pathname, filename], 'PointModelTemplate');
    disp(['User selected ', fullfile(pathname, filename)])
    handles.workingDir = pathname;
    set(handles.templateDirTxt, 'String', cut_string(pathname));
    set(handles.templateNameTxt, 'String', filename);
end
disp('Saving');
return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  SmoothLandmarks    //Smooths the secondary landmarks in a given loop
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [handles] = SmoothLandmarks(handles)

pri = get(handles.PointModelTemplate, 'primaries')';
pts = get(handles.PointModelTemplate, 'pts')';
pts_orig = pts;
currentLoop = handles.dat.currentLoopNumber;
loops = get(handles.PointModelTemplate, 'loops');
edges=loops{1};
ind = loops{currentLoop};
pts = pts(ind,:);
pri = intersect(pri, ind);
for p = 1:length(pri)
    pri(p) = find(ind == pri(p));
end
[handles,pts]=general_smoothlandmarks(handles,pts,pri,edges);

% 
% if(length(pri) <= 1)
%     set(handles.txtCurrentStatus, 'ForegroundColor', 'red', 'String', 'Need at least two primaries points');
%     return;
% end
% SectionsToSmooth = length(pri) - 1;
% loop = 0;
% % % If loop is complete, loop back to first primary
% if(loop)
%     SectionsToSmooth = length(pri);
%     pri = [pri pri(1)];
% else
%     SectionsToSmooth = length(pri) - 1;
% end
% % Array indexing chages for last section when complete loop is selected
% lastloop = 0;
% for k = 1:SectionsToSmooth
%     % Number of points in current section
%     NptsThisSection = pri(k+1) - pri(k) + 1;
%     x = zeros(NptsThisSection, 1);
%     y = zeros(NptsThisSection, 1);
%     if(NptsThisSection < 0)
%         % Last section, perform loop back to first primary point
%         lastloop = 1;
%         NptsThisSection = size(pts, 1) - pri(k) + 2;
%         x(1) = pts(pri(1),1);
%         x(NptsThisSection) = pts(pri(k), 1);
%         x(2:NptsThisSection-1) = pts(size(pts,1):-1:pri(k)+1,1)';
%         y(1) = pts(pri(1), 2);
%         y(NptsThisSection) = pts(pri(k), 2);
%         y(2:NptsThisSection-1) = pts(size(pts, 1):-1:pri(k)+1, 2)';
%     else
%         % Get x and y components of values between current landmark pair
%         x(1) = pts(pri(k), 1);
%         x(NptsThisSection) = pts(pri(k+1), 1);
%         x(2:NptsThisSection-1) = pts(pri(k)+1:pri(k)+NptsThisSection-2,1);
%         y(1) = pts(pri(k), 2);
%         y(NptsThisSection) = pts(pri(k+1), 2);
%         y(2:NptsThisSection-1) = pts(pri(k)+1:pri(k)+NptsThisSection-2,2);
%     end
%     Nint = 50; % Number of interpolation points used
%     % Fit data using a spline interpolation
%     t = 1:NptsThisSection;
%     ts = 1:1/Nint:NptsThisSection;
%     xfit = spline(t, x, ts); % x-coordinates of interpolating line
%     yfit = spline(t, y, ts); % y-coordinates of interpolating line
%     % Calculate the length of the line through the secondaries
%     xfitS = xfit(2:length(xfit)) - xfit(1:length(xfit)-1);
%     yfitS = yfit(2:length(yfit)) - yfit(1:length(yfit)-1);
%     LineLength = cumsum(sqrt((xfitS.^2) + (yfitS.^2)));
%     % Calculate what the spacing should be between the secondaries.
%     DistanceBetweenPoints = LineLength(length(LineLength)) / (NptsThisSection - 1);
%     % Clear from last iteration
%     newx=[]; newy=[];
%     % Find position of new points
%     for n = 2:NptsThisSection-1
%         idx = min(find(LineLength >= (n-1) * DistanceBetweenPoints)) + 1;
%         newx(n-1) = xfit(idx);
%         newy(n-1) = yfit(idx);
%     end
%     if(~lastloop)
%         pts(pri(k)+1:pri(k+1)-1, 1) = newx';
%         pts(pri(k)+1:pri(k+1)-1, 2) = newy';
%     else
%         pts(pri(k)+1:size(pts, 1), 1) = flipud(newx');
%         pts(pri(k)+1:size(pts, 1), 2) = flipud(newy');
%     end
% 
% end
pts_orig(ind, :) = pts;
handles.PointModelTemplate = set(handles.PointModelTemplate, 'pts', pts_orig');
handles.dat.plotH = PlotTemplate(handles.mainAxes, handles.PointModelTemplate, handles, handles.dat.plotH);
if(loop)
    pri = pri(1:length(pri)-1);
end
