private async Task Recluster(List <ClusterNode> nodes, Dictionary <ClusterNode, List <IClusterableMatch> > extendedClusters, List <IClusterableMatch> immediateFamily, Dictionary <int, IClusterableMatch> matchesByIndex, ConcurrentDictionary <int, float[]> matrix) { _progressData.Reset($"Reclustering {extendedClusters.Count} primary clusters", extendedClusters.Count); var primaryClustersTasks = extendedClusters .Where(kvp => kvp.Value.Count > 0) .Select(async kvp => { var nodeToRecluster = kvp.Key; var additionalMatches = kvp.Value; var leafNodesByIndex = nodeToRecluster.GetOrderedLeafNodes().ToDictionary(leafNode => leafNode.Index); var clusterableMatches = leafNodesByIndex.Keys.Select(index => matchesByIndex[index]).Concat(additionalMatches).ToList(); var maxIndex = additionalMatches.Max(match => match.Coords.Max()); _matrixBuilder.ExtendMatrix(matrix, additionalMatches, maxIndex); var reclusteredNodes = await ClusterAsync(clusterableMatches, immediateFamily, clusterableMatches.Max(match => match.Index), matrix, ProgressData.SuppressProgress).ConfigureAwait(false); if (reclusteredNodes.Count == 0) { _progressData.Increment(); return(nodeToRecluster); } var reclusteredNode = reclusteredNodes.First(); foreach (var reclusteredLeafNode in reclusteredNode.GetOrderedLeafNodes()) { if (leafNodesByIndex.TryGetValue(reclusteredLeafNode.Index, out var originalLeafNode)) { reclusteredLeafNode.Parent.ReplaceChild(reclusteredLeafNode, originalLeafNode); } } if (nodeToRecluster.Parent != null) { nodeToRecluster.Parent.ReplaceChild(nodeToRecluster, reclusteredNode); } else { nodes.Remove(nodeToRecluster); nodes.Add(reclusteredNode); } _progressData.Increment(); return(reclusteredNode); }); var primaryClusters = await Task.WhenAll(primaryClustersTasks); _progressData.Reset(); }
private async Task Recluster(ICollection <ClusterNode> nodes, Dictionary <Node, List <IClusterableMatch> > extendedClusters, List <IClusterableMatch> immediateFamily, IReadOnlyDictionary <int, IClusterableMatch> matchesByIndex, ConcurrentDictionary <int, float[]> matrix) { _progressData.Reset($"Reclustering {extendedClusters.Count} primary clusters", extendedClusters.Count); var primaryClustersTaskData = extendedClusters .Where(kvp => kvp.Value.Count > 0) .Select(kvp => { var nodeToRecluster = kvp.Key; var additionalMatches = kvp.Value; var leafNodesByIndex = nodeToRecluster.GetOrderedLeafNodes().ToDictionary(leafNode => leafNode.Index); var clusterableMatches = leafNodesByIndex.Keys.Select(index => matchesByIndex[index]).Concat(additionalMatches).ToList(); return(new { NodeToRecluster = nodeToRecluster, AdditionalMatches = additionalMatches, LeafNodesByIndex = leafNodesByIndex, ClusterableMatches = clusterableMatches, }); }).ToList(); var additionalMatchesDistinct = primaryClustersTaskData.SelectMany(data => data.AdditionalMatches).Distinct().ToList(); var maxIndex = additionalMatchesDistinct.SelectMany(match => match.Coords).DefaultIfEmpty(-1).Max(); if (maxIndex < 0) { _progressData.Reset(); return; } _matrixBuilder.ExtendMatrix(matrix, additionalMatchesDistinct, maxIndex); var primaryClustersTasks = primaryClustersTaskData .Select(async data => { var reclusteredNodes = await ClusterAsync(data.ClusterableMatches, immediateFamily, matrix, ProgressData.SuppressProgress).ConfigureAwait(false); if (reclusteredNodes.Count == 0) { _progressData.Increment(); return(data.NodeToRecluster); } var nodeToReclusterParent = data.NodeToRecluster.Parent; var reclusteredNode = reclusteredNodes.First(); foreach (var reclusteredLeafNode in reclusteredNode.GetOrderedLeafNodes()) { if (data.LeafNodesByIndex.TryGetValue(reclusteredLeafNode.Index, out var originalLeafNode)) { reclusteredLeafNode.Parent.ReplaceChild(reclusteredLeafNode, originalLeafNode); } } if (nodeToReclusterParent != null) { nodeToReclusterParent.ReplaceChild(data.NodeToRecluster, reclusteredNode); } else { if (data.NodeToRecluster is ClusterNode clusterNode) { nodes.Remove(clusterNode); } nodes.Add(reclusteredNode); } _progressData.Increment(); return(reclusteredNode); }); await Task.WhenAll(primaryClustersTasks); _progressData.Reset(); }