always output to stderr for out of memory - (no dependence on OOM dialog here (for...
[jalview.git] / src / jalview / io / AnnotationFile.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)\r
3  * Copyright (C) 2008 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.net.*;\r
23 import java.util.*;\r
24 \r
25 import jalview.analysis.*;\r
26 import jalview.datamodel.*;\r
27 import jalview.schemes.*;\r
28 \r
29 public class AnnotationFile\r
30 {\r
31   StringBuffer text = new StringBuffer(\r
32       "JALVIEW_ANNOTATION\n"\r
33       + "# Created: "\r
34       + new java.util.Date() + "\n\n");\r
35   /**\r
36    * convenience method for pre-2.4 feature files which have no view, hidden columns or hidden row keywords.\r
37    * @param annotations\r
38    * @param groups\r
39    * @param properties\r
40    * @return feature file as a string.\r
41    */\r
42   public String printAnnotations(AlignmentAnnotation[] annotations,\r
43                                  Vector groups,\r
44                                  Hashtable properties)\r
45   {\r
46     return printAnnotations(annotations, groups,\r
47             properties, null);\r
48 \r
49   }\r
50   /**\r
51    * hold all the information about a particular view definition\r
52    * read from or written out in an annotations file.\r
53    */\r
54   public class ViewDef {\r
55     public String viewname;\r
56     public HiddenSequences hidseqs;\r
57     public ColumnSelection hiddencols;\r
58     public Vector visibleGroups;\r
59     public ViewDef(String viewname, HiddenSequences hidseqs,\r
60             ColumnSelection hiddencols)\r
61     {\r
62       this.viewname = viewname;\r
63       this.hidseqs = hidseqs;\r
64       this.hiddencols = hiddencols;\r
65     }\r
66   }\r
67   public String printAnnotations(AlignmentAnnotation[] annotations,\r
68           Vector groups,\r
69           Hashtable properties, ViewDef[] views)\r
70   {\r
71     if (annotations != null)\r
72     {\r
73       boolean oneColour = true;\r
74       AlignmentAnnotation row;\r
75       String comma;\r
76       SequenceI refSeq = null;\r
77 \r
78       StringBuffer colours = new StringBuffer();\r
79       StringBuffer graphLine = new StringBuffer();\r
80 \r
81       Hashtable graphGroup = new Hashtable();\r
82 \r
83       java.awt.Color color;\r
84 \r
85       for (int i = 0; i < annotations.length; i++)\r
86       {\r
87         row = annotations[i];\r
88 \r
89         if (!row.visible && !row.hasScore())\r
90         {\r
91           continue;\r
92         }\r
93 \r
94         color = null;\r
95         oneColour = true;\r
96 \r
97         if (row.sequenceRef == null)\r
98         {\r
99           if (refSeq != null)\r
100           {\r
101             text.append("\nSEQUENCE_REF\tALIGNMENT\n");\r
102           }\r
103 \r
104           refSeq = null;\r
105         }\r
106 \r
107         else if (refSeq == null || refSeq != row.sequenceRef)\r
108         {\r
109           refSeq = row.sequenceRef;\r
110           text.append("\nSEQUENCE_REF\t" + refSeq.getName() + "\n");\r
111         }\r
112 \r
113         if (row.graph == AlignmentAnnotation.NO_GRAPH)\r
114         {\r
115           text.append("NO_GRAPH\t");\r
116         }\r
117         else\r
118         {\r
119           if (row.graph == AlignmentAnnotation.BAR_GRAPH)\r
120           {\r
121             text.append("BAR_GRAPH\t");\r
122           }\r
123           else if (row.graph == AlignmentAnnotation.LINE_GRAPH)\r
124           {\r
125             text.append("LINE_GRAPH\t");\r
126           }\r
127 \r
128           if (row.getThreshold() != null)\r
129           {\r
130             graphLine.append("GRAPHLINE\t"\r
131                              + row.label + "\t"\r
132                              + row.getThreshold().value + "\t"\r
133                              + row.getThreshold().label + "\t"\r
134                              + jalview.util.Format.getHexString(\r
135                                  row.getThreshold().colour) + "\n"\r
136                 );\r
137           }\r
138 \r
139           if (row.graphGroup > -1)\r
140           {\r
141             String key = String.valueOf(row.graphGroup);\r
142             if (graphGroup.containsKey(key))\r
143             {\r
144               graphGroup.put(key, graphGroup.get(key)\r
145                              + "\t" + row.label);\r
146             }\r
147             else\r
148             {\r
149               graphGroup.put(key, row.label);\r
150             }\r
151           }\r
152         }\r
153 \r
154         text.append(row.label + "\t");\r
155         if (row.description != null)\r
156         {\r
157           text.append(row.description + "\t");\r
158         }\r
159 \r
160         for (int j = 0; row.annotations!=null && j < row.annotations.length; j++)\r
161         {\r
162           if (refSeq != null &&\r
163               jalview.util.Comparison.isGap(refSeq.getCharAt(j)))\r
164           {\r
165             continue;\r
166           }\r
167 \r
168           if (row.annotations[j] != null)\r
169           {\r
170             comma = "";\r
171             if (row.annotations[j].secondaryStructure != ' ')\r
172             {\r
173               text.append(comma + row.annotations[j].secondaryStructure);\r
174               comma = ",";\r
175             }\r
176             if (row.annotations[j].displayCharacter!=null\r
177                 && row.annotations[j].displayCharacter.length() > 0\r
178                 && !row.annotations[j].displayCharacter.equals(" "))\r
179             {\r
180               text.append(comma + row.annotations[j].displayCharacter);\r
181               comma = ",";\r
182             }\r
183 \r
184             if (row.annotations[j] != null)\r
185             {\r
186               if(color!=null && !color.equals(row.annotations[j].colour))\r
187               {\r
188                 oneColour = false;\r
189               }\r
190 \r
191               color = row.annotations[j].colour;\r
192               if (row.annotations[j].value != 0f && row.annotations[j].value!=Float.NaN) \r
193               {\r
194                 text.append(comma + row.annotations[j].value);\r
195               }\r
196             }\r
197 \r
198             if(row.annotations[j].colour!=null\r
199                && row.annotations[j].colour!=java.awt.Color.black)\r
200             {\r
201               text.append(comma+"["+\r
202                           jalview.util.Format.getHexString(\r
203                           row.annotations[j].colour)+"]");\r
204             }\r
205           }\r
206           text.append("|");\r
207         }\r
208 \r
209         if(row.hasScore())\r
210           text.append("\t"+row.score);\r
211 \r
212         text.append("\n");\r
213 \r
214         if (color != null && color != java.awt.Color.black && oneColour)\r
215         {\r
216           colours.append("COLOUR\t"\r
217                          + row.label + "\t"\r
218                          + jalview.util.Format.getHexString(color) + "\n");\r
219         }\r
220 \r
221       }\r
222 \r
223       text.append("\n");\r
224 \r
225       text.append(colours.toString());\r
226       text.append(graphLine.toString());\r
227       if (graphGroup.size() > 0)\r
228       {\r
229         text.append("COMBINE\t");\r
230         Enumeration en = graphGroup.elements();\r
231         while (en.hasMoreElements())\r
232         {\r
233           text.append(en.nextElement() + "\n");\r
234         }\r
235       }\r
236     }\r
237 \r
238     if (groups != null)\r
239     {\r
240       printGroups(groups);\r
241     }\r
242 \r
243     if(properties!=null)\r
244     {\r
245       text.append("\n\nALIGNMENT");\r
246       Enumeration en = properties.keys();\r
247       while(en.hasMoreElements())\r
248       {\r
249         String key = en.nextElement().toString();\r
250         text.append("\t"+key+"="+properties.get(key));\r
251       }\r
252 \r
253     }\r
254     \r
255     return text.toString();\r
256   }\r
257 \r
258   public void printGroups(Vector sequenceGroups)\r
259   {\r
260     SequenceGroup sg;\r
261     for (int i = 0; i < sequenceGroups.size(); i++)\r
262     {\r
263       sg = (SequenceGroup) sequenceGroups.elementAt(i);\r
264       text.append("SEQUENCE_GROUP\t"\r
265                   + sg.getName() + "\t"\r
266                   + (sg.getStartRes() + 1) + "\t"\r
267                   + (sg.getEndRes() + 1) + "\t" + "-1\t");\r
268       for (int s = 0; s < sg.getSize(); s++)\r
269       {\r
270         text.append(sg.getSequenceAt(s).getName() + "\t");\r
271       }\r
272 \r
273       text.append("\nPROPERTIES\t" + sg.getName() + "\t");\r
274 \r
275       if (sg.getDescription() != null)\r
276       {\r
277         text.append("description=" + sg.getDescription() + "\t");\r
278       }\r
279       if (sg.cs != null)\r
280       {\r
281         text.append("colour=" + ColourSchemeProperty.getColourName(sg.cs) +\r
282                     "\t");\r
283         if (sg.cs.getThreshold() != 0)\r
284         {\r
285           text.append("pidThreshold=" + sg.cs.getThreshold());\r
286         }\r
287         if (sg.cs.conservationApplied())\r
288         {\r
289           text.append("consThreshold=" + sg.cs.getConservationInc() + "\t");\r
290         }\r
291       }\r
292       text.append("outlineColour=" +\r
293                   jalview.util.Format.getHexString(sg.getOutlineColour()) +\r
294                   "\t");\r
295 \r
296       text.append("displayBoxes=" + sg.getDisplayBoxes() + "\t");\r
297       text.append("displayText=" + sg.getDisplayText() + "\t");\r
298       text.append("colourText=" + sg.getColourText() + "\t");\r
299 \r
300       if (sg.textColour != java.awt.Color.black)\r
301       {\r
302         text.append("textCol1=" +\r
303                     jalview.util.Format.getHexString(sg.textColour) + "\t");\r
304       }\r
305       if (sg.textColour2 != java.awt.Color.white)\r
306       {\r
307         text.append("textCol2=" +\r
308                     jalview.util.Format.getHexString(sg.textColour2) + "\t");\r
309       }\r
310       if (sg.thresholdTextColour != 0)\r
311       {\r
312         text.append("textColThreshold=" + sg.thresholdTextColour);\r
313       }\r
314       if (sg.idColour!=null)\r
315       {\r
316         text.append("idColour="+jalview.util.Format.getHexString(sg.idColour)+"\t");\r
317       }\r
318 \r
319       text.append("\n\n");\r
320 \r
321     }\r
322   }\r
323 \r
324   SequenceI refSeq = null;\r
325   String refSeqId = null;\r
326   public boolean readAnnotationFile(AlignmentI al,\r
327                                     String file,\r
328                                     String protocol)\r
329   {\r
330     try\r
331     {\r
332       BufferedReader in = null;\r
333       if (protocol.equals(AppletFormatAdapter.FILE))\r
334       {\r
335         in = new BufferedReader(new FileReader(file));\r
336       }\r
337       else if (protocol.equals(AppletFormatAdapter.URL))\r
338       {\r
339         URL url = new URL(file);\r
340         in = new BufferedReader(new InputStreamReader(url.openStream()));\r
341       }\r
342       else if (protocol.equals(AppletFormatAdapter.PASTE))\r
343       {\r
344         in = new BufferedReader(new StringReader(file));\r
345       }\r
346       else if (protocol.equals(AppletFormatAdapter.CLASSLOADER))\r
347       {\r
348         java.io.InputStream is = getClass().getResourceAsStream("/" + file);\r
349         if (is != null)\r
350         {\r
351           in = new BufferedReader(new java.io.InputStreamReader(is));\r
352         }\r
353       }\r
354 \r
355       String line, label, description, token;\r
356       int graphStyle, index;\r
357       int refSeqIndex = 1;\r
358       int existingAnnotations = 0;\r
359       if (al.getAlignmentAnnotation() != null)\r
360       {\r
361         existingAnnotations = al.getAlignmentAnnotation().length;\r
362       }\r
363 \r
364       int alWidth = al.getWidth();\r
365 \r
366       StringTokenizer st;\r
367       Annotation[] annotations;\r
368       AlignmentAnnotation annotation = null;\r
369 \r
370       // First confirm this is an Annotation file\r
371       boolean jvAnnotationFile = false;\r
372       while ( (line = in.readLine()) != null)\r
373       {\r
374         if (line.indexOf("#") == 0)\r
375         {\r
376           continue;\r
377         }\r
378 \r
379         if (line.indexOf("JALVIEW_ANNOTATION") > -1)\r
380         {\r
381           jvAnnotationFile = true;\r
382           break;\r
383         }\r
384       }\r
385 \r
386       if (!jvAnnotationFile)\r
387       {\r
388         in.close();\r
389         return false;\r
390       }\r
391 \r
392       while ( (line = in.readLine()) != null)\r
393       {\r
394         if (line.indexOf("#") == 0\r
395             || line.indexOf("JALVIEW_ANNOTATION") > -1\r
396             || line.length() == 0)\r
397         {\r
398           continue;\r
399         }\r
400 \r
401         st = new StringTokenizer(line, "\t");\r
402         token = st.nextToken();\r
403         if (token.equalsIgnoreCase("COLOUR"))\r
404         {\r
405           colourAnnotations(al, st.nextToken(), st.nextToken());\r
406           continue;\r
407         }\r
408 \r
409         else if (token.equalsIgnoreCase("COMBINE"))\r
410         {\r
411           combineAnnotations(al, st);\r
412           continue;\r
413         }\r
414 \r
415         else if (token.equalsIgnoreCase("GRAPHLINE"))\r
416         {\r
417           addLine(al, st);\r
418           continue;\r
419         }\r
420 \r
421         else if (token.equalsIgnoreCase("SEQUENCE_REF"))\r
422         {\r
423           if (st.hasMoreTokens())\r
424           {\r
425             refSeq = al.findName(refSeqId=st.nextToken());\r
426           if (refSeq==null)\r
427           {\r
428             refSeqId=null;\r
429           }\r
430           try\r
431           {\r
432             refSeqIndex = Integer.parseInt(st.nextToken());\r
433             if (refSeqIndex < 1)\r
434             {\r
435               refSeqIndex = 1;\r
436               System.out.println(\r
437                   "WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile");\r
438             }\r
439           }\r
440           catch (Exception ex)\r
441           {\r
442             refSeqIndex = 1;\r
443           }\r
444           } else {\r
445             refSeq = null;\r
446             refSeqId = null;\r
447           }\r
448           continue ;\r
449         }\r
450 \r
451         else if (token.equalsIgnoreCase("SEQUENCE_GROUP"))\r
452         {\r
453           addGroup(al, st);\r
454           continue;\r
455         }\r
456 \r
457         else if (token.equalsIgnoreCase("PROPERTIES"))\r
458         {\r
459           addProperties(al, st);\r
460           continue;\r
461         }\r
462 \r
463         else if( token.equalsIgnoreCase("BELOW_ALIGNMENT"))\r
464         {\r
465           setBelowAlignment(al, st);\r
466           continue;\r
467         }\r
468         else if( token.equalsIgnoreCase("ALIGNMENT"))\r
469         {\r
470           addAlignmentDetails(al, st);\r
471           continue;\r
472         }\r
473 \r
474         graphStyle = AlignmentAnnotation.getGraphValueFromString(token);\r
475         label = st.nextToken();\r
476 \r
477 \r
478         index = 0;\r
479         annotations = new Annotation[alWidth];\r
480         description = null;\r
481         float score = Float.NaN;\r
482 \r
483         if(st.hasMoreTokens())\r
484         {\r
485           line = st.nextToken();\r
486 \r
487           if (line.indexOf("|") ==-1)\r
488           {\r
489             description = line;\r
490             if (st.hasMoreTokens())\r
491               line = st.nextToken();\r
492           }\r
493 \r
494           if(st.hasMoreTokens())\r
495           {\r
496             //This must be the score\r
497             score = Float.valueOf(st.nextToken()).floatValue();\r
498           }\r
499 \r
500           st = new StringTokenizer(line, "|", true);\r
501 \r
502 \r
503           boolean emptyColumn = true;\r
504           boolean onlyOneElement = (st.countTokens()==1);\r
505 \r
506           while (st.hasMoreElements() && index < alWidth)\r
507           {\r
508             token = st.nextToken().trim();\r
509 \r
510             if(onlyOneElement)\r
511             {\r
512               try\r
513               {\r
514                 score = Float.valueOf(token).floatValue();\r
515                 break;\r
516               }\r
517               catch(NumberFormatException ex){}\r
518             }\r
519 \r
520             if (token.equals("|"))\r
521             {\r
522               if (emptyColumn)\r
523               {\r
524                 index++;\r
525               }\r
526 \r
527               emptyColumn = true;\r
528             }\r
529             else\r
530             {\r
531               annotations[index++] = parseAnnotation(token);\r
532               emptyColumn = false;\r
533             }\r
534           }\r
535 \r
536         }\r
537 \r
538         annotation = new AlignmentAnnotation(label,\r
539                                              description,\r
540                                              (index==0) ? null : annotations,\r
541                                              0,\r
542                                              0,\r
543                                              graphStyle);\r
544 \r
545         annotation.score = score;\r
546 \r
547         if (refSeq != null)\r
548         {\r
549           annotation.belowAlignment=false;\r
550           do {\r
551             // copy before we do any mapping business.\r
552             // TODO: verify that undo/redo with 1:many sequence associated annotations can be undone correctly\r
553             AlignmentAnnotation ann = new AlignmentAnnotation(annotation);\r
554             annotation.createSequenceMapping(refSeq, refSeqIndex, false);\r
555             annotation.adjustForAlignment();\r
556             refSeq.addAlignmentAnnotation(annotation);\r
557             al.addAnnotation(annotation);\r
558             al.setAnnotationIndex(annotation,\r
559                                 al.getAlignmentAnnotation().length - existingAnnotations -\r
560                                 1);\r
561             // and recover our virgin copy to use again if necessary.\r
562             annotation = ann;\r
563             \r
564           } while (refSeqId!=null && (refSeq=al.findName(refSeq, refSeqId, true))!=null);\r
565         } else {\r
566           al.addAnnotation(annotation);\r
567           al.setAnnotationIndex(annotation,\r
568                               al.getAlignmentAnnotation().length - existingAnnotations -\r
569                               1);\r
570         }\r
571       }\r
572 \r
573     }\r
574     catch (Exception ex)\r
575     {\r
576       ex.printStackTrace();\r
577       System.out.println("Problem reading annotation file: " + ex);\r
578       return false;\r
579     }\r
580     return true;\r
581   }\r
582 \r
583   Annotation parseAnnotation(String string)\r
584   {\r
585     String desc = null, displayChar = null;\r
586     char ss = ' '; // secondaryStructure\r
587     float value = 0;\r
588     boolean parsedValue = false;\r
589 \r
590     //find colour here\r
591     java.awt.Color colour = null;\r
592     int i=string.indexOf("[");\r
593     int j=string.indexOf("]");\r
594     if(i>-1 && j>-1)\r
595     {\r
596       UserColourScheme ucs = new UserColourScheme();\r
597 \r
598       colour = ucs.getColourFromString(string.substring(i+1,j));\r
599 \r
600       string = string.substring(0,i)+string.substring(j+1);\r
601     }\r
602 \r
603     StringTokenizer st = new StringTokenizer(string, ",");\r
604     String token;\r
605     while (st.hasMoreTokens())\r
606     {\r
607       token = st.nextToken().trim();\r
608       if (token.length() == 0)\r
609       {\r
610         continue;\r
611       }\r
612 \r
613       if (!parsedValue)\r
614       {\r
615         try\r
616         {\r
617           displayChar = token;\r
618           value = new Float(token).floatValue();\r
619           parsedValue = true;\r
620           continue;\r
621         }\r
622         catch (NumberFormatException ex)\r
623         {}\r
624       }\r
625 \r
626       if (token.equals("H") || token.equals("E"))\r
627       {\r
628         // Either this character represents a helix or sheet\r
629         // or an integer which can be displayed\r
630         ss = token.charAt(0);\r
631         if (displayChar.equals(token.substring(0, 1)))\r
632         {\r
633           displayChar = "";\r
634         }\r
635       }\r
636       else if (desc == null)\r
637       {\r
638         desc = token;\r
639       }\r
640 \r
641     }\r
642 \r
643     if (displayChar!=null\r
644         && displayChar.length() > 1\r
645         &&  desc!=null\r
646         && desc.length() == 1)\r
647     {\r
648       String tmp = displayChar;\r
649       displayChar = desc;\r
650       desc = tmp;\r
651     }\r
652     /*\r
653      * In principle, this code will ensure that the Annotation element generated is renderable by any of the applet or application rendering code\r
654      * but instead we check for null strings when the display character is rendered. \r
655     if (displayChar==null)\r
656     {\r
657       displayChar="";\r
658     }\r
659     */\r
660     Annotation anot = new Annotation(displayChar, desc, ss, value);\r
661 \r
662     anot.colour = colour;\r
663 \r
664     return anot;\r
665   }\r
666 \r
667   void colourAnnotations(AlignmentI al, String label, String colour)\r
668   {\r
669     UserColourScheme ucs = new UserColourScheme(colour);\r
670     Annotation[] annotations;\r
671     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
672     {\r
673       if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(label))\r
674       {\r
675         annotations = al.getAlignmentAnnotation()[i].annotations;\r
676         for (int j = 0; j < annotations.length; j++)\r
677         {\r
678           if (annotations[j] != null)\r
679           {\r
680             annotations[j].colour = ucs.findColour('A');\r
681           }\r
682         }\r
683       }\r
684     }\r
685   }\r
686 \r
687   void combineAnnotations(AlignmentI al, StringTokenizer st)\r
688   {\r
689     int graphGroup = -1;\r
690     String group = st.nextToken();\r
691     //First make sure we are not overwriting the graphIndex\r
692     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
693     {\r
694       if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
695       {\r
696         graphGroup = al.getAlignmentAnnotation()[i].graphGroup + 1;\r
697         al.getAlignmentAnnotation()[i].graphGroup = graphGroup;\r
698         break;\r
699       }\r
700     }\r
701 \r
702     //Now update groups\r
703     while (st.hasMoreTokens())\r
704     {\r
705       group = st.nextToken();\r
706       for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
707       {\r
708         if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
709         {\r
710           al.getAlignmentAnnotation()[i].graphGroup = graphGroup;\r
711           break;\r
712         }\r
713       }\r
714     }\r
715   }\r
716 \r
717   void addLine(AlignmentI al, StringTokenizer st)\r
718   {\r
719     String group = st.nextToken();\r
720     AlignmentAnnotation annotation = null;\r
721 \r
722     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
723     {\r
724       if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
725       {\r
726         annotation = al.getAlignmentAnnotation()[i];\r
727         break;\r
728       }\r
729     }\r
730 \r
731     if (annotation == null)\r
732     {\r
733       return;\r
734     }\r
735     float value = new Float(st.nextToken()).floatValue();\r
736     String label = st.hasMoreTokens() ? st.nextToken() : null;\r
737     java.awt.Color colour = null;\r
738     if (st.hasMoreTokens())\r
739     {\r
740       UserColourScheme ucs = new UserColourScheme(st.nextToken());\r
741       colour = ucs.findColour('A');\r
742     }\r
743 \r
744     annotation.setThreshold(new GraphLine(value, label, colour));\r
745   }\r
746 \r
747   void addGroup(AlignmentI al, StringTokenizer st)\r
748   {\r
749     SequenceGroup sg = new SequenceGroup();\r
750     sg.setName(st.nextToken());\r
751     sg.setStartRes(Integer.parseInt(st.nextToken()) - 1);\r
752     sg.setEndRes(Integer.parseInt(st.nextToken()) - 1);\r
753 \r
754     String index = st.nextToken();\r
755     if (index.equals("-1"))\r
756     {\r
757       while (st.hasMoreElements())\r
758       {\r
759         sg.addSequence(al.findName(st.nextToken()), false);\r
760       }\r
761     }\r
762     else\r
763     {\r
764       StringTokenizer st2 = new StringTokenizer(index, ",");\r
765 \r
766       while (st2.hasMoreTokens())\r
767       {\r
768         String tmp = st2.nextToken();\r
769         if (tmp.equals("*"))\r
770         {\r
771           for (int i = 0; i < al.getHeight(); i++)\r
772           {\r
773             sg.addSequence(al.getSequenceAt(i), false);\r
774           }\r
775         }\r
776         else if (tmp.indexOf("-") >= 0)\r
777         {\r
778           StringTokenizer st3 = new StringTokenizer(tmp, "-");\r
779 \r
780           int start = (Integer.parseInt(st3.nextToken()));\r
781           int end = (Integer.parseInt(st3.nextToken()));\r
782 \r
783           if (end > start)\r
784           {\r
785             for (int i = start; i <= end; i++)\r
786             {\r
787               sg.addSequence(al.getSequenceAt(i - 1), false);\r
788             }\r
789           }\r
790         }\r
791         else\r
792         {\r
793           sg.addSequence(al.getSequenceAt(Integer.parseInt(tmp) - 1), false);\r
794         }\r
795       }\r
796     }\r
797 \r
798 \r
799 \r
800     if (refSeq != null)\r
801     {\r
802       sg.setStartRes(refSeq.findIndex(sg.getStartRes() + 1) - 1);\r
803       sg.setEndRes(refSeq.findIndex(sg.getEndRes() + 1) - 1);\r
804     }\r
805 \r
806     if (sg.getSize() > 0)\r
807     {\r
808       al.addGroup(sg);\r
809     }\r
810   }\r
811 \r
812   void addProperties(AlignmentI al, StringTokenizer st)\r
813   {\r
814 \r
815     //So far we have only added groups to the annotationHash,\r
816     //the idea is in the future properties can be added to\r
817     //alignments, other annotations etc\r
818     if (al.getGroups() == null)\r
819     {\r
820       return;\r
821     }\r
822     SequenceGroup sg = null;\r
823 \r
824     String name = st.nextToken();\r
825 \r
826     Vector groups = al.getGroups();\r
827     for (int i = 0; i < groups.size(); i++)\r
828     {\r
829       sg = (SequenceGroup) groups.elementAt(i);\r
830       if (sg.getName().equals(name))\r
831       {\r
832         break;\r
833       }\r
834       else\r
835       {\r
836         sg = null;\r
837       }\r
838     }\r
839 \r
840     if (sg != null)\r
841     {\r
842       String keyValue, key, value;\r
843       ColourSchemeI def = sg.cs;\r
844       sg.cs = null;\r
845       while (st.hasMoreTokens())\r
846       {\r
847         keyValue = st.nextToken();\r
848         key = keyValue.substring(0, keyValue.indexOf("="));\r
849         value = keyValue.substring(keyValue.indexOf("=") + 1);\r
850 \r
851         if (key.equalsIgnoreCase("description"))\r
852         {\r
853           sg.setDescription(value);\r
854         }\r
855         else if (key.equalsIgnoreCase("colour"))\r
856         {\r
857           sg.cs = ColourSchemeProperty.getColour(al, value);\r
858         }\r
859         else if (key.equalsIgnoreCase("pidThreshold"))\r
860         {\r
861           sg.cs.setThreshold(Integer.parseInt(value), true);\r
862 \r
863         }\r
864         else if (key.equalsIgnoreCase("consThreshold"))\r
865         {\r
866           sg.cs.setConservationInc(Integer.parseInt(value));\r
867           Conservation c = new Conservation("Group",\r
868                                             ResidueProperties.propHash, 3,\r
869                                             sg.getSequences(null),\r
870                                             sg.getStartRes(),\r
871                                             sg.getEndRes() + 1);\r
872 \r
873           c.calculate();\r
874           c.verdict(false, 25);\r
875 \r
876           sg.cs.setConservation(c);\r
877 \r
878         }\r
879         else if (key.equalsIgnoreCase("outlineColour"))\r
880         {\r
881           sg.setOutlineColour(new UserColourScheme(value).findColour('A'));\r
882         }\r
883         else if (key.equalsIgnoreCase("displayBoxes"))\r
884         {\r
885           sg.setDisplayBoxes(Boolean.valueOf(value).booleanValue());\r
886         }\r
887         else if (key.equalsIgnoreCase("displayText"))\r
888         {\r
889           sg.setDisplayText(Boolean.valueOf(value).booleanValue());\r
890         }\r
891         else if (key.equalsIgnoreCase("colourText"))\r
892         {\r
893           sg.setColourText(Boolean.valueOf(value).booleanValue());\r
894         }\r
895         else if (key.equalsIgnoreCase("textCol1"))\r
896         {\r
897           sg.textColour = new UserColourScheme(value).findColour('A');\r
898         }\r
899         else if (key.equalsIgnoreCase("textCol2"))\r
900         {\r
901           sg.textColour2 = new UserColourScheme(value).findColour('A');\r
902         }\r
903         else if (key.equalsIgnoreCase("textColThreshold"))\r
904         {\r
905           sg.thresholdTextColour = Integer.parseInt(value);\r
906         }\r
907         else if (key.equalsIgnoreCase("idColour"))\r
908         {\r
909           // consider warning if colour doesn't resolve to a real colour\r
910           sg.setIdColour((def = new UserColourScheme(value)).findColour('A'));\r
911         }\r
912         sg.recalcConservation();\r
913       }\r
914       if (sg.cs==null)\r
915       {\r
916         sg.cs = def;\r
917       }\r
918     }\r
919   }\r
920 \r
921   void setBelowAlignment(AlignmentI al, StringTokenizer st)\r
922   {\r
923     String token;\r
924     AlignmentAnnotation aa;\r
925     while(st.hasMoreTokens())\r
926     {\r
927       token = st.nextToken();\r
928       for(int i=0; i<al.getAlignmentAnnotation().length; i++)\r
929       {\r
930         aa = al.getAlignmentAnnotation()[i];\r
931         if(aa.sequenceRef==refSeq && aa.label.equals(token))\r
932         {\r
933           aa.belowAlignment = true;\r
934         }\r
935       }\r
936     }\r
937   }\r
938 \r
939   void addAlignmentDetails(AlignmentI al, StringTokenizer st)\r
940   {\r
941     String keyValue, key, value;\r
942     while (st.hasMoreTokens())\r
943     {\r
944       keyValue = st.nextToken();\r
945       key = keyValue.substring(0, keyValue.indexOf("="));\r
946       value = keyValue.substring(keyValue.indexOf("=") + 1);\r
947       al.setProperty(key,value);\r
948     }\r
949   }\r
950 \r
951   /**\r
952    * Write annotations as a CSV file of the form 'label, value, value, ...' for each row.\r
953    * @param annotations\r
954    * @return CSV file as a string.\r
955    */\r
956   public String printCSVAnnotations(AlignmentAnnotation[] annotations)\r
957   {\r
958     StringBuffer sp = new StringBuffer();\r
959     for (int i=0; i<annotations.length; i++)\r
960     {\r
961       String atos = annotations[i].toString();\r
962       int p = 0;\r
963       do {\r
964         int cp = atos.indexOf("\n", p);\r
965         sp.append(annotations[i].label);\r
966         sp.append(",");\r
967         if (cp>p)\r
968         {\r
969           sp.append(atos.substring(p, cp+1));\r
970         } else {\r
971           sp.append(atos.substring(p));\r
972           sp.append("\n");\r
973         }\r
974         p = cp+1;\r
975       } while (p>0);\r
976     }\r
977     return sp.toString();\r
978   }\r
979 }\r