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