/// <summary> /// Get the last coding exon /// </summary> /// <returns></returns> public Exon GetLastCodingExon() { List <CDS> cds = CdsSortedStrand; if (cds.Count == 0) { return(null); } if (LastCodingExon == null) { // Get transcription start position long cend = IsStrandPlus() ? cds.Last().OneBasedEnd : cds.Last().OneBasedStart; // Pick exon intersecting cdsStart (TSS) foreach (Exon exon in ExonsSortedStrand) { if (exon.Intersects(cend)) { LastCodingExon = exon; } } // Sanity check if (LastCodingExon == null) { throw new ArgumentException("Error: Cannot find first coding exon for transcript:\n" + this); } } return(LastCodingExon); }
/// <summary> /// Analyze insertions in this transcript. Add changeEffect to 'changeEffect' /// </summary> /// <param name="exon"></param> /// <returns></returns> protected override bool ChangeCodon(Exon exon) { string netChange = Variant.NetChange(Transcript.IsStrandMinus()); CodonsReference = CodonsRef(); CodonsAlternate = CodonsAlt(); EffectType effType; if (netChange.Length % CODON_SIZE != 0) { /** * Length not multiple of CODON_SIZE => FRAME_SHIFT * E.g. : * Original: AAA CCC GGG AAA CCC GGG AAA CCC GGG * Insert 'TT' pos 0: TTA AAC CCG GGA AAC CCG GGA AAC CCG GG * Insert 'TT' pos 1: ATT AAC CCG GGA AAC CCG GGA AAC CCG GG * Insert 'TT' pos 2: AAT TAC CCG GGA AAC CCG GGA AAC CCG GG */ effType = EffectType.FRAME_SHIFT; } else if (CodonStartIndex == 0) { /** * Length multiple of CODON_SIZE and insertion happens at codon boundary => CODON_INSERTION * E.g. : * Original: AAA CCC GGG AAA CCC GGG AAA CCC GGG * Insert 'TTT' pos 0: TTT AAA CCC GGG AAA CCC GGG AAA CCC GGG */ effType = EffectType.CODON_INSERTION; } else { /** * Length multiple of CODON_SIZE and insertion does not happen at codon boundary => CODON_CHANGE_PLUS_CODON_INSERTION * E.g. : * Original: AAA CCC GGG AAA CCC GGG AAA CCC GGG * Insert 'TTT' pos 1: ATT TAA CCC GGG AAA CCC GGG AAA CCC GGG * Insert 'TTT' pos 2: AAT TTA CCC GGG AAA CCC GGG AAA CCC GGG */ if (CodonsAlternate.ToUpper(CultureInfo.InvariantCulture).StartsWith(CodonsReference.ToUpper(CultureInfo.InvariantCulture))) { /** * May be the inserted base are equal to the old ones. * E.g. * Original: AAA CCC GGG AAA CCC GGG AAA CCC GGG * Insert 'AAA' pos 1: AAA AAA CCC GGG AAA CCC GGG AAA CCC GGG */ effType = EffectType.CODON_INSERTION; } else { effType = EffectType.CODON_CHANGE_PLUS_CODON_INSERTION; } } Effect(exon, effType, false); return(true); }
/// <summary> /// Get the simplest string describing the effect (this is mostly used for testcases) /// </summary> /// <param name="shortFormat"></param> /// <returns></returns> public string ToStringSimple(bool shortFormat) { string transcriptId = ""; Transcript tr = GetTranscript(); if (tr != null) { transcriptId = tr.ID; } string exonId = ""; Exon exon = GetExon(); //if (exon != null) exonId = exon.getId(); string eff = Effect(shortFormat, true, true, false, false); if (eff != "") { return(eff); } if (exonId != "") { return(exonId); } if (transcriptId != "") { return(transcriptId); } return("NO EFFECT"); }
/// <summary> /// Create UTR regions for this transcript /// </summary> public List <UTR> CreateUTRs() { if (CodingDomainSequences.Count == 0) { return(UTRs); } List <Interval> missing = Exons.OfType <Interval>().ToList(); foreach (Interval interval in UTRs.Concat(CodingDomainSequences.OfType <Interval>().ToList())) { missing = missing.SelectMany(i => i.Minus(interval)).ToList(); } long codingMin = CodingDomainSequences.Select(c => c.OneBasedStart).Min(); long codingMax = CodingDomainSequences.Select(c => c.OneBasedEnd).Max(); foreach (Interval interval in missing) { Exon x = FindExon(interval); if (x == null) { throw new ArgumentException("Cannot find exon for UTR: " + interval.ToString()); } UTR toAdd = null; if (IsStrandPlus()) { if (interval.OneBasedEnd <= codingMin) { toAdd = new UTR5Prime(x, x.ChromosomeID, x.Source, x.Strand, interval.OneBasedStart, interval.OneBasedEnd); } else if (interval.OneBasedStart >= codingMax) { toAdd = new UTR3Prime(x, x.ChromosomeID, x.Source, x.Strand, interval.OneBasedStart, interval.OneBasedEnd); } } else { if (interval.OneBasedStart >= codingMax) { toAdd = new UTR5Prime(x, x.ChromosomeID, x.Source, x.Strand, interval.OneBasedStart, interval.OneBasedEnd); } else if (interval.OneBasedEnd <= codingMin) { toAdd = new UTR3Prime(x, x.ChromosomeID, x.Source, x.Strand, interval.OneBasedStart, interval.OneBasedEnd); } } // OK? if (toAdd != null) { UTRs.Add(toAdd); } } return(UTRs); }
/// <summary> /// Find base at genomic coordinate 'pos' /// </summary> /// <param name="pos"></param> /// <returns></returns> public ISequence BaseAt(int pos) { CalcCdsStartEnd(); Exon ex = FindExon(pos); if (ex == null) { return(null); } return(ex.basesAt(pos - ex.OneBasedStart, 1)); }
/// <summary> /// Analyze SNPs in this transcript. Add changeEffect to 'changeEffect' /// </summary> /// <param name="exon"></param> /// <returns></returns> protected override bool ChangeCodon(Exon exon) { // Get old and new codons CodonsReference = CodonsRef(); CodonsAlternate = CodonsAlt(); // Use a generic low priority variant, this allows 'AdditionalEffects' to override it Effect(exon, EffectType.CODON_CHANGE, true); if (CodonsReference == "") { VariantEffects.AddErrorWarning(Variant, ErrorWarningType.ERROR_MISSING_CDS_SEQUENCE); } return(true); }
public string getSequence() { // Create UTR sequence StringBuilder sb = new StringBuilder(); foreach (UTR5Prime utr in get5primeUtrs()) { Exon ex = (Exon)utr.Parent; ISequence utrSeq = ex.Sequence; if (utr.Length() < utrSeq.Count) { utrSeq = utrSeq.GetSubSequence(0, utr.Length()); } // UTR5' may stop before end of exon sb.Append(SequenceExtensions.ConvertToString(utrSeq)); } return(sb.ToString()); }
/// <summary> /// Set marker. Add some warnings if the marker relates to incomplete transcripts /// </summary> /// <param name="marker"></param> public void SetMarker(Interval marker) { Marker = marker; Transcript transcript = GetTranscript(); if (transcript != null) { // Transcript level errors or warnings AddErrorWarningInfo(transcript.sanityCheck(Variant)); // Exon level errors or warnings Exon exon = GetExon(); if (exon != null) { AddErrorWarningInfo(exon.SanityCheck(Variant)); } } }
public List <Intron> CreateIntrons() { Exon previous = null; foreach (Exon x in Exons) { if (previous == null) { previous = x; continue; } Intron intron = new Intron(this, x.ChromosomeID, x.Source, x.Strand, previous.OneBasedEnd + 1, x.OneBasedStart - 1); if (intron.Length() > 0) { Introns.Add(intron); } } return(Introns); }
private static MetadataListItem <List <string> > CDSFeatureMetadata(CDS cds, Exon exon) { string cdsAttributes = exon.GetGtfAttributes() + " protein_id \"" + (cds.Parent as Transcript).ProteinID + "\";"; var feature = new MetadataListItem <List <string> >(cds.FeatureType, cdsAttributes); feature.SubItems["source"] = new List <string> { cds.Source.ToString() }; feature.SubItems["start"] = new List <string> { cds.OneBasedStart.ToString() }; feature.SubItems["end"] = new List <string> { cds.OneBasedEnd.ToString() }; if (cds.Strand != ".") { feature.SubItems["strand"] = new List <string> { cds.Strand.ToString() }; } // might take in features without strand later on return(feature); }
/// <summary> /// Corrrects coordinates of end of coding sequence based on coding sequence length /// </summary> /// <param name="codingSequenceLength"></param> /// <returns></returns> public UTR3Prime EndFrameCorrection(long codingSequenceLength) { long endFrame = codingSequenceLength % 3; if (endFrame <= 0) { return(null); } // nothing to do // First exon is not zero? => Create a UTR5 prime to compensate Exon parent = (FindParent(typeof(Transcript)) as Transcript).GetLastCodingExon(); UTR3Prime utr3 = null; if (IsStrandPlus()) { long start = OneBasedEnd - (endFrame - 1); utr3 = new UTR3Prime(parent, parent.ChromosomeID, parent.Source, parent.Strand, start, OneBasedEnd); } else { long end = OneBasedStart + (endFrame - 1); utr3 = new UTR3Prime(parent, parent.ChromosomeID, parent.Source, parent.Strand, OneBasedStart, end); } // correct start or end coordinates if (IsStrandPlus()) { OneBasedEnd -= endFrame; } else { OneBasedStart += endFrame; } return(utr3); }
public List <MetadataListItem <List <string> > > GetFeatures() { var features = new List <MetadataListItem <List <string> > >(); var geneMetadata = GetGtfFeatureMetadata(); features.Add(geneMetadata); List <Interval> exonsAndCds = Exons.OfType <Interval>().Concat(CodingDomainSequences).OrderBy(t => t.OneBasedStart).ToList(); // exons before cds; exons should come up first after stable sorting Exon currentExon = null; foreach (Interval xc in exonsAndCds) { Exon x = xc as Exon; if (x != null) { currentExon = x; features.Add(x.GetGtfFeatureMetadata()); } else { features.Add(CDSFeatureMetadata(xc as CDS, currentExon)); } } return(features); }
/// <summary> /// Corrrects coordinates of end of coding sequence based on coding sequence length /// </summary> /// <param name="codingSequenceLength"></param> /// <returns></returns> public UTR5Prime StartFrameCorrection() { if (StartFrame <= 0) { return(null); } // nothing to do // First exon is not zero? => Create a UTR5 prime to compensate Exon parent = (FindParent(typeof(Transcript)) as Transcript).GetLastCodingExon(); UTR5Prime utr5 = null; if (IsStrandPlus()) { long end = OneBasedStart + (StartFrame - 1); utr5 = new UTR5Prime(parent, parent.Source, parent.ChromosomeID, parent.Strand, OneBasedStart, end, null); } else { long start = OneBasedEnd - (StartFrame - 1); utr5 = new UTR5Prime(parent, parent.Source, parent.ChromosomeID, parent.Strand, start, OneBasedEnd, null); } // correct start or end coordinates if (IsStrandPlus()) { OneBasedStart += StartFrame; } else { OneBasedEnd -= StartFrame; } StartFrame = 0; return(utr5); }
protected UTR(Exon parent, string chromID, string source, string strand, long oneBasedStart, long oneBasedEnd) : base(parent, chromID, source, strand, oneBasedStart, oneBasedEnd) { }
protected UTR(Exon parent, string chromID, string source, string strand, long oneBasedStart, long oneBasedEnd, HashSet <Variant> variants) : base(parent, chromID, source, strand, oneBasedStart, oneBasedEnd, variants) { }
/// <summary> /// Processes a feature from a GFF3 gene model file. /// </summary> /// <param name="feature"></param> /// <param name="oneBasedStart"></param> /// <param name="oneBasedEnd"></param> /// <param name="chrom"></param> /// <param name="attributes"></param> public void ProcessGff3Feature(MetadataListItem <List <string> > feature, long oneBasedStart, long oneBasedEnd, Chromosome chrom, Dictionary <string, string> attributes) { bool hasGeneId = attributes.TryGetValue("gene_id", out string geneId); bool hasTranscriptId = attributes.TryGetValue("transcript_id", out string transcriptId); bool hasExonId = attributes.TryGetValue("exon_id", out string exonId); bool hasProteinId = attributes.TryGetValue("protein_id", out string proteinId); bool hasSource = feature.SubItems.TryGetValue("source", out List <string> sourceish); // false if empty ("." in GFF format) bool hasStrand = feature.SubItems.TryGetValue("strand", out List <string> strandish); // false if empty ("." in GFF format) bool hasFrame = feature.SubItems.TryGetValue("frame", out List <string> framey); // false if empty ("." in GFF format) string source = hasSource ? sourceish[0] : ""; if (!hasStrand) { return; } // strand is a required to do anything in this program string strand = strandish[0]; int frame = 0; if (hasFrame) { int.TryParse(framey[0], out frame); } if (hasGeneId && (currentGene == null || hasGeneId && geneId != currentGene.ID)) { currentGene = new Gene(geneId, chrom, source, strand, oneBasedStart, oneBasedEnd, feature); Genes.Add(currentGene); GenomeForest.Add(currentGene); } if (hasTranscriptId && (currentTranscript == null || hasTranscriptId && transcriptId != currentTranscript.ID)) { if (currentTranscript != null) { Transcript.SetRegions(currentTranscript); currentTranscript.FrameCorrection(); } currentTranscript = new Transcript(transcriptId, currentGene, source, strand, oneBasedStart, oneBasedEnd, null, null, feature); currentGene.Transcripts.Add(currentTranscript); GenomeForest.Add(currentTranscript); } if (hasExonId) { ISequence exon_dna = chrom.Sequence.GetSubSequence(oneBasedStart - 1, oneBasedEnd - oneBasedStart + 1); Exon exon = new Exon(currentTranscript, currentTranscript.IsStrandPlus() ? exon_dna : exon_dna.GetReverseComplementedSequence(), source, oneBasedStart, oneBasedEnd, chrom == null ? "" : chrom.ChromosomeID, strand, null, feature); if (exon.Length() > 0) { currentTranscript.Exons.Add(exon); } } else if (hasProteinId) { CDS cds = new CDS(currentTranscript, chrom.Sequence.ID, source, strand, oneBasedStart, oneBasedEnd, null, frame); if (cds.Length() > 0) { currentTranscript.CodingDomainSequences.Add(cds); currentTranscript.ProteinID = proteinId; } } else // nothing to do { } }
/// <summary> /// Processes a feature from a GTF gene model file. /// </summary> /// <param name="feature"></param> /// <param name="oneBasedStart"></param> /// <param name="oneBasedEnd"></param> /// <param name="chrom"></param> /// <param name="attributes"></param> public void ProcessGtfFeature(MetadataListItem <List <string> > feature, long oneBasedStart, long oneBasedEnd, Chromosome chrom, Dictionary <string, string> attributes) { bool hasGeneId = attributes.TryGetValue("gene_id", out string geneId); bool hasTranscriptId = attributes.TryGetValue("transcript_id", out string transcriptId); bool hasProteinId = attributes.TryGetValue("protein_id", out string proteinId); bool hasExonId = attributes.TryGetValue("exon_id", out string exonId); bool hasSource = feature.SubItems.TryGetValue("source", out List <string> sourceish); bool hasStrand = feature.SubItems.TryGetValue("strand", out List <string> strandish); bool hasFrame = feature.SubItems.TryGetValue("frame", out List <string> framey); string source = hasSource ? sourceish[0] : ""; if (!hasStrand) { return; } // strand is a required to do anything in this program string strand = strandish[0]; int frame = 0; if (hasFrame) { int.TryParse(framey[0], out frame); } // Trim prefixes from the IDs string genePrefix = "gene:"; string transcriptPrefix = "transcript:"; if (hasGeneId && geneId.StartsWith(genePrefix)) { string newGeneId = geneId.Substring(genePrefix.Length); feature.FreeText.Replace(geneId, newGeneId); geneId = newGeneId; } if (hasTranscriptId && transcriptId.StartsWith(transcriptPrefix)) { string newTranscriptId = transcriptId.Substring(transcriptPrefix.Length); feature.FreeText.Replace(transcriptId, newTranscriptId); transcriptId = newTranscriptId; } if (hasProteinId && proteinId.StartsWith(transcriptPrefix)) { proteinId = proteinId.Substring(transcriptPrefix.Length); // transcript id is used for protein id sometimes } // Catch the transcript features before they go by if available, i.e. if the file doesn't just have exons if (feature.Key == "transcript" && (currentTranscript == null || hasTranscriptId && transcriptId != currentTranscript.ID)) { if (currentGene == null || hasGeneId && geneId != currentGene.ID) { currentGene = new Gene(geneId, chrom, source, strand, oneBasedStart, oneBasedEnd, feature); Genes.Add(currentGene); GenomeForest.Add(currentGene); } currentTranscript = new Transcript(transcriptId, currentGene, source, strand, oneBasedStart, oneBasedEnd, null, null, feature); currentGene.Transcripts.Add(currentTranscript); GenomeForest.Add(currentTranscript); } if (feature.Key == "exon" || feature.Key == "CDS") { if (currentGene == null || hasGeneId && geneId != currentGene.ID) { currentGene = new Gene(geneId, chrom, source, strand, oneBasedStart, oneBasedEnd, feature); Genes.Add(currentGene); GenomeForest.Add(currentGene); } if (currentTranscript == null || hasTranscriptId && transcriptId != currentTranscript.ID) { if (currentTranscript != null) { Transcript.SetRegions(currentTranscript); currentTranscript.FrameCorrection(); } currentTranscript = new Transcript(transcriptId, currentGene, source, strand, oneBasedStart, oneBasedEnd, null, null, feature); currentGene.Transcripts.Add(currentTranscript); GenomeForest.Add(currentTranscript); } if (feature.Key == "exon") { ISequence exon_dna = chrom.Sequence.GetSubSequence(oneBasedStart - 1, oneBasedEnd - oneBasedStart + 1); Exon exon = new Exon(currentTranscript, currentTranscript.IsStrandPlus() ? exon_dna : exon_dna.GetReverseComplementedSequence(), source, oneBasedStart, oneBasedEnd, chrom.Sequence.ID, strand, null, feature); if (exon.Length() > 0) { currentTranscript.Exons.Add(exon); } } else if (feature.Key == "CDS") { CDS cds = new CDS(currentTranscript, chrom.Sequence.ID, source, strand, oneBasedStart, oneBasedEnd, null, frame); if (hasProteinId) { currentTranscript.ProteinID = proteinId; } if (cds.Length() > 0) { currentTranscript.CodingDomainSequences.Add(cds); } } else { // nothing to do } } }
/// <summary> /// Calculate the effect on an exon /// </summary> /// <param name="exon"></param> /// <returns></returns> protected virtual bool ChangeCodon(Exon exon) { throw new InvalidOperationException("Unimplemented method codonChangeSingle() for\n\t\tVariant type : " + Variant.GetType().Name + "\n\t\tClass : " + GetType().Name + "\n\t\tVariant : " + Variant); }
public UTR3Prime(Exon parent, string chromID, string source, string strand, long oneBasedStart, long oneBasedEnd) : base(parent, chromID, source, strand, oneBasedStart, oneBasedEnd) { }
public string ToString(bool useSeqOntology, bool useHgvs) { // Get data to show string geneId = "", geneName = "", transcriptId = "", exonId = "", customId = ""; string bioType = null; int exonRank = -1; if (Marker != null) { // Gene Id, name and biotype Gene gene = GetGene(); Transcript tr = GetTranscript(); // CDS size info if (gene != null) { geneId = gene.ID; //geneName = gene.getGeneName(); //bioType = (getBiotype() == null ? "" : getBiotype().ToString()); } // Update trId if (tr != null) { transcriptId = tr.ID; } // Exon rank information Exon exon = GetExon(); //if (exon != null) //{ // exonId = exon.ID; // exonRank = exon.getRank(); //} // Regulation //if (isRegulation()) bioType = ((Regulation)marker).getRegulationType(); } // Add seqChage's ID //if (!variant.getId() == "") customId += variant.getId(); // Add custom markers //if (marker != null && marker is Custom) customId += (customId == "" ? "" : ";") + marker.getId(); // CDS length long cdsSize = GetCdsLength(); string error = String.Join(",", Error); string warning = String.Join(",", Warning); string errWarn = error + (error == "" ? "" : "|") + warning; //string aaChange = ""; //if (useHgvs) aaChange = getHgvs(); //else aaChange = ((aaRef.Length + aaAlt.Length) > 0 ? aaRef + "/" + aaAlt : ""); string aaChange = ((ReferenceAA.Length + AlternateAA.Length) > 0 ? ReferenceAA + "/" + AlternateAA : ""); return(errWarn // + "\t" + geneId // + "\t" + geneName // + "\t" + bioType // + "\t" + transcriptId // + "\t" + exonId // + "\t" + (exonRank >= 0 ? exonRank.ToString() : "") // + "\t" + Effect(false, false, false, useSeqOntology, false) // + "\t" + aaChange // + "\t" + ((CodonsRef.Length + CodonsAlt.Length) > 0 ? CodonsRef + "/" + CodonsAlt : "") // + "\t" + (CodonNum >= 0 ? (CodonNum + 1).ToString() : "") // //+ "\t" + (codonDegeneracy >= 0 ? codonDegeneracy + "" : "") // + "\t" + (cdsSize >= 0 ? cdsSize.ToString() : "") // + "\t" + (CodonsAroundOld.Length > 0 ? CodonsAroundOld + " / " + CodonsAroundNew : "") // + "\t" + (AroundOldAAs.Length > 0 ? AroundOldAAs + " / " + AroundNewAAs : "") // + "\t" + customId // ); }
/// <summary> /// Find a CDS that matches exactly the exon /// </summary> /// <param name="exon"></param> /// <returns></returns> public CDS FindCds(Exon exon) { return(CodingDomainSequences.FirstOrDefault(c => exon.Includes(c))); }
/// <summary> /// Analyze deletions in this transcript. /// </summary> /// <param name="exon"></param> /// <returns></returns> protected override bool ChangeCodon(Exon exon) { // Is there any net effect? if (NetCodingSequenceChange == "") { return(false); } EffectType effType; if (Variant.Includes(exon)) { /** * An exon has been entirely removed */ CodonsReference = ""; CodonsAlternate = ""; CodonStartNumber = -1; CodonStartIndex = -1; effType = EffectType.EXON_DELETED; } else if (NetCodingSequenceChange.Length % CODON_SIZE != 0) { /** * Length not multiple of CODON_SIZE => FRAME_SHIFT * E.g. : * Original: AAA CCC GGG AAA CCC GGG AAA CCC GGG * Delete 'AA' pos 0: ACC CGG GAA ACC CGG GAA ACC CGG G * Delete 'AA' pos 1: ACC CGG GAA ACC CGG GAA ACC CGG G * Delete 'AC' pos 2: AAC CGG GAA ACC CGG GAA ACC CGG G */ CodonsReference = CodonsRef(); CodonsAlternate = ""; effType = EffectType.FRAME_SHIFT; } else if (CodonStartIndex == 0) { /** * Length multiple of CODON_SIZE and insertion happens at codon boundary => CODON_DELETION * E.g. : * Original: AAA CCC GGG AAA CCC GGG AAA CCC GGG * Delete 'AAA' pos 0: CCC GGG AAA CCC GGG AAA CCC GGG */ CodonsReference = CodonsRef(); CodonsAlternate = ""; effType = EffectType.CODON_DELETION; } else { /** * Length multiple of CODON_SIZE and insertion does not happen at codon boundary => CODON_CHANGE_PLUS_CODON_DELETION * E.g. : * Original: AAA CCC GGG AAA CCC GGG AAA CCC GGG * Delete 'AAC' pos 1: ACC GGG AAA CCC GGG AAA CCC GGG * Delete 'ACC' pos 2: AAC GGG AAA CCC GGG AAA CCC GGG */ CodonsReference = CodonsRef(); CodonsAlternate = CodonsAlt(); if (CodonsAlternate == "" || CodonsReference.StartsWith(CodonsAlternate)) { /** * Note: It might happen that the last codon of the exon was deleted. * In this case there is no 'CODON_CHANGE' * E.g. * Original: AAA CCC GGG AAA CCC GGG AAA CCC GGG * Delete 'GGG' pos 24: ACC CCC GGG AAA CCC GGG AAA CCC * * Note2: It may also be the case that the deleted bases are equal to the following ones. * E.g. * Original: ACG TCG TCC GGG AAA CCC GGG AAA CCC GGG * Delete 'CGT' pos 1: ACG TCC GGG AAA CCC GGG AAA CCC GGG */ effType = EffectType.CODON_DELETION; } else { effType = EffectType.CODON_CHANGE_PLUS_CODON_DELETION; } } Effect(exon, effType, false); return(true); }
public UTR3Prime(Exon parent, string chromID, string source, string strand, long oneBasedStart, long oneBasedEnd, HashSet <Variant> variants) : base(parent, chromID, source, strand, oneBasedStart, oneBasedEnd, variants) { }
/// <summary> /// Copy an exon /// </summary> /// <param name="x"></param> public Exon(Exon x) : this(x.Parent as Transcript, x.Sequence, x.Source, x.OneBasedStart, x.OneBasedEnd, x.ChromosomeID, x.Strand, x.FeatureMetadata) { }