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