Are the labels all secondary Strutures? are the displayChars actually descriptions?
[jalview.git] / src / jalview / io / AnnotationFile.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 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 \r
20 package jalview.io;\r
21 \r
22 import java.io.*;\r
23 import jalview.datamodel.*;\r
24 import java.util.*;\r
25 import jalview.schemes.UserColourScheme;\r
26 import java.net.URL;\r
27 \r
28 \r
29 public class AnnotationFile\r
30 {\r
31 \r
32   public String printAnnotations(AlignmentAnnotation [] annotations)\r
33   {\r
34     StringBuffer text = new StringBuffer(\r
35       "JALVIEW_ANNOTATION\n"\r
36       +"# Created: "\r
37       +new java.util.Date()+"\n\n");\r
38 \r
39     AlignmentAnnotation row;\r
40     String comma;\r
41     SequenceI seqref = null;\r
42 \r
43     StringBuffer colours = new StringBuffer();\r
44     StringBuffer graphLine = new StringBuffer();\r
45 \r
46     Hashtable graphGroup = new Hashtable();\r
47 \r
48     java.awt.Color color;\r
49 \r
50     for(int i=0; i<annotations.length; i++)\r
51     {\r
52       row = annotations[i];\r
53       color = null;\r
54 \r
55       if( row.sequenceRef == null)\r
56         seqref = null;\r
57 \r
58       else if (seqref == null || seqref != row.sequenceRef)\r
59       {\r
60         seqref = row.sequenceRef;\r
61         text.append("\nSEQUENCE_REF\t" + seqref.getName() + "\n");\r
62       }\r
63 \r
64 \r
65       if( row.graph == AlignmentAnnotation.NO_GRAPH)\r
66       {\r
67           text.append("NO_GRAPH\t");\r
68       }\r
69       else\r
70       {\r
71         if( row.graph == AlignmentAnnotation.BAR_GRAPH)\r
72           text.append("BAR_GRAPH\t");\r
73         else if(row.graph == AlignmentAnnotation.LINE_GRAPH)\r
74           text.append("LINE_GRAPH\t");\r
75 \r
76         if(row.getThreshold()!=null)\r
77             graphLine.append("GRAPHLINE\t"\r
78                              + row.label + "\t"\r
79                              + row.getThreshold().value + "\t"\r
80                              + row.getThreshold().label + "\t"\r
81                              + jalview.util.Format.getHexString(\r
82                                  row.getThreshold().colour)+"\n"\r
83                 );\r
84 \r
85           if(row.graphGroup>-1)\r
86           {\r
87             String key = String.valueOf(row.graphGroup);\r
88             if(graphGroup.containsKey(key))\r
89               graphGroup.put(key, graphGroup.get(key)\r
90                              +"\t"+row.label);\r
91             else\r
92               graphGroup.put(key, row.label);\r
93           }\r
94       }\r
95 \r
96       text.append(row.label+"\t");\r
97 \r
98       for(int j=0; j<row.annotations.length; j++)\r
99       {\r
100         if (seqref != null && jalview.util.Comparison.isGap(seqref.getCharAt(j)))\r
101           continue;\r
102 \r
103         if(row.annotations[j]!=null)\r
104         {\r
105           comma = "";\r
106           if (row.annotations[j].secondaryStructure!=' ')\r
107           {\r
108             text.append(comma + row.annotations[j].secondaryStructure);\r
109             comma = ",";\r
110           }\r
111           if (row.annotations[j].displayCharacter.length() > 0\r
112                   && !row.annotations[j].displayCharacter.equals(" "))\r
113               {\r
114                 text.append(comma + row.annotations[j].displayCharacter);\r
115                 comma = ",";\r
116               }\r
117 \r
118           if (row.annotations[j]!=null)\r
119           {\r
120             color = row.annotations[j].colour;\r
121             if (row.annotations[j].value!=0f)\r
122               text.append(comma + row.annotations[j].value);\r
123           }\r
124         }\r
125         text.append("|");\r
126       }\r
127 \r
128       text.append("\n");\r
129 \r
130       if(color!=null && color!=java.awt.Color.black)\r
131       {\r
132         colours.append("COLOUR\t"\r
133                        +row.label+"\t"\r
134                        +jalview.util.Format.getHexString(color)+"\n");\r
135       }\r
136 \r
137     }\r
138 \r
139     text.append("\n");\r
140 \r
141     text.append(colours.toString());\r
142     text.append(graphLine.toString());\r
143     if(graphGroup.size()>0)\r
144     {\r
145       text.append("COMBINE\t");\r
146       Enumeration en = graphGroup.elements();\r
147       while(en.hasMoreElements())\r
148       {\r
149         text.append(en.nextElement()+"\n");\r
150       }\r
151     }\r
152 \r
153     return text.toString();\r
154   }\r
155 \r
156   public boolean readAnnotationFile(AlignmentI al, String file)\r
157   {\r
158     try\r
159     {\r
160       BufferedReader in = null;\r
161       java.io.InputStream is = getClass().getResourceAsStream("/" + file);\r
162       if (is != null)\r
163       {\r
164         in = new BufferedReader(new java.io.InputStreamReader(is));\r
165       }\r
166       else\r
167       {\r
168         try\r
169         {\r
170           URL url = new URL(file);\r
171           in = new BufferedReader(new InputStreamReader(url.openStream()));\r
172         }\r
173         catch (java.net.MalformedURLException ex)\r
174         {\r
175           in = new BufferedReader(new FileReader(file));\r
176         }\r
177       }\r
178 \r
179       String line, label, description, token;\r
180       int graphStyle, index;\r
181       SequenceI refSeq = null;\r
182       int refSeqIndex = 1;\r
183       int existingAnnotations = 0;\r
184       if(al.getAlignmentAnnotation()!=null)\r
185        existingAnnotations = al.getAlignmentAnnotation().length;\r
186 \r
187       int alWidth = al.getWidth();\r
188 \r
189       StringTokenizer st;\r
190       Annotation[] annotations;\r
191       AlignmentAnnotation annotation = null;\r
192 \r
193       // First confirm this is an Annotation file\r
194       boolean jvAnnotationFile = false;\r
195       while ( (line = in.readLine()) != null)\r
196       {\r
197         if (line.indexOf("#") == 0 )\r
198           continue;\r
199 \r
200         if (line.indexOf("JALVIEW_ANNOTATION") > -1)\r
201         {\r
202           jvAnnotationFile = true;\r
203           break;\r
204         }\r
205       }\r
206 \r
207       if(!jvAnnotationFile)\r
208       {\r
209         in.close();\r
210         return false;\r
211       }\r
212 \r
213       while ( (line = in.readLine()) != null)\r
214       {\r
215         if(line.indexOf("#")==0\r
216            || line.indexOf("JALVIEW_ANNOTATION")>-1\r
217            || line.length()==0)\r
218           continue;\r
219 \r
220         st = new StringTokenizer(line, "\t");\r
221         token = st.nextToken();\r
222         if(token.equalsIgnoreCase("COLOUR"))\r
223         {\r
224           colourAnnotations(al, st.nextToken(), st.nextToken());\r
225           continue;\r
226         }\r
227 \r
228         if(token.equalsIgnoreCase("COMBINE") )\r
229         {\r
230           combineAnnotations(al, st);\r
231           continue;\r
232         }\r
233 \r
234         if (token.equalsIgnoreCase("GRAPHLINE"))\r
235         {\r
236           addLine(al, st);\r
237           continue;\r
238         }\r
239 \r
240 \r
241         if(token.equalsIgnoreCase("SEQUENCE_REF") )\r
242         {\r
243           refSeq = al.findName(st.nextToken());\r
244           try{\r
245             refSeqIndex = Integer.parseInt(st.nextToken());\r
246             if(refSeqIndex<1)\r
247             {\r
248               refSeqIndex = 1;\r
249               System.out.println("WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile");\r
250             }\r
251           }\r
252           catch(Exception ex)\r
253           {\r
254             refSeqIndex = 1;\r
255           }\r
256 \r
257           continue;\r
258         }\r
259 \r
260 \r
261         graphStyle = AlignmentAnnotation.getGraphValueFromString(token);\r
262         label = description = st.nextToken();\r
263 \r
264         line = st.nextToken();\r
265 \r
266         st = new StringTokenizer(line, "|", true);\r
267         annotations = new Annotation[alWidth];\r
268 \r
269         index = 0;\r
270         boolean emptyColumn = true;\r
271 \r
272 \r
273         while (st.hasMoreElements() && index<alWidth)\r
274         {\r
275           token = st.nextToken().trim();\r
276           if(token.equals("|"))\r
277           {\r
278             if(emptyColumn)\r
279               index++;\r
280 \r
281             emptyColumn = true;\r
282           }\r
283           else\r
284           {\r
285             annotations[index++] = parseAnnotation(token);\r
286             emptyColumn = false;\r
287           }\r
288         }\r
289 \r
290        annotation = new AlignmentAnnotation(label,\r
291                                           description,\r
292                                           annotations,\r
293                                           0,\r
294                                           0,\r
295                                           graphStyle);\r
296 \r
297        if(refSeq!=null)\r
298        {\r
299          annotation.createSequenceMapping(refSeq, refSeqIndex, false);\r
300          refSeq.addAlignmentAnnotation(annotation);\r
301        }\r
302 \r
303        al.addAnnotation(annotation);\r
304 \r
305        al.setAnnotationIndex(annotation,  al.getAlignmentAnnotation().length - existingAnnotations-1);\r
306       }\r
307 \r
308     }catch(Exception ex)\r
309     {\r
310       ex.printStackTrace();\r
311       System.out.println("Problem reading annotation file: "+ex);\r
312       return false;\r
313     }\r
314     return true;\r
315   }\r
316 \r
317   Annotation parseAnnotation(String string)\r
318   {\r
319     String desc = null, displayChar="";\r
320     char ss = ' '; // secondaryStructure\r
321     float value = 0;\r
322     boolean parsedValue = false;\r
323     StringTokenizer st = new StringTokenizer(string, ",");\r
324     String token;\r
325     while(st.hasMoreTokens())\r
326     {\r
327       token = st.nextToken().trim();\r
328       if(token.length()==0)\r
329         continue;\r
330 \r
331       if(!parsedValue)\r
332       {\r
333         try{\r
334           displayChar = token;\r
335           value = new Float(token).floatValue();\r
336           parsedValue = true;\r
337           continue;\r
338         }catch(NumberFormatException ex){}\r
339       }\r
340 \r
341       if(token.equals("H") || token.equals("E"))\r
342       {\r
343         // Either this character represents a helix or sheet\r
344         // or an integer which can be displayed\r
345         ss = token.charAt(0);\r
346         if(displayChar.equals(token.substring(0,1)))\r
347           displayChar = "";\r
348       }\r
349       else if(desc==null)\r
350         desc = token;\r
351 \r
352     }\r
353 \r
354     if(desc == null)\r
355       desc = value+"";\r
356 \r
357     if(displayChar.length()>1 && desc.length()==1)\r
358     {\r
359       String tmp = displayChar;\r
360       displayChar = desc;\r
361       desc = tmp;\r
362     }\r
363 \r
364     return new Annotation(displayChar, desc, ss, value);\r
365   }\r
366 \r
367   void colourAnnotations(AlignmentI al, String label, String colour)\r
368   {\r
369     UserColourScheme ucs = new UserColourScheme(colour);\r
370     Annotation[] annotations;\r
371     for(int i=0; i<al.getAlignmentAnnotation().length; i++)\r
372     {\r
373       if(al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(label))\r
374       {\r
375         annotations = al.getAlignmentAnnotation()[i].annotations;\r
376         for(int j=0; j<annotations.length; j++)\r
377         {\r
378           if(annotations[j]!=null)\r
379             annotations[j].colour = ucs.findColour('A');\r
380         }\r
381       }\r
382     }\r
383   }\r
384 \r
385   void combineAnnotations(AlignmentI al, StringTokenizer st)\r
386   {\r
387     int graphGroup = -1;\r
388     String group = st.nextToken();\r
389     //First make sure we are not overwriting the graphIndex\r
390     for(int i=0; i<al.getAlignmentAnnotation().length; i++)\r
391     {\r
392       if(al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
393       {\r
394         graphGroup = al.getAlignmentAnnotation()[i].graphGroup +1;\r
395         al.getAlignmentAnnotation()[i].graphGroup = graphGroup;\r
396         break;\r
397       }\r
398     }\r
399 \r
400     //Now update groups\r
401     while(st.hasMoreTokens())\r
402     {\r
403       group = st.nextToken();\r
404       for(int i=0; i<al.getAlignmentAnnotation().length; i++)\r
405       {\r
406         if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
407         {\r
408           al.getAlignmentAnnotation()[i].graphGroup = graphGroup;\r
409           break;\r
410         }\r
411       }\r
412     }\r
413   }\r
414 \r
415   void addLine(AlignmentI al, StringTokenizer st)\r
416   {\r
417     String group = st.nextToken();\r
418     AlignmentAnnotation annotation = null;\r
419 \r
420     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
421     {\r
422       if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
423       {\r
424         annotation = al.getAlignmentAnnotation()[i];\r
425         break;\r
426       }\r
427     }\r
428 \r
429     if(annotation==null)\r
430       return;\r
431     float value = new Float(st.nextToken()).floatValue();\r
432     String label = st.hasMoreTokens() ?  st.nextToken() : null;\r
433     java.awt.Color colour = null;\r
434     if(st.hasMoreTokens())\r
435     {\r
436       UserColourScheme ucs = new UserColourScheme(st.nextToken());\r
437       colour = ucs.findColour('A');\r
438     }\r
439 \r
440     annotation.setThreshold(new GraphLine(value, label, colour));\r
441 \r
442   }\r
443 }\r