Features are now an array, not vector
[jalview.git] / src / jalview / datamodel / Sequence.java
1 /*\r
2 * Jalview - A Sequence Alignment Editor and Viewer\r
3 * Copyright (C) 2005 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.awt.*;\r
22 \r
23 import java.util.*;\r
24 \r
25 \r
26 /**\r
27  * DOCUMENT ME!\r
28  *\r
29  * @author $author$\r
30  * @version $Revision$\r
31  */\r
32 public class Sequence implements SequenceI\r
33 {\r
34     SequenceI datasetSequence;\r
35     String name;\r
36     String sequence;\r
37     String description;\r
38     int start;\r
39     int end;\r
40     Color color = Color.white;\r
41     Vector pdbIds;\r
42     String vamsasId;\r
43     Vector dbrefs;\r
44 \r
45     /** This annotation is displayed below the alignment but the\r
46      * positions are tied to the residues of this sequence */\r
47     Vector annotation;\r
48 \r
49     /** DOCUMENT ME!! */\r
50     public SequenceFeature [] sequenceFeatures;\r
51 \r
52     /**\r
53      * Creates a new Sequence object.\r
54      *\r
55      * @param name DOCUMENT ME!\r
56      * @param sequence DOCUMENT ME!\r
57      * @param start DOCUMENT ME!\r
58      * @param end DOCUMENT ME!\r
59      */\r
60     public Sequence(String name, String sequence, int start, int end)\r
61     {\r
62       this.name = name;\r
63       this.sequence = sequence;\r
64       this.start = start;\r
65       this.end = end;\r
66 \r
67       parseId();\r
68 \r
69       checkValidRange();\r
70     }\r
71 \r
72     com.stevesoft.pat.Regex limitrx = new com.stevesoft.pat.Regex(\r
73                         "[/][0-9]{1,}[-][0-9]{1,}$");\r
74     com.stevesoft.pat.Regex endrx = new com.stevesoft.pat.Regex(\r
75                         "[0-9]{1,}$");\r
76 \r
77     void parseId()\r
78     {\r
79         // Does sequence have the /start-end signiature?\r
80          if(limitrx.search(name))\r
81          {\r
82             name = limitrx.left();\r
83             endrx.search(limitrx.stringMatched());\r
84             setStart( Integer.parseInt( limitrx.stringMatched().substring(1,endrx.matchedFrom()-1 )));\r
85             setEnd(   Integer.parseInt( endrx.stringMatched() ));\r
86          }\r
87     }\r
88 \r
89     void checkValidRange()\r
90     {\r
91       if (end < 1)\r
92       {\r
93         int endRes = 0;\r
94         char ch;\r
95         for (int j = 0; j < sequence.length(); j++)\r
96         {\r
97           ch = sequence.charAt(j);\r
98           if (!jalview.util.Comparison.isGap( (ch)))\r
99           {\r
100             endRes++;\r
101           }\r
102         }\r
103         if (endRes > 0)\r
104         {\r
105           endRes += start - 1;\r
106         }\r
107 \r
108         this.end = endRes;\r
109       }\r
110 \r
111     }\r
112 \r
113     /**\r
114      * Creates a new Sequence object.\r
115      *\r
116      * @param name DOCUMENT ME!\r
117      * @param sequence DOCUMENT ME!\r
118      */\r
119     public Sequence(String name, String sequence)\r
120     {\r
121         this(name, sequence, 1, -1);\r
122     }\r
123 \r
124     /**\r
125      * Creates a new Sequence object.\r
126      *\r
127      * @param seq DOCUMENT ME!\r
128      */\r
129     public Sequence(SequenceI seq)\r
130     {\r
131         this(seq.getName(), seq.getSequence(), seq.getStart(), seq.getEnd());\r
132     }\r
133 \r
134     /**\r
135      * DOCUMENT ME!\r
136      *\r
137      * @param v DOCUMENT ME!\r
138      */\r
139     public void setSequenceFeatures(SequenceFeature [] features)\r
140     {\r
141         sequenceFeatures = features;\r
142     }\r
143 \r
144     public void addSequenceFeature(SequenceFeature sf)\r
145     {\r
146       if(sequenceFeatures==null)\r
147       {\r
148         sequenceFeatures = new SequenceFeature[0];\r
149       }\r
150 \r
151       SequenceFeature [] temp = new SequenceFeature[sequenceFeatures.length+1];\r
152       System.arraycopy(sequenceFeatures, 0, temp, 0, sequenceFeatures.length);\r
153       temp[sequenceFeatures.length] = sf;\r
154 \r
155 \r
156       sequenceFeatures = temp;\r
157     }\r
158 \r
159     SequenceFeature [] sfarray;\r
160 \r
161         public SequenceFeature[] getsfarray()\r
162         {\r
163           return sfarray;\r
164         }\r
165 \r
166 \r
167     /**\r
168      * DOCUMENT ME!\r
169      *\r
170      * @return DOCUMENT ME!\r
171      */\r
172     public SequenceFeature [] getSequenceFeatures()\r
173     {\r
174         return sequenceFeatures;\r
175     }\r
176 \r
177     public void addPDBId(PDBEntry entry)\r
178     {\r
179       if(pdbIds == null)\r
180         pdbIds = new Vector();\r
181 \r
182       pdbIds.addElement(entry);\r
183     }\r
184 \r
185     /**\r
186      * DOCUMENT ME!\r
187      *\r
188      * @param id DOCUMENT ME!\r
189      */\r
190     public void setPDBId(Vector id)\r
191     {\r
192         pdbIds = id;\r
193     }\r
194 \r
195     /**\r
196      * DOCUMENT ME!\r
197      *\r
198      * @return DOCUMENT ME!\r
199      */\r
200     public Vector getPDBId()\r
201     {\r
202         return pdbIds;\r
203     }\r
204 \r
205     /**\r
206      * DOCUMENT ME!\r
207      *\r
208      * @return DOCUMENT ME!\r
209      */\r
210     public String getDisplayId(boolean jvsuffix)\r
211     {\r
212       StringBuffer result = new StringBuffer(name);\r
213       if (jvsuffix)\r
214       {\r
215         result.append("/" + start + "-" + end);\r
216       }\r
217 \r
218       return result.toString();\r
219     }\r
220 \r
221     /**\r
222      * DOCUMENT ME!\r
223      *\r
224      * @param name DOCUMENT ME!\r
225      */\r
226     public void setName(String name)\r
227     {\r
228       this.name = name;\r
229       this.parseId();\r
230     }\r
231 \r
232     /**\r
233      * DOCUMENT ME!\r
234      *\r
235      * @return DOCUMENT ME!\r
236      */\r
237     public String getName()\r
238     {\r
239        return this.name;\r
240     }\r
241 \r
242     /**\r
243      * DOCUMENT ME!\r
244      *\r
245      * @param start DOCUMENT ME!\r
246      */\r
247     public void setStart(int start)\r
248     {\r
249         this.start = start;\r
250     }\r
251 \r
252     /**\r
253      * DOCUMENT ME!\r
254      *\r
255      * @return DOCUMENT ME!\r
256      */\r
257     public int getStart()\r
258     {\r
259         return this.start;\r
260     }\r
261 \r
262     /**\r
263      * DOCUMENT ME!\r
264      *\r
265      * @param end DOCUMENT ME!\r
266      */\r
267     public void setEnd(int end)\r
268     {\r
269         this.end = end;\r
270     }\r
271 \r
272     /**\r
273      * DOCUMENT ME!\r
274      *\r
275      * @return DOCUMENT ME!\r
276      */\r
277     public int getEnd()\r
278     {\r
279         return this.end;\r
280     }\r
281 \r
282     /**\r
283      * DOCUMENT ME!\r
284      *\r
285      * @return DOCUMENT ME!\r
286      */\r
287     public int getLength()\r
288     {\r
289         return this.sequence.length();\r
290     }\r
291 \r
292     /**\r
293      * DOCUMENT ME!\r
294      *\r
295      * @param seq DOCUMENT ME!\r
296      */\r
297     public void setSequence(String seq)\r
298     {\r
299         this.sequence = seq;\r
300         checkValidRange();\r
301     }\r
302 \r
303     /**\r
304      * DOCUMENT ME!\r
305      *\r
306      * @return DOCUMENT ME!\r
307      */\r
308     public String getSequence()\r
309     {\r
310         return this.sequence;\r
311     }\r
312 \r
313     /**\r
314      * DOCUMENT ME!\r
315      *\r
316      * @param start DOCUMENT ME!\r
317      * @param end DOCUMENT ME!\r
318      *\r
319      * @return DOCUMENT ME!\r
320      */\r
321     public String getSequence(int start, int end)\r
322     {\r
323         // JBPNote - left to user to pad the result here (TODO:Decide on this policy)\r
324         if (start >= sequence.length())\r
325         {\r
326             return "";\r
327         }\r
328 \r
329         if (end >= sequence.length())\r
330         {\r
331             end = sequence.length();\r
332         }\r
333 \r
334         return this.sequence.substring(start, end);\r
335     }\r
336 \r
337     /**\r
338      * DOCUMENT ME!\r
339      *\r
340      * @param i DOCUMENT ME!\r
341      *\r
342      * @return DOCUMENT ME!\r
343      */\r
344     public char getCharAt(int i)\r
345     {\r
346         if (i < sequence.length())\r
347         {\r
348             return sequence.charAt(i);\r
349         }\r
350         else\r
351         {\r
352             return ' ';\r
353         }\r
354     }\r
355 \r
356     /**\r
357      * DOCUMENT ME!\r
358      *\r
359      * @param desc DOCUMENT ME!\r
360      */\r
361     public void setDescription(String desc)\r
362     {\r
363         this.description = desc;\r
364     }\r
365 \r
366     /**\r
367      * DOCUMENT ME!\r
368      *\r
369      * @return DOCUMENT ME!\r
370      */\r
371     public String getDescription()\r
372     {\r
373         return this.description;\r
374     }\r
375 \r
376     /**\r
377      * DOCUMENT ME!\r
378      *\r
379      * @param pos DOCUMENT ME!\r
380      *\r
381      * @return DOCUMENT ME!\r
382      */\r
383     public int findIndex(int pos)\r
384     {\r
385         // returns the alignment position for a residue\r
386         int j = start;\r
387         int i = 0;\r
388 \r
389         while ((i < sequence.length()) && (j <= end) && (j <= pos))\r
390         {\r
391             if (!jalview.util.Comparison.isGap(sequence.charAt(i)))\r
392             {\r
393                 j++;\r
394             }\r
395 \r
396             i++;\r
397         }\r
398 \r
399         if ((j == end) && (j < pos))\r
400         {\r
401             return end + 1;\r
402         }\r
403         else\r
404         {\r
405             return i;\r
406         }\r
407     }\r
408 \r
409     /**\r
410      * DOCUMENT ME!\r
411      *\r
412      * @param i DOCUMENT ME!\r
413      *\r
414      * @return DOCUMENT ME!\r
415      */\r
416     public int findPosition(int i)\r
417     {\r
418         // Returns the sequence position for an alignment position\r
419         int j = 0;\r
420         int pos = start;\r
421 \r
422         while ((j < i) && (j < sequence.length()))\r
423         {\r
424             if (!jalview.util.Comparison.isGap((sequence.charAt(j))))\r
425             {\r
426                 pos++;\r
427             }\r
428 \r
429             j++;\r
430         }\r
431 \r
432         return pos;\r
433     }\r
434 \r
435     /**\r
436      * DOCUMENT ME!\r
437      *\r
438      * @return DOCUMENT ME!\r
439      */\r
440     public int[] gapMap()\r
441     {\r
442         // Returns an int array giving the position of each residue in the sequence in the alignment\r
443         String seq = jalview.analysis.AlignSeq.extractGaps("-. ", sequence);\r
444         int[] map = new int[seq.length()];\r
445         int j = 0;\r
446         int p = 0;\r
447 \r
448         while (j < sequence.length())\r
449         {\r
450             if (!jalview.util.Comparison.isGap(sequence.charAt(j)))\r
451             {\r
452                 map[p++] = j;\r
453             }\r
454 \r
455             j++;\r
456         }\r
457 \r
458         return map;\r
459     }\r
460 \r
461     /**\r
462      * DOCUMENT ME!\r
463      *\r
464      * @param i DOCUMENT ME!\r
465      */\r
466     public void deleteCharAt(int i)\r
467     {\r
468         if (i >= sequence.length())\r
469         {\r
470             return;\r
471         }\r
472 \r
473         sequence = sequence.substring(0, i) + sequence.substring(i + 1);\r
474     }\r
475 \r
476     /**\r
477      * DOCUMENT ME!\r
478      *\r
479      * @param i DOCUMENT ME!\r
480      * @param j DOCUMENT ME!\r
481      */\r
482     public void deleteChars(int i, int j)\r
483     {\r
484         if (i >= sequence.length())\r
485         {\r
486             return;\r
487         }\r
488 \r
489         if (j >= sequence.length())\r
490         {\r
491             sequence = sequence.substring(0, i);\r
492         }\r
493         else\r
494         {\r
495             sequence = sequence.substring(0, i) + sequence.substring(j);\r
496         }\r
497     }\r
498 \r
499     /**\r
500      * DOCUMENT ME!\r
501      *\r
502      * @param i DOCUMENT ME!\r
503      * @param c DOCUMENT ME!\r
504      */\r
505     public void insertCharAt(int i, char c)\r
506     {\r
507         insertCharAt(i, c, true);\r
508     }\r
509 \r
510     /**\r
511      * DOCUMENT ME!\r
512      *\r
513      * @param i DOCUMENT ME!\r
514      * @param c DOCUMENT ME!\r
515      * @param chop DOCUMENT ME!\r
516      */\r
517     public void insertCharAt(int i, char c, boolean chop)\r
518     {\r
519         String tmp = new String(sequence);\r
520 \r
521         if (i < sequence.length())\r
522         {\r
523             sequence = tmp.substring(0, i) + String.valueOf(c) +\r
524                 tmp.substring(i);\r
525         }\r
526         else\r
527         {\r
528             // JBPNote : padding char at end of sequence. We'll not get away with this when we insert residues, I bet!\r
529             char[] ch = new char[(1 + i) - sequence.length()];\r
530 \r
531             for (int j = 0, k = ch.length; j < k; j++)\r
532                 ch[j] = c;\r
533 \r
534             sequence = tmp + String.valueOf(ch);\r
535         }\r
536     }\r
537 \r
538     /**\r
539      * DOCUMENT ME!\r
540      *\r
541      * @param c DOCUMENT ME!\r
542      */\r
543     public void setColor(Color c)\r
544     {\r
545         this.color = c;\r
546     }\r
547 \r
548     /**\r
549      * DOCUMENT ME!\r
550      *\r
551      * @return DOCUMENT ME!\r
552      */\r
553     public Color getColor()\r
554     {\r
555         return color;\r
556     }\r
557 \r
558     public String getVamsasId()\r
559     {\r
560       return vamsasId;\r
561     }\r
562 \r
563     public void setVamsasId(String id)\r
564     {\r
565       vamsasId = id;\r
566     }\r
567 \r
568     public void setDBRef(Vector dbref)\r
569     {\r
570       dbrefs = dbref;\r
571     }\r
572     public Vector getDBRef()\r
573     {\r
574       return dbrefs;\r
575     }\r
576 \r
577     public void addDBRef(DBRefEntry entry)\r
578     {\r
579       if(dbrefs == null)\r
580         dbrefs = new Vector();\r
581 \r
582       dbrefs.addElement(entry);\r
583     }\r
584 \r
585     public void setDatasetSequence(SequenceI seq)\r
586     {\r
587       datasetSequence = seq;\r
588     }\r
589 \r
590     public SequenceI getDatasetSequence()\r
591     {\r
592       return datasetSequence;\r
593     }\r
594 \r
595     public AlignmentAnnotation [] getAnnotation()\r
596     {\r
597       if(annotation==null)\r
598         return null;\r
599 \r
600       AlignmentAnnotation [] ret = new AlignmentAnnotation[annotation.size()];\r
601       for(int r = 0; r<ret.length; r++)\r
602         ret[r] = (AlignmentAnnotation)annotation.elementAt(r);\r
603 \r
604       return ret;\r
605     }\r
606 \r
607     public void addAlignmentAnnotation(AlignmentAnnotation annotation)\r
608     {\r
609       if(this.annotation==null)\r
610         this.annotation = new Vector();\r
611 \r
612       this.annotation.addElement( annotation );\r
613     }\r
614 \r
615 }\r