コード例 #1
0
ファイル: Core.cs プロジェクト: mjr129/metaboclust
        /// <summary>
        /// Adds and applies a single new clustering algorithm.
        /// </summary>
        public void AddClusterer(ConfigurationClusterer toAdd, ProgressReporter setProgress)
        {
            List <ConfigurationClusterer> existing = new List <ConfigurationClusterer>(this.Clusterers);

            existing.Add(toAdd);
            this.SetClusterers(existing.ToArray(), setProgress, false);
        }
コード例 #2
0
        void create_clusters_from_pathways()
        {
            this.BeginWait("Create clusters from pathways", false);

            var args = new ArgsClusterer(Algo.ID_PATFROMPATH, this._core.Matrices.First(), null, null, null, false, EClustererStatistics.None, null, "P:")
            {
                OverrideDisplayName = "create_clusters_from_pathways",
            };

            ConfigurationClusterer config = new ConfigurationClusterer()
            {
                Args = args
            };

            this._core.AddClusterer(config, new ProgressReporter(this));

            this.EndWait();
        }
コード例 #3
0
        /// <summary>IMPLEMENTS ClustererBase</summary>
        protected override IEnumerable <Cluster> Cluster(IntensityMatrix vmatrix, DistanceMatrix dmatrix, ArgsClusterer args, ConfigurationClusterer tag, ProgressReporter prog)
        {
            Dictionary <Cluster, Cluster>          result   = new Dictionary <Cluster, Cluster>();
            WeakReference <ConfigurationClusterer> wrMethod = (WeakReference <ConfigurationClusterer>)args.Parameters[0];
            ConfigurationClusterer existing = wrMethod.GetTargetOrThrow();
            var existingResults             = existing.Results;

            foreach (Vector vector in vmatrix.Vectors)
            {
                Cluster existingCluster = existingResults.Assignments.FirstOrDefault(z => z.Peak == vector.Peak)?.Cluster;

                if (existingCluster != null)
                {
                    Cluster newCluster = result.GetOrCreate(existingCluster, xc => new Cluster(xc.ShortName, tag));

                    newCluster.Assignments.Add(new Assignment(vector, newCluster, double.NaN));
                }
            }

            return(result.Values);
        }
コード例 #4
0
        protected override IEnumerable <Cluster> Cluster(IntensityMatrix vmatrix, DistanceMatrix UNUSED, ArgsClusterer args, ConfigurationClusterer tag, ProgressReporter prog)
        {
            ConfigurationClusterer config     = ((WeakReference <ConfigurationClusterer>)args.Parameters[0]).GetTargetOrThrow();
            List <Cluster>         myClusters = new List <Cluster>();

            // Iterate existing clusters
            prog.Enter("Iterating existing");

            for (int index = 0; index < config.Results.Clusters.Length; index++)
            {
                Cluster cluster = config.Results.Clusters[index];
                prog.SetProgress(index, config.Results.Clusters.Length);

                if (!cluster.States.HasFlag(Session.Main.Cluster.EStates.Insignificants))
                {
                    // Get the centre
                    IReadOnlyList <double> centre = cluster.GetCentre(ECentreMode.Average, ECandidateMode.Assignments)[0];

                    // Reorder the centre to match our vmatrix
                    // centre = Reorder(centre, config.Results.VMatrix.Conditions, vmatrix.Conditions);

                    Cluster myCluster = new Cluster(cluster.DisplayName, tag);
                    myCluster.Exemplars.Add(centre);
                    myClusters.Add(myCluster);
                }
            }

            prog.Leave();

            prog.Enter("Assigning peaks");
            LegacyClustererHelper.Assign(vmatrix, myClusters, ECandidateMode.Exemplars, args.Distance, prog);
            prog.Leave();

            Cluster matchCluster = new Cluster("Matches", tag);

            matchCluster.States |= Session.Main.Cluster.EStates.Insignificants;

            return(myClusters);
        }
