+ * Parses a Jalview features file format colour descriptor
+ * [label|][mincolour|maxcolour
+ * |[absolute|]minvalue|maxvalue|thresholdtype|thresholdvalue] Examples:
+ * <ul>
+ * <li>red</li>
+ * <li>a28bbb</li>
+ * <li>25,125,213</li>
+ * <li>label</li>
+ * <li>label|||0.0|0.0|above|12.5</li>
+ * <li>label|||0.0|0.0|below|12.5</li>
+ * <li>red|green|12.0|26.0|none</li>
+ * <li>a28bbb|3eb555|12.0|26.0|above|12.5</li>
+ * <li>a28bbb|3eb555|abso|12.0|26.0|below|12.5</li>
+ * </ul>
+ *
+ * @param descriptor
+ * @return
+ * @throws IllegalArgumentException
+ * if not parseable
+ */
+ public static FeatureColour parseJalviewFeatureColour(String descriptor)
+ {
+ StringTokenizer gcol = new StringTokenizer(descriptor, "|", true);
+ float min = Float.MIN_VALUE;
+ float max = Float.MAX_VALUE;
+ boolean labelColour = false;
+
+ String mincol = gcol.nextToken();
+ if (mincol == "|")
+ {
+ throw new IllegalArgumentException(
+ "Expected either 'label' or a colour specification in the line: "
+ + descriptor);
+ }
+ String maxcol = null;
+ if (mincol.toLowerCase().indexOf("label") == 0)
+ {
+ labelColour = true;
+ mincol = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ // skip '|'
+ mincol = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
+ }
+
+ if (!labelColour && !gcol.hasMoreTokens())
+ {
+ /*
+ * only a simple colour specification - parse it
+ */
+ Color colour = UserColourScheme.getColourFromString(descriptor);
+ if (colour == null)
+ {
+ throw new IllegalArgumentException("Invalid colour descriptor: "
+ + descriptor);
+ }
+ return new FeatureColour(colour);
+ }
+
+ /*
+ * autoScaled == true: colours range over actual score range
+ * autoScaled == false ('abso'): colours range over min/max range
+ */
+ boolean autoScaled = true;
+ String tok = null, minval, maxval;
+ if (mincol != null)
+ {
+ // at least four more tokens
+ if (mincol.equals("|"))
+ {
+ mincol = "";
+ }
+ else
+ {
+ gcol.nextToken(); // skip next '|'
+ }
+ maxcol = gcol.nextToken();
+ if (maxcol.equals("|"))
+ {
+ maxcol = "";
+ }
+ else
+ {
+ gcol.nextToken(); // skip next '|'
+ }
+ tok = gcol.nextToken();
+ gcol.nextToken(); // skip next '|'
+ if (tok.toLowerCase().startsWith("abso"))
+ {
+ minval = gcol.nextToken();
+ gcol.nextToken(); // skip next '|'
+ autoScaled = false;
+ }
+ else
+ {
+ minval = tok;
+ }
+ maxval = gcol.nextToken();
+ if (gcol.hasMoreTokens())
+ {
+ gcol.nextToken(); // skip next '|'
+ }
+ try
+ {
+ if (minval.length() > 0)
+ {
+ min = new Float(minval).floatValue();
+ }
+ } catch (Exception e)
+ {
+ throw new IllegalArgumentException(
+ "Couldn't parse the minimum value for graduated colour ("
+ + descriptor + ")");
+ }
+ try
+ {
+ if (maxval.length() > 0)
+ {
+ max = new Float(maxval).floatValue();
+ }
+ } catch (Exception e)
+ {
+ throw new IllegalArgumentException(
+ "Couldn't parse the maximum value for graduated colour ("
+ + descriptor + ")");
+ }
+ }
+ else
+ {
+ // add in some dummy min/max colours for the label-only
+ // colourscheme.
+ mincol = "FFFFFF";
+ maxcol = "000000";
+ }
+
+ /*
+ * construct the FeatureColour
+ */
+ FeatureColour featureColour;
+ try
+ {
+ featureColour = new FeatureColour(
+ new UserColourScheme(mincol).findColour('A'),
+ new UserColourScheme(maxcol).findColour('A'), min, max);
+ featureColour.setColourByLabel(labelColour);
+ featureColour.setAutoScaled(autoScaled);
+ // add in any additional parameters
+ String ttype = null, tval = null;
+ if (gcol.hasMoreTokens())
+ {
+ // threshold type and possibly a threshold value
+ ttype = gcol.nextToken();
+ if (ttype.toLowerCase().startsWith("below"))
+ {
+ featureColour.setBelowThreshold(true);
+ }
+ else if (ttype.toLowerCase().startsWith("above"))
+ {
+ featureColour.setAboveThreshold(true);
+ }
+ else
+ {
+ if (!ttype.toLowerCase().startsWith("no"))
+ {
+ System.err.println("Ignoring unrecognised threshold type : "
+ + ttype);
+ }
+ }
+ }
+ if (featureColour.hasThreshold())
+ {
+ try
+ {
+ gcol.nextToken();
+ tval = gcol.nextToken();
+ featureColour.setThreshold(new Float(tval).floatValue());
+ } catch (Exception e)
+ {
+ System.err.println("Couldn't parse threshold value as a float: ("
+ + tval + ")");
+ }
+ }
+ if (gcol.hasMoreTokens())
+ {
+ System.err
+ .println("Ignoring additional tokens in parameters in graduated colour specification\n");
+ while (gcol.hasMoreTokens())
+ {
+ System.err.println("|" + gcol.nextToken());
+ }
+ System.err.println("\n");
+ }
+ return featureColour;
+ } catch (Exception e)
+ {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+
+ /**