JAL-1152 menu tweaks plus new option to put Autocalc at top or below.
[jalview.git] / test / jalview / analysis / AnnotationSorterTest.java
1 package jalview.analysis;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertTrue;
5 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
6 import jalview.datamodel.Alignment;
7 import jalview.datamodel.AlignmentAnnotation;
8 import jalview.datamodel.Sequence;
9 import jalview.datamodel.SequenceI;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Random;
14
15 import org.junit.Before;
16 import org.junit.Test;
17
18 public class AnnotationSorterTest
19 {
20   private static final int NUM_SEQS = 6;
21
22   private static final int NUM_ANNS = 7;
23
24   private static final String SS = "secondary structure";
25
26   AlignmentAnnotation[] anns = new AlignmentAnnotation[0];
27
28   Alignment al = null;
29
30   /*
31    * Set up 6 sequences and 7 annotations.
32    */
33   @Before
34   public void setUp()
35   {
36     al = buildAlignment(NUM_SEQS);
37     anns = buildAnnotations(NUM_ANNS);
38   }
39
40   /**
41    * Construct an array of numAnns annotations
42    * 
43    * @param numAnns
44    * 
45    * @return
46    */
47   protected AlignmentAnnotation[] buildAnnotations(int numAnns)
48   {
49     List<AlignmentAnnotation> annlist = new ArrayList<AlignmentAnnotation>();
50     for (int i = 0; i < numAnns; i++)
51     {
52       AlignmentAnnotation ann = new AlignmentAnnotation(SS + i, "", 0);
53       annlist.add(ann);
54     }
55     return annlist.toArray(anns);
56   }
57
58   /**
59    * Make an alignment with numSeqs sequences in it.
60    * 
61    * @param numSeqs
62    * 
63    * @return
64    */
65   private Alignment buildAlignment(int numSeqs)
66   {
67     SequenceI[] seqs = new Sequence[numSeqs];
68     for (int i = 0; i < numSeqs; i++)
69     {
70       seqs[i] = new Sequence("Sequence" + i, "axrdkfp");
71     }
72     return new Alignment(seqs);
73   }
74
75   /**
76    * Test sorting by annotation type (label) within sequence order, including
77    * <ul>
78    * <li>annotations with no sequence reference - sort to end keeping mutual
79    * ordering</li>
80    * <li>annotations with sequence ref = sort in sequence order</li>
81    * <li>multiple annotations for same sequence ref - sort by label
82    * non-case-specific</li>
83    * <li>annotations with reference to sequence not in alignment - treat like no
84    * sequence ref</li>
85    * </ul>
86    */
87   @Test
88   public void testSortBySequenceAndType()
89   {
90     // @formatter:off
91     anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
92     anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
93     anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
94     anns[3].sequenceRef = null;                anns[3].label = "Quality";
95     anns[4].sequenceRef = null;                anns[4].label = "Consensus";
96     anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "label5";
97     anns[6].sequenceRef = al.getSequenceAt(3); anns[6].label = "IRP";
98     // @formatter:on
99
100     AnnotationSorter testee = new AnnotationSorter(al, false);
101     testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
102     assertEquals("label5", anns[0].label); // for sequence 0
103     assertEquals("label0", anns[1].label); // for sequence 1
104     assertEquals("iron", anns[2].label); // sequence 3 /iron
105     assertEquals("IRP", anns[3].label); // sequence 3/IRP
106     assertEquals("structure", anns[4].label); // sequence 3/structure
107     assertEquals("Quality", anns[5].label); // non-sequence annotations
108     assertEquals("Consensus", anns[6].label); // retain ordering
109   }
110
111   /**
112    * Test sorting by annotation type (label) within sequence order, including
113    * <ul>
114    * <li>annotations with no sequence reference - sort to end keeping mutual
115    * ordering</li>
116    * <li>annotations with sequence ref = sort in sequence order</li>
117    * <li>multiple annotations for same sequence ref - sort by label
118    * non-case-specific</li>
119    * <li>annotations with reference to sequence not in alignment - treat like no
120    * sequence ref</li>
121    * </ul>
122    */
123   @Test
124   public void testSortByTypeAndSequence()
125   {
126     // @formatter:off
127     anns[0].sequenceRef = al.getSequenceAt(1); anns[0].label = "label0";
128     anns[1].sequenceRef = al.getSequenceAt(3); anns[1].label = "structure";
129     anns[2].sequenceRef = al.getSequenceAt(3); anns[2].label = "iron";
130     anns[3].sequenceRef = null;                anns[3].label = "Quality";
131     anns[4].sequenceRef = null;                anns[4].label = "Consensus";
132     anns[5].sequenceRef = al.getSequenceAt(0); anns[5].label = "IRON";
133     anns[6].sequenceRef = al.getSequenceAt(2); anns[6].label = "Structure";
134     // @formatter:on
135
136     AnnotationSorter testee = new AnnotationSorter(al, false);
137     testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
138     assertEquals("IRON", anns[0].label); // IRON / sequence 0
139     assertEquals("iron", anns[1].label); // iron / sequence 3
140     assertEquals("label0", anns[2].label); // label0 / sequence 1
141     assertEquals("Structure", anns[3].label); // Structure / sequence 2
142     assertEquals("structure", anns[4].label); // structure / sequence 3
143     assertEquals("Quality", anns[5].label); // non-sequence annotations
144     assertEquals("Consensus", anns[6].label); // retain ordering
145   }
146
147   @Test
148   public void testSort_timingPresorted()
149   {
150     final long targetTime = 100; // ms
151     final int numSeqs = 10000;
152     final int numAnns = 20000;
153     al = buildAlignment(numSeqs);
154     anns = buildAnnotations(numAnns);
155
156     /*
157      * Set the annotations presorted by label
158      */
159     Random r = new Random();
160     final SequenceI[] sequences = al.getSequencesArray();
161     for (int i = 0; i < anns.length; i++)
162     {
163       SequenceI randomSequenceRef = sequences[r.nextInt(sequences.length)];
164       anns[i].sequenceRef = randomSequenceRef;
165       anns[i].label = "label" + i;
166     }
167     long startTime = System.currentTimeMillis();
168     AnnotationSorter testee = new AnnotationSorter(al, false);
169     testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
170     long endTime = System.currentTimeMillis();
171     final long elapsed = endTime - startTime;
172     System.out.println("Timing test for presorted " + numSeqs
173             + " sequences and "
174             + numAnns + " annotations took " + elapsed + "ms");
175     assertTrue("Sort took more than " + targetTime + "ms",
176             elapsed <= targetTime);
177   }
178
179   /**
180    * Timing test for sorting randomly sorted annotations
181    */
182   @Test
183   public void testSort_timingUnsorted()
184   {
185     final int numSeqs = 2000;
186     final int numAnns = 4000;
187     al = buildAlignment(numSeqs);
188     anns = buildAnnotations(numAnns);
189
190     /*
191      * Set the annotations in random order with respect to the sequences
192      */
193     Random r = new Random();
194     final SequenceI[] sequences = al.getSequencesArray();
195     for (int i = 0; i < anns.length; i++)
196     {
197       SequenceI randomSequenceRef = sequences[r.nextInt(sequences.length)];
198       anns[i].sequenceRef = randomSequenceRef;
199       anns[i].label = "label" + i;
200     }
201     long startTime = System.currentTimeMillis();
202     AnnotationSorter testee = new AnnotationSorter(al, false);
203     testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
204     long endTime = System.currentTimeMillis();
205     final long elapsed = endTime - startTime;
206     System.out.println("Timing test for unsorted " + numSeqs
207             + " sequences and "
208             + numAnns + " annotations took " + elapsed + "ms");
209   }
210
211   /**
212    * Timing test for sorting annotations with a limited range of types (labels).
213    */
214   @Test
215   public void testSort_timingSemisorted()
216   {
217     final int numSeqs = 2000;
218     final int numAnns = 4000;
219     al = buildAlignment(numSeqs);
220     anns = buildAnnotations(numAnns);
221
222     String[] labels = new String[]
223     { "label1", "label2", "label3", "label4", "label5", "label6" };
224
225     /*
226      * Set the annotations in sequence order with randomly assigned labels.
227      */
228     Random r = new Random();
229     final SequenceI[] sequences = al.getSequencesArray();
230     for (int i = 0; i < anns.length; i++)
231     {
232       SequenceI sequenceRef = sequences[i % sequences.length];
233       anns[i].sequenceRef = sequenceRef;
234       anns[i].label = labels[r.nextInt(labels.length)];
235     }
236     long startTime = System.currentTimeMillis();
237     AnnotationSorter testee = new AnnotationSorter(al, false);
238     testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
239     long endTime = System.currentTimeMillis();
240     long elapsed = endTime - startTime;
241     System.out.println("Sort by type for semisorted " + numSeqs
242             + " sequences and "
243             + numAnns + " annotations took " + elapsed + "ms");
244
245     // now resort by sequence
246     startTime = System.currentTimeMillis();
247     testee.sort(anns, SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
248     endTime = System.currentTimeMillis();
249     elapsed = endTime - startTime;
250     System.out.println("Resort by sequence for semisorted " + numSeqs
251             + " sequences and " + numAnns + " annotations took " + elapsed
252             + "ms");
253
254     // now resort by type
255     startTime = System.currentTimeMillis();
256     testee.sort(anns, SequenceAnnotationOrder.LABEL_AND_SEQUENCE);
257     endTime = System.currentTimeMillis();
258     elapsed = endTime - startTime;
259     System.out.println("Resort by type for semisorted " + numSeqs
260             + " sequences and " + numAnns + " annotations took " + elapsed
261             + "ms");
262   }
263 }