1 package jalview.renderer.seqfeatures;
3 import static org.testng.Assert.assertEquals;
4 import static org.testng.Assert.assertFalse;
5 import static org.testng.Assert.assertTrue;
7 import jalview.api.FeatureColourI;
8 import jalview.datamodel.SequenceFeature;
9 import jalview.datamodel.SequenceI;
10 import jalview.gui.AlignFrame;
11 import jalview.gui.AlignViewport;
12 import jalview.gui.FeatureRenderer;
13 import jalview.io.DataSourceType;
14 import jalview.io.FileLoader;
15 import jalview.schemes.FeatureColour;
17 import java.awt.Color;
19 import org.testng.annotations.BeforeMethod;
20 import org.testng.annotations.BeforeTest;
21 import org.testng.annotations.Test;
24 * Unit tests for feature colour determination, including but not limited to
26 * <li>gap position</li>
27 * <li>no features present</li>
28 * <li>features present but show features turned off</li>
29 * <li>features displayed but selected feature turned off</li>
30 * <li>features displayed but feature group turned off</li>
31 * <li>feature displayed but none at the specified position</li>
32 * <li>multiple features at position, with no transparency</li>
33 * <li>multiple features at position, with transparency</li>
34 * <li>score graduated feature colour</li>
35 * <li>contact feature start at the selected position</li>
36 * <li>contact feature end at the selected position</li>
37 * <li>contact feature straddling the selected position (not shown)</li>
40 public class FeatureColourFinderTest
42 private AlignViewport av;
44 private SequenceI seq;
46 private FeatureColourFinder finder;
48 private AlignFrame af;
50 private FeatureRenderer fr;
52 @BeforeTest(alwaysRun = true)
55 // aligned column 8 is sequence position 6
56 String s = ">s1\nABCDE---FGHIJKLMNOPQRSTUVWXYZ\n";
57 af = new FileLoader().LoadFileWaitTillLoaded(s,
58 DataSourceType.PASTE);
59 av = af.getViewport();
60 seq = av.getAlignment().getSequenceAt(0);
61 fr = af.getFeatureRenderer();
62 finder = new FeatureColourFinder(fr);
66 * Clear down any sequence features before each test (not as easy as it
69 @BeforeMethod(alwaysRun = true)
70 public void setUpBeforeTest()
72 SequenceFeature[] sfs = seq.getSequenceFeatures();
75 for (SequenceFeature sf : sfs)
77 seq.deleteFeature(sf);
80 fr.findAllFeatures(true);
83 * reset all feature groups to visible
85 for (String group : fr.getGroups(false))
87 fr.setGroupVisibility(group, true);
90 fr.clearRenderOrder();
91 av.setShowSequenceFeatures(true);
94 @Test(groups = "Functional")
95 public void testFindFeatureColour_noFeatures()
97 av.setShowSequenceFeatures(false);
98 Color c = finder.findFeatureColour(Color.blue, seq, 10);
99 assertEquals(c, Color.blue);
101 av.setShowSequenceFeatures(true);
102 c = finder.findFeatureColour(Color.blue, seq, 10);
103 assertEquals(c, Color.blue);
106 @Test(groups = "Functional")
107 public void testFindFeatureColour_noFeaturesShown()
109 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
110 Float.NaN, "MetalGroup"));
112 av.setShowSequenceFeatures(false);
113 Color c = finder.findFeatureColour(Color.blue, seq, 10);
114 assertEquals(c, Color.blue);
117 @Test(groups = "Functional")
118 public void testFindFeatureColour_singleFeatureAtPosition()
120 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
121 Float.NaN, "MetalGroup"));
122 fr.setColour("Metal", new FeatureColour(Color.red));
124 av.setShowSequenceFeatures(true);
125 Color c = finder.findFeatureColour(Color.blue, seq, 10);
126 assertEquals(c, Color.red);
129 @Test(groups = "Functional")
130 public void testFindFeatureColour_gapPosition()
132 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, 0f,
134 fr.setColour("Metal", new FeatureColour(Color.red));
136 av.setShowSequenceFeatures(true);
137 Color c = finder.findFeatureColour(null, seq, 6);
138 assertEquals(c, Color.white);
141 @Test(groups = "Functional")
142 public void testFindFeatureColour_multipleFeaturesAtPositionNoTransparency()
145 * featuresAdded -> FeatureRendererModel.updateRenderOrder which adds any
146 * new features 'on top' (but reverses the order of any added features)
148 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
149 Float.NaN, "MetalGroup"));
150 FeatureColour red = new FeatureColour(Color.red);
151 fr.setColour("Metal", red);
153 seq.addSequenceFeature(new SequenceFeature("Domain", "Domain", 4, 15,
154 Float.NaN, "DomainGroup"));
155 FeatureColour green = new FeatureColour(Color.green);
156 fr.setColour("Domain", green);
158 av.setShowSequenceFeatures(true);
161 * expect Domain (green) to be rendered above Metal (red)
163 Color c = finder.findFeatureColour(Color.blue, seq, 10);
164 assertEquals(c, Color.green);
167 * now promote Metal above Domain
168 * - currently no way other than mimicking reordering of
169 * table in Feature Settings
171 Object[][] data = new Object[2][];
172 data[0] = new Object[] { "Metal", red, true };
173 data[1] = new Object[] { "Domain", green, true };
174 fr.setFeaturePriority(data);
175 c = finder.findFeatureColour(Color.blue, seq, 10);
176 assertEquals(c, Color.red);
179 * ..and turn off display of Metal
182 fr.setFeaturePriority(data);
183 c = finder.findFeatureColour(Color.blue, seq, 10);
184 assertEquals(c, Color.green);
187 @Test(groups = "Functional")
188 public void testFindFeatureColour_singleFeatureNotAtPosition()
190 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 8, 12,
191 Float.NaN, "MetalGroup"));
192 fr.setColour("Metal", new FeatureColour(Color.red));
194 av.setShowSequenceFeatures(true);
195 // column 2 = sequence position 3
196 Color c = finder.findFeatureColour(Color.blue, seq, 2);
197 assertEquals(c, Color.blue);
200 @Test(groups = "Functional")
201 public void testFindFeatureColour_featureTypeNotDisplayed()
203 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
204 Float.NaN, "MetalGroup"));
205 FeatureColour red = new FeatureColour(Color.red);
206 fr.setColour("Metal", red);
208 av.setShowSequenceFeatures(true);
209 Color c = finder.findFeatureColour(Color.blue, seq, 10);
210 assertEquals(c, Color.red);
213 * turn off display of Metal - is this the easiest way to do it??
215 Object[][] data = new Object[1][];
216 data[0] = new Object[] { "Metal", red, false };
217 fr.setFeaturePriority(data);
218 c = finder.findFeatureColour(Color.blue, seq, 10);
219 assertEquals(c, Color.blue);
222 * turn display of Metal back on
224 data[0] = new Object[] { "Metal", red, true };
225 fr.setFeaturePriority(data);
226 c = finder.findFeatureColour(Color.blue, seq, 10);
227 assertEquals(c, Color.red);
230 @Test(groups = "Functional")
231 public void testFindFeatureColour_featureGroupNotDisplayed()
233 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
234 Float.NaN, "MetalGroup"));
235 FeatureColour red = new FeatureColour(Color.red);
236 fr.setColour("Metal", red);
238 av.setShowSequenceFeatures(true);
239 Color c = finder.findFeatureColour(Color.blue, seq, 10);
240 assertEquals(c, Color.red);
243 * turn off display of MetalGroup
245 fr.setGroupVisibility("MetalGroup", false);
246 c = finder.findFeatureColour(Color.blue, seq, 10);
247 assertEquals(c, Color.blue);
250 * turn display of MetalGroup back on
252 fr.setGroupVisibility("MetalGroup", true);
253 c = finder.findFeatureColour(Color.blue, seq, 10);
254 assertEquals(c, Color.red);
257 @Test(groups = "Functional")
258 public void testFindFeatureColour_contactFeature()
261 * currently contact feature == type "Disulphide Bond" or "Disulfide Bond" !!
263 seq.addSequenceFeature(new SequenceFeature("Disulphide Bond",
264 "Contact", 2, 12, Float.NaN, "Disulphide"));
265 fr.setColour("Disulphide Bond", new FeatureColour(Color.red));
267 av.setShowSequenceFeatures(true);
270 * Contact positions are residues 2 and 12
271 * which are columns 1 and 14
272 * positions in between don't count for a contact feature!
274 Color c = finder.findFeatureColour(Color.blue, seq, 10);
275 assertEquals(c, Color.blue);
276 c = finder.findFeatureColour(Color.blue, seq, 8);
277 assertEquals(c, Color.blue);
278 c = finder.findFeatureColour(Color.blue, seq, 1);
279 assertEquals(c, Color.red);
280 c = finder.findFeatureColour(Color.blue, seq, 14);
281 assertEquals(c, Color.red);
284 @Test(groups = "Functional")
285 public void testFindFeatureColour_graduatedFeatureColour()
287 seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
289 seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 4,
291 seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 7,
295 * graduated colour from 0 to 10
297 Color min = new Color(100, 50, 150);
298 Color max = new Color(200, 0, 100);
299 FeatureColourI fc = new FeatureColour(min, max, 0, 10);
300 fr.setColour("kd", fc);
302 av.setShowSequenceFeatures(true);
305 * position 2, column 1, score 0 - minimum colour in range
307 Color c = finder.findFeatureColour(Color.blue, seq, 1);
308 assertEquals(c, min);
311 * position 7, column 9, score 10 - maximum colour in range
313 c = finder.findFeatureColour(Color.blue, seq, 9);
314 assertEquals(c, max);
317 * position 4, column 3, score 5 - half way from min to max
319 c = finder.findFeatureColour(Color.blue, seq, 3);
320 assertEquals(c, new Color(150, 25, 125));
323 @Test(groups = "Functional")
324 public void testFindFeatureColour_transparencySingleFeature()
326 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
327 Float.NaN, "MetalGroup"));
328 FeatureColour red = new FeatureColour(Color.red);
329 fr.setColour("Metal", red);
331 av.setShowSequenceFeatures(true);
334 * the FeatureSettings transparency slider has range 0-70 which
335 * corresponds to a transparency value of 1 - 0.3
336 * A value of 0.4 gives a combination of
337 * 0.4 * red(255, 0, 0) + 0.6 * cyan(0, 255, 255) = (102, 153, 153)
339 fr.setTransparency(0.4f);
340 Color c = finder.findFeatureColour(Color.cyan, seq, 10);
341 assertEquals(c, new Color(102, 153, 153));
344 @Test(groups = "Functional")
345 public void testFindFeatureColour_transparencyTwoFeatures()
347 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
348 Float.NaN, "MetalGroup"));
349 FeatureColour red = new FeatureColour(Color.red);
350 fr.setColour("Metal", red);
352 seq.addSequenceFeature(new SequenceFeature("Domain", "Domain", 4, 15,
353 Float.NaN, "DomainGroup"));
354 FeatureColour green = new FeatureColour(Color.green);
355 fr.setColour("Domain", green);
357 av.setShowSequenceFeatures(true);
360 * Domain (green) rendered above Metal (red) above background (cyan)
361 * 1) 0.6 * red(255, 0, 0) + 0.4 * cyan(0, 255, 255) = (153, 102, 102)
362 * 2) 0.6* green(0, 255, 0) + 0.4 * (153, 102, 102) = (61, 194, 41) rounded
364 fr.setTransparency(0.6f);
365 Color c = finder.findFeatureColour(Color.cyan, seq, 10);
366 assertEquals(c, new Color(61, 194, 41));
369 * now promote Metal above Domain
370 * - currently no way other than mimicking reordering of
371 * table in Feature Settings
372 * Metal (red) rendered above Domain (green) above background (cyan)
373 * 1) 0.6 * green(0, 255, 0) + 0.4 * cyan(0, 255, 255) = (0, 255, 102)
374 * 2) 0.6* red(255, 0, 0) + 0.4 * (0, 255, 102) = (153, 102, 41) rounded
376 Object[][] data = new Object[2][];
377 data[0] = new Object[] { "Metal", red, true };
378 data[1] = new Object[] { "Domain", green, true };
379 fr.setFeaturePriority(data);
380 c = finder.findFeatureColour(Color.cyan, seq, 10);
381 assertEquals(c, new Color(153, 102, 41));
384 * ..and turn off display of Metal
385 * Domain (green) above background (pink)
386 * 0.6 * green(0, 255, 0) + 0.4 * pink(255, 175, 175) = (102, 223, 70)
389 fr.setFeaturePriority(data);
390 c = finder.findFeatureColour(Color.pink, seq, 10);
391 assertEquals(c, new Color(102, 223, 70));
394 @Test(groups = "Functional")
395 public void testNoFeaturesDisplayed()
398 * no features on alignment to render
400 assertTrue(finder.noFeaturesDisplayed());
404 * it will be automatically set visible but we leave
405 * the viewport configured not to show features
407 av.setShowSequenceFeatures(false);
408 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
409 Float.NaN, "MetalGroup"));
410 FeatureColour red = new FeatureColour(Color.red);
411 fr.setColour("Metal", red);
413 assertTrue(finder.noFeaturesDisplayed());
416 * turn on feature display
418 av.setShowSequenceFeatures(true);
419 assertFalse(finder.noFeaturesDisplayed());
422 * turn off display of Metal
424 Object[][] data = new Object[1][];
425 data[0] = new Object[] { "Metal", red, false };
426 fr.setFeaturePriority(data);
427 assertTrue(finder.noFeaturesDisplayed());
430 * turn display of Metal back on
432 fr.setVisible("Metal");
433 assertFalse(finder.noFeaturesDisplayed());
436 * turn off MetalGroup - has no effect here since the group of a
437 * sequence feature instance is independent of its type
439 fr.setGroupVisibility("MetalGroup", false);
440 assertFalse(finder.noFeaturesDisplayed());
443 * a finder with no feature renderer
445 FeatureColourFinder finder2 = new FeatureColourFinder(null);
446 assertTrue(finder2.noFeaturesDisplayed());