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