Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.datamodel

File SequenceTest.java

 

Code metrics

2
1,075
49
1
2,130
1,421
52
0.05
21.94
49
1.06

Classes

Class Line # Actions
SequenceTest 53 1,075 52 37
0.967140396.7%
 

Contributing tests

This file is covered by 43 tests. .

Source view

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.assertNotNull;
26    import static org.testng.AssertJUnit.assertNotSame;
27    import static org.testng.AssertJUnit.assertNull;
28    import static org.testng.AssertJUnit.assertSame;
29    import static org.testng.AssertJUnit.assertTrue;
30   
31    import jalview.analysis.AlignmentGenerator;
32    import jalview.commands.EditCommand;
33    import jalview.commands.EditCommand.Action;
34    import jalview.datamodel.PDBEntry.Type;
35    import jalview.gui.JvOptionPane;
36    import jalview.util.MapList;
37   
38    import java.io.File;
39    import java.util.ArrayList;
40    import java.util.Arrays;
41    import java.util.BitSet;
42    import java.util.Iterator;
43    import java.util.List;
44    import java.util.Vector;
45   
46    import org.testng.Assert;
47    import org.testng.annotations.BeforeClass;
48    import org.testng.annotations.BeforeMethod;
49    import org.testng.annotations.Test;
50   
51    import junit.extensions.PA;
52   
 
53    public class SequenceTest
54    {
55   
 
56  1 toggle @BeforeClass(alwaysRun = true)
57    public void setUpJvOptionPane()
58    {
59  1 JvOptionPane.setInteractiveMode(false);
60  1 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
61    }
62   
63    Sequence seq;
64   
 
65  43 toggle @BeforeMethod(alwaysRun = true)
66    public void setUp()
67    {
68  43 seq = new Sequence("FER1", "AKPNGVL");
69    }
70   
 
71  1 toggle @Test(groups = { "Functional" })
72    public void testInsertGapsAndGapmaps()
73    {
74  1 SequenceI aseq = seq.deriveSequence();
75  1 aseq.insertCharAt(2, 3, '-');
76  1 aseq.insertCharAt(6, 3, '-');
77  1 assertEquals("Gap insertions not correct", "AK---P---NGVL",
78    aseq.getSequenceAsString());
79  1 List<int[]> gapInt = aseq.getInsertions();
80  1 assertEquals("Gap interval 1 start wrong", 2, gapInt.get(0)[0]);
81  1 assertEquals("Gap interval 1 end wrong", 4, gapInt.get(0)[1]);
82  1 assertEquals("Gap interval 2 start wrong", 6, gapInt.get(1)[0]);
83  1 assertEquals("Gap interval 2 end wrong", 8, gapInt.get(1)[1]);
84   
85  1 BitSet gapfield = aseq.getInsertionsAsBits();
86  1 BitSet expectedgaps = new BitSet();
87  1 expectedgaps.set(2, 5);
88  1 expectedgaps.set(6, 9);
89   
90  1 assertEquals(6, expectedgaps.cardinality());
91   
92  1 assertEquals("getInsertionsAsBits didn't mark expected number of gaps",
93    6, gapfield.cardinality());
94   
95  1 assertEquals("getInsertionsAsBits not correct.", expectedgaps, gapfield);
96    }
97   
 
98  1 toggle @Test(groups = ("Functional"))
99    public void testIsProtein()
100    {
101    // test Protein
102  1 assertTrue(new Sequence("prot", "ASDFASDFASDF").isProtein());
103    // test DNA
104  1 assertFalse(new Sequence("prot", "ACGTACGTACGT").isProtein());
105    // test RNA
106  1 SequenceI sq = new Sequence("prot", "ACGUACGUACGU");
107  1 assertFalse(sq.isProtein());
108    // change sequence, should trigger an update of cached result
109  1 sq.setSequence("ASDFASDFADSF");
110  1 assertTrue(sq.isProtein());
111    }
112   
 
113  1 toggle @Test(groups = { "Functional" })
114    public void testGetAnnotation()
115    {
116    // initial state returns null not an empty array
117  1 assertNull(seq.getAnnotation());
118  1 AlignmentAnnotation ann = addAnnotation("label1", "desc1", "calcId1",
119    1f);
120  1 AlignmentAnnotation[] anns = seq.getAnnotation();
121  1 assertEquals(1, anns.length);
122  1 assertSame(ann, anns[0]);
123   
124    // removing all annotations reverts array to null
125  1 seq.removeAlignmentAnnotation(ann);
126  1 assertNull(seq.getAnnotation());
127    }
128   
 
129  1 toggle @Test(groups = { "Functional" })
130    public void testGetAnnotation_forLabel()
131    {
132  1 AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
133    1f);
134  1 addAnnotation("label2", "desc2", "calcId2", 1f);
135  1 AlignmentAnnotation ann3 = addAnnotation("label1", "desc3", "calcId3",
136    1f);
137  1 AlignmentAnnotation[] anns = seq.getAnnotation("label1");
138  1 assertEquals(2, anns.length);
139  1 assertSame(ann1, anns[0]);
140  1 assertSame(ann3, anns[1]);
141    }
142   
 
143  10 toggle private AlignmentAnnotation addAnnotation(String label,
144    String description, String calcId, float value)
145    {
146  10 final AlignmentAnnotation annotation = new AlignmentAnnotation(label,
147    description, value);
148  10 annotation.setCalcId(calcId);
149  10 seq.addAlignmentAnnotation(annotation);
150  10 return annotation;
151    }
152   
 
153  1 toggle @Test(groups = { "Functional" })
154    public void testGetAlignmentAnnotations_forCalcIdAndLabel()
155    {
156  1 addAnnotation("label1", "desc1", "calcId1", 1f);
157  1 AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2",
158    1f);
159  1 addAnnotation("label2", "desc3", "calcId3", 1f);
160  1 AlignmentAnnotation ann4 = addAnnotation("label2", "desc3", "calcId2",
161    1f);
162  1 addAnnotation("label5", "desc3", null, 1f);
163  1 addAnnotation(null, "desc3", "calcId3", 1f);
164   
165  1 List<AlignmentAnnotation> anns = seq.getAlignmentAnnotations("calcId2",
166    "label2");
167  1 assertEquals(2, anns.size());
168  1 assertSame(ann2, anns.get(0));
169  1 assertSame(ann4, anns.get(1));
170   
171  1 assertTrue(seq.getAlignmentAnnotations("calcId2", "label3").isEmpty());
172  1 assertTrue(seq.getAlignmentAnnotations("calcId3", "label5").isEmpty());
173  1 assertTrue(seq.getAlignmentAnnotations("calcId2", null).isEmpty());
174  1 assertTrue(seq.getAlignmentAnnotations(null, "label3").isEmpty());
175  1 assertTrue(seq.getAlignmentAnnotations(null, null).isEmpty());
176    }
177   
178    /**
179    * Tests for addAlignmentAnnotation. Note this method has the side-effect of
180    * setting the sequenceRef on the annotation. Adding the same annotation twice
181    * should be ignored.
182    */
 
183  1 toggle @Test(groups = { "Functional" })
184    public void testAddAlignmentAnnotation()
185    {
186  1 assertNull(seq.getAnnotation());
187  1 final AlignmentAnnotation annotation = new AlignmentAnnotation("a",
188    "b", 2d);
189  1 assertNull(annotation.sequenceRef);
190  1 seq.addAlignmentAnnotation(annotation);
191  1 assertSame(seq, annotation.sequenceRef);
192  1 AlignmentAnnotation[] anns = seq.getAnnotation();
193  1 assertEquals(1, anns.length);
194  1 assertSame(annotation, anns[0]);
195   
196    // re-adding does nothing
197  1 seq.addAlignmentAnnotation(annotation);
198  1 anns = seq.getAnnotation();
199  1 assertEquals(1, anns.length);
200  1 assertSame(annotation, anns[0]);
201   
202    // an identical but different annotation can be added
203  1 final AlignmentAnnotation annotation2 = new AlignmentAnnotation("a",
204    "b", 2d);
205  1 seq.addAlignmentAnnotation(annotation2);
206  1 anns = seq.getAnnotation();
207  1 assertEquals(2, anns.length);
208  1 assertSame(annotation, anns[0]);
209  1 assertSame(annotation2, anns[1]);
210    }
211   
 
212  1 toggle @Test(groups = { "Functional" })
213    public void testGetStartGetEnd()
214    {
215  1 SequenceI sq = new Sequence("test", "ABCDEF");
216  1 assertEquals(1, sq.getStart());
217  1 assertEquals(6, sq.getEnd());
218   
219  1 sq = new Sequence("test", "--AB-C-DEF--");
220  1 assertEquals(1, sq.getStart());
221  1 assertEquals(6, sq.getEnd());
222   
223  1 sq = new Sequence("test", "----");
224  1 assertEquals(1, sq.getStart());
225  1 assertEquals(0, sq.getEnd()); // ??
226    }
227   
228    /**
229    * Tests for the method that returns an alignment column position (base 1) for
230    * a given sequence position (base 1).
231    */
 
232  1 toggle @Test(groups = { "Functional" })
233    public void testFindIndex()
234    {
235    /*
236    * call sequenceChanged() after each test to invalidate any cursor,
237    * forcing the 1-arg findIndex to be executed
238    */
239  1 SequenceI sq = new Sequence("test", "ABCDEF");
240  1 assertEquals(0, sq.findIndex(0));
241  1 sq.sequenceChanged();
242  1 assertEquals(1, sq.findIndex(1));
243  1 sq.sequenceChanged();
244  1 assertEquals(5, sq.findIndex(5));
245  1 sq.sequenceChanged();
246  1 assertEquals(6, sq.findIndex(6));
247  1 sq.sequenceChanged();
248  1 assertEquals(6, sq.findIndex(9));
249   
250  1 final String aligned = "-A--B-C-D-E-F--";
251  1 assertEquals(15, aligned.length());
252  1 sq = new Sequence("test/8-13", aligned);
253  1 assertEquals(2, sq.findIndex(8));
254  1 sq.sequenceChanged();
255  1 assertEquals(5, sq.findIndex(9));
256  1 sq.sequenceChanged();
257  1 assertEquals(7, sq.findIndex(10));
258   
259    // before start returns 0
260  1 sq.sequenceChanged();
261  1 assertEquals(0, sq.findIndex(0));
262  1 sq.sequenceChanged();
263  1 assertEquals(0, sq.findIndex(-1));
264   
265    // beyond end returns last residue column
266  1 sq.sequenceChanged();
267  1 assertEquals(13, sq.findIndex(99));
268   
269    /*
270    * residue before sequence 'end' but beyond end of sequence returns
271    * length of sequence (last column) (rightly or wrongly!)
272    */
273  1 sq = new Sequence("test/8-15", "A-B-C-"); // trailing gap case
274  1 assertEquals(6, sq.getLength());
275  1 sq.sequenceChanged();
276  1 assertEquals(sq.getLength(), sq.findIndex(14));
277  1 sq = new Sequence("test/8-99", "-A--B-C-D"); // trailing residue case
278  1 sq.sequenceChanged();
279  1 assertEquals(sq.getLength(), sq.findIndex(65));
280   
281    /*
282    * residue after sequence 'start' but before first residue returns
283    * zero (before first column) (rightly or wrongly!)
284    */
285  1 sq = new Sequence("test/8-15", "-A-B-C-"); // leading gap case
286  1 sq.sequenceChanged();
287  1 assertEquals(0, sq.findIndex(3));
288  1 sq = new Sequence("test/8-15", "A-B-C-"); // leading residue case
289  1 sq.sequenceChanged();
290  1 assertEquals(0, sq.findIndex(2));
291    }
292   
293    /**
294    * Tests for the method that returns a dataset sequence position (start..) for
295    * an aligned column position (base 0).
296    */
 
