Clover icon

Coverage Report

  1. Project Clover database Mon Sep 2 2024 17:57:51 BST
  2. Package jalview.datamodel

File SequenceTest.java

 

Code metrics

2
1,175
54
1
2,347
1,578
57
0.05
21.76
54
1.06

Classes

Class Line # Actions
SequenceTest 54 1,175 57
0.969943197%
 

Contributing tests

This file is covered by 47 tests. .

Source view

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