1 package jalview.analysis;
\r
3 import java.util.Hashtable;
\r
4 import java.util.Vector;
\r
6 import jalview.datamodel.AlignedCodonFrame;
\r
7 import jalview.datamodel.Alignment;
\r
8 import jalview.datamodel.AlignmentAnnotation;
\r
9 import jalview.datamodel.AlignmentI;
\r
10 import jalview.datamodel.Annotation;
\r
11 import jalview.datamodel.ColumnSelection;
\r
12 import jalview.datamodel.FeatureProperties;
\r
13 import jalview.datamodel.Mapping;
\r
14 import jalview.datamodel.Sequence;
\r
15 import jalview.datamodel.SequenceFeature;
\r
16 import jalview.datamodel.SequenceI;
\r
17 import jalview.schemes.ResidueProperties;
\r
18 import jalview.util.MapList;
\r
19 import jalview.util.ShiftList;
\r
27 * @return -1 if cdp1 aligns before cdp2, 0 if in the same column or cdp2 is
\r
28 * null, +1 if after cdp2
\r
30 private static int compare_codonpos(int[] cdp1, int[] cdp2)
\r
33 || (cdp1[0] == cdp2[0] && cdp1[1] == cdp2[1] && cdp1[2] == cdp2[2]))
\r
35 if (cdp1[0] < cdp2[0] || cdp1[1] < cdp2[1] || cdp1[2] < cdp2[2])
\r
36 return -1; // one base in cdp1 precedes the corresponding base in the
\r
38 return 1; // one base in cdp1 appears after the corresponding base in the
\r
43 * DNA->mapped protein sequence alignment translation given set of sequences
\r
44 * 1. id distinct coding regions within selected region for each sequence 2.
\r
45 * generate peptides based on inframe (or given) translation or (optionally
\r
46 * and where specified) out of frame translations (annotated appropriately) 3.
\r
47 * align peptides based on codon alignment
\r
50 * id potential products from dna 1. search for distinct products within
\r
51 * selected region for each selected sequence 2. group by associated DB type.
\r
52 * 3. return as form for input into above function
\r
58 * create a new alignment of protein sequences by an inframe translation of
\r
59 * the provided NA sequences
\r
64 * @param gapCharacter
\r
65 * @param annotations
\r
69 public static AlignmentI CdnaTranslate(SequenceI[] selection,
\r
70 String[] seqstring, int viscontigs[], char gapCharacter,
\r
71 AlignmentAnnotation[] annotations, int aWidth)
\r
73 AlignedCodonFrame codons = new AlignedCodonFrame(aWidth); // stores hash of
\r
79 int s, sSize = selection.length;
\r
80 Vector pepseqs = new Vector();
\r
81 for (s = 0; s < sSize; s++)
\r
83 SequenceI newseq = translateCodingRegion(selection[s], seqstring[s],
\r
84 viscontigs, codons, gapCharacter);
\r
87 pepseqs.addElement(newseq);
\r
90 if (codons.aaWidth == 0)
\r
92 SequenceI[] newseqs = new SequenceI[pepseqs.size()];
\r
93 pepseqs.copyInto(newseqs);
\r
94 AlignmentI al = new Alignment(newseqs);
\r
95 al.padGaps(); // ensure we look aligned.
\r
96 al.setDataset(null);
\r
97 translateAlignedAnnotations(annotations, al, codons);
\r
98 al.addCodonFrame(codons);
\r
103 * translate na alignment annotations onto translated amino acid alignment al
\r
104 * using codon mapping codons
\r
106 * @param annotations
\r
110 public static void translateAlignedAnnotations(
\r
111 AlignmentAnnotation[] annotations, AlignmentI al,
\r
112 AlignedCodonFrame codons)
\r
114 // //////////////////////////////
\r
115 // Copy annotations across
\r
117 // Can only do this for columns with consecutive codons, or where
\r
118 // annotation is sequence associated.
\r
121 if (annotations != null)
\r
123 for (int i = 0; i < annotations.length; i++)
\r
125 // Skip any autogenerated annotation
\r
126 if (annotations[i].autoCalculated)
\r
131 aSize = codons.getaaWidth(); // aa alignment width.
\r
132 jalview.datamodel.Annotation[] anots = (annotations[i].annotations == null) ? null
\r
133 : new jalview.datamodel.Annotation[aSize];
\r
136 for (a = 0; a < aSize; a++)
\r
138 // process through codon map.
\r
139 if (codons.codons[a] != null
\r
140 && codons.codons[a][0] == (codons.codons[a][2] - 2))
\r
142 pos = codons.codons[a][0];
\r
143 if (annotations[i].annotations[pos] == null
\r
144 || annotations[i].annotations[pos] == null)
\r
146 // We just take the annotation in the first base in the codon
\r
147 anots[a] = new Annotation(annotations[i].annotations[pos]);
\r
152 jalview.datamodel.AlignmentAnnotation aa = new jalview.datamodel.AlignmentAnnotation(
\r
153 annotations[i].label, annotations[i].description, anots);
\r
154 if (annotations[i].hasScore)
\r
156 aa.setScore(annotations[i].getScore());
\r
158 if (annotations[i].sequenceRef != null)
\r
160 SequenceI aaSeq = codons
\r
161 .getAaForDnaSeq(annotations[i].sequenceRef);
\r
164 // aa.compactAnnotationArray(); // throw away alignment annotation
\r
166 aa.setSequenceRef(aaSeq);
\r
167 aa.createSequenceMapping(aaSeq, aaSeq.getStart(), true); // rebuild
\r
169 aa.adjustForAlignment();
\r
170 aaSeq.addAlignmentAnnotation(aa);
\r
174 al.addAnnotation(aa);
\r
180 * Translate a na sequence
\r
184 * @param viscontigs
\r
186 * @param gapCharacter
\r
188 * @return sequence ready to be added to alignment.
\r
190 public static SequenceI translateCodingRegion(SequenceI selection,
\r
191 String seqstring, int[] viscontigs, AlignedCodonFrame codons,
\r
194 ShiftList vismapping = new ShiftList(); // map from viscontigs to seqstring
\r
196 int vc, scontigs[] = new int[viscontigs.length];
\r
198 for (vc = 0; vc < viscontigs.length; vc += 2)
\r
200 vismapping.addShift(npos, viscontigs[vc]);
\r
201 scontigs[vc] = npos;
\r
202 npos += viscontigs[vc + 1];
\r
203 scontigs[vc + 1] = npos;
\r
206 StringBuffer protein = new StringBuffer();
\r
207 String seq = seqstring.replace('U', 'T');
\r
208 char codon[] = new char[3];
\r
209 int cdp[] = new int[3], rf = 0, lastnpos = 0, nend;
\r
212 for (npos = 0, nend = seq.length(); npos < nend; npos++)
\r
214 if (!jalview.util.Comparison.isGap(seq.charAt(npos)))
\r
216 cdp[rf] = npos; // store position
\r
217 codon[rf++] = seq.charAt(npos); // store base
\r
219 // filled an RF yet ?
\r
222 String aa = ResidueProperties.codonTranslate(new String(codon));
\r
225 aa = String.valueOf(gapCharacter);
\r
228 if (aa.equals("STOP"))
\r
234 // insert/delete gaps prior to this codon - if necessary
\r
235 boolean findpos = true;
\r
238 // first ensure that the codons array is long enough.
\r
239 codons.checkCodonFrameWidth(aspos);
\r
240 // now check to see if we place the aa at the current aspos in the
\r
241 // protein alignment
\r
242 switch (Dna.compare_codonpos(cdp, codons.codons[aspos]))
\r
245 codons.insertAAGap(aspos, gapCharacter);
\r
249 // this aa appears after the aligned codons at aspos, so prefix it
\r
251 aa = "" + gapCharacter + aa;
\r
253 if (aspos >= codons.aaWidth)
\r
254 codons.aaWidth = aspos + 1;
\r
255 break; // check the next position for alignment
\r
257 // codon aligns at aspos position.
\r
261 // codon aligns with all other sequence residues found at aspos
\r
262 protein.append(aa);
\r
264 if (codons.codons[aspos] == null)
\r
266 // mark this column as aligning to this aligned reading frame
\r
267 codons.codons[aspos] = new int[]
\r
268 { cdp[0], cdp[1], cdp[2] };
\r
271 if (aspos >= codons.aaWidth)
\r
272 codons.aaWidth = aspos + 1;
\r
277 SequenceI newseq = new Sequence(selection.getName(), protein
\r
281 jalview.bin.Cache.log
\r
282 .debug("trimming contigs for incomplete terminal codon.");
\r
283 // map and trim contigs to ORF region
\r
284 vc = scontigs.length - 1;
\r
285 lastnpos = vismapping.shift(lastnpos); // place npos in context of
\r
286 // whole dna alignment (rather
\r
287 // than visible contigs)
\r
288 // incomplete ORF could be broken over one or two visible contig
\r
290 while (vc >= 0 && scontigs[vc] > lastnpos)
\r
292 if (vc > 0 && scontigs[vc - 1] > lastnpos)
\r
298 // correct last interval in list.
\r
299 scontigs[vc] = lastnpos;
\r
303 if (vc > 0 && (vc + 1) < scontigs.length)
\r
305 // truncate map list to just vc elements
\r
306 int t[] = new int[vc + 1];
\r
307 System.arraycopy(scontigs, 0, t, 0, vc + 1);
\r
313 if (scontigs != null)
\r
316 // Find sequence position for scontigs positions on the nucleotide
\r
317 // sequence string we were passed.
\r
318 for (vc = 0; vc < viscontigs.length; vc += 2)
\r
320 scontigs[vc] = selection.findPosition(scontigs[vc]); // not from 1!
\r
321 npos += viscontigs[vc];
\r
322 scontigs[vc + 1] = selection
\r
323 .findPosition(npos + scontigs[vc + 1]); // exclusive
\r
324 if (scontigs[vc + 1] == selection.getEnd())
\r
327 // trim trailing empty intervals.
\r
328 if ((vc + 2) < scontigs.length)
\r
330 int t[] = new int[vc + 2];
\r
331 System.arraycopy(scontigs, 0, t, 0, vc + 2);
\r
335 MapList map = new MapList(scontigs, new int[]
\r
336 { 1, resSize }, 3, 1); // TODO: store mapping on newSeq for linked
\r
337 // DNA/Protein viewing.
\r
338 transferCodedFeatures(selection, newseq, map, null, null);
\r
339 SequenceI rseq = newseq.deriveSequence(); // construct a dataset
\r
340 // sequence for our new
\r
341 // peptide, regardless.
\r
342 // store a mapping (this actually stores a mapping between the dataset
\r
343 // sequences for the two sequences
\r
344 codons.addMap(selection, newseq, map);
\r
348 // register the mapping somehow
\r
354 * Given a peptide newly translated from a dna sequence, copy over and set any
\r
355 * features on the peptide from the DNA. If featureTypes is null, all features
\r
356 * on the dna sequence are searched (rather than just the displayed ones), and
\r
357 * similarly for featureGroups.
\r
362 * @param featureTypes
\r
363 * hash who's keys are the displayed feature type strings
\r
364 * @param featureGroups
\r
365 * hash where keys are feature groups and values are Boolean objects
\r
366 * indicating if they are displayed.
\r
368 private static void transferCodedFeatures(SequenceI dna, SequenceI pep,
\r
369 MapList map, Hashtable featureTypes, Hashtable featureGroups)
\r
371 SequenceFeature[] sf = dna.getDatasetSequence().getSequenceFeatures();
\r
373 jalview.datamodel.DBRefEntry[] dnarefs = jalview.util.DBRefUtils
\r
374 .selectRefs(dna.getDBRef(),
\r
375 jalview.datamodel.DBRefSource.DNACODINGDBS);
\r
376 if (dnarefs != null)
\r
378 // intersect with pep
\r
379 for (int d = 0; d < dnarefs.length; d++)
\r
381 Mapping mp = dnarefs[d].getMap();
\r
389 for (int f = 0; f < sf.length; f++)
\r
391 fgstate = (featureGroups == null) ? null : ((Boolean) featureGroups
\r
392 .get(sf[f].featureGroup));
\r
393 if ((featureTypes == null || featureTypes.containsKey(sf[f]
\r
395 && (fgstate == null || fgstate.booleanValue()))
\r
397 if (FeatureProperties.isCodingFeature(null, sf[f].getType()))
\r
399 // if (map.intersectsFrom(sf[f].begin, sf[f].end))
\r