297  1 toggle @Test(groups = { "Functional" })
298    public void testFindPosition()
299    {
300    /*
301    * call sequenceChanged() after each test to invalidate any cursor,
302    * forcing the 1-arg findPosition to be executed
303    */
304  1 SequenceI sq = new Sequence("test/8-13", "ABCDEF");
305  1 assertEquals(8, sq.findPosition(0));
306    // Sequence should now hold a cursor at [8, 0]
307  1 assertEquals("test:Pos8:Col1:startCol1:endCol0:tok0",
308    PA.getValue(sq, "cursor").toString());
309  1 SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor");
310  1 int token = (int) PA.getValue(sq, "changeCount");
311  1 assertEquals(new SequenceCursor(sq, 8, 1, token), cursor);
312   
313  1 sq.sequenceChanged();
314   
315    /*
316    * find F13 at column offset 5, cursor should update to [13, 6]
317    * endColumn is found and saved in cursor
318    */
319  1 assertEquals(13, sq.findPosition(5));
320  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
321  1 assertEquals(++token, (int) PA.getValue(sq, "changeCount"));
322  1 assertEquals(new SequenceCursor(sq, 13, 6, token), cursor);
323  1 assertEquals("test:Pos13:Col6:startCol1:endCol6:tok1",
324    PA.getValue(sq, "cursor").toString());
325   
326    // assertEquals(-1, seq.findPosition(6)); // fails
327   
328  1 sq = new Sequence("test/8-11", "AB-C-D--");
329  1 token = (int) PA.getValue(sq, "changeCount"); // 0
330  1 assertEquals(8, sq.findPosition(0));
331  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
332  1 assertEquals(new SequenceCursor(sq, 8, 1, token), cursor);
333  1 assertEquals("test:Pos8:Col1:startCol1:endCol0:tok0",
334    PA.getValue(sq, "cursor").toString());
335   
336  1 sq.sequenceChanged();
337  1 assertEquals(9, sq.findPosition(1));
338  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
339  1 assertEquals(new SequenceCursor(sq, 9, 2, ++token), cursor);
340  1 assertEquals("test:Pos9:Col2:startCol1:endCol0:tok1",
341    PA.getValue(sq, "cursor").toString());
342   
343  1 sq.sequenceChanged();
344    // gap position 'finds' residue to the right (not the left as per javadoc)
345    // cursor is set to the last residue position found [B 2]
346  1 assertEquals(10, sq.findPosition(2));
347  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
348  1 assertEquals(new SequenceCursor(sq, 9, 2, ++token), cursor);
349  1 assertEquals("test:Pos9:Col2:startCol1:endCol0:tok2",
350    PA.getValue(sq, "cursor").toString());
351   
352  1 sq.sequenceChanged();
353  1 assertEquals(10, sq.findPosition(3));
354  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
355  1 assertEquals(new SequenceCursor(sq, 10, 4, ++token), cursor);
356  1 assertEquals("test:Pos10:Col4:startCol1:endCol0:tok3",
357    PA.getValue(sq, "cursor").toString());
358   
359  1 sq.sequenceChanged();
360    // column[4] is the gap after C - returns D11
361    // cursor is set to [C 4]
362  1 assertEquals(11, sq.findPosition(4));
363  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
364  1 assertEquals(new SequenceCursor(sq, 10, 4, ++token), cursor);
365  1 assertEquals("test:Pos10:Col4:startCol1:endCol0:tok4",
366    PA.getValue(sq, "cursor").toString());
367   
368  1 sq.sequenceChanged();
369  1 assertEquals(11, sq.findPosition(5)); // D
370  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
371  1 assertEquals(new SequenceCursor(sq, 11, 6, ++token), cursor);
372    // lastCol has been found and saved in the cursor
373  1 assertEquals("test:Pos11:Col6:startCol1:endCol6:tok5",
374    PA.getValue(sq, "cursor").toString());
375   
376  1 sq.sequenceChanged();
377    // returns 1 more than sequence length if off the end ?!?
378  1 assertEquals(12, sq.findPosition(6));
379   
380  1 sq.sequenceChanged();
381  1 assertEquals(12, sq.findPosition(7));
382   
383    /*
384    * first findPosition should also set firstResCol in cursor
385    */
386  1 sq = new Sequence("test/8-13", "--AB-C-DEF--");
387  1 assertEquals(8, sq.findPosition(0));
388  1 assertNull(PA.getValue(sq, "cursor"));
389   
390  1 sq.sequenceChanged();
391  1 assertEquals(8, sq.findPosition(1));
392  1 assertNull(PA.getValue(sq, "cursor"));
393   
394  1 sq.sequenceChanged();
395  1 assertEquals(8, sq.findPosition(2));
396  1 assertEquals("test:Pos8:Col3:startCol3:endCol0:tok2",
397    PA.getValue(sq, "cursor").toString());
398   
399  1 sq.sequenceChanged();
400  1 assertEquals(9, sq.findPosition(3));
401  1 assertEquals("test:Pos9:Col4:startCol3:endCol0:tok3",
402    PA.getValue(sq, "cursor").toString());
403   
404  1 sq.sequenceChanged();
405    // column[4] is a gap, returns next residue pos (C10)
406    // cursor is set to last residue found [B]
407  1 assertEquals(10, sq.findPosition(4));
408  1 assertEquals("test:Pos9:Col4:startCol3:endCol0:tok4",
409    PA.getValue(sq, "cursor").toString());
410   
411  1 sq.sequenceChanged();
412  1 assertEquals(10, sq.findPosition(5));
413  1 assertEquals("test:Pos10:Col6:startCol3:endCol0:tok5",
414    PA.getValue(sq, "cursor").toString());
415   
416  1 sq.sequenceChanged();
417    // column[6] is a gap, returns next residue pos (D11)
418    // cursor is set to last residue found [C]
419  1 assertEquals(11, sq.findPosition(6));
420  1 assertEquals("test:Pos10:Col6:startCol3:endCol0:tok6",
421    PA.getValue(sq, "cursor").toString());
422   
423  1 sq.sequenceChanged();
424  1 assertEquals(11, sq.findPosition(7));
425  1 assertEquals("test:Pos11:Col8:startCol3:endCol0:tok7",
426    PA.getValue(sq, "cursor").toString());
427   
428  1 sq.sequenceChanged();
429  1 assertEquals(12, sq.findPosition(8));
430  1 assertEquals("test:Pos12:Col9:startCol3:endCol0:tok8",
431    PA.getValue(sq, "cursor").toString());
432   
433    /*
434    * when the last residue column is found, it is set in the cursor
435    */
436  1 sq.sequenceChanged();
437  1 assertEquals(13, sq.findPosition(9));
438  1 assertEquals("test:Pos13:Col10:startCol3:endCol10:tok9",
439    PA.getValue(sq, "cursor").toString());
440   
441  1 sq.sequenceChanged();
442  1 assertEquals(14, sq.findPosition(10));
443  1 assertEquals("test:Pos13:Col10:startCol3:endCol10:tok10",
444    PA.getValue(sq, "cursor").toString());
445   
446    /*
447    * findPosition for column beyond sequence length
448    * returns 1 more than last residue position
449    */
450  1 sq.sequenceChanged();
451  1 assertEquals(14, sq.findPosition(11));
452  1 assertEquals("test:Pos13:Col10:startCol3:endCol10:tok11",
453    PA.getValue(sq, "cursor").toString());
454   
455  1 sq.sequenceChanged();
456  1 assertEquals(14, sq.findPosition(99));
457  1 assertEquals("test:Pos13:Col10:startCol3:endCol10:tok12",
458    PA.getValue(sq, "cursor").toString());
459   
460    /*
461    * gapped sequence ending in non-gap
462    */
463  1 sq = new Sequence("test/8-13", "--AB-C-DEF");
464  1 assertEquals(13, sq.findPosition(9));
465  1 assertEquals("test:Pos13:Col10:startCol3:endCol10:tok0",
466    PA.getValue(sq, "cursor").toString());
467  1 sq.sequenceChanged();
468  1 assertEquals(12, sq.findPosition(8));
469  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
470    // sequenceChanged() invalidates cursor.lastResidueColumn
471  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
472  1 assertEquals("test:Pos12:Col9:startCol3:endCol0:tok1",
473    cursor.toString());
474    // findPosition with cursor accepts base 1 column values
475  1 assertEquals(13, ((Sequence) sq).findPosition(10, cursor));
476  1 assertEquals(13, sq.findPosition(9)); // F13
477    // lastResidueColumn has now been found and saved in cursor
478  1 assertEquals("test:Pos13:Col10:startCol3:endCol10:tok1",
479    PA.getValue(sq, "cursor").toString());
480    }
481   
 
482  1 toggle @Test(groups = { "Functional" })
483    public void testDeleteChars()
484    {
485    /*
486    * internal delete
487    */
488  1 SequenceI sq = new Sequence("test", "ABCDEF");
489  1 assertNull(PA.getValue(sq, "datasetSequence"));
490  1 assertEquals(1, sq.getStart());
491  1 assertEquals(6, sq.getEnd());
492  1 sq.deleteChars(2, 3);
493  1 assertEquals("ABDEF", sq.getSequenceAsString());
494  1 assertEquals(1, sq.getStart());
495  1 assertEquals(5, sq.getEnd());
496  1 assertNull(PA.getValue(sq, "datasetSequence"));
497   
498    /*
499    * delete at start
500    */
501  1 sq = new Sequence("test", "ABCDEF");
502  1 sq.deleteChars(0, 2);
503  1 assertEquals("CDEF", sq.getSequenceAsString());
504  1 assertEquals(3, sq.getStart());
505  1 assertEquals(6, sq.getEnd());
506  1 assertNull(PA.getValue(sq, "datasetSequence"));
507   
508    /*
509    * delete at end
510    */
511  1 sq = new Sequence("test", "ABCDEF");
512  1 sq.deleteChars(4, 6);
513  1 assertEquals("ABCD", sq.getSequenceAsString());
514  1 assertEquals(1, sq.getStart());
515  1 assertEquals(4, sq.getEnd());
516  1 assertNull(PA.getValue(sq, "datasetSequence"));
517    }
518   
 
519  1 toggle @Test(groups = { "Functional" })
520    public void testDeleteChars_withDbRefsAndFeatures()
521    {
522    /*
523    * internal delete - new dataset sequence created
524    * gets a copy of any dbrefs
525    */
526  1 SequenceI sq = new Sequence("test", "ABCDEF");
527  1 sq.createDatasetSequence();
528  1 DBRefEntry dbr1 = new DBRefEntry("Uniprot", "0", "a123");
529  1 sq.addDBRef(dbr1);
530  1 Object ds = PA.getValue(sq, "datasetSequence");
531  1 assertNotNull(ds);
532  1 assertEquals(1, sq.getStart());
533  1 assertEquals(6, sq.getEnd());
534  1 sq.deleteChars(2, 3);
535  1 assertEquals("ABDEF", sq.getSequenceAsString());
536  1 assertEquals(1, sq.getStart());
537  1 assertEquals(5, sq.getEnd());
538  1 Object newDs = PA.getValue(sq, "datasetSequence");
539  1 assertNotNull(newDs);
540  1 assertNotSame(ds, newDs);
541  1 assertNotNull(sq.getDBRefs());
542  1 assertEquals(1, sq.getDBRefs().length);
543  1 assertNotSame(dbr1, sq.getDBRefs()[0]);
544  1 assertEquals(dbr1, sq.getDBRefs()[0]);
545   
546    /*
547    * internal delete with sequence features
548    * (failure case for JAL-2541)
549    */
550  1 sq = new Sequence("test", "ABCDEF");
551  1 sq.createDatasetSequence();
552  1 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 2, 4, 2f,
553    "CathGroup");
554  1 sq.addSequenceFeature(sf1);
555  1 ds = PA.getValue(sq, "datasetSequence");
556  1 assertNotNull(ds);
557  1 assertEquals(1, sq.getStart());
558  1 assertEquals(6, sq.getEnd());
559  1 sq.deleteChars(2, 4);
560  1 assertEquals("ABEF", sq.getSequenceAsString());
561  1 assertEquals(1, sq.getStart());
562  1 assertEquals(4, sq.getEnd());
563  1 newDs = PA.getValue(sq, "datasetSequence");
564  1 assertNotNull(newDs);
565  1 assertNotSame(ds, newDs);
566  1 List<SequenceFeature> sfs = sq.getSequenceFeatures();
567  1 assertEquals(1, sfs.size());
568  1 assertNotSame(sf1, sfs.get(0));
569  1 assertEquals(sf1, sfs.get(0));
570   
571    /*
572    * delete at start - no new dataset sequence created
573    * any sequence features remain as before
574    */
575  1 sq = new Sequence("test", "ABCDEF");
576  1 sq.createDatasetSequence();
577  1 ds = PA.getValue(sq, "datasetSequence");
578  1 sf1 = new SequenceFeature("Cath", "desc", 2, 4, 2f, "CathGroup");
579  1 sq.addSequenceFeature(sf1);
580  1 sq.deleteChars(0, 2);
581  1 assertEquals("CDEF", sq.getSequenceAsString());
582  1 assertEquals(3, sq.getStart());
583  1 assertEquals(6, sq.getEnd());
584  1 assertSame(ds, PA.getValue(sq, "datasetSequence"));
585  1 sfs = sq.getSequenceFeatures();
586  1 assertNotNull(sfs);
587  1 assertEquals(1, sfs.size());
588  1 assertSame(sf1, sfs.get(0));
589   
590    /*
591    * delete at end - no new dataset sequence created
592    * any dbrefs remain as before
593    */
594  1 sq = new Sequence("test", "ABCDEF");
595  1 sq.createDatasetSequence();
596  1 ds = PA.getValue(sq, "datasetSequence");
597  1 dbr1 = new DBRefEntry("Uniprot", "0", "a123");
598  1 sq.addDBRef(dbr1);
599  1 sq.deleteChars(4, 6);
600  1 assertEquals("ABCD", sq.getSequenceAsString());
601  1 assertEquals(1, sq.getStart());
602  1 assertEquals(4, sq.getEnd());
603  1 assertSame(ds, PA.getValue(sq, "datasetSequence"));
604  1 assertNotNull(sq.getDBRefs());
605  1 assertEquals(1, sq.getDBRefs().length);
606  1 assertSame(dbr1, sq.getDBRefs()[0]);
607    }
608   
 
