/// <summary> /// Assign a SegmentPloidy to each CanvasSegment, based on which model matches this segment best: /// </summary> void AssignPloidyCallsGaussianMixture() { // For segments with (almost) no variants alleles at all, we'll assign them a dummy MAF, and // we simply won't consider MAF when determining the closest ploidy: double dummyMAF = -1; foreach (CanvasSegment segment in this.Segments) { // Compute (MAF, Coverage) for this segment: List <double> MAF = new List <double>(); foreach (float VF in segment.VariantFrequencies) { MAF.Add(VF > 0.5 ? 1 - VF : VF); } double medianCoverage = CanvasCommon.Utilities.Median(segment.Counts); double medianMAF = dummyMAF; SegmentPloidy bestPloidy = null; double bestProbability = 0; if (MAF.Count >= 10) { medianMAF = Utilities.Median(MAF); } Dictionary <SegmentPloidy, double> posteriorProbabilities = GaussianMixtureModel.EMComputePosteriorProbs(AllPloidies, medianMAF, medianCoverage); // Find the closest ploidy. foreach (SegmentPloidy ploidy in AllPloidies) { if (bestPloidy == null || posteriorProbabilities[ploidy] > bestProbability) { bestProbability = posteriorProbabilities[ploidy]; bestPloidy = ploidy; } } if (bestProbability == 0) { // Sanity-check: If we didn't find anything with probability > 0, then fall back to the simplest possible // thing: Call purely on coverage. segment.CopyNumber = (int)Math.Round(2 * medianCoverage / this.DiploidCoverage); segment.MajorChromosomeCount = null; } else { segment.CopyNumber = bestPloidy.CopyNumber; segment.MajorChromosomeCount = bestPloidy.MajorChromosomeCount; if (MAF.Count < 10) { segment.MajorChromosomeCount = null; // Don't assign MCC if we don't have variant allele frequencies } } } }