Clover icon

Coverage Report

  1. Project Clover database Thu Nov 7 2024 10:11:34 GMT
  2. Package jalview.analysis

File AnnotationSorterTest.java

 

Code metrics

10
190
15
1
413
253
20
0.11
12.67
15
1.33

Classes

Class Line # Actions
AnnotationSorterTest 40 190 20
1.0100%
 

Contributing tests

This file is covered by 8 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.analysis;
22   
23    import static org.testng.AssertJUnit.assertEquals;
24   
25    import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
26    import jalview.datamodel.Alignment;
27    import jalview.datamodel.AlignmentAnnotation;
28    import jalview.datamodel.Sequence;
29    import jalview.datamodel.SequenceI;
30    import jalview.gui.JvOptionPane;
31   
32    import java.util.ArrayList;
33    import java.util.List;
34    import java.util.Random;
35   
36    import org.testng.annotations.BeforeClass;
37    import org.testng.annotations.BeforeMethod;
38    import org.testng.annotations.Test;
39   
 
40    public class AnnotationSorterTest
41    {
42   
 
43  1 toggle @BeforeClass(alwaysRun = true)
44    public void setUpJvOptionPane()
45    {
46  1 JvOptionPane.setInteractiveMode(false);
47  1 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
48    }
49   
50    private static final int NUM_SEQS = 6;
51   
52    private static final int NUM_ANNS = 7;
53   
54    private static final String SS = "secondary structure";
55   
56    AlignmentAnnotation[] anns = new AlignmentAnnotation[0];
57   
58    Alignment al = null;
59   
60    /*
61    * Set up 6 sequences and 7 annotations.
62    */
 
63  8 toggle @BeforeMethod(alwaysRun = true)
64    public void setUp()
65    {
66  8 al = buildAlignment(NUM_SEQS);
67  8 anns = buildAnnotations(NUM_ANNS);
68    }
69   
70    /**
71    * Construct an array of numAnns annotations
72    *
73    * @param numAnns
74    *
75    * @return
76    */
 
77  17 toggle protected AlignmentAnnotation[] buildAnnotations(int numAnns)
78    {
79  17 List<AlignmentAnnotation> annlist = new ArrayList<AlignmentAnnotation>();
80  33373 for (int i = 0; i < numAnns; i++)
81    {
82  33356 AlignmentAnnotation ann = new AlignmentAnnotation(SS + i, "", 0);
83  33356 annlist.add(ann);
84    }
85  17 return annlist.toArray(anns);
86    }
87   
88    /**
89    * Make an alignment with numSeqs sequences in it.
90    *
91    * @param numSeqs
92    *
93    * @return
94    */
 
95  17 toggle private Alignment buildAlignment(int numSeqs)
96    {
97  17 SequenceI[] seqs = new Sequence[numSeqs];
98  16715 for (int i = 0; i < numSeqs; i++)
99    {
100  16698 seqs[i] = new Sequence("Sequence" + i, "axrdkfp");
101    }
102  17 return new Alignment(seqs);
103    }
104   
105    /**
106    * Test sorting by annotation type (label) within sequence order, including
107    * <ul>
108    * <li>annotations with no sequence reference - sort to end keeping mutual
109    * ordering</li>
110    * <li>annotations with sequence ref = sort in sequence order</li>
111    * <li>multiple annotations for same sequence ref - sort by label
112    * non-case-specific</li>
113    * <li>annotations with reference to sequence not in alignment - treat like no
114    * sequence ref</li>
115    * </ul>
116    */
 
117  1 toggle @Test(groups = { "Functional" })
118    public void testSortBySequenceAndType_autocalcLast()
119    {
120    // @formatter:off
121  1 anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
122  1 anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
123  1 anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
124  1 anns[3].autoCalculated = true; anns[3].label = "Quality";
125  1 anns[4].autoCalculated = true; anns[4].label = "Consensus";
126  1 anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "label5";
127  1 anns[6].sequenceRef = al.getSequenceAt(3); anns[6].label = "IRP";
128    // @formatter:on
129   
130  1 AnnotationSorter testee = new AnnotationSorter(al, false);
131  1 testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
132  1 assertEquals("label5", anns[0].label); // for sequence 0
133  1 assertEquals("label0", anns[1].label); // for sequence 1
134  1 assertEquals("iron", anns[2].label); // sequence 3 /iron
135  1 assertEquals("IRP", anns[3].label); // sequence 3/IRP
136  1 assertEquals("structure", anns[4].label); // sequence 3/structure
137  1 assertEquals("Quality", anns[5].label); // autocalc annotations
138  1 assertEquals("Consensus", anns[6].label); // retain ordering
139    }
140   
141    /**
142    * Variant with autocalculated annotations sorting to front
143    */
 
144  1 toggle @Test(groups = { "Functional" })
145    public void testSortBySequenceAndType_autocalcFirst()
146    {
147    // @formatter:off
148  1 anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
149  1 anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
150  1 anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
151  1 anns[3].autoCalculated = true; anns[3].label = "Quality";
152  1 anns[4].autoCalculated = true; anns[4].label = "Consensus";
153  1 anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "label5";
154  1 anns[6].sequenceRef = al.getSequenceAt(3); anns[6].label = "IRP";
155    // @formatter:on
156   
157  1 AnnotationSorter testee = new AnnotationSorter(al, true);
158  1 testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
159  1 assertEquals("Quality", anns[0].label); // autocalc annotations
160  1 assertEquals("Consensus", anns[1].label); // retain ordering
161  1 assertEquals("label5", anns[2].label); // for sequence 0
162  1 assertEquals("label0", anns[3].label); // for sequence 1
163  1 assertEquals("iron", anns[4].label); // sequence 3 /iron
164  1 assertEquals("IRP", anns[5].label); // sequence 3/IRP
165  1 assertEquals("structure", anns[6].label); // sequence 3/structure
166    }
167   
168    /**
169    * Test sorting by annotation type (label) within sequence order, including
170    * <ul>
171    * <li>annotations with no sequence reference - sort to end keeping mutual
172    * ordering</li>
173    * <li>annotations with sequence ref = sort in sequence order</li>
174    * <li>multiple annotations for same sequence ref - sort by label
175    * non-case-specific</li>
176    * <li>annotations with reference to sequence not in alignment - treat like no
177    * sequence ref</li>
178    * </ul>
179    */
 
180  1 toggle @Test(groups = { "Functional" })
181    public void testSortByTypeAndSequence_autocalcLast()
182    {
183    // @formatter:off
184  1 anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
185  1 anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
186  1 anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
187  1 anns[3].autoCalculated = true; anns[3].label = "Quality";
188  1 anns[4].autoCalculated = true; anns[4].label = "Consensus";
189  1 anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "IRON";
190  1 anns[6].sequenceRef = al.getSequenceAt(2); anns[6].label = "Structure";
191    // @formatter:on
192   
193  1 AnnotationSorter testee = new AnnotationSorter(al, false);
194  1 testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
195  1 assertEquals("IRON", anns[0].label); // IRON / sequence 0
196  1 assertEquals("iron", anns[1].label); // iron / sequence 3
197  1 assertEquals("label0", anns[2].label); // label0 / sequence 1
198  1 assertEquals("Structure", anns[3].label); // Structure / sequence 2
199  1 assertEquals("structure", anns[4].label); // structure / sequence 3
200  1 assertEquals("Quality", anns[5].label); // autocalc annotations
201  1 assertEquals("Consensus", anns[6].label); // retain ordering
202    }
203   
204    /**
205    * Variant of test with autocalculated annotations sorted to front
206    */
 
207  1 toggle @Test(groups = { "Functional" })
208    public void testSortByTypeAndSequence_autocalcFirst()
209    {
210    // @formatter:off
211  1 anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
212  1 anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
213  1 anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
214  1 anns[3].autoCalculated = true; anns[3].label = "Quality";
215  1 anns[4].autoCalculated = true; anns[4].label = "Consensus";
216  1 anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "IRON";
217  1 anns[6].sequenceRef = al.getSequenceAt(2); anns[6].label = "Structure";
218    // @formatter:on
219   
220  1 AnnotationSorter testee = new AnnotationSorter(al, true);
221  1 testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
222  1 assertEquals("Quality", anns[0].label); // autocalc annotations
223  1 assertEquals("Consensus", anns[1].label); // retain ordering
224  1 assertEquals("IRON", anns[2].label); // IRON / sequence 0
225  1 assertEquals("iron", anns[3].label); // iron / sequence 3
226  1 assertEquals("label0", anns[4].label); // label0 / sequence 1
227  1 assertEquals("Structure", anns[5].label); // Structure / sequence 2
228  1 assertEquals("structure", anns[6].label); // structure / sequence 3
229    }
230   
231    /**
232    * Variant of test with autocalculated annotations sorted to front but
233    * otherwise no change.
234    */
 
235  1 toggle @Test(groups = { "Functional" })
236    public void testNoSort_autocalcFirst()
237    {
238    // @formatter:off
239  1 anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
240  1 anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
241  1 anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
242  1 anns[3].autoCalculated = true; anns[3].label = "Quality";
243  1 anns[4].autoCalculated = true; anns[4].label = "Consensus";
244  1 anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "IRON";
245  1 anns[6].sequenceRef = al.getSequenceAt(2); anns[6].label = "Structure";
246    // @formatter:on
247   
248  1 AnnotationSorter testee = new AnnotationSorter(al, true);
249  1 testee.sort(anns, SequenceAnnotationOrder.NONE);
250  1 assertEquals("Quality", anns[0].label); // autocalc annotations
251  1 assertEquals("Consensus", anns[1].label); // retain ordering
252  1 assertEquals("label0", anns[2].label);
253  1 assertEquals("structure", anns[3].label);
254  1 assertEquals("iron", anns[4].label);
255  1 assertEquals("IRON", anns[5].label);
256  1 assertEquals("Structure", anns[6].label);
257    }
258   
 
259  1 toggle @Test(groups = { "Functional" })
260    public void testSort_timingPresorted()
261    {
262  1 testTiming_presorted(50, 100);
263  1 testTiming_presorted(500, 1000);
264  1 testTiming_presorted(5000, 10000);
265    }
266   
267    /**
268    * Test timing to sort annotations already in the sort order.
269    *
270    * @param numSeqs
271    * @param numAnns
272    */
 
273  3 toggle private void testTiming_presorted(final int numSeqs, final int numAnns)
274    {
275  3 Alignment alignment = buildAlignment(numSeqs);
276  3 AlignmentAnnotation[] annotations = buildAnnotations(numAnns);
277   
278    /*
279    * Set the annotations presorted by label
280    */
281  3 Random r = new Random();
282  3 final SequenceI[] sequences = alignment.getSequencesArray();
283  11103 for (int i = 0; i < annotations.length; i++)
284    {
285  11100 SequenceI randomSequenceRef = sequences[r.nextInt(sequences.length)];
286  11100 annotations[i].sequenceRef = randomSequenceRef;
287  11100 annotations[i].label = "label" + i;
288    }
289  3 long startTime = System.currentTimeMillis();
290  3 AnnotationSorter testee = new AnnotationSorter(alignment, false);
291  3 testee.sort(annotations, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
292  3 long endTime = System.currentTimeMillis();
293  3 final long elapsed = endTime - startTime;
294  3 System.out.println(
295    "Timing test for presorted " + numSeqs + " sequences and "
296    + numAnns + " annotations took " + elapsed + "ms");
297    }
298   
299    /**
300    * Timing tests for sorting randomly sorted annotations for various sizes.
301    */
 
302  1 toggle @Test(groups = { "Functional" })
303    public void testSort_timingUnsorted()
304    {
305  1 testTiming_unsorted(50, 100);
306  1 testTiming_unsorted(500, 1000);
307  1 testTiming_unsorted(5000, 10000);
308    }
309   
310    /**
311    * Generate annotations randomly sorted with respect to sequences, and time
312    * sorting.
313    *
314    * @param numSeqs
315    * @param numAnns
316    */
 
317  3 toggle private void testTiming_unsorted(final int numSeqs, final int numAnns)
318    {
319  3 Alignment alignment = buildAlignment(numSeqs);
320  3 AlignmentAnnotation[] annotations = buildAnnotations(numAnns);
321   
322    /*
323    * Set the annotations in random order with respect to the sequences
324    */
325  3 Random r = new Random();
326  3 final SequenceI[] sequences = alignment.getSequencesArray();
327  11103 for (int i = 0; i < annotations.length; i++)
328    {
329  11100 SequenceI randomSequenceRef = sequences[r.nextInt(sequences.length)];
330  11100 annotations[i].sequenceRef = randomSequenceRef;
331  11100 annotations[i].label = "label" + i;
332    }
333  3 long startTime = System.currentTimeMillis();
334  3 AnnotationSorter testee = new AnnotationSorter(alignment, false);
335  3 testee.sort(annotations, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
336  3 long endTime = System.currentTimeMillis();
337  3 final long elapsed = endTime - startTime;
338  3 System.out.println(
339    "Timing test for unsorted " + numSeqs + " sequences and "
340    + numAnns + " annotations took " + elapsed + "ms");
341    }
342   
343    /**
344    * Timing test for sorting annotations with a limited range of types (labels).
345    */
 
346  1 toggle @Test(groups = { "Functional" })
347    public void testSort_timingSemisorted()
348    {
349  1 testTiming_semiSorted(50, 100);
350  1 testTiming_semiSorted(500, 1000);
351  1 testTiming_semiSorted(5000, 10000);
352    }
353   
354    /**
355    * Mimic 'semi-sorted' annotations:
356    * <ul>
357    * <li>set up in sequence order, with randomly assigned labels from a limited
358    * range</li>
359    * <li>sort by label and sequence order, report timing</li>
360    * <li>resort by sequence and label, report timing</li>
361    * <li>resort by label and sequence, report timing</li>
362    * </ul>
363    *
364    * @param numSeqs
365    * @param numAnns
366    */
 
367  3 toggle private void testTiming_semiSorted(final int numSeqs, final int numAnns)
368    {
369  3 Alignment alignment = buildAlignment(numSeqs);
370  3 AlignmentAnnotation[] annotations = buildAnnotations(numAnns);
371   
372  3 String[] labels = new String[] { "label1", "label2", "label3", "label4",
373    "label5", "label6" };
374   
375    /*
376    * Set the annotations in sequence order with randomly assigned labels.
377    */
378  3 Random r = new Random();
379  3 final SequenceI[] sequences = alignment.getSequencesArray();
380  11103 for (int i = 0; i < annotations.length; i++)
381    {
382  11100 SequenceI sequenceRef = sequences[i % sequences.length];
383  11100 annotations[i].sequenceRef = sequenceRef;
384  11100 annotations[i].label = labels[r.nextInt(labels.length)];
385    }
386  3 long startTime = System.currentTimeMillis();
387  3 AnnotationSorter testee = new AnnotationSorter(alignment, false);
388  3 testee.sort(annotations, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
389  3 long endTime = System.currentTimeMillis();
390  3 long elapsed = endTime - startTime;
391  3 System.out.println(
392    "Sort by label for semisorted " + numSeqs + " sequences and "
393    + numAnns + " annotations took " + elapsed + "ms");
394   
395    // now resort by sequence
396  3 startTime = System.currentTimeMillis();
397  3 testee.sort(annotations, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
398  3 endTime = System.currentTimeMillis();
399  3 elapsed = endTime - startTime;
400  3 System.out.println("Resort by sequence for semisorted " + numSeqs
401    + " sequences and " + numAnns + " annotations took " + elapsed
402    + "ms");
403   
404    // now resort by label
405  3 startTime = System.currentTimeMillis();
406  3 testee.sort(annotations, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
407  3 endTime = System.currentTimeMillis();
408  3 elapsed = endTime - startTime;
409  3 System.out.println(
410    "Resort by label for semisorted " + numSeqs + " sequences and "
411    + numAnns + " annotations took " + elapsed + "ms");
412    }
413    }