609  1 toggle @Test(groups = { "Functional" })
610    public void testInsertCharAt()
611    {
612    // non-static methods:
613  1 SequenceI sq = new Sequence("test", "ABCDEF");
614  1 sq.insertCharAt(0, 'z');
615  1 assertEquals("zABCDEF", sq.getSequenceAsString());
616  1 sq.insertCharAt(2, 2, 'x');
617  1 assertEquals("zAxxBCDEF", sq.getSequenceAsString());
618   
619    // for static method see StringUtilsTest
620    }
621   
622    /**
623    * Test the method that returns an array of aligned sequence positions where
624    * the array index is the data sequence position (both base 0).
625    */
 
626  1 toggle @Test(groups = { "Functional" })
627    public void testGapMap()
628    {
629  1 SequenceI sq = new Sequence("test", "-A--B-CD-E--F-");
630  1 sq.createDatasetSequence();
631  1 assertEquals("[1, 4, 6, 7, 9, 12]", Arrays.toString(sq.gapMap()));
632    }
633   
634    /**
635    * Test the method that gets sequence features, either from the sequence or
636    * its dataset.
637    */
 
638  1 toggle @Test(groups = { "Functional" })
639    public void testGetSequenceFeatures()
640    {
641  1 SequenceI sq = new Sequence("test", "GATCAT");
642  1 sq.createDatasetSequence();
643   
644  1 assertTrue(sq.getSequenceFeatures().isEmpty());
645   
646    /*
647    * SequenceFeature on sequence
648    */
649  1 SequenceFeature sf = new SequenceFeature("Cath", "desc", 2, 4, 2f, null);
650  1 sq.addSequenceFeature(sf);
651  1 List<SequenceFeature> sfs = sq.getSequenceFeatures();
652  1 assertEquals(1, sfs.size());
653  1 assertSame(sf, sfs.get(0));
654   
655    /*
656    * SequenceFeature on sequence and dataset sequence; returns that on
657    * sequence
658    *
659    * Note JAL-2046: spurious: we have no use case for this at the moment.
660    * This test also buggy - as sf2.equals(sf), no new feature is added
661    */
662  1 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 2, 4, 2f,
663    null);
664  1 sq.getDatasetSequence().addSequenceFeature(sf2);
665  1 sfs = sq.getSequenceFeatures();
666  1 assertEquals(1, sfs.size());
667  1 assertSame(sf, sfs.get(0));
668   
669    /*
670    * SequenceFeature on dataset sequence only
671    * Note JAL-2046: spurious: we have no use case for setting a non-dataset sequence's feature array to null at the moment.
672    */
673  1 sq.setSequenceFeatures(null);
674  1 assertTrue(sq.getDatasetSequence().getSequenceFeatures().isEmpty());
675   
676    /*
677    * Corrupt case - no SequenceFeature, dataset's dataset is the original
678    * sequence. Test shows no infinite loop results.
679    */
680  1 sq.getDatasetSequence().setSequenceFeatures(null);
681    /**
682    * is there a usecase for this ? setDatasetSequence should throw an error if
683    * this actually occurs.
684    */
685  1 try
686    {
687  1 sq.getDatasetSequence().setDatasetSequence(sq); // loop!
688  0 Assert.fail("Expected Error to be raised when calling setDatasetSequence with self reference");
689    } catch (IllegalArgumentException e)
690    {
691    // TODO Jalview error/exception class for raising implementation errors
692  1 assertTrue(e.getMessage().toLowerCase()
693    .contains("implementation error"));
694    }
695  1 assertTrue(sq.getSequenceFeatures().isEmpty());
696    }
697   
698    /**
699    * Test the method that returns an array, indexed by sequence position, whose
700    * entries are the residue positions at the sequence position (or to the right
701    * if a gap)
702    */
 
703  1 toggle @Test(groups = { "Functional" })
704    public void testFindPositionMap()
705    {
706    /*
707    * Note: Javadoc for findPosition says it returns the residue position to
708    * the left of a gapped position; in fact it returns the position to the
709    * right. Also it returns a non-existent residue position for a gap beyond
710    * the sequence.
711    */
712  1 Sequence sq = new Sequence("TestSeq", "AB.C-D E.");
713  1 int[] map = sq.findPositionMap();
714  1 assertEquals(Arrays.toString(new int[] { 1, 2, 3, 3, 4, 4, 5, 5, 6 }),
715    Arrays.toString(map));
716    }
717   
718    /**
719    * Test for getSubsequence
720    */
 
721  1 toggle @Test(groups = { "Functional" })
722    public void testGetSubsequence()
723    {
724  1 SequenceI sq = new Sequence("TestSeq", "ABCDEFG");
725  1 sq.createDatasetSequence();
726   
727    // positions are base 0, end position is exclusive
728  1 SequenceI subseq = sq.getSubSequence(2, 4);
729   
730  1 assertEquals("CD", subseq.getSequenceAsString());
731    // start/end are base 1 positions
732  1 assertEquals(3, subseq.getStart());
733  1 assertEquals(4, subseq.getEnd());
734    // subsequence shares the full dataset sequence
735  1 assertSame(sq.getDatasetSequence(), subseq.getDatasetSequence());
736    }
737   
738    /**
739    * test createDatasetSequence behaves to doc
740    */
 
741  1 toggle @Test(groups = { "Functional" })
742    public void testCreateDatasetSequence()
743    {
744  1 SequenceI sq = new Sequence("my", "ASDASD");
745  1 sq.addSequenceFeature(new SequenceFeature("type", "desc", 1, 10, 1f,
746    "group"));
747  1 sq.addDBRef(new DBRefEntry("source", "version", "accession"));
748  1 assertNull(sq.getDatasetSequence());
749  1 assertNotNull(PA.getValue(sq, "sequenceFeatureStore"));
750  1 assertNotNull(PA.getValue(sq, "dbrefs"));
751   
752  1 SequenceI rds = sq.createDatasetSequence();
753  1 assertNotNull(rds);
754  1 assertNull(rds.getDatasetSequence());
755  1 assertSame(sq.getDatasetSequence(), rds);
756   
757    // sequence features and dbrefs transferred to dataset sequence
758  1 assertNull(PA.getValue(sq, "sequenceFeatureStore"));
759  1 assertNull(PA.getValue(sq, "dbrefs"));
760  1 assertNotNull(PA.getValue(rds, "sequenceFeatureStore"));
761  1 assertNotNull(PA.getValue(rds, "dbrefs"));
762    }
763   
764    /**
765    * Test for deriveSequence applied to a sequence with a dataset
766    */
 
767  1 toggle @Test(groups = { "Functional" })
768    public void testDeriveSequence_existingDataset()
769    {
770  1 Sequence sq = new Sequence("Seq1", "CD");
771  1 sq.setDatasetSequence(new Sequence("Seq1", "ABCDEF"));
772  1 sq.getDatasetSequence().addSequenceFeature(
773    new SequenceFeature("", "", 1, 2, 0f, null));
774  1 sq.setStart(3);
775  1 sq.setEnd(4);
776   
777  1 sq.setDescription("Test sequence description..");
778  1 sq.setVamsasId("TestVamsasId");
779  1 sq.addDBRef(new DBRefEntry("PDB", "version0", "1TST"));
780   
781  1 sq.addDBRef(new DBRefEntry("PDB", "version1", "1PDB"));
782  1 sq.addDBRef(new DBRefEntry("PDB", "version2", "2PDB"));
783  1 sq.addDBRef(new DBRefEntry("PDB", "version3", "3PDB"));
784  1 sq.addDBRef(new DBRefEntry("PDB", "version4", "4PDB"));
785   
786  1 sq.addPDBId(new PDBEntry("1PDB", "A", Type.PDB, "filePath/test1"));
787  1 sq.addPDBId(new PDBEntry("1PDB", "B", Type.PDB, "filePath/test1"));
788  1 sq.addPDBId(new PDBEntry("2PDB", "A", Type.MMCIF, "filePath/test2"));
789  1 sq.addPDBId(new PDBEntry("2PDB", "B", Type.MMCIF, "filePath/test2"));
790   
791    // these are the same as ones already added
792  1 DBRefEntry pdb1pdb = new DBRefEntry("PDB", "version1", "1PDB");
793  1 DBRefEntry pdb2pdb = new DBRefEntry("PDB", "version2", "2PDB");
794   
795  1 List<DBRefEntry> primRefs = Arrays.asList(new DBRefEntry[] { pdb1pdb,
796    pdb2pdb });
797   
798  1 sq.getDatasetSequence().addDBRef(pdb1pdb); // should do nothing
799  1 sq.getDatasetSequence().addDBRef(pdb2pdb); // should do nothing
800  1 sq.getDatasetSequence().addDBRef(
801    new DBRefEntry("PDB", "version3", "3PDB")); // should do nothing
802  1 sq.getDatasetSequence().addDBRef(
803    new DBRefEntry("PDB", "version4", "4PDB")); // should do nothing
804   
805  1 PDBEntry pdbe1a = new PDBEntry("1PDB", "A", Type.PDB, "filePath/test1");
806  1 PDBEntry pdbe1b = new PDBEntry("1PDB", "B", Type.PDB, "filePath/test1");
807  1 PDBEntry pdbe2a = new PDBEntry("2PDB", "A", Type.MMCIF,
808    "filePath/test2");
809  1 PDBEntry pdbe2b = new PDBEntry("2PDB", "B", Type.MMCIF,
810    "filePath/test2");
811  1 sq.getDatasetSequence().addPDBId(pdbe1a);
812  1 sq.getDatasetSequence().addPDBId(pdbe1b);
813  1 sq.getDatasetSequence().addPDBId(pdbe2a);
814  1 sq.getDatasetSequence().addPDBId(pdbe2b);
815   
816    /*
817    * test we added pdb entries to the dataset sequence
818    */
819  1 Assert.assertEquals(sq.getDatasetSequence().getAllPDBEntries(), Arrays
820    .asList(new PDBEntry[] { pdbe1a, pdbe1b, pdbe2a, pdbe2b }),
821    "PDB Entries were not found on dataset sequence.");
822   
823    /*
824    * we should recover a pdb entry that is on the dataset sequence via PDBEntry
825    */
826  1 Assert.assertEquals(pdbe1a,
827    sq.getDatasetSequence().getPDBEntry("1PDB"),
828    "PDB Entry '1PDB' not found on dataset sequence via getPDBEntry.");
829  1 ArrayList<Annotation> annotsList = new ArrayList<>();
830  1 System.out.println(">>>>>> " + sq.getSequenceAsString().length());
831  1 annotsList.add(new Annotation("A", "A", 'X', 0.1f));
832  1 annotsList.add(new Annotation("A", "A", 'X', 0.1f));
833  1 Annotation[] annots = annotsList.toArray(new Annotation[0]);
834  1 sq.addAlignmentAnnotation(new AlignmentAnnotation("Test annot",
835    "Test annot description", annots));
836  1 sq.getDatasetSequence().addAlignmentAnnotation(
837    new AlignmentAnnotation("Test annot", "Test annot description",
838    annots));
839  1 Assert.assertEquals(sq.getDescription(), "Test sequence description..");
840  1 Assert.assertEquals(sq.getDBRefs().length, 5); // DBRefs are on dataset
841    // sequence
842  1 Assert.assertEquals(sq.getAllPDBEntries().size(), 4);
843  1 Assert.assertNotNull(sq.getAnnotation());
844  1 Assert.assertEquals(sq.getAnnotation()[0].annotations.length, 2);
845  1 Assert.assertEquals(sq.getDatasetSequence().getDBRefs().length, 5); // same
846    // as
847    // sq.getDBRefs()
848  1 Assert.assertEquals(sq.getDatasetSequence().getAllPDBEntries().size(),
849    4);
850  1 Assert.assertNotNull(sq.getDatasetSequence().getAnnotation());
851   
852  1 Sequence derived = (Sequence) sq.deriveSequence();
853   
854  1 Assert.assertEquals(derived.getDescription(),
855    "Test sequence description..");
856  1 Assert.assertEquals(derived.getDBRefs().length, 5); // come from dataset
857  1 Assert.assertEquals(derived.getAllPDBEntries().size(), 4);
858  1 Assert.assertNotNull(derived.getAnnotation());
859  1 Assert.assertEquals(derived.getAnnotation()[0].annotations.length, 2);
860  1 Assert.assertEquals(derived.getDatasetSequence().getDBRefs().length, 5);
861  1 Assert.assertEquals(derived.getDatasetSequence().getAllPDBEntries()
862    .size(), 4);
863  1 Assert.assertNotNull(derived.getDatasetSequence().getAnnotation());
864   
865  1 assertEquals("CD", derived.getSequenceAsString());
866  1 assertSame(sq.getDatasetSequence(), derived.getDatasetSequence());
867   
868    // derived sequence should access dataset sequence features
869  1 assertNotNull(sq.getSequenceFeatures());
870  1 assertEquals(sq.getSequenceFeatures(), derived.getSequenceFeatures());
871   
872    /*
873    * verify we have primary db refs *just* for PDB IDs with associated
874    * PDBEntry objects
875    */
876   
877  1 assertEquals(primRefs, sq.getPrimaryDBRefs());
878  1 assertEquals(primRefs, sq.getDatasetSequence().getPrimaryDBRefs());
879   
880  1 assertEquals(sq.getPrimaryDBRefs(), derived.getPrimaryDBRefs());
881   
882    }
883   
884    /**
885    * Test for deriveSequence applied to an ungapped sequence with no dataset
886    */
 