コード例 #5
0
        /// <summary>IMPLEMENTS ClustererBase</summary>
        protected override IEnumerable <Cluster> Cluster(IntensityMatrix vmatrix, DistanceMatrix dmatrix, ArgsClusterer args, ConfigurationClusterer tag, ProgressReporter prog)
        {
            Cluster result = new Cluster("Com", tag);

            foreach (Vector vector in vmatrix.Vectors)
            {
                result.Assignments.Add(new Assignment(vector, result, double.NaN));
            }

            return(new Cluster[] { result });
        }
コード例 #6
0
        /// <summary>
        /// ACTION!
        /// </summary>
        protected override IEnumerable <Cluster> Cluster(IntensityMatrix vm, DistanceMatrix dm, ArgsClusterer args, ConfigurationClusterer tag, ProgressReporter prog)
        {
            // Construct similarity matrix
            int N = vm.NumRows;

            double[,] s; // = new double[N, N];
            double[,] r  = new double[N, N];
            double[,] a  = new double[N, N];
            double[,] rn = new double[N, N];
            double[,] an = new double[N, N];

            // CALCULATE SIMILARITIES "S"
            s = dm.Values;

            // CALCULATE PREFERENCES "diag(S)"
            double median = ApMedian(s);

            for (int i = 0; i < N; i++)
            {
                s[i, i] = median;
            }

            // SET LAMBDA (change rate)
            const double lambda = 0.5;

            prog.SetProgress(-1);

            // CALCULATE NEXT R AND NEXT A
            for (int iter = 0; iter < 100; iter++)
            {
                prog.Enter("Affinity Propagation Iteration " + iter);

                // CALCULATE R
                // r[i,k] =   s[i,k]
                //          - max( a[i,kp] + s[i,kp] )
                for (int i = 0; i < N; i++)
                {
                    for (int k = 0; k < N; k++)
                    {
                        double v = double.MinValue;

                        for (int kp = 0; kp < N; kp++)
                        {
                            if (kp != k)
                            {
                                v = Math.Max(v, a[i, kp] + s[i, kp]);
                            }
                        }

                        rn[i, k] = s[i, k] - v;
                    }
                }

                for (int i = 0; i < N; i++)
                {
                    for (int k = 0; k < N; k++)
                    {
                        r[i, k] = r[i, k] * lambda + rn[i, k] * (1 - lambda);
                    }
                }

                // CALCULATE A
                // a[i, k] = min(0, r(k,k)
                //                 + sum( max ( 0,
                //                        r(ip, k)
                // a[k, k] = sum( max( 0, r(ip, k ) )
                for (int i = 0; i < N; i++)
                {
                    for (int k = 0; k < N; k++)
                    {
                        if (i != k)
                        {
                            double v = 0;

                            for (int ip = 0; ip < N; ip++)
                            {
                                if (ip != i && ip != k)
                                {
                                    v += Math.Max(0, r[ip, k]);
                                }
                            }

                            an[i, k] = Math.Min(0, r[k, k] + v);
                        }
                        else
                        {
                            double v = 0;

                            for (int ip = 0; ip < N; ip++)
                            {
                                if (ip != i && ip != k)
                                {
                                    v += Math.Max(0, r[ip, k]);
                                }
                            }

                            an[k, k] = v;
                        }
                    }
                }

                for (int i = 0; i < N; i++)
                {
                    for (int k = 0; k < N; k++)
                    {
                        a[i, k] = a[i, k] * lambda + an[i, k] * (1 - lambda);
                    }
                }

                prog.Leave();
            }

            // CALCULATE EXEMPLARS "E"
            // the value of k that maximizes a(i,k) + r(i,k)
            int[]    exemplars = new int[N];
            double[] scores    = new double[N];

            for (int i = 0; i < N; i++)
            {
                double maxVal = double.MinValue;
                int    maxK   = -1;

                for (int k = 0; k < N; k++)
                {
                    double val = a[i, k] + r[i, k];

                    if (val > maxVal)
                    {
                        maxVal = val;
                        maxK   = k;
                    }
                }

                exemplars[i] = maxK;
                scores[i]    = maxVal; // HIGHER is better
            }

            // CONVERT TO CLUSTERS
            Dictionary <int, Cluster> dict = new Dictionary <int, Cluster>();

            for (int pInd = 0; pInd < vm.NumRows; pInd++)
            {
                Vector vec   = vm.Vectors[pInd];
                int    exe   = exemplars[pInd];
                Vector vecx  = vm.Vectors[exe];
                double score = scores[pInd]; // HIGHER is better

                Cluster clu = dict.GetOrCreate(exe, x => new Cluster(vecx.Peak.DisplayName, tag));

                clu.Assignments.Add(new Assignment(vec, clu, score));
            }

            return(dict.Values.OrderBy(z => z.DisplayName));
        }
