function [tree,json] = partsTree(D, mincounts)

if nargin == 1
    mincounts = 0;
end

tree.parent = []; % node = 0 is the root node
tree.nodewords = {};
tree.counts = zeros(100*20,1);

% remove stop words
%   'crop',...
%D = removestopwords(D);

%[names, namesCounts] = LMobjectnames(D);

% Identify whole objects first and that have more than N annotated examples
% only add as branches the ones that have as root a whole frequent object
% put the counts as part of the object name when building the tree. 
m=0;
%keyboard

for n = 1:length(D)
    n
    D(n).annotation = changeId(D(n).annotation);
    
    %nodes = [];
    agenda = 1:LMcountobject(D(n));
    parents = [0 -1];  % [node index in full tree, object index-1. -1 denotes a root object.]
    while ~isempty(agenda)
        % Take first element in the agenda and push it to the end
        j = agenda(1);
        agenda = [agenda(2:end) agenda(1)];
        
        name = strtrim(lower(D(n).annotation.object(j).name));
        [hasparts, ispartof] = findparts(D(n).annotation,j);
        if isempty(ispartof)
            %ispartof = -1;
            p = 0;
        else
            p = parents(find(parents(:,2)==ispartof),1);
        end
        
        
        % find the index of the parent object in the full tree:
        %p = parents(find(parents(:,2)==ispartof),1)
        
        if ~isempty(p)
            % If the parent is already in the tree, then we can insert the
            % object. But first we need to check if the object is also in
            % the list. If it is in the list we will just increase the
            % counter. Otherwise we will added as a children.
            
            % Check if object already in the list (k = tree index if
            % found)
            k0 = find(tree.parent==p);
            k = k0(strmatch(name, tree.nodewords(k0), 'exact'));
            
            if ~isempty(k)
                % if the object is already in the list
                % increment instance counts
                tree.counts(k) = tree.counts(k)+1;
                % add image and object key
                tree.crop(k).data = [tree.crop(k).data; n j];
                %nodes(j) = k;
            else
                % if object is not in the list, insert the object in the
                % tree
                k = length(tree.parent)+1;
                tree.parent(k) = p;
                tree.nodewords{k} = name;
                tree.counts(k) = 1;
                tree.crop(k).data = [n j];
                
                %nodes(j) = k;
                %parents = [parents; k j-1];
            end
            
            % remove from agenda this object
            parents = [parents; k j-1];
            agenda(end) = [];            
        end
    end
end
                
tree.counts = tree.counts(1:length(tree.parent))';                

% for i = 1:length(tree.parent)
%     if ~isempty(tree.counts(i)) && tree.counts(i)>0
%         tree.nodewords{i} = sprintf('%s (%d)', tree.nodewords{i}, tree.counts(i));
%     end
% end

% add counts 

if nargout > 1
    json = getStringBranch(tree,0,mincounts);
end

if nargout==0
    showTree(tree)
end

function json = getStringBranch(tree, parent, mincounts)

json = [];

if parent == 0
    json = sprintf('{ "name": "root"');
else
    json = sprintf('{ "name": "%s (%d)"', tree.nodewords{parent}, tree.counts(parent));
end

j = find((tree.parent == parent).*(tree.counts>=mincounts));

% sort j alphabetically
[~,jj] = sort(tree.nodewords(j));
j = j(jj);

if ~isempty(j)
    json = [json sprintf(',\n"children": [\n')];
    for n = 1:length(j)
        json = [json getStringBranch(tree, j(n), 10+0*mincounts)];
    end
    json = json(1:end-2);
    json = [json sprintf('\n]\n')];
end

json = [json sprintf('},\n')];

if parent == 0
    json = json(1:end-2);
end





% Here is one example of a json string:
% {
%  "name": "SUN",
%  "children": [
%   {
%    "name": "kitchen",
%    "children": [
%     {
%      "name": "sink",
%      "children": [
%       {"name": "faucet", "size": 3938},
%       {"name": "sink", "size": 3812, "link": "http://www.test.edu"},
%       {"name": "HierarchicalCluster", "size": 6714},
%       {"name": "MergeEdge", "size": 743}
%      ]
%     },
%   ]
%  },
% }

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% function [tree, nodes] = addbranch(tree, branch)
% %
% % Add a new branch to the tree
% 
% N = length(branch);
% M = length(tree.parent);
% parent = 0; %start on the root
% for n = N:-1:1
%     % two different nodes might have the same name!
%     np = find(tree.parent==parent);
%     node = strmatch(strtrim(branch{n}), tree.nodewords(np), 'exact');
%     node = np(node);
% 
%     if isempty(node)
%         % connect node to the root
%         tree.parent(M+1) = parent;
%         tree.nodewords{M+1} = strtrim(branch{n});
%         nodes(n) = M+1;
% 
%         M = M+1;
%         parent = M;
%     else
%         parent = node;
%         nodes(n) = node;
%     end
% end
% 