887  1 toggle @Test(groups = { "Functional" })
888    public void testDeriveSequence_noDatasetUngapped()
889    {
890  1 SequenceI sq = new Sequence("Seq1", "ABCDEF");
891  1 assertEquals(1, sq.getStart());
892  1 assertEquals(6, sq.getEnd());
893  1 SequenceI derived = sq.deriveSequence();
894  1 assertEquals("ABCDEF", derived.getSequenceAsString());
895  1 assertEquals("ABCDEF", derived.getDatasetSequence()
896    .getSequenceAsString());
897    }
898   
899    /**
900    * Test for deriveSequence applied to a gapped sequence with no dataset
901    */
 
902  1 toggle @Test(groups = { "Functional" })
903    public void testDeriveSequence_noDatasetGapped()
904    {
905  1 SequenceI sq = new Sequence("Seq1", "AB-C.D EF");
906  1 assertEquals(1, sq.getStart());
907  1 assertEquals(6, sq.getEnd());
908  1 assertNull(sq.getDatasetSequence());
909  1 SequenceI derived = sq.deriveSequence();
910  1 assertEquals("AB-C.D EF", derived.getSequenceAsString());
911  1 assertEquals("ABCDEF", derived.getDatasetSequence()
912    .getSequenceAsString());
913    }
914   
 
915  1 toggle @Test(groups = { "Functional" })
916    public void testCopyConstructor_noDataset()
917    {
918  1 SequenceI seq1 = new Sequence("Seq1", "AB-C.D EF");
919  1 seq1.setDescription("description");
920  1 seq1.addAlignmentAnnotation(new AlignmentAnnotation("label", "desc",
921    1.3d));
922  1 seq1.addSequenceFeature(new SequenceFeature("type", "desc", 22, 33,
923    12.4f, "group"));
924  1 seq1.addPDBId(new PDBEntry("1A70", "B", Type.PDB, "File"));
925  1 seq1.addDBRef(new DBRefEntry("EMBL", "1.2", "AZ12345"));
926   
927  1 SequenceI copy = new Sequence(seq1);
928   
929  1 assertNull(copy.getDatasetSequence());
930   
931  1 verifyCopiedSequence(seq1, copy);
932   
933    // copy has a copy of the DBRefEntry
934    // this is murky - DBrefs are only copied for dataset sequences
935    // where the test for 'dataset sequence' is 'dataset is null'
936    // but that doesn't distinguish it from an aligned sequence
937    // which has not yet generated a dataset sequence
938    // NB getDBRef looks inside dataset sequence if not null
939  1 DBRefEntry[] dbrefs = copy.getDBRefs();
940  1 assertEquals(1, dbrefs.length);
941  1 assertFalse(dbrefs[0] == seq1.getDBRefs()[0]);
942  1 assertTrue(dbrefs[0].equals(seq1.getDBRefs()[0]));
943    }
944   
 
945  1 toggle @Test(groups = { "Functional" })
946    public void testCopyConstructor_withDataset()
947    {
948  1 SequenceI seq1 = new Sequence("Seq1", "AB-C.D EF");
949  1 seq1.createDatasetSequence();
950  1 seq1.setDescription("description");
951  1 seq1.addAlignmentAnnotation(new AlignmentAnnotation("label", "desc",
952    1.3d));
953    // JAL-2046 - what is the contract for using a derived sequence's
954    // addSequenceFeature ?
955  1 seq1.addSequenceFeature(new SequenceFeature("type", "desc", 22, 33,
956    12.4f, "group"));
957  1 seq1.addPDBId(new PDBEntry("1A70", "B", Type.PDB, "File"));
958    // here we add DBRef to the dataset sequence:
959  1 seq1.getDatasetSequence().addDBRef(
960    new DBRefEntry("EMBL", "1.2", "AZ12345"));
961   
962  1 SequenceI copy = new Sequence(seq1);
963   
964  1 assertNotNull(copy.getDatasetSequence());
965  1 assertSame(copy.getDatasetSequence(), seq1.getDatasetSequence());
966   
967  1 verifyCopiedSequence(seq1, copy);
968   
969    // getDBRef looks inside dataset sequence and this is shared,
970    // so holds the same dbref objects
971  1 DBRefEntry[] dbrefs = copy.getDBRefs();
972  1 assertEquals(1, dbrefs.length);
973  1 assertSame(dbrefs[0], seq1.getDBRefs()[0]);
974    }
975   
976    /**
977    * Helper to make assertions about a copied sequence
978    *
979    * @param seq1
980    * @param copy
981    */
 
982  2 toggle protected void verifyCopiedSequence(SequenceI seq1, SequenceI copy)
983    {
984    // verify basic properties:
985  2 assertEquals(copy.getName(), seq1.getName());
986  2 assertEquals(copy.getDescription(), seq1.getDescription());
987  2 assertEquals(copy.getStart(), seq1.getStart());
988  2 assertEquals(copy.getEnd(), seq1.getEnd());
989  2 assertEquals(copy.getSequenceAsString(), seq1.getSequenceAsString());
990   
991    // copy has a copy of the annotation:
992  2 AlignmentAnnotation[] anns = copy.getAnnotation();
993  2 assertEquals(1, anns.length);
994  2 assertFalse(anns[0] == seq1.getAnnotation()[0]);
995  2 assertEquals(anns[0].label, seq1.getAnnotation()[0].label);
996  2 assertEquals(anns[0].description, seq1.getAnnotation()[0].description);
997  2 assertEquals(anns[0].score, seq1.getAnnotation()[0].score);
998   
999    // copy has a copy of the sequence feature:
1000  2 List<SequenceFeature> sfs = copy.getSequenceFeatures();
1001  2 assertEquals(1, sfs.size());
1002  2 if (seq1.getDatasetSequence() != null
1003    && copy.getDatasetSequence() == seq1.getDatasetSequence())
1004    {
1005  1 assertSame(sfs.get(0), seq1.getSequenceFeatures().get(0));
1006    }
1007    else
1008    {
1009  1 assertNotSame(sfs.get(0), seq1.getSequenceFeatures().get(0));
1010    }
1011  2 assertEquals(sfs.get(0), seq1.getSequenceFeatures().get(0));
1012   
1013    // copy has a copy of the PDB entry
1014  2 Vector<PDBEntry> pdbs = copy.getAllPDBEntries();
1015  2 assertEquals(1, pdbs.size());
1016  2 assertFalse(pdbs.get(0) == seq1.getAllPDBEntries().get(0));
1017  2 assertTrue(pdbs.get(0).equals(seq1.getAllPDBEntries().get(0)));
1018    }
1019   
 
1020  1 toggle @Test(groups = "Functional")
1021    public void testGetCharAt()
1022    {
1023  1 SequenceI sq = new Sequence("", "abcde");
1024  1 assertEquals('a', sq.getCharAt(0));
1025  1 assertEquals('e', sq.getCharAt(4));
1026  1 assertEquals(' ', sq.getCharAt(5));
1027  1 assertEquals(' ', sq.getCharAt(-1));
1028    }
1029   
 
1030  1 toggle @Test(groups = { "Functional" })
1031    public void testAddSequenceFeatures()
1032    {
1033  1 SequenceI sq = new Sequence("", "abcde");
1034    // type may not be null
1035  1 assertFalse(sq.addSequenceFeature(new SequenceFeature(null, "desc", 4,
1036    8, 0f, null)));
1037  1 assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
1038    8, 0f, null)));
1039    // can't add a duplicate feature
1040  1 assertFalse(sq.addSequenceFeature(new SequenceFeature("Cath", "desc",
1041    4, 8, 0f, null)));
1042    // can add a different feature
1043  1 assertTrue(sq.addSequenceFeature(new SequenceFeature("Scop", "desc", 4,
1044    8, 0f, null))); // different type
1045  1 assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath",
1046    "description", 4, 8, 0f, null)));// different description
1047  1 assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 3,
1048    8, 0f, null))); // different start position
1049  1 assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
1050    9, 0f, null))); // different end position
1051  1 assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
1052    8, 1f, null))); // different score
1053  1 assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
1054    8, Float.NaN, null))); // score NaN
1055  1 assertTrue(sq.addSequenceFeature(new SequenceFeature("Cath", "desc", 4,
1056    8, 0f, "Metal"))); // different group
1057  1 assertEquals(8, sq.getFeatures().getAllFeatures().size());
1058    }
1059   
1060    /**
1061    * Tests for adding (or updating) dbrefs
1062    *
1063    * @see DBRefEntry#updateFrom(DBRefEntry)
1064    */
 
1065  1 toggle @Test(groups = { "Functional" })
1066    public void testAddDBRef()
1067    {
1068  1 SequenceI sq = new Sequence("", "abcde");
1069  1 assertNull(sq.getDBRefs());
1070  1 DBRefEntry dbref = new DBRefEntry("Uniprot", "1", "P00340");
1071  1 sq.addDBRef(dbref);
1072  1 assertEquals(1, sq.getDBRefs().length);
1073  1 assertSame(dbref, sq.getDBRefs()[0]);
1074   
1075    /*
1076    * change of version - new entry
1077    */
1078  1 DBRefEntry dbref2 = new DBRefEntry("Uniprot", "2", "P00340");
1079  1 sq.addDBRef(dbref2);
1080  1 assertEquals(2, sq.getDBRefs().length);
1081  1 assertSame(dbref, sq.getDBRefs()[0]);
1082  1 assertSame(dbref2, sq.getDBRefs()[1]);
1083   
1084    /*
1085    * matches existing entry - not added
1086    */
1087  1 sq.addDBRef(new DBRefEntry("UNIPROT", "1", "p00340"));
1088  1 assertEquals(2, sq.getDBRefs().length);
1089   
1090    /*
1091    * different source = new entry
1092    */
1093  1 DBRefEntry dbref3 = new DBRefEntry("UniRef", "1", "p00340");
1094  1 sq.addDBRef(dbref3);
1095  1 assertEquals(3, sq.getDBRefs().length);
1096  1 assertSame(dbref3, sq.getDBRefs()[2]);
1097   
1098    /*
1099    * different ref = new entry
1100    */
1101  1 DBRefEntry dbref4 = new DBRefEntry("UniRef", "1", "p00341");
1102  1 sq.addDBRef(dbref4);
1103  1 assertEquals(4, sq.getDBRefs().length);
1104  1 assertSame(dbref4, sq.getDBRefs()[3]);
1105   
1106    /*
1107    * matching ref with a mapping - map updated
1108    */
1109  1 DBRefEntry dbref5 = new DBRefEntry("UniRef", "1", "p00341");
1110  1 Mapping map = new Mapping(new MapList(new int[] { 1, 3 }, new int[] {
1111    1, 1 }, 3, 1));
1112  1 dbref5.setMap(map);
1113  1 sq.addDBRef(dbref5);
1114  1 assertEquals(4, sq.getDBRefs().length);
1115  1 assertSame(dbref4, sq.getDBRefs()[3]);
1116  1 assertSame(map, dbref4.getMap());
1117   
1118    /*
1119    * 'real' version replaces "0" version
1120    */
1121  1 dbref2.setVersion("0");
1122  1 DBRefEntry dbref6 = new DBRefEntry(dbref2.getSource(), "3",
1123    dbref2.getAccessionId());
1124  1 sq.addDBRef(dbref6);
1125  1 assertEquals(4, sq.getDBRefs().length);
1126  1 assertSame(dbref2, sq.getDBRefs()[1]);
1127  1 assertEquals("3", dbref2.getVersion());
1128   
1129    /*
1130    * 'real' version replaces "source:0" version
1131    */
1132  1 dbref3.setVersion("Uniprot:0");
1133  1 DBRefEntry dbref7 = new DBRefEntry(dbref3.getSource(), "3",
1134    dbref3.getAccessionId());
1135  1 sq.addDBRef(dbref7);
1136  1 assertEquals(4, sq.getDBRefs().length);
1137  1 assertSame(dbref3, sq.getDBRefs()[2]);
1138  1 assertEquals("3", dbref2.getVersion());
1139    }
1140   
 
