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