コード例 #7
0
        /// <summary>
        ///
        /// </summary>
        protected override IEnumerable <Cluster> Cluster(IntensityMatrix vmatrix, DistanceMatrix dmatrix, ArgsClusterer args, ConfigurationClusterer tag, ProgressReporter prog)
        {
            ConfigurationClusterer    existing           = ((WeakReference <ConfigurationClusterer>)args.Parameters[0]).GetTarget();
            List <List <Assignment> > uniqueCombinations = new List <List <Assignment> >();
            List <Cluster>            newClusters        = new List <Cluster>();
            List <ObservationInfo[]>  observations       = new List <ObservationInfo[]>();

            var existingResults = existing.Results;

            prog.Enter("Finding unique matches");

            for (int row = 0; row < vmatrix.NumRows; row++)
            {
                Vector vector = vmatrix.Vectors[row];
                Peak   peak   = vector.Peak;
                prog.SetProgress(row, vmatrix.NumRows);

                List <Assignment> assignments = new List <Assignment>(existingResults.Assignments
                                                                      .Where(z => z.Peak == peak)
                                                                      .OrderBy(z => z.Vector.Group.Order));

                int     index = FindMatch(uniqueCombinations, assignments);
                Cluster pat;

                if (index == -1)
                {
                    uniqueCombinations.Add(assignments);

                    string name = StringHelper.ArrayToString <Assignment>(assignments, z => z.Vector.Group.DisplayShortName + "." + z.Cluster.ShortName, " / ");

                    pat = new Cluster(name, tag);

                    // Centre (merge centres)
                    IEnumerable <IReadOnlyList <double> > centres = assignments.Select(z => z.Cluster.Centres.First());
                    pat.Centres.Add(centres.SelectMany(z => z).ToArray());

                    // Vector (merge vectors)
                    if (assignments[0].Vector.Observations != null)
                    {
                        observations.Add(assignments.Select(z => z.Vector.Observations).SelectMany(z => z).ToArray());
                    }
                    else
                    {
                        observations.Add(null);
                    }

                    // Relations (all clusters)
                    pat.Related.AddRange(assignments.Select(z => z.Cluster).Unique());

                    foreach (Cluster pat2 in pat.Related)
                    {
                        if (!pat2.Related.Contains(pat))
                        {
                            pat2.Related.Add(pat);
                        }
                    }

                    index = newClusters.Count;
                    newClusters.Add(pat);
                }


                pat = newClusters[index];

                double[] values = assignments.Select(z => z.Vector.Values).SelectMany(z => z).ToArray();
                pat.Assignments.Add(new Assignment(vector, pat, assignments.Count));
            }

            prog.Leave();

            return(newClusters);
        }