1141  1 toggle @Test(groups = { "Functional" })
1142    public void testGetPrimaryDBRefs_peptide()
1143    {
1144  1 SequenceI sq = new Sequence("aseq", "ASDFKYLMQPRST", 10, 22);
1145   
1146    // no dbrefs
1147  1 List<DBRefEntry> primaryDBRefs = sq.getPrimaryDBRefs();
1148  1 assertTrue(primaryDBRefs.isEmpty());
1149   
1150    // empty dbrefs
1151  1 sq.setDBRefs(new DBRefEntry[] {});
1152  1 primaryDBRefs = sq.getPrimaryDBRefs();
1153  1 assertTrue(primaryDBRefs.isEmpty());
1154   
1155    // primary - uniprot
1156  1 DBRefEntry upentry1 = new DBRefEntry("UNIPROT", "0", "Q04760");
1157  1 sq.addDBRef(upentry1);
1158   
1159    // primary - uniprot with congruent map
1160  1 DBRefEntry upentry2 = new DBRefEntry("UNIPROT", "0", "Q04762");
1161  1 upentry2.setMap(new Mapping(null, new MapList(new int[] { 10, 22 },
1162    new int[] { 10, 22 }, 1, 1)));
1163  1 sq.addDBRef(upentry2);
1164   
1165    // primary - uniprot with map of enclosing sequence
1166  1 DBRefEntry upentry3 = new DBRefEntry("UNIPROT", "0", "Q04763");
1167  1 upentry3.setMap(new Mapping(null, new MapList(new int[] { 8, 24 },
1168    new int[] { 8, 24 }, 1, 1)));
1169  1 sq.addDBRef(upentry3);
1170   
1171    // not primary - uniprot with map of sub-sequence (5')
1172  1 DBRefEntry upentry4 = new DBRefEntry("UNIPROT", "0", "Q04764");
1173  1 upentry4.setMap(new Mapping(null, new MapList(new int[] { 10, 18 },
1174    new int[] { 10, 18 }, 1, 1)));
1175  1 sq.addDBRef(upentry4);
1176   
1177    // not primary - uniprot with map that overlaps 3'
1178  1 DBRefEntry upentry5 = new DBRefEntry("UNIPROT", "0", "Q04765");
1179  1 upentry5.setMap(new Mapping(null, new MapList(new int[] { 12, 22 },
1180    new int[] { 12, 22 }, 1, 1)));
1181  1 sq.addDBRef(upentry5);
1182   
1183    // not primary - uniprot with map to different coordinates frame
1184  1 DBRefEntry upentry6 = new DBRefEntry("UNIPROT", "0", "Q04766");
1185  1 upentry6.setMap(new Mapping(null, new MapList(new int[] { 12, 18 },
1186    new int[] { 112, 118 }, 1, 1)));
1187  1 sq.addDBRef(upentry6);
1188   
1189    // not primary - dbref to 'non-core' database
1190  1 DBRefEntry upentry7 = new DBRefEntry("Pfam", "0", "PF00903");
1191  1 sq.addDBRef(upentry7);
1192   
1193    // primary - type is PDB
1194  1 DBRefEntry pdbentry = new DBRefEntry("PDB", "0", "1qip");
1195  1 sq.addDBRef(pdbentry);
1196   
1197    // not primary - PDBEntry has no file
1198  1 sq.addDBRef(new DBRefEntry("PDB", "0", "1AAA"));
1199   
1200    // not primary - no PDBEntry
1201  1 sq.addDBRef(new DBRefEntry("PDB", "0", "1DDD"));
1202   
1203    // add corroborating PDB entry for primary DBref -
1204    // needs to have a file as well as matching ID
1205    // note PDB ID is not treated as case sensitive
1206  1 sq.addPDBId(new PDBEntry("1QIP", null, Type.PDB, new File("/blah")
1207    .toString()));
1208   
1209    // not valid DBRef - no file..
1210  1 sq.addPDBId(new PDBEntry("1AAA", null, null, null));
1211   
1212  1 primaryDBRefs = sq.getPrimaryDBRefs();
1213  1 assertEquals(4, primaryDBRefs.size());
1214  1 assertTrue("Couldn't find simple primary reference (UNIPROT)",
1215    primaryDBRefs.contains(upentry1));
1216  1 assertTrue("Couldn't find mapped primary reference (UNIPROT)",
1217    primaryDBRefs.contains(upentry2));
1218  1 assertTrue("Couldn't find mapped context reference (UNIPROT)",
1219    primaryDBRefs.contains(upentry3));
1220  1 assertTrue("Couldn't find expected PDB primary reference",
1221    primaryDBRefs.contains(pdbentry));
1222    }
1223   
 
1224  1 toggle @Test(groups = { "Functional" })
1225    public void testGetPrimaryDBRefs_nucleotide()
1226    {
1227  1 SequenceI sq = new Sequence("aseq", "TGATCACTCGACTAGCATCAGCATA", 10, 34);
1228   
1229    // primary - Ensembl
1230  1 DBRefEntry dbr1 = new DBRefEntry("ENSEMBL", "0", "ENSG1234");
1231  1 sq.addDBRef(dbr1);
1232   
1233    // not primary - Ensembl 'transcript' mapping of sub-sequence
1234  1 DBRefEntry dbr2 = new DBRefEntry("ENSEMBL", "0", "ENST1234");
1235  1 dbr2.setMap(new Mapping(null, new MapList(new int[] { 15, 25 },
1236    new int[] { 1, 11 }, 1, 1)));
1237  1 sq.addDBRef(dbr2);
1238   
1239    // primary - EMBL with congruent map
1240  1 DBRefEntry dbr3 = new DBRefEntry("EMBL", "0", "J1234");
1241  1 dbr3.setMap(new Mapping(null, new MapList(new int[] { 10, 34 },
1242    new int[] { 10, 34 }, 1, 1)));
1243  1 sq.addDBRef(dbr3);
1244   
1245    // not primary - to non-core database
1246  1 DBRefEntry dbr4 = new DBRefEntry("CCDS", "0", "J1234");
1247  1 sq.addDBRef(dbr4);
1248   
1249    // not primary - to protein
1250  1 DBRefEntry dbr5 = new DBRefEntry("UNIPROT", "0", "Q87654");
1251  1 sq.addDBRef(dbr5);
1252   
1253  1 List<DBRefEntry> primaryDBRefs = sq.getPrimaryDBRefs();
1254  1 assertEquals(2, primaryDBRefs.size());
1255  1 assertTrue(primaryDBRefs.contains(dbr1));
1256  1 assertTrue(primaryDBRefs.contains(dbr3));
1257    }
1258   
1259    /**
1260    * Test the method that updates the list of PDBEntry from any new DBRefEntry
1261    * for PDB
1262    */
 
1263  1 toggle @Test(groups = { "Functional" })
1264    public void testUpdatePDBIds()
1265    {
1266  1 PDBEntry pdbe1 = new PDBEntry("3A6S", null, null, null);
1267  1 seq.addPDBId(pdbe1);
1268  1 seq.addDBRef(new DBRefEntry("Ensembl", "8", "ENST1234"));
1269  1 seq.addDBRef(new DBRefEntry("PDB", "0", "1A70"));
1270  1 seq.addDBRef(new DBRefEntry("PDB", "0", "4BQGa"));
1271  1 seq.addDBRef(new DBRefEntry("PDB", "0", "3a6sB"));
1272    // 7 is not a valid chain code:
1273  1 seq.addDBRef(new DBRefEntry("PDB", "0", "2GIS7"));
1274   
1275  1 seq.updatePDBIds();
1276  1 List<PDBEntry> pdbIds = seq.getAllPDBEntries();
1277  1 assertEquals(4, pdbIds.size());
1278  1 assertSame(pdbe1, pdbIds.get(0));
1279    // chain code got added to 3A6S:
1280  1 assertEquals("B", pdbe1.getChainCode());
1281  1 assertEquals("1A70", pdbIds.get(1).getId());
1282    // 4BQGA is parsed into id + chain
1283  1 assertEquals("4BQG", pdbIds.get(2).getId());
1284  1 assertEquals("a", pdbIds.get(2).getChainCode());
1285  1 assertEquals("2GIS7", pdbIds.get(3).getId());
1286  1 assertNull(pdbIds.get(3).getChainCode());
1287    }
1288   
1289    /**
1290    * Test the method that either adds a pdbid or updates an existing one
1291    */
 
1292  1 toggle @Test(groups = { "Functional" })
1293    public void testAddPDBId()
1294    {
1295  1 PDBEntry pdbe = new PDBEntry("3A6S", null, null, null);
1296  1 seq.addPDBId(pdbe);
1297  1 assertEquals(1, seq.getAllPDBEntries().size());
1298  1 assertSame(pdbe, seq.getPDBEntry("3A6S"));
1299  1 assertSame(pdbe, seq.getPDBEntry("3a6s")); // case-insensitive
1300   
1301    // add the same entry
1302  1 seq.addPDBId(pdbe);
1303  1 assertEquals(1, seq.getAllPDBEntries().size());
1304  1 assertSame(pdbe, seq.getPDBEntry("3A6S"));
1305   
1306    // add an identical entry
1307  1 seq.addPDBId(new PDBEntry("3A6S", null, null, null));
1308  1 assertEquals(1, seq.getAllPDBEntries().size());
1309  1 assertSame(pdbe, seq.getPDBEntry("3A6S"));
1310   
1311    // add a different entry
1312  1 PDBEntry pdbe2 = new PDBEntry("1A70", null, null, null);
1313  1 seq.addPDBId(pdbe2);
1314  1 assertEquals(2, seq.getAllPDBEntries().size());
1315  1 assertSame(pdbe, seq.getAllPDBEntries().get(0));
1316  1 assertSame(pdbe2, seq.getAllPDBEntries().get(1));
1317   
1318    // update pdbe with chain code, file, type
1319  1 PDBEntry pdbe3 = new PDBEntry("3a6s", "A", Type.PDB, "filepath");
1320  1 seq.addPDBId(pdbe3);
1321  1 assertEquals(2, seq.getAllPDBEntries().size());
1322  1 assertSame(pdbe, seq.getAllPDBEntries().get(0)); // updated in situ
1323  1 assertEquals("3A6S", pdbe.getId()); // unchanged
1324  1 assertEquals("A", pdbe.getChainCode()); // updated
1325  1 assertEquals(Type.PDB.toString(), pdbe.getType()); // updated
1326  1 assertEquals("filepath", pdbe.getFile()); // updated
1327  1 assertSame(pdbe2, seq.getAllPDBEntries().get(1));
1328   
1329    // add with a different file path
1330  1 PDBEntry pdbe4 = new PDBEntry("3a6s", "A", Type.PDB, "filepath2");
1331  1 seq.addPDBId(pdbe4);
1332  1 assertEquals(3, seq.getAllPDBEntries().size());
1333  1 assertSame(pdbe4, seq.getAllPDBEntries().get(2));
1334   
1335    // add with a different chain code
1336  1 PDBEntry pdbe5 = new PDBEntry("3a6s", "B", Type.PDB, "filepath");
1337  1 seq.addPDBId(pdbe5);
1338  1 assertEquals(4, seq.getAllPDBEntries().size());
1339  1 assertSame(pdbe5, seq.getAllPDBEntries().get(3));
1340    }
1341   
 
