public void AgeIsCorrectlyPrinted() { string description = new Genome(age: 3).ToString(); Assert.True(description.Contains("Age: 3"), $"Genome's age is not printed. Print was: {description}."); }
/// <summary> /// Determines the matching segments shared by this and the specified Genome. /// </summary> /// <param name="other">The other Genome to compare.</param> /// <param name="minSnpCount">The minimum number of contiguous matching Snp allele values to be considered a valid match.</param> /// <param name="minCm">The minimum length of a segment in centiMorgans to be considered a valid match.</param> /// <param name="minStitchCm">The minimum length of each of two segments that may be stitched together when separated by a single mismatch.</param> /// <param name="minStitchSnpCount">The minimum number of contiguous matching SNP allele values in each of two segments that may be /// stitched together when separated by a single mismatch.</param> /// <param name="onlyFull">Specifies whether </param> /// <returns>An IList of SegmentMatch structs describing the matching segments that were identified.</returns> public IList<SegmentMatch> MatchingSegments(Genome other, int minSnpCount, double minCm, int minStitchSnpCount, double minStitchCm, bool onlyFull) { var snps = this.GetSnps(); var result = new List<SegmentMatch>(); int matchCount = 0; int hoHoSnpCount = 0; var prevChr = -1; Snp startSnp, endSnp; startSnp = endSnp = null; int snpCount = 0; int genomeSnpCount = snps.Count; bool canJoinWithPrevious = false; foreach (var snp in snps) { snpCount++; byte alleles = this.genotypes[snp]; bool hoho = alleles.IsHomozygous(); alleles &= Allele.AllAlleles; if ((alleles != Allele.AT) && ((alleles & Allele.T) != 0)) alleles ^= Allele.AT; if ((alleles != Allele.CG) && ((alleles & Allele.G) != 0)) alleles ^= Allele.CG; byte otherAlleles = Allele.Null; if (other.Contains(snp)) otherAlleles = other[snp]; hoho &= otherAlleles.IsHomozygous(); otherAlleles &= Allele.AllAlleles; if ((otherAlleles != Allele.AT) && ((otherAlleles & Allele.T) != 0)) otherAlleles ^= Allele.AT; if ((otherAlleles != Allele.CG) && ((otherAlleles & Allele.G) != 0)) otherAlleles ^= Allele.CG; bool haveNull = ((alleles == Allele.Null) || (otherAlleles == Allele.Null)); hoho &= !haveNull; bool sameChromosome = (snp.Chromosome == prevChr); bool buildingMatch = (matchCount > 0); bool haveMatch = (haveNull && buildingMatch && sameChromosome) || ((alleles == otherAlleles) && !haveNull); if (!onlyFull) haveMatch = haveMatch || ((alleles & otherAlleles) != 0); if (buildingMatch) { if (haveMatch && sameChromosome && (snpCount != genomeSnpCount)) { endSnp = snp; if (!haveNull) { matchCount++; if (hoho) hoHoSnpCount++; } } else { if ((matchCount >= minStitchSnpCount) && (endSnp.cM - startSnp.cM >= minStitchCm)) { // matching segment is big enough to keep if (canJoinWithPrevious) { var lastMatch = result[result.Count - 1]; result[result.Count - 1] = new SegmentMatch(lastMatch.StartSnp, endSnp, lastMatch.SnpCount + matchCount, lastMatch.HoHoSnpCount + hoHoSnpCount, lastMatch.HalvesMatched); } else { result.Add(new SegmentMatch(startSnp, endSnp, matchCount, hoHoSnpCount, onlyFull ? 2 : 1)); } canJoinWithPrevious = sameChromosome; } else { if (!haveNull) canJoinWithPrevious = false; } if (haveMatch) { //we're on next chromosome and it starts with a match startSnp = endSnp = snp; matchCount = 1; if (hoho) hoHoSnpCount = 1; } else { startSnp = endSnp = null; matchCount = 0; hoHoSnpCount = 0; } } } else { // !buildingMatch if (haveMatch) { startSnp = endSnp = snp; matchCount = 1; if (hoho) hoHoSnpCount = 1; } else { if (!haveNull) canJoinWithPrevious = false; } } prevChr = snp.Chromosome; } List<SegmentMatch> filteredResult = new List<SegmentMatch>(); if ((minSnpCount != minStitchSnpCount) || (minCm != minStitchCm)) { foreach (var match in result) { if ((match.SnpCount >= minSnpCount) && (match.CmLength >= minCm)) { filteredResult.Add(match); } } return filteredResult; } else { return result; } }