private void ProcessVariant(IAlleleSource source, CalledAllele variant) { // determine metrics _coverageCalculator.Compute(variant, source); if (variant.AlleleSupport > 0) { if (_config.NoiseModel == NoiseModel.Window) { VariantQualityCalculator.Compute(variant, _config.MaxVariantQscore, (int)MathOperations.PtoQ(variant.SumOfBaseQuality / variant.TotalCoverage)); } else { VariantQualityCalculator.Compute(variant, _config.MaxVariantQscore, _config.EstimatedBaseCallQuality); } StrandBiasCalculator.Compute(variant, variant.SupportByDirection, _config.EstimatedBaseCallQuality, _config.StrandBiasFilterThreshold, _config.StrandBiasModel); } // set genotype, filter, etc AlleleProcessor.Process(variant, _config.MinFrequency, _config.LowDepthFilter, _config.VariantQscoreFilterThreshold, _config.FilterSingleStrandVariants, _config.VariantFreqFilter, _config.LowGTqFilter, _config.IndelRepeatFilter, _config.RMxNFilterSettings, _config.ChrReference, source.ExpectStitchedReads); }
/// <summary> /// Warning. This algorithm has an inherent assumption: /// the VS must be in order of their true position (first base of difference). /// Thats not always how they appeared in the vcf. /// </summary> /// <param name="allele"></param> /// <param name="clusterVariantSites"></param> /// <param name="referenceSequence"></param> /// <param name="neighborhoodDepthAtSites"></param> /// <param name="clusterCountsAtSites"></param> /// <param name="chromosome"></param> /// <returns></returns> public static CalledAllele Create(string chromosome, int alleleCoordinate, string alleleReference, string alleleAlternate, int varCount, int noCallCount, int totalCoverage, int refSpt, AlleleCategory category, int qNoiselevel, int maxQscore) { if (totalCoverage < varCount) //sometimes the orignal vcf and the bam dont agree... { totalCoverage = varCount; } // Nima: Commented this line for pics-1017 //refSpt = totalCoverage - varCount; if (category == AlleleCategory.Reference) { refSpt = varCount; } var allele = new CalledAllele(category) { Chromosome = chromosome, ReferencePosition = alleleCoordinate, ReferenceAllele = alleleReference, AlternateAllele = alleleAlternate, TotalCoverage = totalCoverage, Type = category, AlleleSupport = varCount, ReferenceSupport = refSpt, NumNoCalls = noCallCount, VariantQscore = VariantQualityCalculator.AssignPoissonQScore(varCount, totalCoverage, qNoiselevel, maxQscore), NoiseLevelApplied = qNoiselevel }; allele.SetFractionNoCalls(); return(allele); }
public void Compute() { // Based on Tamsen's original PValue test, just extended to our Compute method List <int[]> SampleValues_ExpectedQScore = new List <int[]>() //coverage,var calls} { new int[] { 100, 0, 0 }, new int[] { 100, 1, 2 }, new int[] { 100, 5, 24 }, new int[] { 200, 10, 43 }, new int[] { 500, 25, 98 }, new int[] { 5000, 250, 890 }, new int[] { 10000, 250, 356 }, new int[] { 10000, 500, 1770 }, new int[] { 10000, 9995, 156912 }, //ok, this is a silly number. but we are checking the range.. }; foreach (int[] item in SampleValues_ExpectedQScore) { var variant = new CalledAllele(AlleleCategory.Snv) { ReferencePosition = 1, ReferenceAllele = "A", AlternateAllele = "T", TotalCoverage = item[0], AlleleSupport = item[1], }; VariantQualityCalculator.Compute(variant, int.MaxValue, 20); Assert.Equal(item[2], variant.VariantQscore); //check upped bd works: VariantQualityCalculator.Compute(variant, 100, 20); Assert.Equal(Math.Min(100, item[2]), variant.VariantQscore); } }
private static bool PushThroughRamificationsOfGTChange(CalledAllele VariantA, CalledAllele VariantB, CalledAllele Consensus, int RefCountA, int RefCountB, int DepthA, int DepthB, Genotype GT, int MaxQScore, VariantComparisonCase Case) { int NoiseLevel = Consensus.NoiseLevelApplied; if (((GT == Genotype.HomozygousRef) || (GT == Genotype.RefLikeNoCall)) && (Case == VariantComparisonCase.OneReferenceOneAlternate)) { Consensus.AlternateAllele = "."; Consensus.ReferenceAllele = Consensus.ReferenceAllele.Substring(0, 1); if (VariantA != null) { VariantA.VariantQscore = VariantQualityCalculator.AssignPoissonQScore( RefCountA, DepthA, NoiseLevel, MaxQScore); } if (VariantB != null) { VariantB.VariantQscore = VariantQualityCalculator.AssignPoissonQScore( RefCountB, DepthB, NoiseLevel, MaxQScore); } Consensus.AlleleSupport = Consensus.ReferenceSupport; return(true); } return(false); }
/// <summary> /// Warning. This algorithm has an inherent assumption: /// the VS must be in order of their true position (first base of difference). /// Thats not always how they appeared in the vcf. /// </summary> /// <param name="allele"></param> /// <param name="clusterVariantSites"></param> /// <param name="referenceSequence"></param> /// <param name="neighborhoodDepthAtSites"></param> /// <param name="clusterCountsAtSites"></param> /// <param name="chromosome"></param> /// <returns></returns> public static CalledAllele Create(string chromosome, int alleleCoordinate, string alleleReference, string alleleAlternate, int varCount, int totalCoverage, AlleleCategory category, int qNoiselevel, int maxQscore) { if (totalCoverage < varCount) //sometimes the orignal vcf and the bam dont agree... { totalCoverage = varCount; } if (category == AlleleCategory.Reference) { return(new CalledAllele() { Chromosome = chromosome, Coordinate = alleleCoordinate, Reference = alleleReference, Alternate = alleleAlternate, TotalCoverage = totalCoverage, AlleleSupport = varCount, ReferenceSupport = varCount, VariantQscore = VariantQualityCalculator.AssignPoissonQScore(varCount, totalCoverage, qNoiselevel, maxQscore) }); } return(new CalledAllele(category) { Chromosome = chromosome, Coordinate = alleleCoordinate, Reference = alleleReference, Alternate = alleleAlternate, TotalCoverage = totalCoverage, AlleleSupport = varCount, ReferenceSupport = totalCoverage - varCount, VariantQscore = VariantQualityCalculator.AssignPoissonQScore(varCount, totalCoverage, qNoiselevel, maxQscore) }); }
public void CheckQScoresWithBadInput() { //should never happen, but lets be gracefull //and not crash Assert.Equal(0, VariantQualityCalculator.AssignPoissonQScore(0, 0, 0, 100)); //call count, cov, basecallQ Assert.Equal(0, VariantQualityCalculator.AssignPoissonQScore(0, 0, 20, 100)); //call count, cov, basecallQ Assert.Equal(0, VariantQualityCalculator.AssignPoissonQScore(0, -1, 20, 100)); //call count, cov, basecallQ Assert.Equal(0, VariantQualityCalculator.AssignPoissonQScore(-1, 0, 20, 100)); //call count, cov, basecallQ Assert.Equal(0, VariantQualityCalculator.AssignPoissonQScore(-1, -1, 20, 100)); //call count, cov, basecallQ }
public void SupplementSupportWithClippedReads(CallableNeighborhood neighborhood) { var neighbors = neighborhood.VcfVariantSites; var refName = neighbors.First().ReferenceName; _alignmentExtractor.Jump(refName); Logger.WriteToLog("Supplementing candidate variant support with soft clipped reads."); //var readFilter = new NeighborhoodReadFilter(_options); //var clippedReadComparator = new ClippedReadComparator(); //var mnvClippedReadComparator = new MNVClippedReadComparator(scReadFilter); Read read = new Read(); while (true) { if (!_alignmentExtractor.GetNextAlignment(read)) { break; // no more reads } // Check if clipped part matches alternate allele of any candidate variant foreach (var mnv in neighborhood.CandidateVariants) { // Do not boost support for SNVs and short MNVs if (mnv.ReferenceAllele.Length + mnv.AlternateAllele.Length < _minSizeForClipRescue) { continue; } if (_mnvClippedReadComparator.DoesClippedReadSupportMNV(read, mnv)) { // Nima: in current implementation, same read can support multiple candidate variants. // In future we may want to "assign" reads to only one candidate variant. // Risk: reads that support an MNV, may also support candidate variants. This can lead to false positives. mnv.AlleleSupport++; mnv.SoftClipAlleleSupport++; } } if (read.Position > neighborhood.LastPositionOfInterestWithLookAhead) { break; } } // Update Q score before moving on // Nima: Q score will be calculated twice for some variants // (once in PhasedVariantExtractor.cs>Create() , and another time here) foreach (var mnv in neighborhood.CandidateVariants) { mnv.VariantQscore = VariantQualityCalculator.AssignPoissonQScore(mnv.AlleleSupport, mnv.ReferenceSupport, _qNoiseLevel, _maxQscore); Logger.WriteToLog("Added soft clip support of {0} to MNV: {1}.", mnv.AlleleSupport - mnv.SoftClipAlleleSupport, mnv.ToString()); } }
public static void UpdateVariantQScoreAndRefilter(int maxQscore, int filterQScore, Dictionary <MutationCategory, int> qCalibratedRates, CalledAllele originalVar, MutationCategory cat, bool subsample) { double depth; double callCount; //tjd+ // We can revisit this math at a later date. Exactly how we lower the Qscores // or filter the suspect calls is TBD. We should work with this new algorithm // on a larger collection of datasets representing various alignment issues, // and modify the code/parameters as needed. // A few thoughts: Amplicon edge issues don't get better the deeper you sequence. // We need to scale out depth from the Q score calculation (since the original Q score is a fxn of depth/freq). // One option is to Cap at ~100 DP (TODO, this should be a parameter, a fxn of your bascallquality). // double subSampleToThis = 100; // tjd- double denominator = MathOperations.QtoP(qCalibratedRates[cat]); double subSampleToThis = 1.0 / denominator; if ((qCalibratedRates[cat] == 0) || (denominator == 0)) { subsample = false; } bool canUpdateQ = HaveInfoToUpdateQ(originalVar, out depth, out callCount); if (subsample && (depth > subSampleToThis)) { callCount = callCount * subSampleToThis / depth; depth = subSampleToThis; } if (canUpdateQ) { int newQ = VariantQualityCalculator.AssignPoissonQScore( (int)callCount, (int)depth, qCalibratedRates[cat], Math.Min(originalVar.VariantQscore, maxQscore)); //note, using "originalVar.VariantQscore" and the maxQ stops us from ever RAISING the q score over these values. InsertNewQ(qCalibratedRates, originalVar, cat, newQ, true); //update filters if needed if (newQ < filterQScore) { if (originalVar.Filters.Contains(FilterType.LowVariantQscore)) { return; } originalVar.Filters.Add(FilterType.LowVariantQscore); } } }
public void AssignPValue() { var callCount = 1; double pValue = VariantQualityCalculator.AssignPValue(callCount, 100, 20); Assert.Equal(0.6321, pValue, 4); //If observed call count is 0, return 1 callCount = 0; pValue = VariantQualityCalculator.AssignPValue(callCount, 100, 20); Assert.Equal(1, pValue, 4); }
public void AssignPoissonQScore() { //If rounded qScore is above maxQScore, should return maxQScore var coverage = 500; var varSupport = 25; var estQuality = 20; var expectedActualQValue = 98; var maxQValue = expectedActualQValue + 1; maxQValue = 1000; double finalQValue = VariantQualityCalculator.AssignPoissonQScore(varSupport, coverage, estQuality, maxQValue); Assert.Equal(expectedActualQValue, finalQValue); maxQValue = expectedActualQValue - 1; finalQValue = VariantQualityCalculator.AssignPoissonQScore(varSupport, coverage, estQuality, maxQValue); Assert.Equal(maxQValue, finalQValue); }
public void Pisces_AssignPValue() { List <int[]> SampleValues = new List <int[]>() //coverage,var calls} { new int[] { 100, 0 }, new int[] { 100, 1 }, new int[] { 100, 5 }, new int[] { 200, 10 }, new int[] { 500, 25 }, new int[] { 5000, 250 }, }; List <double[]> ReturnedValues = new List <double[]>(); { }//p,Q foreach (int[] item in SampleValues) { double pValue = VariantQualityCalculator.AssignPValue(item[1], item[0], 20); double Qscore = MathOperations.PtoQ(pValue); double FinalQValue = VariantQualityCalculator.AssignPoissonQScore(item[1], item[0], 20, 100); double[] Result = new double[] { pValue, Qscore, FinalQValue }; ReturnedValues.Add(Result); } Assert.Equal(ReturnedValues[0][0], 1, 4); Assert.Equal(ReturnedValues[0][2], 0, 4); Assert.Equal(ReturnedValues[1][0], 0.6321, 4); Assert.Equal(ReturnedValues[1][2], 2, 4); Assert.Equal(ReturnedValues[2][0], 0.003659, 4); Assert.Equal(ReturnedValues[2][2], 24, 4); Assert.Equal(ReturnedValues[3][0], 4.65 * Math.Pow(10, -5), 5); Assert.Equal(ReturnedValues[3][2], 43, 4); Assert.Equal(ReturnedValues[4][0], 1.599 * Math.Pow(10, -10), 10); Assert.Equal(ReturnedValues[4][2], 98, 4); Assert.Equal(ReturnedValues[5][0], 0.0, 10); Assert.Equal(ReturnedValues[5][2], 100, 4); }
public static void UpdateVariant(int maxQscore, int filterQScore, Dictionary <MutationCategory, int> qCalibratedRates, VcfVariant originalVar, MutationCategory cat) { int depth; int callCount; bool canUpdateQ = HaveInfoToUpdateQ(originalVar, out depth, out callCount); if (canUpdateQ) { int newQ = VariantQualityCalculator.AssignPoissonQScore( callCount, depth, qCalibratedRates[cat], maxQscore); InsertNewQ(qCalibratedRates, originalVar, cat, newQ); //update filters if needed if (newQ < filterQScore) { var vcfConfig = new VcfWriterConfig(); vcfConfig.VariantQualityFilterThreshold = filterQScore; var formatter = new VcfFormatter(vcfConfig); string lowQString = formatter.MapFilter(FilterType.LowVariantQscore); string passString = VcfFormatter.PassFilter; if (originalVar.Filters.Contains(lowQString)) { return; } if (originalVar.Filters == passString) { originalVar.Filters = lowQString; } else { originalVar.Filters += VcfFormatter.FilterSeparator + lowQString; } } } }
public void EvaluateVariants() { var config = new VariantCallerConfig { MaxVariantQscore = 100, NoiseLevelUsedForQScoring = 20, ChrReference = new ChrReference { Sequence = "ACGTACGT", Name = "Boo" }, GenotypeCalculator = new SomaticGenotyper(), LocusProcessor = new SomaticLocusProcessor() }; var variantCaller = new AlleleCaller(config); var highCoverageCoordinate = 123; var lowCoverageCoordinate = 456; var passingVariant = new CandidateAllele("chr1", highCoverageCoordinate, "A", "T", AlleleCategory.Snv) { SupportByDirection = new[] { 500, 0, 0 } // Freq is 500/1500, q is 100 }; var passingVariant2 = new CandidateAllele("chr1", highCoverageCoordinate, "A", "C", AlleleCategory.Snv) { SupportByDirection = new[] { 500, 0, 0 } // Freq is 500/1500, q is 100 }; var lowFreqVariant = new CandidateAllele("chr2", highCoverageCoordinate, "A", "T", AlleleCategory.Snv) { SupportByDirection = new[] { 1, 0, 0 } // Freq is 1/1500, q is 0 }; var lowCoverageVariant = new CandidateAllele("chr3", lowCoverageCoordinate, "A", "T", AlleleCategory.Snv) { SupportByDirection = new[] { 10, 0, 0 } // Freq is 10/15, q is 100 }; var lowqVariant = new CandidateAllele("chr4", highCoverageCoordinate, "A", "T", AlleleCategory.Snv) { SupportByDirection = new[] { 40, 0, 0 } // Freq is 40/1500, q is 72 }; var passingReferenceHigh = new CandidateAllele("chr1", highCoverageCoordinate, "A", "A", AlleleCategory.Reference) { SupportByDirection = new[] { 500, 0, 0 } // Freq is 500/1500, q is 100 }; var passingReferenceLow = new CandidateAllele("chr3", lowCoverageCoordinate, "A", "A", AlleleCategory.Reference) { SupportByDirection = new[] { 10, 0, 0 } // Freq is 10/15, q is 100 }; var candidateVariants = new List <CandidateAllele> { passingVariant }; //Variants should be correctly mapped var mockAlleleCountSource = MockStateManager(highCoverageCoordinate, lowCoverageCoordinate).Object; var BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); var BaseCalledAllele = BaseCalledAlleles.First(); Assert.Equal(passingVariant.AlternateAllele, BaseCalledAllele.AlternateAllele); Assert.Equal(passingVariant.ReferenceAllele, BaseCalledAllele.ReferenceAllele); Assert.Equal(passingVariant.Chromosome, BaseCalledAllele.Chromosome); Assert.Equal(passingVariant.ReferencePosition, BaseCalledAllele.ReferencePosition); Assert.Equal(passingVariant.Support, BaseCalledAllele.AlleleSupport); Assert.True(passingVariant.Type != AlleleCategory.Reference); Assert.True(BaseCalledAllele.Type == AlleleCategory.Snv); //After the Calculator steps are performed, variants that don't meet //our requirements to be callable should drop out //High coverage requirement - lowCoverageVariant should drop out. config.MinCoverage = (HighCoverageMultiplier * NumAlleles * NumDirections) - 1; config.IncludeReferenceCalls = false; config.MinVariantQscore = 0; config.MinFrequency = 0; variantCaller = new AlleleCaller(config); candidateVariants = new List <CandidateAllele> { passingVariant, lowFreqVariant, lowCoverageVariant }; BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); Assert.Equal(2, BaseCalledAlleles.Count()); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, lowFreqVariant))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowCoverageVariant))); //High coverage but allow reference calls = nothing should drop out config.IncludeReferenceCalls = true; variantCaller = new AlleleCaller(config); candidateVariants = new List <CandidateAllele> { passingVariant, lowFreqVariant, lowCoverageVariant }; BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); foreach (var cvar in BaseCalledAlleles) { Console.WriteLine(cvar.VariantQscore); } Assert.Equal(3, BaseCalledAlleles.Count()); //High frequency requirement - low frequency variant should drop out config.MinCoverage = 0; config.IncludeReferenceCalls = false; config.MinVariantQscore = 0; config.MinFrequency = ((float)lowCoverageVariant.Support + 1) / (HighCoverageMultiplier * NumAlleles * NumDirections); BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); Assert.Equal(2, BaseCalledAlleles.Count()); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowFreqVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, lowCoverageVariant))); //High q score requirement - low frequency variant should drop out config.MinCoverage = 0; config.IncludeReferenceCalls = false; config.MinVariantQscore = 0; config.MinFrequency = 0; config.MinVariantQscore = VariantQualityCalculator.AssignPoissonQScore(lowqVariant.Support, (HighCoverageMultiplier * Constants.NumCovContributingAlleleTypes * Constants.NumDirectionTypes), config.NoiseLevelUsedForQScoring, config.MaxVariantQscore) + 1; candidateVariants = new List <CandidateAllele> { passingVariant, passingVariant2, lowFreqVariant, lowCoverageVariant, lowqVariant }; BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); Assert.Equal(3, BaseCalledAlleles.Count()); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant2))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowFreqVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, lowCoverageVariant))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowqVariant))); //High genotype q score requirement - low GQ variant should filter config.MinCoverage = 0; config.IncludeReferenceCalls = false; config.MinVariantQscore = 0; config.MinFrequency = 0; config.GenotypeCalculator = new DiploidThresholdingGenotyper(); config.LowGTqFilter = 20; config.MaxGenotypeQscore = int.MaxValue; candidateVariants = new List <CandidateAllele> { passingVariant, passingVariant2, lowFreqVariant, lowCoverageVariant, lowqVariant }; variantCaller = new AlleleCaller(config); BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); Assert.Equal(2, BaseCalledAlleles.Count()); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant2))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowFreqVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, lowCoverageVariant))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowqVariant))); var calledList = BaseCalledAlleles.ToList(); Assert.True(calledList[0].Filters.Contains(FilterType.LowGenotypeQuality)); //1249, forced to 0 for nocall. Assert.True(calledList[1].Filters.Contains(FilterType.LowGenotypeQuality)); //1249, forced to 0 for nocall //Assert.True(calledList[2].Filters.Contains(FilterType.LowGenotypeQuality));//0 pruned //go back to somatic config for the rest of the tests. config.GenotypeCalculator = new SomaticGenotyper(); config.LowGTqFilter = 0; config.MaxGenotypeQscore = 0; config.MinVariantQscore = VariantQualityCalculator.AssignPoissonQScore(lowqVariant.Support, (HighCoverageMultiplier * Constants.NumCovContributingAlleleTypes * Constants.NumDirectionTypes), config.NoiseLevelUsedForQScoring, config.MaxVariantQscore) + 1; // reference calls included candidateVariants = new List <CandidateAllele> { passingReferenceHigh, passingReferenceLow }; variantCaller = new AlleleCaller(config); BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); Assert.Equal(2, BaseCalledAlleles.Count()); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingReferenceHigh))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingReferenceLow))); // reference calls only included if no passing variant candidateVariants = new List <CandidateAllele> { passingReferenceHigh, passingReferenceLow, passingVariant, passingVariant2, lowFreqVariant, lowCoverageVariant, lowqVariant }; BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); Assert.Equal(3, BaseCalledAlleles.Count()); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, passingReferenceHigh))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, passingReferenceLow))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant2))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowFreqVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, lowCoverageVariant))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowqVariant))); // reference calls only included if no passing variant (lowCoverageVariant fails) candidateVariants = new List <CandidateAllele> { passingReferenceLow, lowCoverageVariant, }; config.IncludeReferenceCalls = false; config.MinCoverage = (HighCoverageMultiplier * NumAlleles * NumDirections) - 1; variantCaller = new AlleleCaller(config); BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); Assert.Equal(1, BaseCalledAlleles.Count()); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingReferenceLow))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowCoverageVariant))); // candidates outside of intervals are trimmed off config.MinCoverage = 0; config.MinVariantQscore = 0; config.MinFrequency = 0; variantCaller = new AlleleCaller(config, new ChrIntervalSet(new List <Region>() { new Region(highCoverageCoordinate, lowCoverageCoordinate) }, "chr1")); candidateVariants = new List <CandidateAllele> { passingVariant, lowFreqVariant, lowCoverageVariant }; BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); Assert.Equal(3, BaseCalledAlleles.Count()); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, lowFreqVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, lowCoverageVariant))); variantCaller = new AlleleCaller(config, new ChrIntervalSet(new List <Region>() { new Region(highCoverageCoordinate, highCoverageCoordinate) }, "chr1")); BaseCalledAlleles = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource).Values.SelectMany(v => v); Assert.Equal(2, BaseCalledAlleles.Count()); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, passingVariant))); Assert.True(BaseCalledAlleles.Any(v => MatchVariants(v, lowFreqVariant))); Assert.False(BaseCalledAlleles.Any(v => MatchVariants(v, lowCoverageVariant))); }
public void CheckQScoresWithParameters(int depth) { var outputFile = Path.Combine(UnitTestPaths.TestDataDirectory, "QScoreCalculations_depth" + depth + ".csv"); if (!Directory.Exists(UnitTestPaths.TestDataDirectory)) { Directory.CreateDirectory(UnitTestPaths.TestDataDirectory); } if (File.Exists(outputFile)) { File.Delete(outputFile); } List <int[]> SampleValues = new List <int[]>() { }; //coverage,var calls double noise = 0.01; for (int i = 5; i < depth;) { SampleValues.Add(new int[] { depth, i }); i = i + 5; } List <double[]> BasicReturnedValues = new List <double[]>(); List <double[]> RawReturnedValues = new List <double[]>(); List <double[]> TriangleValues = new List <double[]>(); List <double[]> ChernoffReturnedValues = new List <double[]>(); { }//p,Q foreach (int[] item in SampleValues) { double pValue = VariantQualityCalculator.AssignPValue(item[1], item[0], 20); double Qscore = MathOperations.PtoQ(pValue); double[] Result = new double[] { pValue, Qscore }; BasicReturnedValues.Add(Result); TriangleValues.Add( Triangle_AssignQValue(item[0], noise, item[1])); ChernoffReturnedValues.Add(ChernoffBd_AssignQValue(item[0], noise, item[1] - 1)); RawReturnedValues.Add(new double[] { VariantQualityCalculator.AssignRawPoissonQScore(item[1], item[0], 20) }); } using (StreamWriter sw = new StreamWriter(outputFile)) { sw.WriteLine("noise, depth, call count,vf, exact p, exact Q, triangle approx, chrenoff approx,new Q"); var excelValuesForDepth500 = GetExcelValuesForDepth500(); var cherValuesForDepth10000 = GetExpectedValuesForDepth10000(); for (int i = 0; i < SampleValues.Count; i++) { sw.WriteLine(string.Join(",", noise.ToString(), SampleValues[i][0].ToString(), SampleValues[i][1].ToString(), ((double)SampleValues[i][1] / SampleValues[i][0]).ToString(), BasicReturnedValues[i][0], BasicReturnedValues[i][1], TriangleValues[i][1], ChernoffReturnedValues[i][1], RawReturnedValues[i][0] )); //check this never goes to NAN over our range Assert.False(TriangleValues[i][1] == double.NaN); if ((depth == 500) && (i < 6))//this list only has 6 values, before excel looses its lunch due to precision { //noise depth call count exact P exact Q Assert.Equal(excelValuesForDepth500[i][3], BasicReturnedValues[i][0], 4); Assert.Equal(excelValuesForDepth500[i][4], BasicReturnedValues[i][1], 4); } } if (depth == 10000)//checks we have a good dynamic range, but have not wandered off much from the limit. { Assert.Equal(cherValuesForDepth10000[0][4], ChernoffReturnedValues[1998][1], 4); Assert.Equal(cherValuesForDepth10000[0][5], RawReturnedValues[1998][0], 4); double error = (ChernoffReturnedValues[1998][1] - RawReturnedValues[1998][0]) / ChernoffReturnedValues[1998][1]; Assert.True(error <= 0.03); } } }
private static int CombineQualitiesByPoolingReads(int CallCount, int CovDepth, int EstimatedBaseCallQuality, int MaxQScore) { return(VariantQualityCalculator.AssignPoissonQScore(CallCount, CovDepth, EstimatedBaseCallQuality, MaxQScore)); }