36932d1597907cbf1e2f0edeaafefa68fdcc62e8
[jalview.git] / test / jalview / datamodel / ColumnSelectionTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
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.
11  *  
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.
16  * 
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.
20  */
21 package jalview.datamodel;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertSame;
26 import static org.testng.AssertJUnit.assertTrue;
27
28 import java.util.Arrays;
29 import java.util.List;
30
31 import org.testng.annotations.Test;
32
33 public class ColumnSelectionTest
34 {
35
36   @Test(groups = { "Functional" })
37   public void testAddElement()
38   {
39     ColumnSelection cs = new ColumnSelection();
40     cs.addElement(2);
41     cs.addElement(5);
42     cs.addElement(3);
43     cs.addElement(5); // ignored
44     List<Integer> sel = cs.getSelected();
45     assertEquals("[2, 5, 3]", sel.toString());
46   }
47
48   /**
49    * Test the remove method - in particular to verify that remove(int i) removes
50    * the element whose value is i, _NOT_ the i'th element.
51    */
52   @Test(groups = { "Functional" })
53   public void testRemoveElement()
54   {
55     ColumnSelection cs = new ColumnSelection();
56     cs.addElement(2);
57     cs.addElement(5);
58
59     // removing elements not in the list has no effect
60     cs.removeElement(0);
61     cs.removeElement(1);
62     List<Integer> sel = cs.getSelected();
63     assertEquals(2, sel.size());
64     assertEquals(new Integer(2), sel.get(0));
65     assertEquals(new Integer(5), sel.get(1));
66
67     // removing an element in the list removes it
68     cs.removeElement(2);
69     assertEquals(1, sel.size());
70     assertEquals(new Integer(5), sel.get(0));
71   }
72
73   /**
74    * Test the method that finds the visible column position of an alignment
75    * column, allowing for hidden columns.
76    */
77   @Test(groups = { "Functional" })
78   public void testFindColumnPosition()
79   {
80     ColumnSelection cs = new ColumnSelection();
81     assertEquals(5, cs.findColumnPosition(5));
82
83     // hiding column 6 makes no difference
84     cs.hideColumns(6, 6);
85     assertEquals(5, cs.findColumnPosition(5));
86
87     // hiding column 4 moves column 5 to column 4
88     cs.hideColumns(4, 4);
89     assertEquals(4, cs.findColumnPosition(5));
90
91     // hiding columns 1 and 2 moves column 5 to column 2
92     cs.hideColumns(1, 2);
93     assertEquals(2, cs.findColumnPosition(5));
94   }
95
96   /**
97    * Test the code used to locate the reference sequence ruler origin
98    */
99   @Test(groups = { "Functional" })
100   public void testLocateVisibleBoundsofSequence()
101   {
102     ColumnSelection cs = new ColumnSelection();
103     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
104     assertEquals(2, seq.findIndex(seq.getStart()));
105
106     // no hidden columns
107     assertEquals(
108             Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
109                 seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
110                 seq.getEnd() }),
111             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
112
113     // hidden column on gap after end of sequence - should not affect bounds
114     cs.hideColumns(13);
115     assertEquals(
116             Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
117                 seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
118                 seq.getEnd() }),
119             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
120
121     cs.revealAllHiddenColumns();
122     // hidden column on gap before beginning of sequence - should vis bounds by
123     // one
124     cs.hideColumns(0);
125     assertEquals(
126             Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 2,
127                 seq.findIndex(seq.getEnd()) - 2, seq.getStart(),
128                 seq.getEnd() }),
129             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
130
131     cs.revealAllHiddenColumns();
132     // hide columns around most of sequence - leave one residue remaining
133     cs.hideColumns(1, 3);
134     cs.hideColumns(6, 11);
135     assertEquals("-D",
136             cs.getVisibleSequenceStrings(0, 5, new SequenceI[] { seq })[0]);
137     assertEquals(Arrays.toString(new int[] { 1, 1, 3, 3 }),
138             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
139     cs.revealAllHiddenColumns();
140
141     // hide whole sequence - should just get location of hidden region
142     // containing sequence
143     cs.hideColumns(1, 11);
144     assertEquals(Arrays.toString(new int[] { 0, 1, 0, 0 }),
145             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
146
147   }
148
149   @Test(groups = { "Functional" })
150   public void testHideColumns()
151   {
152     ColumnSelection cs = new ColumnSelection();
153     cs.hideColumns(5);
154     List<int[]> hidden = cs.getHiddenColumns();
155     assertEquals(1, hidden.size());
156     assertEquals("[5, 5]", Arrays.toString(hidden.get(0)));
157
158     cs.hideColumns(3);
159     assertEquals(2, hidden.size());
160     // two hidden ranges, in order:
161     assertSame(hidden, cs.getHiddenColumns());
162     assertEquals("[3, 3]", Arrays.toString(hidden.get(0)));
163     assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
164
165     // hiding column 4 expands [3, 3] to [3, 4]
166     // not fancy enough to coalesce this into [3, 5] though
167     cs.hideColumns(4);
168     hidden = cs.getHiddenColumns();
169     assertEquals(2, hidden.size());
170     assertEquals("[3, 4]", Arrays.toString(hidden.get(0)));
171     assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
172
173     // clear hidden columns (note they are added to selected)
174     cs.revealAllHiddenColumns();
175     // it is now actually null but getter returns an empty list
176     assertTrue(cs.getHiddenColumns().isEmpty());
177
178     cs.hideColumns(3, 6);
179     hidden = cs.getHiddenColumns();
180     int[] firstHiddenRange = hidden.get(0);
181     assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
182
183     // adding a subrange of already hidden should do nothing
184     cs.hideColumns(4, 5);
185     assertEquals(1, hidden.size());
186     assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
187     cs.hideColumns(3, 5);
188     assertEquals(1, hidden.size());
189     assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
190     cs.hideColumns(4, 6);
191     assertEquals(1, hidden.size());
192     assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
193     cs.hideColumns(3, 6);
194     assertEquals(1, hidden.size());
195     assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
196
197     cs.revealAllHiddenColumns();
198     cs.hideColumns(2, 4);
199     hidden = cs.getHiddenColumns();
200     assertEquals(1, hidden.size());
201     assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
202
203     // extend contiguous with 2 positions overlap
204     cs.hideColumns(3, 5);
205     assertEquals(1, hidden.size());
206     assertEquals("[2, 5]", Arrays.toString(hidden.get(0)));
207
208     // extend contiguous with 1 position overlap
209     cs.hideColumns(5, 6);
210     assertEquals(1, hidden.size());
211     assertEquals("[2, 6]", Arrays.toString(hidden.get(0)));
212
213     // extend contiguous with overlap both ends:
214     cs.hideColumns(1, 7);
215     assertEquals(1, hidden.size());
216     assertEquals("[1, 7]", Arrays.toString(hidden.get(0)));
217   }
218
219   /**
220    * Test the method that hides a specified column including any adjacent
221    * selected columns. This is a convenience method for the case where multiple
222    * column regions are selected and then hidden using menu option View | Hide |
223    * Selected Columns.
224    */
225   @Test(groups = { "Functional" })
226   public void testHideColumns_withSelection()
227   {
228     ColumnSelection cs = new ColumnSelection();
229     // select columns 4-6
230     cs.addElement(4);
231     cs.addElement(5);
232     cs.addElement(6);
233     // hide column 5 (and adjacent):
234     cs.hideColumns(5);
235     // 4,5,6 now hidden:
236     List<int[]> hidden = cs.getHiddenColumns();
237     assertEquals(1, hidden.size());
238     assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
239     // none now selected:
240     assertTrue(cs.getSelected().isEmpty());
241
242     // repeat, hiding column 4 (5 and 6)
243     cs = new ColumnSelection();
244     cs.addElement(4);
245     cs.addElement(5);
246     cs.addElement(6);
247     cs.hideColumns(4);
248     hidden = cs.getHiddenColumns();
249     assertEquals(1, hidden.size());
250     assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
251     assertTrue(cs.getSelected().isEmpty());
252
253     // repeat, hiding column (4, 5 and) 6
254     cs = new ColumnSelection();
255     cs.addElement(4);
256     cs.addElement(5);
257     cs.addElement(6);
258     cs.hideColumns(6);
259     hidden = cs.getHiddenColumns();
260     assertEquals(1, hidden.size());
261     assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
262     assertTrue(cs.getSelected().isEmpty());
263
264     // repeat, with _only_ adjacent columns selected
265     cs = new ColumnSelection();
266     cs.addElement(4);
267     cs.addElement(6);
268     cs.hideColumns(5);
269     hidden = cs.getHiddenColumns();
270     assertEquals(1, hidden.size());
271     assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
272     assertTrue(cs.getSelected().isEmpty());
273   }
274
275   /**
276    * Test the method that hides all (possibly disjoint) selected column ranges
277    */
278   @Test(groups = { "Functional" })
279   public void testHideSelectedColumns()
280   {
281     ColumnSelection cs = new ColumnSelection();
282     int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
283     for (int col : sel)
284     {
285       cs.addElement(col);
286     }
287     cs.hideColumns(15, 18);
288
289     cs.hideSelectedColumns();
290     assertTrue(cs.getSelected().isEmpty());
291     List<int[]> hidden = cs.getHiddenColumns();
292     assertEquals(4, hidden.size());
293     assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
294     assertEquals("[7, 9]", Arrays.toString(hidden.get(1)));
295     assertEquals("[15, 18]", Arrays.toString(hidden.get(2)));
296     assertEquals("[20, 22]", Arrays.toString(hidden.get(3)));
297   }
298
299   /**
300    * Test the method that gets runs of selected columns ordered by column. If
301    * this fails, HideSelectedColumns may also fail
302    */
303   @Test(groups = { "Functional" })
304   public void testgetSelectedRanges()
305   {
306     ColumnSelection cs = new ColumnSelection();
307     int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
308     for (int col : sel)
309     {
310       cs.addElement(col);
311     }
312     List<int[]> range;
313     range = cs.getSelectedRanges();
314     assertEquals(3, range.size());
315     assertEquals("[2, 4]", Arrays.toString(range.get(0)));
316     assertEquals("[7, 9]", Arrays.toString(range.get(1)));
317     assertEquals("[20, 22]", Arrays.toString(range.get(2)));
318     cs.addElement(0);
319     cs.addElement(1);
320     range = cs.getSelectedRanges();
321     assertEquals(3, range.size());
322     assertEquals("[0, 4]", Arrays.toString(range.get(0)));
323   }
324
325   /**
326    * Test the method that reveals a range of hidden columns given the start
327    * column of the range
328    */
329   @Test(groups = { "Functional" })
330   public void testRevealHiddenColumns()
331   {
332     ColumnSelection cs = new ColumnSelection();
333     cs.hideColumns(5, 8);
334     cs.addElement(10);
335     cs.revealHiddenColumns(5);
336     // hidden columns list now null but getter returns empty list:
337     assertTrue(cs.getHiddenColumns().isEmpty());
338     // revealed columns are marked as selected (added to selection):
339     assertEquals("[10, 5, 6, 7, 8]", cs.getSelected().toString());
340
341     // calling with a column other than the range start does nothing:
342     cs = new ColumnSelection();
343     cs.hideColumns(5, 8);
344     List<int[]> hidden = cs.getHiddenColumns();
345     cs.revealHiddenColumns(6);
346     assertSame(hidden, cs.getHiddenColumns());
347     assertTrue(cs.getSelected().isEmpty());
348   }
349
350   @Test(groups = { "Functional" })
351   public void testRevealAllHiddenColumns()
352   {
353     ColumnSelection cs = new ColumnSelection();
354     cs.hideColumns(5, 8);
355     cs.hideColumns(2, 3);
356     cs.addElement(11);
357     cs.addElement(1);
358     cs.revealAllHiddenColumns();
359
360     /*
361      * revealing hidden columns adds them (in order) to the (unordered)
362      * selection list
363      */
364     assertTrue(cs.getHiddenColumns().isEmpty());
365     assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]", cs.getSelected().toString());
366   }
367
368   @Test(groups = { "Functional" })
369   public void testIsVisible()
370   {
371     ColumnSelection cs = new ColumnSelection();
372     cs.hideColumns(2, 4);
373     cs.hideColumns(6, 7);
374     assertTrue(cs.isVisible(0));
375     assertTrue(cs.isVisible(-99));
376     assertTrue(cs.isVisible(1));
377     assertFalse(cs.isVisible(2));
378     assertFalse(cs.isVisible(3));
379     assertFalse(cs.isVisible(4));
380     assertTrue(cs.isVisible(5));
381     assertFalse(cs.isVisible(6));
382     assertFalse(cs.isVisible(7));
383   }
384
385   @Test(groups = { "Functional" })
386   public void testGetVisibleContigs()
387   {
388     ColumnSelection cs = new ColumnSelection();
389     cs.hideColumns(3, 6);
390     cs.hideColumns(8, 9);
391     cs.hideColumns(12, 12);
392
393     // start position is inclusive, end position exclusive:
394     int[] visible = cs.getVisibleContigs(1, 13);
395     assertEquals("[1, 2, 7, 7, 10, 11]", Arrays.toString(visible));
396
397     visible = cs.getVisibleContigs(4, 14);
398     assertEquals("[7, 7, 10, 11, 13, 13]", Arrays.toString(visible));
399
400     visible = cs.getVisibleContigs(3, 10);
401     assertEquals("[7, 7]", Arrays.toString(visible));
402
403     visible = cs.getVisibleContigs(4, 6);
404     assertEquals("[]", Arrays.toString(visible));
405   }
406
407   @Test(groups = { "Functional" })
408   public void testInvertColumnSelection()
409   {
410     ColumnSelection cs = new ColumnSelection();
411     cs.addElement(4);
412     cs.addElement(6);
413     cs.addElement(8);
414     cs.hideColumns(3, 3);
415     cs.hideColumns(6, 6);
416
417     // invert selection from start (inclusive) to end (exclusive)
418     // hidden columns are _not_ changed
419     cs.invertColumnSelection(2, 9);
420     assertEquals("[2, 5, 7]", cs.getSelected().toString());
421
422     cs.invertColumnSelection(1, 9);
423     assertEquals("[1, 4, 8]", cs.getSelected().toString());
424   }
425
426   @Test(groups = { "Functional" })
427   public void testMaxColumnSelection()
428   {
429     ColumnSelection cs = new ColumnSelection();
430     cs.addElement(0);
431     cs.addElement(513);
432     cs.addElement(1);
433     assertEquals(513, cs.getMax());
434     cs.removeElement(513);
435     assertEquals(1, cs.getMax());
436     cs.removeElement(1);
437     assertEquals(0, cs.getMax());
438     cs.addElement(512);
439     cs.addElement(513);
440     assertEquals(513, cs.getMax());
441
442   }
443
444   @Test(groups = { "Functional" })
445   public void testMinColumnSelection()
446   {
447     ColumnSelection cs = new ColumnSelection();
448     cs.addElement(0);
449     cs.addElement(513);
450     cs.addElement(1);
451     assertEquals(0, cs.getMin());
452     cs.removeElement(0);
453     assertEquals(1, cs.getMin());
454     cs.addElement(0);
455     assertEquals(0, cs.getMin());
456   }
457 }