merge
[jalview.git] / test / jalview / util / MapListTest.java
1 package jalview.util;
2
3 import static org.testng.AssertJUnit.assertEquals;
4 import static org.testng.AssertJUnit.assertFalse;
5 import static org.testng.AssertJUnit.assertNull;
6 import static org.testng.AssertJUnit.assertTrue;
7
8 import java.util.ArrayList;
9 import java.util.Arrays;
10 import java.util.List;
11
12 import org.testng.annotations.Test;
13
14 public class MapListTest
15 {
16
17   @Test(groups ={ "Functional" })
18   public void testSomething()
19   {
20     MapList ml = new MapList(new int[]
21     { 1, 5, 10, 15, 25, 20 }, new int[]
22     { 51, 1 }, 1, 3);
23     MapList ml1 = new MapList(new int[]
24     { 1, 3, 17, 4 }, new int[]
25     { 51, 1 }, 1, 3);
26     MapList ml2 = new MapList(new int[]
27     { 1, 60 }, new int[]
28     { 1, 20 }, 3, 1);
29     // test internal consistency
30     int to[] = new int[51];
31     testMap(ml, 1, 60);
32     MapList mldna = new MapList(new int[]
33     { 2, 2, 6, 8, 12, 16 }, new int[]
34     { 1, 3 }, 3, 1);
35     int[] frm = mldna.locateInFrom(1, 1);
36     testLocateFrom(mldna, 1, 1, new int[]
37     { 2, 2, 6, 7 });
38     testMap(mldna, 1, 3);
39     /*
40      * for (int from=1; from<=51; from++) { int[] too=ml.shiftTo(from); int[]
41      * toofrom=ml.shiftFrom(too[0]);
42      * System.out.println("ShiftFrom("+from+")=="+too[0]+" %
43      * "+too[1]+"\t+-+\tShiftTo("+too[0]+")=="+toofrom[0]+" % "+toofrom[1]); }
44      */
45   }
46
47   private static void testLocateFrom(MapList mldna, int i, int j, int[] ks)
48   {
49     int[] frm = mldna.locateInFrom(i, j);
50     assertEquals("Failed test locate from " + i + " to " + j,
51             Arrays.toString(frm), Arrays.toString(ks));
52   }
53
54   /**
55    * test routine. not incremental.
56    * 
57    * @param ml
58    * @param fromS
59    * @param fromE
60    */
61   private void testMap(MapList ml, int fromS, int fromE)
62   {
63     // todo convert to JUnit style tests
64     for (int from = 1; from <= 25; from++)
65     {
66       int[] too = ml.shiftFrom(from);
67       System.out.print("ShiftFrom(" + from + ")==");
68       if (too == null)
69       {
70         System.out.print("NaN\n");
71       }
72       else
73       {
74         System.out.print(too[0] + " % " + too[1] + " (" + too[2] + ")");
75         System.out.print("\t+--+\t");
76         int[] toofrom = ml.shiftTo(too[0]);
77         if (toofrom != null)
78         {
79           if (toofrom[0] != from)
80           {
81             System.err.println("Mapping not reflexive:" + from + " "
82                     + too[0] + "->" + toofrom[0]);
83           }
84           System.out.println("ShiftTo(" + too[0] + ")==" + toofrom[0]
85                   + " % " + toofrom[1] + " (" + toofrom[2] + ")");
86         }
87         else
88         {
89           System.out.println("ShiftTo(" + too[0] + ")=="
90                   + "NaN! - not Bijective Mapping!");
91         }
92       }
93     }
94     int mmap[][] = ml.makeFromMap();
95     System.out.println("FromMap : (" + mmap[0][0] + " " + mmap[0][1] + " "
96             + mmap[0][2] + " " + mmap[0][3] + " ");
97     for (int i = 1; i <= mmap[1].length; i++)
98     {
99       if (mmap[1][i - 1] == -1)
100       {
101         System.out.print(i + "=XXX");
102   
103       }
104       else
105       {
106         System.out.print(i + "=" + (mmap[0][2] + mmap[1][i - 1]));
107       }
108       if (i % 20 == 0)
109       {
110         System.out.print("\n");
111       }
112       else
113       {
114         System.out.print(",");
115       }
116     }
117     // test range function
118     System.out.print("\nTest locateInFrom\n");
119     {
120       int f = mmap[0][2], t = mmap[0][3];
121       while (f <= t)
122       {
123         System.out.println("Range " + f + " to " + t);
124         int rng[] = ml.locateInFrom(f, t);
125         if (rng != null)
126         {
127           for (int i = 0; i < rng.length; i++)
128           {
129             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));
130           }
131         }
132         else
133         {
134           System.out.println("No range!");
135         }
136         System.out.print("\nReversed\n");
137         rng = ml.locateInFrom(t, f);
138         if (rng != null)
139         {
140           for (int i = 0; i < rng.length; i++)
141           {
142             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));
143           }
144         }
145         else
146         {
147           System.out.println("No range!");
148         }
149         System.out.print("\n");
150         f++;
151         t--;
152       }
153     }
154     System.out.print("\n");
155     mmap = ml.makeToMap();
156     System.out.println("ToMap : (" + mmap[0][0] + " " + mmap[0][1] + " "
157             + mmap[0][2] + " " + mmap[0][3] + " ");
158     for (int i = 1; i <= mmap[1].length; i++)
159     {
160       if (mmap[1][i - 1] == -1)
161       {
162         System.out.print(i + "=XXX");
163   
164       }
165       else
166       {
167         System.out.print(i + "=" + (mmap[0][2] + mmap[1][i - 1]));
168       }
169       if (i % 20 == 0)
170       {
171         System.out.print("\n");
172       }
173       else
174       {
175         System.out.print(",");
176       }
177     }
178     System.out.print("\n");
179     // test range function
180     System.out.print("\nTest locateInTo\n");
181     {
182       int f = mmap[0][2], t = mmap[0][3];
183       while (f <= t)
184       {
185         System.out.println("Range " + f + " to " + t);
186         int rng[] = ml.locateInTo(f, t);
187         if (rng != null)
188         {
189           for (int i = 0; i < rng.length; i++)
190           {
191             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));
192           }
193         }
194         else
195         {
196           System.out.println("No range!");
197         }
198         System.out.print("\nReversed\n");
199         rng = ml.locateInTo(t, f);
200         if (rng != null)
201         {
202           for (int i = 0; i < rng.length; i++)
203           {
204             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));
205           }
206         }
207         else
208         {
209           System.out.println("No range!");
210         }
211         f++;
212         t--;
213         System.out.print("\n");
214       }
215     }
216   }
217
218   /**
219    * Tests for method that locates ranges in the 'from' map for given range in
220    * the 'to' map.
221    */
222   @Test(groups ={ "Functional" })
223   public void testLocateInFrom_noIntrons()
224   {
225     /*
226      * Simple mapping with no introns
227      */
228     int[] codons = new int[]
229     { 1, 12 };
230     int[] protein = new int[]
231     { 1, 4 };
232     MapList ml = new MapList(codons, protein, 3, 1);
233     assertEquals("[1, 3]", Arrays.toString(ml.locateInFrom(1, 1)));
234     assertEquals("[4, 6]", Arrays.toString(ml.locateInFrom(2, 2)));
235     assertEquals("[7, 9]", Arrays.toString(ml.locateInFrom(3, 3)));
236     assertEquals("[10, 12]", Arrays.toString(ml.locateInFrom(4, 4)));
237     assertEquals("[1, 6]", Arrays.toString(ml.locateInFrom(1, 2)));
238     assertEquals("[1, 9]", Arrays.toString(ml.locateInFrom(1, 3)));
239     assertEquals("[1, 12]", Arrays.toString(ml.locateInFrom(1, 4)));
240     assertEquals("[4, 9]", Arrays.toString(ml.locateInFrom(2, 3)));
241     assertEquals("[4, 12]", Arrays.toString(ml.locateInFrom(2, 4)));
242     assertEquals("[7, 12]", Arrays.toString(ml.locateInFrom(3, 4)));
243     assertEquals("[10, 12]", Arrays.toString(ml.locateInFrom(4, 4)));
244
245     assertNull(ml.locateInFrom(0, 0));
246     assertNull(ml.locateInFrom(1, 5));
247     assertNull(ml.locateInFrom(-1, 1));
248   }
249
250   /**
251    * Tests for method that locates ranges in the 'from' map for given range in
252    * the 'to' map.
253    */
254   @Test(groups ={ "Functional" })
255   public void testLocateInFrom_withIntrons()
256   {
257     /*
258      * Exons at positions [2, 3, 5] [6, 7, 9] [10, 12, 14] [16, 17, 18] i.e.
259      * 2-3, 5-7, 9-10, 12-12, 14-14, 16-18
260      */
261     int[] codons =
262     { 2, 3, 5, 7, 9, 10, 12, 12, 14, 14, 16, 18 };
263     int[] protein =
264     { 1, 4 };
265     MapList ml = new MapList(codons, protein, 3, 1);
266     assertEquals("[2, 3, 5, 5]", Arrays.toString(ml.locateInFrom(1, 1)));
267     assertEquals("[6, 7, 9, 9]", Arrays.toString(ml.locateInFrom(2, 2)));
268     assertEquals("[10, 10, 12, 12, 14, 14]",
269             Arrays.toString(ml.locateInFrom(3, 3)));
270     assertEquals("[16, 18]", Arrays.toString(ml.locateInFrom(4, 4)));
271   }
272
273   /**
274    * Tests for method that locates ranges in the 'to' map for given range in the
275    * 'from' map.
276    */
277   @Test(groups ={ "Functional" })
278   public void testLocateInTo_noIntrons()
279   {
280     /*
281      * Simple mapping with no introns
282      */
283     int[] codons = new int[]
284     { 1, 12 };
285     int[] protein = new int[]
286     { 1, 4 };
287     MapList ml = new MapList(codons, protein, 3, 1);
288     assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(1, 3)));
289     assertEquals("[2, 2]", Arrays.toString(ml.locateInTo(4, 6)));
290     assertEquals("[3, 3]", Arrays.toString(ml.locateInTo(7, 9)));
291     assertEquals("[4, 4]", Arrays.toString(ml.locateInTo(10, 12)));
292     assertEquals("[1, 2]", Arrays.toString(ml.locateInTo(1, 6)));
293     assertEquals("[1, 3]", Arrays.toString(ml.locateInTo(1, 9)));
294     assertEquals("[1, 4]", Arrays.toString(ml.locateInTo(1, 12)));
295     assertEquals("[2, 2]", Arrays.toString(ml.locateInTo(4, 6)));
296     assertEquals("[2, 4]", Arrays.toString(ml.locateInTo(4, 12)));
297
298     /*
299      * A part codon is treated as if a whole one.
300      */
301     assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(1, 1)));
302     assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(1, 2)));
303     assertEquals("[1, 2]", Arrays.toString(ml.locateInTo(1, 4)));
304     assertEquals("[1, 3]", Arrays.toString(ml.locateInTo(2, 8)));
305     assertEquals("[1, 4]", Arrays.toString(ml.locateInTo(3, 11)));
306     assertEquals("[2, 4]", Arrays.toString(ml.locateInTo(5, 11)));
307
308     assertNull(ml.locateInTo(0, 0));
309     assertNull(ml.locateInTo(1, 13));
310     assertNull(ml.locateInTo(-1, 1));
311   }
312
313   /**
314    * Tests for method that locates ranges in the 'to' map for given range in the
315    * 'from' map.
316    */
317   @Test(groups ={ "Functional" })
318   public void testLocateInTo_withIntrons()
319   {
320     /*
321      * Exons at positions [2, 3, 5] [6, 7, 9] [10, 12, 14] [16, 17, 18] i.e.
322      * 2-3, 5-7, 9-10, 12-12, 14-14, 16-18
323      */
324     int[] codons =
325     { 2, 3, 5, 7, 9, 10, 12, 12, 14, 14, 16, 18 };
326     /*
327      * Mapped proteins at positions 1, 3, 4, 6 in the sequence
328      */
329     int[] protein =
330     { 1, 1, 3, 4, 6, 6 };
331     MapList ml = new MapList(codons, protein, 3, 1);
332
333     /*
334      * Can't map from an unmapped position
335      */
336     assertNull(ml.locateInTo(1, 2));
337     assertNull(ml.locateInTo(2, 4));
338     assertNull(ml.locateInTo(4, 4));
339
340     /*
341      * Valid range or subrange of codon1 maps to protein1.
342      */
343     assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(2, 2)));
344     assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(3, 3)));
345     assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(3, 5)));
346     assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(2, 3)));
347     assertEquals("[1, 1]", Arrays.toString(ml.locateInTo(2, 5)));
348
349     // codon position 6 starts the next protein:
350     assertEquals("[1, 1, 3, 3]", Arrays.toString(ml.locateInTo(3, 6)));
351
352     // codon positions 7 to 17 (part) cover proteins 2/3/4 at positions 3/4/6
353     assertEquals("[3, 4, 6, 6]", Arrays.toString(ml.locateInTo(7, 17)));
354
355   }
356
357   /**
358    * Test equals method.
359    */
360   @Test(groups ={ "Functional" })
361   public void testEquals()
362   {
363     int[] codons = new int[]
364     { 2, 3, 5, 7, 9, 10, 12, 12, 14, 14, 16, 18 };
365     int[] protein = new int[]
366     { 1, 4 };
367     MapList ml = new MapList(codons, protein, 3, 1);
368     MapList ml1 = new MapList(codons, protein, 3, 1); // same values
369     MapList ml2 = new MapList(codons, protein, 2, 1); // fromRatio differs
370     MapList ml3 = new MapList(codons, protein, 3, 2); // toRatio differs
371     codons[2] = 4;
372     MapList ml6 = new MapList(codons, protein, 3, 1); // fromShifts differ
373     protein[1] = 3;
374     MapList ml7 = new MapList(codons, protein, 3, 1); // toShifts differ
375
376     assertTrue(ml.equals(ml));
377     assertTrue(ml.equals(ml1));
378     assertTrue(ml1.equals(ml));
379
380     assertFalse(ml.equals(null));
381     assertFalse(ml.equals("hello"));
382     assertFalse(ml.equals(ml2));
383     assertFalse(ml.equals(ml3));
384     assertFalse(ml.equals(ml6));
385     assertFalse(ml.equals(ml7));
386     assertFalse(ml6.equals(ml7));
387
388     try
389     {
390       MapList ml4 = new MapList(codons, null, 3, 1); // toShifts null
391       assertFalse(ml.equals(ml4));
392     } catch (NullPointerException e)
393     {
394       // actually thrown by constructor before equals can be called
395     }
396     try
397     {
398       MapList ml5 = new MapList(null, protein, 3, 1); // fromShifts null
399       assertFalse(ml.equals(ml5));
400     } catch (NullPointerException e)
401     {
402       // actually thrown by constructor before equals can be called
403     }
404   }
405
406   /**
407    * Test for the method that flattens a list of ranges into a single array.
408    */
409   @Test(groups ={ "Functional" })
410   public void testGetRanges()
411   {
412     List<int[]> ranges = new ArrayList<int[]>();
413     ranges.add(new int[]
414     { 2, 3 });
415     ranges.add(new int[]
416     { 5, 6 });
417     assertEquals("[2, 3, 5, 6]", Arrays.toString(MapList.getRanges(ranges)));
418   }
419
420   /**
421    * Check state after construction
422    */
423   @Test(groups ={ "Functional" })
424   public void testConstructor()
425   {
426     int[] codons =
427     { 2, 3, 5, 7, 9, 10, 12, 12, 14, 14, 16, 18 };
428     int[] protein =
429     { 1, 1, 3, 4, 6, 6 };
430     MapList ml = new MapList(codons, protein, 3, 1);
431     assertEquals(3, ml.getFromRatio());
432     assertEquals(2, ml.getFromLowest());
433     assertEquals(18, ml.getFromHighest());
434     assertEquals(1, ml.getToLowest());
435     assertEquals(6, ml.getToHighest());
436     assertEquals("{[2, 3], [5, 7], [9, 10], [12, 12], [14, 14], [16, 18]}",
437             prettyPrint(ml.getFromRanges()));
438     assertEquals("{[1, 1], [3, 4], [6, 6]}", prettyPrint(ml.getToRanges()));
439
440     /*
441      * Also copy constructor
442      */
443     MapList ml2 = new MapList(ml);
444     assertEquals(3, ml2.getFromRatio());
445     assertEquals(2, ml2.getFromLowest());
446     assertEquals(18, ml2.getFromHighest());
447     assertEquals(1, ml2.getToLowest());
448     assertEquals(6, ml2.getToHighest());
449     assertEquals("{[2, 3], [5, 7], [9, 10], [12, 12], [14, 14], [16, 18]}",
450             prettyPrint(ml2.getFromRanges()));
451     assertEquals("{[1, 1], [3, 4], [6, 6]}", prettyPrint(ml2.getToRanges()));
452   }
453
454   /**
455    * Convert a List of {[i, j], [k, l], ...} to "[[i, j], [k, l], ...]"
456    * 
457    * @param ranges
458    * @return
459    */
460   private String prettyPrint(List<int[]> ranges)
461   {
462     StringBuilder sb = new StringBuilder(ranges.size() * 5);
463     boolean first = true;
464     sb.append("{");
465     for (int[] range : ranges)
466     {
467       if (!first)
468       {
469         sb.append(", ");
470       }
471       sb.append(Arrays.toString(range));
472       first = false;
473     }
474     sb.append("}");
475     return sb.toString();
476   }
477
478   /**
479    * Test the method that creates an inverse mapping
480    */
481   @Test(groups ={ "Functional" })
482   public void testGetInverse()
483   {
484     int[] codons =
485     { 2, 3, 5, 7, 9, 10, 12, 12, 14, 14, 16, 18 };
486     int[] protein =
487     { 1, 1, 3, 4, 6, 6 };
488
489     MapList ml = new MapList(codons, protein, 3, 1);
490     MapList ml2 = ml.getInverse();
491     assertEquals(ml.getFromRatio(), ml2.getToRatio());
492     assertEquals(ml.getFromRatio(), ml2.getToRatio());
493     assertEquals(ml.getToHighest(), ml2.getFromHighest());
494     assertEquals(ml.getFromHighest(), ml2.getToHighest());
495     assertEquals(prettyPrint(ml.getFromRanges()),
496             prettyPrint(ml2.getToRanges()));
497     assertEquals(prettyPrint(ml.getToRanges()),
498             prettyPrint(ml2.getFromRanges()));
499   }
500
501   @Test(groups ={ "Functional" })
502   public void testToString()
503   {
504     MapList ml = new MapList(new int[]
505     { 1, 5, 10, 15, 25, 20 }, new int[]
506     { 51, 1 }, 1, 3);
507     String s = ml.toString();
508     assertEquals("From (1:3) [ [1, 5] [10, 15] [25, 20] ] To [ [51, 1] ]",
509             s);
510   }
511 }