Example #1
0
            public void AddBranch(TreeBranch branch)
            {
                // A node can only support three connections
                if (branches.Count == 3)
                {
                    throw new OverflowException("This node already has 3 connections.");
                }
                else
                {
                    // If the branch being added connects this node to a leaf, and one of the other branches also
                    // connects to a leaf, this is a terminal node. Add this node to the list of terminal nodes.
                    if (branch.Follow(this).GetType() == typeof(TreeLeaf))
                    {
                        foreach (TreeBranch otherBranch in branches)
                        {
                            if (otherBranch.Follow(this).GetType() == typeof(TreeLeaf))
                            {
                                tree.terminalNodesList.Add(this);
                            }
                        }
                    }

                    branches.Add(branch);
                }
            }
Example #2
0
            public void RemoveBranch(TreeBranch branch)
            {
                // List's Remove method handles low-count and not-in-list conditions,
                // so I won't handle them here.
                // bool removeFlag = branches.Remove(branch); Not sure why I need the return code.
                branches.Remove(branch);

                if (childBranch1 == branch)
                {
                    childBranch1 = null;
                }
                else if (childBranch2 == branch)
                {
                    childBranch2 = null;
                }


                //if (!removeFlag)
                //{
                //    return false;
                //}

                if (parentBranch == branch)
                {
                    RemoveParent();
                }

                // If the branch removal results in no connections, the node can be removed from the tree.
                if (branches.Count == 0)
                {
                    tree.nodesList.Remove(this);
                }
                else if (true)
                {
                    // If the branch was a terminal node and the branch being removed was connected to a leaf,
                    // if only one other branch is connected to a leaf, this is no longer a terminal node.
                    // Remove this node from the list of terminal nodes.
                    if (branch.Follow(this).GetType() == typeof(TreeLeaf))
                    {
                        int leafCount = 0;
                        foreach (TreeBranch otherBranch in branches)
                        {
                            if (otherBranch.Follow(this).GetType() == typeof(TreeLeaf))
                            {
                                leafCount += 1;
                            }
                        }

                        if (leafCount <= 1)
                        {
                            tree.terminalNodesList.Remove(this);
                        }
                    }
                }
                //return true;
            }
Example #3
0
        void AssertPaternity()
        // For each branch out from the given root which is not a parent branch, assign that branch
        // as the child's parent branch.
        // As this could be deeply recursive and could result in a stack overflow, this must be coded as a loop.
        {
            Stack <Tuple <TreeMember, TreeBranch> > arguments = new Stack <Tuple <TreeMember, TreeBranch> >();
            TreeBranch prevBranch = new TreeBranch();
            bool       stepBack   = false;

            foreach (TreeBranch rootBranch in root.Branches)
            {
                arguments.Push(Tuple.Create(rootBranch.Follow(root), rootBranch));

                while (arguments.Count > 0)
                {
                    Tuple <TreeMember, TreeBranch> nextArgument = arguments.Peek();
                    TreeMember member       = nextArgument.Item1;
                    TreeBranch parentBranch = nextArgument.Item2;
                    stepBack = false;

                    member.parentBranch = parentBranch;
                    ((TreeNode)parentBranch.Follow(member)).SetChild(parentBranch);

                    if (member.GetType() == typeof(TreeNode))
                    {
                        TreeNode node = (TreeNode)member;
                        if (node.Branches.Contains(prevBranch))
                        // If the previously-used branch is a member of this node's branches, that means we've already used the
                        // branches of this node, and can discard it.
                        {
                            stepBack = true;
                        }
                        else
                        {
                            foreach (TreeBranch branch in node.Branches)
                            {
                                if (branch != parentBranch)
                                {
                                    arguments.Push(Tuple.Create(branch.Follow(node), branch));
                                }
                            }
                        }
                    }
                    else
                    {
                        stepBack = true;
                    }

                    if (stepBack)
                    {
                        prevBranch = parentBranch;
                        arguments.Pop();
                    }
                }
            }
        }
Example #4
0
 public TreeNode GetParent()
 {
     if (parentBranch != null)
     {
         return((TreeNode)parentBranch.Follow(this));
     }
     else
     {
         return(null);
     }
 }
