public void Equality_Reference() { // happy path var chromosome = "chr1"; var coordinate = 1; var reference = "A"; var alternate = "A"; var candidateVariant = new CandidateAllele(chromosome, coordinate, reference, alternate, AlleleCategory.Reference); var otherVariant = new CandidateAllele(chromosome, coordinate, reference, alternate, AlleleCategory.Reference); Assert.True(candidateVariant.Equals(otherVariant)); // error conditions otherVariant = new CandidateAllele("chrX", coordinate, reference, alternate, AlleleCategory.Reference); // different chrom Assert.False(candidateVariant.Equals(otherVariant)); otherVariant = new CandidateAllele(chromosome, 9999, reference, alternate, AlleleCategory.Reference); // different coord Assert.False(candidateVariant.Equals(otherVariant)); otherVariant = new CandidateAllele(chromosome, coordinate, "XYZ", alternate, AlleleCategory.Reference); // different reference Assert.False(candidateVariant.Equals(otherVariant)); otherVariant = new CandidateAllele(chromosome, coordinate, reference, "XYZ", AlleleCategory.Reference); // different alt Assert.False(candidateVariant.Equals(otherVariant)); var otherVariantInsertion = new CandidateAllele(chromosome, coordinate, reference, alternate, AlleleCategory.Mnv); // different variant type Assert.False(candidateVariant.Equals(otherVariantInsertion)); otherVariant = null; Assert.False(candidateVariant.Equals(otherVariant)); }
public void Constructor_MNV() { // happy path var chromosome = "chr1"; var coordinate = 1; var reference = "ATC"; var alternate = "GAA"; var candidateVariant = new CandidateAllele(chromosome, coordinate, reference, alternate, AlleleCategory.Mnv); Assert.Equal(chromosome, candidateVariant.Chromosome); Assert.Equal(coordinate, candidateVariant.ReferencePosition); Assert.Equal(reference, candidateVariant.ReferenceAllele); Assert.Equal(alternate, candidateVariant.AlternateAllele); //Verify Length Assert.Equal(3, candidateVariant.Length); // error conditions // chromosome name Assert.Throws <ArgumentException>(() => new CandidateAllele("", coordinate, reference, alternate, AlleleCategory.Mnv)); Assert.Throws <ArgumentException>(() => new CandidateAllele(null, coordinate, reference, alternate, AlleleCategory.Mnv)); // coordinate Assert.Throws <ArgumentException>(() => new CandidateAllele(chromosome, -1, reference, alternate, AlleleCategory.Mnv)); // reference Assert.Throws <ArgumentException>(() => new CandidateAllele(chromosome, coordinate, "", alternate, AlleleCategory.Mnv)); Assert.Throws <ArgumentException>(() => new CandidateAllele(chromosome, coordinate, null, alternate, AlleleCategory.Mnv)); // alternate Assert.Throws <ArgumentException>(() => new CandidateAllele(chromosome, coordinate, reference, "", AlleleCategory.Mnv)); Assert.Throws <ArgumentException>(() => new CandidateAllele(chromosome, coordinate, reference, null, AlleleCategory.Mnv)); }
public void CallVariants_MnvReallocatesToSnvOutsideInterval() { var config = new VariantCallerConfig { MaxVariantQscore = 100, EstimatedBaseCallQuality = 20, IncludeReferenceCalls = true, MinFrequency = 6f / 150 }; var intervalSet = new ChrIntervalSet(new List <Region>() { new Region(1900, 1950) }, "chr1"); var variantCaller = new AlleleCaller(config, intervalSet); // ----------------------------------------------- // Passing MNV that spans interval edge should be called if it begins within intervals // Failing MNVs that span interval edge and are reallocated to SNVs should only have those SNVs called if they are within intervals // (broken-out SNVs outside intervals should not be called even if they gain enough support to be called). // ----------------------------------------------- var passingMnv = new CandidateAllele("chr1", 1950, "TTT", "CCC", AlleleCategory.Mnv) { SupportByDirection = new[] { 10, 0, 0 } }; var failingMnv1 = new CandidateAllele("chr1", 1950, "TTT", "GGG", AlleleCategory.Mnv) // only the first SNV should be called (1950 T>G) { SupportByDirection = new[] { 5, 0, 0 } }; var failingMnv1Booster = new CandidateAllele("chr1", 1949, "TTTT", "GGGG", AlleleCategory.Mnv) // only the second SNV should be called (1950 T>G) { SupportByDirection = new[] { 5, 0, 0 } }; var failingMnv2 = new CandidateAllele("chr1", 1950, "TTT", "AAA", AlleleCategory.Mnv) // none of these should be called { SupportByDirection = new[] { 5, 0, 0 } }; var mockStateManager = MockStateManager(306, 0); var candidateVariants = new List <CandidateAllele> { passingMnv, failingMnv1, failingMnv2, failingMnv1Booster }; var batch = new CandidateBatch(candidateVariants) { MaxClearedPosition = 2000 }; var calledVariants = variantCaller.Call(batch, mockStateManager.Object); PrintResults(calledVariants.ToList()); Assert.Equal(2, calledVariants.Count()); }
public static CalledAllele Map(CandidateAllele candidate) { /* * var calledAllele = candidate.Type == AlleleCategory.Reference * ? (BaseCalledAllele)new BaseCalledAllele() * : new BaseCalledAllele(candidate.Type); */ var calledAllele = new CalledAllele(candidate.Type); calledAllele.Alternate = candidate.Alternate; calledAllele.Reference = candidate.Reference; calledAllele.Chromosome = candidate.Chromosome; calledAllele.Coordinate = candidate.Coordinate; calledAllele.AlleleSupport = candidate.Support; Array.Copy(candidate.SupportByDirection, calledAllele.SupportByDirection, candidate.SupportByDirection.Length); if (candidate.Type != AlleleCategory.Reference) { for (var i = 0; i < candidate.ReadCollapsedCounts.Length; i++) { calledAllele.ReadCollapsedCounts[i] = candidate.ReadCollapsedCounts[i]; } } return(calledAllele); }
public void CreateAndAdd() { var candidates = new List <CandidateAllele>() { new CandidateAllele("chr1", 100, "A", "AT", AlleleCategory.Insertion), new CandidateAllele("chr1", 100, "A", "A", AlleleCategory.Reference), new CandidateAllele("chr1", 100, "A", "T", AlleleCategory.Snv), new CandidateAllele("chr1", 200, "A", "T", AlleleCategory.Mnv) }; var batch = new CandidateBatch(candidates); var batchCandidates = batch.GetCandidates(); Assert.Equal(4, batchCandidates.Count); foreach (var candidate in candidates) { Assert.True(batchCandidates.Contains(candidate)); } // add new candidate var newCandidate = new CandidateAllele("chr1", 200, "AT", "A", AlleleCategory.Deletion); batch.Add(new List <CandidateAllele>() { newCandidate }); Assert.Equal(5, batchCandidates.Count); Assert.True(batchCandidates.Contains(newCandidate)); }
/// <summary> /// Create a new candidate allele from alignment and add support. Exposed only for unit testing. /// </summary> /// <param name="type"></param> /// <param name="chromosome"></param> /// <param name="coordinate"></param> /// <param name="reference"></param> /// <param name="alternate"></param> /// <param name="alignment"></param> /// <param name="startIndexInRead"></param> /// <returns></returns> public static CandidateAllele Create(AlleleCategory type, string chromosome, int coordinate, string reference, string alternate, Read alignment, int startIndexInRead) { var candidate = new CandidateAllele(chromosome, coordinate, reference, alternate, type); var alleleSupportDirection = GetSupportDirection(candidate, alignment, startIndexInRead); candidate.SupportByDirection[(int)alleleSupportDirection]++; if (alignment.IsDuplex) { if (alleleSupportDirection == DirectionType.Stitched) { candidate.ReadCollapsedCounts[(int)ReadCollapsedType.DuplexStitched]++; } else { candidate.ReadCollapsedCounts[(int)ReadCollapsedType.DuplexNonStitched]++; } } else { if (alleleSupportDirection == DirectionType.Stitched) { candidate.ReadCollapsedCounts[(int)ReadCollapsedType.SimplexStitched]++; } else { candidate.ReadCollapsedCounts[(int)ReadCollapsedType.SimplexNonStitched]++; } } return(candidate); }
public Dictionary <SomaticVariantType, List <VariantSite> > FindVariantSites(Read read, string chromosomeName) { var pseudoRefChromosome = new string('R', (int)read.CigarData.GetReferenceSpan() + 100); var dict = new Dictionary <SomaticVariantType, List <VariantSite> >() { { SomaticVariantType.Deletion, new List <VariantSite>() }, { SomaticVariantType.SNP, new List <VariantSite>() }, { SomaticVariantType.Insertion, new List <VariantSite>() } }; var startIndexInRead = 0; var startIndexInPseudoReference = 1; for (var cigarOpIndex = 0; cigarOpIndex < read.CigarData.Count; cigarOpIndex++) { var operation = read.CigarData[cigarOpIndex]; CandidateAllele candidate = null; var type = SomaticVariantType.SNP; var found = false; switch (operation.Type) { case 'I': candidate = ExtractInsertionFromOperation(read, pseudoRefChromosome, startIndexInRead, operation.Length, startIndexInPseudoReference, chromosomeName); type = SomaticVariantType.Insertion; found = true; break; case 'D': candidate = ExtractDeletionFromOperation(read, pseudoRefChromosome, startIndexInRead, operation.Length, startIndexInPseudoReference, chromosomeName); type = SomaticVariantType.Deletion; found = true; break; case 'M': candidate = ExtractGappedMnv(read, pseudoRefChromosome, startIndexInRead, (int)operation.Length, startIndexInPseudoReference, chromosomeName); type = SomaticVariantType.SNP; found = true; break; } if (found) { dict[type].Add(MapCandidateVariant(read.Position, candidate, candidate == null, startIndexInPseudoReference)); } if (operation.IsReadSpan()) { startIndexInRead += (int)operation.Length; } if (operation.IsReferenceSpan()) { startIndexInPseudoReference += (int)operation.Length; } } return(dict); }
public void CallVariants_MnvTakingRefSupport() { var config = new VariantCallerConfig { MaxVariantQscore = 100, EstimatedBaseCallQuality = 20, IncludeReferenceCalls = true }; var variantCaller = new AlleleCaller(config); //Failing MNV shouldn't contribute var passingMnv = new CandidateAllele("chr1", 305, "TTA", "GTG", AlleleCategory.Mnv) { SupportByDirection = new[] { 10, 0, 0 } }; var passingSnv = new CandidateAllele("chr1", 306, "T", "G", AlleleCategory.Snv) { SupportByDirection = new[] { 200, 0, 0 } }; var passingDeletion = new CandidateAllele("chr1", 305, "TTT", "T", AlleleCategory.Deletion) { SupportByDirection = new[] { 100, 0, 0 } }; var mockAlleleCountSource = MockStateManager(306, 0); mockAlleleCountSource.Setup(c => c.GetGappedMnvRefCount(306)).Returns(10); mockAlleleCountSource.Setup(c => c.AddGappedMnvRefCount(It.IsAny <Dictionary <int, int> >())).Callback((Dictionary <int, int> lookup) => { Assert.Equal(1, lookup.Count); Assert.True(lookup.ContainsKey(306)); Assert.Equal(10, lookup[306]); }); config.MinCoverage = 0; config.MinVariantQscore = 0; config.MinFrequency = 0; variantCaller = new AlleleCaller(config); var candidateVariants = new List <CandidateAllele> { passingMnv, passingDeletion, passingSnv }; var calledVariants = variantCaller.Call(new CandidateBatch(candidateVariants), mockAlleleCountSource.Object); PrintResults(calledVariants.ToList()); Assert.True(calledVariants.Any(v => MatchVariants(v, passingMnv, 10))); // Passing MNV should have additional support from big failed MNV Assert.True(calledVariants.Any(v => MatchVariants(v, passingSnv, 200))); // Passing SNV should have coverage that includes the passing MNV but not support Assert.True(calledVariants.Any(v => MatchVariants(v, passingDeletion))); // Passing deletion should not do anything here Assert.Equal((3 * HighCoverageMultiplier) - passingMnv.Support, ((CalledVariant)calledVariants.First(v => MatchVariants(v, passingSnv))).ReferenceSupport); // Passing SNV should have coverage that includes the passing MNV but not support }
private CandidateAllele Map(BaseCalledAllele called) { var candidateAllele = new CandidateAllele(called.Chromosome, called.Coordinate, called.Reference, called.Alternate, called.Type); Array.Copy(called.SupportByDirection, candidateAllele.SupportByDirection, called.SupportByDirection.Length); return(candidateAllele); }
public void AddCandidate(CandidateAllele candidate, bool trackOpenEnded = false) { if (candidate.Type == AlleleCategory.Reference) { throw new ArgumentException(string.Format("Unable to add candidate '{0}': reference candidates are not tracked.", candidate)); } if (!IsPositionInRegion(candidate.Coordinate)) { throw new ArgumentException(string.Format("Unable to add candidate at position {0} to region '{1}'", candidate.Coordinate, Name)); } var regionIndex = candidate.Coordinate - StartPosition; var existingCandidates = _candidateVariantsLookup[regionIndex]; if (existingCandidates == null) { _candidateVariantsLookup[regionIndex] = new List <CandidateAllele> { candidate } } ; else { //TJD - this used to be a hash table, not a find, //where each variants unique signature was the key. //this might be why we have seen a performance hit in the new pisces. var foundAtIndex = trackOpenEnded ? existingCandidates.FindIndex(c => c.Equals(candidate) && c.OpenOnLeft == candidate.OpenOnLeft && c.OpenOnRight == candidate.OpenOnRight) : existingCandidates.FindIndex(c => c.Equals(candidate)); if (foundAtIndex == -1) { existingCandidates.Add(candidate); } else { var existingMatch = existingCandidates[foundAtIndex]; for (var i = 0; i < existingMatch.SupportByDirection.Length; i++) { existingMatch.SupportByDirection[i] += candidate.SupportByDirection[i]; } for (var i = 0; i < existingMatch.ReadCollapsedCounts.Length; i++) { existingMatch.ReadCollapsedCounts[i] += candidate.ReadCollapsedCounts[i]; } } } UpdateMaxPosition(candidate); }
/// <summary> /// Create a new candidate allele from alignment and add support. Exposed only for unit testing. /// </summary> /// <param name="type"></param> /// <param name="chromosome"></param> /// <param name="coordinate"></param> /// <param name="reference"></param> /// <param name="alternate"></param> /// <param name="alignment"></param> /// <param name="startIndexInRead"></param> /// <returns></returns> public static CandidateAllele Create(AlleleCategory type, string chromosome, int coordinate, string reference, string alternate, Read alignment, int startIndexInRead) { var candidate = new CandidateAllele(chromosome, coordinate, reference, alternate, type); candidate.SupportByDirection[(int)GetSupportDirection(candidate, alignment, startIndexInRead)]++; return(candidate); }
/// <summary> /// Get the support direction at a particular point in a read, for a given candidate. Exposed only for unit testing. /// </summary> /// <param name="candidate"></param> /// <param name="bamAlignment"></param> /// <param name="startIndexInRead"></param> /// <returns></returns> public static DirectionType GetSupportDirection(CandidateAllele candidate, Read bamAlignment, int startIndexInRead) { if (candidate.Type == AlleleCategory.Snv || candidate.Type == AlleleCategory.Reference) { return(bamAlignment.SequencedBaseDirectionMap[startIndexInRead]); } var leftAnchorIndex = startIndexInRead - 1; var rightAnchorIndex = candidate.Type == AlleleCategory.Deletion ? startIndexInRead : startIndexInRead + candidate.Length; var lastIndex = bamAlignment.Sequence.Length - 1; if (rightAnchorIndex == 0) { return(bamAlignment.SequencedBaseDirectionMap[rightAnchorIndex]); } if (leftAnchorIndex == lastIndex) // this should only happen for deletion at the end { return(bamAlignment.SequencedBaseDirectionMap[lastIndex]); } if (leftAnchorIndex == rightAnchorIndex - 1) // for deletions { if (bamAlignment.CigarDirections != null) { return(GetDeletionDirectionForStitchedRead(bamAlignment, leftAnchorIndex, rightAnchorIndex)); } //fall back to old method if we were not tracking directions "inside" deletions. var startDirection = bamAlignment.SequencedBaseDirectionMap[leftAnchorIndex]; var endDirection = bamAlignment.SequencedBaseDirectionMap[rightAnchorIndex]; //GB: why do we preferentially do this, below? //TD: I believe its arbitrary and also it is what we always used to do.So any changes here would have unknown affects. I think the original point was, if all else fails, at least be predictable. return(startDirection == DirectionType.Stitched ? endDirection : startDirection); } DirectionType direction = DirectionType.Forward; // otherwise, walk through and if any direction between anchor points is stitched, return stitched for (var i = leftAnchorIndex + 1; i < rightAnchorIndex; i++) { direction = bamAlignment.SequencedBaseDirectionMap[i]; if (direction == DirectionType.Stitched) { return(DirectionType.Stitched); } } // sanity check that we didn't magically transition from F/R or R/F without stitched region if (bamAlignment.SequencedBaseDirectionMap[leftAnchorIndex + 1] != bamAlignment.SequencedBaseDirectionMap[rightAnchorIndex - 1]) { throw new InvalidDataException("Alignment error: Found change in direction without encountering stitched direction"); } return(direction); }
private VariantSite MapCandidateVariant(int readPosition, CandidateAllele allele, bool failed, int refPosition) { var positionAdjustment = failed ? refPosition : allele.Coordinate; var position = readPosition - 2 + positionAdjustment; return(new VariantSite(position) { VcfReferenceAllele = failed ? "N" : allele.Reference, VcfAlternateAllele = failed ? "N" : allele.Alternate }); }
private IEnumerable <CandidateAllele> CreateCandidateAlleleFromForceAlleles(int position, List <Tuple <string, string> > forcedAlleles) { var candidates = new List <CandidateAllele>(); foreach (var forcedAllele in forcedAlleles) { var category = GetAlleleCategory(forcedAllele.Item1, forcedAllele.Item2); var candidateAllele = new CandidateAllele(_chrReference.Name, position, forcedAllele.Item1, forcedAllele.Item2, category); candidates.Add(candidateAllele); } return(candidates); }
public void PrunedForcedAlleleShouldBeCalled() { var mockCandidateToBatch = new Mock <ICandidateBatch>(); var candidateAllele1 = new CandidateAllele("chr1", 10, "G", "T", AlleleCategory.Snv); mockCandidateToBatch.Setup(s => s.GetCandidates()).Returns(new List <CandidateAllele> { candidateAllele1 }); mockCandidateToBatch.SetupGet(s => s.MaxClearedPosition).Returns(100); var config = new VariantCallerConfig { MinCoverage = 20 }; var myChrRef = new ChrReference() { Name = "chr1", Sequence = "ATGGCCTACGATTAGTAGGT" }; config.ChrReference = myChrRef; //config.MinCoverage = 20; var mockCoverageCalculator = new Mock <ICoverageCalculator>(); mockCoverageCalculator.Setup(x => x.Compute(It.IsAny <CalledAllele>(), It.IsAny <IAlleleSource>())); var mockGenotypeCalculator = new Mock <IGenotypeCalculator>(); mockGenotypeCalculator.Setup(x => x.SetGenotypes(It.IsAny <IEnumerable <CalledAllele> >())).Returns <List <CalledAllele> >(s => s); //note: returns allele to prune config.GenotypeCalculator = mockGenotypeCalculator.Object; config.LocusProcessor = new DiploidLocusProcessor(); var alleleCaller = new AlleleCaller(config, null, null, mockCoverageCalculator.Object); var mockAlleleSource = new Mock <IAlleleSource>(); var observedAllelewithoutForcedAllele = alleleCaller.Call(mockCandidateToBatch.Object, mockAlleleSource.Object); Assert.Equal(0, observedAllelewithoutForcedAllele.Count); var forcedGtAlleles = new HashSet <Tuple <string, int, string, string> > { new Tuple <string, int, string, string>("chr1", 10, "G", "T") }; alleleCaller.AddForcedGtAlleles(forcedGtAlleles); var observedCalledAllele = alleleCaller.Call(mockCandidateToBatch.Object, mockAlleleSource.Object); Assert.Equal(1, observedCalledAllele.Count); Assert.True(observedCalledAllele.First().Value.First().IsForcedToReport); }
private BaseCalledAllele Map(CandidateAllele candidate) { var calledAllele = candidate.Type == AlleleCategory.Reference ? (BaseCalledAllele) new CalledReference() : new CalledVariant(candidate.Type); calledAllele.Alternate = candidate.Alternate; calledAllele.Reference = candidate.Reference; calledAllele.Chromosome = candidate.Chromosome; calledAllele.Coordinate = candidate.Coordinate; calledAllele.AlleleSupport = candidate.Support; Array.Copy(candidate.SupportByDirection, calledAllele.SupportByDirection, candidate.SupportByDirection.Length); return(calledAllele); }
private bool MatchVariants(BaseCalledAllele calledVariant, CandidateAllele candidateVariant, int?expectedSupport = null, float?expectedFreq = null) { if (calledVariant.Chromosome == candidateVariant.Chromosome && calledVariant.Coordinate == candidateVariant.Coordinate && calledVariant.Reference == candidateVariant.Reference && calledVariant.Alternate == candidateVariant.Alternate && calledVariant.Type == candidateVariant.Type && (expectedFreq == null || calledVariant.Frequency == expectedFreq) && (expectedSupport == null || calledVariant.AlleleSupport == expectedSupport) ) { return(true); } return(false); }
private bool MatchVariants(CalledAllele BaseCalledAllele, CandidateAllele candidateVariant, int?expectedSupport = null, float?expectedFreq = null) { if (BaseCalledAllele.Chromosome == candidateVariant.Chromosome && BaseCalledAllele.ReferencePosition == candidateVariant.ReferencePosition && BaseCalledAllele.ReferenceAllele == candidateVariant.ReferenceAllele && BaseCalledAllele.AlternateAllele == candidateVariant.AlternateAllele && BaseCalledAllele.Type == candidateVariant.Type && (expectedFreq == null || BaseCalledAllele.Frequency == expectedFreq) && (expectedSupport == null || BaseCalledAllele.AlleleSupport == expectedSupport) ) { return(true); } return(false); }
/// <summary> /// Get the support direction at a particular point in a read, for a given candidate. Exposed only for unit testing. /// </summary> /// <param name="candidate"></param> /// <param name="bamAlignment"></param> /// <param name="startIndexInRead"></param> /// <returns></returns> public static DirectionType GetSupportDirection(CandidateAllele candidate, Read bamAlignment, int startIndexInRead) { if (candidate.Type == AlleleCategory.Snv || candidate.Type == AlleleCategory.Reference) { return(bamAlignment.SequencedBaseDirectionMap[startIndexInRead]); } var leftAnchorIndex = startIndexInRead - 1; var rightAnchorIndex = candidate.Type == AlleleCategory.Deletion ? startIndexInRead : startIndexInRead + candidate.Length; var lastIndex = bamAlignment.Sequence.Length - 1; if (rightAnchorIndex == 0) { return(bamAlignment.SequencedBaseDirectionMap[rightAnchorIndex]); } if (leftAnchorIndex == lastIndex) // this should only happen for deletion at the end { return(bamAlignment.SequencedBaseDirectionMap[lastIndex]); } if (leftAnchorIndex == rightAnchorIndex - 1) // for deletions { var startDirection = bamAlignment.SequencedBaseDirectionMap[leftAnchorIndex]; var endDirection = bamAlignment.SequencedBaseDirectionMap[rightAnchorIndex]; return(startDirection == DirectionType.Stitched ? endDirection : startDirection); } DirectionType direction = DirectionType.Forward; // otherwise, walk through and if any direction between anchor points is stitched, return stitched for (var i = leftAnchorIndex + 1; i < rightAnchorIndex; i++) { direction = bamAlignment.SequencedBaseDirectionMap[i]; if (direction == DirectionType.Stitched) { return(DirectionType.Stitched); } } // sanity check that we didn't magically transition from F/R or R/F without stitched region if (bamAlignment.SequencedBaseDirectionMap[leftAnchorIndex + 1] != bamAlignment.SequencedBaseDirectionMap[rightAnchorIndex - 1]) { throw new Exception("Found change in direction without encountering stitched direction"); } return(direction); }
public static CandidateAllele Map(CalledAllele called) { var candidateAllele = new CandidateAllele(called.Chromosome, called.Coordinate, called.Reference, called.Alternate, called.Type); Array.Copy(called.SupportByDirection, candidateAllele.SupportByDirection, called.SupportByDirection.Length); if (called.Type != AlleleCategory.Reference) { for (var i = 0; i < called.ReadCollapsedCounts.Length; i++) { candidateAllele.ReadCollapsedCounts[i] = called.ReadCollapsedCounts[i]; } } return(candidateAllele); }
public void AddCandidate(CandidateAllele candidate) { if (candidate.Type == AlleleCategory.Reference) { throw new ArgumentException(string.Format("Unable to add candidate '{0}': reference candidates are not tracked.", candidate)); } if (!IsPositionInRegion(candidate.Coordinate)) { throw new ArgumentException(string.Format("Unable to add candidate at position {0} to region '{1}'", candidate.Coordinate, Name)); } var regionIndex = candidate.Coordinate - StartPosition; var existingCandidates = _candidateVariantsLookup[regionIndex]; if (existingCandidates == null) { _candidateVariantsLookup[regionIndex] = new List <CandidateAllele>() { candidate } } ; else { var foundAtIndex = existingCandidates.IndexOf(candidate); if (foundAtIndex == -1) { existingCandidates.Add(candidate); } else { var existingMatch = existingCandidates[foundAtIndex]; for (var i = 0; i < existingMatch.SupportByDirection.Length; i++) { existingMatch.SupportByDirection[i] += candidate.SupportByDirection[i]; } } } UpdateMaxPosition(candidate); }
public void CandidateAllele_IsFullyAnchored() { var candidateVariant = new CandidateAllele("chr1", 1, "AGC", "AGCTACT", AlleleCategory.Insertion); candidateVariant.OpenOnLeft = true; candidateVariant.OpenOnRight = true; Assert.False(candidateVariant.FullyAnchored); candidateVariant.OpenOnLeft = true; candidateVariant.OpenOnRight = false; Assert.False(candidateVariant.FullyAnchored); candidateVariant.OpenOnLeft = false; candidateVariant.OpenOnRight = true; Assert.False(candidateVariant.FullyAnchored); candidateVariant.OpenOnLeft = false; candidateVariant.OpenOnRight = false; Assert.True(candidateVariant.FullyAnchored); }
private void UpdateMaxPosition(CandidateAllele candidate) { int otherEnd = 0; switch (candidate.Type) { case AlleleCategory.Deletion: otherEnd = candidate.ReferencePosition + candidate.ReferenceAllele.Length; break; case AlleleCategory.Insertion: otherEnd = candidate.ReferencePosition + 1; break; case AlleleCategory.Mnv: otherEnd = candidate.ReferencePosition + candidate.ReferenceAllele.Length - 1; break; } if (otherEnd > MaxAlleleEndpoint) { MaxAlleleEndpoint = otherEnd; } }
public void TestOpennessUpdates() { // The generally the openness of the variant does not change, but when // SNVs of opposing endedness collapse into another variant the endedness will become anchored. var MNVFullOpenLeft = GetBasicMNV(); MNVFullOpenLeft.OpenOnLeft = true; var MNVFullOpenRight = GetBasicMNV(); MNVFullOpenRight.OpenOnRight = true; var snvOpenLeft = new CandidateAllele("chr1", 12, "T", "A", AlleleCategory.Snv); snvOpenLeft.OpenOnLeft = true; var snvOpenRight = new CandidateAllele("chr1", 5, "T", "A", AlleleCategory.Snv); snvOpenRight.OpenOnRight = true; // Baseline tests ExecuteEndednessTest(new List <CandidateAllele>() { MNVFullOpenLeft, snvOpenLeft }, true, false); ExecuteEndednessTest(new List <CandidateAllele>() { MNVFullOpenRight, snvOpenRight }, false, true); // Collapse Tests ExecuteEndednessTest(new List <CandidateAllele>() { MNVFullOpenLeft, snvOpenRight }, false, false); ExecuteEndednessTest(new List <CandidateAllele>() { MNVFullOpenLeft, snvOpenRight }, false, false); }
public static CalledAllele Map(CandidateAllele candidate) { var calledAllele = new CalledAllele(candidate.Type); calledAllele.AlternateAllele = candidate.AlternateAllele; calledAllele.ReferenceAllele = candidate.ReferenceAllele; calledAllele.Chromosome = candidate.Chromosome; calledAllele.ReferencePosition = candidate.ReferencePosition; calledAllele.AlleleSupport = candidate.Support; calledAllele.WellAnchoredSupport = candidate.WellAnchoredSupport; calledAllele.IsForcedToReport = candidate.IsForcedAllele; Array.Copy(candidate.SupportByDirection, calledAllele.SupportByDirection, candidate.SupportByDirection.Length); Array.Copy(candidate.WellAnchoredSupportByDirection, calledAllele.WellAnchoredSupportByDirection, candidate.WellAnchoredSupportByDirection.Length); if (candidate.Type != AlleleCategory.Reference) { for (var i = 0; i < candidate.ReadCollapsedCountsMut.Length; i++) { calledAllele.ReadCollapsedCountsMut[i] = candidate.ReadCollapsedCountsMut[i]; } } if (candidate.SupportByAmplicon.AmpliconNames != null) { calledAllele.SupportByAmplicon = new Models.AmpliconCounts() { AmpliconNames = new string[Constants.MaxNumOverlappingAmplicons], CountsForAmplicon = new int[Constants.MaxNumOverlappingAmplicons] }; Array.Copy(candidate.SupportByAmplicon.AmpliconNames, calledAllele.SupportByAmplicon.AmpliconNames, candidate.SupportByAmplicon.AmpliconNames.Length); Array.Copy(candidate.SupportByAmplicon.CountsForAmplicon, calledAllele.SupportByAmplicon.CountsForAmplicon, candidate.SupportByAmplicon.CountsForAmplicon.Length); } return(calledAllele); }
public static CalledAllele Map(CandidateAllele candidate) { var calledAllele = new CalledAllele(candidate.Type); calledAllele.AlternateAllele = candidate.AlternateAllele; calledAllele.ReferenceAllele = candidate.ReferenceAllele; calledAllele.Chromosome = candidate.Chromosome; calledAllele.ReferencePosition = candidate.ReferencePosition; calledAllele.AlleleSupport = candidate.Support; calledAllele.WellAnchoredSupport = candidate.WellAnchoredSupport; calledAllele.IsForcedToReport = candidate.IsForcedAllele; Array.Copy(candidate.SupportByDirection, calledAllele.SupportByDirection, candidate.SupportByDirection.Length); Array.Copy(candidate.WellAnchoredSupportByDirection, calledAllele.WellAnchoredSupportByDirection, candidate.WellAnchoredSupportByDirection.Length); if (candidate.Type != AlleleCategory.Reference) { for (var i = 0; i < candidate.ReadCollapsedCountsMut.Length; i++) { calledAllele.ReadCollapsedCountsMut[i] = candidate.ReadCollapsedCountsMut[i]; } } return(calledAllele); }
public void MapToBaseCalledAllele() { //Called variant var allele = new CandidateAllele("chr1", 1, "A", "G", AlleleCategory.Snv); allele.SupportByDirection = new[] { 10, 20, 30 }; var BaseCalledAllele = AlleleHelper.Map(allele); Assert.True(BaseCalledAllele.Type != AlleleCategory.Reference); Assert.Equal(BaseCalledAllele.Chromosome, allele.Chromosome); Assert.Equal(BaseCalledAllele.Coordinate, allele.Coordinate); Assert.Equal(BaseCalledAllele.Reference, allele.Reference); Assert.Equal(BaseCalledAllele.Alternate, allele.Alternate); Assert.Equal(BaseCalledAllele.Type, allele.Type); Assert.Equal(BaseCalledAllele.SupportByDirection.Count(), allele.SupportByDirection.Count()); for (int i = 0; i < allele.SupportByDirection.Count(); i++) { Assert.Equal(BaseCalledAllele.SupportByDirection[i], allele.SupportByDirection[i]); } //Called reference allele.Type = AlleleCategory.Reference; var calledReference = AlleleHelper.Map(allele); Assert.True(calledReference.Type == AlleleCategory.Reference); Assert.Equal(calledReference.Chromosome, allele.Chromosome); Assert.Equal(calledReference.Coordinate, allele.Coordinate); Assert.Equal(calledReference.Reference, allele.Reference); Assert.Equal(calledReference.Alternate, allele.Alternate); Assert.Equal(calledReference.Type, allele.Type); Assert.Equal(calledReference.SupportByDirection.Count(), allele.SupportByDirection.Count()); for (int i = 0; i < allele.SupportByDirection.Count(); i++) { Assert.Equal(calledReference.SupportByDirection[i], allele.SupportByDirection[i]); } }
public void ExecuteTest_GetCandidates(bool withReference, bool withIntervals) { var testRegion = new RegionState(1, 50); var chrReference = new ChrReference() { Name = "chr1", Sequence = string.Concat(Enumerable.Repeat("A", 50)) }; var snv1 = new CandidateAllele("chr1", 5, "A", "T", AlleleCategory.Snv) { SupportByDirection = new [] { 10, 5, 0 } }; var snv2 = new CandidateAllele("chr1", 15, "A", "T", AlleleCategory.Snv) { SupportByDirection = new[] { 10, 5, 0 } }; testRegion.AddCandidate(snv1); testRegion.AddCandidate(snv2); for (var i = 0; i < 5; i++) { testRegion.AddAlleleCount(5, AlleleType.A, DirectionType.Stitched); // ref @ variant position testRegion.AddAlleleCount(6, AlleleType.A, DirectionType.Stitched); // ref by itself testRegion.AddAlleleCount(10, AlleleType.C, DirectionType.Stitched); // nonref by itself (no ref) testRegion.AddAlleleCount(15, AlleleType.A, DirectionType.Reverse); // ref (multiple directions) + nonref testRegion.AddAlleleCount(15, AlleleType.A, DirectionType.Forward); testRegion.AddAlleleCount(15, AlleleType.T, DirectionType.Reverse); } ChrIntervalSet intervals = null; if (withIntervals) { intervals = new ChrIntervalSet(new List <CallSomaticVariants.Logic.RegionState.Region>() { new CallSomaticVariants.Logic.RegionState.Region(3, 6), new CallSomaticVariants.Logic.RegionState.Region(16, 16) }, "chr1"); } var expectedList = new List <CandidateAllele>(); expectedList.Add(snv1); expectedList.Add(snv2); if (withReference) { expectedList.Add(new CandidateAllele("chr1", 5, "A", "A", AlleleCategory.Reference) { SupportByDirection = new[] { 0, 0, 5 } }); expectedList.Add(new CandidateAllele("chr1", 6, "A", "A", AlleleCategory.Reference) { SupportByDirection = new[] { 0, 0, 5 } }); expectedList.Add(new CandidateAllele("chr1", 10, "A", "A", AlleleCategory.Reference) { SupportByDirection = new[] { 0, 0, 0 } }); expectedList.Add(new CandidateAllele("chr1", 15, "A", "A", AlleleCategory.Reference) { SupportByDirection = new[] { 5, 5, 0 } }); } if (withIntervals) { expectedList = expectedList.Where(c => c.Coordinate == 5 || c.Coordinate == 6 || c.Type != AlleleCategory.Reference).ToList(); if (withReference) { expectedList.Add(new CandidateAllele("chr1", 3, "A", "A", AlleleCategory.Reference) { SupportByDirection = new[] { 0, 0, 0 } }); expectedList.Add(new CandidateAllele("chr1", 4, "A", "A", AlleleCategory.Reference) { SupportByDirection = new[] { 0, 0, 0 } }); expectedList.Add(new CandidateAllele("chr1", 16, "A", "A", AlleleCategory.Reference) { SupportByDirection = new[] { 0, 0, 0 } }); } } var allCandidates = testRegion.GetAllCandidates(withReference, chrReference, intervals); VerifyCandidates(expectedList, allCandidates); }
public void AddAndGetCandidates() { // ----------------------------------------------- // simple test case adding candidate to empty region // ----------------------------------------------- var testRegion = new RegionState(1000, 2000); var snv1 = new CandidateAllele("chr1", 1500, "A", "T", AlleleCategory.Snv) { SupportByDirection = new[] { 10, 0, 0 } }; testRegion.AddCandidate(snv1); var allCandidates = testRegion.GetAllCandidates(false, null); Assert.Equal(allCandidates.Count, 1); var fetchedCandidate = allCandidates[0]; Assert.True(fetchedCandidate.Equals(snv1)); // ----------------------------------------------- // add same type of candidate but at different position // ----------------------------------------------- var snv2 = new CandidateAllele("chr1", 1501, "A", "T", AlleleCategory.Snv) { SupportByDirection = new[] { 5, 0, 0 } }; testRegion.AddCandidate(snv2); allCandidates = testRegion.GetAllCandidates(false, null); Assert.Equal(allCandidates.Count, 2); // make sure coverage is preserved fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(snv1)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 10); fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(snv2)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 5); // ----------------------------------------------- // add a different type of candidate at same position // ----------------------------------------------- var deletion1 = new CandidateAllele("chr1", 1500, "AT", "A", AlleleCategory.Deletion) { SupportByDirection = new[] { 15, 0, 0 } }; testRegion.AddCandidate(deletion1); allCandidates = testRegion.GetAllCandidates(false, null); Assert.Equal(allCandidates.Count, 3); // make sure coverage is preserved fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(snv1)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 10); fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(snv2)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 5); fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(deletion1)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 15); // ----------------------------------------------- // add same variant, but more coverage // ----------------------------------------------- var moreSnv1 = new CandidateAllele("chr1", 1500, "A", "T", AlleleCategory.Snv) { SupportByDirection = new[] { 2, 0, 0 } }; testRegion.AddCandidate(moreSnv1); allCandidates = testRegion.GetAllCandidates(false, null); Assert.Equal(allCandidates.Count, 3); // make sure coverage is incremented fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(snv1)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 12); // make sure coverage is preserved fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(snv2)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 5); fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(deletion1)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 15); var moreDeletion1 = new CandidateAllele("chr1", 1500, "AT", "A", AlleleCategory.Deletion) { SupportByDirection = new[] { 0, 18, 0 } }; testRegion.AddCandidate(moreDeletion1); allCandidates = testRegion.GetAllCandidates(false, null); Assert.Equal(allCandidates.Count, 3); // make sure coverage is incremented fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(deletion1)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 33); // make sure coverage is preserved fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(snv1)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 12); fetchedCandidate = allCandidates.FirstOrDefault(c => c.Equals(snv2)); Assert.True(fetchedCandidate != null && fetchedCandidate.Support == 5); // ----------------------------------------------- // add insertion that goes off block // ----------------------------------------------- var edgeInsertion = new CandidateAllele("chr1", 2000, "A", "TCG", AlleleCategory.Insertion) { SupportByDirection = new[] { 5, 0, 0 } }; testRegion.AddCandidate(edgeInsertion); allCandidates = testRegion.GetAllCandidates(false, null); Assert.Equal(allCandidates.Count, 4); Assert.Equal(2001, testRegion.MaxAlleleEndpoint); // ----------------------------------------------- // add mnv that goes off block // ----------------------------------------------- var edgeMnv = new CandidateAllele("chr1", 1999, "ATCC", "TCGG", AlleleCategory.Mnv) { SupportByDirection = new[] { 5, 0, 0 } }; testRegion.AddCandidate(edgeMnv); allCandidates = testRegion.GetAllCandidates(false, null); Assert.Equal(allCandidates.Count, 5); Assert.Equal(2002, testRegion.MaxAlleleEndpoint); // ----------------------------------------------- // add deletion that goes off block // ----------------------------------------------- var edgeDeletion = new CandidateAllele("chr1", 1999, "A" + new string('T', 25), "A", AlleleCategory.Deletion) { SupportByDirection = new[] { 5, 0, 0 } }; testRegion.AddCandidate(edgeDeletion); allCandidates = testRegion.GetAllCandidates(false, null); Assert.Equal(allCandidates.Count, 6); Assert.Equal(2025, testRegion.MaxAlleleEndpoint); // ----------------------------------------------- // add variant that goes off block but not as far as the deletion did - max endpoint should stay the same // ----------------------------------------------- var edgeMnv2 = new CandidateAllele("chr1", 1999, "ATCGA", "TCGCT", AlleleCategory.Mnv) { SupportByDirection = new[] { 5, 0, 0 } }; testRegion.AddCandidate(edgeMnv2); allCandidates = testRegion.GetAllCandidates(false, null); Assert.Equal(allCandidates.Count, 7); Assert.Equal(2025, testRegion.MaxAlleleEndpoint); }
public CandidateIndel(CandidateAllele baseCandidateAllele) : base(baseCandidateAllele.Chromosome, baseCandidateAllele.ReferencePosition, baseCandidateAllele.ReferenceAllele, baseCandidateAllele.AlternateAllele, baseCandidateAllele.Type) { SupportByDirection = baseCandidateAllele.SupportByDirection; IsKnown = baseCandidateAllele.IsKnown; }