private void CBS(uint nPerm = 10000, string pMethod = "hybrid", int minWidth = 2, int kMax = 25,
uint nMin = 200, double eta = 0.05, uint[] sbdry = null, double trim = 0.025,
double undoPrune = 0.05, double undoSD = 3, int verbose = 1)
{
if (minWidth < 2 || minWidth > 5)
{
Console.Error.WriteLine("Minimum segment width should be between 2 and 5");
Environment.Exit(1);
}
if (nMin < 4 * kMax)
{
Console.Error.WriteLine("nMin should be >= 4 * kMax");
Environment.Exit(1);
}
if (sbdry == null)
{
GetBoundary.ComputeBoundary(nPerm, this.Alpha, eta, out sbdry);
}
Dictionary<string, int[]> inaByChr = new Dictionary<string, int[]>();
Dictionary<string, double[]> finiteScoresByChr = new Dictionary<string, double[]>();
List<ThreadStart> tasks = new List<ThreadStart>();
foreach (KeyValuePair<string, double[]> scoreByChrKVP in ScoreByChr)
{
tasks.Add(new ThreadStart(() =>
{
string chr = scoreByChrKVP.Key;
int[] ina;
Helper.GetFiniteIndices(scoreByChrKVP.Value, out ina); // not NaN, -Inf, Inf
double[] scores;
if (ina.Length == scoreByChrKVP.Value.Length)
{
scores = scoreByChrKVP.Value;
}
else
{
Helper.ExtractValues<double>(scoreByChrKVP.Value, ina, out scores);
}
lock (finiteScoresByChr)
{
finiteScoresByChr[chr] = scores;
inaByChr[chr] = ina;
}
}));
}
//Parallel.ForEach(tasks, t => { t.Invoke(); });
Isas.Shared.Utilities.DoWorkParallelThreads(tasks);
// Quick sanity-check: If we don't have any segments, then return a dummy result.
int n = 0;
foreach (var list in finiteScoresByChr.Values)
{
n += list.Length;
}
if (n == 0)
{
this.SegmentationResults = this.GetDummySegmentationResults();
return;
}
double trimmedSD = Math.Sqrt(ChangePoint.TrimmedVariance(finiteScoresByChr, trim: trim));
Dictionary<string, Segment[]> segmentByChr = new Dictionary<string, Segment[]>();
// when parallelizing we need an RNG for each chromosome to get deterministic results
Random seedGenerator = new MersenneTwister(0);
Dictionary<string, Random> perChromosomeRandom = new Dictionary<string, Random>();
foreach (string chr in this.ScoreByChr.Keys)
{
perChromosomeRandom[chr] = new MersenneTwister(seedGenerator.NextFullRangeInt32(), true);
}
tasks = new List<ThreadStart>();
foreach (string chr in ScoreByChr.Keys)
{
tasks.Add(new ThreadStart(() =>
{
int[] ina = inaByChr[chr];
int[] lengthSeg;
double[] segmentMeans;
ChangePoint.ChangePoints(this.ScoreByChr[chr], sbdry, out lengthSeg, out segmentMeans, perChromosomeRandom[chr],
dataType: this.DataType, alpha: this.Alpha, nPerm: nPerm,
pMethod: pMethod, minWidth: minWidth, kMax: kMax, nMin: nMin, trimmedSD: trimmedSD,
undoSplits: this.UndoMethod, undoPrune: undoPrune, undoSD: undoSD, verbose: verbose);
Segment[] segments = new Segment[lengthSeg.Length];
int cs1 = 0, cs2 = -1; // cumulative sum
for (int i = 0; i < lengthSeg.Length; i++)
{
cs2 += lengthSeg[i];
int start = ina[cs1];
int end = ina[cs2];
segments[i] = new Segment();
segments[i].start = this.StartByChr[chr][start]; // Genomic start
segments[i].end = this.EndByChr[chr][end]; // Genomic end
segments[i].nMarkers = lengthSeg[i];
segments[i].mean = segmentMeans[i];
cs1 += lengthSeg[i];
}
lock (segmentByChr)
{
segmentByChr[chr] = segments;
}
}));
}
//Parallel.ForEach(tasks, t => { t.Invoke(); });
Isas.Shared.Utilities.DoWorkParallelThreads(tasks);
this.SegmentationResults = new GenomeSegmentationResults(segmentByChr);
}