Example #5
0
        void CountNodeChildren()
        // Walk the tree up from the terminal nodes and count the children of each node.
        {
            if (!isRooted)
            {
                throw new InvalidOperationException("The tree must be rooted to count children.");
            }

            foreach (TreeNode terminalNode in terminalNodesList)
            {
                terminalNode.childCount = 2;

                TreeNode currentNode = terminalNode;

                while (currentNode != root)
                {
                    TreeBranch parentBranch = currentNode.parentBranch;
                    TreeNode   parentNode   = (TreeNode)parentBranch.Follow(currentNode);
                    TreeBranch otherChildBranch;

                    if (parentNode.childBranch1 == parentBranch)
                    {
                        otherChildBranch = parentNode.childBranch2;
                    }
                    else // should be childBranch2
                    {
                        otherChildBranch = parentNode.childBranch1;
                    }

                    if (otherChildBranch.Follow(parentNode).GetType() == typeof(TreeLeaf))
                    {
                        parentNode.childCount = currentNode.childCount + 1;
                    }
                    else if (parentNode.childCount > 0)
                    {
                        parentNode.childCount += currentNode.childCount;
                    }
                    else
                    {
                        // Need to wait for another terminal node to propogate up.
                        parentNode.childCount += currentNode.childCount;
                        break;
                    }

                    currentNode = parentNode;
                }
            }
        }
Example #6
0
        static double GetSumBranchLength(TreeMember member, TreeBranch baseBranch, bool includeBranch, out int numLeaves)
        // This is a recursive function
        //
        {
            // Algorithm:
            //   1. Store the branch length to the current member in "distance" (except the first if includeBranch is true).
            //   2. If the current member is a node, add the other branches to the stack and continue the loop.
            //      If the current member is a leaf, add 1 to the number of leaves, add the stemLength to the sumBranchLength, and subtract the length to this branch from the distance.
            //   3.

            double sumBranchLength = 0;

            numLeaves = 0;
            Stack <Tuple <TreeMember, TreeBranch> > arguments = new Stack <Tuple <TreeMember, TreeBranch> >();
            double distance = 0;

            arguments.Push(Tuple.Create(baseBranch.Follow(member), baseBranch));
            TreeBranch prevBranch = new TreeBranch();
            bool       stepBack   = false;

            while (arguments.Count > 0)
            {
                Tuple <TreeMember, TreeBranch> nextArgument = arguments.Peek();
                TreeMember nextMember     = nextArgument.Item1;
                TreeBranch nextBaseBranch = nextArgument.Item2;

                if (nextMember.GetType() == typeof(TreeNode))
                {
                    TreeNode node = (TreeNode)nextMember;
                    if (node.Branches.Contains(prevBranch))
                    // If the previously-used branch is a member of this node's branches, that means we've already used the
                    // branches of this node, and can discard it.
                    {
                        stepBack = true;
                    }
                    else
                    {
                        distance += nextBaseBranch.BranchLength;
                        foreach (TreeBranch branch in node.Branches)
                        {
                            if (branch != nextBaseBranch)
                            {
                                arguments.Push(Tuple.Create(branch.Follow(node), branch));
                            }
                        }
                    }
                }
                else
                // This is a leaf, so add the distance to the sum, increment the leaf count, and step backward
                {
                    distance        += nextBaseBranch.BranchLength;
                    sumBranchLength += distance;
                    numLeaves++;
                    stepBack = true;
                }

                if (stepBack)
                {
                    prevBranch = nextBaseBranch;
                    distance  -= nextBaseBranch.BranchLength;
                    arguments.Pop();
                    stepBack = false;
                }
            }

            if (!includeBranch)
            {   // If we didn't want to include the base branch length, correct for that here.
                sumBranchLength -= numLeaves * baseBranch.BranchLength;
            }

            return(sumBranchLength);
        }
