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.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertNotNull;
26 import static org.testng.AssertJUnit.assertNotSame;
27 import static org.testng.AssertJUnit.assertSame;
28 import static org.testng.AssertJUnit.assertTrue;
30 import java.util.ArrayList;
31 import java.util.List;
33 import org.testng.Assert;
34 import org.testng.annotations.BeforeClass;
35 import org.testng.annotations.BeforeMethod;
36 import org.testng.annotations.Test;
38 import jalview.bin.Cache;
39 import jalview.bin.Jalview;
40 import jalview.datamodel.AlignedCodonFrame;
41 import jalview.datamodel.Alignment;
42 import jalview.datamodel.AlignmentAnnotation;
43 import jalview.datamodel.AlignmentI;
44 import jalview.datamodel.Annotation;
45 import jalview.datamodel.ContactMatrixI;
46 import jalview.datamodel.SearchResults;
47 import jalview.datamodel.SearchResultsI;
48 import jalview.datamodel.SeqDistanceContactMatrix;
49 import jalview.datamodel.Sequence;
50 import jalview.datamodel.SequenceGroup;
51 import jalview.datamodel.SequenceI;
52 import jalview.io.DataSourceType;
53 import jalview.io.FileLoader;
54 import jalview.schemes.ClustalxColourScheme;
55 import jalview.schemes.ColourSchemeI;
56 import jalview.schemes.PIDColourScheme;
57 import jalview.structure.StructureSelectionManager;
58 import jalview.util.MapList;
59 import jalview.viewmodel.ViewportRanges;
61 public class AlignViewportTest
64 @BeforeClass(alwaysRun = true)
65 public void setUpJvOptionPane()
67 JvOptionPane.setInteractiveMode(false);
68 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
75 @BeforeClass(alwaysRun = true)
76 public static void setUpBeforeClass() throws Exception
80 { "-nonews", "-props", "test/jalview/testProps.jvprops" });
83 * remove any sequence mappings left lying around by other tests
85 StructureSelectionManager ssm = StructureSelectionManager
86 .getStructureSelectionManager(Desktop.instance);
90 @BeforeMethod(alwaysRun = true)
93 SequenceI seq1 = new Sequence("Seq1", "ABC");
94 SequenceI seq2 = new Sequence("Seq2", "ABC");
95 SequenceI seq3 = new Sequence("Seq3", "ABC");
96 SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3 };
97 al = new Alignment(seqs);
99 testee = new AlignViewport(al);
103 * Test that a mapping is not deregistered when a second view is closed but
104 * the first still holds a reference to the mapping
106 @Test(groups = { "Functional" })
107 public void testDeregisterMapping_onCloseView()
110 * alignment with reference to mappings
112 AlignFrame af1 = new FileLoader()
113 .LoadFileWaitTillLoaded(">Seq1\nCAGT\n", DataSourceType.PASTE);
115 SequenceI s1 = af1.getViewport().getAlignment().getSequenceAt(0);
116 AlignedCodonFrame acf1 = new AlignedCodonFrame();
118 new MapList(new int[]
119 { 1, 4 }, new int[] { 1, 4 }, 1, 1));
120 AlignedCodonFrame acf2 = new AlignedCodonFrame();
122 new MapList(new int[]
123 { 1, 4 }, new int[] { 4, 1 }, 1, 1));
125 List<AlignedCodonFrame> mappings = new ArrayList<>();
128 af1.getViewport().getAlignment().setCodonFrames(mappings);
129 af1.newView_actionPerformed(null);
132 * Verify that creating the alignment for the new View has registered the
135 StructureSelectionManager ssm = StructureSelectionManager
136 .getStructureSelectionManager(Desktop.instance);
137 List<AlignedCodonFrame> sequenceMappings = ssm.getSequenceMappings();
138 assertEquals(2, sequenceMappings.size());
139 assertTrue(sequenceMappings.contains(acf1));
140 assertTrue(sequenceMappings.contains(acf2));
143 * Close the second view. Verify that mappings are not removed as the first
144 * view still holds a reference to them.
146 af1.closeMenuItem_actionPerformed(false);
147 assertEquals(2, sequenceMappings.size());
148 assertTrue(sequenceMappings.contains(acf1));
149 assertTrue(sequenceMappings.contains(acf2));
153 * Test that a mapping is deregistered if no alignment holds a reference to it
155 @Test(groups = { "Functional" })
156 public void testDeregisterMapping_withNoReference()
158 Desktop d = Desktop.instance;
160 StructureSelectionManager ssm = StructureSelectionManager
161 .getStructureSelectionManager(Desktop.instance);
164 AlignFrame af1 = new FileLoader()
165 .LoadFileWaitTillLoaded(">Seq1\nRSVQ\n", DataSourceType.PASTE);
166 AlignFrame af2 = new FileLoader()
167 .LoadFileWaitTillLoaded(">Seq2\nDGEL\n", DataSourceType.PASTE);
168 SequenceI cs1 = new Sequence("cseq1", "CCCGGGTTTAAA");
169 SequenceI cs2 = new Sequence("cseq2", "CTTGAGTCTAGA");
170 SequenceI s1 = af1.getViewport().getAlignment().getSequenceAt(0);
171 SequenceI s2 = af2.getViewport().getAlignment().getSequenceAt(0);
172 // need to be distinct
173 AlignedCodonFrame acf1 = new AlignedCodonFrame();
175 new MapList(new int[]
176 { 1, 4 }, new int[] { 1, 12 }, 1, 3));
177 AlignedCodonFrame acf2 = new AlignedCodonFrame();
179 new MapList(new int[]
180 { 1, 4 }, new int[] { 1, 12 }, 1, 3));
181 AlignedCodonFrame acf3 = new AlignedCodonFrame();
182 acf3.addMap(cs2, cs2,
183 new MapList(new int[]
184 { 1, 12 }, new int[] { 1, 12 }, 1, 1));
186 List<AlignedCodonFrame> mappings1 = new ArrayList<>();
188 af1.getViewport().getAlignment().setCodonFrames(mappings1);
190 List<AlignedCodonFrame> mappings2 = new ArrayList<>();
193 af2.getViewport().getAlignment().setCodonFrames(mappings2);
196 * AlignFrame1 has mapping acf1, AlignFrame2 has acf2 and acf3
199 List<AlignedCodonFrame> ssmMappings = ssm.getSequenceMappings();
200 assertEquals(0, ssmMappings.size());
201 ssm.registerMapping(acf1);
202 assertEquals(1, ssmMappings.size());
203 ssm.registerMapping(acf2);
204 assertEquals(2, ssmMappings.size());
205 ssm.registerMapping(acf3);
206 assertEquals(3, ssmMappings.size());
209 * Closing AlignFrame2 should remove its mappings from
210 * StructureSelectionManager, since AlignFrame1 has no reference to them
212 af2.closeMenuItem_actionPerformed(true);
213 assertEquals(1, ssmMappings.size());
214 assertTrue(ssmMappings.contains(acf1));
218 * Test that a mapping is not deregistered if another alignment holds a
221 @Test(groups = { "Functional" })
222 public void testDeregisterMapping_withReference()
224 Desktop d = Desktop.instance;
226 StructureSelectionManager ssm = StructureSelectionManager
227 .getStructureSelectionManager(Desktop.instance);
230 AlignFrame af1 = new FileLoader()
231 .LoadFileWaitTillLoaded(">Seq1\nRSVQ\n", DataSourceType.PASTE);
232 AlignFrame af2 = new FileLoader()
233 .LoadFileWaitTillLoaded(">Seq2\nDGEL\n", DataSourceType.PASTE);
234 SequenceI cs1 = new Sequence("cseq1", "CCCGGGTTTAAA");
235 SequenceI cs2 = new Sequence("cseq2", "CTTGAGTCTAGA");
236 SequenceI s1 = af1.getViewport().getAlignment().getSequenceAt(0);
237 SequenceI s2 = af2.getViewport().getAlignment().getSequenceAt(0);
238 // need to be distinct
239 AlignedCodonFrame acf1 = new AlignedCodonFrame();
241 new MapList(new int[]
242 { 1, 4 }, new int[] { 1, 12 }, 1, 3));
243 AlignedCodonFrame acf2 = new AlignedCodonFrame();
245 new MapList(new int[]
246 { 1, 4 }, new int[] { 1, 12 }, 1, 3));
247 AlignedCodonFrame acf3 = new AlignedCodonFrame();
248 acf3.addMap(cs2, cs2,
249 new MapList(new int[]
250 { 1, 12 }, new int[] { 1, 12 }, 1, 1));
252 List<AlignedCodonFrame> mappings1 = new ArrayList<>();
255 af1.getViewport().getAlignment().setCodonFrames(mappings1);
257 List<AlignedCodonFrame> mappings2 = new ArrayList<>();
260 af2.getViewport().getAlignment().setCodonFrames(mappings2);
263 * AlignFrame1 has mappings acf1 and acf2, AlignFrame2 has acf2 and acf3
266 List<AlignedCodonFrame> ssmMappings = ssm.getSequenceMappings();
267 assertEquals(0, ssmMappings.size());
268 ssm.registerMapping(acf1);
269 assertEquals(1, ssmMappings.size());
270 ssm.registerMapping(acf2);
271 assertEquals(2, ssmMappings.size());
272 ssm.registerMapping(acf3);
273 assertEquals(3, ssmMappings.size());
276 * Closing AlignFrame2 should remove mapping acf3 from
277 * StructureSelectionManager, but not acf2, since AlignFrame1 still has a
280 af2.closeMenuItem_actionPerformed(true);
281 assertEquals(2, ssmMappings.size());
282 assertTrue(ssmMappings.contains(acf1));
283 assertTrue(ssmMappings.contains(acf2));
284 assertFalse(ssmMappings.contains(acf3));
288 * Test for JAL-1306 - conservation thread should run even when only Quality
289 * (and not Conservation) is enabled in Preferences
291 @Test(groups = { "Functional" }, timeOut = 2000)
292 public void testUpdateConservation_qualityOnly()
294 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
295 Boolean.TRUE.toString());
296 Cache.applicationProperties.setProperty("SHOW_QUALITY",
297 Boolean.TRUE.toString());
298 Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
299 Boolean.FALSE.toString());
300 Cache.applicationProperties.setProperty("SHOW_OCCUPANCY",
301 Boolean.FALSE.toString());
302 Cache.applicationProperties.setProperty("SHOW_IDENTITY",
303 Boolean.FALSE.toString());
304 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
305 "examples/uniref50.fa", DataSourceType.FILE);
308 * wait for Conservation thread to complete
310 AlignViewport viewport = af.getViewport();
311 waitForCalculations(viewport);
312 AlignmentAnnotation[] anns = viewport.getAlignment()
313 .getAlignmentAnnotation();
314 assertNotNull("No annotations found", anns);
315 assertEquals("More than one annotation found", 1, anns.length);
316 assertTrue("Annotation is not Quality",
317 anns[0].description.startsWith("Alignment Quality"));
318 Annotation[] annotations = anns[0].annotations;
319 assertNotNull("Quality annotations are null", annotations);
320 assertNotNull("Quality in column 1 is null", annotations[0]);
321 assertTrue("No quality value in column 1", annotations[0].value > 10f);
325 * Wait for consensus etc calculation threads to complete
329 protected void waitForCalculations(AlignViewport viewport)
338 } catch (InterruptedException e)
341 } while (viewport.getCalcManager().isWorking());
345 @Test(groups = { "Functional" })
346 public void testSetGlobalColourScheme()
349 * test for JAL-2283: don't inadvertently turn on colour by conservation
351 Cache.applicationProperties.setProperty("DEFAULT_COLOUR_PROT", "None");
352 Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
353 Boolean.TRUE.toString());
354 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
355 "examples/uniref50.fa", DataSourceType.FILE);
356 ColourSchemeI cs = new PIDColourScheme();
357 AlignViewport viewport = af.getViewport();
358 viewport.setGlobalColourScheme(cs);
359 assertFalse(viewport.getResidueShading().conservationApplied());
362 * JAL-3201 groups have their own ColourSchemeI instances
364 AlignmentI aln = viewport.getAlignment();
365 SequenceGroup sg1 = new SequenceGroup();
366 sg1.addSequence(aln.getSequenceAt(0), false);
367 sg1.addSequence(aln.getSequenceAt(2), false);
368 SequenceGroup sg2 = new SequenceGroup();
369 sg2.addSequence(aln.getSequenceAt(1), false);
370 sg2.addSequence(aln.getSequenceAt(3), false);
373 viewport.setColourAppliesToAllGroups(true);
374 viewport.setGlobalColourScheme(new ClustalxColourScheme());
375 ColourSchemeI cs0 = viewport.getGlobalColourScheme();
376 ColourSchemeI cs1 = sg1.getColourScheme();
377 ColourSchemeI cs2 = sg2.getColourScheme();
378 assertTrue(cs0 instanceof ClustalxColourScheme);
379 assertTrue(cs1 instanceof ClustalxColourScheme);
380 assertTrue(cs2 instanceof ClustalxColourScheme);
381 assertNotSame(cs0, cs1);
382 assertNotSame(cs0, cs2);
383 assertNotSame(cs1, cs2);
386 @Test(groups = { "Functional" })
387 public void testSetGetHasSearchResults()
389 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
390 "examples/uniref50.fa", DataSourceType.FILE);
391 SearchResultsI sr = new SearchResults();
392 SequenceI s1 = af.getViewport().getAlignment().getSequenceAt(0);
394 // create arbitrary range on first sequence
395 sr.addResult(s1, s1.getStart() + 10, s1.getStart() + 15);
398 af.getViewport().setSearchResults(sr);
400 assertTrue(af.getViewport().hasSearchResults());
402 assertEquals(sr, af.getViewport().getSearchResults());
404 // set(null) results in has -> false
406 af.getViewport().setSearchResults(null);
407 assertFalse(af.getViewport().hasSearchResults());
411 * Verify that setting the selection group has the side-effect of setting the
412 * context on the group, unless it already has one, but does not change
413 * whether the group is defined or not.
415 @Test(groups = { "Functional" })
416 public void testSetSelectionGroup()
418 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
419 "examples/uniref50.fa", DataSourceType.FILE);
420 AlignViewport av = af.getViewport();
421 SequenceGroup sg1 = new SequenceGroup();
422 SequenceGroup sg2 = new SequenceGroup();
423 SequenceGroup sg3 = new SequenceGroup();
425 av.setSelectionGroup(sg1);
426 assertSame(sg1.getContext(), av.getAlignment()); // context set
427 assertFalse(sg1.isDefined()); // group not defined
429 sg2.setContext(sg1, false);
430 av.setSelectionGroup(sg2);
431 assertFalse(sg2.isDefined()); // unchanged
432 assertSame(sg2.getContext(), sg1); // unchanged
434 // create a defined group
435 sg3.setContext(av.getAlignment(), true);
436 av.setSelectionGroup(sg3);
437 assertTrue(sg3.isDefined()); // unchanged
441 * Verify that setting/clearing SHOW_OCCUPANCY preference adds or omits
442 * occupancy row from viewport
444 @Test(groups = { "Functional" })
445 public void testShowOrDontShowOccupancy()
448 jalview.bin.Cache.setProperty("SHOW_OCCUPANCY",
449 Boolean.FALSE.toString());
450 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
451 "examples/uniref50.fa", DataSourceType.FILE);
452 AlignViewport av = af.getViewport();
453 Assert.assertNull(av.getAlignmentGapAnnotation(),
454 "Preference did not disable occupancy row.");
456 for (AlignmentAnnotation aa : av.getAlignment().findAnnotations(null,
461 Assert.assertEquals(c, 0, "Expected zero occupancy rows.");
464 jalview.bin.Cache.setProperty("SHOW_OCCUPANCY",
465 Boolean.TRUE.toString());
466 af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
467 DataSourceType.FILE);
468 av = af.getViewport();
469 Assert.assertNotNull(av.getAlignmentGapAnnotation(),
470 "Preference did not enable occupancy row.");
472 for (AlignmentAnnotation aa : av.getAlignment().findAnnotations(null,
473 null, av.getAlignmentGapAnnotation().label))
478 Assert.assertEquals(c, 1, "Expected to find one occupancy row.");
481 @Test(groups = { "Functional" })
482 public void testGetConsensusSeq()
489 * consensus expected to be A-C
491 String fasta = ">s1\nA-C\n>s2\nA-C\n>s3\nA-D\n>s4\n--D\n";
492 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(fasta,
493 DataSourceType.PASTE);
494 AlignViewport testme = af.getViewport();
495 waitForCalculations(testme);
496 SequenceI cons = testme.getConsensusSeq();
497 assertEquals("A-C", cons.getSequenceAsString());
500 @Test(groups = { "Functional" })
501 public void testHideRevealSequences()
503 ViewportRanges ranges = testee.getRanges();
504 assertEquals(3, al.getHeight());
505 assertEquals(0, ranges.getStartSeq());
506 assertEquals(2, ranges.getEndSeq());
509 * hide first sequence
511 testee.hideSequence(new SequenceI[] { al.getSequenceAt(0) });
512 assertEquals(2, al.getHeight());
513 assertEquals(0, ranges.getStartSeq());
514 assertEquals(1, ranges.getEndSeq());
517 * reveal hidden sequences above the first
519 testee.showSequence(0);
520 assertEquals(3, al.getHeight());
521 assertEquals(0, ranges.getStartSeq());
522 assertEquals(2, ranges.getEndSeq());
525 * hide first and third sequences
529 { al.getSequenceAt(0), al.getSequenceAt(2) });
530 assertEquals(1, al.getHeight());
531 assertEquals(0, ranges.getStartSeq());
532 assertEquals(0, ranges.getEndSeq());
535 * reveal all hidden sequences
537 testee.showAllHiddenSeqs();
538 assertEquals(3, al.getHeight());
539 assertEquals(0, ranges.getStartSeq());
540 assertEquals(2, ranges.getEndSeq());
542 @Test(groups = {"Functional"})
543 public void testGetSelectionAsNewSequences_withContactMatrices()
545 SequenceI seq = new Sequence("seq","ACADA");
546 ContactMatrixI cmat = new SeqDistanceContactMatrix(5);
547 seq.addContactList(cmat);
548 Alignment al = new Alignment(new SequenceI[] {seq.deriveSequence() });
549 al.addAnnotation(al.getSequenceAt(0).getAnnotation()[0]);
550 AlignFrame af = new AlignFrame(al,500,500);
552 SequenceI selseqs[] = af.getViewport().getSelectionAsNewSequence();
553 assertNotNull(selseqs[0].getAnnotation());
554 assertNotNull(selseqs[0].getAnnotation()[0]);
555 assertEquals(cmat,selseqs[0].getContactMatrixFor(selseqs[0].getAnnotation()[0]));
557 assertNotNull(selseqs[0].getContactListFor(selseqs[0].getAnnotation()[0], 2));
559 // now select everything and test again
560 af.selectAllSequenceMenuItem_actionPerformed(null);
561 selseqs = af.getViewport().getSelectionAsNewSequence();
562 assertNotNull(selseqs[0].getAnnotation());
563 assertNotNull(selseqs[0].getAnnotation()[0]);
564 assertEquals(cmat,selseqs[0].getContactMatrixFor(selseqs[0].getAnnotation()[0]));
565 assertNotNull(selseqs[0].getContactListFor(selseqs[0].getAnnotation()[0], 2));