/// <summary>
        /// Creates a graphviz format representation of the tree edges and its nodes.
        /// </summary>
        /// <param name="userContext">The user context.</param>
        /// <param name="tree">The tree.</param>
        /// <param name="treeNodes">The tree nodes.</param>
        /// <param name="treeIterationMode">The tree iteration mode.</param>
        /// <param name="onlyValid">if set to <c>true</c> only valid relations are included.</param>
        /// <param name="format">The format.</param>
        /// <returns>A GraphViz graph.</returns>
        public static string CreateGraphvizFormatRepresentation(
            IUserContext userContext,
            TaxonRelationsTree tree,
            ICollection <ITaxonRelationsTreeNode> treeNodes,
            TaxonRelationsTreeIterationMode treeIterationMode,
            bool onlyValid,
            GraphVizFormat format)
        {
            // Get edges.
            var edges = tree.GetAllEdges(
                treeNodes,
                treeIterationMode,
                onlyValid,
                treeIterationMode != TaxonRelationsTreeIterationMode.OnlyChildren);

            string str = CreateGraphvizFormatRepresentation(
                userContext,
                tree,
                edges,
                treeNodes,
                format);

            return(str);
        }
        /// <summary>
        /// Creates a graphviz format representation of the tree edges and its nodes.
        /// </summary>
        /// <param name="userContext">The user context.</param>
        /// <param name="tree">The tree.</param>
        /// <param name="edges">The edges.</param>
        /// <param name="sourceNodes">The source nodes.</param>
        /// <param name="format">The format.</param>
        /// <returns></returns>
        public static string CreateGraphvizFormatRepresentation(
            IUserContext userContext,
            TaxonRelationsTree tree,
            IEnumerable <ITaxonRelationsTreeEdge> edges,
            IEnumerable <ITaxonRelationsTreeNode> sourceNodes,
            GraphVizFormat format)
        {
            // Get all nodes and remove duplicates using a HashSet.
            HashSet <ITaxonRelationsTreeNode> nodes = new HashSet <ITaxonRelationsTreeNode>();

            if (edges != null)
            {
                foreach (var edge in edges)
                {
                    nodes.Add(edge.Parent);
                    nodes.Add(edge.Child);
                }
            }

            if (sourceNodes != null)
            {
                foreach (ITaxonRelationsTreeNode node in sourceNodes)
                {
                    nodes.Add(node);
                }
            }

            HashSet <ITaxon>             taxaSet = new HashSet <ITaxon>(nodes.Select(x => x.Taxon));
            HashSet <LumpSplitEventList> lumps   = null;
            HashSet <LumpSplitEventList> splits  = null;

            if (format.ShowLumpsAndSplits)
            {
                HashSet <int> taxonIdsSet = new HashSet <int>(nodes.Select(x => x.Taxon.Id));
                lumps  = GetAllLumpEventListsForTaxa(userContext, nodes);
                splits = GetAllSplitEventListsForTaxa(userContext, nodes);
                HashSet <int>    lumpSplitExtraTaxonIds = new HashSet <int>();
                HashSet <ITaxon> lumpSplitExtraTaxa     = GetLumpSplitsExtraTaxa(taxaSet, splits, lumps);

                foreach (var taxon in lumpSplitExtraTaxa)
                {
                    nodes.Add(tree.GetTreeNode(taxon.Id));
                }
            }

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("digraph {");

            //-------------------
            // Create main tree
            //-------------------
            foreach (ITaxonRelationsTreeNode node in nodes)
            {
                sb.AppendLine(string.Format(
                                  "node_{0} [label=\"{1}\", shape=box, style=rounded, color={2}, peripheries={3}, penwidth={4}];",
                                  node.Taxon.Id,
                                  GetNodeLabel(node),
                                  node.Taxon.IsValid ? "black" : "red",
                                  node.Taxon.Category.IsTaxonomic ? 1 : 2,
                                  node.Taxon.IsValid ? 1 : 2));
            }

            foreach (var edge in edges)
            {
                string edgeLabel;
                if (format.ShowRelationId)
                {
                    edgeLabel = edge.IsValid ? edge.TaxonRelation.Id.ToString() : string.Format("({0})\\n\\[Not valid\\]", edge.TaxonRelation.Id);
                }
                else
                {
                    edgeLabel = edge.IsValid ? "" : "\\[Not valid\\]";
                }

                sb.AppendLine(string.Format(
                                  "node_{0} -> node_{1} [style={2}, color={3}, label=\"{4}\"];",
                                  edge.Parent.Taxon.Id,
                                  edge.Child.Taxon.Id,
                                  edge.IsMain ? "solid" : "dashed",
                                  edge.IsValid ? "black" : "red",
                                  edgeLabel));
            }

            //------------------
            // Add lump splits
            //------------------
            if (format.ShowLumpsAndSplits)
            {
                //lumps = GetAllLumpEventListsForTaxa(userContext, nodes);
                //splits = GetAllSplitEventListsForTaxa(userContext, nodes);

                int clusterCount = 0;
                // Lumps
                foreach (LumpSplitEventList lumpSplitEventList in lumps)
                {
                    AddLumpCluster(sb, lumpSplitEventList, clusterCount, taxaSet);
                    clusterCount++;
                }

                // Splits
                foreach (LumpSplitEventList lumpSplitEventList in splits)
                {
                    AddSplitCluster(sb, lumpSplitEventList, clusterCount, taxaSet);
                    clusterCount++;
                }
            }

            sb.AppendLine("}");
            return(sb.ToString());
        }