71e86b354208977ef26825e91032fe0e8e055155
[jalview.git] / src / jalview / io / ClustalFile.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.io;\r
20 \r
21 import java.io.*;\r
22 import java.util.*;\r
23 \r
24 import jalview.datamodel.*;\r
25 import jalview.util.*;\r
26 \r
27 public class ClustalFile\r
28     extends AlignFile\r
29 {\r
30   Vector ids;\r
31 \r
32   public ClustalFile()\r
33   {\r
34   }\r
35 \r
36   public ClustalFile(String inStr)\r
37   {\r
38     super(inStr);\r
39   }\r
40 \r
41   public ClustalFile(String inFile, String type)\r
42       throws IOException\r
43   {\r
44     super(inFile, type);\r
45   }\r
46 \r
47   public void initData()\r
48   {\r
49     super.initData();\r
50     ids = new Vector();\r
51   }\r
52 \r
53   public void parse()\r
54   {\r
55     int i = 0;\r
56     boolean flag = false;\r
57 \r
58     Vector headers = new Vector();\r
59     Hashtable seqhash = new Hashtable();\r
60 \r
61     String line;\r
62 \r
63     try\r
64     {\r
65       while ( (line = nextLine()) != null)\r
66       {\r
67         if (line.indexOf(" ") != 0)\r
68         {\r
69           StringTokenizer str = new StringTokenizer(line, " ");\r
70           String id = "";\r
71 \r
72           if (str.hasMoreTokens())\r
73           {\r
74             id = str.nextToken();\r
75 \r
76             if (id.equals("CLUSTAL"))\r
77             {\r
78               flag = true;\r
79             }\r
80             else\r
81             {\r
82               if (flag)\r
83               {\r
84                 StringBuffer tempseq;\r
85 \r
86                 if (seqhash.containsKey(id))\r
87                 {\r
88                   tempseq = (StringBuffer) seqhash.get(id);\r
89                 }\r
90                 else\r
91                 {\r
92                   tempseq = new StringBuffer();\r
93                   seqhash.put(id, tempseq);\r
94                 }\r
95 \r
96                 if (! (headers.contains(id)))\r
97                 {\r
98                   headers.addElement(id);\r
99                 }\r
100 \r
101                 if (str.hasMoreTokens())\r
102                 {\r
103                   tempseq.append(str.nextToken());\r
104                 }\r
105               }\r
106             }\r
107           }\r
108         }\r
109       }\r
110     }\r
111     catch (IOException e)\r
112     {\r
113       System.err.println("Exception parsing clustal file " + e);\r
114       e.printStackTrace();\r
115     }\r
116 \r
117     if (flag)\r
118     {\r
119       this.noSeqs = headers.size();\r
120 \r
121       //Add sequences to the hash\r
122       for (i = 0; i < headers.size(); i++)\r
123       {\r
124         int start = 1;\r
125         int end = -1;\r
126 \r
127         if (seqhash.get(headers.elementAt(i)) != null)\r
128         {\r
129           if (maxLength < seqhash.get(headers.elementAt(i)).toString()\r
130               .length())\r
131           {\r
132             maxLength = seqhash.get(headers.elementAt(i)).toString()\r
133                 .length();\r
134           }\r
135 \r
136           String head = headers.elementAt(i).toString();\r
137 \r
138           if (head.indexOf("/") > 0)\r
139           {\r
140             StringTokenizer st = new StringTokenizer(head, "/");\r
141 \r
142             if (st.countTokens() == 2)\r
143             {\r
144               ids.addElement(st.nextToken());\r
145 \r
146               String tmp = st.nextToken();\r
147               st = new StringTokenizer(tmp, "-");\r
148 \r
149               if (st.countTokens() == 2)\r
150               {\r
151                 start = Integer.valueOf(st.nextToken())\r
152                     .intValue();\r
153                 end = Integer.valueOf(st.nextToken()).intValue();\r
154               }\r
155             }\r
156             else\r
157             {\r
158               ids.addElement(headers.elementAt(i));\r
159             }\r
160           }\r
161           else\r
162           {\r
163             ids.addElement(headers.elementAt(i));\r
164           }\r
165 \r
166           Sequence newSeq = new Sequence(ids.elementAt(i).toString(),\r
167                                          seqhash.get(headers.elementAt(i).\r
168               toString())\r
169                                          .toString(), start, end);\r
170 \r
171           seqs.addElement(newSeq);\r
172         }\r
173         else\r
174         {\r
175           System.err.println(\r
176               "Clustal File Reader: Can't find sequence for " +\r
177               headers.elementAt(i));\r
178         }\r
179       }\r
180     }\r
181   }\r
182 \r
183   public String print()\r
184   {\r
185     return print(getSeqsAsArray());\r
186   }\r
187 \r
188   public static String print(SequenceI[] s)\r
189   {\r
190     StringBuffer out = new StringBuffer("CLUSTAL\n\n");\r
191 \r
192     int max = 0;\r
193     int maxid = 0;\r
194 \r
195     int i = 0;\r
196 \r
197     while ( (i < s.length) && (s[i] != null))\r
198     {\r
199       String tmp = s[i].getName() + "/" + s[i].getStart() + "-" +\r
200           s[i].getEnd();\r
201 \r
202       if (s[i].getSequence().length() > max)\r
203       {\r
204         max = s[i].getSequence().length();\r
205       }\r
206 \r
207       if (tmp.length() > maxid)\r
208       {\r
209         maxid = tmp.length();\r
210       }\r
211 \r
212       i++;\r
213     }\r
214 \r
215     if (maxid < 15)\r
216     {\r
217       maxid = 15;\r
218     }\r
219 \r
220     maxid++;\r
221 \r
222     int len = 60;\r
223     int nochunks = (max / len) + 1;\r
224 \r
225     for (i = 0; i < nochunks; i++)\r
226     {\r
227       int j = 0;\r
228 \r
229       while ( (j < s.length) && (s[j] != null))\r
230       {\r
231         out.append(new Format("%-" + maxid + "s").form(s[j].getName() +\r
232             "/" + s[j].getStart() + "-" + s[j].getEnd()) + " ");\r
233 \r
234         int start = i * len;\r
235         int end = start + len;\r
236 \r
237         if ( (end < s[j].getSequence().length()) &&\r
238             (start < s[j].getSequence().length()))\r
239         {\r
240           out.append(s[j].getSequence().substring(start, end));\r
241         }\r
242         else\r
243         {\r
244           if (start < s[j].getSequence().length())\r
245           {\r
246             out.append(s[j].getSequence().substring(start));\r
247           }\r
248         }\r
249 \r
250         out.append("\n");\r
251         j++;\r
252       }\r
253 \r
254       out.append("\n");\r
255     }\r
256 \r
257     return out.toString();\r
258   }\r
259 }\r