boolean hasThreshold();
/**
- * Returns the computed colour for the given sequence feature
+ * Returns the computed colour for the given sequence feature. Answers null if
+ * the score of this feature instance is outside the range to render (if any),
+ * i.e. lies below or above a configured threshold.
*
* @param feature
* @return
Color getColor(SequenceFeature feature);
/**
- * 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
- */
- boolean isColored(SequenceFeature feature);
-
- /**
* Update the min-max range for a graduated colour scheme
*
* @param min
float mm[] = fr.getMinMax().get(type)[0];
min = mm[0];
max = mm[1];
+ threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
oldcs = fr.getFeatureColours().get(type);
if (oldcs.isGraduatedColour())
{
+ threshline.value = oldcs.getThreshold();
cs = new FeatureColour((FeatureColour) oldcs, min, max);
}
else
thresholdValue.setText("");
}
- else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
- && threshline == null)
- {
- // todo visual indication of feature threshold
- threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
- "Threshold", Color.black);
- }
-
if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
{
adjusting = true;
// initialise threshold slider and selector
threshold.setSelectedIndex(cs.isAboveThreshold() ? 1 : 2);
slider.setEnabled(true);
+ slider.setValue((int) (cs.getThreshold() * scaleFactor));
thresholdValue.setEnabled(true);
threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
-
+ threshline.value = cs.getThreshold();
}
adjusting = false;
for (SequenceFeature sf : overlaps)
{
Color featureColour = fc.getColor(sf);
+ if (featureColour == null)
+ {
+ // score feature outwith threshold for colouring
+ continue;
+ }
/*
* if feature starts/ends outside the visible range,
int featureEndCol = sf.begin == sf.end ? featureStartCol : seq
.findIndex(visibleEnd);
- if (sf.isContactFeature())
+ // Color featureColour = getColour(sequenceFeature);
+
+ boolean isContactFeature = sf.isContactFeature();
+
+ if (isContactFeature)
{
boolean drawn = renderFeature(g, seq, featureStartCol - 1,
featureStartCol - 1, featureColour, start, end, y1,
drawnColour = featureColour;
}
}
- else if (showFeature(sf))
+ else
{
/*
* showing feature score by height of colour
{
if (!featureGroupNotShown(sequenceFeature))
{
- return getColour(sequenceFeature);
+ Color col = getColour(sequenceFeature);
+ if (col != null)
+ {
+ return col;
+ }
}
}
}
return getColour();
}
- // todo should we check for above/below threshold here?
+ /*
+ * graduated colour case, optionally with threshold
+ * (treating Float.NaN as within visible range here)
+ */
+ float scr = feature.getScore();
+ if (isAboveThreshold() && scr <= threshold)
+ {
+ return null;
+ }
+ if (isBelowThreshold() && scr >= threshold)
+ {
+ return null;
+ }
if (range == 0.0)
{
return getMaxColour();
}
- float scr = feature.getScore();
if (Float.isNaN(scr))
{
return getMinColour();
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()
{
* Returns the configured colour for a particular feature instance. This
* includes calculation of 'colour by label', or of a graduated score colour,
* if applicable. It does not take into account feature visibility or colour
- * transparency.
+ * transparency. Returns null for a score feature whose score value lies
+ * outside any colour threshold.
*
* @param feature
* @return
}
/**
- * Answers true unless the feature has a graduated colour scheme and the
- * feature value lies outside the current threshold for display
- *
- * @param sequenceFeature
- * @return
- */
- protected boolean showFeature(SequenceFeature sequenceFeature)
- {
- FeatureColourI fc = getFeatureStyle(sequenceFeature.type);
- return fc.isColored(sequenceFeature);
- }
-
- /**
* Answers true if the feature type is currently selected to be displayed,
* else false
*
FeatureColourFinder finder2 = new FeatureColourFinder(null);
assertTrue(finder2.noFeaturesDisplayed());
}
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_graduatedWithThreshold()
+ {
+ seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
+ 2, 0f, "KdGroup"));
+ seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 4,
+ 4, 5f, "KdGroup"));
+ seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 7,
+ 7, 10f, "KdGroup"));
+
+ /*
+ * graduated colour from 0 to 10
+ * above threshold value of 5
+ */
+ Color min = new Color(100, 50, 150);
+ Color max = new Color(200, 0, 100);
+ FeatureColourI fc = new FeatureColour(min, max, 0, 10);
+ fc.setAboveThreshold(true);
+ fc.setThreshold(5f);
+ fr.setColour("kd", fc);
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+
+ /*
+ * position 2, column 1, score 0 - below threshold - default colour
+ */
+ Color c = finder.findFeatureColour(Color.blue, seq, 1);
+ assertEquals(c, Color.blue);
+
+ /*
+ * position 4, column 3, score 5 - at threshold - default colour
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 3);
+ assertEquals(c, Color.blue);
+
+ /*
+ * position 7, column 9, score 10 - maximum colour in range
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 9);
+ assertEquals(c, max);
+
+ /*
+ * now colour below threshold of 5
+ */
+ fc.setBelowThreshold(true);
+
+ /*
+ * position 2, column 1, score 0 - min colour
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 1);
+ assertEquals(c, min);
+
+ /*
+ * position 4, column 3, score 5 - at threshold - default colour
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 3);
+ assertEquals(c, Color.blue);
+
+ /*
+ * position 7, column 9, score 10 - above threshold - default colour
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 9);
+ assertEquals(c, Color.blue);
+ }
}
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;
}
@Test(groups = { "Functional" })
- public void testIsColored_simpleColour()
- {
- FeatureColour fc = new FeatureColour(Color.RED);
- assertTrue(fc
- .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
- }
-
- @Test(groups = { "Functional" })
- public void testIsColored_colourByLabel()
- {
- FeatureColour fc = new FeatureColour();
- fc.setColourByLabel(true);
- assertTrue(fc
- .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
- }
-
- @Test(groups = { "Functional" })
- public void testIsColored_aboveThreshold()
- {
- // graduated colour range from score 20 to 100
- FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 20f,
- 100f);
-
- // score 0 is adjusted to bottom of range
- SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 0f,
- null);
- assertTrue(fc.isColored(sf));
- assertEquals(Color.WHITE, fc.getColor(sf));
-
- // score 120 is adjusted to top of range
- sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
- sf.getFeatureGroup(), 120f);
- assertEquals(Color.BLACK, fc.getColor(sf));
-
- // value below threshold is still rendered
- // setting threshold has no effect yet...
- fc.setThreshold(60f);
- sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
- sf.getFeatureGroup(), 36f);
- assertTrue(fc.isColored(sf));
- assertEquals(new Color(204, 204, 204), fc.getColor(sf));
-
- // now apply threshold:
- fc.setAboveThreshold(true);
- assertFalse(fc.isColored(sf));
- // colour is still returned though ?!?
- assertEquals(new Color(204, 204, 204), fc.getColor(sf));
-
- sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
- sf.getFeatureGroup(), 84f);
- // above threshold now
- assertTrue(fc.isColored(sf));
- assertEquals(new Color(51, 51, 51), fc.getColor(sf));
- }
-
- @Test(groups = { "Functional" })
public void testGetColor_simpleColour()
{
FeatureColour fc = new FeatureColour(Color.RED);
}
@Test(groups = { "Functional" })
- public void testGetColor_belowThreshold()
+ public void testGetColor_aboveBelowThreshold()
{
// gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0)
FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f,
SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f,
null);
fc.setThreshold(100f); // ignore for now
- assertTrue(fc.isColored(sf));
assertEquals(new Color(204, 204, 204), fc.getColor(sf));
fc.setAboveThreshold(true); // feature lies below threshold
- assertFalse(fc.isColored(sf));
- assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+ assertNull(fc.getColor(sf));
+
+ fc.setBelowThreshold(true);
+ fc.setThreshold(70f);
+ assertNull(fc.getColor(sf)); // feature score == threshold - hidden
+ fc.setThreshold(69f);
+ assertNull(fc.getColor(sf)); // feature score > threshold - hidden
}
/**