1342  1 toggle @Test(
1343    groups = { "Functional" },
1344    expectedExceptions = { IllegalArgumentException.class })
1345    public void testSetDatasetSequence_toSelf()
1346    {
1347  1 seq.setDatasetSequence(seq);
1348    }
1349   
 
1350  1 toggle @Test(
1351    groups = { "Functional" },
1352    expectedExceptions = { IllegalArgumentException.class })
1353    public void testSetDatasetSequence_cascading()
1354    {
1355  1 SequenceI seq2 = new Sequence("Seq2", "xyz");
1356  1 seq2.createDatasetSequence();
1357  1 seq.setDatasetSequence(seq2);
1358    }
1359   
 
1360  1 toggle @Test(groups = { "Functional" })
1361    public void testFindFeatures()
1362    {
1363  1 SequenceI sq = new Sequence("test/8-16", "-ABC--DEF--GHI--");
1364  1 sq.createDatasetSequence();
1365   
1366  1 assertTrue(sq.findFeatures(1, 99).isEmpty());
1367   
1368    // add non-positional feature
1369  1 SequenceFeature sf0 = new SequenceFeature("Cath", "desc", 0, 0, 2f,
1370    null);
1371  1 sq.addSequenceFeature(sf0);
1372    // add feature on BCD
1373  1 SequenceFeature sfBCD = new SequenceFeature("Cath", "desc", 9, 11, 2f,
1374    null);
1375  1 sq.addSequenceFeature(sfBCD);
1376    // add feature on DE
1377  1 SequenceFeature sfDE = new SequenceFeature("Cath", "desc", 11, 12, 2f,
1378    null);
1379  1 sq.addSequenceFeature(sfDE);
1380    // add contact feature at [B, H]
1381  1 SequenceFeature sfContactBH = new SequenceFeature("Disulphide bond",
1382    "desc", 9, 15, 2f, null);
1383  1 sq.addSequenceFeature(sfContactBH);
1384    // add contact feature at [F, G]
1385  1 SequenceFeature sfContactFG = new SequenceFeature("Disulfide Bond",
1386    "desc", 13, 14, 2f, null);
1387  1 sq.addSequenceFeature(sfContactFG);
1388    // add single position feature at [I]
1389  1 SequenceFeature sfI = new SequenceFeature("Disulfide Bond",
1390    "desc", 16, 16, null);
1391  1 sq.addSequenceFeature(sfI);
1392   
1393    // no features in columns 1-2 (-A)
1394  1 List<SequenceFeature> found = sq.findFeatures(1, 2);
1395  1 assertTrue(found.isEmpty());
1396   
1397    // columns 1-6 (-ABC--) includes BCD and B/H feature but not DE
1398  1 found = sq.findFeatures(1, 6);
1399  1 assertEquals(2, found.size());
1400  1 assertTrue(found.contains(sfBCD));
1401  1 assertTrue(found.contains(sfContactBH));
1402   
1403    // columns 5-6 (--) includes (enclosing) BCD but not (contact) B/H feature
1404  1 found = sq.findFeatures(5, 6);
1405  1 assertEquals(1, found.size());
1406  1 assertTrue(found.contains(sfBCD));
1407   
1408    // columns 7-10 (DEF-) includes BCD, DE, F/G but not B/H feature
1409  1 found = sq.findFeatures(7, 10);
1410  1 assertEquals(3, found.size());
1411  1 assertTrue(found.contains(sfBCD));
1412  1 assertTrue(found.contains(sfDE));
1413  1 assertTrue(found.contains(sfContactFG));
1414   
1415    // columns 10-11 (--) should find nothing
1416  1 found = sq.findFeatures(10, 11);
1417  1 assertEquals(0, found.size());
1418   
1419    // columns 14-14 (I) should find variant feature
1420  1 found = sq.findFeatures(14, 14);
1421  1 assertEquals(1, found.size());
1422  1 assertTrue(found.contains(sfI));
1423    }
1424   
 
1425  1 toggle @Test(groups = { "Functional" })
1426    public void testFindIndex_withCursor()
1427    {
1428  1 Sequence sq = new Sequence("test/8-13", "-A--BCD-EF--");
1429   
1430    // find F given A, check cursor is now at the found position
1431  1 assertEquals(10, sq.findIndex(13, new SequenceCursor(sq, 8, 2, 0)));
1432  1 SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1433  1 assertEquals(13, cursor.residuePosition);
1434  1 assertEquals(10, cursor.columnPosition);
1435   
1436    // find A given F
1437  1 assertEquals(2, sq.findIndex(8, new SequenceCursor(sq, 13, 10, 0)));
1438  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1439  1 assertEquals(8, cursor.residuePosition);
1440  1 assertEquals(2, cursor.columnPosition);
1441   
1442    // find C given C (no cursor update is done for this case)
1443  1 assertEquals(6, sq.findIndex(10, new SequenceCursor(sq, 10, 6, 0)));
1444  1 SequenceCursor cursor2 = (SequenceCursor) PA.getValue(sq, "cursor");
1445  1 assertSame(cursor2, cursor);
1446   
1447    /*
1448    * sequence 'end' beyond end of sequence returns length of sequence
1449    * (for compatibility with pre-cursor code)
1450    * - also verify the cursor is left in a valid state
1451    */
1452  1 sq = new Sequence("test/8-99", "-A--B-C-D-E-F--"); // trailing gap case
1453  1 assertEquals(7, sq.findIndex(10)); // establishes a cursor
1454  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1455  1 assertEquals(10, cursor.residuePosition);
1456  1 assertEquals(7, cursor.columnPosition);
1457  1 assertEquals(sq.getLength(), sq.findIndex(65));
1458  1 cursor2 = (SequenceCursor) PA.getValue(sq, "cursor");
1459  1 assertSame(cursor, cursor2); // not updated for this case!
1460   
1461  1 sq = new Sequence("test/8-99", "-A--B-C-D-E-F"); // trailing residue case
1462  1 sq.findIndex(10); // establishes a cursor
1463  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1464  1 assertEquals(sq.getLength(), sq.findIndex(65));
1465  1 cursor2 = (SequenceCursor) PA.getValue(sq, "cursor");
1466  1 assertSame(cursor, cursor2); // not updated for this case!
1467   
1468    /*
1469    * residue after sequence 'start' but before first residue should return
1470    * zero (for compatibility with pre-cursor code)
1471    */
1472  1 sq = new Sequence("test/8-15", "-A-B-C-"); // leading gap case
1473  1 sq.findIndex(10); // establishes a cursor
1474  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1475  1 assertEquals(0, sq.findIndex(3));
1476  1 cursor2 = (SequenceCursor) PA.getValue(sq, "cursor");
1477  1 assertSame(cursor, cursor2); // not updated for this case!
1478   
1479  1 sq = new Sequence("test/8-15", "A-B-C-"); // leading residue case
1480  1 sq.findIndex(10); // establishes a cursor
1481  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1482  1 assertEquals(0, sq.findIndex(2));
1483  1 cursor2 = (SequenceCursor) PA.getValue(sq, "cursor");
1484  1 assertSame(cursor, cursor2); // not updated for this case!
1485    }
1486   
 
1487  1 toggle @Test(groups = { "Functional" })
1488    public void testFindPosition_withCursor()
1489    {
1490  1 Sequence sq = new Sequence("test/8-13", "-A--BCD-EF--");
1491   
1492    // find F pos given A - lastCol gets set in cursor
1493  1 assertEquals(13, sq.findPosition(10, new SequenceCursor(sq, 8, 2, 0)));
1494  1 assertEquals("test:Pos13:Col10:startCol0:endCol10:tok0",
1495    PA.getValue(sq, "cursor").toString());
1496   
1497    // find A pos given F - first residue column is saved in cursor
1498  1 assertEquals(8, sq.findPosition(2, new SequenceCursor(sq, 13, 10, 0)));
1499  1 assertEquals("test:Pos8:Col2:startCol2:endCol10:tok0",
1500    PA.getValue(sq, "cursor").toString());
1501   
1502    // find C pos given C (neither startCol nor endCol is set)
1503  1 assertEquals(10, sq.findPosition(6, new SequenceCursor(sq, 10, 6, 0)));
1504  1 assertEquals("test:Pos10:Col6:startCol0:endCol0:tok0",
1505    PA.getValue(sq, "cursor").toString());
1506   
1507    // now the grey area - what residue position for a gapped column? JAL-2562
1508   
1509    // find 'residue' for column 3 given cursor for D (so working left)
1510    // returns B9; cursor is updated to [B 5]
1511  1 assertEquals(9, sq.findPosition(3, new SequenceCursor(sq, 11, 7, 0)));
1512  1 assertEquals("test:Pos9:Col5:startCol0:endCol0:tok0",
1513    PA.getValue(sq, "cursor").toString());
1514   
1515    // find 'residue' for column 8 given cursor for D (so working right)
1516    // returns E12; cursor is updated to [D 7]
1517  1 assertEquals(12, sq.findPosition(8, new SequenceCursor(sq, 11, 7, 0)));
1518  1 assertEquals("test:Pos11:Col7:startCol0:endCol0:tok0",
1519    PA.getValue(sq, "cursor").toString());
1520   
1521    // find 'residue' for column 12 given cursor for B
1522    // returns 1 more than last residue position; cursor is updated to [F 10]
1523    // lastCol position is saved in cursor
1524  1 assertEquals(14, sq.findPosition(12, new SequenceCursor(sq, 9, 5, 0)));
1525  1 assertEquals("test:Pos13:Col10:startCol0:endCol10:tok0",
1526    PA.getValue(sq, "cursor").toString());
1527   
1528    /*
1529    * findPosition for column beyond length of sequence
1530    * returns 1 more than the last residue position
1531    * cursor is set to last real residue position [F 10]
1532    */
1533  1 assertEquals(14, sq.findPosition(99, new SequenceCursor(sq, 8, 2, 0)));
1534  1 assertEquals("test:Pos13:Col10:startCol0:endCol10:tok0",
1535    PA.getValue(sq, "cursor").toString());
1536   
1537    /*
1538    * and the case without a trailing gap
1539    */
1540  1 sq = new Sequence("test/8-13", "-A--BCD-EF");
1541    // first find C from A
1542  1 assertEquals(10, sq.findPosition(6, new SequenceCursor(sq, 8, 2, 0)));
1543  1 SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1544  1 assertEquals("test:Pos10:Col6:startCol0:endCol0:tok0",
1545    cursor.toString());
1546    // now 'find' 99 from C
1547    // cursor is set to [F 10] and saved lastCol
1548  1 assertEquals(14, sq.findPosition(99, cursor));
1549  1 assertEquals("test:Pos13:Col10:startCol0:endCol10:tok0",
1550    PA.getValue(sq, "cursor").toString());
1551    }
1552   
 
1553  0 toggle @Test
1554    public void testIsValidCursor()
1555    {
1556  0 Sequence sq = new Sequence("Seq", "ABC--DE-F", 8, 13);
1557  0 assertFalse(sq.isValidCursor(null));
1558   
1559    /*
1560    * cursor is valid if it has valid sequence ref and changeCount token
1561    * and positions within the range of the sequence
1562    */
1563  0 int changeCount = (int) PA.getValue(sq, "changeCount");
1564  0 SequenceCursor cursor = new SequenceCursor(sq, 13, 1, changeCount);
1565  0 assertTrue(sq.isValidCursor(cursor));
1566   
1567    /*
1568    * column position outside [0 - length] is rejected
1569    */
1570  0 cursor = new SequenceCursor(sq, 13, -1, changeCount);
1571  0 assertFalse(sq.isValidCursor(cursor));
1572  0 cursor = new SequenceCursor(sq, 13, 10, changeCount);
1573  0 assertFalse(sq.isValidCursor(cursor));
1574  0 cursor = new SequenceCursor(sq, 7, 8, changeCount);
1575  0 assertFalse(sq.isValidCursor(cursor));
1576  0 cursor = new SequenceCursor(sq, 14, 2, changeCount);
1577  0 assertFalse(sq.isValidCursor(cursor));
1578   
1579    /*
1580    * wrong sequence is rejected
1581    */
1582  0 cursor = new SequenceCursor(null, 13, 1, changeCount);
1583  0 assertFalse(sq.isValidCursor(cursor));
1584  0 cursor = new SequenceCursor(new Sequence("Seq", "abc"), 13, 1,
1585    changeCount);
1586  0 assertFalse(sq.isValidCursor(cursor));
1587   
1588    /*
1589    * wrong token value is rejected
1590    */
1591  0 cursor = new SequenceCursor(sq, 13, 1, changeCount + 1);
1592  0 assertFalse(sq.isValidCursor(cursor));
1593  0 cursor = new SequenceCursor(sq, 13, 1, changeCount - 1);
1594  0 assertFalse(sq.isValidCursor(cursor));
1595    }
1596   
 