Example #7
0
        void DetermineSteps()
        // Determine the groups to be used in each step of the alignment.
        // Step through the tree to find the terminal leaf-only nodes and step back to join them together,
        // with each step stored in a tuple, and the leaf groups 1 and 2 stored in lists in members 1 and 2 of the
        // tuple, respectively.
        // Possible to parallelize, but it looks like the overhead is generally too much for the work being done.
        // may want to test that on larger sets, however.
        {
            if (!isRooted)
            {
                throw new InvalidOperationException("The tree must be rooted to determine alignment steps.");
            }

            Dictionary <TreeNode, List <TreeLeaf> > waitingList = new Dictionary <TreeNode, List <TreeLeaf> >(); // Store the members of one child of the node until the other child has been evaluated.

            steps = new List <Tuple <ReadOnlyCollection <T>, ReadOnlyCollection <T>, double> >();

            foreach (TreeNode terminalNode in terminalNodesList)
            {
                List <TreeLeaf> group1 = new List <TreeLeaf>();
                TreeLeaf        leaf1  = (TreeLeaf)terminalNode.childBranch1.Follow(terminalNode);
                group1.Add(leaf1);
                List <TreeLeaf> group2 = new List <TreeLeaf>();
                TreeLeaf        leaf2  = (TreeLeaf)terminalNode.childBranch2.Follow(terminalNode);
                group2.Add(leaf2);


                steps.Add(CreateStep(group1, group2));

                TreeNode currentNode = terminalNode;

                List <TreeLeaf> childLeaves = new List <TreeLeaf>();
                childLeaves.Add(leaf1);
                childLeaves.Add(leaf2);

                while (currentNode != root)
                {
                    TreeBranch parentBranch = currentNode.parentBranch;
                    TreeNode   parentNode   = (TreeNode)parentBranch.Follow(currentNode);
                    TreeBranch otherChildBranch;

                    group1 = new List <TreeLeaf>();
                    group2 = new List <TreeLeaf>();

                    if (parentNode.childBranch1 == parentBranch)
                    {
                        otherChildBranch = parentNode.childBranch2;
                    }
                    else // should be childBranch2
                    {
                        otherChildBranch = parentNode.childBranch1;
                    }

                    if (otherChildBranch.Follow(parentNode).GetType() == typeof(TreeLeaf))
                    // The other child is a leaf, so we're okay.
                    {
                        group1 = childLeaves;
                        TreeLeaf otherChildLeaf = (TreeLeaf)otherChildBranch.Follow(parentNode);
                        group2.Add(otherChildLeaf);
                    }
                    else if (waitingList.ContainsKey(parentNode))
                    // The other child is a node which was waiting for the other children to be evaluated.
                    {
                        group1 = childLeaves.ToList <TreeLeaf>();
                        group2 = waitingList[parentNode];
                    }
                    else
                    // The other child is a node. We'll need to save the current child and store the values
                    // for later. This also means we need to start over with another terminal node.
                    {
                        waitingList.Add(parentNode, childLeaves);
                        break;
                    }

                    steps.Add(CreateStep(group1, group2));

                    foreach (TreeLeaf leaf in group2)
                    {
                        childLeaves.Add(leaf);
                    }

                    currentNode = parentNode;
                }
            }
        }
Example #8
0
        public void CalculateSimilarities()
        // Construct a similarities matrix
        // Clustal does this by storing the path to root for each leaf (storing the distance), then finds the common ancestor
        // for each pair, storing the distance from the other sequence to it.
        //
        // I think a better implementation would be to loop over the leaves to get their paths to root, then for each pair,
        // walk their paths until they diverge
        {
            similarityMatrix = new double[leavesCount, leavesCount];

            Dictionary <TreeLeaf, List <Tuple <TreeNode, double> > > pathsToRoot = new Dictionary <TreeLeaf, List <Tuple <TreeNode, double> > >();

            foreach (TreeLeaf leaf in leavesList)
            {
                List <Tuple <TreeNode, double> > pathToRoot = new List <Tuple <TreeNode, double> >();

                double     distance     = 0;
                TreeBranch parentBranch = leaf.parentBranch;
                TreeNode   parentNode   = (TreeNode)parentBranch.Follow(leaf);

                while (true)
                {
                    distance += parentBranch.BranchLength;
                    pathToRoot.Add(Tuple.Create(parentNode, distance));
                    parentBranch = parentNode.parentBranch;
                    if (parentBranch != null)
                    {
                        parentNode = (TreeNode)parentBranch.Follow(parentNode);
                    }
                    else
                    {
                        break;
                    }
                }
                pathsToRoot.Add(leaf, pathToRoot);
            }


            for (int i = 0; i < leavesCount - 1; i++)
            {
                TreeLeaf leafI = leavesList[i];
                List <Tuple <TreeNode, double> > pathToRootI = pathsToRoot[leafI];

                for (int j = i + 1; j < leavesCount; j++)
                {
                    TreeLeaf leafJ = leavesList[j];
                    List <Tuple <TreeNode, double> > pathToRootJ = pathsToRoot[leafJ];
                    bool found = false;

                    foreach (Tuple <TreeNode, double> pathMemberI in pathToRootI)
                    {
                        foreach (Tuple <TreeNode, double> pathmemberJ in pathToRootJ)
                        {
                            if (pathMemberI.Item1 == pathmemberJ.Item1)
                            {
                                found = true;
                                similarityMatrix[i, j] = 1 - (pathMemberI.Item2 + pathmemberJ.Item2);
                                break;
                            }
                        }
                        if (found)
                        {
                            break;
                        }
                    }
                }
            }

            // Then Clustal forces any values less than 0.01 to be 0.01 (within the sequence ranges)
            // and sets small values above 1 to 1, but values above 1.1 go into an error handling method.
            // I won't implement this yet. Note that this is done while they are still in distances, not
            // similarities.
        }