public int FindClusters(double rhoCutoff = RhoCutoff)
{
CentroidsMAFs = new List<double>();
CentroidsCoverage = new List<double>();
int segmentsLength = this.Segments.Count;
List<int> CentroidsIndex = new List<int>(segmentsLength);
for (int segmentIndex = 0; segmentIndex < segmentsLength; segmentIndex++)
{
if (this.Rho[segmentIndex] > rhoCutoff && this.Centroids[segmentIndex] > CentroidsCutoff && this.Segments[segmentIndex].MAF >= 0)
{
CentroidsIndex.Add(segmentIndex);
CentroidsMAFs.Add(this.Segments[segmentIndex].MAF);
CentroidsCoverage.Add(this.Segments[segmentIndex].Coverage);
}
}
// sort list and return indices
List<int> runOrder = new List<int>();
var sortedScores = Rho.Select((x, i) => new KeyValuePair<double, int>(x, i)).OrderByDescending(x => x.Key).ToList();
runOrder = sortedScores.Select(x => x.Value).ToList();
foreach (int runOrderIndex in runOrder)
{
// set segment cluster value to the cluster centroid
if (CentroidsIndex.Contains(runOrderIndex))
{
this.Segments[runOrderIndex].Cluster = CentroidsIndex.FindIndex(x => x == runOrderIndex) + 1;
}
// set segment cluster value to the closest cluster segment
else
{
double? tmpDistance = null;
double minDistance = Double.MaxValue;
int minRhoElementIndex = 0;
for (int tmpIndex = 0; tmpIndex < segmentsLength; tmpIndex++)
{
if (Rho[tmpIndex] > Rho[runOrderIndex] && this.Segments[tmpIndex].MAF >= 0)
{
tmpDistance = GetDistance(segmentsLength, tmpIndex, runOrderIndex);
if (tmpDistance.HasValue)
{
if (tmpDistance < minDistance)
{
minRhoElementIndex = tmpIndex;
minDistance = (double)tmpDistance;
}
}
}
}
// populate clusters
if (this.Segments[runOrderIndex].MAF >= 0)
this.Segments[runOrderIndex].Cluster = this.Segments[minRhoElementIndex].Cluster;
if (!this.Segments[runOrderIndex].Cluster.HasValue || this.Segments[runOrderIndex].MAF < 0 || this.Segments[runOrderIndex].KnearestNeighbour > this._knearestNeighbourCutoff)
this.Segments[runOrderIndex].Cluster = -1;
}
}
return CentroidsIndex.Count;
}