JAL-3438 spotless for 2.11.2.0
[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.assertTrue;
26 import static org.testng.AssertJUnit.fail;
27
28 import jalview.analysis.AlignmentGenerator;
29 import jalview.gui.JvOptionPane;
30 import jalview.viewmodel.annotationfilter.AnnotationFilterParameter;
31 import jalview.viewmodel.annotationfilter.AnnotationFilterParameter.SearchableAnnotationField;
32 import jalview.viewmodel.annotationfilter.AnnotationFilterParameter.ThresholdType;
33
34 import java.util.Arrays;
35 import java.util.BitSet;
36 import java.util.Collections;
37 import java.util.ConcurrentModificationException;
38 import java.util.Iterator;
39 import java.util.List;
40
41 import org.testng.annotations.BeforeClass;
42 import org.testng.annotations.Test;
43
44 public class ColumnSelectionTest
45 {
46
47   @BeforeClass(alwaysRun = true)
48   public void setUpJvOptionPane()
49   {
50     JvOptionPane.setInteractiveMode(false);
51     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
52   }
53
54   @Test(groups = { "Functional" })
55   public void testAddElement()
56   {
57     ColumnSelection cs = new ColumnSelection();
58     cs.addElement(2);
59     cs.addElement(5);
60     cs.addElement(3);
61     cs.addElement(5); // ignored
62     List<Integer> sel = cs.getSelected();
63     assertEquals("[2, 5, 3]", sel.toString());
64   }
65
66   @Test(groups = { "Functional" })
67   public void testSetElementsFrom()
68   {
69     ColumnSelection fromcs = new ColumnSelection();
70     ColumnSelection tocs = new ColumnSelection();
71     HiddenColumns hidden = new HiddenColumns();
72
73     fromcs.addElement(2);
74     fromcs.addElement(3);
75     fromcs.addElement(5);
76
77     tocs.setElementsFrom(fromcs, hidden);
78     assertTrue(tocs.equals(fromcs));
79
80     hidden.hideColumns(4, 6);
81     tocs.setElementsFrom(fromcs, hidden);
82
83     // expect cols 2 and 3 to be selected but not 5
84     ColumnSelection expectcs = new ColumnSelection();
85     expectcs.addElement(2);
86     expectcs.addElement(3);
87     assertTrue(tocs.equals(expectcs));
88   }
89
90   /**
91    * Test the remove method - in particular to verify that remove(int i) removes
92    * the element whose value is i, _NOT_ the i'th element.
93    */
94   @Test(groups = { "Functional" })
95   public void testRemoveElement()
96   {
97     ColumnSelection cs = new ColumnSelection();
98     cs.addElement(2);
99     cs.addElement(5);
100
101     // removing elements not in the list has no effect
102     cs.removeElement(0);
103     cs.removeElement(1);
104     List<Integer> sel = cs.getSelected();
105     assertEquals(2, sel.size());
106     assertEquals(Integer.valueOf(2), sel.get(0));
107     assertEquals(Integer.valueOf(5), sel.get(1));
108
109     // removing an element in the list removes it
110     cs.removeElement(2);
111     // ...and also from the read-only view
112     assertEquals(1, sel.size());
113     sel = cs.getSelected();
114     assertEquals(1, sel.size());
115     assertEquals(Integer.valueOf(5), sel.get(0));
116   }
117
118   /**
119    * Test the method that hides a specified column including any adjacent
120    * selected columns. This is a convenience method for the case where multiple
121    * column regions are selected and then hidden using menu option View | Hide |
122    * Selected Columns.
123    */
124   @Test(groups = { "Functional" })
125   public void testHideColumns_withSelection()
126   {
127     // create random alignment
128     AlignmentGenerator gen = new AlignmentGenerator(false);
129     AlignmentI al = gen.generate(50, 20, 123, 5, 5);
130
131     ColumnSelection cs = new ColumnSelection();
132     // select columns 4-6
133     cs.addElement(4);
134     cs.addElement(5);
135     cs.addElement(6);
136     // hide column 5 (and adjacent):
137     cs.hideSelectedColumns(5, al.getHiddenColumns());
138     // 4,5,6 now hidden:
139     Iterator<int[]> regions = al.getHiddenColumns().iterator();
140     assertEquals(1, al.getHiddenColumns().getNumberOfRegions());
141     assertEquals("[4, 6]", Arrays.toString(regions.next()));
142     // none now selected:
143     assertTrue(cs.getSelected().isEmpty());
144
145     // repeat, hiding column 4 (5 and 6)
146     al = gen.generate(50, 20, 123, 5, 5);
147     cs = new ColumnSelection();
148     cs.addElement(4);
149     cs.addElement(5);
150     cs.addElement(6);
151     cs.hideSelectedColumns(4, al.getHiddenColumns());
152     regions = al.getHiddenColumns().iterator();
153     assertEquals(1, al.getHiddenColumns().getNumberOfRegions());
154     assertEquals("[4, 6]", Arrays.toString(regions.next()));
155     assertTrue(cs.getSelected().isEmpty());
156
157     // repeat, hiding column (4, 5 and) 6
158     al = gen.generate(50, 20, 123, 5, 5);
159     cs = new ColumnSelection();
160     cs.addElement(4);
161     cs.addElement(5);
162     cs.addElement(6);
163     cs.hideSelectedColumns(6, al.getHiddenColumns());
164     regions = al.getHiddenColumns().iterator();
165     assertEquals(1, al.getHiddenColumns().getNumberOfRegions());
166     assertEquals("[4, 6]", Arrays.toString(regions.next()));
167     assertTrue(cs.getSelected().isEmpty());
168
169     // repeat, with _only_ adjacent columns selected
170     al = gen.generate(50, 20, 123, 5, 5);
171     cs = new ColumnSelection();
172     cs.addElement(4);
173     cs.addElement(6);
174     cs.hideSelectedColumns(5, al.getHiddenColumns());
175     regions = al.getHiddenColumns().iterator();
176     assertEquals(1, al.getHiddenColumns().getNumberOfRegions());
177     assertEquals("[4, 6]", Arrays.toString(regions.next()));
178     assertTrue(cs.getSelected().isEmpty());
179   }
180
181   /**
182    * Test the method that hides all (possibly disjoint) selected column ranges
183    */
184   @Test(groups = { "Functional" })
185   public void testHideSelectedColumns()
186   {
187     // create random alignment
188     AlignmentGenerator gen = new AlignmentGenerator(false);
189     AlignmentI al = gen.generate(50, 20, 123, 5, 5);
190
191     ColumnSelection cs = new ColumnSelection();
192     int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
193     for (int col : sel)
194     {
195       cs.addElement(col);
196     }
197
198     HiddenColumns cols = al.getHiddenColumns();
199     cols.hideColumns(15, 18);
200
201     cs.hideSelectedColumns(al);
202     assertTrue(cs.getSelected().isEmpty());
203     Iterator<int[]> regions = cols.iterator();
204     assertEquals(4, cols.getNumberOfRegions());
205     assertEquals("[2, 4]", Arrays.toString(regions.next()));
206     assertEquals("[7, 9]", Arrays.toString(regions.next()));
207     assertEquals("[15, 18]", Arrays.toString(regions.next()));
208     assertEquals("[20, 22]", Arrays.toString(regions.next()));
209   }
210
211   /**
212    * Test the method that gets runs of selected columns ordered by column. If
213    * this fails, HideSelectedColumns may also fail
214    */
215   @Test(groups = { "Functional" })
216   public void testGetSelectedRanges()
217   {
218     /*
219      * getSelectedRanges returns ordered columns regardless
220      * of the order in which they are added
221      */
222     ColumnSelection cs = new ColumnSelection();
223     int[] sel = { 4, 3, 7, 21, 9, 20, 8, 22, 2 };
224     for (int col : sel)
225     {
226       cs.addElement(col);
227     }
228     List<int[]> range;
229     range = cs.getSelectedRanges();
230     assertEquals(3, range.size());
231     assertEquals("[2, 4]", Arrays.toString(range.get(0)));
232     assertEquals("[7, 9]", Arrays.toString(range.get(1)));
233     assertEquals("[20, 22]", Arrays.toString(range.get(2)));
234     cs.addElement(0);
235     cs.addElement(1);
236     range = cs.getSelectedRanges();
237     assertEquals(3, range.size());
238     assertEquals("[0, 4]", Arrays.toString(range.get(0)));
239   }
240
241   @Test(groups = { "Functional" })
242   public void testInvertColumnSelection()
243   {
244     // create random alignment
245     AlignmentGenerator gen = new AlignmentGenerator(false);
246     AlignmentI al = gen.generate(50, 20, 123, 5, 5);
247
248     ColumnSelection cs = new ColumnSelection();
249     cs.addElement(4);
250     cs.addElement(6);
251     cs.addElement(8);
252
253     HiddenColumns cols = al.getHiddenColumns();
254     cols.hideColumns(3, 3);
255     cols.hideColumns(6, 6);
256
257     // invert selection from start (inclusive) to end (exclusive)
258     cs.invertColumnSelection(2, 9, al);
259     assertEquals("[2, 5, 7]", cs.getSelected().toString());
260
261     cs.invertColumnSelection(1, 9, al);
262     assertEquals("[1, 4, 8]", cs.getSelected().toString());
263   }
264
265   @Test(groups = { "Functional" })
266   public void testMaxColumnSelection()
267   {
268     ColumnSelection cs = new ColumnSelection();
269     cs.addElement(0);
270     cs.addElement(513);
271     cs.addElement(1);
272     assertEquals(513, cs.getMax());
273     cs.removeElement(513);
274     assertEquals(1, cs.getMax());
275     cs.removeElement(1);
276     assertEquals(0, cs.getMax());
277     cs.addElement(512);
278     cs.addElement(513);
279     assertEquals(513, cs.getMax());
280
281   }
282
283   @Test(groups = { "Functional" })
284   public void testMinColumnSelection()
285   {
286     ColumnSelection cs = new ColumnSelection();
287     cs.addElement(0);
288     cs.addElement(513);
289     cs.addElement(1);
290     assertEquals(0, cs.getMin());
291     cs.removeElement(0);
292     assertEquals(1, cs.getMin());
293     cs.addElement(0);
294     assertEquals(0, cs.getMin());
295   }
296
297   @Test(groups = { "Functional" })
298   public void testEquals()
299   {
300     ColumnSelection cs = new ColumnSelection();
301     cs.addElement(0);
302     cs.addElement(513);
303     cs.addElement(1);
304
305     // same selections added in a different order
306     ColumnSelection cs2 = new ColumnSelection();
307     cs2.addElement(1);
308     cs2.addElement(513);
309     cs2.addElement(0);
310
311     assertTrue(cs.equals(cs2));
312     assertTrue(cs.equals(cs));
313     assertTrue(cs2.equals(cs));
314     assertTrue(cs2.equals(cs2));
315
316     cs2.addElement(12);
317     assertFalse(cs.equals(cs2));
318     assertFalse(cs2.equals(cs));
319
320     cs2.removeElement(12);
321     assertTrue(cs.equals(cs2));
322   }
323
324   /*
325       cs2.hideSelectedColumns(88);
326       assertFalse(cs.equals(cs2));
327       /*
328        * unhiding a column adds it to selection!
329        */
330   /*    cs2.revealHiddenColumns(88);
331       assertFalse(cs.equals(cs2));
332       cs.addElement(88);
333       assertTrue(cs.equals(cs2));
334     */
335
336   /**
337    * Test the method that returns selected columns, in the order in which they
338    * were added
339    */
340   @Test(groups = { "Functional" })
341   public void testGetSelected()
342   {
343     ColumnSelection cs = new ColumnSelection();
344     int[] sel = { 4, 3, 7, 21 };
345     for (int col : sel)
346     {
347       cs.addElement(col);
348     }
349
350     List<Integer> selected = cs.getSelected();
351     assertEquals(4, selected.size());
352     assertEquals("[4, 3, 7, 21]", selected.toString());
353
354     /*
355      * getSelected returns a read-only view of the list
356      * verify the view follows any changes in it
357      */
358     cs.removeElement(7);
359     cs.addElement(1);
360     cs.removeElement(4);
361     assertEquals("[3, 21, 1]", selected.toString());
362   }
363
364   /**
365    * Test to verify that the list returned by getSelection cannot be modified
366    */
367   @Test(groups = { "Functional" })
368   public void testGetSelected_isReadOnly()
369   {
370     ColumnSelection cs = new ColumnSelection();
371     cs.addElement(3);
372
373     List<Integer> selected = cs.getSelected();
374     try
375     {
376       selected.clear();
377       fail("expected exception");
378     } catch (UnsupportedOperationException e)
379     {
380       // expected
381     }
382     try
383     {
384       selected.add(1);
385       fail("expected exception");
386     } catch (UnsupportedOperationException e)
387     {
388       // expected
389     }
390     try
391     {
392       selected.remove(3);
393       fail("expected exception");
394     } catch (UnsupportedOperationException e)
395     {
396       // expected
397     }
398     try
399     {
400       Collections.sort(selected);
401       fail("expected exception");
402     } catch (UnsupportedOperationException e)
403     {
404       // expected
405     }
406   }
407
408   /**
409    * Test that demonstrates a ConcurrentModificationException is thrown if you
410    * change the selection while iterating over it
411    */
412   @Test(
413     groups = "Functional",
414     expectedExceptions =
415     { ConcurrentModificationException.class })
416   public void testGetSelected_concurrentModification()
417   {
418     ColumnSelection cs = new ColumnSelection();
419     cs.addElement(0);
420     cs.addElement(1);
421     cs.addElement(2);
422
423     /*
424      * simulate changing the list under us (e.g. in a separate
425      * thread) while iterating over it -> ConcurrentModificationException
426      */
427     List<Integer> selected = cs.getSelected();
428     for (Integer col : selected)
429     {
430       if (col.intValue() == 0)
431       {
432         cs.removeElement(1);
433       }
434     }
435   }
436
437   @Test(groups = "Functional")
438   public void testMarkColumns()
439   {
440     ColumnSelection cs = new ColumnSelection();
441     cs.addElement(5); // this will be cleared
442     BitSet toMark = new BitSet();
443     toMark.set(1);
444     toMark.set(3);
445     toMark.set(6);
446     toMark.set(9);
447
448     assertTrue(cs.markColumns(toMark, 3, 8, false, false, false));
449     List<Integer> selected = cs.getSelected();
450     assertEquals(2, selected.size());
451     assertTrue(selected.contains(3));
452     assertTrue(selected.contains(6));
453   }
454
455   @Test(groups = "Functional")
456   public void testMarkColumns_extend()
457   {
458     ColumnSelection cs = new ColumnSelection();
459     cs.addElement(1);
460     cs.addElement(5);
461     BitSet toMark = new BitSet();
462     toMark.set(1);
463     toMark.set(3);
464     toMark.set(6);
465     toMark.set(9);
466
467     /*
468      * extending selection of {3, 6} should leave {1, 3, 5, 6} selected
469      */
470     assertTrue(cs.markColumns(toMark, 3, 8, false, true, false));
471     List<Integer> selected = cs.getSelected();
472     assertEquals(4, selected.size());
473     assertTrue(selected.contains(1));
474     assertTrue(selected.contains(3));
475     assertTrue(selected.contains(5));
476     assertTrue(selected.contains(6));
477   }
478
479   @Test(groups = "Functional")
480   public void testMarkColumns_invert()
481   {
482     ColumnSelection cs = new ColumnSelection();
483     cs.addElement(5); // this will be cleared
484     BitSet toMark = new BitSet();
485     toMark.set(1);
486     toMark.set(3);
487     toMark.set(6);
488     toMark.set(9);
489
490     /*
491      * inverted selection of {3, 6} should select {4, 5, 7, 8}
492      */
493     assertTrue(cs.markColumns(toMark, 3, 8, true, false, false));
494     List<Integer> selected = cs.getSelected();
495     assertEquals(4, selected.size());
496     assertTrue(selected.contains(4));
497     assertTrue(selected.contains(5));
498     assertTrue(selected.contains(7));
499     assertTrue(selected.contains(8));
500   }
501
502   @Test(groups = "Functional")
503   public void testMarkColumns_toggle()
504   {
505     ColumnSelection cs = new ColumnSelection();
506     cs.addElement(1); // outside change range
507     cs.addElement(3);
508     cs.addElement(4);
509     cs.addElement(10); // outside change range
510     BitSet toMark = new BitSet();
511     toMark.set(1);
512     toMark.set(3);
513     toMark.set(6);
514     toMark.set(9);
515
516     /*
517      * toggling state of {3, 6} should leave {1, 4, 6, 10} selected
518      */
519     assertTrue(cs.markColumns(toMark, 3, 8, false, false, true));
520     List<Integer> selected = cs.getSelected();
521     assertEquals(4, selected.size());
522     assertTrue(selected.contains(1));
523     assertTrue(selected.contains(4));
524     assertTrue(selected.contains(6));
525     assertTrue(selected.contains(10));
526   }
527
528   @Test(groups = "Functional")
529   public void testCopyConstructor()
530   {
531     ColumnSelection cs = new ColumnSelection();
532     cs.addElement(3);
533     cs.addElement(1);
534
535     ColumnSelection cs2 = new ColumnSelection(cs);
536     assertTrue(cs2.hasSelectedColumns());
537
538     // order of column selection is preserved
539     assertEquals("[3, 1]", cs2.getSelected().toString());
540   }
541
542   @Test(groups = { "Functional" })
543   public void testStretchGroup_expand()
544   {
545     /*
546      * test that emulates clicking column 4 (selected)
547      * and dragging right to column 5 (all base 0)
548      */
549     ColumnSelection cs = new ColumnSelection();
550     cs.addElement(4);
551     SequenceGroup sg = new SequenceGroup();
552     sg.setStartRes(4);
553     sg.setEndRes(4);
554     cs.stretchGroup(5, sg, 4, 4);
555     assertEquals(cs.getSelected().size(), 2);
556     assertTrue(cs.contains(4));
557     assertTrue(cs.contains(5));
558     assertEquals(sg.getStartRes(), 4);
559     assertEquals(sg.getEndRes(), 5);
560
561     /*
562      * emulate drag right with columns 10-20 already selected
563      */
564     cs.clear();
565     for (int i = 10; i <= 20; i++)
566     {
567       cs.addElement(i);
568     }
569     assertEquals(cs.getSelected().size(), 11);
570     sg = new SequenceGroup();
571     sg.setStartRes(10);
572     sg.setEndRes(20);
573     cs.stretchGroup(21, sg, 10, 20);
574     assertEquals(cs.getSelected().size(), 12);
575     assertTrue(cs.contains(10));
576     assertTrue(cs.contains(21));
577     assertEquals(sg.getStartRes(), 10);
578     assertEquals(sg.getEndRes(), 21);
579   }
580
581   @Test(groups = { "Functional" })
582   public void testStretchGroup_shrink()
583   {
584     /*
585      * emulate drag left to 19 with columns 10-20 already selected
586      */
587     ColumnSelection cs = new ColumnSelection();
588     for (int i = 10; i <= 20; i++)
589     {
590       cs.addElement(i);
591     }
592     assertEquals(cs.getSelected().size(), 11);
593     SequenceGroup sg = new SequenceGroup();
594     sg.setStartRes(10);
595     sg.setEndRes(20);
596     cs.stretchGroup(19, sg, 10, 20);
597     assertEquals(cs.getSelected().size(), 10);
598     assertTrue(cs.contains(10));
599     assertTrue(cs.contains(19));
600     assertFalse(cs.contains(20));
601     assertEquals(sg.getStartRes(), 10);
602     assertEquals(sg.getEndRes(), 19);
603   }
604
605   @Test(groups = { "Functional" })
606   public void testFilterAnnotations()
607   {
608     ColumnSelection cs = new ColumnSelection();
609
610     /*
611      * filter with no conditions clears the selection
612      */
613     Annotation[] anns = new Annotation[] { null };
614     AnnotationFilterParameter filter = new AnnotationFilterParameter();
615     cs.addElement(3);
616     int added = cs.filterAnnotations(anns, filter);
617     assertEquals(0, added);
618     assertTrue(cs.isEmpty());
619
620     /*
621      * select on description (regex)
622      */
623     filter.setRegexString("w.rld");
624     filter.addRegexSearchField(SearchableAnnotationField.DESCRIPTION);
625     Annotation helix = new Annotation("(", "hello", '<', 2f);
626     Annotation sheet = new Annotation("(", "world", '<', 2f);
627     added = cs.filterAnnotations(new Annotation[] { null, helix, sheet },
628             filter);
629     assertEquals(1, added);
630     assertTrue(cs.contains(2));
631
632     /*
633      * select on label (invalid regex, exact match)
634      */
635     filter = new AnnotationFilterParameter();
636     filter.setRegexString("(");
637     filter.addRegexSearchField(SearchableAnnotationField.DISPLAY_STRING);
638     added = cs.filterAnnotations(new Annotation[] { null, helix, sheet },
639             filter);
640     assertEquals(2, added);
641     assertTrue(cs.contains(1));
642     assertTrue(cs.contains(2));
643
644     /*
645      * select Helix (secondary structure symbol H)
646      */
647     filter = new AnnotationFilterParameter();
648     filter.setFilterAlphaHelix(true);
649     helix = new Annotation("x", "desc", 'H', 0f);
650     sheet = new Annotation("x", "desc", 'E', 1f);
651     Annotation turn = new Annotation("x", "desc", 'S', 2f);
652     Annotation ann4 = new Annotation("x", "desc", 'Y', 3f);
653     added = cs
654             .filterAnnotations(new Annotation[]
655             { null, helix, sheet, turn, ann4 }, filter);
656     assertEquals(1, added);
657     assertTrue(cs.contains(1));
658
659     /*
660      * select Helix and Sheet (E)
661      */
662     filter.setFilterBetaSheet(true);
663     added = cs
664             .filterAnnotations(new Annotation[]
665             { null, helix, sheet, turn, ann4 }, filter);
666     assertEquals(2, added);
667     assertTrue(cs.contains(1));
668     assertTrue(cs.contains(2));
669
670     /*
671      * select Sheet and Turn (S)
672      */
673     filter.setFilterAlphaHelix(false);
674     filter.setFilterTurn(true);
675     added = cs
676             .filterAnnotations(new Annotation[]
677             { null, helix, sheet, turn, ann4 }, filter);
678     assertEquals(2, added);
679     assertTrue(cs.contains(2));
680     assertTrue(cs.contains(3));
681
682     /*
683      * select value < 2f (ann1, ann2)
684      */
685     filter = new AnnotationFilterParameter();
686     filter.setThresholdType(ThresholdType.BELOW_THRESHOLD);
687     filter.setThresholdValue(2f);
688     added = cs
689             .filterAnnotations(new Annotation[]
690             { null, helix, sheet, turn, ann4 }, filter);
691     assertEquals(2, added);
692     assertTrue(cs.contains(1));
693     assertTrue(cs.contains(2));
694
695     /*
696      * select value > 2f (ann4 only)
697      */
698     filter.setThresholdType(ThresholdType.ABOVE_THRESHOLD);
699     added = cs
700             .filterAnnotations(new Annotation[]
701             { null, helix, sheet, turn, ann4 }, filter);
702     assertEquals(1, added);
703     assertTrue(cs.contains(4));
704
705     /*
706      * select >2f or Helix
707      */
708     filter.setFilterAlphaHelix(true);
709     added = cs
710             .filterAnnotations(new Annotation[]
711             { null, helix, sheet, turn, ann4 }, filter);
712     assertEquals(2, added);
713     assertTrue(cs.contains(1));
714     assertTrue(cs.contains(4));
715
716     /*
717      * select < 1f or Helix; one annotation matches both
718      * return value should only count it once
719      */
720     filter.setThresholdType(ThresholdType.BELOW_THRESHOLD);
721     filter.setThresholdValue(1f);
722     added = cs
723             .filterAnnotations(new Annotation[]
724             { null, helix, sheet, turn, ann4 }, filter);
725     assertEquals(1, added);
726     assertTrue(cs.contains(1));
727   }
728 }