Annotation/feature exporter
[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     String 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\r
59            || !seqref.equals(row.sequenceRef.getName()))\r
60       {\r
61         seqref = row.sequenceRef.getName();\r
62         text.append("\nSEQUENCE_REF\t" + seqref + "\n");\r
63       }\r
64 \r
65 \r
66       switch( row.graph )\r
67       {\r
68         case AlignmentAnnotation.NO_GRAPH:\r
69           text.append("NO_GRAPH\t");\r
70           break;\r
71         case AlignmentAnnotation.BAR_GRAPH:\r
72           text.append("BAR_GRAPH\t");\r
73         case 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(row.annotations[j]!=null)\r
101         {\r
102           comma = "";\r
103           if (row.annotations[j].displayCharacter.length() > 0\r
104               && !row.annotations[j].displayCharacter.equals(" "))\r
105           {\r
106             text.append(row.annotations[j].displayCharacter);\r
107             comma = ",";\r
108           }\r
109           if (row.annotations[j].secondaryStructure!=' ')\r
110           {\r
111             text.append(comma + row.annotations[j].secondaryStructure);\r
112             comma = ",";\r
113           }\r
114           if (row.annotations[j].value!=0f)\r
115           {\r
116             color = row.annotations[j].colour;\r
117             text.append(comma + row.annotations[j].value);\r
118           }\r
119         }\r
120         text.append("|");\r
121       }\r
122 \r
123       text.append("\n");\r
124 \r
125       if(color!=null && color!=java.awt.Color.black)\r
126       {\r
127         colours.append("COLOUR\t"\r
128                        +row.label+"\t"\r
129                        +jalview.util.Format.getHexString(color)+"\n");\r
130       }\r
131 \r
132     }\r
133 \r
134     text.append("\n");\r
135 \r
136     text.append(colours.toString());\r
137     text.append(graphLine.toString());\r
138     if(graphGroup.size()>0)\r
139     {\r
140       text.append("COMBINE\t");\r
141       Enumeration en = graphGroup.elements();\r
142       while(en.hasMoreElements())\r
143       {\r
144         text.append(en.nextElement()+"\n");\r
145       }\r
146     }\r
147 \r
148     return text.toString();\r
149   }\r
150 \r
151   public boolean readAnnotationFile(AlignmentI al, String file)\r
152   {\r
153     try\r
154     {\r
155       BufferedReader in = null;\r
156       java.io.InputStream is = getClass().getResourceAsStream("/" + file);\r
157       if (is != null)\r
158       {\r
159         in = new BufferedReader(new java.io.InputStreamReader(is));\r
160       }\r
161       else\r
162       {\r
163         try\r
164         {\r
165           URL url = new URL(file);\r
166           in = new BufferedReader(new InputStreamReader(url.openStream()));\r
167         }\r
168         catch (java.net.MalformedURLException ex)\r
169         {\r
170           in = new BufferedReader(new FileReader(file));\r
171         }\r
172       }\r
173 \r
174       String line, label, description, token;\r
175       int graphStyle, index;\r
176       SequenceI refSeq = null;\r
177       int refSeqIndex = 1;\r
178       int existingAnnotations = 0;\r
179       if(al.getAlignmentAnnotation()!=null)\r
180        existingAnnotations = al.getAlignmentAnnotation().length;\r
181 \r
182       int alWidth = al.getWidth();\r
183 \r
184       StringTokenizer st;\r
185       Annotation[] annotations;\r
186       AlignmentAnnotation annotation = null;\r
187 \r
188       // First confirm this is an Annotation file\r
189       boolean jvAnnotationFile = false;\r
190       while ( (line = in.readLine()) != null)\r
191       {\r
192         if (line.indexOf("#") == 0 )\r
193           continue;\r
194 \r
195         if (line.indexOf("JALVIEW_ANNOTATION") > -1)\r
196         {\r
197           jvAnnotationFile = true;\r
198           break;\r
199         }\r
200       }\r
201 \r
202       if(!jvAnnotationFile)\r
203       {\r
204         in.close();\r
205         return false;\r
206       }\r
207 \r
208       while ( (line = in.readLine()) != null)\r
209       {\r
210         if(line.indexOf("#")==0\r
211            || line.indexOf("JALVIEW_ANNOTATION")>-1\r
212            || line.length()==0)\r
213           continue;\r
214 \r
215         st = new StringTokenizer(line, "\t");\r
216         token = st.nextToken();\r
217         if(token.equalsIgnoreCase("COLOUR"))\r
218         {\r
219           colourAnnotations(al, st.nextToken(), st.nextToken());\r
220           continue;\r
221         }\r
222 \r
223         if(token.equalsIgnoreCase("COMBINE") )\r
224         {\r
225           combineAnnotations(al, st);\r
226           continue;\r
227         }\r
228 \r
229         if (token.equalsIgnoreCase("GRAPHLINE"))\r
230         {\r
231           addLine(al, st);\r
232           continue;\r
233         }\r
234 \r
235 \r
236         if(token.equalsIgnoreCase("SEQUENCE_REF") )\r
237         {\r
238           refSeq = al.findName(st.nextToken());\r
239           try{\r
240             refSeqIndex = Integer.parseInt(st.nextToken());\r
241           }\r
242           catch(Exception ex)\r
243           {\r
244             refSeqIndex = 1;\r
245           }\r
246 \r
247           continue;\r
248         }\r
249 \r
250 \r
251         graphStyle = AlignmentAnnotation.getGraphValueFromString(token);\r
252         label = description = st.nextToken();\r
253 \r
254         line = st.nextToken();\r
255 \r
256         st = new StringTokenizer(line, "|", true);\r
257         annotations = new Annotation[alWidth];\r
258 \r
259         index = 0;\r
260         boolean emptyColumn = true;\r
261 \r
262 \r
263         while (st.hasMoreElements() && index<alWidth)\r
264         {\r
265           token = st.nextToken().trim();\r
266           if(token.equals("|"))\r
267           {\r
268             if(emptyColumn)\r
269               index++;\r
270 \r
271             emptyColumn = true;\r
272           }\r
273           else\r
274           {\r
275             annotations[index++] = parseAnnotation(token);\r
276             emptyColumn = false;\r
277           }\r
278         }\r
279 \r
280        annotation = new AlignmentAnnotation(label,\r
281                                           description,\r
282                                           annotations,\r
283                                           0,\r
284                                           0,\r
285                                           graphStyle);\r
286 \r
287        if(refSeq!=null)\r
288        {\r
289          annotation.createSequenceMapping(refSeq, refSeqIndex);\r
290          refSeq.addAlignmentAnnotation(annotation);\r
291        }\r
292 \r
293        al.addAnnotation(annotation);\r
294 \r
295        al.setAnnotationIndex(annotation,  al.getAlignmentAnnotation().length - existingAnnotations-1);\r
296       }\r
297 \r
298     }catch(Exception ex)\r
299     {\r
300       ex.printStackTrace();\r
301       System.out.println("Problem reading annotation file: "+ex);\r
302       return false;\r
303     }\r
304     return true;\r
305   }\r
306 \r
307   Annotation parseAnnotation(String string)\r
308   {\r
309     String desc = "", displayChar="";\r
310     char ss = ' '; // secondaryStructure\r
311     float value = 0;\r
312     boolean parsedValue = false;\r
313     StringTokenizer st = new StringTokenizer(string, ",");\r
314     String token;\r
315     while(st.hasMoreTokens())\r
316     {\r
317       token = st.nextToken().trim();\r
318       if(token.length()==0)\r
319         continue;\r
320 \r
321       if(!parsedValue)\r
322       {\r
323         try{\r
324           value = new Float(token).floatValue();\r
325           displayChar = token;\r
326           parsedValue = true;\r
327         }catch(NumberFormatException ex){}\r
328       }\r
329 \r
330       if(token.equals("H") || token.equals("E"))\r
331       {\r
332         // Either this character represents a helix or sheet\r
333         // or an integer which can be displayed\r
334         ss = token.charAt(0);\r
335       }\r
336       else if(desc.length()<1)\r
337         desc = token;\r
338 \r
339     }\r
340 \r
341     return new Annotation(displayChar, desc, ss, value);\r
342   }\r
343 \r
344   void colourAnnotations(AlignmentI al, String label, String colour)\r
345   {\r
346     UserColourScheme ucs = new UserColourScheme(colour);\r
347     Annotation[] annotations;\r
348     for(int i=0; i<al.getAlignmentAnnotation().length; i++)\r
349     {\r
350       if(al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(label))\r
351       {\r
352         annotations = al.getAlignmentAnnotation()[i].annotations;\r
353         for(int j=0; j<annotations.length; j++)\r
354         {\r
355           if(annotations[j]!=null)\r
356             annotations[j].colour = ucs.findColour("A");\r
357         }\r
358       }\r
359     }\r
360   }\r
361 \r
362   void combineAnnotations(AlignmentI al, StringTokenizer st)\r
363   {\r
364     int graphGroup = -1;\r
365     String group = st.nextToken();\r
366     //First make sure we are not overwriting the graphIndex\r
367     for(int i=0; i<al.getAlignmentAnnotation().length; i++)\r
368     {\r
369       if(al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
370       {\r
371         graphGroup = al.getAlignmentAnnotation()[i].graphGroup +1;\r
372         al.getAlignmentAnnotation()[i].graphGroup = graphGroup;\r
373         break;\r
374       }\r
375     }\r
376 \r
377     //Now update groups\r
378     while(st.hasMoreTokens())\r
379     {\r
380       group = st.nextToken();\r
381       for(int i=0; i<al.getAlignmentAnnotation().length; i++)\r
382       {\r
383         if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
384         {\r
385           al.getAlignmentAnnotation()[i].graphGroup = graphGroup;\r
386           break;\r
387         }\r
388       }\r
389     }\r
390   }\r
391 \r
392   void addLine(AlignmentI al, StringTokenizer st)\r
393   {\r
394     String group = st.nextToken();\r
395     AlignmentAnnotation annotation = null;\r
396 \r
397     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
398     {\r
399       if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
400       {\r
401         annotation = al.getAlignmentAnnotation()[i];\r
402         break;\r
403       }\r
404     }\r
405 \r
406     if(annotation==null)\r
407       return;\r
408     float value = new Float(st.nextToken()).floatValue();\r
409     String label = st.hasMoreTokens() ?  st.nextToken() : null;\r
410     java.awt.Color colour = null;\r
411     if(st.hasMoreTokens())\r
412     {\r
413       UserColourScheme ucs = new UserColourScheme(st.nextToken());\r
414       colour = ucs.findColour("A");\r
415     }\r
416 \r
417     annotation.setThreshold(new GraphLine(value, label, colour));\r
418 \r
419   }\r
420 }\r