1597  1 toggle @Test(groups = { "Functional" })
1598    public void testFindPosition_withCursorAndEdits()
1599    {
1600  1 Sequence sq = new Sequence("test/8-13", "-A--BCD-EF--");
1601   
1602    // find F pos given A
1603  1 assertEquals(13, sq.findPosition(10, new SequenceCursor(sq, 8, 2, 0)));
1604  1 int token = (int) PA.getValue(sq, "changeCount"); // 0
1605  1 SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1606  1 assertEquals(new SequenceCursor(sq, 13, 10, token), cursor);
1607   
1608    /*
1609    * setSequence should invalidate the cursor cached by the sequence
1610    */
1611  1 sq.setSequence("-A-BCD-EF---"); // one gap removed
1612  1 assertEquals(8, sq.getStart()); // sanity check
1613  1 assertEquals(11, sq.findPosition(5)); // D11
1614    // cursor should now be at [D 6]
1615  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1616  1 assertEquals(new SequenceCursor(sq, 11, 6, ++token), cursor);
1617   
1618    /*
1619    * deleteChars should invalidate the cached cursor
1620    */
1621  1 sq.deleteChars(2, 5); // delete -BC
1622  1 assertEquals("-AD-EF---", sq.getSequenceAsString());
1623  1 assertEquals(8, sq.getStart()); // sanity check
1624  1 assertEquals(10, sq.findPosition(4)); // E10
1625    // cursor should now be at [E 5]
1626  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1627  1 assertEquals(new SequenceCursor(sq, 10, 5, ++token), cursor);
1628   
1629    /*
1630    * Edit to insert gaps should invalidate the cached cursor
1631    * insert 2 gaps at column[3] to make -AD---EF---
1632    */
1633  1 SequenceI[] seqs = new SequenceI[] { sq };
1634  1 AlignmentI al = new Alignment(seqs);
1635  1 new EditCommand().appendEdit(Action.INSERT_GAP, seqs, 3, 2, al, true);
1636  1 assertEquals("-AD---EF---", sq.getSequenceAsString());
1637  1 assertEquals(10, sq.findPosition(4)); // E10
1638    // cursor should now be at [D 3]
1639  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1640  1 assertEquals(new SequenceCursor(sq, 9, 3, ++token), cursor);
1641   
1642    /*
1643    * insertCharAt should invalidate the cached cursor
1644    * insert CC at column[4] to make -AD-CC--EF---
1645    */
1646  1 sq.insertCharAt(4, 2, 'C');
1647  1 assertEquals("-AD-CC--EF---", sq.getSequenceAsString());
1648  1 assertEquals(13, sq.findPosition(9)); // F13
1649    // cursor should now be at [F 10]
1650  1 cursor = (SequenceCursor) PA.getValue(sq, "cursor");
1651  1 assertEquals(new SequenceCursor(sq, 13, 10, ++token), cursor);
1652    }
1653   
 
1654  1 toggle @Test(groups = { "Functional" })
1655    public void testGetSequence()
1656    {
1657  1 String seqstring = "-A--BCD-EF--";
1658  1 Sequence sq = new Sequence("test/8-13", seqstring);
1659  1 sq.createDatasetSequence();
1660  1 assertTrue(Arrays.equals(sq.getSequence(), seqstring.toCharArray()));
1661  1 assertTrue(Arrays.equals(sq.getDatasetSequence().getSequence(),
1662    "ABCDEF".toCharArray()));
1663   
1664    // verify a copy of the sequence array is returned
1665  1 char[] theSeq = (char[]) PA.getValue(sq, "sequence");
1666  1 assertNotSame(theSeq, sq.getSequence());
1667  1 theSeq = (char[]) PA.getValue(sq.getDatasetSequence(), "sequence");
1668  1 assertNotSame(theSeq, sq.getDatasetSequence().getSequence());
1669    }
1670   
 
1671  1 toggle @Test(groups = { "Functional" })
1672    public void testReplace()
1673    {
1674  1 String seqstring = "-A--BCD-EF--";
1675  1 SequenceI sq = new Sequence("test/8-13", seqstring);
1676  1 assertEquals(0, PA.getValue(sq, "changeCount"));
1677   
1678  1 assertEquals(0, sq.replace('A', 'A')); // same char
1679  1 assertEquals(seqstring, sq.getSequenceAsString());
1680  1 assertEquals(0, PA.getValue(sq, "changeCount"));
1681   
1682  1 assertEquals(0, sq.replace('X', 'Y')); // not there
1683  1 assertEquals(seqstring, sq.getSequenceAsString());
1684  1 assertEquals(0, PA.getValue(sq, "changeCount"));
1685   
1686  1 assertEquals(1, sq.replace('A', 'K'));
1687  1 assertEquals("-K--BCD-EF--", sq.getSequenceAsString());
1688  1 assertEquals(1, PA.getValue(sq, "changeCount"));
1689   
1690  1 assertEquals(6, sq.replace('-', '.'));
1691  1 assertEquals(".K..BCD.EF..", sq.getSequenceAsString());
1692  1 assertEquals(2, PA.getValue(sq, "changeCount"));
1693    }
1694   
 
1695  1 toggle @Test(groups = { "Functional" })
1696    public void testFindPositions()
1697    {
1698  1 SequenceI sq = new Sequence("test/8-13", "-ABC---DE-F--");
1699   
1700    /*
1701    * invalid inputs
1702    */
1703  1 assertNull(sq.findPositions(6, 5));
1704  1 assertNull(sq.findPositions(0, 5));
1705  1 assertNull(sq.findPositions(-1, 5));
1706   
1707    /*
1708    * all gapped ranges
1709    */
1710  1 assertNull(sq.findPositions(1, 1)); // 1-based columns
1711  1 assertNull(sq.findPositions(5, 5));
1712  1 assertNull(sq.findPositions(5, 6));
1713  1 assertNull(sq.findPositions(5, 7));
1714   
1715    /*
1716    * all ungapped ranges
1717    */
1718  1 assertEquals(new Range(8, 8), sq.findPositions(2, 2)); // A
1719  1 assertEquals(new Range(8, 9), sq.findPositions(2, 3)); // AB
1720  1 assertEquals(new Range(8, 10), sq.findPositions(2, 4)); // ABC
1721  1 assertEquals(new Range(9, 10), sq.findPositions(3, 4)); // BC
1722   
1723    /*
1724    * gap to ungapped range
1725    */
1726  1 assertEquals(new Range(8, 10), sq.findPositions(1, 4)); // ABC
1727  1 assertEquals(new Range(11, 12), sq.findPositions(6, 9)); // DE
1728   
1729    /*
1730    * ungapped to gapped range
1731    */
1732  1 assertEquals(new Range(10, 10), sq.findPositions(4, 5)); // C
1733  1 assertEquals(new Range(9, 13), sq.findPositions(3, 11)); // BCDEF
1734   
1735    /*
1736    * ungapped to ungapped enclosing gaps
1737    */
1738  1 assertEquals(new Range(10, 11), sq.findPositions(4, 8)); // CD
1739  1 assertEquals(new Range(8, 13), sq.findPositions(2, 11)); // ABCDEF
1740   
1741    /*
1742    * gapped to gapped enclosing ungapped
1743    */
1744  1 assertEquals(new Range(8, 10), sq.findPositions(1, 5)); // ABC
1745  1 assertEquals(new Range(11, 12), sq.findPositions(5, 10)); // DE
1746  1 assertEquals(new Range(8, 13), sq.findPositions(1, 13)); // the lot
1747  1 assertEquals(new Range(8, 13), sq.findPositions(1, 99));
1748    }
1749   
 
1750  1 toggle @Test(groups = { "Functional" })
1751    public void testGapBitset()
1752    {
1753  1 SequenceI sq = new Sequence("test/8-13", "-ABC---DE-F--");
1754  1 BitSet bs = sq.gapBitset();
1755  1 BitSet expected = new BitSet();
1756  1 expected.set(0);
1757  1 expected.set(4, 7);
1758  1 expected.set(9);
1759  1 expected.set(11, 13);
1760   
1761  1 assertTrue(bs.equals(expected));
1762   
1763    }
1764   
 
1765  0 toggle public void testFindFeatures_largeEndPos()
1766    {
1767    /*
1768    * imitate a PDB sequence where end is larger than end position
1769    */
1770  0 SequenceI sq = new Sequence("test", "-ABC--DEF--", 1, 20);
1771  0 sq.createDatasetSequence();
1772   
1773  0 assertTrue(sq.findFeatures(1, 9).isEmpty());
1774    // should be no array bounds exception - JAL-2772
1775  0 assertTrue(sq.findFeatures(1, 15).isEmpty());
1776   
1777    // add feature on BCD
1778  0 SequenceFeature sfBCD = new SequenceFeature("Cath", "desc", 2, 4, 2f,
1779    null);
1780  0 sq.addSequenceFeature(sfBCD);
1781   
1782    // no features in columns 1-2 (-A)
1783  0 List<SequenceFeature> found = sq.findFeatures(1, 2);
1784  0 assertTrue(found.isEmpty());
1785   
1786    // columns 1-6 (-ABC--) includes BCD
1787  0 found = sq.findFeatures(1, 6);
1788  0 assertEquals(1, found.size());
1789  0 assertTrue(found.contains(sfBCD));
1790   
1791    // columns 10-11 (--) should find nothing
1792  0 found = sq.findFeatures(10, 11);
1793  0 assertEquals(0, found.size());
1794    }
1795   
 
1796  1 toggle @Test(groups = { "Functional" })
1797    public void testSetName()
1798    {
1799  1 SequenceI sq = new Sequence("test", "-ABC---DE-F--");
1800  1 assertEquals("test", sq.getName());
1801  1 assertEquals(1, sq.getStart());
1802  1 assertEquals(6, sq.getEnd());
1803   
1804  1 sq.setName("testing");
1805  1 assertEquals("testing", sq.getName());
1806   
1807  1 sq.setName("test/8-10");
1808  1 assertEquals("test", sq.getName());
1809  1 assertEquals(8, sq.getStart());
1810  1 assertEquals(13, sq.getEnd()); // note end is recomputed
1811   
1812  1 sq.setName("testing/7-99");
1813  1 assertEquals("testing", sq.getName());
1814  1 assertEquals(7, sq.getStart());
1815  1 assertEquals(99, sq.getEnd()); // end may be beyond physical end
1816   
1817  1 sq.setName("/2-3");
1818  1 assertEquals("", sq.getName());
1819  1 assertEquals(2, sq.getStart());
1820  1 assertEquals(7, sq.getEnd());
1821   
1822  1 sq.setName("test/"); // invalid
1823  1 assertEquals("test/", sq.getName());
1824  1 assertEquals(2, sq.getStart());
1825  1 assertEquals(7, sq.getEnd());
1826   
1827  1 sq.setName("test/6-13/7-99");
1828  1 assertEquals("test/6-13", sq.getName());
1829  1 assertEquals(7, sq.getStart());
1830  1 assertEquals(99, sq.getEnd());
1831   
1832  1 sq.setName("test/0-5"); // 0 is invalid - ignored
1833  1 assertEquals("test/0-5", sq.getName());
1834  1 assertEquals(7, sq.getStart());
1835  1 assertEquals(99, sq.getEnd());
1836   
1837  1 sq.setName("test/a-5"); // a is invalid - ignored
1838  1 assertEquals("test/a-5", sq.getName());
1839  1 assertEquals(7, sq.getStart());
1840  1 assertEquals(99, sq.getEnd());
1841   
1842  1 sq.setName("test/6-5"); // start > end is invalid - ignored
1843  1 assertEquals("test/6-5", sq.getName());
1844  1 assertEquals(7, sq.getStart());
1845  1 assertEquals(99, sq.getEnd());
1846   
1847  1 sq.setName("test/5"); // invalid - ignored
1848  1 assertEquals("test/5", sq.getName());
1849  1 assertEquals(7, sq.getStart());
1850  1 assertEquals(99, sq.getEnd());
1851   
1852  1 sq.setName("test/-5"); // invalid - ignored
1853  1 assertEquals("test/-5", sq.getName());
1854  1 assertEquals(7, sq.getStart());
1855  1 assertEquals(99, sq.getEnd());
1856   
1857  1 sq.setName("test/5-"); // invalid - ignored
1858  1 assertEquals("test/5-", sq.getName());
1859  1 assertEquals(7, sq.getStart());
1860  1 assertEquals(99, sq.getEnd());
1861   
1862  1 sq.setName("test/5-6-7"); // invalid - ignored
1863  1 assertEquals("test/5-6-7", sq.getName());
1864  1 assertEquals(7, sq.getStart());
1865  1 assertEquals(99, sq.getEnd());
1866   
1867  1 sq.setName(null); // invalid, gets converted to space
1868  1 assertEquals("", sq.getName());
1869  1 assertEquals(7, sq.getStart());
1870  1 assertEquals(99, sq.getEnd());
1871    }
1872   
 
