void GroupProteinsOrPeptides(
            IDictionary <string, Node> entities,
            IReadOnlyList <string> entityNames,
            Type entityType,
            GlobalIDContainer globalIDTracker)
        {
            for (var count = 0; count != entityNames.Count; count++)
            {
                // Is the key there?
                if (!entities.ContainsKey(entityNames[count]))
                {
                    continue;
                }

                // Get the protein or peptide
                var entity = entities[entityNames[count]];

                // Only proceed if the correct type
                if (entity.GetType() != entityType)
                {
                    continue;
                }

                var duplicates = new NodeChildren <Node>();

                // Look for duplicates and add to a duplicate list
                duplicates.AddRange(FindDuplicates(entity));

                if (duplicates.Count <= 1)
                {
                    continue;
                }

                // Create a protein or peptide group from the duplicates
                Group newGroup;

                if (entityType == typeof(Protein))
                {
                    newGroup = new ProteinGroup(duplicates, globalIDTracker);
                }
                else if (entityType == typeof(Peptide))
                {
                    newGroup = new PeptideGroup(duplicates, globalIDTracker);
                }
                else
                {
                    throw new Exception("Invalid type: must be Protein or Peptide");
                }

                foreach (var duplicateItem in duplicates)
                {
                    // Remove entities from the library, add the new group
                    entities.Remove(duplicateItem.NodeName);
                }

                entities.Add(newGroup.NodeName, newGroup);
            }
        }
        private NodeChildren <Node> FindDuplicates(Node node)
        {
            node.Children.Sort();
            var candidates = new NodeChildren <Node>();

            candidates.AddRange(node.Children[0].Children);
            candidates.Remove(node);

            var count = 0;

            // Pulls out candidates with different counts of children than the master
            while (candidates.Count != count)
            {
                if (node.Children.Count != candidates[count].Children.Count)
                {
                    candidates.RemoveAt(count);
                }
                else
                {
                    count++;
                }
            }

            // May want to change the List to a Hashset to be faster.
            // Finds identical sets.
            foreach (var childNode in node.Children)
            {
                count = 0;
                while (candidates.Count != count)
                {
                    if (!childNode.Children.Contains(candidates[count]))
                    {
                        candidates.RemoveAt(count);
                    }
                    else
                    {
                        count++;
                    }
                }
            }
            candidates.Add(node);
            return(candidates);
        }