コード例 #8
0
ファイル: FrmActEvaluate.cs プロジェクト: mjr129/metaboclust
        /// <summary>
        /// Actual test running
        /// </summary>
        private static ClusterEvaluationPointer RunTest(Core core, ClusterEvaluationPointer origPointer, ClusterEvaluationConfiguration test, ProgressReporter proggy, bool paranoid, int index, int of)
        {
            UiControls.Assert(core.FileNames.Session != null, "Didn't expect the session filename to be null for cluster evaluation.");

            List <ClusterEvaluationParameterResult> results = new List <ClusterEvaluationParameterResult>();

            // Iterate over parameters
            for (int valueIndex = 0; valueIndex < test.ParameterValues.Length; valueIndex++)
            {
                object value = test.ParameterValues[valueIndex];

                List <ResultClusterer> repetitions = new List <ResultClusterer>();

                // Iterate over repetitions
                for (int repetition = 0; repetition < test.NumberOfRepeats; repetition++)
                {
                    proggy.Enter("Test " + index + "/" + of + ", parameter " + valueIndex + "/" + test.ParameterValues.Length + ", repetition " + repetition + "/" + test.NumberOfRepeats);

                    // Create config
                    string   newName          = AlgoParameterCollection.ParamToString(value) + " " + StringHelper.Circle(repetition + 1);
                    object[] copyOfParameters = test.ClustererConfiguration.Parameters.ToArray();
                    copyOfParameters[test.ParameterIndex] = value;
                    ArgsClusterer copyOfArgs = new ArgsClusterer(
                        test.ClustererConfiguration.Id,
                        test.ClustererConfiguration.SourceProvider,
                        test.ClustererConfiguration.PeakFilter,
                        test.ClustererConfiguration.Distance,
                        test.ClustererConfiguration.ObsFilter,
                        test.ClustererConfiguration.SplitGroups,
                        test.ClustererConfiguration.Statistics,
                        copyOfParameters,
                        test.ClustererConfiguration.OverrideShortName)
                    {
                        OverrideDisplayName = newName,
                        Comment             = test.ClustererConfiguration.Comment
                    };
                    var copyOfConfig = new ConfigurationClusterer()
                    {
                        Args = copyOfArgs
                    };

                    // Try load previus result
                    ResultClusterer result = null;

                    if (paranoid)
                    {
                        result = TryLoadIntermediateResult(core, test.Guid, valueIndex, repetition, proggy);
                    }

                    if (result == null)
                    {
                        // DO CLUSTERING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        proggy.Enter("Clustering");
                        result = copyOfConfig.Cluster(core, 0, proggy);
                        proggy.Leave();

                        if (paranoid)
                        {
                            SaveIntermediateResult(core, test.Guid, valueIndex, repetition, result, proggy);
                        }
                    }

                    // Add result
                    repetitions.Add(result);

                    string name = AlgoParameterCollection.ParamToString(value);

                    results.Add(new ClusterEvaluationParameterResult(name, test, valueIndex, repetitions));

                    proggy.Leave();
                }
            }

            ClusterEvaluationResults final = new ClusterEvaluationResults(core, test, results);

            string folder      = UiControls.GetOrCreateFixedFolder(UiControls.EInitialFolder.Evaluations);
            string sessionName = Path.GetFileNameWithoutExtension(core.FileNames.Session);
            string fileName    = core.Options.ClusteringEvaluationResultsFileName;

            fileName = fileName.Replace("{SESSION}", sessionName);
            fileName = fileName.Replace("{RESULTS}", folder + "\\");
            fileName = UiControls.GetNewFile(fileName);

            return(SaveResults(core, fileName, origPointer, final, proggy));
        }
コード例 #9
0
        /// <summary>
        ///
        /// </summary>
        protected override IEnumerable <Cluster> Cluster(IntensityMatrix vmatrix, DistanceMatrix UNUSED, ArgsClusterer args, ConfigurationClusterer tag, ProgressReporter prog)
        {
            // GET OPTIONS
            int k = (int)args.Parameters[0];

            // CREATE RANDOM CENTRES
            Random rnd = new Random();

            var            potentialCentres = new List <Vector>(vmatrix.Vectors);
            List <Cluster> clusters         = new List <Cluster>();

            for (int n = 0; n < k; n++)
            {
                int random = rnd.Next(potentialCentres.Count);

                Cluster p   = new Cluster((clusters.Count + 1).ToString(), tag);
                Vector  vec = potentialCentres[random];
                p.Exemplars.Add(vec.Values);

                potentialCentres.RemoveAt(random);

                clusters.Add(p);
            }

            // Assign to exemplars
            prog.Enter("Initialising assignments");
            LegacyClustererHelper.Assign(vmatrix, clusters, ECandidateMode.Exemplars, args.Distance, prog);
            prog.Leave();

            // Centre
            LegacyClustererHelper.PerformKMeansCentering(vmatrix, clusters, args.Distance, prog);

            return(clusters);
        }
