Clover icon

Coverage Report

  1. Project Clover database Tue Mar 10 2026 14:58:44 GMT
  2. Package jalview.datamodel

File SequenceTest.java

 

Code metrics

2
1,194
58
1
2,394
1,615
61
0.05
20.59
58
1.05

Classes

Class Line # Actions
SequenceTest 54 1,194 61
0.00%
 

Contributing tests

No tests hitting this source file were found.

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