/// <summary> /// Calculate additional effect due to codon changes, e.g. A frame-shift that also affects a stop codon /// </summary> /// <param name="codonsOld"></param> /// <param name="codonsNew"></param> /// <param name="codonNum"></param> /// <param name="codonIndex"></param> /// <returns></returns> protected EffectType AdditionalEffect(string codonsOld, string codonsNew, int codonNum, int codonIndex) { EffectType newEffectType = EffectType.NONE; bool hasOldAa = CodonExtensions.TryTranslateCodon(Transcript.Gene.Chromosome.Mitochondrial, codonsOld, out byte oldAA); bool hasNewAa = CodonExtensions.TryTranslateCodon(Transcript.Gene.Chromosome.Mitochondrial, codonsNew, out byte newAA); bool isStartNew = Transcript.Gene.Chromosome.Mitochondrial ? CodonsVertebrateMitochondrial.START_CODONS.Contains(codonsNew.ToUpper(CultureInfo.InvariantCulture)) : CodonsStandard.START_CODONS.Contains(codonsNew.ToUpper(CultureInfo.InvariantCulture)); bool isStartOld = Transcript.Gene.Chromosome.Mitochondrial ? CodonsVertebrateMitochondrial.START_CODONS.Contains(codonsOld.ToUpper(CultureInfo.InvariantCulture)) : CodonsStandard.START_CODONS.Contains(codonsOld.ToUpper(CultureInfo.InvariantCulture)); bool isStopOld = hasOldAa && oldAA == Alphabets.Protein.Ter; bool isStopNew = hasNewAa && newAA == Alphabets.Protein.Ter; if (Variant.isSnv() || Variant.isMnv()) { // SNM and MNP effects if (oldAA.Equals(newAA)) { // Same AA: Synonymous coding if (codonNum == 0 && isStartOld) { // It is in the first codon (which also is a start codon) if (isStartNew) { newEffectType = EffectType.SYNONYMOUS_START; } // The new codon is also a start codon => SYNONYMOUS_START else { newEffectType = EffectType.START_LOST; } // The AA is the same, but the codon is not a start codon => start lost } else if (isStopOld) { // Stop codon if (isStopNew) { newEffectType = EffectType.SYNONYMOUS_STOP; } // New codon is also a stop => SYNONYMOUS_STOP else { newEffectType = EffectType.STOP_LOST; } // New codon is not a stop, the we've lost a stop } else { newEffectType = EffectType.SYNONYMOUS_CODING; // All other cases are just SYNONYMOUS_CODING } } else { // Different AA: Non-synonymous coding if ((codonNum == 0) && isStartOld) { // It is in the first codon (which also is a start codon) if (isStartNew) { newEffectType = EffectType.NON_SYNONYMOUS_START; } // Non-synonymous mutation on first codon => start lost else { newEffectType = EffectType.START_LOST; } // Non-synonymous mutation on first codon => start lost } else if (isStopOld) { // Stop codon if (isStopNew) { newEffectType = EffectType.NON_SYNONYMOUS_STOP; } // Notice: This should never happen for SNPs! (for some reason I removed this comment at some point and that create some confusion): http://www.biostars.org/post/show/51352/in-snpeff-impact-what-is-difference-between-stop_gained-and-non-synonymous_stop/ else { newEffectType = EffectType.STOP_LOST; } } else if (isStopNew) { newEffectType = EffectType.STOP_GAINED; } else { newEffectType = EffectType.NON_SYNONYMOUS_CODING; // All other cases are just NON_SYN } } } else { // Add a new effect in some cases if ((codonNum == 0) && isStartOld && !isStartNew) { newEffectType = EffectType.START_LOST; } else if (isStopOld && !isStopNew) { newEffectType = EffectType.STOP_LOST; } else if (!isStopOld && isStopNew) { newEffectType = EffectType.STOP_GAINED; } } return(newEffectType); }