/// <summary> /// Method to create a tree with two children /// </summary> public static BifiTree GetBifiTree(string _label, BifiTree _left, decimal _leftBranch, BifiTree _right, decimal _rightBranch) { BifiTree treeReturn = new BifiTree(_label); treeReturn.SetLeft(_left, _leftBranch); treeReturn.SetRight(_right, _rightBranch); return(treeReturn); }
/// <summary> /// Calculates a matrix of the summed edge distances /// <paramref name="_rootedTree">Tree with dummy root</paramref> /// </summary> private void BuildTreeMatrix(BifiTree _rootedTree) { // Initalize tree matrix decimal[,] treeMatrix = new decimal[StartMatrix.GetLength(0), StartMatrix.GetLength(1)]; // Then iterate through matrix, get the labels and look in the rootedTree for the distances // Sum them up and write the value in the treeMatrix for (int i = 0; i < treeMatrix.GetLength(0); i++) { for (int j = 0; j < treeMatrix.GetLength(1); j++) { // Get labels for this matrix entry string x_label = StartLabels[i]; string y_label = StartLabels[j]; if (i == j) { treeMatrix[i, j] = 0; } else { List <BifiTree> treeX = new List <BifiTree>(), treeY = new List <BifiTree>(); _rootedTree.GetWay(x_label, treeX); _rootedTree.GetWay(y_label, treeY); // Reverse the order of the list treeX.Reverse(); treeY.Reverse(); // Search through the List till we found the minimal root node while (treeX.Count > 1 && treeY.Count > 1 && treeX[1] == treeY[1]) { treeX.RemoveAt(0); treeY.RemoveAt(0); } decimal dist = 0m; // Calculate backwarts int List X for (int intX = treeX.Count - 1; intX >= 1; intX--) { dist += (treeX[intX - 1].Left == treeX[intX] ? treeX[intX - 1].LeftBranch : treeX[intX - 1].RightBranch).Value; } // And frontwarts in List Y for (int intY = 0; intY < treeY.Count - 1; intY++) { dist += (treeY[intY].Left == treeY[intY + 1] ? treeY[intY].LeftBranch : treeY[intY].RightBranch).Value; } treeMatrix[i, j] = dist; } } } TreeMatrix = treeMatrix; }
/// <summary> /// Method to create a tree with one child /// </summary> public static BifiTree GetBifiTree(string _label, BifiTree _child, decimal _branch, LeftRight _leftRight) { BifiTree treeReturn = new BifiTree(_label); if (_leftRight == LeftRight.Left) { treeReturn.SetLeft(_child, _branch); } else { treeReturn.SetRight(_child, _branch); } return(treeReturn); }
/// <summary> /// Set right child with branch length /// </summary> /// <param name="_right">Right child</param> /// <param name="_rightBranch">Branch length to right child</param> public void SetRight(BifiTree _right, decimal _rightBranch) { Right = _right; RightBranch = _rightBranch; }
/// <summary> /// Set left child with branch length /// </summary> /// <param name="_left">Left child</param> /// <param name="_leftBranch">Branch length to left child</param> public void SetLeft(BifiTree _left, decimal _leftBranch) { Left = _left; LeftBranch = _leftBranch; }
/// <summary> /// Controls neighbor-joining sub-steps /// </summary> private void NeighborJoiningController(decimal[,] _distMatrix, Dictionary <int, string> _labels, Dictionary <int, int> _nodeLevels) { //Terminate or proceed? if (_distMatrix.GetLength(0) > 2) { //Get average distances Dictionary <int, decimal> averages = GetAverageDistances(_distMatrix); //Get intermediate matrix decimal[,] intermediate = SubtractAverageDistance(averages, _distMatrix); //Choose neigbors by minimal value in intermediate matrix List <Tuple <int, int> > minimals = GetMinimalsFromMatrix(intermediate); Tuple <int, int> neighbors = ChooseNeighbors(minimals, _nodeLevels); //Define new node string newNode = _labels[neighbors.Item1] + _labels[neighbors.Item2]; //Joining neighbors //Calculate distance from OldA to New and add to Tuple list decimal d_oldA_new = (_distMatrix[neighbors.Item1, neighbors.Item2] + averages[neighbors.Item1] - averages[neighbors.Item2]) / 2; NodesAndEdges.Add(Tuple.Create(_labels[neighbors.Item1], d_oldA_new, newNode)); //Calcutate distance from OldB to New and add to Tuple list decimal d_oldB_new = _distMatrix[neighbors.Item1, neighbors.Item2] - d_oldA_new; NodesAndEdges.Add(Tuple.Create(_labels[neighbors.Item2], d_oldB_new, newNode)); //Add children to tree Nodes.Add(BifiTree.GetBifiTree(newNode, Nodes.SingleOrDefault(a => a.Label == _labels[neighbors.Item1]), d_oldA_new, Nodes.SingleOrDefault(a => a.Label == _labels[neighbors.Item2]), d_oldB_new)); //Delete children from node list Nodes.Remove(Nodes.SingleOrDefault(a => a.Label == _labels[neighbors.Item1])); Nodes.Remove(Nodes.SingleOrDefault(a => a.Label == _labels[neighbors.Item2])); //Reduce labels Dictionary <int, string> reducedLabels = new Dictionary <int, string>(); Dictionary <int, int> reducedLevels = new Dictionary <int, int>(); for (int count = 0; count <= _labels.Count - 1; count++) { if (count == neighbors.Item1) { reducedLabels.Add(reducedLabels.Count, newNode); // When cluster is added, increment level counter level++; reducedLevels.Add(reducedLevels.Count, level); } else if (count == neighbors.Item2) { continue; } else { reducedLabels.Add(reducedLabels.Count, _labels[count]); reducedLevels.Add(reducedLevels.Count, _nodeLevels[count]); } } Dictionary <string, int> dicIndex2Label = new Dictionary <string, int>(); foreach (KeyValuePair <int, string> kvPairAktuell in _labels) { dicIndex2Label.Add(kvPairAktuell.Value, kvPairAktuell.Key); } //Reduce matrix decimal[,] reducedMatrix = new decimal[_distMatrix.GetLength(0) - 1, _distMatrix.GetLength(1) - 1]; for (int i = 0; i < reducedMatrix.GetLength(0); i++) { for (int j = 0; j < reducedMatrix.GetLength(1); j++) { if (i == j) { reducedMatrix[i, j] = 0; } else if (reducedLabels[i] == newNode) { decimal dist_new1_j = _distMatrix[neighbors.Item1, dicIndex2Label[reducedLabels[j]]]; decimal dist_new2_j = _distMatrix[neighbors.Item2, dicIndex2Label[reducedLabels[j]]]; decimal dist_new1_new2 = _distMatrix[neighbors.Item1, neighbors.Item2]; reducedMatrix[i, j] = (dist_new1_j + dist_new2_j - dist_new1_new2) / 2; } else if (reducedLabels[j] == newNode) { decimal dist_i_new1 = _distMatrix[dicIndex2Label[reducedLabels[i]], neighbors.Item1]; decimal dist_i_new2 = _distMatrix[dicIndex2Label[reducedLabels[i]], neighbors.Item2]; decimal dist_new1_new2 = _distMatrix[neighbors.Item1, neighbors.Item2]; reducedMatrix[i, j] = (dist_i_new1 + dist_i_new2 - dist_new1_new2) / 2; } else { reducedMatrix[i, j] = _distMatrix[dicIndex2Label[reducedLabels[i]], dicIndex2Label[reducedLabels[j]]]; } } } //Call myself again NeighborJoiningController(reducedMatrix, reducedLabels, reducedLevels); } // If matrix is reduced to two elements if (terminator == false) { // Add last Triple to NodesAndEdges if (_distMatrix[0, 0] == 0 && _distMatrix[1, 1] == 0 && _distMatrix[0, 1] == _distMatrix[1, 0]) { //Create last edge NodesAndEdges.Add(Tuple.Create(_labels[0], _distMatrix[0, 1], _labels[1])); /* The smallest possible unrooted tree has 3 edges. * Therefore, the imaginary root node neccesary for the Newick string has three children. * Because this can't be done with a strictly bifurcating tree, * the last edge between two BifiTrees needs to be drawn here! */ string newickA = Nodes.SingleOrDefault(a => a.Label == _labels[0]).GetNewickString(); string newickB = Nodes.SingleOrDefault(a => a.Label == _labels[1]).GetNewickString(); // The brackets of one of the trees need to be deleted newickA = newickA.Substring(1, newickA.Length - 2); // To the other tree with brackets the last distance needs to be appended newickB = newickB + ":" + _distMatrix[0, 1].ToString("0.#####", CultureInfo.CreateSpecificCulture("en-GB")); NewickTree = "(" + newickA + "," + newickB + ");"; BifiTree root = BifiTree.GetBifiTree("root", Nodes.SingleOrDefault(a => a.Label == _labels[0]), 0m, Nodes.SingleOrDefault(a => a.Label == _labels[1]), _distMatrix[0, 1]); BuildTreeMatrix(root); MinEdge = this.NodesAndEdges.Min(item => Math.Abs(item.Item2)); } // Still needs to be written to .txt // This should be done via UI... terminator = true; } }