Formatting
[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   public String printAnnotations(AlignmentAnnotation[] annotations,\r
38                                  Vector groups)\r
39   {\r
40     if (annotations != null)\r
41     {\r
42       AlignmentAnnotation row;\r
43       String comma;\r
44       SequenceI seqref = null;\r
45 \r
46       StringBuffer colours = new StringBuffer();\r
47       StringBuffer graphLine = new StringBuffer();\r
48 \r
49       Hashtable graphGroup = new Hashtable();\r
50 \r
51       java.awt.Color color;\r
52 \r
53       for (int i = 0; i < annotations.length; i++)\r
54       {\r
55         row = annotations[i];\r
56 \r
57         if (!row.visible)\r
58         {\r
59           continue;\r
60         }\r
61 \r
62         color = null;\r
63 \r
64         if (row.sequenceRef == null)\r
65         {\r
66           if (seqref != null)\r
67           {\r
68             text.append("\nSEQUENCE_REF\tALIGNMENT\n");\r
69           }\r
70 \r
71           seqref = null;\r
72         }\r
73 \r
74         else if (seqref == null || seqref != row.sequenceRef)\r
75         {\r
76           seqref = row.sequenceRef;\r
77           text.append("\nSEQUENCE_REF\t" + seqref.getName() + "\n");\r
78         }\r
79 \r
80         if (row.graph == AlignmentAnnotation.NO_GRAPH)\r
81         {\r
82           text.append("NO_GRAPH\t");\r
83         }\r
84         else\r
85         {\r
86           if (row.graph == AlignmentAnnotation.BAR_GRAPH)\r
87           {\r
88             text.append("BAR_GRAPH\t");\r
89           }\r
90           else if (row.graph == AlignmentAnnotation.LINE_GRAPH)\r
91           {\r
92             text.append("LINE_GRAPH\t");\r
93           }\r
94 \r
95           if (row.getThreshold() != null)\r
96           {\r
97             graphLine.append("GRAPHLINE\t"\r
98                              + row.label + "\t"\r
99                              + row.getThreshold().value + "\t"\r
100                              + row.getThreshold().label + "\t"\r
101                              + jalview.util.Format.getHexString(\r
102                                  row.getThreshold().colour) + "\n"\r
103                 );\r
104           }\r
105 \r
106           if (row.graphGroup > -1)\r
107           {\r
108             String key = String.valueOf(row.graphGroup);\r
109             if (graphGroup.containsKey(key))\r
110             {\r
111               graphGroup.put(key, graphGroup.get(key)\r
112                              + "\t" + row.label);\r
113             }\r
114             else\r
115             {\r
116               graphGroup.put(key, row.label);\r
117             }\r
118           }\r
119         }\r
120 \r
121         text.append(row.label + "\t");\r
122         if (row.description != null)\r
123         {\r
124           text.append(row.description + "\t");\r
125         }\r
126 \r
127         for (int j = 0; j < row.annotations.length; j++)\r
128         {\r
129           if (seqref != null &&\r
130               jalview.util.Comparison.isGap(seqref.getCharAt(j)))\r
131           {\r
132             continue;\r
133           }\r
134 \r
135           if (row.annotations[j] != null)\r
136           {\r
137             comma = "";\r
138             if (row.annotations[j].secondaryStructure != ' ')\r
139             {\r
140               text.append(comma + row.annotations[j].secondaryStructure);\r
141               comma = ",";\r
142             }\r
143             if (row.annotations[j].displayCharacter.length() > 0\r
144                 && !row.annotations[j].displayCharacter.equals(" "))\r
145             {\r
146               text.append(comma + row.annotations[j].displayCharacter);\r
147               comma = ",";\r
148             }\r
149 \r
150             if (row.annotations[j] != null)\r
151             {\r
152               color = row.annotations[j].colour;\r
153               if (row.annotations[j].value != 0f)\r
154               {\r
155                 text.append(comma + row.annotations[j].value);\r
156               }\r
157             }\r
158           }\r
159           text.append("|");\r
160         }\r
161 \r
162         text.append("\n");\r
163 \r
164         if (color != null && color != java.awt.Color.black)\r
165         {\r
166           colours.append("COLOUR\t"\r
167                          + row.label + "\t"\r
168                          + jalview.util.Format.getHexString(color) + "\n");\r
169         }\r
170 \r
171       }\r
172 \r
173       text.append("\n");\r
174 \r
175       text.append(colours.toString());\r
176       text.append(graphLine.toString());\r
177       if (graphGroup.size() > 0)\r
178       {\r
179         text.append("COMBINE\t");\r
180         Enumeration en = graphGroup.elements();\r
181         while (en.hasMoreElements())\r
182         {\r
183           text.append(en.nextElement() + "\n");\r
184         }\r
185       }\r
186     }\r
187 \r
188     if (groups != null)\r
189     {\r
190       printGroups(groups);\r
191     }\r
192 \r
193     return text.toString();\r
194   }\r
195 \r
196   public void printGroups(Vector sequenceGroups)\r
197   {\r
198     SequenceGroup sg;\r
199     for (int i = 0; i < sequenceGroups.size(); i++)\r
200     {\r
201       sg = (SequenceGroup) sequenceGroups.elementAt(i);\r
202       text.append("SEQUENCE_GROUP\t"\r
203                   + sg.getName() + "\t"\r
204                   + (sg.getStartRes() + 1) + "\t"\r
205                   + (sg.getEndRes() + 1) + "\t" + "-1\t");\r
206       for (int s = 0; s < sg.getSize(); s++)\r
207       {\r
208         text.append(sg.getSequenceAt(s).getName() + "\t");\r
209       }\r
210 \r
211       text.append("\nPROPERTIES\t" + sg.getName() + "\t");\r
212 \r
213       if (sg.getDescription() != null)\r
214       {\r
215         text.append("description=" + sg.getDescription() + "\t");\r
216       }\r
217       if (sg.cs != null)\r
218       {\r
219         text.append("colour=" + ColourSchemeProperty.getColourName(sg.cs) +\r
220                     "\t");\r
221         if (sg.cs.getThreshold() != 0)\r
222         {\r
223           text.append("pidThreshold=" + sg.cs.getThreshold());\r
224         }\r
225         if (sg.cs.conservationApplied())\r
226         {\r
227           text.append("consThreshold=" + sg.cs.getConservationInc() + "\t");\r
228         }\r
229       }\r
230       text.append("outlineColour=" +\r
231                   jalview.util.Format.getHexString(sg.getOutlineColour()) +\r
232                   "\t");\r
233 \r
234       text.append("displayBoxes=" + sg.getDisplayBoxes() + "\t");\r
235       text.append("displayText=" + sg.getDisplayText() + "\t");\r
236       text.append("colourText=" + sg.getColourText() + "\t");\r
237 \r
238       if (sg.textColour != java.awt.Color.black)\r
239       {\r
240         text.append("textCol1=" +\r
241                     jalview.util.Format.getHexString(sg.textColour) + "\t");\r
242       }\r
243       if (sg.textColour2 != java.awt.Color.white)\r
244       {\r
245         text.append("textCol2=" +\r
246                     jalview.util.Format.getHexString(sg.textColour2) + "\t");\r
247       }\r
248       if (sg.thresholdTextColour != 0)\r
249       {\r
250         text.append("textColThreshold=" + sg.thresholdTextColour);\r
251       }\r
252 \r
253       text.append("\n\n");\r
254 \r
255     }\r
256   }\r
257 \r
258   SequenceI refSeq = null;\r
259   public boolean readAnnotationFile(AlignmentI al,\r
260                                     String file,\r
261                                     String protocol)\r
262   {\r
263     try\r
264     {\r
265       BufferedReader in = null;\r
266       if (protocol.equals(AppletFormatAdapter.FILE))\r
267       {\r
268         in = new BufferedReader(new FileReader(file));\r
269       }\r
270       else if (protocol.equals(AppletFormatAdapter.URL))\r
271       {\r
272         URL url = new URL(file);\r
273         in = new BufferedReader(new InputStreamReader(url.openStream()));\r
274       }\r
275       else if (protocol.equals(AppletFormatAdapter.PASTE))\r
276       {\r
277         in = new BufferedReader(new StringReader(file));\r
278       }\r
279       else if (protocol.equals(AppletFormatAdapter.CLASSLOADER))\r
280       {\r
281         java.io.InputStream is = getClass().getResourceAsStream("/" + file);\r
282         if (is != null)\r
283         {\r
284           in = new BufferedReader(new java.io.InputStreamReader(is));\r
285         }\r
286       }\r
287 \r
288       String line, label, description, token;\r
289       int graphStyle, index;\r
290       int refSeqIndex = 1;\r
291       int existingAnnotations = 0;\r
292       if (al.getAlignmentAnnotation() != null)\r
293       {\r
294         existingAnnotations = al.getAlignmentAnnotation().length;\r
295       }\r
296 \r
297       int alWidth = al.getWidth();\r
298 \r
299       StringTokenizer st;\r
300       Annotation[] annotations;\r
301       AlignmentAnnotation annotation = null;\r
302 \r
303       // First confirm this is an Annotation file\r
304       boolean jvAnnotationFile = false;\r
305       while ( (line = in.readLine()) != null)\r
306       {\r
307         if (line.indexOf("#") == 0)\r
308         {\r
309           continue;\r
310         }\r
311 \r
312         if (line.indexOf("JALVIEW_ANNOTATION") > -1)\r
313         {\r
314           jvAnnotationFile = true;\r
315           break;\r
316         }\r
317       }\r
318 \r
319       if (!jvAnnotationFile)\r
320       {\r
321         in.close();\r
322         return false;\r
323       }\r
324 \r
325       while ( (line = in.readLine()) != null)\r
326       {\r
327         if (line.indexOf("#") == 0\r
328             || line.indexOf("JALVIEW_ANNOTATION") > -1\r
329             || line.length() == 0)\r
330         {\r
331           continue;\r
332         }\r
333 \r
334         st = new StringTokenizer(line, "\t");\r
335         token = st.nextToken();\r
336         if (token.equalsIgnoreCase("COLOUR"))\r
337         {\r
338           colourAnnotations(al, st.nextToken(), st.nextToken());\r
339           continue;\r
340         }\r
341 \r
342         else if (token.equalsIgnoreCase("COMBINE"))\r
343         {\r
344           combineAnnotations(al, st);\r
345           continue;\r
346         }\r
347 \r
348         else if (token.equalsIgnoreCase("GRAPHLINE"))\r
349         {\r
350           addLine(al, st);\r
351           continue;\r
352         }\r
353 \r
354         else if (token.equalsIgnoreCase("SEQUENCE_REF"))\r
355         {\r
356           refSeq = al.findName(st.nextToken());\r
357           try\r
358           {\r
359             refSeqIndex = Integer.parseInt(st.nextToken());\r
360             if (refSeqIndex < 1)\r
361             {\r
362               refSeqIndex = 1;\r
363               System.out.println(\r
364                   "WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile");\r
365             }\r
366           }\r
367           catch (Exception ex)\r
368           {\r
369             refSeqIndex = 1;\r
370           }\r
371 \r
372           continue ;\r
373         }\r
374 \r
375         else if (token.equalsIgnoreCase("SEQUENCE_GROUP"))\r
376         {\r
377           addGroup(al, st);\r
378           continue;\r
379         }\r
380 \r
381         else if (token.equalsIgnoreCase("PROPERTIES"))\r
382         {\r
383           addProperties(al, st);\r
384           continue;\r
385         }\r
386 \r
387         graphStyle = AlignmentAnnotation.getGraphValueFromString(token);\r
388         label = st.nextToken();\r
389 \r
390         if (st.countTokens() > 1)\r
391         {\r
392           description = st.nextToken();\r
393         }\r
394         else\r
395         {\r
396           description = null;\r
397         }\r
398 \r
399         line = st.nextToken();\r
400 \r
401         st = new StringTokenizer(line, "|", true);\r
402         annotations = new Annotation[alWidth];\r
403 \r
404         index = 0;\r
405         boolean emptyColumn = true;\r
406 \r
407         while (st.hasMoreElements() && index < alWidth)\r
408         {\r
409           token = st.nextToken().trim();\r
410           if (token.equals("|"))\r
411           {\r
412             if (emptyColumn)\r
413             {\r
414               index++;\r
415             }\r
416 \r
417             emptyColumn = true;\r
418           }\r
419           else\r
420           {\r
421             annotations[index++] = parseAnnotation(token);\r
422             emptyColumn = false;\r
423           }\r
424         }\r
425 \r
426         annotation = new AlignmentAnnotation(label,\r
427                                              description,\r
428                                              annotations,\r
429                                              0,\r
430                                              0,\r
431                                              graphStyle);\r
432 \r
433         if (refSeq != null)\r
434         {\r
435           annotation.createSequenceMapping(refSeq, refSeqIndex, false);\r
436           refSeq.addAlignmentAnnotation(annotation);\r
437         }\r
438 \r
439         al.addAnnotation(annotation);\r
440 \r
441         al.setAnnotationIndex(annotation,\r
442                               al.getAlignmentAnnotation().length - existingAnnotations -\r
443                               1);\r
444       }\r
445 \r
446     }\r
447     catch (Exception ex)\r
448     {\r
449       ex.printStackTrace();\r
450       System.out.println("Problem reading annotation file: " + ex);\r
451       return false;\r
452     }\r
453     return true;\r
454   }\r
455 \r
456   Annotation parseAnnotation(String string)\r
457   {\r
458     String desc = null, displayChar = "";\r
459     char ss = ' '; // secondaryStructure\r
460     float value = 0;\r
461     boolean parsedValue = false;\r
462     StringTokenizer st = new StringTokenizer(string, ",");\r
463     String token;\r
464     while (st.hasMoreTokens())\r
465     {\r
466       token = st.nextToken().trim();\r
467       if (token.length() == 0)\r
468       {\r
469         continue;\r
470       }\r
471 \r
472       if (!parsedValue)\r
473       {\r
474         try\r
475         {\r
476           displayChar = token;\r
477           value = new Float(token).floatValue();\r
478           parsedValue = true;\r
479           continue;\r
480         }\r
481         catch (NumberFormatException ex)\r
482         {}\r
483       }\r
484 \r
485       if (token.equals("H") || token.equals("E"))\r
486       {\r
487         // Either this character represents a helix or sheet\r
488         // or an integer which can be displayed\r
489         ss = token.charAt(0);\r
490         if (displayChar.equals(token.substring(0, 1)))\r
491         {\r
492           displayChar = "";\r
493         }\r
494       }\r
495       else if (desc == null)\r
496       {\r
497         desc = token;\r
498       }\r
499 \r
500     }\r
501 \r
502     if (desc == null)\r
503     {\r
504       desc = value + "";\r
505     }\r
506 \r
507     if (displayChar.length() > 1 && desc.length() == 1)\r
508     {\r
509       String tmp = displayChar;\r
510       displayChar = desc;\r
511       desc = tmp;\r
512     }\r
513 \r
514     return new Annotation(displayChar, desc, ss, value);\r
515   }\r
516 \r
517   void colourAnnotations(AlignmentI al, String label, String colour)\r
518   {\r
519     UserColourScheme ucs = new UserColourScheme(colour);\r
520     Annotation[] annotations;\r
521     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
522     {\r
523       if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(label))\r
524       {\r
525         annotations = al.getAlignmentAnnotation()[i].annotations;\r
526         for (int j = 0; j < annotations.length; j++)\r
527         {\r
528           if (annotations[j] != null)\r
529           {\r
530             annotations[j].colour = ucs.findColour('A');\r
531           }\r
532         }\r
533       }\r
534     }\r
535   }\r
536 \r
537   void combineAnnotations(AlignmentI al, StringTokenizer st)\r
538   {\r
539     int graphGroup = -1;\r
540     String group = st.nextToken();\r
541     //First make sure we are not overwriting the graphIndex\r
542     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
543     {\r
544       if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
545       {\r
546         graphGroup = al.getAlignmentAnnotation()[i].graphGroup + 1;\r
547         al.getAlignmentAnnotation()[i].graphGroup = graphGroup;\r
548         break;\r
549       }\r
550     }\r
551 \r
552     //Now update groups\r
553     while (st.hasMoreTokens())\r
554     {\r
555       group = st.nextToken();\r
556       for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
557       {\r
558         if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
559         {\r
560           al.getAlignmentAnnotation()[i].graphGroup = graphGroup;\r
561           break;\r
562         }\r
563       }\r
564     }\r
565   }\r
566 \r
567   void addLine(AlignmentI al, StringTokenizer st)\r
568   {\r
569     String group = st.nextToken();\r
570     AlignmentAnnotation annotation = null;\r
571 \r
572     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)\r
573     {\r
574       if (al.getAlignmentAnnotation()[i].label.equalsIgnoreCase(group))\r
575       {\r
576         annotation = al.getAlignmentAnnotation()[i];\r
577         break;\r
578       }\r
579     }\r
580 \r
581     if (annotation == null)\r
582     {\r
583       return;\r
584     }\r
585     float value = new Float(st.nextToken()).floatValue();\r
586     String label = st.hasMoreTokens() ? st.nextToken() : null;\r
587     java.awt.Color colour = null;\r
588     if (st.hasMoreTokens())\r
589     {\r
590       UserColourScheme ucs = new UserColourScheme(st.nextToken());\r
591       colour = ucs.findColour('A');\r
592     }\r
593 \r
594     annotation.setThreshold(new GraphLine(value, label, colour));\r
595   }\r
596 \r
597   void addGroup(AlignmentI al, StringTokenizer st)\r
598   {\r
599     SequenceGroup sg = new SequenceGroup();\r
600     sg.setName(st.nextToken());\r
601     sg.setStartRes(Integer.parseInt(st.nextToken()) - 1);\r
602     sg.setEndRes(Integer.parseInt(st.nextToken()) - 1);\r
603 \r
604     String index = st.nextToken();\r
605     if (index.equals("-1"))\r
606     {\r
607       while (st.hasMoreElements())\r
608       {\r
609         sg.addSequence(al.findName(st.nextToken()), false);\r
610       }\r
611     }\r
612     else\r
613     {\r
614       StringTokenizer st2 = new StringTokenizer(index, ",");\r
615 \r
616       while (st2.hasMoreTokens())\r
617       {\r
618         String tmp = st2.nextToken();\r
619         if (tmp.equals("*"))\r
620         {\r
621           for (int i = 0; i < al.getHeight(); i++)\r
622           {\r
623             sg.addSequence(al.getSequenceAt(i), false);\r
624           }\r
625         }\r
626         else if (tmp.indexOf("-") >= 0)\r
627         {\r
628           StringTokenizer st3 = new StringTokenizer(tmp, "-");\r
629 \r
630           int start = (Integer.parseInt(st3.nextToken()));\r
631           int end = (Integer.parseInt(st3.nextToken()));\r
632 \r
633           if (end > start)\r
634           {\r
635             for (int i = start; i <= end; i++)\r
636             {\r
637               sg.addSequence(al.getSequenceAt(i - 1), false);\r
638             }\r
639           }\r
640         }\r
641         else\r
642         {\r
643           sg.addSequence(al.getSequenceAt(Integer.parseInt(tmp) - 1), false);\r
644         }\r
645       }\r
646     }\r
647 \r
648     if (refSeq != null)\r
649     {\r
650       sg.setStartRes(refSeq.findIndex(sg.getStartRes() + 1) - 1);\r
651       sg.setEndRes(refSeq.findIndex(sg.getEndRes() + 1) - 1);\r
652     }\r
653 \r
654     if (sg.getSize() > 0)\r
655     {\r
656       al.addGroup(sg);\r
657     }\r
658   }\r
659 \r
660   void addProperties(AlignmentI al, StringTokenizer st)\r
661   {\r
662 \r
663     //So far we have only added groups to the annotationHash,\r
664     //the idea is in the future properties can be added to\r
665     //alignments, other annotations etc\r
666     if (al.getGroups() == null)\r
667     {\r
668       return;\r
669     }\r
670     SequenceGroup sg = null;\r
671 \r
672     String name = st.nextToken();\r
673 \r
674     Vector groups = al.getGroups();\r
675     for (int i = 0; i < groups.size(); i++)\r
676     {\r
677       sg = (SequenceGroup) groups.elementAt(i);\r
678       if (sg.getName().equals(name))\r
679       {\r
680         break;\r
681       }\r
682       else\r
683       {\r
684         sg = null;\r
685       }\r
686     }\r
687 \r
688     if (sg != null)\r
689     {\r
690       String keyValue, key, value;\r
691       while (st.hasMoreTokens())\r
692       {\r
693         keyValue = st.nextToken();\r
694         key = keyValue.substring(0, keyValue.indexOf("="));\r
695         value = keyValue.substring(keyValue.indexOf("=") + 1);\r
696 \r
697         if (key.equalsIgnoreCase("description"))\r
698         {\r
699           sg.setDescription(value);\r
700         }\r
701         else if (key.equalsIgnoreCase("colour"))\r
702         {\r
703           sg.cs = ColourSchemeProperty.getColour(al, value);\r
704         }\r
705         else if (key.equalsIgnoreCase("pidThreshold"))\r
706         {\r
707           sg.cs.setThreshold(Integer.parseInt(value), true);\r
708 \r
709         }\r
710         else if (key.equalsIgnoreCase("consThreshold"))\r
711         {\r
712           sg.cs.setConservationInc(Integer.parseInt(value));\r
713           Conservation c = new Conservation("Group",\r
714                                             ResidueProperties.propHash, 3,\r
715                                             sg.getSequences(null),\r
716                                             sg.getStartRes(),\r
717                                             sg.getEndRes() + 1);\r
718 \r
719           c.calculate();\r
720           c.verdict(false, 25);\r
721 \r
722           sg.cs.setConservation(c);\r
723 \r
724         }\r
725         else if (key.equalsIgnoreCase("outlineColour"))\r
726         {\r
727           sg.setOutlineColour(new UserColourScheme(value).findColour('A'));\r
728         }\r
729         else if (key.equalsIgnoreCase("displayBoxes"))\r
730         {\r
731           sg.setDisplayBoxes(Boolean.valueOf(value).booleanValue());\r
732         }\r
733         else if (key.equalsIgnoreCase("displayText"))\r
734         {\r
735           sg.setDisplayText(Boolean.valueOf(value).booleanValue());\r
736         }\r
737         else if (key.equalsIgnoreCase("colourText"))\r
738         {\r
739           sg.setColourText(Boolean.valueOf(value).booleanValue());\r
740         }\r
741         else if (key.equalsIgnoreCase("textCol1"))\r
742         {\r
743           sg.textColour = new UserColourScheme(value).findColour('A');\r
744         }\r
745         else if (key.equalsIgnoreCase("textCol2"))\r
746         {\r
747           sg.textColour2 = new UserColourScheme(value).findColour('A');\r
748         }\r
749         else if (key.equalsIgnoreCase("textColThreshold"))\r
750         {\r
751           sg.thresholdTextColour = Integer.parseInt(value);\r
752         }\r
753 \r
754         sg.recalcConservation();\r
755       }\r
756     }\r
757   }\r
758 }\r