/// <summary> /// Did we gain a start codon in this 5'UTR interval? /// </summary> /// <param name="seqChange"></param> /// <returns>A new start codon (if gained)</returns> private string startGained(Variant seqChange) { if (!seqChange.isSnv()) { return(""); } // Only SNPs supported. // Calculate SNP position relative to UTRs long pos = seqChange.DistanceBases(get5primeUtrs().OfType <Interval>().ToList(), IsStrandMinus()); // Change base at SNP position string sequence = getSequence(); char[] chars = sequence.ToCharArray(); char snpBase = seqChange.NetChange(this)[0]; if (IsStrandMinus() && Alphabets.DNA.TryGetComplementSymbol((byte)snpBase, out byte complement)) { snpBase = (char)complement; } chars[pos] = snpBase; // Do we gain a new start codon? return(startGained(chars, pos)); }
/// <summary> /// Return functional class of this effect (i.e. NONSENSE, MISSENSE, SILENT or NONE) /// </summary> /// <returns></returns> public FunctionalClass GetFunctionalClass() { if (Variant.isSnv()) { if (!AlternateAA.Equals(ReferenceAA)) { Translation.TranslateDnaCodon(CodonsAlt, out byte aa); return(aa == Alphabets.Protein.Ter ? FunctionalClass.NONSENSE : FunctionalClass.MISSENSE); } if (!CodonsAlt.Equals(CodonsRef)) { return(FunctionalClass.SILENT); } } return(FunctionalClass.NONE); }
/// <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); }