/// <summary> /// Thread operation to calculate statistics for [cluster]. /// /// [cluster] is guarenteed to be unique, so needn't be locked. /// </summary> private static void Thread_CalculateClusterStatistics([Const] Core core, [Const] EClustererStatistics statistics, [MutableSafe] Cluster cluster, [MutableSafe] ProgressParallelHandler prog) { prog.SafeIncrement(); cluster.CalculateAveragedStatistics(); cluster.CalculateCommentFlags(); Dictionary <string, double> clusterStatistics = cluster.ClusterStatistics; List <Assignment> assignments = cluster.Assignments.List; int hcomp, numcomp, hpeak, numpath; ClustererStatisticsHelper.CalculateHighestCompounds(cluster, out hcomp, out numcomp); ClustererStatisticsHelper.CalculateHighestPeaks(cluster, out hpeak, out numpath); clusterStatistics[STAT_CLUSTER_AVERAGE_HIGHEST_NUM_COMPOUNDS] = hcomp; clusterStatistics[STAT_CLUSTER_AVERAGE_NUM_COMPOUNDS] = numcomp; clusterStatistics[STAT_CLUSTER_AVERAGE_HIGHEST_NUM_PEAKS] = hpeak; clusterStatistics[STAT_CLUSTER_AVERAGE_NUM_PATHWAYS] = numpath; ////////////////////////// // GROUP STATS (cluster) if (statistics.HasFlag(EClustererStatistics.ClusterAverages)) { AddAveragedStatistics(core, clusterStatistics, assignments); } }
/// <summary> /// Thread operation fo calculate statistics for [stat]. /// /// [stat] is guarenteed to be unique, however stat.Assignment is not, hence stat.Assignment must be locked. /// /// Currently only stat.Assignment.AssignmentStatistics is the only member to be R/W locked, since that is all /// that is modified. /// </summary> private static void Thread_CalculateAssignmentStatistics([Const] EClustererStatistics statistics, [MutableUnsafe] ForStat stat, [Const] Cluster[] realClusters, [Const] ConfigurationMetric metric, [MutableSafe] ProgressParallelHandler prog) { prog.SafeIncrement(); // STATS: Distance from avg if (stat.ClusterVector != null) { // Euclidean if (statistics.HasFlag(EClustererStatistics.EuclideanFromAverage)) { double ed = Maths.Euclidean(stat.AssignmentVector.Values, stat.ClusterVector); stat.Assignment.AssignmentStatistics.ThreadSafeIndex(CreatePartialKey(stat.ObsFilter, STAT_ASSIGNMENT_EUCLIDEAN_FROM_AVG), ed); stat.Assignment.AssignmentStatistics.ThreadSafeIndex(CreatePartialKey(stat.ObsFilter, STAT_ASSIGNMENT_EUCLIDEAN_FROM_AVG_SQUARED), ed * ed); } // Custom (if applicable) if (metric != null && statistics.HasFlag(EClustererStatistics.DistanceFromAverage) && !(metric.Args.Id == Algo.ID_METRIC_EUCLIDEAN && statistics.HasFlag(EClustererStatistics.EuclideanFromAverage))) { string key1 = metric.ToString() + STAT_ASSIGNMENT_DISTANCE_FROM_AVG; string key2 = metric.ToString() + STAT_ASSIGNMENT_DISTANCE_FROM_AVG_SQUARED; double dd = metric.Calculate(stat.AssignmentVector.Values, stat.ClusterVector); stat.Assignment.AssignmentStatistics.ThreadSafeIndex(CreatePartialKey(stat.ObsFilter, key1), dd); stat.Assignment.AssignmentStatistics.ThreadSafeIndex(CreatePartialKey(stat.ObsFilter, key2), dd * dd); } } // STATS: Silhouette Cluster nextNearestCluster = null; if (statistics.HasFlag(EClustererStatistics.SilhouetteWidth)) { double silhouetteWidth; double nextNearestClusterId; ClustererStatisticsHelper.CalculateSilhouette(stat, realClusters, out silhouetteWidth, out nextNearestCluster); if (!double.TryParse(nextNearestCluster.ShortName, out nextNearestClusterId)) { nextNearestClusterId = double.NaN; } // Silhouette stat.Assignment.AssignmentStatistics.ThreadSafeIndex(CreatePartialKey(stat.ObsFilter, STAT_ASSIGNMENT_SILHOUETTE_WIDTH), silhouetteWidth); stat.Assignment.AssignmentStatistics.ThreadSafeIndex(CreatePartialKey(stat.ObsFilter, STAT_ASSIGNMENT_NEXT_NEAREST_CLUSTER), nextNearestClusterId); } // STATS: Score if (stat.ObsFilter == null) { // Score stat.Assignment.AssignmentStatistics.ThreadSafeIndex(STAT_ASSIGNMENT_SCORE, stat.Assignment.Score); // Next nearest cluster stat.Assignment.NextNearestCluster = nextNearestCluster; // Only one ForStat per Assignment has ObsFilter == null so thread safe not required } }
/// <summary> /// Calculates statistics for the algorithm as a whole. /// </summary> private void CalculateSummaryStatistics(Core core, EClustererStatistics statistics, Cluster[] realClusters) { if (statistics.HasFlag(EClustererStatistics.AlgorithmAverages)) { AddAveragedStatistics(core, this.ClustererStatistics, Assignments); } if (statistics.HasFlag(EClustererStatistics.BayesianInformationCriterion)) { this.ClustererStatistics[STAT_CLUSTERER_BIC] = ClustererStatisticsHelper.CalculateBic(realClusters, Assignments); } }