X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fschemes%2FFeatureColour.java;h=71a89b045936865a9d3f365cf785c7ffcc7c3c9e;hb=8ace2707dd1c5cfbb1688efa265fd0afcec35def;hp=213868be1b85515b4411d41530b5dca1b6abb9e2;hpb=bf0d052fef43e9809b7170dbfd372b3ea116391b;p=jalview.git diff --git a/src/jalview/schemes/FeatureColour.java b/src/jalview/schemes/FeatureColour.java index 213868b..71a89b0 100644 --- a/src/jalview/schemes/FeatureColour.java +++ b/src/jalview/schemes/FeatureColour.java @@ -1,17 +1,56 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ package jalview.schemes; import jalview.api.FeatureColourI; import jalview.datamodel.SequenceFeature; +import jalview.util.ColorUtils; import jalview.util.Format; import java.awt.Color; import java.util.StringTokenizer; /** - * A class that wraps either a simple colour or a graduated colour + * A class that represents a colour scheme for a feature type. Options supported + * are currently + * */ public class FeatureColour implements FeatureColourI { + static final Color DEFAULT_NO_COLOUR = Color.LIGHT_GRAY; + private static final String BAR = "|"; final private Color colour; @@ -20,10 +59,30 @@ public class FeatureColour implements FeatureColourI final private Color maxColour; + /* + * colour to use for colour by attribute when the + * attribute value is absent + */ + final private Color noColour; + + /* + * if true, then colour has a gradient based on a numerical + * range (either feature score, or an attribute value) + */ private boolean graduatedColour; + /* + * if true, colour values are generated from a text string, + * either feature description, or an attribute value + */ private boolean colourByLabel; + /* + * if not null, the value of [attribute, [sub-attribute] ...] + * is used for colourByLabel or graduatedColour + */ + private String[] attributeName; + private float threshold; private float base; @@ -101,11 +160,11 @@ public class FeatureColour implements FeatureColourI /* * only a simple colour specification - parse it */ - Color colour = UserColourScheme.getColourFromString(descriptor); + Color colour = ColorUtils.parseColourString(descriptor); if (colour == null) { - throw new IllegalArgumentException("Invalid colour descriptor: " - + descriptor); + throw new IllegalArgumentException( + "Invalid colour descriptor: " + descriptor); } return new FeatureColour(colour); } @@ -192,9 +251,9 @@ public class FeatureColour implements FeatureColourI FeatureColour featureColour; try { - featureColour = new FeatureColour( - new UserColourScheme(mincol).findColour('A'), - new UserColourScheme(maxcol).findColour('A'), min, max); + Color minColour = ColorUtils.parseColourString(mincol); + Color maxColour = ColorUtils.parseColourString(maxcol); + featureColour = new FeatureColour(minColour, maxColour, min, max); featureColour.setColourByLabel(labelColour); featureColour.setAutoScaled(autoScaled); // add in any additional parameters @@ -215,8 +274,8 @@ public class FeatureColour implements FeatureColourI { if (!ttype.toLowerCase().startsWith("no")) { - System.err.println("Ignoring unrecognised threshold type : " - + ttype); + System.err.println( + "Ignoring unrecognised threshold type : " + ttype); } } } @@ -235,8 +294,8 @@ public class FeatureColour implements FeatureColourI } if (gcol.hasMoreTokens()) { - System.err - .println("Ignoring additional tokens in parameters in graduated colour specification\n"); + System.err.println( + "Ignoring additional tokens in parameters in graduated colour specification\n"); while (gcol.hasMoreTokens()) { System.err.println("|" + gcol.nextToken()); @@ -267,6 +326,7 @@ public class FeatureColour implements FeatureColourI { minColour = Color.WHITE; maxColour = Color.BLACK; + noColour = DEFAULT_NO_COLOUR; minRed = 0f; minGreen = 0f; minBlue = 0f; @@ -277,7 +337,8 @@ public class FeatureColour implements FeatureColourI } /** - * Constructor given a colour range and a score range + * Constructor given a colour range and a score range, defaulting 'no value + * colour' to be the same as minimum colour * * @param low * @param high @@ -286,28 +347,7 @@ public class FeatureColour implements FeatureColourI */ public FeatureColour(Color low, Color high, float min, float max) { - graduatedColour = true; - colour = null; - minColour = low; - maxColour = high; - threshold = Float.NaN; - isHighToLow = min >= max; - minRed = low.getRed() / 255f; - minGreen = low.getGreen() / 255f; - minBlue = low.getBlue() / 255f; - deltaRed = (high.getRed() / 255f) - minRed; - deltaGreen = (high.getGreen() / 255f) - minGreen; - deltaBlue = (high.getBlue() / 255f) - minBlue; - if (isHighToLow) - { - base = max; - range = min - max; - } - else - { - base = min; - range = max - min; - } + this(low, high, low, min, max); } /** @@ -317,9 +357,11 @@ public class FeatureColour implements FeatureColourI */ public FeatureColour(FeatureColour fc) { + graduatedColour = fc.graduatedColour; colour = fc.colour; minColour = fc.minColour; maxColour = fc.maxColour; + noColour = fc.noColour; minRed = fc.minRed; minGreen = fc.minGreen; minBlue = fc.minBlue; @@ -329,15 +371,17 @@ public class FeatureColour implements FeatureColourI base = fc.base; range = fc.range; isHighToLow = fc.isHighToLow; + attributeName = fc.attributeName; setAboveThreshold(fc.isAboveThreshold()); setBelowThreshold(fc.isBelowThreshold()); setThreshold(fc.getThreshold()); setAutoScaled(fc.isAutoScaled()); setColourByLabel(fc.isColourByLabel()); } - + /** * Copy constructor with new min/max ranges + * * @param fc * @param min * @param max @@ -345,10 +389,45 @@ public class FeatureColour implements FeatureColourI public FeatureColour(FeatureColour fc, float min, float max) { this(fc); - graduatedColour = true; updateBounds(min, max); } + public FeatureColour(Color low, Color high, Color noValueColour, + float min, float max) + { + if (low == null) + { + low = Color.white; + } + if (high == null) + { + high = Color.black; + } + graduatedColour = true; + colour = null; + minColour = low; + maxColour = high; + noColour = noValueColour; + threshold = Float.NaN; + isHighToLow = min >= max; + minRed = low.getRed() / 255f; + minGreen = low.getGreen() / 255f; + minBlue = low.getBlue() / 255f; + deltaRed = (high.getRed() / 255f) - minRed; + deltaGreen = (high.getGreen() / 255f) - minGreen; + deltaBlue = (high.getBlue() / 255f) - minBlue; + if (isHighToLow) + { + base = max; + range = min - max; + } + else + { + base = min; + range = max - min; + } + } + @Override public boolean isGraduatedColour() { @@ -387,6 +466,12 @@ public class FeatureColour implements FeatureColourI } @Override + public Color getNoColour() + { + return noColour; + } + + @Override public boolean isColourByLabel() { return colourByLabel; @@ -405,6 +490,7 @@ public class FeatureColour implements FeatureColourI setGraduatedColour(false); } } + @Override public boolean isBelowThreshold() { @@ -474,10 +560,7 @@ public class FeatureColour implements FeatureColourI } /** - * Updates the base and range appropriately for the given minmax range - * - * @param min - * @param max + * {@inheritDoc} */ @Override public void updateBounds(float min, float max) @@ -510,8 +593,10 @@ public class FeatureColour implements FeatureColourI { if (isColourByLabel()) { - return UserColourScheme - .createColourFromName(feature.getDescription()); + String label = attributeName == null ? feature.getDescription() + : feature.getValueAsString(attributeName); + return label == null ? noColour : ColorUtils + .createColourFromName(label); } if (!isGraduatedColour()) @@ -519,15 +604,41 @@ public class FeatureColour implements FeatureColourI return getColour(); } - // todo should we check for above/below threshold here? - if (range == 0.0) + /* + * graduated colour case, optionally with threshold + * may be based on feature score on an attribute value + * Float.NaN is assigned minimum visible score colour + * no such attribute is assigned the 'no value' colour + */ + float scr = feature.getScore(); + if (attributeName != null) { - return getMaxColour(); + try + { + String attVal = feature.getValueAsString(attributeName); + scr = Float.valueOf(attVal); + } catch (Throwable e) + { + scr = Float.NaN; + } } - float scr = feature.getScore(); if (Float.isNaN(scr)) { - return getMinColour(); + return noColour; + } + + if (isAboveThreshold() && scr <= threshold) + { + return null; + } + + if (isBelowThreshold() && scr >= threshold) + { + return null; + } + if (range == 0.0) + { + return getMaxColour(); } float scl = (scr - base) / range; if (isHighToLow) @@ -542,7 +653,8 @@ public class FeatureColour implements FeatureColourI { scl = 1f; } - return new Color(minRed + scl * deltaRed, minGreen + scl * deltaGreen, minBlue + scl * deltaBlue); + return new Color(minRed + scl * deltaRed, minGreen + scl * deltaGreen, + minBlue + scl * deltaBlue); } /** @@ -569,44 +681,6 @@ public class FeatureColour implements FeatureColourI return (isHighToLow) ? (base + range) : base; } - /** - * Answers true if the feature has a simple colour, or is coloured by label, - * or has a graduated colour and the score of this feature instance is within - * the range to render (if any), i.e. does not lie below or above any - * threshold set. - * - * @param feature - * @return - */ - @Override - public boolean isColored(SequenceFeature feature) - { - if (isColourByLabel() || !isGraduatedColour()) - { - return true; - } - - float val = feature.getScore(); - if (Float.isNaN(val)) - { - return true; - } - if (Float.isNaN(this.threshold)) - { - return true; - } - - if (isAboveThreshold() && val <= threshold) - { - return false; - } - if (isBelowThreshold() && val >= threshold) - { - return false; - } - return true; - } - @Override public boolean isSimpleColour() { @@ -669,4 +743,22 @@ public class FeatureColour implements FeatureColourI return String.format("%s\t%s", featureType, colourString); } + @Override + public boolean isColourByAttribute() + { + return attributeName != null; + } + + @Override + public String[] getAttributeName() + { + return attributeName; + } + + @Override + public void setAttributeName(String... name) + { + attributeName = name; + } + }