2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.Assert.assertFalse;
25 import static org.testng.Assert.assertNotSame;
26 import static org.testng.Assert.assertSame;
27 import static org.testng.Assert.assertTrue;
29 import jalview.api.FeatureColourI;
30 import jalview.bin.Cache;
31 import jalview.bin.Jalview;
32 import jalview.datamodel.Alignment;
33 import jalview.datamodel.AlignmentI;
34 import jalview.datamodel.Sequence;
35 import jalview.datamodel.SequenceFeature;
36 import jalview.datamodel.SequenceGroup;
37 import jalview.datamodel.SequenceI;
38 import jalview.io.DataSourceType;
39 import jalview.io.FileLoader;
40 import jalview.io.Jalview2xmlTests;
41 import jalview.renderer.ResidueShaderI;
42 import jalview.schemes.BuriedColourScheme;
43 import jalview.schemes.FeatureColour;
44 import jalview.schemes.HelixColourScheme;
45 import jalview.schemes.JalviewColourScheme;
46 import jalview.schemes.StrandColourScheme;
47 import jalview.schemes.TurnColourScheme;
48 import jalview.util.MessageManager;
50 import java.awt.Color;
51 import java.util.List;
53 import org.testng.annotations.AfterMethod;
54 import org.testng.annotations.BeforeClass;
55 import org.testng.annotations.BeforeMethod;
56 import org.testng.annotations.Test;
58 public class AlignFrameTest
62 @BeforeClass(alwaysRun = true)
63 public void setUpJvOptionPane()
65 JvOptionPane.setInteractiveMode(false);
66 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
69 @Test(groups = "Functional")
70 public void testHideFeatureColumns()
72 SequenceI seq1 = new Sequence("Seq1", "ABCDEFGHIJ");
73 SequenceI seq2 = new Sequence("Seq2", "ABCDEFGHIJ");
74 seq1.addSequenceFeature(new SequenceFeature("Metal", "", 1, 5, 0f, null));
75 seq2.addSequenceFeature(new SequenceFeature("Metal", "", 6, 10, 10f,
77 seq1.addSequenceFeature(new SequenceFeature("Turn", "", 2, 4,
79 seq2.addSequenceFeature(new SequenceFeature("Turn", "", 7, 9,
81 AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
82 AlignFrame alignFrame = new AlignFrame(al, al.getWidth(),
86 * make all features visible (select feature columns checks visibility)
88 alignFrame.getFeatureRenderer().findAllFeatures(true);
91 * hiding a feature not present does nothing
93 assertFalse(alignFrame.hideFeatureColumns("exon", true));
94 assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
95 assertTrue(alignFrame.getViewport().getAlignment().getHiddenColumns()
96 .getHiddenColumnsCopy().isEmpty());
97 assertFalse(alignFrame.hideFeatureColumns("exon", false));
98 assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
99 assertTrue(alignFrame.getViewport().getAlignment().getHiddenColumns()
100 .getHiddenColumnsCopy().isEmpty());
103 * hiding a feature in all columns does nothing
105 assertFalse(alignFrame.hideFeatureColumns("Metal", true));
106 assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
107 List<int[]> hidden = alignFrame.getViewport().getAlignment()
108 .getHiddenColumns().getHiddenColumnsCopy();
109 assertTrue(hidden.isEmpty());
112 * threshold Metal to hide features where score < 5
113 * seq1 feature in columns 1-5 is hidden
114 * seq2 feature in columns 6-10 is shown
116 FeatureColourI fc = new FeatureColour(Color.red, Color.blue, 0f, 10f);
117 fc.setAboveThreshold(true);
119 alignFrame.getFeatureRenderer().setColour("Metal", fc);
120 assertTrue(alignFrame.hideFeatureColumns("Metal", true));
121 hidden = alignFrame.getViewport().getAlignment().getHiddenColumns()
122 .getHiddenColumnsCopy();
123 assertEquals(hidden.size(), 1);
124 assertEquals(hidden.get(0)[0], 5);
125 assertEquals(hidden.get(0)[1], 9);
128 * hide a feature present in some columns
129 * sequence positions [2-4], [7-9] are column positions
130 * [1-3], [6-8] base zero
132 alignFrame.getViewport().showAllHiddenColumns();
133 assertTrue(alignFrame.hideFeatureColumns("Turn", true));
134 hidden = alignFrame.getViewport().getAlignment().getHiddenColumns()
135 .getHiddenColumnsCopy();
136 assertEquals(hidden.size(), 2);
137 assertEquals(hidden.get(0)[0], 1);
138 assertEquals(hidden.get(0)[1], 3);
139 assertEquals(hidden.get(1)[0], 6);
140 assertEquals(hidden.get(1)[1], 8);
143 @BeforeClass(alwaysRun = true)
144 public static void setUpBeforeClass() throws Exception
147 * use read-only test properties file
149 Cache.loadProperties("test/jalview/io/testProps.jvprops");
150 Jalview.main(new String[] { "-nonews" });
153 @AfterMethod(alwaysRun = true)
154 public void tearDown()
156 Desktop.instance.closeAll_actionPerformed(null);
160 * configure (read-only) properties for test to ensure Consensus is computed
161 * for colour Above PID testing
163 @BeforeMethod(alwaysRun = true)
166 Cache.loadProperties("test/jalview/io/testProps.jvprops");
167 Cache.applicationProperties.setProperty("SHOW_IDENTITY",
168 Boolean.TRUE.toString());
169 af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
170 DataSourceType.FILE);
173 * wait for Consensus thread to complete
177 while (af.getViewport().getConsensusSeq() == null)
182 } catch (InterruptedException e)
190 * Test that changing background (alignment) colour scheme
192 * <li>with Apply Colour to All Groups not selected, does not change group
194 * <li>with Apply Colour to All Groups selected, does change group colours</li>
195 * <li>in neither case, changes alignment or group colour thresholds (PID or
199 @Test(groups = "Functional")
200 public void testChangeColour_background_groupsAndThresholds()
202 AlignViewport av = af.getViewport();
203 AlignmentI al = av.getAlignment();
206 * Colour alignment by Buried Index
208 af.applyToAllGroups_actionPerformed(false);
209 af.changeColour_actionPerformed(JalviewColourScheme.Buried.toString());
210 assertTrue(av.getGlobalColourScheme() instanceof BuriedColourScheme);
211 assertFalse(av.getResidueShading().conservationApplied());
212 assertEquals(av.getResidueShading().getThreshold(), 0);
215 * Apply Conservation 20%
217 af.conservationMenuItem_actionPerformed(true);
218 SliderPanel sp = SliderPanel.getSliderPanel();
219 assertEquals(sp.getTitle(), MessageManager.formatMessage(
220 "label.conservation_colour_increment",
221 new String[] { "Background" }));
222 assertTrue(sp.isForConservation());
224 assertTrue(av.getResidueShading().conservationApplied());
225 assertEquals(av.getResidueShading().getConservationInc(), 20);
228 * Apply PID threshold 10% (conservation still applies as well)
230 af.abovePIDThreshold_actionPerformed(true);
231 sp = SliderPanel.getSliderPanel();
232 assertFalse(sp.isForConservation());
233 assertEquals(sp.getTitle(), MessageManager.formatMessage(
234 "label.percentage_identity_threshold",
235 new String[] { "Background" }));
237 assertEquals(av.getResidueShading().getThreshold(), 10);
238 assertTrue(av.getResidueShading().conservationApplied());
239 assertEquals(av.getResidueShading().getConservationInc(), 20);
242 * create a group with Strand colouring, 30% Conservation
243 * and 40% PID threshold
245 SequenceGroup sg = new SequenceGroup();
246 sg.addSequence(al.getSequenceAt(0), false);
249 av.setSelectionGroup(sg);
252 * apply 30% Conservation to group
254 PopupMenu popupMenu = new PopupMenu(af.alignPanel, null, null);
255 popupMenu.changeColour_actionPerformed(JalviewColourScheme.Strand
257 assertTrue(sg.getColourScheme() instanceof StrandColourScheme);
258 assertEquals(al.getGroups().size(), 1);
259 assertSame(al.getGroups().get(0), sg);
260 popupMenu.conservationMenuItem_actionPerformed(true);
261 sp = SliderPanel.getSliderPanel();
262 assertTrue(sp.isForConservation());
263 assertEquals(sp.getTitle(), MessageManager.formatMessage(
264 "label.conservation_colour_increment",
265 new String[] { sg.getName() }));
267 assertTrue(sg.getGroupColourScheme().conservationApplied());
268 assertEquals(sg.getGroupColourScheme().getConservationInc(), 30);
271 * apply 40% PID threshold to group
273 popupMenu.abovePIDColour_actionPerformed(true);
274 sp = SliderPanel.getSliderPanel();
275 assertFalse(sp.isForConservation());
276 assertEquals(sp.getTitle(), MessageManager.formatMessage(
277 "label.percentage_identity_threshold",
278 new String[] { sg.getName() }));
280 assertEquals(sg.getGroupColourScheme().getThreshold(), 40);
281 // conservation threshold is unchanged:
282 assertTrue(sg.getGroupColourScheme().conservationApplied());
283 assertEquals(sg.getGroupColourScheme().getConservationInc(), 30);
286 * change alignment colour - group colour, and all thresholds,
287 * should be unaffected
289 af.changeColour_actionPerformed(JalviewColourScheme.Turn.toString());
290 assertTrue(av.getGlobalColourScheme() instanceof TurnColourScheme);
291 assertTrue(av.getResidueShading().conservationApplied());
292 assertEquals(av.getResidueShading().getConservationInc(), 20);
293 assertEquals(av.getResidueShading().getThreshold(), 10);
294 assertTrue(sg.getColourScheme() instanceof StrandColourScheme);
295 assertTrue(sg.getGroupColourScheme().conservationApplied());
296 assertEquals(sg.getGroupColourScheme().getConservationInc(), 30);
297 assertEquals(sg.getGroupColourScheme().getThreshold(), 40);
300 * Now change alignment colour with Apply Colour To All Groups
301 * - group colour should change, but not colour thresholds
303 af.applyToAllGroups_actionPerformed(true);
304 af.changeColour_actionPerformed(JalviewColourScheme.Helix.toString());
305 assertTrue(av.getGlobalColourScheme() instanceof HelixColourScheme);
306 assertTrue(av.getResidueShading().conservationApplied());
307 assertEquals(av.getResidueShading().getConservationInc(), 20);
308 assertEquals(av.getResidueShading().getThreshold(), 10);
309 assertTrue(sg.getColourScheme() instanceof HelixColourScheme);
310 assertTrue(sg.getGroupColourScheme().conservationApplied());
311 assertEquals(sg.getGroupColourScheme().getConservationInc(), 30);
312 assertEquals(sg.getGroupColourScheme().getThreshold(), 40);
316 * Test residue colouring with various options
318 * <li>no PID or Conservation threshold</li>
319 * <li>colour by Conservation applied</li>
320 * <li>colour by Conservation removed</li>
321 * <li>colour above PID - various values</li>
322 * <li>colour above PID removed</li>
323 * <li>Above PID plus By Conservation combined</li>
324 * <li>remove Above PID to leave just By Conservation</li>
325 * <li>re-add Above PID</li>
326 * <li>remove By Conservation to leave just Above PID</li>
327 * <li>remove Above PID to leave original colours</li>
330 @Test(groups = "Functional")
331 public void testColourThresholdActions()
333 AlignViewport av = af.getViewport();
334 AlignmentI al = av.getAlignment();
337 * Colour alignment by Helix Propensity, no thresholds
339 af.applyToAllGroups_actionPerformed(false);
340 af.changeColour_actionPerformed(JalviewColourScheme.Helix.toString());
341 assertTrue(av.getGlobalColourScheme() instanceof HelixColourScheme);
342 assertFalse(av.getResidueShading().conservationApplied());
343 assertEquals(av.getResidueShading().getThreshold(), 0);
346 * inspect the colour of
347 * FER_CAPAN.9(I), column 14 (14 base 0)
348 * FER_CAPAN.10(SER), column 16 (15 base 0)
350 SequenceI ferCapan = al.findName("FER_CAPAN");
351 ResidueShaderI rs = av.getResidueShading();
352 Color c = rs.findColour('I', 14, ferCapan);
353 Color i_original = new Color(138, 117, 138);
354 assertEquals(c, i_original);
355 c = rs.findColour('S', 15, ferCapan);
356 Color s_original = new Color(54, 201, 54);
357 assertEquals(c, s_original);
360 * colour by conservation with increment 10
362 af.conservationMenuItem_actionPerformed(true);
363 SliderPanel sp = SliderPanel.getSliderPanel();
364 assertTrue(sp.isForConservation());
365 assertEquals(sp.getValue(), 30); // initial slider setting
367 assertSame(rs, av.getResidueShading());
368 c = rs.findColour('I', 14, ferCapan);
369 Color i_faded = new Color(196, 186, 196);
370 assertEquals(c, i_faded);
371 c = rs.findColour('S', 15, ferCapan);
372 Color s_faded = new Color(144, 225, 144);
373 assertEquals(c, s_faded);
376 * deselect By Conservation - colour should revert
378 af.conservationMenuItem_actionPerformed(false);
379 c = rs.findColour('S', 15, ferCapan);
380 assertEquals(c, s_original);
383 * now Above PID, threshold = 0%
384 * should be no change
386 af.abovePIDThreshold_actionPerformed(true);
387 sp = SliderPanel.getSliderPanel();
388 assertFalse(sp.isForConservation());
389 assertEquals(sp.getValue(), 0); // initial slider setting
390 c = rs.findColour('I', 14, ferCapan);
391 assertEquals(c, i_original);
392 c = rs.findColour('S', 15, ferCapan);
393 assertEquals(c, s_original);
396 * Above PID, threshold = 1%
397 * 15.I becomes White because no match to consensus (V)
398 * 16.S remains coloured as matches 66.66% consensus
401 c = rs.findColour('I', 14, ferCapan);
402 assertEquals(c, Color.white);
403 c = rs.findColour('S', 15, ferCapan);
404 assertEquals(c, s_original);
407 * threshold 66% - no further change yet...
410 c = rs.findColour('I', 14, ferCapan);
411 assertEquals(c, Color.white);
412 c = rs.findColour('S', 15, ferCapan);
413 assertEquals(c, s_original);
416 * threshold 67% - now both residues are white
419 c = rs.findColour('I', 14, ferCapan);
420 assertEquals(c, Color.white);
421 c = rs.findColour('S', 15, ferCapan);
422 assertEquals(c, Color.white);
425 * deselect Above PID - colours should revert
427 af.abovePIDThreshold_actionPerformed(false);
428 c = rs.findColour('I', 14, ferCapan);
429 assertEquals(c, i_original);
430 c = rs.findColour('S', 15, ferCapan);
431 assertEquals(c, s_original);
434 * Now combine Above 50% PID and By Conservation 10%
435 * 15.I is White because no match to consensus (V)
436 * 16.S is coloured but faded
438 af.abovePIDThreshold_actionPerformed(true);
439 sp = SliderPanel.getSliderPanel();
440 assertFalse(sp.isForConservation());
442 af.conservationMenuItem_actionPerformed(true);
443 sp = SliderPanel.getSliderPanel();
444 assertTrue(sp.isForConservation());
446 c = rs.findColour('I', 14, ferCapan);
447 assertEquals(c, Color.white);
448 c = rs.findColour('S', 15, ferCapan);
449 assertEquals(c, s_faded);
452 * turn off Above PID - should just leave Conservation fading as before
454 af.abovePIDThreshold_actionPerformed(false);
455 c = rs.findColour('I', 14, ferCapan);
456 assertEquals(c, i_faded);
457 c = rs.findColour('S', 15, ferCapan);
458 assertEquals(c, s_faded);
461 * Now add Above 50% PID to conservation colouring
462 * - should give the same as PID followed by conservation (above)
464 af.abovePIDThreshold_actionPerformed(true);
465 SliderPanel.getSliderPanel().valueChanged(50);
466 c = rs.findColour('I', 14, ferCapan);
467 assertEquals(c, Color.white);
468 c = rs.findColour('S', 15, ferCapan);
469 assertEquals(c, s_faded);
472 * turn off By Conservation
473 * should leave I white, S original (unfaded) colour
475 af.conservationMenuItem_actionPerformed(false);
476 c = rs.findColour('I', 14, ferCapan);
477 assertEquals(c, Color.white);
478 c = rs.findColour('S', 15, ferCapan);
479 assertEquals(c, s_original);
482 * finally turn off Above PID to leave original colours
484 af.abovePIDThreshold_actionPerformed(false);
485 c = rs.findColour('I', 14, ferCapan);
486 assertEquals(c, i_original);
487 c = rs.findColour('S', 15, ferCapan);
488 assertEquals(c, s_original);
492 * Verify that making a New View transfers alignment and group colour schemes,
493 * including any thresholds, to the new view. Because New View is performed by
494 * saving and reloading a 'project' file, this is similar to verifying a
495 * project save and reload.
497 * @see Jalview2xmlTests#testStoreAndRecoverColourThresholds()
499 @Test(groups = "Functional")
500 public void testNewView_colourThresholds()
502 AlignViewport av = af.getViewport();
503 AlignmentI al = av.getAlignment();
506 * Colour alignment by Buried Index, Above 10% PID, By Conservation 20%
508 af.changeColour_actionPerformed(JalviewColourScheme.Buried.toString());
509 assertTrue(av.getGlobalColourScheme() instanceof BuriedColourScheme);
510 af.abovePIDThreshold_actionPerformed(true);
511 SliderPanel sp = SliderPanel.getSliderPanel();
512 assertFalse(sp.isForConservation());
514 af.conservationMenuItem_actionPerformed(true);
515 sp = SliderPanel.getSliderPanel();
516 assertTrue(sp.isForConservation());
518 ResidueShaderI rs = av.getResidueShading();
519 assertEquals(rs.getThreshold(), 10);
520 assertTrue(rs.conservationApplied());
521 assertEquals(rs.getConservationInc(), 20);
524 * create a group with Strand colouring, 30% Conservation
525 * and 40% PID threshold
527 SequenceGroup sg = new SequenceGroup();
528 sg.addSequence(al.getSequenceAt(0), false);
531 av.setSelectionGroup(sg);
532 PopupMenu popupMenu = new PopupMenu(af.alignPanel, null, null);
533 popupMenu.changeColour_actionPerformed(JalviewColourScheme.Strand
535 assertTrue(sg.getColourScheme() instanceof StrandColourScheme);
536 assertEquals(al.getGroups().size(), 1);
537 assertSame(al.getGroups().get(0), sg);
538 popupMenu.conservationMenuItem_actionPerformed(true);
539 sp = SliderPanel.getSliderPanel();
540 assertTrue(sp.isForConservation());
542 popupMenu.abovePIDColour_actionPerformed(true);
543 sp = SliderPanel.getSliderPanel();
544 assertFalse(sp.isForConservation());
546 rs = sg.getGroupColourScheme();
547 assertTrue(rs.conservationApplied());
548 assertEquals(rs.getConservationInc(), 30);
549 assertEquals(rs.getThreshold(), 40);
552 * set slider panel focus to the background alignment
554 af.conservationMenuItem_actionPerformed(true);
555 sp = SliderPanel.getSliderPanel();
556 assertTrue(sp.isForConservation());
557 assertEquals(sp.getTitle(), MessageManager.formatMessage(
558 "label.conservation_colour_increment",
559 new String[] { "Background" }));
562 * make a new View, verify alignment and group colour schemes
564 af.newView_actionPerformed(null);
565 assertEquals(af.alignPanel.getViewName(), "View 1");
566 AlignViewport av2 = af.getViewport();
567 assertNotSame(av, av2);
568 assertSame(av2, af.alignPanel.av);
569 rs = av2.getResidueShading();
570 assertNotSame(av.getResidueShading(), rs);
571 assertEquals(rs.getThreshold(), 10);
572 assertTrue(rs.conservationApplied(), rs.toString());
573 assertEquals(rs.getConservationInc(), 20);
574 assertEquals(av2.getAlignment().getGroups().size(), 1);
575 sg = av2.getAlignment().getGroups().get(0);
576 rs = sg.getGroupColourScheme();
577 assertTrue(rs.conservationApplied());
578 assertEquals(rs.getConservationInc(), 30);
579 assertEquals(rs.getThreshold(), 40);
582 * check the Conservation SliderPanel (still open) is linked to
583 * and updates the new view (JAL-2385)
585 sp = SliderPanel.getSliderPanel();
586 assertTrue(sp.isForConservation());
587 assertEquals(sp.getTitle(), MessageManager.formatMessage(
588 "label.conservation_colour_increment",
589 new String[] { "View 1" }));
591 assertEquals(av2.getResidueShading().getConservationInc(), 22);