apply gpl development license
[jalview.git] / src / jalview / analysis / Dna.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)\r
3  * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  * \r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  * \r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  * \r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.analysis;\r
20 \r
21 import java.util.Enumeration;\r
22 import java.util.Hashtable;\r
23 import java.util.Vector;\r
24 \r
25 import jalview.datamodel.AlignedCodonFrame;\r
26 import jalview.datamodel.Alignment;\r
27 import jalview.datamodel.AlignmentAnnotation;\r
28 import jalview.datamodel.AlignmentI;\r
29 import jalview.datamodel.Annotation;\r
30 import jalview.datamodel.ColumnSelection;\r
31 import jalview.datamodel.DBRefEntry;\r
32 import jalview.datamodel.FeatureProperties;\r
33 import jalview.datamodel.Mapping;\r
34 import jalview.datamodel.Sequence;\r
35 import jalview.datamodel.SequenceFeature;\r
36 import jalview.datamodel.SequenceI;\r
37 import jalview.schemes.ResidueProperties;\r
38 import jalview.util.MapList;\r
39 import jalview.util.ShiftList;\r
40 \r
41 public class Dna\r
42 {\r
43   /**\r
44    * \r
45    * @param cdp1\r
46    * @param cdp2\r
47    * @return -1 if cdp1 aligns before cdp2, 0 if in the same column or cdp2 is\r
48    *         null, +1 if after cdp2\r
49    */\r
50   private static int compare_codonpos(int[] cdp1, int[] cdp2)\r
51   {\r
52     if (cdp2 == null\r
53             || (cdp1[0] == cdp2[0] && cdp1[1] == cdp2[1] && cdp1[2] == cdp2[2]))\r
54       return 0;\r
55     if (cdp1[0] < cdp2[0] || cdp1[1] < cdp2[1] || cdp1[2] < cdp2[2])\r
56       return -1; // one base in cdp1 precedes the corresponding base in the\r
57     // other codon\r
58     return 1; // one base in cdp1 appears after the corresponding base in the\r
59     // other codon.\r
60   }\r
61 \r
62   /**\r
63    * DNA->mapped protein sequence alignment translation given set of sequences\r
64    * 1. id distinct coding regions within selected region for each sequence 2.\r
65    * generate peptides based on inframe (or given) translation or (optionally\r
66    * and where specified) out of frame translations (annotated appropriately) 3.\r
67    * align peptides based on codon alignment\r
68    */\r
69   /**\r
70    * id potential products from dna 1. search for distinct products within\r
71    * selected region for each selected sequence 2. group by associated DB type.\r
72    * 3. return as form for input into above function\r
73    */\r
74   /**\r
75    * \r
76    */\r
77   /**\r
78    * create a new alignment of protein sequences by an inframe translation of\r
79    * the provided NA sequences\r
80    * \r
81    * @param selection\r
82    * @param seqstring\r
83    * @param viscontigs\r
84    * @param gapCharacter\r
85    * @param annotations\r
86    * @param aWidth\r
87    * @param dataset\r
88    *                destination dataset for translated sequences and mappings\r
89    * @return\r
90    */\r
91   public static AlignmentI CdnaTranslate(SequenceI[] selection,\r
92           String[] seqstring, int viscontigs[], char gapCharacter,\r
93           AlignmentAnnotation[] annotations, int aWidth, Alignment dataset)\r
94   {\r
95     return CdnaTranslate(selection, seqstring, null, viscontigs,\r
96             gapCharacter, annotations, aWidth, dataset);\r
97   }\r
98 \r
99   /**\r
100    * \r
101    * @param selection\r
102    * @param seqstring\r
103    * @param product -\r
104    *                array of DbRefEntry objects from which exon map in seqstring\r
105    *                is derived\r
106    * @param viscontigs\r
107    * @param gapCharacter\r
108    * @param annotations\r
109    * @param aWidth\r
110    * @param dataset\r
111    * @return\r
112    */\r
113   public static AlignmentI CdnaTranslate(SequenceI[] selection,\r
114           String[] seqstring, DBRefEntry[] product, int viscontigs[],\r
115           char gapCharacter, AlignmentAnnotation[] annotations, int aWidth,\r
116           Alignment dataset)\r
117   {\r
118     AlignedCodonFrame codons = new AlignedCodonFrame(aWidth); // stores hash of\r
119     // subsequent\r
120     // positions for\r
121     // each codon\r
122     // start position\r
123     // in alignment\r
124     int s, sSize = selection.length;\r
125     Vector pepseqs = new Vector();\r
126     for (s = 0; s < sSize; s++)\r
127     {\r
128       SequenceI newseq = translateCodingRegion(selection[s], seqstring[s],\r
129               viscontigs, codons, gapCharacter,\r
130               (product != null) ? product[s] : null); // possibly anonymous\r
131                                                       // product\r
132       if (newseq != null)\r
133       {\r
134         pepseqs.addElement(newseq);\r
135         SequenceI ds = newseq;\r
136         while (ds.getDatasetSequence() != null)\r
137         {\r
138           ds = ds.getDatasetSequence();\r
139         }\r
140         dataset.addSequence(ds);\r
141       }\r
142     }\r
143     if (codons.aaWidth == 0)\r
144       return null;\r
145     SequenceI[] newseqs = new SequenceI[pepseqs.size()];\r
146     pepseqs.copyInto(newseqs);\r
147     AlignmentI al = new Alignment(newseqs);\r
148     al.padGaps(); // ensure we look aligned.\r
149     al.setDataset(dataset);\r
150     translateAlignedAnnotations(annotations, al, codons);\r
151     al.addCodonFrame(codons);\r
152     return al;\r
153   }\r
154 \r
155   /**\r
156    * fake the collection of DbRefs with associated exon mappings to identify if\r
157    * a translation would generate distinct product in the currently selected\r
158    * region.\r
159    * \r
160    * @param selection\r
161    * @param viscontigs\r
162    * @return\r
163    */\r
164   public static boolean canTranslate(SequenceI[] selection,\r
165           int viscontigs[])\r
166   {\r
167     for (int gd = 0; gd < selection.length; gd++)\r
168     {\r
169       SequenceI dna = selection[gd];\r
170       jalview.datamodel.DBRefEntry[] dnarefs = jalview.util.DBRefUtils\r
171               .selectRefs(dna.getDBRef(),\r
172                       jalview.datamodel.DBRefSource.DNACODINGDBS);\r
173       if (dnarefs != null)\r
174       {\r
175         // intersect with pep\r
176         // intersect with pep\r
177         Vector mappedrefs = new Vector();\r
178         DBRefEntry[] refs = dna.getDBRef();\r
179         for (int d = 0; d < refs.length; d++)\r
180         {\r
181           if (refs[d].getMap() != null && refs[d].getMap().getMap() != null\r
182                   && refs[d].getMap().getMap().getFromRatio() == 3\r
183                   && refs[d].getMap().getMap().getToRatio() == 1)\r
184           {\r
185             mappedrefs.addElement(refs[d]); // add translated protein maps\r
186           }\r
187         }\r
188         dnarefs = new DBRefEntry[mappedrefs.size()];\r
189         mappedrefs.copyInto(dnarefs);\r
190         for (int d = 0; d < dnarefs.length; d++)\r
191         {\r
192           Mapping mp = dnarefs[d].getMap();\r
193           if (mp != null)\r
194           {\r
195             for (int vc = 0; vc < viscontigs.length; vc += 2)\r
196             {\r
197               int[] mpr = mp.locateMappedRange(viscontigs[vc],\r
198                       viscontigs[vc + 1]);\r
199               if (mpr != null)\r
200               {\r
201                 return true;\r
202               }\r
203             }\r
204           }\r
205         }\r
206       }\r
207     }\r
208     return false;\r
209   }\r
210 \r
211   /**\r
212    * generate a set of translated protein products from annotated sequenceI\r
213    * \r
214    * @param selection\r
215    * @param viscontigs\r
216    * @param gapCharacter\r
217    * @param dataset\r
218    *                destination dataset for translated sequences\r
219    * @param annotations\r
220    * @param aWidth\r
221    * @return\r
222    */\r
223   public static AlignmentI CdnaTranslate(SequenceI[] selection,\r
224           int viscontigs[], char gapCharacter, Alignment dataset)\r
225   {\r
226     int alwidth = 0;\r
227     Vector cdnasqs = new Vector();\r
228     Vector cdnasqi = new Vector();\r
229     Vector cdnaprod = new Vector();\r
230     for (int gd = 0; gd < selection.length; gd++)\r
231     {\r
232       SequenceI dna = selection[gd];\r
233       jalview.datamodel.DBRefEntry[] dnarefs = jalview.util.DBRefUtils\r
234               .selectRefs(dna.getDBRef(),\r
235                       jalview.datamodel.DBRefSource.DNACODINGDBS);\r
236       if (dnarefs != null)\r
237       {\r
238         // intersect with pep\r
239         Vector mappedrefs = new Vector();\r
240         DBRefEntry[] refs = dna.getDBRef();\r
241         for (int d = 0; d < refs.length; d++)\r
242         {\r
243           if (refs[d].getMap() != null && refs[d].getMap().getMap() != null\r
244                   && refs[d].getMap().getMap().getFromRatio() == 3\r
245                   && refs[d].getMap().getMap().getToRatio() == 1)\r
246           {\r
247             mappedrefs.addElement(refs[d]); // add translated protein maps\r
248           }\r
249         }\r
250         dnarefs = new DBRefEntry[mappedrefs.size()];\r
251         mappedrefs.copyInto(dnarefs);\r
252         for (int d = 0; d < dnarefs.length; d++)\r
253         {\r
254           Mapping mp = dnarefs[d].getMap();\r
255           StringBuffer sqstr = new StringBuffer();\r
256           if (mp != null)\r
257           {\r
258             Mapping intersect = mp.intersectVisContigs(viscontigs);\r
259             // generate seqstring for this sequence based on mapping\r
260 \r
261             if (sqstr.length() > alwidth)\r
262               alwidth = sqstr.length();\r
263             cdnasqs.addElement(sqstr.toString());\r
264             cdnasqi.addElement(dna);\r
265             cdnaprod.addElement(intersect);\r
266           }\r
267         }\r
268       }\r
269       SequenceI[] cdna = new SequenceI[cdnasqs.size()];\r
270       DBRefEntry[] prods = new DBRefEntry[cdnaprod.size()];\r
271       String[] xons = new String[cdnasqs.size()];\r
272       cdnasqs.copyInto(xons);\r
273       cdnaprod.copyInto(prods);\r
274       cdnasqi.copyInto(cdna);\r
275       return CdnaTranslate(cdna, xons, prods, viscontigs, gapCharacter,\r
276               null, alwidth, dataset);\r
277     }\r
278     return null;\r
279   }\r
280 \r
281   /**\r
282    * translate na alignment annotations onto translated amino acid alignment al\r
283    * using codon mapping codons\r
284    * \r
285    * @param annotations\r
286    * @param al\r
287    * @param codons\r
288    */\r
289   public static void translateAlignedAnnotations(\r
290           AlignmentAnnotation[] annotations, AlignmentI al,\r
291           AlignedCodonFrame codons)\r
292   {\r
293     // //////////////////////////////\r
294     // Copy annotations across\r
295     //\r
296     // Can only do this for columns with consecutive codons, or where\r
297     // annotation is sequence associated.\r
298 \r
299     int pos, a, aSize;\r
300     if (annotations != null)\r
301     {\r
302       for (int i = 0; i < annotations.length; i++)\r
303       {\r
304         // Skip any autogenerated annotation\r
305         if (annotations[i].autoCalculated)\r
306         {\r
307           continue;\r
308         }\r
309 \r
310         aSize = codons.getaaWidth(); // aa alignment width.\r
311         jalview.datamodel.Annotation[] anots = (annotations[i].annotations == null) ? null\r
312                 : new jalview.datamodel.Annotation[aSize];\r
313         if (anots != null)\r
314         {\r
315           for (a = 0; a < aSize; a++)\r
316           {\r
317             // process through codon map.\r
318             if (codons.codons[a] != null\r
319                     && codons.codons[a][0] == (codons.codons[a][2] - 2))\r
320             {\r
321               anots[a] = getCodonAnnotation(codons.codons[a],\r
322                       annotations[i].annotations);\r
323             }\r
324           }\r
325         }\r
326 \r
327         jalview.datamodel.AlignmentAnnotation aa = new jalview.datamodel.AlignmentAnnotation(\r
328                 annotations[i].label, annotations[i].description, anots);\r
329         aa.graph = annotations[i].graph;\r
330         aa.graphGroup = annotations[i].graphGroup;\r
331         aa.graphHeight = annotations[i].graphHeight;\r
332         if (annotations[i].getThreshold() != null)\r
333         {\r
334           aa.setThreshold(new jalview.datamodel.GraphLine(annotations[i]\r
335                   .getThreshold()));\r
336         }\r
337         if (annotations[i].hasScore)\r
338         {\r
339           aa.setScore(annotations[i].getScore());\r
340         }\r
341         if (annotations[i].sequenceRef != null)\r
342         {\r
343           SequenceI aaSeq = codons\r
344                   .getAaForDnaSeq(annotations[i].sequenceRef);\r
345           if (aaSeq != null)\r
346           {\r
347             // aa.compactAnnotationArray(); // throw away alignment annotation\r
348             // positioning\r
349             aa.setSequenceRef(aaSeq);\r
350             aa.createSequenceMapping(aaSeq, aaSeq.getStart(), true); // rebuild\r
351             // mapping\r
352             aa.adjustForAlignment();\r
353             aaSeq.addAlignmentAnnotation(aa);\r
354           }\r
355 \r
356         }\r
357         al.addAnnotation(aa);\r
358       }\r
359     }\r
360   }\r
361 \r
362   private static Annotation getCodonAnnotation(int[] is,\r
363           Annotation[] annotations)\r
364   {\r
365     // Have a look at all the codon positions for annotation and put the first\r
366     // one found into the translated annotation pos.\r
367     for (int p = 0; p < 3; p++)\r
368     {\r
369       if (annotations[is[p]] != null)\r
370       {\r
371         return new Annotation(annotations[is[p]]);\r
372       }\r
373     }\r
374     return null;\r
375   }\r
376 \r
377   /**\r
378    * Translate a na sequence\r
379    * \r
380    * @param selection\r
381    *                sequence displayed under viscontigs visible columns\r
382    * @param seqstring\r
383    *                ORF read in some global alignment reference frame\r
384    * @param viscontigs\r
385    *                mapping from global reference frame to visible seqstring ORF\r
386    *                read\r
387    * @param codons\r
388    *                Definition of global ORF alignment reference frame\r
389    * @param gapCharacter\r
390    * @param newSeq\r
391    * @return sequence ready to be added to alignment.\r
392    */\r
393   public static SequenceI translateCodingRegion(SequenceI selection,\r
394           String seqstring, int[] viscontigs, AlignedCodonFrame codons,\r
395           char gapCharacter, DBRefEntry product)\r
396   {\r
397     Vector skip = new Vector();\r
398     int skipint[] = null;\r
399     ShiftList vismapping = new ShiftList(); // map from viscontigs to seqstring\r
400     // intervals\r
401     int vc, scontigs[] = new int[viscontigs.length];\r
402     int npos = 0;\r
403     for (vc = 0; vc < viscontigs.length; vc += 2)\r
404     {\r
405       if (vc == 0)\r
406       {\r
407         vismapping.addShift(npos, viscontigs[vc]);\r
408       }\r
409       else\r
410       {\r
411         // hidden region\r
412         vismapping.addShift(npos, viscontigs[vc] - viscontigs[vc - 1] + 1);\r
413       }\r
414       scontigs[vc] = viscontigs[vc];\r
415       scontigs[vc + 1] = viscontigs[vc + 1];\r
416     }\r
417 \r
418     StringBuffer protein = new StringBuffer();\r
419     String seq = seqstring.replace('U', 'T');\r
420     char codon[] = new char[3];\r
421     int cdp[] = new int[3], rf = 0, lastnpos = 0, nend;\r
422     int aspos = 0;\r
423     int resSize = 0;\r
424     for (npos = 0, nend = seq.length(); npos < nend; npos++)\r
425     {\r
426       if (!jalview.util.Comparison.isGap(seq.charAt(npos)))\r
427       {\r
428         cdp[rf] = npos; // store position\r
429         codon[rf++] = seq.charAt(npos); // store base\r
430       }\r
431       // filled an RF yet ?\r
432       if (rf == 3)\r
433       {\r
434         String aa = ResidueProperties.codonTranslate(new String(codon));\r
435         rf = 0;\r
436         if (aa == null)\r
437         {\r
438           aa = String.valueOf(gapCharacter);\r
439           if (skipint == null)\r
440           {\r
441             skipint = new int[]\r
442             { cdp[0], cdp[2] };\r
443           }\r
444           skipint[1] = cdp[2];\r
445         }\r
446         else\r
447         {\r
448           if (skipint != null)\r
449           {\r
450             // edit scontigs\r
451             skipint[0] = vismapping.shift(skipint[0]);\r
452             skipint[1] = vismapping.shift(skipint[1]);\r
453             for (vc = 0; vc < scontigs.length; vc += 2)\r
454             {\r
455               if (scontigs[vc + 1] < skipint[0])\r
456               {\r
457                 continue;\r
458               }\r
459               if (scontigs[vc] <= skipint[0])\r
460               {\r
461                 if (skipint[0] == scontigs[vc])\r
462                 {\r
463 \r
464                 }\r
465                 else\r
466                 {\r
467                   int[] t = new int[scontigs.length + 2];\r
468                   System.arraycopy(scontigs, 0, t, 0, vc - 1);\r
469                   // scontigs[vc]; //\r
470                 }\r
471               }\r
472             }\r
473             skip.addElement(skipint);\r
474             skipint = null;\r
475           }\r
476           if (aa.equals("STOP"))\r
477           {\r
478             aa = "X";\r
479           }\r
480           resSize++;\r
481         }\r
482         // insert/delete gaps prior to this codon - if necessary\r
483         boolean findpos = true;\r
484         while (findpos)\r
485         {\r
486           // first ensure that the codons array is long enough.\r
487           codons.checkCodonFrameWidth(aspos);\r
488           // now check to see if we place the aa at the current aspos in the\r
489           // protein alignment\r
490           switch (Dna.compare_codonpos(cdp, codons.codons[aspos]))\r
491           {\r
492           case -1:\r
493             codons.insertAAGap(aspos, gapCharacter);\r
494             findpos = false;\r
495             break;\r
496           case +1:\r
497             // this aa appears after the aligned codons at aspos, so prefix it\r
498             // with a gap\r
499             aa = "" + gapCharacter + aa;\r
500             aspos++;\r
501             // if (aspos >= codons.aaWidth)\r
502             // codons.aaWidth = aspos + 1;\r
503             break; // check the next position for alignment\r
504           case 0:\r
505             // codon aligns at aspos position.\r
506             findpos = false;\r
507           }\r
508         }\r
509         // codon aligns with all other sequence residues found at aspos\r
510         protein.append(aa);\r
511         lastnpos = npos;\r
512         if (codons.codons[aspos] == null)\r
513         {\r
514           // mark this column as aligning to this aligned reading frame\r
515           codons.codons[aspos] = new int[]\r
516           { cdp[0], cdp[1], cdp[2] };\r
517         }\r
518         if (aspos >= codons.aaWidth)\r
519         {\r
520           // update maximum alignment width \r
521           // (we can do this without calling checkCodonFrameWidth because it was already done above)\r
522           codons.setAaWidth(aspos);\r
523         }\r
524         // ready for next translated reading frame alignment position (if any)\r
525         aspos++;\r
526       }\r
527     }\r
528     if (resSize > 0)\r
529     {\r
530       SequenceI newseq = new Sequence(selection.getName(), protein\r
531               .toString());\r
532       if (rf != 0)\r
533       {\r
534         jalview.bin.Cache.log\r
535                 .debug("trimming contigs for incomplete terminal codon.");\r
536         // map and trim contigs to ORF region\r
537         vc = scontigs.length - 1;\r
538         lastnpos = vismapping.shift(lastnpos); // place npos in context of\r
539         // whole dna alignment (rather\r
540         // than visible contigs)\r
541         // incomplete ORF could be broken over one or two visible contig\r
542         // intervals.\r
543         while (vc >= 0 && scontigs[vc] > lastnpos)\r
544         {\r
545           if (vc > 0 && scontigs[vc - 1] > lastnpos)\r
546           {\r
547             vc -= 2;\r
548           }\r
549           else\r
550           {\r
551             // correct last interval in list.\r
552             scontigs[vc] = lastnpos;\r
553           }\r
554         }\r
555 \r
556         if (vc > 0 && (vc + 1) < scontigs.length)\r
557         {\r
558           // truncate map list to just vc elements\r
559           int t[] = new int[vc + 1];\r
560           System.arraycopy(scontigs, 0, t, 0, vc + 1);\r
561           scontigs = t;\r
562         }\r
563         if (vc <= 0)\r
564           scontigs = null;\r
565       }\r
566       if (scontigs != null)\r
567       {\r
568         npos = 0;\r
569         // map scontigs to actual sequence positions on selection\r
570         for (vc = 0; vc < scontigs.length; vc += 2)\r
571         {\r
572           scontigs[vc] = selection.findPosition(scontigs[vc]); // not from 1!\r
573           scontigs[vc + 1] = selection.findPosition(scontigs[vc + 1]); // exclusive\r
574           if (scontigs[vc + 1] == selection.getEnd())\r
575             break;\r
576         }\r
577         // trim trailing empty intervals.\r
578         if ((vc + 2) < scontigs.length)\r
579         {\r
580           int t[] = new int[vc + 2];\r
581           System.arraycopy(scontigs, 0, t, 0, vc + 2);\r
582           scontigs = t;\r
583         }\r
584         /*\r
585          * delete intervals in scontigs which are not translated. 1. map skip\r
586          * into sequence position intervals 2. truncate existing ranges and add\r
587          * new ranges to exclude untranslated regions. if (skip.size()>0) {\r
588          * Vector narange = new Vector(); for (vc=0; vc<scontigs.length; vc++) {\r
589          * narange.addElement(new int[] {scontigs[vc]}); } int sint=0,iv[]; vc =\r
590          * 0; while (sint<skip.size()) { skipint = (int[])\r
591          * skip.elementAt(sint); do { iv = (int[]) narange.elementAt(vc); if\r
592          * (iv[0]>=skipint[0] && iv[0]<=skipint[1]) { if (iv[0]==skipint[0]) { //\r
593          * delete beginning of range } else { // truncate range and create new\r
594          * one if necessary iv = (int[]) narange.elementAt(vc+1); if (iv[0]<=skipint[1]) { //\r
595          * truncate range iv[0] = skipint[1]; } else {\r
596          *  } } } else if (iv[0]<skipint[0]) { iv = (int[])\r
597          * narange.elementAt(vc+1); } } while (iv[0]) } }\r
598          */\r
599         MapList map = new MapList(scontigs, new int[]\r
600         { 1, resSize }, 3, 1);\r
601 \r
602         // update newseq as if it was generated as mapping from product\r
603 \r
604         if (product != null)\r
605         {\r
606           newseq.setName(product.getSource() + "|"\r
607                   + product.getAccessionId());\r
608           if (product.getMap() != null)\r
609           {\r
610             // Mapping mp = product.getMap();\r
611             // newseq.setStart(mp.getPosition(scontigs[0]));\r
612             // newseq.setEnd(mp\r
613             // .getPosition(scontigs[scontigs.length - 1]));\r
614           }\r
615         }\r
616         transferCodedFeatures(selection, newseq, map, null, null);\r
617         SequenceI rseq = newseq.deriveSequence(); // construct a dataset\r
618         // sequence for our new\r
619         // peptide, regardless.\r
620         // store a mapping (this actually stores a mapping between the dataset\r
621         // sequences for the two sequences\r
622         codons.addMap(selection, rseq, map);\r
623         return rseq;\r
624       }\r
625     }\r
626     // register the mapping somehow\r
627     // \r
628     return null;\r
629   }\r
630 \r
631   /**\r
632    * Given a peptide newly translated from a dna sequence, copy over and set any\r
633    * features on the peptide from the DNA. If featureTypes is null, all features\r
634    * on the dna sequence are searched (rather than just the displayed ones), and\r
635    * similarly for featureGroups.\r
636    * \r
637    * @param dna\r
638    * @param pep\r
639    * @param map\r
640    * @param featureTypes\r
641    *                hash who's keys are the displayed feature type strings\r
642    * @param featureGroups\r
643    *                hash where keys are feature groups and values are Boolean\r
644    *                objects indicating if they are displayed.\r
645    */\r
646   private static void transferCodedFeatures(SequenceI dna, SequenceI pep,\r
647           MapList map, Hashtable featureTypes, Hashtable featureGroups)\r
648   {\r
649     SequenceFeature[] sf = dna.getDatasetSequence().getSequenceFeatures();\r
650     Boolean fgstate;\r
651     jalview.datamodel.DBRefEntry[] dnarefs = jalview.util.DBRefUtils\r
652             .selectRefs(dna.getDBRef(),\r
653                     jalview.datamodel.DBRefSource.DNACODINGDBS);\r
654     if (dnarefs != null)\r
655     {\r
656       // intersect with pep\r
657       for (int d = 0; d < dnarefs.length; d++)\r
658       {\r
659         Mapping mp = dnarefs[d].getMap();\r
660         if (mp != null)\r
661         {\r
662         }\r
663       }\r
664     }\r
665     if (sf != null)\r
666     {\r
667       for (int f = 0; f < sf.length; f++)\r
668       {\r
669         fgstate = (featureGroups == null) ? null : ((Boolean) featureGroups\r
670                 .get(sf[f].featureGroup));\r
671         if ((featureTypes == null || featureTypes.containsKey(sf[f]\r
672                 .getType()))\r
673                 && (fgstate == null || fgstate.booleanValue()))\r
674         {\r
675           if (FeatureProperties.isCodingFeature(null, sf[f].getType()))\r
676           {\r
677             // if (map.intersectsFrom(sf[f].begin, sf[f].end))\r
678             {\r
679 \r
680             }\r
681           }\r
682         }\r
683       }\r
684     }\r
685   }\r
686 }\r