1873  1 toggle @Test(groups = { "Functional" })
1874    public void testCheckValidRange()
1875    {
1876  1 Sequence sq = new Sequence("test/7-12", "-ABC---DE-F--");
1877  1 assertEquals(7, sq.getStart());
1878  1 assertEquals(12, sq.getEnd());
1879   
1880    /*
1881    * checkValidRange ensures end is at least the last residue position
1882    */
1883  1 PA.setValue(sq, "end", 2);
1884  1 sq.checkValidRange();
1885  1 assertEquals(12, sq.getEnd());
1886   
1887    /*
1888    * end may be beyond the last residue position
1889    */
1890  1 PA.setValue(sq, "end", 22);
1891  1 sq.checkValidRange();
1892  1 assertEquals(22, sq.getEnd());
1893    }
1894   
 
1895  1 toggle @Test(groups = { "Functional" })
1896    public void testDeleteChars_withGaps()
1897    {
1898    /*
1899    * delete gaps only
1900    */
1901  1 SequenceI sq = new Sequence("test/8-10", "A-B-C");
1902  1 sq.createDatasetSequence();
1903  1 assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
1904  1 sq.deleteChars(1, 2); // delete first gap
1905  1 assertEquals("AB-C", sq.getSequenceAsString());
1906  1 assertEquals(8, sq.getStart());
1907  1 assertEquals(10, sq.getEnd());
1908  1 assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
1909   
1910    /*
1911    * delete gaps and residues at start (no new dataset sequence)
1912    */
1913  1 sq = new Sequence("test/8-10", "A-B-C");
1914  1 sq.createDatasetSequence();
1915  1 sq.deleteChars(0, 3); // delete A-B
1916  1 assertEquals("-C", sq.getSequenceAsString());
1917  1 assertEquals(10, sq.getStart());
1918  1 assertEquals(10, sq.getEnd());
1919  1 assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
1920   
1921    /*
1922    * delete gaps and residues at end (no new dataset sequence)
1923    */
1924  1 sq = new Sequence("test/8-10", "A-B-C");
1925  1 sq.createDatasetSequence();
1926  1 sq.deleteChars(2, 5); // delete B-C
1927  1 assertEquals("A-", sq.getSequenceAsString());
1928  1 assertEquals(8, sq.getStart());
1929  1 assertEquals(8, sq.getEnd());
1930  1 assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString());
1931   
1932    /*
1933    * delete gaps and residues internally (new dataset sequence)
1934    * first delete from gap to residue
1935    */
1936  1 sq = new Sequence("test/8-10", "A-B-C");
1937  1 sq.createDatasetSequence();
1938  1 sq.deleteChars(1, 3); // delete -B
1939  1 assertEquals("A-C", sq.getSequenceAsString());
1940  1 assertEquals(8, sq.getStart());
1941  1 assertEquals(9, sq.getEnd());
1942  1 assertEquals("AC", sq.getDatasetSequence().getSequenceAsString());
1943  1 assertEquals(8, sq.getDatasetSequence().getStart());
1944  1 assertEquals(9, sq.getDatasetSequence().getEnd());
1945   
1946    /*
1947    * internal delete from gap to gap
1948    */
1949  1 sq = new Sequence("test/8-10", "A-B-C");
1950  1 sq.createDatasetSequence();
1951  1 sq.deleteChars(1, 4); // delete -B-
1952  1 assertEquals("AC", sq.getSequenceAsString());
1953  1 assertEquals(8, sq.getStart());
1954  1 assertEquals(9, sq.getEnd());
1955  1 assertEquals("AC", sq.getDatasetSequence().getSequenceAsString());
1956  1 assertEquals(8, sq.getDatasetSequence().getStart());
1957  1 assertEquals(9, sq.getDatasetSequence().getEnd());
1958   
1959    /*
1960    * internal delete from residue to residue
1961    */
1962  1 sq = new Sequence("test/8-10", "A-B-C");
1963  1 sq.createDatasetSequence();
1964  1 sq.deleteChars(2, 3); // delete B
1965  1 assertEquals("A--C", sq.getSequenceAsString());
1966  1 assertEquals(8, sq.getStart());
1967  1 assertEquals(9, sq.getEnd());
1968  1 assertEquals("AC", sq.getDatasetSequence().getSequenceAsString());
1969  1 assertEquals(8, sq.getDatasetSequence().getStart());
1970  1 assertEquals(9, sq.getDatasetSequence().getEnd());
1971    }
1972   
1973    /**
1974    * Test the code used to locate the reference sequence ruler origin
1975    */
 
1976  1 toggle @Test(groups = { "Functional" })
1977    public void testLocateVisibleStartofSequence()
1978    {
1979    // create random alignment
1980  1 AlignmentGenerator gen = new AlignmentGenerator(false);
1981  1 AlignmentI al = gen.generate(50, 20, 123, 5, 5);
1982   
1983  1 HiddenColumns cs = al.getHiddenColumns();
1984  1 ColumnSelection colsel = new ColumnSelection();
1985   
1986  1 SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
1987  1 assertEquals(2, seq.findIndex(seq.getStart()));
1988   
1989    // no hidden columns
1990  1 assertEquals(seq.findIndex(seq.getStart()) - 1,
1991    seq.firstResidueOutsideIterator(cs.iterator()));
1992   
1993    // hidden column on gap after end of sequence - should not affect bounds
1994  1 colsel.hideSelectedColumns(13, al.getHiddenColumns());
1995  1 assertEquals(seq.findIndex(seq.getStart()) - 1,
1996    seq.firstResidueOutsideIterator(cs.iterator()));
1997   
1998  1 cs.revealAllHiddenColumns(colsel);
1999    // hidden column on gap before beginning of sequence - should vis bounds by
2000    // one
2001  1 colsel.hideSelectedColumns(0, al.getHiddenColumns());
2002  1 assertEquals(seq.findIndex(seq.getStart()) - 2,
2003    cs.absoluteToVisibleColumn(
2004    seq.firstResidueOutsideIterator(cs.iterator())));
2005   
2006  1 cs.revealAllHiddenColumns(colsel);
2007    // hide columns around most of sequence - leave one residue remaining
2008  1 cs.hideColumns(1, 3);
2009  1 cs.hideColumns(6, 11);
2010   
2011  1 Iterator<int[]> it = cs.getVisContigsIterator(0, 6, false);
2012   
2013  1 assertEquals("-D", seq.getSequenceStringFromIterator(it));
2014    // cs.getVisibleSequenceStrings(0, 5, new SequenceI[]
2015    // { seq })[0]);
2016   
2017  1 assertEquals(4, seq.firstResidueOutsideIterator(cs.iterator()));
2018  1 cs.revealAllHiddenColumns(colsel);
2019   
2020    // hide whole sequence - should just get location of hidden region
2021    // containing sequence
2022  1 cs.hideColumns(1, 11);
2023  1 assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator()));
2024   
2025  1 cs.revealAllHiddenColumns(colsel);
2026  1 cs.hideColumns(0, 15);
2027  1 assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator()));
2028   
2029  1 SequenceI seq2 = new Sequence("RefSeq2", "-------A-SD-ASD--E---");
2030   
2031  1 cs.revealAllHiddenColumns(colsel);
2032  1 cs.hideColumns(7, 17);
2033  1 assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator()));
2034   
2035  1 cs.revealAllHiddenColumns(colsel);
2036  1 cs.hideColumns(3, 17);
2037  1 assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator()));
2038   
2039  1 cs.revealAllHiddenColumns(colsel);
2040  1 cs.hideColumns(3, 19);
2041  1 assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator()));
2042   
2043  1 cs.revealAllHiddenColumns(colsel);
2044  1 cs.hideColumns(0, 0);
2045  1 assertEquals(1, seq.firstResidueOutsideIterator(cs.iterator()));
2046   
2047  1 cs.revealAllHiddenColumns(colsel);
2048  1 cs.hideColumns(0, 1);
2049  1 assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator()));
2050   
2051  1 cs.revealAllHiddenColumns(colsel);
2052  1 cs.hideColumns(0, 2);
2053  1 assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator()));
2054   
2055  1 cs.revealAllHiddenColumns(colsel);
2056  1 cs.hideColumns(1, 1);
2057  1 assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator()));
2058   
2059  1 cs.revealAllHiddenColumns(colsel);
2060  1 cs.hideColumns(1, 2);
2061  1 assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator()));
2062   
2063  1 cs.revealAllHiddenColumns(colsel);
2064  1 cs.hideColumns(1, 3);
2065  1 assertEquals(4, seq.firstResidueOutsideIterator(cs.iterator()));
2066   
2067  1 cs.revealAllHiddenColumns(colsel);
2068  1 cs.hideColumns(0, 2);
2069  1 cs.hideColumns(5, 6);
2070  1 assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator()));
2071   
2072  1 cs.revealAllHiddenColumns(colsel);
2073  1 cs.hideColumns(0, 2);
2074  1 cs.hideColumns(5, 6);
2075  1 cs.hideColumns(9, 10);
2076  1 assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator()));
2077   
2078  1 cs.revealAllHiddenColumns(colsel);
2079  1 cs.hideColumns(0, 2);
2080  1 cs.hideColumns(7, 11);
2081  1 assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator()));
2082   
2083  1 cs.revealAllHiddenColumns(colsel);
2084  1 cs.hideColumns(2, 4);
2085  1 cs.hideColumns(7, 11);
2086  1 assertEquals(1, seq.firstResidueOutsideIterator(cs.iterator()));
2087   
2088  1 cs.revealAllHiddenColumns(colsel);
2089  1 cs.hideColumns(2, 4);
2090  1 cs.hideColumns(7, 12);
2091  1 assertEquals(1, seq.firstResidueOutsideIterator(cs.iterator()));
2092   
2093  1 cs.revealAllHiddenColumns(colsel);
2094  1 cs.hideColumns(1, 11);
2095  1 assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator()));
2096   
2097  1 cs.revealAllHiddenColumns(colsel);
2098  1 cs.hideColumns(0, 12);
2099  1 assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator()));
2100   
2101  1 cs.revealAllHiddenColumns(colsel);
2102  1 cs.hideColumns(0, 4);
2103  1 cs.hideColumns(6, 12);
2104  1 assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator()));
2105   
2106  1 cs.revealAllHiddenColumns(colsel);
2107  1 cs.hideColumns(0, 1);
2108  1 cs.hideColumns(3, 12);
2109  1 assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator()));
2110   
2111  1 cs.revealAllHiddenColumns(colsel);
2112  1 cs.hideColumns(3, 14);
2113  1 cs.hideColumns(17, 19);
2114  1 assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator()));
2115   
2116  1 cs.revealAllHiddenColumns(colsel);
2117  1 cs.hideColumns(3, 7);
2118  1 cs.hideColumns(9, 14);
2119  1 cs.hideColumns(17, 19);
2120  1 assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator()));
2121   
2122  1 cs.revealAllHiddenColumns(colsel);
2123  1 cs.hideColumns(0, 1);
2124  1 cs.hideColumns(3, 4);
2125  1 cs.hideColumns(6, 8);
2126  1 cs.hideColumns(10, 12);
2127  1 assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator()));
2128   
2129    }
2130    }