JAL-3490 revised layout and search algorithm (more tests to be added)
[jalview.git] / test / jalview / analysis / FinderTest.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.analysis;
22
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.Assert.assertSame;
25 import static org.testng.Assert.assertTrue;
26
27 import jalview.api.AlignViewportI;
28 import jalview.api.FinderI;
29 import jalview.bin.Cache;
30 import jalview.datamodel.Alignment;
31 import jalview.datamodel.AlignmentI;
32 import jalview.datamodel.ColumnSelection;
33 import jalview.datamodel.HiddenColumns;
34 import jalview.datamodel.SearchResultMatchI;
35 import jalview.datamodel.SearchResultsI;
36 import jalview.datamodel.Sequence;
37 import jalview.datamodel.SequenceGroup;
38 import jalview.gui.AlignFrame;
39 import jalview.gui.AlignViewport;
40 import jalview.gui.JvOptionPane;
41 import jalview.io.DataSourceType;
42 import jalview.io.FileLoader;
43
44 import java.util.List;
45
46 import org.testng.annotations.AfterMethod;
47 import org.testng.annotations.BeforeClass;
48 import org.testng.annotations.Test;
49
50 import junit.extensions.PA;
51
52 public class FinderTest
53 {
54   @BeforeClass(alwaysRun = true)
55   public void setUpJvOptionPane()
56   {
57     JvOptionPane.setInteractiveMode(false);
58     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
59   }
60
61   private AlignFrame af;
62
63   private AlignmentI al;
64
65   private AlignViewportI av;
66
67   @BeforeClass(groups = "Functional")
68   public void setUp()
69   {
70     Cache.loadProperties("test/jalview/io/testProps.jvprops");
71     Cache.applicationProperties.setProperty("PAD_GAPS",
72             Boolean.FALSE.toString());
73
74     //@formatter:off
75     String seqData = 
76         "seq1/8-18 ABCD--EF-GHIJI\n" + 
77         "seq2      A--BCDefHI\n" + 
78         "seq3      --bcdEFH\n" + 
79         "seq4      aa---aMMMMMaaa\n";
80     //@formatter:on
81     af = new FileLoader().LoadFileWaitTillLoaded(seqData,
82             DataSourceType.PASTE);
83     av = af.getViewport();
84     al = av.getAlignment();
85   }
86
87   @AfterMethod(alwaysRun = true)
88   public void tearDownAfterTest()
89   {
90     av.setSelectionGroup(null);
91   }
92
93   /**
94    * Test for find matches of a regular expression
95    */
96   @Test(groups = "Functional")
97   public void testFind_regex()
98   {
99     /*
100      * find next match only
101      */
102     Finder f = new Finder(av);
103     f.findNext("E.H", false, false, false); // 'E, any character, H'
104     // should match seq2 efH only
105     SearchResultsI sr = f.getSearchResults();
106     assertEquals(sr.getSize(), 1);
107     List<SearchResultMatchI> matches = sr.getResults();
108     assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
109     assertEquals(matches.get(0).getStart(), 5);
110     assertEquals(matches.get(0).getEnd(), 7);
111
112     f = new Finder(av);
113     f.findAll("E.H", false, false, false); // 'E, any character, H'
114     // should match seq2 efH and seq3 EFH
115     sr = f.getSearchResults();
116     assertEquals(sr.getSize(), 2);
117     matches = sr.getResults();
118     assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
119     assertSame(matches.get(1).getSequence(), al.getSequenceAt(2));
120     assertEquals(matches.get(0).getStart(), 5);
121     assertEquals(matches.get(0).getEnd(), 7);
122     assertEquals(matches.get(1).getStart(), 4);
123     assertEquals(matches.get(1).getEnd(), 6);
124   }
125
126   /**
127    * Test for (undocumented) find residue by position
128    */
129   @Test(groups = "Functional")
130   public void testFind_residueNumber()
131   {
132     Finder f = new Finder(av);
133
134     /*
135      * find first match should return seq1 residue 9
136      */
137     f.findNext("9", false, false, false);
138     SearchResultsI sr = f.getSearchResults();
139     assertEquals(sr.getSize(), 1);
140     List<SearchResultMatchI> matches = sr.getResults();
141     assertSame(matches.get(0).getSequence(), al.getSequenceAt(0));
142     assertEquals(matches.get(0).getStart(), 9);
143     assertEquals(matches.get(0).getEnd(), 9);
144
145     /*
146      * find all matches should return seq1 and seq4 (others are too short)
147      */
148     f = new Finder(av);
149     f.findAll("9", false, false, false);
150     sr = f.getSearchResults();
151     assertEquals(sr.getSize(), 2);
152     matches = sr.getResults();
153     assertSame(matches.get(0).getSequence(), al.getSequenceAt(0));
154     assertSame(matches.get(1).getSequence(), al.getSequenceAt(3));
155     assertEquals(matches.get(0).getStart(), 9);
156     assertEquals(matches.get(0).getEnd(), 9);
157     assertEquals(matches.get(1).getStart(), 9);
158     assertEquals(matches.get(1).getEnd(), 9);
159
160     /*
161      * parsing of search string as integer is strict
162      */
163     f = new Finder(av);
164     f.findNext(" 9", false, false, false);
165     assertTrue(f.getSearchResults().isEmpty());
166   }
167
168   /**
169    * Test for find next action
170    */
171   @Test(groups = "Functional")
172   public void testFindNext()
173   {
174     /*
175      * start at second sequence; residueIndex of -1
176      * means sequence id / description is searched
177      */
178     Finder f = new Finder(av);
179     PA.setValue(f, "sequenceIndex", 1);
180     PA.setValue(f, "residueIndex", -1);
181     f.findNext("e", false, false, false); // matches id
182
183     assertTrue(f.getSearchResults().isEmpty());
184     assertEquals(f.getIdMatches().size(), 1);
185     assertSame(f.getIdMatches().get(0), al.getSequenceAt(1));
186
187     // residueIndex is now 0 - for use in next find next
188     // searching A--BCDefHI
189     assertEquals(PA.getValue(f, "residueIndex"), 0);
190     f = new Finder(av);
191     PA.setValue(f, "sequenceIndex", 1);
192     PA.setValue(f, "residueIndex", 0);
193     f.findNext("e", false, false, false); // matches in sequence
194     assertTrue(f.getIdMatches().isEmpty());
195     assertEquals(f.getSearchResults().getSize(), 1);
196     List<SearchResultMatchI> matches = f.getSearchResults().getResults();
197     assertEquals(matches.get(0).getStart(), 5);
198     assertEquals(matches.get(0).getEnd(), 5);
199     assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
200     // still in the second sequence
201     assertEquals(PA.getValue(f, "sequenceIndex"), 1);
202     // next residue offset to search from is 5
203     assertEquals(PA.getValue(f, "residueIndex"), 5);
204
205     // find next from end of sequence - finds next sequence id
206     f = new Finder(av);
207     PA.setValue(f, "sequenceIndex", 1);
208     PA.setValue(f, "residueIndex", 7);
209     f.findNext("e", false, false, false);
210     assertEquals(f.getIdMatches().size(), 1);
211     assertSame(f.getIdMatches().get(0), al.getSequenceAt(2));
212     assertTrue(f.getSearchResults().isEmpty());
213   }
214
215   /**
216    * Test for matching within sequence descriptions
217    */
218   @Test(groups = "Functional")
219   public void testFind_inDescription()
220   {
221     AlignmentI al2 = new Alignment(al);
222     al2.getSequenceAt(0).setDescription("BRAF");
223     al2.getSequenceAt(1).setDescription("braf");
224
225     AlignViewportI av2 = new AlignViewport(al2);
226
227     /*
228      * find first match only
229      */
230     Finder f = new Finder(av2);
231     f.findNext("rAF", false, true, false);
232     assertEquals(f.getIdMatches().size(), 1);
233     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
234     assertTrue(f.getSearchResults().isEmpty());
235
236     /*
237      * find all matches
238      */
239     f = new Finder(av2);
240     f.findAll("rAF", false, true, false);
241     assertEquals(f.getIdMatches().size(), 2);
242     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
243     assertSame(f.getIdMatches().get(1), al2.getSequenceAt(1));
244     assertTrue(f.getSearchResults().isEmpty());
245
246     /*
247      * case sensitive
248      */
249     f = new Finder(av2);
250     f.findAll("RAF", true, true, false);
251     assertEquals(f.getIdMatches().size(), 1);
252     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
253     assertTrue(f.getSearchResults().isEmpty());
254
255     /*
256      * match sequence id, description and sequence!
257      */
258     al2.getSequenceAt(0).setDescription("the efh sequence");
259     al2.getSequenceAt(0).setName("mouseEFHkinase");
260     al2.getSequenceAt(1).setName("humanEFHkinase");
261     f = new Finder(av2);
262
263     /*
264      * sequence matches should have no duplicates
265      */
266     f.findAll("EFH", false, true, false);
267     assertEquals(f.getIdMatches().size(), 2);
268     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
269     assertSame(f.getIdMatches().get(1), al2.getSequenceAt(1));
270
271     assertEquals(f.getSearchResults().getSize(), 2);
272     SearchResultMatchI match = f.getSearchResults().getResults().get(0);
273     assertSame(match.getSequence(), al2.getSequenceAt(1));
274     assertEquals(match.getStart(), 5);
275     assertEquals(match.getEnd(), 7);
276     match = f.getSearchResults().getResults().get(1);
277     assertSame(match.getSequence(), al2.getSequenceAt(2));
278     assertEquals(match.getStart(), 4);
279     assertEquals(match.getEnd(), 6);
280   }
281
282   /**
283    * Test for matching within sequence ids
284    */
285   @Test(groups = "Functional")
286   public void testFindAll_sequenceIds()
287   {
288     Finder f = new Finder(av);
289
290     /*
291      * case insensitive; seq1 occurs twice in sequence id but
292      * only one match should be returned
293      */
294     f.findAll("SEQ1", false, false, false);
295     assertEquals(f.getIdMatches().size(), 1);
296     assertSame(f.getIdMatches().get(0), al.getSequenceAt(0));
297     SearchResultsI searchResults = f.getSearchResults();
298     assertTrue(searchResults.isEmpty());
299
300     /*
301      * case sensitive
302      */
303     f = new Finder(av);
304     f.findAll("SEQ1", true, false, false);
305     searchResults = f.getSearchResults();
306     assertTrue(searchResults.isEmpty());
307
308     /*
309      * match both sequence id and sequence
310      */
311     AlignmentI al2 = new Alignment(al);
312     AlignViewportI av2 = new AlignViewport(al2);
313     al2.addSequence(new Sequence("aBz", "xyzabZpqrAbZ"));
314     f = new Finder(av2);
315     f.findAll("ABZ", false, false, false);
316     assertEquals(f.getIdMatches().size(), 1);
317     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(4));
318     searchResults = f.getSearchResults();
319     assertEquals(searchResults.getSize(), 2);
320     SearchResultMatchI match = searchResults.getResults().get(0);
321     assertSame(match.getSequence(), al2.getSequenceAt(4));
322     assertEquals(match.getStart(), 4);
323     assertEquals(match.getEnd(), 6);
324     match = searchResults.getResults().get(1);
325     assertSame(match.getSequence(), al2.getSequenceAt(4));
326     assertEquals(match.getStart(), 10);
327     assertEquals(match.getEnd(), 12);
328   }
329
330   /**
331    * Test finding next match of a sequence pattern in an alignment
332    */
333   @Test(groups = "Functional")
334   public void testFind_findNext()
335   {
336     // "seq1/8-18 ABCD--EF-GHIJI\n" +
337     // "seq2 A--BCDefHI\n" +
338     // "seq3 --bcdEFH\n" +
339     // "seq4 aa---aMMMMMaaa\n";
340     /*
341      * efh should be matched in seq2 only
342      */
343     FinderI f = new Finder(av);
344     f.findNext("EfH", false, false, false);
345     SearchResultsI searchResults = f.getSearchResults();
346     assertEquals(searchResults.getSize(), 1);
347     SearchResultMatchI match = searchResults.getResults().get(0);
348     assertSame(match.getSequence(), al.getSequenceAt(1));
349     assertEquals(match.getStart(), 5);
350     assertEquals(match.getEnd(), 7);
351
352     /*
353      * I should be found in seq1 (twice) and seq2 (once)
354      */
355     f = new Finder(av);
356     f.findNext("I", false, false, false); // find next: seq1/16
357     searchResults = f.getSearchResults();
358     assertEquals(searchResults.getSize(), 1);
359     match = searchResults.getResults().get(0);
360     assertSame(match.getSequence(), al.getSequenceAt(0));
361     assertEquals(match.getStart(), 16);
362     assertEquals(match.getEnd(), 16);
363
364     f.findNext("I", false, false, false); // find next: seq1/18
365     searchResults = f.getSearchResults();
366     assertEquals(searchResults.getSize(), 1);
367     match = searchResults.getResults().get(0);
368     assertSame(match.getSequence(), al.getSequenceAt(0));
369     assertEquals(match.getStart(), 18);
370     assertEquals(match.getEnd(), 18);
371
372     f.findNext("I", false, false, false); // find next: seq2/8
373     searchResults = f.getSearchResults();
374     assertEquals(searchResults.getSize(), 1);
375     match = searchResults.getResults().get(0);
376     assertSame(match.getSequence(), al.getSequenceAt(1));
377     assertEquals(match.getStart(), 8);
378     assertEquals(match.getEnd(), 8);
379
380     f.findNext("I", false, false, false);
381     assertTrue(f.getSearchResults().isEmpty());
382
383     /*
384      * find should reset to start of alignment after a failed search
385      */
386     f.findNext("I", false, false, false); // find next: seq1/16
387     searchResults = f.getSearchResults();
388     assertEquals(searchResults.getSize(), 1);
389     match = searchResults.getResults().get(0);
390     assertSame(match.getSequence(), al.getSequenceAt(0));
391     assertEquals(match.getStart(), 16);
392     assertEquals(match.getEnd(), 16);
393   }
394
395   /**
396    * Test for JAL-2302 to verify that sub-matches are not included in a find all
397    * result
398    */
399   @Test(groups = "Functional")
400   public void testFind_maximalResultOnly()
401   {
402     Finder f = new Finder(av);
403     f.findAll("M+", false, false, false);
404     SearchResultsI searchResults = f.getSearchResults();
405     assertEquals(searchResults.getSize(), 1);
406     SearchResultMatchI match = searchResults.getResults().get(0);
407     assertSame(match.getSequence(), al.getSequenceAt(3));
408     assertEquals(match.getStart(), 4); // dataset sequence positions
409     assertEquals(match.getEnd(), 8); // base 1
410   }
411
412   /**
413    * Test finding all matches of a sequence pattern in an alignment
414    */
415   @Test(groups = "Functional")
416   public void testFindAll()
417   {
418     Finder f = new Finder(av);
419     f.findAll("EfH", false, false, false);
420     SearchResultsI searchResults = f.getSearchResults();
421     assertEquals(searchResults.getSize(), 2);
422     SearchResultMatchI match = searchResults.getResults().get(0);
423     assertSame(match.getSequence(), al.getSequenceAt(1));
424     assertEquals(match.getStart(), 5);
425     assertEquals(match.getEnd(), 7);
426     match = searchResults.getResults().get(1);
427     assertSame(match.getSequence(), al.getSequenceAt(2));
428     assertEquals(match.getStart(), 4);
429     assertEquals(match.getEnd(), 6);
430
431     /*
432      * find all I should find 2 positions in seq1, 1 in seq2
433      */
434     f.findAll("I", false, false, false);
435     searchResults = f.getSearchResults();
436     assertEquals(searchResults.getSize(), 3);
437     match = searchResults.getResults().get(0);
438     assertSame(match.getSequence(), al.getSequenceAt(0));
439     assertEquals(match.getStart(), 16);
440     assertEquals(match.getEnd(), 16);
441     match = searchResults.getResults().get(1);
442     assertSame(match.getSequence(), al.getSequenceAt(0));
443     assertEquals(match.getStart(), 18);
444     assertEquals(match.getEnd(), 18);
445     match = searchResults.getResults().get(2);
446     assertSame(match.getSequence(), al.getSequenceAt(1));
447     assertEquals(match.getStart(), 8);
448     assertEquals(match.getEnd(), 8);
449   }
450
451   /**
452    * Test finding all matches, case-sensitive
453    */
454   @Test(groups = "Functional")
455   public void testFind_findAllCaseSensitive()
456   {
457     Finder f = new Finder(av);
458
459     /*
460      * BC should match seq1/9-10 and seq2/2-3
461      */
462     f.findAll("BC", true, false, false);
463     SearchResultsI searchResults = f.getSearchResults();
464     assertEquals(searchResults.getSize(), 2);
465     SearchResultMatchI match = searchResults.getResults().get(0);
466     assertSame(match.getSequence(), al.getSequenceAt(0));
467     assertEquals(match.getStart(), 9);
468     assertEquals(match.getEnd(), 10);
469     match = searchResults.getResults().get(1);
470     assertSame(match.getSequence(), al.getSequenceAt(1));
471     assertEquals(match.getStart(), 2);
472     assertEquals(match.getEnd(), 3);
473
474     /*
475      * bc should match seq3/1-2
476      */
477     f = new Finder(av);
478     f.findAll("bc", true, false, false);
479     searchResults = f.getSearchResults();
480     assertEquals(searchResults.getSize(), 1);
481     match = searchResults.getResults().get(0);
482     assertSame(match.getSequence(), al.getSequenceAt(2));
483     assertEquals(match.getStart(), 1);
484     assertEquals(match.getEnd(), 2);
485
486     f.findAll("bC", true, false, false);
487     assertTrue(f.getSearchResults().isEmpty());
488   }
489
490   /**
491    * Test finding next match of a sequence pattern in a selection group
492    */
493   @Test(groups = "Functional")
494   public void testFind_inSelection()
495   {
496     /*
497      * select sequences 2 and 3, columns 4-6 which contains
498      * BCD
499      * cdE
500      */
501     SequenceGroup sg = new SequenceGroup();
502     sg.setStartRes(3);
503     sg.setEndRes(5);
504     sg.addSequence(al.getSequenceAt(1), false);
505     sg.addSequence(al.getSequenceAt(2), false);
506     av.setSelectionGroup(sg);
507
508     FinderI f = new Finder(av);
509     f.findNext("b", false, false, false);
510     assertTrue(f.getIdMatches().isEmpty());
511     SearchResultsI searchResults = f.getSearchResults();
512     assertEquals(searchResults.getSize(), 1);
513     SearchResultMatchI match = searchResults.getResults().get(0);
514     assertSame(match.getSequence(), al.getSequenceAt(1));
515     assertEquals(match.getStart(), 2);
516     assertEquals(match.getEnd(), 2);
517
518     /*
519      * a second Find should not return the 'b' in seq3 as outside the selection
520      */
521     f.findNext("b", false, false, false);
522     assertTrue(f.getSearchResults().isEmpty());
523     assertTrue(f.getIdMatches().isEmpty());
524
525     f = new Finder(av);
526     f.findNext("d", false, false, false);
527     assertTrue(f.getIdMatches().isEmpty());
528     searchResults = f.getSearchResults();
529     assertEquals(searchResults.getSize(), 1);
530     match = searchResults.getResults().get(0);
531     assertSame(match.getSequence(), al.getSequenceAt(1));
532     assertEquals(match.getStart(), 4);
533     assertEquals(match.getEnd(), 4);
534     f.findNext("d", false, false, false);
535     assertTrue(f.getIdMatches().isEmpty());
536     searchResults = f.getSearchResults();
537     assertEquals(searchResults.getSize(), 1);
538     match = searchResults.getResults().get(0);
539     assertSame(match.getSequence(), al.getSequenceAt(2));
540     assertEquals(match.getStart(), 3);
541     assertEquals(match.getEnd(), 3);
542   }
543
544   /**
545    * Test finding all matches of a search pattern in a selection group
546    */
547   @Test(groups = "Functional")
548   public void testFind_findAllInSelection()
549   {
550     /*
551      * select sequences 2 and 3, columns 4-6 which contains
552      * BCD
553      * cdE
554      */
555     SequenceGroup sg = new SequenceGroup();
556     sg.setStartRes(3);
557     sg.setEndRes(5);
558     sg.addSequence(al.getSequenceAt(1), false);
559     sg.addSequence(al.getSequenceAt(2), false);
560     av.setSelectionGroup(sg);
561   
562     /*
563      * search for 'e' should match two sequence ids and one residue
564      */
565     Finder f = new Finder(av);
566     f.findAll("e", false, false, false);
567     assertEquals(f.getIdMatches().size(), 2);
568     assertSame(f.getIdMatches().get(0), al.getSequenceAt(1));
569     assertSame(f.getIdMatches().get(1), al.getSequenceAt(2));
570     SearchResultsI searchResults = f.getSearchResults();
571     assertEquals(searchResults.getSize(), 1);
572     SearchResultMatchI match = searchResults.getResults().get(0);
573     assertSame(match.getSequence(), al.getSequenceAt(2));
574     assertEquals(match.getStart(), 4);
575     assertEquals(match.getEnd(), 4);
576
577     /*
578      * search for 'Q' should match two sequence ids only
579      */
580     f = new Finder(av);
581     f.findAll("Q", false, false, false);
582     assertEquals(f.getIdMatches().size(), 2);
583     assertSame(f.getIdMatches().get(0), al.getSequenceAt(1));
584     assertSame(f.getIdMatches().get(1), al.getSequenceAt(2));
585     assertTrue(f.getSearchResults().isEmpty());
586   }
587
588   /**
589    * Test finding in selection with a sequence too short to reach it
590    */
591   @Test(groups = "Functional")
592   public void testFind_findAllInSelectionWithShortSequence()
593   {
594     /*
595      * select all sequences, columns 10-12
596      * BCD
597      * cdE
598      */
599     SequenceGroup sg = new SequenceGroup();
600     sg.setStartRes(9);
601     sg.setEndRes(11);
602     sg.addSequence(al.getSequenceAt(0), false);
603     sg.addSequence(al.getSequenceAt(1), false);
604     sg.addSequence(al.getSequenceAt(2), false);
605     sg.addSequence(al.getSequenceAt(3), false);
606     av.setSelectionGroup(sg);
607
608     /*
609      * search for 'I' should match two sequence positions
610      */
611     Finder f = new Finder(av);
612     f.findAll("I", false, false, false);
613     assertTrue(f.getIdMatches().isEmpty());
614     SearchResultsI searchResults = f.getSearchResults();
615     assertEquals(searchResults.getSize(), 2);
616     SearchResultMatchI match = searchResults.getResults().get(0);
617     assertSame(match.getSequence(), al.getSequenceAt(0));
618     assertEquals(match.getStart(), 16);
619     assertEquals(match.getEnd(), 16);
620     match = searchResults.getResults().get(1);
621     assertSame(match.getSequence(), al.getSequenceAt(1));
622     assertEquals(match.getStart(), 8);
623     assertEquals(match.getEnd(), 8);
624   }
625
626   /**
627    * Test that find does not report hidden positions, but does report matches that
628    * span hidden gaps
629    */
630   @Test(groups = "Functional")
631   public void testFind_withHiddenColumns()
632   {
633     /*
634      * 0    5   9
635      * ABCD--EF-GHI
636      * A--BCDefHI
637      * --bcdEFH
638      * aa---aMMMMMaaa
639      */
640
641     /*
642      * hide column 3 only, search for aaa
643      * should find two matches: aa-[-]-aa and trailing aaa
644      */
645     HiddenColumns hc = new HiddenColumns();
646     hc.hideColumns(3, 3);
647     al.setHiddenColumns(hc);
648     Finder f = new Finder(av);
649     f.findAll("aaa", false, false, false);
650     SearchResultsI searchResults = f.getSearchResults();
651     assertEquals(searchResults.getSize(), 2);
652     SearchResultMatchI match = searchResults.getResults().get(0);
653     assertSame(match.getSequence(), al.getSequenceAt(3));
654     assertEquals(match.getStart(), 1);
655     assertEquals(match.getEnd(), 3);
656     match = searchResults.getResults().get(1);
657     assertSame(match.getSequence(), al.getSequenceAt(3));
658     assertEquals(match.getStart(), 9);
659     assertEquals(match.getEnd(), 11);
660
661     /*
662      * hide 2-4 (CD- -BC bcd ---)
663      */
664     hc.hideColumns(2, 4);
665
666     /*
667      * find all search for D should ignore hidden positions in seq1 and seq3,
668      * find the visible D in seq2
669      */
670     f = new Finder(av);
671     f.findAll("D", false, false, false);
672     searchResults = f.getSearchResults();
673     assertEquals(searchResults.getSize(), 1);
674     match = searchResults.getResults().get(0);
675     assertSame(match.getSequence(), al.getSequenceAt(1));
676     assertEquals(match.getStart(), 4);
677     assertEquals(match.getEnd(), 4);
678
679     /*
680      * search for AD should fail although these are now
681      * consecutive in the visible columns
682      */
683     f = new Finder(av);
684     f.findAll("AD", false, false, false);
685     searchResults = f.getSearchResults();
686     assertTrue(searchResults.isEmpty());
687
688     /*
689      * find all 'aaa' should find both start and end of seq4
690      * (first run includes hidden gaps)
691      */
692     f = new Finder(av);
693     f.findAll("aaa", false, false, false);
694     searchResults = f.getSearchResults();
695     assertEquals(searchResults.getSize(), 2);
696     match = searchResults.getResults().get(0);
697     assertSame(match.getSequence(), al.getSequenceAt(3));
698     assertEquals(match.getStart(), 1);
699     assertEquals(match.getEnd(), 3);
700     match = searchResults.getResults().get(1);
701     assertSame(match.getSequence(), al.getSequenceAt(3));
702     assertEquals(match.getStart(), 9);
703     assertEquals(match.getEnd(), 11);
704
705     /*
706      * hide columns 2-5:
707      * find all 'aaa' should match twice in seq4
708      * (first match partly hidden, second all visible)
709      */
710     hc.hideColumns(2, 5);
711     f = new Finder(av);
712     f.findAll("aaa", false, false, false);
713     searchResults = f.getSearchResults();
714     assertEquals(searchResults.getSize(), 2);
715     match = searchResults.getResults().get(0);
716     assertSame(match.getSequence(), al.getSequenceAt(3));
717     assertEquals(match.getStart(), 1);
718     assertEquals(match.getEnd(), 3);
719     match = searchResults.getResults().get(1);
720     assertSame(match.getSequence(), al.getSequenceAt(3));
721     assertEquals(match.getStart(), 9);
722     assertEquals(match.getEnd(), 11);
723
724     /*
725      * find all 'BE' should not match across hidden columns in seq1
726      */
727     f.findAll("BE", false, false, false);
728     assertTrue(f.getSearchResults().isEmpty());
729
730     /*
731      * boundary case: hide columns at end of alignment
732      * search for H should match seq3/6 only
733      */
734     hc.revealAllHiddenColumns(new ColumnSelection());
735     hc.hideColumns(8, 13);
736     f = new Finder(av);
737     f.findNext("H", false, false, false);
738     searchResults = f.getSearchResults();
739     assertEquals(searchResults.getSize(), 1);
740     match = searchResults.getResults().get(0);
741     assertSame(match.getSequence(), al.getSequenceAt(2));
742     assertEquals(match.getStart(), 6);
743     assertEquals(match.getEnd(), 6);
744   }
745
746   @Test(groups = "Functional")
747   public void testFind_withHiddenColumnsAndSelection()
748   {
749     /*
750      * 0    5   9
751      * ABCD--EF-GHI
752      * A--BCDefHI
753      * --bcdEFH
754      * aa---aMMMMMaaa
755      */
756   
757     /*
758      * hide columns 2-4 and 6-7
759      */
760     HiddenColumns hc = new HiddenColumns();
761     hc.hideColumns(2, 4);
762     hc.hideColumns(6, 7);
763     al.setHiddenColumns(hc);
764   
765     /*
766      * select rows 2-3
767      */
768     SequenceGroup sg = new SequenceGroup();
769     sg.addSequence(al.getSequenceAt(1), false);
770     sg.addSequence(al.getSequenceAt(2), false);
771     sg.setStartRes(0);
772     sg.setEndRes(13);
773     av.setSelectionGroup(sg);
774
775     /*
776      * find all search for A or H
777      * should match seq2/1, seq2/7, not seq3/6
778      */
779     Finder f = new Finder(av);
780     f.findAll("[AH]", false, false, false);
781     SearchResultsI searchResults = f.getSearchResults();
782     assertEquals(searchResults.getSize(), 2);
783     SearchResultMatchI match = searchResults.getResults().get(0);
784     assertSame(match.getSequence(), al.getSequenceAt(1));
785     assertEquals(match.getStart(), 1);
786     assertEquals(match.getEnd(), 1);
787     match = searchResults.getResults().get(1);
788     assertSame(match.getSequence(), al.getSequenceAt(1));
789     assertEquals(match.getStart(), 7);
790     assertEquals(match.getEnd(), 7);
791   }
792 }