Merge branch 'develop' into bug/JAL-1608createGroups
[jalview.git] / test / jalview / schemes / AnnotationColourGradientTest.java
diff --git a/test/jalview/schemes/AnnotationColourGradientTest.java b/test/jalview/schemes/AnnotationColourGradientTest.java
new file mode 100644 (file)
index 0000000..1c93856
--- /dev/null
@@ -0,0 +1,300 @@
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.GraphLine;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import java.awt.Color;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class AnnotationColourGradientTest
+{
+  final static int WIDTH = 11;
+
+  final static int THRESHOLD_FIVE = 5;
+
+  private AlignmentAnnotation ann;
+
+  private SequenceI seq;
+
+  private AlignmentI al;
+
+  Color minColour = new Color(50, 200, 150);
+
+  Color maxColour = new Color(150, 100, 250);
+
+  /**
+   * Setup creates an annotation over 11 columns with values 0-10 and threshold
+   * 5
+   */
+  @BeforeClass(alwaysRun = true)
+  public void setUp()
+  {
+    Annotation[] anns = new Annotation[WIDTH];
+    /*
+     * set annotations with values 0-10, graded colours
+     */
+    for (int col = 0; col < WIDTH; col++)
+    {
+      int hue = col * 20;
+      Color colour = new Color(hue, hue, hue);
+      anns[col] = new Annotation("a", "a", 'a', col, colour);
+    }
+
+    seq = new Sequence("", "");
+    al = new Alignment(new SequenceI[]{ seq});
+    
+    /*
+     * AlignmentAnnotation constructor works out min-max range
+     */
+    ann = new AlignmentAnnotation("", "", anns);
+    ann.setThreshold(new GraphLine(THRESHOLD_FIVE, "", Color.RED));
+    seq.addAlignmentAnnotation(ann);
+  }
+
+  @Test(groups = "Functional")
+  public void testShadeCalculation_noThreshold()
+  {
+    AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+            minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
+    for (int col = 0; col < WIDTH; col++)
+    {
+      Color result = testee.shadeCalculation(ann, col);
+      /*
+       * column <n> is n/10 of the way from minCol to maxCol
+       */
+      Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+              150 + 10 * col);
+      assertEquals(result, expected, "for column " + col);
+    }
+  }
+
+  /**
+   * Test the 'colour above threshold' case
+   */
+  @Test(groups = "Functional")
+  public void testShadeCalculation_aboveThreshold()
+  {
+    AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+            minColour, maxColour, AnnotationColourGradient.ABOVE_THRESHOLD);
+    for (int col = 0; col < WIDTH; col++)
+    {
+      Color result = testee.shadeCalculation(ann, col);
+      /*
+       * colour is derived regardless of the threshold value 
+       * (the renderer will suppress colouring if above/below threshold)
+       */
+      Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+              150 + 10 * col);
+      assertEquals(result, expected, "for column " + col);
+    }
+
+    /*
+     * now make 6-10 the span of the colour range
+     * (annotation value == column number in this test)
+     */
+    testee.setThresholdIsMinMax(true);
+    for (int col = 0; col < THRESHOLD_FIVE; col++)
+    {
+      /*
+       * colours below the threshold are computed as before
+       */
+      Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+              150 + 10 * col);
+      Color result = testee.shadeCalculation(ann, col);
+      assertEquals(result, expected, "for column " + col);
+    }
+    for (int col = THRESHOLD_FIVE; col < WIDTH; col++)
+    {
+      /*
+       * colours for values >= threshold are graduated
+       * range is 6-10 so steps of 100/5 = 20
+       */
+      int factor = col - THRESHOLD_FIVE;
+      Color expected = new Color(50 + 20 * factor, 200 - 20 * factor,
+              150 + 20 * factor);
+      Color result = testee.shadeCalculation(ann, col);
+      assertEquals(result, expected, "for column " + col);
+    }
+  }
+
+  /**
+   * Test the 'colour below threshold' case
+   */
+  @Test(groups = "Functional")
+  public void testShadeCalculation_belowThreshold()
+  {
+    AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+            minColour, maxColour, AnnotationColourGradient.BELOW_THRESHOLD);
+
+    for (int col = 0; col < WIDTH; col++)
+    {
+      Color result = testee.shadeCalculation(ann, col);
+      /*
+       * colour is derived regardless of the threshold value 
+       * (the renderer will suppress colouring if above/below threshold)
+       */
+      Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+              150 + 10 * col);
+      assertEquals(result, expected, "for column " + col);
+    }
+
+    /*
+     * now make 0-5 the span of the colour range
+     * (annotation value == column number in this test)
+     */
+    testee.setThresholdIsMinMax(true);
+    for (int col = THRESHOLD_FIVE + 1; col < WIDTH; col++)
+    {
+      /*
+       * colours above the threshold are computed as before
+       */
+      Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+              150 + 10 * col);
+      Color result = testee.shadeCalculation(ann, col);
+      assertEquals(result, expected, "for column " + col);
+    }
+
+    for (int col = 0; col <= THRESHOLD_FIVE; col++)
+    {
+      /*
+       * colours for values <= threshold are graduated
+       * range is 0-5 so steps of 100/5 = 20
+       */
+      Color expected = new Color(50 + 20 * col, 200 - 20 * col,
+              150 + 20 * col);
+      Color result = testee.shadeCalculation(ann, col);
+      assertEquals(result, expected, "for column " + col);
+    }
+  }
+
+  /**
+   * Test the 'colour above threshold' case
+   */
+  @Test(groups = "Functional")
+  public void testFindColour_aboveThreshold()
+  {
+    AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+            minColour, maxColour, AnnotationColourGradient.ABOVE_THRESHOLD);
+    testee = (AnnotationColourGradient) testee.getInstance(al, null);
+
+    for (int col = 0; col < WIDTH; col++)
+    {
+      Color result = testee.findColour('a', col, seq);
+      /*
+       * expect white below threshold of 5
+       */
+      Color expected = col < 5 ? Color.white : new Color(50 + 10 * col,
+              200 - 10 * col,
+              150 + 10 * col);
+      assertEquals(result, expected, "for column " + col);
+    }
+  
+    /*
+     * now make 6-10 the span of the colour range
+     * (annotation value == column number in this test)
+     */
+    testee.setThresholdIsMinMax(true);
+    for (int col = 0; col < WIDTH; col++)
+    {
+      /*
+       * colours for values >= threshold are graduated
+       * range is 6-10 so steps of 100/5 = 20
+       */
+      int factor = col - THRESHOLD_FIVE;
+      Color expected = col < 5 ? Color.white : new Color(50 + 20 * factor,
+              200 - 20 * factor,
+              150 + 20 * factor);
+      Color result = testee.findColour('a', col, seq);
+      assertEquals(result, expected, "for column " + col);
+    }
+  }
+
+  /**
+   * Test the 'colour below threshold' case
+   */
+  @Test(groups = "Functional")
+  public void testFindColour_belowThreshold()
+  {
+    AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+            minColour, maxColour, AnnotationColourGradient.BELOW_THRESHOLD);
+    testee = (AnnotationColourGradient) testee.getInstance(al, null);
+  
+    for (int col = 0; col < WIDTH; col++)
+    {
+      Color result = testee.findColour('a', col, seq);
+      Color expected = col > 5 ? Color.white : new Color(50 + 10 * col,
+              200 - 10 * col, 150 + 10 * col);
+      assertEquals(result, expected, "for column " + col);
+    }
+  
+    /*
+     * now make 0-5 the span of the colour range
+     * (annotation value == column number in this test)
+     */
+    testee.setThresholdIsMinMax(true);
+    for (int col = 0; col < WIDTH; col++)
+    {
+      /*
+       * colours for values <= threshold are graduated
+       * range is 0-5 so steps of 100/5 = 20
+       */
+      Color expected = col > 5 ? Color.white : new Color(50 + 20 * col,
+              200 - 20 * col, 150 + 20 * col);
+      Color result = testee.findColour('a', col, seq);
+      assertEquals(result, expected, "for column " + col);
+    }
+  }
+
+  @Test(groups = "Functional")
+  public void testFindColour_noThreshold()
+  {
+    AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+            minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
+    testee = (AnnotationColourGradient) testee.getInstance(al, null);
+
+    for (int col = 0; col < WIDTH; col++)
+    {
+      Color result = testee.findColour('a', col, seq);
+      /*
+       * column <n> is n/10 of the way from minCol to maxCol
+       */
+      Color expected = new Color(50 + 10 * col, 200 - 10 * col,
+              150 + 10 * col);
+      assertEquals(result, expected, "for column " + col);
+    }
+  }
+
+  @Test(groups = "Functional")
+  public void testFindColour_originalColours()
+  {
+    AnnotationColourGradient testee = new AnnotationColourGradient(ann,
+            minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
+    testee = (AnnotationColourGradient) testee.getInstance(al, null);
+
+    /*
+     * flag corresponding to 'use original colours' checkbox
+     * - just use the individual annotation colours
+     */
+    testee.setPredefinedColours(true);
+
+    /*
+     * the annotation colour is returned, except for column 0 where it is
+     * black - in this case the colour scheme colour overrides it
+     */
+    for (int col = 0; col < WIDTH; col++)
+    {
+      int hue = col * 20;
+      Color c = col == 0 ? minColour : new Color(hue, hue, hue);
+      assertEquals(testee.findColour('a', col, seq), c, "for column " + col);
+    }
+  }
+}