コード例 #10
0
        /// <summary>
        /// d-k-means++
        /// Ignores insignificant variables.
        /// Returns new clusters (these won't be added to the core so make sure to do so)
        /// </summary>
        private static List <Cluster> AutogenerateClusters(IntensityMatrix vmatrix, List <Cluster> seed, double?stoppingDistance, int?stoppingCount, ConfigurationMetric metric, ConfigurationClusterer tag, ProgressReporter prog)
        {
            // Make a log of whatever limits have been set
            if (!stoppingCount.HasValue && !stoppingDistance.HasValue)
            {
                throw new InvalidOperationException("No stopping condition set.");
            }

            // Assign all variables to nearest
            List <Cluster> result = new List <Cluster>(seed);

            // Get the actual limits
            int    iterations = 0;
            int    count      = (stoppingCount - seed.Count) ?? Int32.MaxValue;
            double distance   = stoppingDistance ?? Double.MinValue;

            // Get the most distant variable
            prog.Enter("Initialising assignments");
            LegacyClustererHelper.Assign(vmatrix, result, ECandidateMode.Exemplars, metric, prog);
            Assignment mostDistant = GetMostDistantAssignment(result);

            prog.Leave();

            // Continue until our limits are breached
            while ((count > 0) && (mostDistant.Score > distance))
            {
                // Check we haven't got unreasonable limits
                iterations++;

                prog.Enter("Centre generation (iteration " + iterations + ")");

                if (iterations > 1000)
                {
                    throw new InvalidOperationException("Too many iterations - exiting.");
                }

                // Create a new cluster with the most distant variable as its exemplar
                var newCluster = new Cluster((result.Count + 1).ToString(), tag);
                result.Add(newCluster);
                newCluster.Exemplars.Add(mostDistant.Vector.Values);  // todo: check to prevent multiple assignment?

                // Make the assignments based on the closest exemplars
                LegacyClustererHelper.Assign(vmatrix, result, ECandidateMode.Exemplars, metric, prog);

                // Basic check
                if (!newCluster.Assignments.Vectors.Contains(mostDistant.Vector))
                {
                    throw new InvalidOperationException("Problem creating new cluster from vector - " + mostDistant.Vector.ToString() + " doesn't like being in its own cluster. Check this vector for discrepancies.");
                }

                // Get the next most distant variable
                count       = count - 1;
                mostDistant = GetMostDistantAssignment(result);

                prog.Leave();
            }

            // Return the number of iterations
            return(result);
        }
