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