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("Seq", ""); 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 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 for boundary case threshold == graphMax (JAL-3206) */ float thresh = ann.threshold.value; ann.threshold.value = ann.graphMax; Color result = testee.shadeCalculation(ann, WIDTH - 1); assertEquals(result, maxColour); testee.setThresholdIsMinMax(false); result = testee.shadeCalculation(ann, WIDTH - 1); assertEquals(result, maxColour); ann.threshold.value = thresh; // reset } /** * 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 for boundary case threshold == graphMin (JAL-3206) */ float thresh = ann.threshold.value; ann.threshold.value = ann.graphMin; Color result = testee.shadeCalculation(ann, 0); assertEquals(result, minColour); testee.setThresholdIsMinMax(false); result = testee.shadeCalculation(ann, 0); assertEquals(result, minColour); ann.threshold.value = thresh; // reset } /** * 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 at or 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 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); } } }