コード例 #11
0
        /// <summary>
        ///
        /// </summary>
        protected override IEnumerable <Cluster> Cluster(IntensityMatrix vmatrix, DistanceMatrix UNUSED, ArgsClusterer args, ConfigurationClusterer tag, ProgressReporter prog)
        {
            // Get parameters
            // COUNT LIMIT
            int countLimit = (int)tag.UntypedArgs.Parameters[0];
            // DISTANCE LIMIT
            double distanceLimit = (double)tag.UntypedArgs.Parameters[1];
            // SEED PEAK
            WeakReference <Peak> seedPeakRef = (WeakReference <Peak>)tag.UntypedArgs.Parameters[2];
            Peak seedPeak = seedPeakRef.GetTargetOrThrow();
            // SEED GROUP
            GroupInfo groupInfo = (GroupInfo)tag.UntypedArgs.Parameters[3];
            // DO-K-MEANS?
            bool doKMeans = (bool)tag.UntypedArgs.Parameters[4];

            // Create the seed cluster
            Cluster        seedCluster = new Cluster("1", tag);
            List <Cluster> seedList    = new List <Cluster> {
                seedCluster
            };
            int seedIndex = vmatrix.FindIndex(new IntensityMatrix.RowHeader(seedPeak, args.SplitGroups ? groupInfo : null));

            if (seedIndex == -1)
            {
                throw new InvalidOperationException($"The chosen peak {{{seedPeak}}} cannot be used a seed because it is not present in the value matrix. Please check that this peak has not been excluded by the filter condition {{{args.PeakFilter}}}.");
            }

            seedCluster.Exemplars.Add(vmatrix.Vectors[seedIndex]);

            // Autogenerate the clusters
            int?   nCountLimit    = (countLimit != Int32.MinValue) ? countLimit : (int?)null;
            double?nDistanceLimit = (distanceLimit != Double.MinValue) ? countLimit : (double?)null;

            List <Cluster> autoGenClusters = AutogenerateClusters(vmatrix, seedList, nDistanceLimit, nCountLimit, args.Distance, tag, prog);

            // Do k-means (if requested)
            if (doKMeans)
            {
                prog.Enter("k-means");
                LegacyClustererHelper.PerformKMeansCentering(vmatrix, autoGenClusters, args.Distance, prog);
                prog.Leave();
            }

            // Return full list
            return(autoGenClusters);
        }
コード例 #12
0
        protected override IEnumerable <Cluster> Cluster(IntensityMatrix vmatrix, DistanceMatrix dmatrix, ArgsClusterer args, ConfigurationClusterer tag, ProgressReporter prog)
        {
            object[] inputs =
            {
                _script.IsInputPresent(0) ? vmatrix.Values : null,
                _script.IsInputPresent(1) ? dmatrix.Values : null
            };

            prog.Enter("Running script");
            prog.SetProgressMarquee();
            int[] clusters = Arr.Instance.RunScriptIntV(_script, inputs, args.Parameters).ToArray();
            prog.Leave();
            prog.Enter("Creating clusters");
            var result = CreateClustersFromIntegers(vmatrix, clusters, tag);

            prog.Leave();
            return(result);
        }
コード例 #13
0
 /// <summary>
 /// Constructor.
 /// </summary>
 public Cluster(string shortName, ConfigurationClusterer creationReason)
 {
     this.ShortName = shortName;
     this.Method    = creationReason;
 }
コード例 #14
0
        /// <summary>
        ///
        /// </summary>
        protected override IEnumerable <Cluster> Cluster(IntensityMatrix vmatrix, DistanceMatrix dmatrix, ArgsClusterer args, ConfigurationClusterer tag, ProgressReporter prog)
        {
            Dictionary <Pathway, Cluster> d = new Dictionary <Pathway, Cluster>();
            List <Cluster> result           = new List <Cluster>();

            prog.Enter("Finding pathways");

            for (int index = 0; index < vmatrix.NumRows; index++)
            {
                Vector vec  = vmatrix.Vectors[index];
                Peak   peak = vec.Peak;
                prog.SetProgress(index, vmatrix.NumRows);

                foreach (Annotation c in peak.Annotations)
                {
                    foreach (Pathway p in c.Compound.Pathways)
                    {
                        Cluster pat;

                        if (!d.TryGetValue(p, out pat))
                        {
                            pat         = new Cluster(p.DefaultDisplayName, tag);
                            pat.States |= Session.Main.Cluster.EStates.Pathway;
                            result.Add(pat);
                            d.Add(p, pat);
                        }

                        if (!pat.Assignments.Peaks.Contains(peak))
                        {
                            pat.Assignments.Add(new Assignment(vec, pat, double.NaN));
                        }
                    }
                }
            }

            prog.Leave();

            return(result);
        }
