/// <summary> /// Calculate codons old / codons new /// </summary> protected void codonOldNew() { if (!Transcript.Intersects(Variant)) { return; } // CDS coordinates cdsStart = Transcript.IsStrandPlus() ? Transcript.CdsOneBasedStart : Transcript.CdsOneBasedEnd; cdsEnd = Transcript.IsStrandPlus() ? Transcript.CdsOneBasedEnd : Transcript.CdsOneBasedStart; // Does it intersect CDS? if (cdsStart > Variant.OneBasedEnd) { return; } if (cdsEnd < Variant.OneBasedStart) { return; } // Base number relative to CDS start long scStart, scEnd; if (Transcript.IsStrandPlus()) { scStart = cdsBaseNumber(Variant.OneBasedStart, false); scEnd = cdsBaseNumber(Variant.OneBasedEnd, true); } else { scEnd = cdsBaseNumber(Variant.OneBasedStart, true); scStart = cdsBaseNumber(Variant.OneBasedEnd, false); } // Update coordinates CodonStartNumber = (int)(scStart / CODON_SIZE); CodonStartIndex = (int)(scStart % CODON_SIZE); // MNP overlap in coding part long scLen = scEnd - scStart; if (scLen < 0) { return; } // Round to codon position long scStart3 = round3(scStart, false); long scEnd3 = round3(scEnd, true); long scLen3 = scEnd3 - scStart3; if (scEnd3 == scStart3) { scEnd3 += 3; } // At least one codon // Append 'N' string padN = ""; long diff = scEnd3 - (Transcript.RetrieveCodingSequence().Count - 1); if (diff > 0) { scEnd3 = Transcript.RetrieveCodingSequence().Count - 1; // Pad with 'N' switch (diff) { case 1: padN = "N"; break; case 2: padN = "NN"; break; default: throw new ArgumentOutOfRangeException("Sanity check failed. Number of 'N' pading is :" + diff + ". This should not happen!"); } } // Get old codon (reference) CodonsReference = SequenceExtensions.ConvertToString(Transcript.RetrieveCodingSequence().GetSubSequence(scStart3, scLen3)); // Get new codon (change) string prepend = CodonsReference.Substring(0, (int)(scStart - scStart3)); string append = scEnd3 > scEnd?CodonsReference.Substring(CodonsReference.Length - (int)(scEnd3 - scEnd)) : ""; CodonsAlternate = prepend + NetCdsChange() + append; // Pad codons with 'N' if required CodonsReference += padN; CodonsAlternate += padN; //--- // Can we simplify codons? //--- if ((CodonsReference != null) && (CodonsAlternate != null)) { while ((CodonsReference.Length >= 3) && (CodonsAlternate.Length >= 3)) { // First codon string cold = CodonsReference.Substring(0, 3); string cnew = CodonsAlternate.Substring(0, 3); // Are codons equal? => Simplify if (cold.Equals(cnew, StringComparison.InvariantCultureIgnoreCase)) { CodonsReference = CodonsReference.Substring(3); CodonsAlternate = CodonsAlternate.Substring(3); CodonStartNumber++; } else { break; } } } }
/// <summary> /// Calculate a list of codon changes /// </summary> public virtual void ChangeCodon() { if (!Transcript.Intersects(Variant)) { return; } // Get coding start (after 5 prime UTR) long cdsStart = Transcript.CdsOneBasedStart; // We may have to calculate 'netCdsChange', which is the effect on the CDS NetCodingSequenceChange = NetCdsChange(); if (RequireNetCdsChange && NetCodingSequenceChange == "") { // This can happen on mixed changes where the 'InDel' part lies outside the transcript's exons CodonsReference = ""; CodonsAlternate = ""; return; } //--- // Concatenate all exons //--- int firstCdsBaseInExon = 0; // Where the exon maps to the CDS (i.e. which CDS base number does the first base in this exon maps to). List <Exon> exons = Transcript.ExonsSortedStrand; foreach (Exon exon in exons) { Exon = exon; if (exon.Intersects(Variant)) { long cdsBaseInExon; // cdsBaseInExon: base number relative to the beginning of the coding part of this exon (i.e. excluding 5'UTRs) if (Transcript.IsStrandPlus()) { long firstvariantBaseInExon = Math.Max(Variant.OneBasedStart, Math.Max(exon.OneBasedStart, cdsStart)); cdsBaseInExon = firstvariantBaseInExon - Math.Max(exon.OneBasedStart, cdsStart); } else { long lastvariantBaseInExon = Math.Min(Variant.OneBasedEnd, Math.Min(exon.OneBasedEnd, cdsStart)); cdsBaseInExon = Math.Min(exon.OneBasedEnd, cdsStart) - lastvariantBaseInExon; } if (cdsBaseInExon < 0) { cdsBaseInExon = 0; } // Get codon number and index within codon (where seqChage is pointing) if (CodonStartNumber < 0) { CodonStartNumber = (int)(firstCdsBaseInExon + cdsBaseInExon) / CODON_SIZE; CodonStartIndex = (int)(firstCdsBaseInExon + cdsBaseInExon) % CODON_SIZE; } // Use appropriate method to calculate codon change bool hasChanged = false; // Was there any change? hasChanged = ChangeCodon(exon); // This is overriden for the specific type of codon change // Any change? => Add change to list if (hasChanged && !VariantEffects.HasMarker()) { VariantEffects.SetMarker(exon); // It is affecting this exon, so we set the marker } // Can we finish after effect of first exon is added? if (ReturnNow) { return; } } firstCdsBaseInExon += Transcript.IsStrandPlus() ? (int)Math.Max(0, exon.OneBasedEnd - Math.Max(exon.OneBasedStart, cdsStart) + 1) : (int)Math.Max(0, Math.Min(cdsStart, exon.OneBasedEnd) - exon.OneBasedStart + 1); } }