applied copyright 2008
[jalview.git] / src / jalview / datamodel / AlignedCodonFrame.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)\r
3  * Copyright (C) 2008 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.datamodel;\r
20 \r
21 import java.util.Enumeration;\r
22 import java.util.Vector;\r
23 \r
24 import jalview.util.MapList;\r
25 \r
26 /**\r
27  * Stores mapping between the columns of a protein alignment and a DNA alignment\r
28  * and a list of individual codon to amino acid mappings between sequences.\r
29  */\r
30 \r
31 public class AlignedCodonFrame\r
32 {\r
33   /**\r
34    * array of nucleotide positions for aligned codons at column of aligned proteins.\r
35    */\r
36   public int[][] codons = null;\r
37   /**\r
38    * width of protein sequence alignement\r
39    * implicit assertion that codons.length >= aaWidth\r
40    */\r
41   public int aaWidth=0;\r
42   /**\r
43    * initialise codon frame with a nominal alignment width\r
44    * @param aWidth\r
45    */\r
46   public AlignedCodonFrame(int aWidth)\r
47   {\r
48     if (aWidth<=0)\r
49    {\r
50       codons=null;\r
51       return;\r
52    }\r
53     codons = new int[aWidth][];\r
54     for (int res = 0; res < aWidth; res++)\r
55       codons[res] = null;\r
56   }\r
57 \r
58   /**\r
59    * ensure that codons array is at least as wide as aslen residues\r
60    * @param aslen\r
61    * @return (possibly newly expanded) codon array\r
62    */\r
63   public int[][] checkCodonFrameWidth(int aslen)\r
64   {\r
65     if (codons.length <= aslen + 1)\r
66     {\r
67       // probably never have to do this ?\r
68       int[][] c = new int[codons.length + 10][];\r
69       for (int i = 0; i < codons.length; i++)\r
70       {\r
71         c[i] = codons[i];\r
72         codons[i] = null;\r
73       }\r
74       codons = c;\r
75     }\r
76     return codons;\r
77   }\r
78   /**\r
79    * @return width of aligned translated amino acid residues \r
80    */\r
81   public int getaaWidth()\r
82   {\r
83     return aaWidth;\r
84   }\r
85   /**\r
86    * TODO: not an ideal solution - we reference the aligned amino acid sequences in order to make insertions on them\r
87    * Better would be dnaAlignment and aaAlignment reference....\r
88    */\r
89   Vector a_aaSeqs=new Vector();\r
90   /**\r
91    * increase aaWidth by one and insert a new aligned codon position space at aspos.\r
92    * @param aspos\r
93    */\r
94   public void insertAAGap(int aspos, char gapCharacter)\r
95   {            \r
96     // this aa appears before the aligned codons at aspos - so shift them in each pair of mapped sequences\r
97     aaWidth++;\r
98     if (a_aaSeqs!=null)\r
99     {\r
100       // we actually have to modify the aligned sequences here, so use the a_aaSeqs vector\r
101       Enumeration sq = a_aaSeqs.elements();\r
102       while (sq.hasMoreElements())\r
103       {\r
104         ((SequenceI) sq.nextElement()).insertCharAt(aspos, gapCharacter);\r
105       }\r
106     }\r
107     checkCodonFrameWidth(aspos);\r
108     if (aspos<aaWidth)\r
109     {\r
110       aaWidth++;\r
111       System.arraycopy(codons, aspos, codons, aspos+1, aaWidth-aspos);\r
112       codons[aspos]=null; // clear so new codon position can be marked.\r
113     }\r
114   }\r
115 \r
116   public void setAaWidth(int aapos)\r
117   {\r
118     aaWidth = aapos;\r
119   }\r
120   /**\r
121    * tied array of na Sequence objects.\r
122    */\r
123   SequenceI[] dnaSeqs=null;\r
124   /**\r
125    * tied array of Mappings to protein sequence Objects and \r
126      SequenceI[] aaSeqs=null;\r
127    * MapLists where eac maps from the corresponding dnaSeqs element to corresponding aaSeqs element  \r
128    */\r
129   Mapping[] dnaToProt=null;\r
130   /**\r
131    * add a mapping between the dataset sequences for the associated dna and protein sequence objects\r
132    * @param dnaseq\r
133    * @param aaseq\r
134    * @param map\r
135    */\r
136   public void addMap(SequenceI dnaseq, SequenceI aaseq, MapList map)\r
137   { \r
138     int nlen=1;\r
139     if (dnaSeqs!=null)\r
140     {\r
141       nlen = dnaSeqs.length+1;\r
142     }\r
143     SequenceI[] ndna = new SequenceI[nlen];\r
144     Mapping[] ndtp = new Mapping[nlen];\r
145     if (dnaSeqs!=null)\r
146     {\r
147       System.arraycopy(dnaSeqs,0,ndna, 0, dnaSeqs.length);\r
148       System.arraycopy(dnaToProt,0,ndtp, 0, dnaSeqs.length);\r
149     }\r
150     dnaSeqs = ndna;\r
151     dnaToProt = ndtp;\r
152     nlen--;\r
153     dnaSeqs[nlen] = (dnaseq.getDatasetSequence()==null) ? dnaseq : dnaseq.getDatasetSequence();\r
154     Mapping mp = new Mapping(map);\r
155     // JBPNote DEBUG! THIS !\r
156     //dnaseq.transferAnnotation(aaseq, mp);\r
157     //aaseq.transferAnnotation(dnaseq, new Mapping(map.getInverse()));\r
158     mp.to = (aaseq.getDatasetSequence()==null) ? aaseq : aaseq.getDatasetSequence();\r
159     a_aaSeqs.addElement(aaseq);\r
160     dnaToProt[nlen] = mp;\r
161   }\r
162 \r
163 \r
164   public SequenceI[] getdnaSeqs()\r
165   {\r
166     return dnaSeqs;\r
167   }\r
168   public SequenceI[] getAaSeqs()\r
169   {\r
170     if (dnaToProt==null)\r
171       return null;\r
172     SequenceI[] sqs = new SequenceI[dnaToProt.length];\r
173     for (int sz=0; sz<dnaToProt.length; sz++)\r
174     {\r
175       sqs[sz]  = dnaToProt[sz].to;\r
176     }\r
177     return sqs;\r
178   }\r
179   public MapList[] getdnaToProt()\r
180   {\r
181     if (dnaToProt==null)\r
182       return null;\r
183     MapList[] sqs = new MapList[dnaToProt.length];\r
184     for (int sz=0; sz<dnaToProt.length; sz++)\r
185     {\r
186       sqs[sz]  = dnaToProt[sz].map;\r
187     }\r
188     return sqs;\r
189   }\r
190   public Mapping[] getProtMappings()\r
191   {\r
192     return dnaToProt;\r
193   }\r
194   /**\r
195    * \r
196    * @param sequenceRef\r
197    * @return null or corresponding aaSeq entry for dnaSeq entry\r
198    */\r
199   public SequenceI getAaForDnaSeq(SequenceI dnaSeqRef)\r
200   {\r
201     if (dnaSeqs==null)\r
202     {\r
203       return null;\r
204     }\r
205     SequenceI dnads = dnaSeqRef.getDatasetSequence();\r
206     for (int ds=0;ds<dnaSeqs.length; ds++)\r
207     {\r
208       if (dnaSeqs[ds]==dnaSeqRef || dnaSeqs[ds]==dnads)\r
209         return dnaToProt[ds].to;\r
210     }\r
211     return null;\r
212   }\r
213   /**\r
214    * \r
215    * @param sequenceRef\r
216    * @return null or corresponding aaSeq entry for dnaSeq entry\r
217    */\r
218   public SequenceI getDnaForAaSeq(SequenceI aaSeqRef)\r
219   {\r
220     if (dnaToProt==null)\r
221     {\r
222       return null;\r
223     }\r
224     SequenceI aads = aaSeqRef.getDatasetSequence();\r
225     for (int as=0;as<dnaToProt.length; as++)\r
226     {\r
227       if (dnaToProt[as].to==aaSeqRef || dnaToProt[as].to==aads)\r
228         return dnaSeqs[as];\r
229     }\r
230     return null;\r
231   }\r
232   /**\r
233    * test to see if codon frame involves seq in any way\r
234    * @param seq a nucleotide or protein sequence\r
235    * @return true if a mapping exists to or from this sequence to any translated sequence\r
236    */\r
237   public boolean involvesSequence(SequenceI seq)\r
238   {\r
239     return getAaForDnaSeq(seq)!=null || getDnaForAaSeq(seq)!=null;\r
240   }\r
241   /**\r
242    * Add search results for regions in other sequences that translate or are translated from a particular position in seq \r
243    * @param seq\r
244    * @param index position in seq\r
245    * @param results where highlighted regions go\r
246    */\r
247   public void markMappedRegion(SequenceI seq, int index, SearchResults results)\r
248   {\r
249     if (dnaToProt==null)\r
250     {\r
251       return;\r
252     }\r
253     int[] codon;\r
254     SequenceI ds = seq.getDatasetSequence();\r
255     for (int mi = 0; mi<dnaToProt.length; mi++)\r
256     {\r
257       if (dnaSeqs[mi]==seq || dnaSeqs[mi]==ds)\r
258       {\r
259         // DEBUG System.err.println("dna pos "+index);\r
260         codon = dnaToProt[mi].map.locateInTo(index,index);\r
261         if (codon!=null)\r
262         {\r
263           for (int i=0; i<codon.length; i+=2)\r
264             {\r
265               results.addResult(dnaToProt[mi].to, codon[i], codon[i+1]);\r
266             }\r
267         }\r
268       } else\r
269         if (dnaToProt[mi].to==seq || dnaToProt[mi].to==ds)\r
270         {\r
271           // DEBUG System.err.println("aa pos "+index);\r
272           {\r
273             codon = dnaToProt[mi].map.locateInFrom(index, index);\r
274             if (codon!=null)\r
275             {\r
276             for (int i=0; i<codon.length; i+=2)\r
277               {\r
278                 results.addResult(dnaSeqs[mi], codon[i], codon[i+1]);\r
279               }\r
280           }\r
281         }\r
282         }\r
283     }\r
284   }\r
285 }\r