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;
18 import java.util.List;
20 import org.testng.annotations.BeforeMethod;
21 import org.testng.annotations.BeforeTest;
22 import org.testng.annotations.Test;
25 * Unit tests for feature colour determination, including but not limited to
27 * <li>gap position</li>
28 * <li>no features present</li>
29 * <li>features present but show features turned off</li>
30 * <li>features displayed but selected feature turned off</li>
31 * <li>features displayed but feature group turned off</li>
32 * <li>feature displayed but none at the specified position</li>
33 * <li>multiple features at position, with no transparency</li>
34 * <li>multiple features at position, with transparency</li>
35 * <li>score graduated feature colour</li>
36 * <li>contact feature start at the selected position</li>
37 * <li>contact feature end at the selected position</li>
38 * <li>contact feature straddling the selected position (not shown)</li>
41 public class FeatureColourFinderTest
43 private AlignViewport av;
45 private SequenceI seq;
47 private FeatureColourFinder finder;
49 private AlignFrame af;
51 private FeatureRenderer fr;
53 @BeforeTest(alwaysRun = true)
56 // aligned column 8 is sequence position 6
57 String s = ">s1\nABCDE---FGHIJKLMNOPQRSTUVWXYZ\n";
58 af = new FileLoader().LoadFileWaitTillLoaded(s,
59 DataSourceType.PASTE);
60 av = af.getViewport();
61 seq = av.getAlignment().getSequenceAt(0);
62 fr = af.getFeatureRenderer();
63 finder = new FeatureColourFinder(fr);
67 * Clear down any sequence features before each test (not as easy as it
70 @BeforeMethod(alwaysRun = true)
71 public void setUpBeforeTest()
73 List<SequenceFeature> sfs = seq.getSequenceFeatures();
74 for (SequenceFeature sf : sfs)
76 seq.deleteFeature(sf);
78 fr.findAllFeatures(true);
81 * reset all feature groups to visible
83 for (String group : fr.getGroups(false))
85 fr.setGroupVisibility(group, true);
88 fr.clearRenderOrder();
89 av.setShowSequenceFeatures(true);
92 @Test(groups = "Functional")
93 public void testFindFeatureColour_noFeatures()
95 av.setShowSequenceFeatures(false);
96 Color c = finder.findFeatureColour(Color.blue, seq, 10);
97 assertEquals(c, Color.blue);
99 av.setShowSequenceFeatures(true);
100 c = finder.findFeatureColour(Color.blue, seq, 10);
101 assertEquals(c, Color.blue);
104 @Test(groups = "Functional")
105 public void testFindFeatureColour_noFeaturesShown()
107 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
108 Float.NaN, "MetalGroup"));
110 av.setShowSequenceFeatures(false);
111 Color c = finder.findFeatureColour(Color.blue, seq, 10);
112 assertEquals(c, Color.blue);
115 @Test(groups = "Functional")
116 public void testFindFeatureColour_singleFeatureAtPosition()
118 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
119 Float.NaN, "MetalGroup"));
120 fr.setColour("Metal", new FeatureColour(Color.red));
122 av.setShowSequenceFeatures(true);
123 Color c = finder.findFeatureColour(Color.blue, seq, 10);
124 assertEquals(c, Color.red);
127 @Test(groups = "Functional")
128 public void testFindFeatureColour_gapPosition()
130 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, 0f,
132 fr.setColour("Metal", new FeatureColour(Color.red));
134 av.setShowSequenceFeatures(true);
135 Color c = finder.findFeatureColour(null, seq, 6);
136 assertEquals(c, Color.white);
139 @Test(groups = "Functional")
140 public void testFindFeatureColour_multipleFeaturesAtPositionNoTransparency()
143 * featuresAdded -> FeatureRendererModel.updateRenderOrder which adds any
144 * new features 'on top' (but reverses the order of any added features)
146 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
147 Float.NaN, "MetalGroup"));
148 FeatureColour red = new FeatureColour(Color.red);
149 fr.setColour("Metal", red);
151 seq.addSequenceFeature(new SequenceFeature("Domain", "Domain", 4, 15,
152 Float.NaN, "DomainGroup"));
153 FeatureColour green = new FeatureColour(Color.green);
154 fr.setColour("Domain", green);
156 av.setShowSequenceFeatures(true);
159 * expect Domain (green) to be rendered above Metal (red)
161 Color c = finder.findFeatureColour(Color.blue, seq, 10);
162 assertEquals(c, Color.green);
165 * now promote Metal above Domain
166 * - currently no way other than mimicking reordering of
167 * table in Feature Settings
169 Object[][] data = new Object[2][];
170 data[0] = new Object[] { "Metal", red, true };
171 data[1] = new Object[] { "Domain", green, true };
172 fr.setFeaturePriority(data);
173 c = finder.findFeatureColour(Color.blue, seq, 10);
174 assertEquals(c, Color.red);
177 * ..and turn off display of Metal
180 fr.setFeaturePriority(data);
181 c = finder.findFeatureColour(Color.blue, seq, 10);
182 assertEquals(c, Color.green);
185 @Test(groups = "Functional")
186 public void testFindFeatureColour_singleFeatureNotAtPosition()
188 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 8, 12,
189 Float.NaN, "MetalGroup"));
190 fr.setColour("Metal", new FeatureColour(Color.red));
192 av.setShowSequenceFeatures(true);
193 // column 2 = sequence position 3
194 Color c = finder.findFeatureColour(Color.blue, seq, 2);
195 assertEquals(c, Color.blue);
198 @Test(groups = "Functional")
199 public void testFindFeatureColour_featureTypeNotDisplayed()
201 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
202 Float.NaN, "MetalGroup"));
203 FeatureColour red = new FeatureColour(Color.red);
204 fr.setColour("Metal", red);
206 av.setShowSequenceFeatures(true);
207 Color c = finder.findFeatureColour(Color.blue, seq, 10);
208 assertEquals(c, Color.red);
211 * turn off display of Metal - is this the easiest way to do it??
213 Object[][] data = new Object[1][];
214 data[0] = new Object[] { "Metal", red, false };
215 fr.setFeaturePriority(data);
216 c = finder.findFeatureColour(Color.blue, seq, 10);
217 assertEquals(c, Color.blue);
220 * turn display of Metal back on
222 data[0] = new Object[] { "Metal", red, true };
223 fr.setFeaturePriority(data);
224 c = finder.findFeatureColour(Color.blue, seq, 10);
225 assertEquals(c, Color.red);
228 @Test(groups = "Functional")
229 public void testFindFeatureColour_featureGroupNotDisplayed()
231 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
232 Float.NaN, "MetalGroup"));
233 FeatureColour red = new FeatureColour(Color.red);
234 fr.setColour("Metal", red);
236 av.setShowSequenceFeatures(true);
237 Color c = finder.findFeatureColour(Color.blue, seq, 10);
238 assertEquals(c, Color.red);
241 * turn off display of MetalGroup
243 fr.setGroupVisibility("MetalGroup", false);
244 c = finder.findFeatureColour(Color.blue, seq, 10);
245 assertEquals(c, Color.blue);
248 * turn display of MetalGroup back on
250 fr.setGroupVisibility("MetalGroup", true);
251 c = finder.findFeatureColour(Color.blue, seq, 10);
252 assertEquals(c, Color.red);
255 @Test(groups = "Functional")
256 public void testFindFeatureColour_contactFeature()
259 * currently contact feature == type "Disulphide Bond" or "Disulfide Bond" !!
261 seq.addSequenceFeature(new SequenceFeature("Disulphide Bond",
262 "Contact", 2, 12, Float.NaN, "Disulphide"));
263 fr.setColour("Disulphide Bond", new FeatureColour(Color.red));
265 av.setShowSequenceFeatures(true);
268 * Contact positions are residues 2 and 12
269 * which are columns 1 and 14
270 * positions in between don't count for a contact feature!
272 Color c = finder.findFeatureColour(Color.blue, seq, 10);
273 assertEquals(c, Color.blue);
274 c = finder.findFeatureColour(Color.blue, seq, 8);
275 assertEquals(c, Color.blue);
276 c = finder.findFeatureColour(Color.blue, seq, 1);
277 assertEquals(c, Color.red);
278 c = finder.findFeatureColour(Color.blue, seq, 14);
279 assertEquals(c, Color.red);
282 @Test(groups = "Functional")
283 public void testFindFeatureColour_graduatedFeatureColour()
285 seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
287 seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 4,
289 seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 7,
293 * graduated colour from 0 to 10
295 Color min = new Color(100, 50, 150);
296 Color max = new Color(200, 0, 100);
297 FeatureColourI fc = new FeatureColour(min, max, 0, 10);
298 fr.setColour("kd", fc);
300 av.setShowSequenceFeatures(true);
303 * position 2, column 1, score 0 - minimum colour in range
305 Color c = finder.findFeatureColour(Color.blue, seq, 1);
306 assertEquals(c, min);
309 * position 7, column 9, score 10 - maximum colour in range
311 c = finder.findFeatureColour(Color.blue, seq, 9);
312 assertEquals(c, max);
315 * position 4, column 3, score 5 - half way from min to max
317 c = finder.findFeatureColour(Color.blue, seq, 3);
318 assertEquals(c, new Color(150, 25, 125));
321 @Test(groups = "Functional")
322 public void testFindFeatureColour_transparencySingleFeature()
324 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
325 Float.NaN, "MetalGroup"));
326 FeatureColour red = new FeatureColour(Color.red);
327 fr.setColour("Metal", red);
329 av.setShowSequenceFeatures(true);
332 * the FeatureSettings transparency slider has range 0-70 which
333 * corresponds to a transparency value of 1 - 0.3
334 * A value of 0.4 gives a combination of
335 * 0.4 * red(255, 0, 0) + 0.6 * cyan(0, 255, 255) = (102, 153, 153)
337 fr.setTransparency(0.4f);
338 Color c = finder.findFeatureColour(Color.cyan, seq, 10);
339 assertEquals(c, new Color(102, 153, 153));
342 @Test(groups = "Functional")
343 public void testFindFeatureColour_transparencyTwoFeatures()
345 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
346 Float.NaN, "MetalGroup"));
347 FeatureColour red = new FeatureColour(Color.red);
348 fr.setColour("Metal", red);
350 seq.addSequenceFeature(new SequenceFeature("Domain", "Domain", 4, 15,
351 Float.NaN, "DomainGroup"));
352 FeatureColour green = new FeatureColour(Color.green);
353 fr.setColour("Domain", green);
355 av.setShowSequenceFeatures(true);
358 * Domain (green) rendered above Metal (red) above background (cyan)
359 * 1) 0.6 * red(255, 0, 0) + 0.4 * cyan(0, 255, 255) = (153, 102, 102)
360 * 2) 0.6* green(0, 255, 0) + 0.4 * (153, 102, 102) = (61, 194, 41) rounded
362 fr.setTransparency(0.6f);
363 Color c = finder.findFeatureColour(Color.cyan, seq, 10);
364 assertEquals(c, new Color(61, 194, 41));
367 * now promote Metal above Domain
368 * - currently no way other than mimicking reordering of
369 * table in Feature Settings
370 * Metal (red) rendered above Domain (green) above background (cyan)
371 * 1) 0.6 * green(0, 255, 0) + 0.4 * cyan(0, 255, 255) = (0, 255, 102)
372 * 2) 0.6* red(255, 0, 0) + 0.4 * (0, 255, 102) = (153, 102, 41) rounded
374 Object[][] data = new Object[2][];
375 data[0] = new Object[] { "Metal", red, true };
376 data[1] = new Object[] { "Domain", green, true };
377 fr.setFeaturePriority(data);
378 c = finder.findFeatureColour(Color.cyan, seq, 10);
379 assertEquals(c, new Color(153, 102, 41));
382 * ..and turn off display of Metal
383 * Domain (green) above background (pink)
384 * 0.6 * green(0, 255, 0) + 0.4 * pink(255, 175, 175) = (102, 223, 70)
387 fr.setFeaturePriority(data);
388 c = finder.findFeatureColour(Color.pink, seq, 10);
389 assertEquals(c, new Color(102, 223, 70));
392 @Test(groups = "Functional")
393 public void testNoFeaturesDisplayed()
396 * no features on alignment to render
398 assertTrue(finder.noFeaturesDisplayed());
402 * it will be automatically set visible but we leave
403 * the viewport configured not to show features
405 av.setShowSequenceFeatures(false);
406 seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12,
407 Float.NaN, "MetalGroup"));
408 FeatureColour red = new FeatureColour(Color.red);
409 fr.setColour("Metal", red);
411 assertTrue(finder.noFeaturesDisplayed());
414 * turn on feature display
416 av.setShowSequenceFeatures(true);
417 assertFalse(finder.noFeaturesDisplayed());
420 * turn off display of Metal
422 Object[][] data = new Object[1][];
423 data[0] = new Object[] { "Metal", red, false };
424 fr.setFeaturePriority(data);
425 assertTrue(finder.noFeaturesDisplayed());
428 * turn display of Metal back on
430 fr.setVisible("Metal");
431 assertFalse(finder.noFeaturesDisplayed());
434 * turn off MetalGroup - has no effect here since the group of a
435 * sequence feature instance is independent of its type
437 fr.setGroupVisibility("MetalGroup", false);
438 assertFalse(finder.noFeaturesDisplayed());
441 * a finder with no feature renderer
443 FeatureColourFinder finder2 = new FeatureColourFinder(null);
444 assertTrue(finder2.noFeaturesDisplayed());