public static decimal DistanceNodeToFinalParent(UpgmaNode node, int recursiveLevel = 0) { if (node.ParentNodeA != null) { var r = node.DistanceParentNodeA + DistanceNodeToFinalParent(node.ParentNodeA, recursiveLevel + 1); if (recursiveLevel == 0) { //Console.WriteLine(String.Join("_", node.NodeIdList) + " distance to final parent: " + r); } return(r); } if (node.ParentNodeB != null) { var r = node.DistanceParentNodeB + DistanceNodeToFinalParent(node.ParentNodeB, recursiveLevel + 1); if (recursiveLevel == 0) { //Console.WriteLine(String.Join("_", node.NodeIdList) + " distance to final parent: " + r); } return(r); } if (!node.IsLeafNode()) { throw new Exception("Node has no parents but is not a leaf node"); } return(0); }
public static List <UpgmaNode> CopyNetwork(List <UpgmaNode> network) { var networkCopy = new List <UpgmaNode>(); for (int index = 0; index < network.Count; index++) { var node = network[index]; var nodeCopy = new UpgmaNode(); nodeCopy.VectorIndexes = new List <int>(node.VectorIndexes); networkCopy.Add(nodeCopy); } for (int index = 0; index < network.Count; index++) { var node = network[index]; var nodeCopy = networkCopy[index]; if (node.ChildNode != null) { nodeCopy.ChildNode = networkCopy[network.IndexOf(node.ChildNode)]; } if (node.ParentNodeA != null) { nodeCopy.ParentNodeA = networkCopy[network.IndexOf(node.ParentNodeA)]; } if (node.ParentNodeB != null) { nodeCopy.ParentNodeB = networkCopy[network.IndexOf(node.ParentNodeB)]; } nodeCopy.DistanceChildNode = node.DistanceChildNode; nodeCopy.DistanceParentNodeA = node.DistanceParentNodeA; nodeCopy.DistanceParentNodeB = node.DistanceParentNodeB; nodeCopy.DistanceMatrixIterationNumber = node.DistanceMatrixIterationNumber; foreach (var parentNode in node.ParentList) { UpgmaNode parentNodeCopy = null; if (parentNode.Node != null) { parentNodeCopy = networkCopy[network.IndexOf((UpgmaNode)parentNode.Node)]; } nodeCopy.ParentList.Add(new GenericNodeWithDistance(parentNodeCopy, parentNode.DistanceToNode)); } foreach (var childNode in node.ChildrenList) { UpgmaNode childNodeCopy = null; if (childNode.Node != null) { childNodeCopy = networkCopy[network.IndexOf((UpgmaNode)childNode.Node)]; } nodeCopy.ChildrenList.Add(new GenericNodeWithDistance(childNodeCopy, childNode.DistanceToNode)); } } return(networkCopy); }
public UpgmaNode(int distanceMatrixIterationNumber, UpgmaNode parentNodeA, decimal distanceParentNodeA, UpgmaNode parentNodeB, decimal distanceParentNodeB, UpgmaNode childNode, decimal distanceChildNode) { DistanceMatrixIterationNumber = distanceMatrixIterationNumber; ParentNodeA = parentNodeA; DistanceParentNodeA = distanceParentNodeA; ParentNodeB = parentNodeB; DistanceParentNodeB = distanceParentNodeB; ChildNode = childNode; DistanceChildNode = distanceChildNode; }
public static void Upgma(List <List <decimal> > distanceMatrix, List <string> vectorNames, int minimumOutputTreeLeafs, out List <List <UpgmaNode> > nodeListList, out List <List <string> > treeListList, out List <string> finalTreeLeafOrderList, bool newickTreeEveryIteration = false, ProgressActionSet progressActionSet = null) { if (distanceMatrix == null || distanceMatrix.Count == 0 || distanceMatrix.Select(a => a.Count).Contains(0)) { throw new ArgumentOutOfRangeException(nameof(distanceMatrix), "distance matrix is null or empty"); } //var makeIterationTrees = false; //var distanceMatrixCache = new List<decimal[,]>(); nodeListList = new List <List <UpgmaNode> >(); var nodeList = new List <UpgmaNode>(); treeListList = new List <List <string> >(); finalTreeLeafOrderList = new List <string>(); // store a list of every index merged to each index position in the distance matrix var distanceMatrixMap = new List <List <int> >(); //var distanceMatrixMapCache = new List<List<List<int>>>(); for (var matrixIndex = 0; matrixIndex < distanceMatrix.Count; matrixIndex++) { distanceMatrixMap.Add(new List <int>()); distanceMatrixMap[matrixIndex].Add(matrixIndex); var node = new UpgmaNode(); node.VectorIndexes.Add(matrixIndex); //node.IsLeafNode = true; node.CopyPropertiesToGenericNodeProperties(); nodeList.Add(node); } int itemsCompleted = 0; int itemsTotal = distanceMatrix.Count; var startTicks = DateTime.Now.Ticks; ProgressActionSet.StartAction(itemsTotal, progressActionSet); while (distanceMatrix.Count > 1 && distanceMatrix.Select(a => a.Count).Max() > 1) { // find which indexes to join var lowestIndexes = UpgmaLowestDistanceIndexes(distanceMatrix); var lowestValue = distanceMatrix[lowestIndexes.X][lowestIndexes.Y]; var lowerIndex = lowestIndexes.X < lowestIndexes.Y ? lowestIndexes.X : lowestIndexes.Y; var higherIndex = lowestIndexes.X > lowestIndexes.Y ? lowestIndexes.X : lowestIndexes.Y; var nodeDistance = lowestValue / 2; if (lowerIndex == higherIndex) { throw new Exception("lower index and higher index have the same value"); } // Take parent node identities var parentNodeIdA = distanceMatrixMap[lowerIndex].OrderBy(o => o).ToList(); var parentNodeIdB = distanceMatrixMap[higherIndex].OrderBy(o => o).ToList(); var childNodeId = new List <int>(); childNodeId.AddRange(parentNodeIdA); childNodeId.AddRange(parentNodeIdB); childNodeId = childNodeId.Distinct().ToList(); // Find if parent nodes already exist var parentNodeCandidatesA = nodeList.Where(a => a.VectorIndexes.OrderBy(o => o).SequenceEqual(parentNodeIdA)).ToList(); var parentNodeCandidatesB = nodeList.Where(a => a.VectorIndexes.OrderBy(o => o).SequenceEqual(parentNodeIdB)).ToList(); UpgmaNode parentNodeA; parentNodeA = parentNodeCandidatesA[0]; UpgmaNode parentNodeB; parentNodeB = parentNodeCandidatesB[0]; var childNode = new UpgmaNode(); nodeList.Add(childNode); parentNodeA.ChildNode = childNode; parentNodeB.ChildNode = childNode; childNode.ParentNodeA = parentNodeA; childNode.ParentNodeB = parentNodeB; var parentTotalDistanceA = DistanceNodeToFinalParent(parentNodeA); var parentTotalDistanceB = DistanceNodeToFinalParent(parentNodeB); parentNodeA.DistanceChildNode = nodeDistance - parentTotalDistanceA; parentNodeB.DistanceChildNode = nodeDistance - parentTotalDistanceB; childNode.DistanceParentNodeA = nodeDistance - parentTotalDistanceA; childNode.DistanceParentNodeB = nodeDistance - parentTotalDistanceB; childNode.DistanceMatrixIterationNumber = itemsCompleted;// distanceMatrixCache.Count - 1; childNode.VectorIndexes = childNodeId; parentNodeA.CopyPropertiesToGenericNodeProperties(); parentNodeB.CopyPropertiesToGenericNodeProperties(); childNode.CopyPropertiesToGenericNodeProperties(); // rearrange the matrix map with the new indexes joined distanceMatrixMap[higherIndex] distanceMatrixMap[lowerIndex].AddRange(distanceMatrixMap[higherIndex]); distanceMatrixMap.RemoveAt(higherIndex); // recalculate distance matrix with indexes joined with mean average distanceMatrix = UpgmaDistanceMatrixNextIteration(distanceMatrix, lowestIndexes); if (newickTreeEveryIteration) { List <string> treeLeafOrderList; var iterationTree = Newick.NewickTreeFormat(nodeList.ToList <GenericNode>(), vectorNames, out treeLeafOrderList, minimumOutputTreeLeafs); treeListList.Add(iterationTree); finalTreeLeafOrderList = treeLeafOrderList; nodeListList.Add(UpgmaNode.CopyNetwork(nodeList)); } itemsCompleted++; ProgressActionSet.ProgressAction(1, progressActionSet); ProgressActionSet.EstimatedTimeRemainingAction(startTicks, itemsCompleted, itemsTotal, progressActionSet); } if (!newickTreeEveryIteration) { List <string> treeLeafOrderList; var iterationTree = Newick.NewickTreeFormat(nodeList.ToList <GenericNode>(), vectorNames, out treeLeafOrderList, minimumOutputTreeLeafs); treeListList.Add(iterationTree); finalTreeLeafOrderList = treeLeafOrderList; nodeListList.Add(UpgmaNode.CopyNetwork(nodeList)); } ProgressActionSet.FinishAction(true, progressActionSet); }