コード例 #15
0
        void wizard_OkClicked(object sender, EventArgs e)
        {
            // Check
            if (!this._wizard.RevalidateAll())
            {
                FrmMsgBox.ShowError(this, "Not all options have been selected.");
                return;
            }

            int    param1_numClusters   = this._radStopN.Checked ? int.Parse(this._txtStopN.Text) : int.MinValue;
            double param2_distanceLimit = this._radStopD.Checked ? double.Parse(this._txtStopD.Text) : double.MinValue;

            Debug.Assert(this._ecbSeedPeak.HasSelection, "Expected a seed peak to be selected");
            WeakReference <Peak> param3_seedPeak  = new WeakReference <Peak>(this._ecbSeedPeak.SelectedItem);
            GroupInfo            param4_seedGroup = NamedItem <GroupInfo> .Extract(this._lstGroups.SelectedItem);

            int             param5_doKMeans = this._radFinishK.Checked ? 1 : 0;
            IMatrixProvider source          = this._ecbSource.SelectedItem;

            object[] parameters = { param1_numClusters, param2_distanceLimit, param3_seedPeak, param4_seedGroup, param5_doKMeans };
            string   name       = "DK";

            // Create a constraint that only allows overlapping timepoints
            HashSet <int>       overlappingPoints = new HashSet <int>();
            var                 fil           = this._ecbFilter.SelectedItem ?? ObsFilter.Empty;
            var                 passed        = fil.Test(source.Provide.Columns.Select(z => z.Observation)).Passed;
            HashSet <GroupInfo> groups        = new HashSet <GroupInfo>(passed.Select(z => z.Group));
            bool                needsExFilter = false;

            foreach (int ctp in this._core.Times)
            {
                bool trueInAny  = false;
                bool falseInAny = false;

                foreach (GroupInfo g in groups)
                {
                    if (passed.Any(z => z.Group == g && z.Time == ctp))
                    {
                        trueInAny = true;
                    }
                    else
                    {
                        falseInAny = true;
                    }
                }

                if (trueInAny && !falseInAny) // i.e. true in all          TT
                {
                    overlappingPoints.Add(ctp);
                }
                else if (trueInAny) // i.e. true in one but not all        TF
                {
                    needsExFilter = true;
                }
                //else if (falseInAny) //  False in all (accptable)        FT
                // else       //     No groups                             FF
            }

            ObsFilter trueFilter;

            if (needsExFilter)
            {
                List <ObsFilter.Condition> conditions = new List <ObsFilter.Condition>
                {
                    new ObsFilter.ConditionFilter(Filter.ELogicOperator.And, false,
                                                  this._ecbFilter.SelectedItem, true),
                    new ObsFilter.ConditionTime(Filter.ELogicOperator.And, false,
                                                Filter.EElementOperator.Is,
                                                overlappingPoints)
                };


                trueFilter = new ObsFilter(null, null, conditions);
                this._core.AddObsFilter(trueFilter);
            }
            else
            {
                trueFilter = this._ecbFilter.SelectedItem;
            }

            ArgsClusterer args = new ArgsClusterer(
                Algo.ID_DKMEANSPPWIZ,
                this._ecbSource.SelectedItem,
                this._ecbPeakFilter.SelectedItem,
                new ConfigurationMetric()
            {
                Args = new ArgsMetric(this._ecbDistance.SelectedItem.Id, this._ecbSource.SelectedItem, this._ecbDistance.SelectedItem.Parameters.StringToParams(this._core, this._txtDistanceParams.Text))
            },
                trueFilter,
                this._chkClusterIndividually.Checked,
                EClustererStatistics.None,
                parameters,
                "DK")
            {
                OverrideDisplayName = name,
                Comment             = "Generated using wizard"
            };

            ConfigurationClusterer config = new ConfigurationClusterer()
            {
                Args = args
            };

            FrmWait.Show(this, "Clustering", null, z => this._core.AddClusterer(config, z));
            this.DialogResult = DialogResult.OK;
        }