Clover icon

Coverage Report

  1. Project Clover database Thu Nov 27 2025 17:07:57 GMT
  2. Package jalview.datamodel

File SequenceTest.java

 

Code metrics

2
1,177
54
1
2,349
1,580
57
0.05
21.8
54
1.06

Classes

Class Line # Actions
SequenceTest 54 1,177 57
0.9699918697%
 

Contributing tests

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