Example #1
0
        /// <summary>
        /// Returns the distance matrix for a set of peaks.
        /// </summary>
        public static DistanceMatrix Create(Core core, IntensityMatrix valueMatrix, ConfigurationMetric metric, ProgressReporter prog)
        {
            int n = valueMatrix.NumRows;

            int bytesRequired = (n * n) * 8;
            int mbRequired    = bytesRequired / (1024 * 1024);
            int limit         = core.Options.ObjectSizeLimit * 1024 * 1024;

            if (bytesRequired > limit)
            {
                // It ain't gonna happen. I'm not creating a distance matrix over 500Mb
                throw new InvalidOperationException("n = " + n + " input vectors. n * n = " + (n * n) + " elements in the distance matrix. 8 bytes per element gives " + (n * n * 8) + " bytes, or " + mbRequired + " megabytes. ObjectSizeLimit is " + core.Options.ObjectSizeLimit + " Mb. Reduce the number of input vectors by filtering the data, or change the limit from the preferences menu. Some algorithms also have the option to disable the distance matrix.");
            }

            double[,] s = new double[n, n];
            prog.Enter("Calculating distance matrix");

            for (int i = 0; i < n; i++)
            {
                prog.SetProgress(i, n);

                for (int j = 0; j < n; j++)
                {
                    s[i, j] = metric.Calculate(valueMatrix.Vectors[i], valueMatrix.Vectors[j]);
                }
            }

            prog.Leave();

            return(new DistanceMatrix(s, valueMatrix));
        }
Example #2
0
        /// <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
            }
        }
Example #3
0
        /// <summary>
        /// Calculates the score for variable v against this cluster.
        /// The centres must have been called first by calling [SetCentre].
        /// </summary>
        public double CalculateScore(IReadOnlyList <double> vector, EDistanceMode distanceMode, ConfigurationMetric distanceMetric)
        {
            switch (distanceMode)
            {
            case EDistanceMode.ClosestCentre:
                return(this.Centres.Count == 0
                        ? double.NaN
                        : (this.Centres.Cast <double[]>().Select(centre => distanceMetric.Calculate(vector, centre))).Min());

            case EDistanceMode.AverageToAllCentres:
                double totalDistance = this.Centres.Cast <double[]>().Sum(centre => distanceMetric.Calculate(vector, centre));

                return(totalDistance / this.Centres.Count);

            default:
                throw new InvalidOperationException("Invalid switch: " + distanceMode.ToString());
            }
        }