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