Clover icon

Coverage Report

  1. Project Clover database Mon Nov 11 2024 20:42:03 GMT
  2. Package jalview.util

File MappingUtilsTest.java

 

Code metrics

18
672
26
1
1,453
1,001
39
0.06
25.85
26
1.5

Classes

Class Line # Actions
MappingUtilsTest 62 672 39
1.0100%
 

Contributing tests

This file is covered by 22 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.util;
22   
23    import static org.testng.AssertJUnit.assertEquals;
24    import static org.testng.AssertJUnit.assertFalse;
25    import static org.testng.AssertJUnit.assertNull;
26    import static org.testng.AssertJUnit.assertSame;
27    import static org.testng.AssertJUnit.assertTrue;
28    import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
29   
30    import java.awt.Color;
31    import java.io.IOException;
32    import java.util.ArrayList;
33    import java.util.Arrays;
34    import java.util.Iterator;
35    import java.util.List;
36   
37    import org.testng.annotations.BeforeClass;
38    import org.testng.annotations.Test;
39   
40    import jalview.api.AlignViewportI;
41    import jalview.bin.Console;
42    import jalview.commands.EditCommand;
43    import jalview.commands.EditCommand.Action;
44    import jalview.commands.EditCommand.Edit;
45    import jalview.datamodel.AlignedCodonFrame;
46    import jalview.datamodel.Alignment;
47    import jalview.datamodel.AlignmentI;
48    import jalview.datamodel.ColumnSelection;
49    import jalview.datamodel.HiddenColumns;
50    import jalview.datamodel.SearchResultMatchI;
51    import jalview.datamodel.SearchResultsI;
52    import jalview.datamodel.Sequence;
53    import jalview.datamodel.SequenceGroup;
54    import jalview.datamodel.SequenceI;
55    import jalview.gui.AlignViewport;
56    import jalview.gui.JvOptionPane;
57    import jalview.io.DataSourceType;
58    import jalview.io.FileFormat;
59    import jalview.io.FileFormatI;
60    import jalview.io.FormatAdapter;
61   
 
62    public class MappingUtilsTest
63    {
 
64  1 toggle @BeforeClass(alwaysRun = true)
65    public void setUp()
66    {
67  1 Console.initLogger();
68    }
69   
 
70  1 toggle @BeforeClass(alwaysRun = true)
71    public void setUpJvOptionPane()
72    {
73  1 JvOptionPane.setInteractiveMode(false);
74  1 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
75    }
76   
77    private AlignViewportI dnaView;
78   
79    private AlignViewportI proteinView;
80   
81    /**
82    * Simple test of mapping with no intron involved.
83    */
 
84  1 toggle @Test(groups = { "Functional" })
85    public void testBuildSearchResults()
86    {
87  1 final Sequence seq1 = new Sequence("Seq1/5-10", "C-G-TA-GC");
88  1 seq1.createDatasetSequence();
89   
90  1 final Sequence aseq1 = new Sequence("Seq1/12-13", "-P-R");
91  1 aseq1.createDatasetSequence();
92   
93    /*
94    * Map dna bases 5-10 to protein residues 12-13
95    */
96  1 AlignedCodonFrame acf = new AlignedCodonFrame();
97  1 MapList map = new MapList(new int[] { 5, 10 }, new int[] { 12, 13 }, 3,
98    1);
99  1 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
100  1 List<AlignedCodonFrame> acfList = Arrays
101    .asList(new AlignedCodonFrame[]
102    { acf });
103   
104    /*
105    * Check protein residue 12 maps to codon 5-7, 13 to codon 8-10
106    */
107  1 SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 12, acfList);
108  1 assertEquals(1, sr.getResults().size());
109  1 SearchResultMatchI m = sr.getResults().get(0);
110  1 assertEquals(seq1.getDatasetSequence(), m.getSequence());
111  1 assertEquals(5, m.getStart());
112  1 assertEquals(7, m.getEnd());
113  1 sr = MappingUtils.buildSearchResults(aseq1, 13, acfList);
114  1 assertEquals(1, sr.getResults().size());
115  1 m = sr.getResults().get(0);
116  1 assertEquals(seq1.getDatasetSequence(), m.getSequence());
117  1 assertEquals(8, m.getStart());
118  1 assertEquals(10, m.getEnd());
119   
120    /*
121    * Check inverse mappings, from codons 5-7, 8-10 to protein 12, 13
122    */
123  7 for (int i = 5; i < 11; i++)
124    {
125  6 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
126  6 assertEquals(1, sr.getResults().size());
127  6 m = sr.getResults().get(0);
128  6 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
129  6 int residue = i > 7 ? 13 : 12;
130  6 assertEquals(residue, m.getStart());
131  6 assertEquals(residue, m.getEnd());
132    }
133    }
134   
135    /**
136    * Simple test of mapping with introns involved.
137    */
 
138  1 toggle @Test(groups = { "Functional" })
139    public void testBuildSearchResults_withIntron()
140    {
141  1 final Sequence seq1 = new Sequence("Seq1/5-17", "c-G-tAGa-GcAgCtt");
142  1 seq1.createDatasetSequence();
143   
144  1 final Sequence aseq1 = new Sequence("Seq1/8-9", "-E-D");
145  1 aseq1.createDatasetSequence();
146   
147    /*
148    * Map dna bases [6, 8, 9], [11, 13, 115] to protein residues 8 and 9
149    */
150  1 AlignedCodonFrame acf = new AlignedCodonFrame();
151  1 MapList map = new MapList(
152    new int[]
153    { 6, 6, 8, 9, 11, 11, 13, 13, 15, 15 }, new int[] { 8, 9 }, 3,
154    1);
155  1 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
156  1 List<AlignedCodonFrame> acfList = Arrays
157    .asList(new AlignedCodonFrame[]
158    { acf });
159   
160    /*
161    * Check protein residue 8 maps to [6, 8, 9]
162    */
163  1 SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 8, acfList);
164  1 assertEquals(2, sr.getResults().size());
165  1 SearchResultMatchI m = sr.getResults().get(0);
166  1 assertEquals(seq1.getDatasetSequence(), m.getSequence());
167  1 assertEquals(6, m.getStart());
168  1 assertEquals(6, m.getEnd());
169  1 m = sr.getResults().get(1);
170  1 assertEquals(seq1.getDatasetSequence(), m.getSequence());
171  1 assertEquals(8, m.getStart());
172  1 assertEquals(9, m.getEnd());
173   
174    /*
175    * Check protein residue 9 maps to [11, 13, 15]
176    */
177  1 sr = MappingUtils.buildSearchResults(aseq1, 9, acfList);
178  1 assertEquals(3, sr.getResults().size());
179  1 m = sr.getResults().get(0);
180  1 assertEquals(seq1.getDatasetSequence(), m.getSequence());
181  1 assertEquals(11, m.getStart());
182  1 assertEquals(11, m.getEnd());
183  1 m = sr.getResults().get(1);
184  1 assertEquals(seq1.getDatasetSequence(), m.getSequence());
185  1 assertEquals(13, m.getStart());
186  1 assertEquals(13, m.getEnd());
187  1 m = sr.getResults().get(2);
188  1 assertEquals(seq1.getDatasetSequence(), m.getSequence());
189  1 assertEquals(15, m.getStart());
190  1 assertEquals(15, m.getEnd());
191   
192    /*
193    * Check inverse mappings, from codons to protein
194    */
195  14 for (int i = 5; i < 18; i++)
196    {
197  13 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
198  13 int residue = (i == 6 || i == 8 || i == 9) ? 8
199  10 : (i == 11 || i == 13 || i == 15 ? 9 : 0);
200  13 if (residue == 0)
201    {
202  7 assertEquals(0, sr.getResults().size());
203  7 continue;
204    }
205  6 assertEquals(1, sr.getResults().size());
206  6 m = sr.getResults().get(0);
207  6 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
208  6 assertEquals(residue, m.getStart());
209  6 assertEquals(residue, m.getEnd());
210    }
211    }
212   
213    /**
214    * Test mapping a sequence group made of entire sequences.
215    *
216    * @throws IOException
217    */
 
218  1 toggle @Test(groups = { "Functional" })
219    public void testMapSequenceGroup_sequences() throws IOException
220    {
221    /*
222    * Set up dna and protein Seq1/2/3 with mappings (held on the protein
223    * viewport).
224    */
225  1 AlignmentI cdna = loadAlignment(">Seq1\nACG\n>Seq2\nTGA\n>Seq3\nTAC\n",
226    FileFormat.Fasta);
227  1 cdna.setDataset(null);
228  1 AlignmentI protein = loadAlignment(">Seq1\nK\n>Seq2\nL\n>Seq3\nQ\n",
229    FileFormat.Fasta);
230  1 protein.setDataset(null);
231  1 AlignedCodonFrame acf = new AlignedCodonFrame();
232  1 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 1 }, 3, 1);
233  4 for (int seq = 0; seq < 3; seq++)
234    {
235  3 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(),
236    protein.getSequenceAt(seq).getDatasetSequence(), map);
237    }
238  1 List<AlignedCodonFrame> acfList = Arrays
239    .asList(new AlignedCodonFrame[]
240    { acf });
241   
242  1 AlignViewportI dnaView = new AlignViewport(cdna);
243  1 AlignViewportI proteinView = new AlignViewport(protein);
244  1 protein.setCodonFrames(acfList);
245   
246    /*
247    * Select Seq1 and Seq3 in the protein
248    */
249  1 SequenceGroup sg = new SequenceGroup();
250  1 sg.setColourText(true);
251  1 sg.setIdColour(Color.GREEN);
252  1 sg.setOutlineColour(Color.LIGHT_GRAY);
253  1 sg.addSequence(protein.getSequenceAt(0), false);
254  1 sg.addSequence(protein.getSequenceAt(2), false);
255  1 sg.setEndRes(protein.getWidth() - 1);
256   
257    /*
258    * Verify the mapped sequence group in dna
259    */
260  1 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
261    proteinView, dnaView);
262  1 assertTrue(mappedGroup.getColourText());
263  1 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
264  1 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
265  1 assertEquals(2, mappedGroup.getSequences().size());
266  1 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
267  1 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(1));
268  1 assertEquals(0, mappedGroup.getStartRes());
269  1 assertEquals(2, mappedGroup.getEndRes()); // 3 columns (1 codon)
270   
271    /*
272    * Verify mapping sequence group from dna to protein
273    */
274  1 sg.clear();
275  1 sg.addSequence(cdna.getSequenceAt(1), false);
276  1 sg.addSequence(cdna.getSequenceAt(0), false);
277  1 sg.setStartRes(0);
278  1 sg.setEndRes(2);
279  1 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
280  1 assertTrue(mappedGroup.getColourText());
281  1 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
282  1 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
283  1 assertEquals(2, mappedGroup.getSequences().size());
284  1 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
285  1 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
286  1 assertEquals(0, mappedGroup.getStartRes());
287  1 assertEquals(0, mappedGroup.getEndRes());
288    }
289   
290    /**
291    * Helper method to load an alignment and ensure dataset sequences are set up.
292    *
293    * @param data
294    * @param format
295    * TODO
296    * @return
297    * @throws IOException
298    */
 
299  14 toggle protected AlignmentI loadAlignment(final String data, FileFormatI format)
300    throws IOException
301    {
302  14 AlignmentI a = new FormatAdapter().readFile(data, DataSourceType.PASTE,
303    format);
304  14 a.setDataset(null);
305  14 return a;
306    }
307   
308    /**
309    * Test mapping a column selection in protein to its dna equivalent
310    *
311    * @throws IOException
312    */
 
313  1 toggle @Test(groups = { "Functional" })
314    public void testMapColumnSelection_proteinToDna() throws IOException
315    {
316  1 setupMappedAlignments();
317   
318  1 ColumnSelection colsel = new ColumnSelection();
319  1 HiddenColumns hidden = new HiddenColumns();
320   
321    /*
322    * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
323    * in dna respectively, overall 0-4
324    */
325  1 colsel.addElement(0);
326  1 ColumnSelection cs = new ColumnSelection();
327  1 HiddenColumns hs = new HiddenColumns();
328  1 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
329    cs, hs);
330  1 assertEquals("[0, 1, 2, 3, 4]", cs.getSelected().toString());
331   
332    /*
333    * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
334    */
335  1 cs.clear();
336  1 colsel.clear();
337  1 colsel.addElement(1);
338  1 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
339    cs, hs);
340  1 assertEquals("[0, 1, 2, 3]", cs.getSelected().toString());
341   
342    /*
343    * Column 2 in protein picks up gaps only - no mapping
344    */
345  1 cs.clear();
346  1 colsel.clear();
347  1 colsel.addElement(2);
348  1 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
349    cs, hs);
350  1 assertEquals("[]", cs.getSelected().toString());
351   
352    /*
353    * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
354    * 6-9, 6-10, 5-8 respectively, overall to 5-10
355    */
356  1 cs.clear();
357  1 colsel.clear();
358  1 colsel.addElement(3);
359  1 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
360    cs, hs);
361  1 assertEquals("[5, 6, 7, 8, 9, 10]", cs.getSelected().toString());
362   
363    /*
364    * Combine selection of columns 1 and 3 to get a discontiguous mapped
365    * selection
366    */
367  1 cs.clear();
368  1 colsel.clear();
369  1 colsel.addElement(1);
370  1 colsel.addElement(3);
371  1 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
372    cs, hs);
373  1 assertEquals("[0, 1, 2, 3, 5, 6, 7, 8, 9, 10]",
374    cs.getSelected().toString());
375    }
376   
377    /**
378    * Set up mappings for tests from 3 dna to 3 protein sequences. Sequences have
379    * offset start positions for a more general test case.
380    *
381    * @throws IOException
382    */
 
383  4 toggle protected void setupMappedAlignments() throws IOException
384    {
385    /*
386    * Map (upper-case = coding):
387    * Seq1/10-18 AC-GctGtC-T to Seq1/40 -K-P
388    * Seq2/20-27 Tc-GA-G-T-T to Seq2/20-27 L--Q
389    * Seq3/30-38 TtTT-AaCGg- to Seq3/60-61\nG--S
390    */
391  4 AlignmentI cdna = loadAlignment(">Seq1/10-18\nAC-GctGtC-T\n"
392    + ">Seq2/20-27\nTc-GA-G-T-Tc\n" + ">Seq3/30-38\nTtTT-AaCGg-\n",
393    FileFormat.Fasta);
394  4 cdna.setDataset(null);
395  4 AlignmentI protein = loadAlignment(
396    ">Seq1/40-41\n-K-P\n>Seq2/50-51\nL--Q\n>Seq3/60-61\nG--S\n",
397    FileFormat.Fasta);
398  4 protein.setDataset(null);
399   
400    // map first dna to first protein seq
401  4 AlignedCodonFrame acf = new AlignedCodonFrame();
402  4 MapList map = new MapList(new int[] { 10, 12, 15, 15, 17, 18 },
403    new int[]
404    { 40, 41 }, 3, 1);
405  4 acf.addMap(cdna.getSequenceAt(0).getDatasetSequence(),
406    protein.getSequenceAt(0).getDatasetSequence(), map);
407   
408    // map second dna to second protein seq
409  4 map = new MapList(new int[] { 20, 20, 22, 23, 24, 26 },
410    new int[]
411    { 50, 51 }, 3, 1);
412  4 acf.addMap(cdna.getSequenceAt(1).getDatasetSequence(),
413    protein.getSequenceAt(1).getDatasetSequence(), map);
414   
415    // map third dna to third protein seq
416  4 map = new MapList(new int[] { 30, 30, 32, 34, 36, 37 },
417    new int[]
418    { 60, 61 }, 3, 1);
419  4 acf.addMap(cdna.getSequenceAt(2).getDatasetSequence(),
420    protein.getSequenceAt(2).getDatasetSequence(), map);
421  4 List<AlignedCodonFrame> acfList = Arrays
422    .asList(new AlignedCodonFrame[]
423    { acf });
424   
425  4 dnaView = new AlignViewport(cdna);
426  4 proteinView = new AlignViewport(protein);
427  4 protein.setCodonFrames(acfList);
428    }
429   
430    /**
431    * Test mapping a column selection in dna to its protein equivalent
432    *
433    * @throws IOException
434    */
 
435  1 toggle @Test(groups = { "Functional" })
436    public void testMapColumnSelection_dnaToProtein() throws IOException
437    {
438  1 setupMappedAlignments();
439   
440  1 ColumnSelection colsel = new ColumnSelection();
441  1 HiddenColumns hidden = new HiddenColumns();
442   
443    /*
444    * Column 0 in dna picks up first bases which map to residue 1, columns 0-1
445    * in protein.
446    */
447  1 ColumnSelection cs = new ColumnSelection();
448  1 HiddenColumns hs = new HiddenColumns();
449  1 colsel.addElement(0);
450  1 MappingUtils.mapColumnSelection(colsel, hidden, dnaView, proteinView,
451    cs, hs);
452  1 assertEquals("[0, 1]", cs.getSelected().toString());
453   
454    /*
455    * Columns 3-5 in dna map to the first residues in protein Seq1, Seq2, and
456    * the first two in Seq3. Overall to columns 0, 1, 3 (col2 is all gaps).
457    */
458  1 colsel.addElement(3);
459  1 colsel.addElement(4);
460  1 colsel.addElement(5);
461  1 cs.clear();
462  1 MappingUtils.mapColumnSelection(colsel, hidden, dnaView, proteinView,
463    cs, hs);
464  1 assertEquals("[0, 1, 3]", cs.getSelected().toString());
465    }
466   
 
467  1 toggle @Test(groups = { "Functional" })
468    public void testMapColumnSelection_null() throws IOException
469    {
470  1 setupMappedAlignments();
471  1 ColumnSelection cs = new ColumnSelection();
472  1 HiddenColumns hs = new HiddenColumns();
473  1 MappingUtils.mapColumnSelection(null, null, dnaView, proteinView, cs,
474    hs);
475  1 assertTrue("mapped selection not empty", cs.getSelected().isEmpty());
476    }
477   
478    /**
479    * Tests for the method that converts a series of [start, end] ranges to
480    * single positions
481    */
 
482  1 toggle @Test(groups = { "Functional" })
483    public void testFlattenRanges()
484    {
485  1 assertEquals("[1, 2, 3, 4]",
486    Arrays.toString(MappingUtils.flattenRanges(new int[]
487    { 1, 4 })));
488  1 assertEquals("[1, 2, 3, 4]",
489    Arrays.toString(MappingUtils.flattenRanges(new int[]
490    { 1, 2, 3, 4 })));
491  1 assertEquals("[1, 2, 3, 4]",
492    Arrays.toString(MappingUtils.flattenRanges(new int[]
493    { 1, 1, 2, 2, 3, 3, 4, 4 })));
494  1 assertEquals("[1, 2, 3, 4, 7, 8, 9, 12]",
495    Arrays.toString(MappingUtils.flattenRanges(new int[]
496    { 1, 4, 7, 9, 12, 12 })));
497    // trailing unpaired start position is ignored:
498  1 assertEquals("[1, 2, 3, 4, 7, 8, 9, 12]",
499    Arrays.toString(MappingUtils.flattenRanges(new int[]
500    { 1, 4, 7, 9, 12, 12, 15 })));
501    }
502   
503    /**
504    * Test mapping a sequence group made of entire columns.
505    *
506    * @throws IOException
507    */
 
508  1 toggle @Test(groups = { "Functional" })
509    public void testMapSequenceGroup_columns() throws IOException
510    {
511    /*
512    * Set up dna and protein Seq1/2/3 with mappings (held on the protein
513    * viewport).
514    */
515  1 AlignmentI cdna = loadAlignment(
516    ">Seq1\nACGGCA\n>Seq2\nTGACAG\n>Seq3\nTACGTA\n",
517    FileFormat.Fasta);
518  1 cdna.setDataset(null);
519  1 AlignmentI protein = loadAlignment(">Seq1\nKA\n>Seq2\nLQ\n>Seq3\nQV\n",
520    FileFormat.Fasta);
521  1 protein.setDataset(null);
522  1 AlignedCodonFrame acf = new AlignedCodonFrame();
523  1 MapList map = new MapList(new int[] { 1, 6 }, new int[] { 1, 2 }, 3, 1);
524  4 for (int seq = 0; seq < 3; seq++)
525    {
526  3 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(),
527    protein.getSequenceAt(seq).getDatasetSequence(), map);
528    }
529  1 List<AlignedCodonFrame> acfList = Arrays
530    .asList(new AlignedCodonFrame[]
531    { acf });
532   
533  1 AlignViewportI dnaView = new AlignViewport(cdna);
534  1 AlignViewportI proteinView = new AlignViewport(protein);
535  1 protein.setCodonFrames(acfList);
536   
537    /*
538    * Select all sequences, column 2 in the protein
539    */
540  1 SequenceGroup sg = new SequenceGroup();
541  1 sg.setColourText(true);
542  1 sg.setIdColour(Color.GREEN);
543  1 sg.setOutlineColour(Color.LIGHT_GRAY);
544  1 sg.addSequence(protein.getSequenceAt(0), false);
545  1 sg.addSequence(protein.getSequenceAt(1), false);
546  1 sg.addSequence(protein.getSequenceAt(2), false);
547  1 sg.setStartRes(1);
548  1 sg.setEndRes(1);
549   
550    /*
551    * Verify the mapped sequence group in dna
552    */
553  1 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
554    proteinView, dnaView);
555  1 assertTrue(mappedGroup.getColourText());
556  1 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
557  1 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
558  1 assertEquals(3, mappedGroup.getSequences().size());
559  1 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
560  1 assertSame(cdna.getSequenceAt(1), mappedGroup.getSequences().get(1));
561  1 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(2));
562  1 assertEquals(3, mappedGroup.getStartRes());
563  1 assertEquals(5, mappedGroup.getEndRes());
564   
565    /*
566    * Verify mapping sequence group from dna to protein
567    */
568  1 sg.clear();
569  1 sg.addSequence(cdna.getSequenceAt(0), false);
570  1 sg.addSequence(cdna.getSequenceAt(1), false);
571  1 sg.addSequence(cdna.getSequenceAt(2), false);
572    // select columns 2 and 3 in DNA which span protein columns 0 and 1
573  1 sg.setStartRes(2);
574  1 sg.setEndRes(3);
575  1 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
576  1 assertTrue(mappedGroup.getColourText());
577  1 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
578  1 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
579  1 assertEquals(3, mappedGroup.getSequences().size());
580  1 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(0));
581  1 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(1));
582  1 assertSame(protein.getSequenceAt(2), mappedGroup.getSequences().get(2));
583  1 assertEquals(0, mappedGroup.getStartRes());
584  1 assertEquals(1, mappedGroup.getEndRes());
585    }
586   
587    /**
588    * Test mapping a sequence group made of a sequences/columns region.
589    *
590    * @throws IOException
591    */
 
592  1 toggle @Test(groups = { "Functional" })
593    public void testMapSequenceGroup_region() throws IOException
594    {
595    /*
596    * Set up gapped dna and protein Seq1/2/3 with mappings (held on the protein
597    * viewport).
598    */
599  1 AlignmentI cdna = loadAlignment(
600    ">Seq1\nA-CG-GC--AT-CA\n>Seq2\n-TG-AC-AG-T-AT\n>Seq3\n-T--ACG-TAAT-G\n",
601    FileFormat.Fasta);
602  1 cdna.setDataset(null);
603  1 AlignmentI protein = loadAlignment(
604    ">Seq1\n-KA-S\n>Seq2\n--L-QY\n>Seq3\nQ-V-M\n",
605    FileFormat.Fasta);
606  1 protein.setDataset(null);
607  1 AlignedCodonFrame acf = new AlignedCodonFrame();
608  1 MapList map = new MapList(new int[] { 1, 9 }, new int[] { 1, 3 }, 3, 1);
609  4 for (int seq = 0; seq < 3; seq++)
610    {
611  3 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(),
612    protein.getSequenceAt(seq).getDatasetSequence(), map);
613    }
614  1 List<AlignedCodonFrame> acfList = Arrays
615    .asList(new AlignedCodonFrame[]
616    { acf });
617   
618  1 AlignViewportI dnaView = new AlignViewport(cdna);
619  1 AlignViewportI proteinView = new AlignViewport(protein);
620  1 protein.setCodonFrames(acfList);
621   
622    /*
623    * Select Seq1 and Seq2 in the protein, column 1 (K/-). Expect mapped
624    * sequence group to cover Seq1, columns 0-3 (ACG). Because the selection
625    * only includes a gap in Seq2 there is no mappable selection region in the
626    * corresponding DNA.
627    */
628  1 SequenceGroup sg = new SequenceGroup();
629  1 sg.setColourText(true);
630  1 sg.setIdColour(Color.GREEN);
631  1 sg.setOutlineColour(Color.LIGHT_GRAY);
632  1 sg.addSequence(protein.getSequenceAt(0), false);
633  1 sg.addSequence(protein.getSequenceAt(1), false);
634  1 sg.setStartRes(1);
635  1 sg.setEndRes(1);
636   
637    /*
638    * Verify the mapped sequence group in dna
639    */
640  1 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
641    proteinView, dnaView);
642  1 assertTrue(mappedGroup.getColourText());
643  1 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
644  1 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
645  1 assertEquals(1, mappedGroup.getSequences().size());
646  1 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
647    // Seq2 in protein has a gap in column 1 - ignored
648    // Seq1 has K which should map to columns 0-3 in Seq1
649  1 assertEquals(0, mappedGroup.getStartRes());
650  1 assertEquals(3, mappedGroup.getEndRes());
651   
652    /*
653    * Now select cols 2-4 in protein. These cover Seq1:AS Seq2:LQ Seq3:VM which
654    * extend over DNA columns 3-12, 1-7, 6-13 respectively, or 1-13 overall.
655    */
656  1 sg.setStartRes(2);
657  1 sg.setEndRes(4);
658  1 mappedGroup = MappingUtils.mapSequenceGroup(sg, proteinView, dnaView);
659  1 assertEquals(1, mappedGroup.getStartRes());
660  1 assertEquals(13, mappedGroup.getEndRes());
661   
662    /*
663    * Verify mapping sequence group from dna to protein
664    */
665  1 sg.clear();
666  1 sg.addSequence(cdna.getSequenceAt(0), false);
667   
668    // select columns 4,5 - includes Seq1:codon2 (A) only
669  1 sg.setStartRes(4);
670  1 sg.setEndRes(5);
671  1 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
672  1 assertEquals(2, mappedGroup.getStartRes());
673  1 assertEquals(2, mappedGroup.getEndRes());
674   
675    // add Seq2 to dna selection cols 4-5 include codons 1 and 2 (LQ)
676  1 sg.addSequence(cdna.getSequenceAt(1), false);
677  1 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
678  1 assertEquals(2, mappedGroup.getStartRes());
679  1 assertEquals(4, mappedGroup.getEndRes());
680   
681    // add Seq3 to dna selection cols 4-5 include codon 1 (Q)
682  1 sg.addSequence(cdna.getSequenceAt(2), false);
683  1 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
684  1 assertEquals(0, mappedGroup.getStartRes());
685  1 assertEquals(4, mappedGroup.getEndRes());
686    }
687   
 
688  1 toggle @Test(groups = { "Functional" })
689    public void testFindMappingsForSequence()
690    {
691  1 SequenceI seq1 = new Sequence("Seq1", "ABC");
692  1 SequenceI seq2 = new Sequence("Seq2", "ABC");
693  1 SequenceI seq3 = new Sequence("Seq3", "ABC");
694  1 SequenceI seq4 = new Sequence("Seq4", "ABC");
695  1 seq1.createDatasetSequence();
696  1 seq2.createDatasetSequence();
697  1 seq3.createDatasetSequence();
698  1 seq4.createDatasetSequence();
699   
700    /*
701    * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1
702    */
703  1 AlignedCodonFrame acf1 = new AlignedCodonFrame();
704  1 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
705  1 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
706  1 AlignedCodonFrame acf2 = new AlignedCodonFrame();
707  1 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
708  1 AlignedCodonFrame acf3 = new AlignedCodonFrame();
709  1 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
710   
711  1 List<AlignedCodonFrame> mappings = new ArrayList<>();
712  1 mappings.add(acf1);
713  1 mappings.add(acf2);
714  1 mappings.add(acf3);
715   
716    /*
717    * Seq1 has three mappings
718    */
719  1 List<AlignedCodonFrame> result = MappingUtils
720    .findMappingsForSequence(seq1, mappings);
721  1 assertEquals(3, result.size());
722  1 assertTrue(result.contains(acf1));
723  1 assertTrue(result.contains(acf2));
724  1 assertTrue(result.contains(acf3));
725   
726    /*
727    * Seq2 has two mappings
728    */
729  1 result = MappingUtils.findMappingsForSequence(seq2, mappings);
730  1 assertEquals(2, result.size());
731  1 assertTrue(result.contains(acf1));
732  1 assertTrue(result.contains(acf2));
733   
734    /*
735    * Seq3 has one mapping
736    */
737  1 result = MappingUtils.findMappingsForSequence(seq3, mappings);
738  1 assertEquals(1, result.size());
739  1 assertTrue(result.contains(acf3));
740   
741    /*
742    * Seq4 has no mappings
743    */
744  1 result = MappingUtils.findMappingsForSequence(seq4, mappings);
745  1 assertEquals(0, result.size());
746   
747  1 result = MappingUtils.findMappingsForSequence(null, mappings);
748  1 assertEquals(0, result.size());
749   
750  1 result = MappingUtils.findMappingsForSequence(seq1, null);
751  1 assertEquals(0, result.size());
752   
753  1 result = MappingUtils.findMappingsForSequence(null, null);
754  1 assertEquals(0, result.size());
755    }
756   
757    /**
758    * just like the one above, but this time, we provide a set of sequences to
759    * subselect the mapping search
760    */
 
761  1 toggle @Test(groups = { "Functional" })
762    public void testFindMappingsForSequenceAndOthers()
763    {
764  1 SequenceI seq1 = new Sequence("Seq1", "ABC");
765  1 SequenceI seq2 = new Sequence("Seq2", "ABC");
766  1 SequenceI seq3 = new Sequence("Seq3", "ABC");
767  1 SequenceI seq4 = new Sequence("Seq4", "ABC");
768  1 seq1.createDatasetSequence();
769  1 seq2.createDatasetSequence();
770  1 seq3.createDatasetSequence();
771  1 seq4.createDatasetSequence();
772   
773    /*
774    * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1, seq3 to seq4
775    */
776  1 AlignedCodonFrame acf1 = new AlignedCodonFrame();
777  1 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
778  1 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
779  1 AlignedCodonFrame acf2 = new AlignedCodonFrame();
780  1 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
781  1 AlignedCodonFrame acf3 = new AlignedCodonFrame();
782  1 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
783  1 AlignedCodonFrame acf4 = new AlignedCodonFrame();
784  1 acf4.addMap(seq3.getDatasetSequence(), seq4.getDatasetSequence(), map);
785   
786  1 List<AlignedCodonFrame> mappings = new ArrayList<>();
787  1 mappings.add(acf1);
788  1 mappings.add(acf2);
789  1 mappings.add(acf3);
790  1 mappings.add(acf4);
791   
792    /*
793    * test for null args
794    */
795  1 List<AlignedCodonFrame> result = MappingUtils
796    .findMappingsForSequenceAndOthers(null, mappings,
797    Arrays.asList(new SequenceI[]
798    { seq1, seq2 }));
799  1 assertTrue(result.isEmpty());
800   
801  1 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, null,
802    Arrays.asList(new SequenceI[]
803    { seq1, seq2 }));
804  1 assertTrue(result.isEmpty());
805   
806    /*
807    * Seq1 has three mappings, but filter argument will only accept
808    * those to seq2
809    */
810  1 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, mappings,
811    Arrays.asList(new SequenceI[]
812    { seq1, seq2, seq1.getDatasetSequence() }));
813  1 assertEquals(2, result.size());
814  1 assertTrue(result.contains(acf1));
815  1 assertTrue(result.contains(acf2));
816  1 assertFalse("Did not expect to find mapping acf3 - subselect failed",
817    result.contains(acf3));
818  1 assertFalse(
819    "Did not expect to find mapping acf4 - doesn't involve sequence",
820    result.contains(acf4));
821   
822    /*
823    * and verify the no filter case
824    */
825  1 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, mappings,
826    null);
827  1 assertEquals(3, result.size());
828  1 assertTrue(result.contains(acf1));
829  1 assertTrue(result.contains(acf2));
830  1 assertTrue(result.contains(acf3));
831    }
832   
 
833  1 toggle @Test(groups = { "Functional" })
834    public void testMapEditCommand()
835    {
836  1 SequenceI dna = new Sequence("Seq1", "---ACG---GCATCA", 8, 16);
837  1 SequenceI protein = new Sequence("Seq2", "-T-AS", 5, 7);
838  1 dna.createDatasetSequence();
839  1 protein.createDatasetSequence();
840  1 AlignedCodonFrame acf = new AlignedCodonFrame();
841  1 MapList map = new MapList(new int[] { 8, 16 }, new int[] { 5, 7 }, 3,
842    1);
843  1 acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
844  1 List<AlignedCodonFrame> mappings = new ArrayList<>();
845  1 mappings.add(acf);
846   
847  1 AlignmentI prot = new Alignment(new SequenceI[] { protein });
848  1 prot.setCodonFrames(mappings);
849  1 AlignmentI nuc = new Alignment(new SequenceI[] { dna });
850   
851    /*
852    * construct and perform the edit command to turn "-T-AS" in to "-T-A--S"
853    * i.e. insert two gaps at column 4
854    */
855  1 EditCommand ec = new EditCommand();
856  1 final Edit edit = ec.new Edit(Action.INSERT_GAP,
857    new SequenceI[]
858    { protein }, 4, 2, '-');
859  1 ec.appendEdit(edit, prot, true, null);
860   
861    /*
862    * the mapped edit command should be to insert 6 gaps before base 4 in the
863    * nucleotide sequence, which corresponds to aligned column 12 in the dna
864    */
865  1 EditCommand mappedEdit = MappingUtils.mapEditCommand(ec, false, nuc,
866    '-', mappings);
867  1 assertEquals(1, mappedEdit.getEdits().size());
868  1 Edit e = mappedEdit.getEdits().get(0);
869  1 assertEquals(1, e.getSequences().length);
870  1 assertEquals(dna, e.getSequences()[0]);
871  1 assertEquals(12, e.getPosition());
872  1 assertEquals(6, e.getNumber());
873    }
874   
875    /**
876    * Tests for the method that converts a series of [start, end] ranges to
877    * single positions, where the mapping is to a reverse strand i.e. start is
878    * greater than end point mapped to
879    */
 
880  1 toggle @Test(groups = { "Functional" })
881    public void testFlattenRanges_reverseStrand()
882    {
883  1 assertEquals("[4, 3, 2, 1]",
884    Arrays.toString(MappingUtils.flattenRanges(new int[]
885    { 4, 1 })));
886  1 assertEquals("[4, 3, 2, 1]",
887    Arrays.toString(MappingUtils.flattenRanges(new int[]
888    { 4, 3, 2, 1 })));
889  1 assertEquals("[4, 3, 2, 1]",
890    Arrays.toString(MappingUtils.flattenRanges(new int[]
891    { 4, 4, 3, 3, 2, 2, 1, 1 })));
892  1 assertEquals("[12, 9, 8, 7, 4, 3, 2, 1]",
893    Arrays.toString(MappingUtils.flattenRanges(new int[]
894    { 12, 12, 9, 7, 4, 1 })));
895    // forwards and backwards anyone?
896  1 assertEquals("[4, 5, 6, 3, 2, 1]",
897    Arrays.toString(MappingUtils.flattenRanges(new int[]
898    { 4, 6, 3, 1 })));
899    // backwards and forwards
900  1 assertEquals("[3, 2, 1, 4, 5, 6]",
901    Arrays.toString(MappingUtils.flattenRanges(new int[]
902    { 3, 1, 4, 6 })));
903    // trailing unpaired start position is ignored:
904  1 assertEquals("[12, 9, 8, 7, 4, 3, 2]",
905    Arrays.toString(MappingUtils.flattenRanges(new int[]
906    { 12, 12, 9, 7, 4, 2, 1 })));
907    }
908   
909    /**
910    * Test mapping a column selection including hidden columns
911    *
912    * @throws IOException
913    */
 
914  1 toggle @Test(groups = { "Functional" })
915    public void testMapColumnSelection_hiddenColumns() throws IOException
916    {
917  1 setupMappedAlignments();
918   
919  1 ColumnSelection proteinSelection = new ColumnSelection();
920  1 HiddenColumns hiddenCols = new HiddenColumns();
921   
922    /*
923    * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
924    * in dna respectively, overall 0-4
925    */
926  1 proteinSelection.hideSelectedColumns(0, hiddenCols);
927  1 ColumnSelection dnaSelection = new ColumnSelection();
928  1 HiddenColumns dnaHidden = new HiddenColumns();
929  1 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
930    proteinView, dnaView, dnaSelection, dnaHidden);
931  1 assertEquals("[]", dnaSelection.getSelected().toString());
932  1 Iterator<int[]> regions = dnaHidden.iterator();
933  1 assertEquals(1, dnaHidden.getNumberOfRegions());
934  1 assertEquals("[0, 4]", Arrays.toString(regions.next()));
935   
936    /*
937    * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
938    */
939  1 dnaSelection = new ColumnSelection();
940  1 dnaHidden = new HiddenColumns();
941  1 hiddenCols.revealAllHiddenColumns(proteinSelection);
942    // the unhidden columns are now marked selected!
943  1 assertEquals("[0]", proteinSelection.getSelected().toString());
944    // deselect these or hideColumns will be expanded to include 0
945  1 proteinSelection.clear();
946  1 proteinSelection.hideSelectedColumns(1, hiddenCols);
947  1 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
948    proteinView, dnaView, dnaSelection, dnaHidden);
949  1 regions = dnaHidden.iterator();
950  1 assertEquals(1, dnaHidden.getNumberOfRegions());
951  1 assertEquals("[0, 3]", Arrays.toString(regions.next()));
952   
953    /*
954    * Column 2 in protein picks up gaps only - no mapping
955    */
956  1 dnaSelection = new ColumnSelection();
957  1 dnaHidden = new HiddenColumns();
958  1 hiddenCols.revealAllHiddenColumns(proteinSelection);
959  1 proteinSelection.clear();
960  1 proteinSelection.hideSelectedColumns(2, hiddenCols);
961  1 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
962    proteinView, dnaView, dnaSelection, dnaHidden);
963  1 assertEquals(0, dnaHidden.getNumberOfRegions());
964   
965    /*
966    * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
967    * 6-9, 6-10, 5-8 respectively, overall to 5-10
968    */
969  1 dnaSelection = new ColumnSelection();
970  1 dnaHidden = new HiddenColumns();
971  1 hiddenCols.revealAllHiddenColumns(proteinSelection);
972  1 proteinSelection.clear();
973  1 proteinSelection.hideSelectedColumns(3, hiddenCols); // 5-10 hidden in dna
974  1 proteinSelection.addElement(1); // 0-3 selected in dna
975  1 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
976    proteinView, dnaView, dnaSelection, dnaHidden);
977  1 assertEquals("[0, 1, 2, 3]", dnaSelection.getSelected().toString());
978  1 regions = dnaHidden.iterator();
979  1 assertEquals(1, dnaHidden.getNumberOfRegions());
980  1 assertEquals("[5, 10]", Arrays.toString(regions.next()));
981   
982    /*
983    * Combine hiding columns 1 and 3 to get discontiguous hidden columns
984    */
985  1 dnaSelection = new ColumnSelection();
986  1 dnaHidden = new HiddenColumns();
987  1 hiddenCols.revealAllHiddenColumns(proteinSelection);
988  1 proteinSelection.clear();
989  1 proteinSelection.hideSelectedColumns(1, hiddenCols);
990  1 proteinSelection.hideSelectedColumns(3, hiddenCols);
991  1 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
992    proteinView, dnaView, dnaSelection, dnaHidden);
993  1 regions = dnaHidden.iterator();
994  1 assertEquals(2, dnaHidden.getNumberOfRegions());
995  1 assertEquals("[0, 3]", Arrays.toString(regions.next()));
996  1 assertEquals("[5, 10]", Arrays.toString(regions.next()));
997    }
998   
 
999  1 toggle @Test(groups = { "Functional" })
1000    public void testGetLength()
1001    {
1002  1 assertEquals(0, MappingUtils.getLength(null));
1003   
1004    /*
1005    * [start, end] ranges
1006    */
1007  1 List<int[]> ranges = new ArrayList<>();
1008  1 assertEquals(0, MappingUtils.getLength(ranges));
1009  1 ranges.add(new int[] { 1, 1 });
1010  1 assertEquals(1, MappingUtils.getLength(ranges));
1011  1 ranges.add(new int[] { 2, 10 });
1012  1 assertEquals(10, MappingUtils.getLength(ranges));
1013  1 ranges.add(new int[] { 20, 10 });
1014  1 assertEquals(21, MappingUtils.getLength(ranges));
1015   
1016    /*
1017    * [start, end, start, end...] ranges
1018    */
1019  1 ranges.clear();
1020  1 ranges.add(new int[] { 1, 5, 8, 4 });
1021  1 ranges.add(new int[] { 8, 2 });
1022  1 ranges.add(new int[] { 12, 12 });
1023  1 assertEquals(18, MappingUtils.getLength(ranges));
1024    }
1025   
 
1026  1 toggle @Test(groups = { "Functional" })
1027    public void testContains()
1028    {
1029  1 assertFalse(MappingUtils.contains(null, 1));
1030  1 List<int[]> ranges = new ArrayList<>();
1031  1 assertFalse(MappingUtils.contains(ranges, 1));
1032   
1033  1 ranges.add(new int[] { 1, 4 });
1034  1 ranges.add(new int[] { 6, 6 });
1035  1 ranges.add(new int[] { 8, 10 });
1036  1 ranges.add(new int[] { 30, 20 });
1037  1 ranges.add(new int[] { -16, -44 });
1038   
1039  1 assertFalse(MappingUtils.contains(ranges, 0));
1040  1 assertTrue(MappingUtils.contains(ranges, 1));
1041  1 assertTrue(MappingUtils.contains(ranges, 2));
1042  1 assertTrue(MappingUtils.contains(ranges, 3));
1043  1 assertTrue(MappingUtils.contains(ranges, 4));
1044  1 assertFalse(MappingUtils.contains(ranges, 5));
1045   
1046  1 assertTrue(MappingUtils.contains(ranges, 6));
1047  1 assertFalse(MappingUtils.contains(ranges, 7));
1048   
1049  1 assertTrue(MappingUtils.contains(ranges, 8));
1050  1 assertTrue(MappingUtils.contains(ranges, 9));
1051  1 assertTrue(MappingUtils.contains(ranges, 10));
1052   
1053  1 assertFalse(MappingUtils.contains(ranges, 31));
1054  1 assertTrue(MappingUtils.contains(ranges, 30));
1055  1 assertTrue(MappingUtils.contains(ranges, 29));
1056  1 assertTrue(MappingUtils.contains(ranges, 20));
1057  1 assertFalse(MappingUtils.contains(ranges, 19));
1058   
1059  1 assertFalse(MappingUtils.contains(ranges, -15));
1060  1 assertTrue(MappingUtils.contains(ranges, -16));
1061  1 assertTrue(MappingUtils.contains(ranges, -44));
1062  1 assertFalse(MappingUtils.contains(ranges, -45));
1063    }
1064   
1065    /**
1066    * Test the method that drops positions from the start of a mapped range
1067    */
 
1068  1 toggle @Test(groups = "Functional")
1069    public void testRemoveStartPositions()
1070    {
1071  1 int[] ranges = new int[] { 1, 10 };
1072  1 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
1073  1 assertEquals("[1, 10]", Arrays.toString(adjusted));
1074   
1075  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1076  1 assertEquals("[2, 10]", Arrays.toString(adjusted));
1077  1 assertEquals("[1, 10]", Arrays.toString(ranges));
1078   
1079  1 ranges = adjusted;
1080  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1081  1 assertEquals("[3, 10]", Arrays.toString(adjusted));
1082  1 assertEquals("[2, 10]", Arrays.toString(ranges));
1083   
1084  1 ranges = new int[] { 2, 3, 10, 12 };
1085  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1086  1 assertEquals("[3, 3, 10, 12]", Arrays.toString(adjusted));
1087  1 assertEquals("[2, 3, 10, 12]", Arrays.toString(ranges));
1088   
1089  1 ranges = new int[] { 2, 2, 8, 12 };
1090  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1091  1 assertEquals("[8, 12]", Arrays.toString(adjusted));
1092  1 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
1093   
1094  1 ranges = new int[] { 2, 2, 8, 12 };
1095  1 adjusted = MappingUtils.removeStartPositions(2, ranges);
1096  1 assertEquals("[9, 12]", Arrays.toString(adjusted));
1097  1 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
1098   
1099  1 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
1100  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1101  1 assertEquals("[4, 4, 9, 12]", Arrays.toString(adjusted));
1102  1 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
1103   
1104  1 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
1105  1 adjusted = MappingUtils.removeStartPositions(2, ranges);
1106  1 assertEquals("[9, 12]", Arrays.toString(adjusted));
1107  1 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
1108   
1109  1 ranges = new int[] { 2, 3, 9, 12 };
1110  1 adjusted = MappingUtils.removeStartPositions(3, ranges);
1111  1 assertEquals("[10, 12]", Arrays.toString(adjusted));
1112  1 assertEquals("[2, 3, 9, 12]", Arrays.toString(ranges));
1113    }
1114   
1115    /**
1116    * Test the method that drops positions from the start of a mapped range, on
1117    * the reverse strand
1118    */
 
1119  1 toggle @Test(groups = "Functional")
1120    public void testRemoveStartPositions_reverseStrand()
1121    {
1122  1 int[] ranges = new int[] { 10, 1 };
1123  1 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
1124  1 assertEquals("[10, 1]", Arrays.toString(adjusted));
1125  1 assertEquals("[10, 1]", Arrays.toString(ranges));
1126   
1127  1 ranges = adjusted;
1128  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1129  1 assertEquals("[9, 1]", Arrays.toString(adjusted));
1130  1 assertEquals("[10, 1]", Arrays.toString(ranges));
1131   
1132  1 ranges = adjusted;
1133  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1134  1 assertEquals("[8, 1]", Arrays.toString(adjusted));
1135  1 assertEquals("[9, 1]", Arrays.toString(ranges));
1136   
1137  1 ranges = new int[] { 12, 11, 9, 6 };
1138  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1139  1 assertEquals("[11, 11, 9, 6]", Arrays.toString(adjusted));
1140  1 assertEquals("[12, 11, 9, 6]", Arrays.toString(ranges));
1141   
1142  1 ranges = new int[] { 12, 12, 8, 4 };
1143  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1144  1 assertEquals("[8, 4]", Arrays.toString(adjusted));
1145  1 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1146   
1147  1 ranges = new int[] { 12, 12, 8, 4 };
1148  1 adjusted = MappingUtils.removeStartPositions(2, ranges);
1149  1 assertEquals("[7, 4]", Arrays.toString(adjusted));
1150  1 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1151   
1152  1 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1153  1 adjusted = MappingUtils.removeStartPositions(1, ranges);
1154  1 assertEquals("[10, 10, 8, 4]", Arrays.toString(adjusted));
1155  1 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1156   
1157  1 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1158  1 adjusted = MappingUtils.removeStartPositions(2, ranges);
1159  1 assertEquals("[8, 4]", Arrays.toString(adjusted));
1160  1 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1161   
1162  1 ranges = new int[] { 12, 11, 8, 4 };
1163  1 adjusted = MappingUtils.removeStartPositions(3, ranges);
1164  1 assertEquals("[7, 4]", Arrays.toString(adjusted));
1165  1 assertEquals("[12, 11, 8, 4]", Arrays.toString(ranges));
1166    }
1167   
 
1168  1 toggle @Test(groups = { "Functional" })
1169    public void testRangeContains()
1170    {
1171    /*
1172    * both forward ranges
1173    */
1174  1 assertTrue(
1175    MappingUtils.rangeContains(new int[]
1176    { 1, 10 }, new int[] { 1, 10 }));
1177  1 assertTrue(
1178    MappingUtils.rangeContains(new int[]
1179    { 1, 10 }, new int[] { 2, 10 }));
1180  1 assertTrue(
1181    MappingUtils.rangeContains(new int[]
1182    { 1, 10 }, new int[] { 1, 9 }));
1183  1 assertTrue(
1184    MappingUtils.rangeContains(new int[]
1185    { 1, 10 }, new int[] { 4, 5 }));
1186  1 assertFalse(
1187    MappingUtils.rangeContains(new int[]
1188    { 1, 10 }, new int[] { 0, 9 }));
1189  1 assertFalse(
1190    MappingUtils.rangeContains(new int[]
1191    { 1, 10 }, new int[] { -10, -9 }));
1192  1 assertFalse(
1193    MappingUtils.rangeContains(new int[]
1194    { 1, 10 }, new int[] { 1, 11 }));
1195  1 assertFalse(
1196    MappingUtils.rangeContains(new int[]
1197    { 1, 10 }, new int[] { 11, 12 }));
1198   
1199    /*
1200    * forward range, reverse query
1201    */
1202  1 assertTrue(
1203    MappingUtils.rangeContains(new int[]
1204    { 1, 10 }, new int[] { 10, 1 }));
1205  1 assertTrue(
1206    MappingUtils.rangeContains(new int[]
1207    { 1, 10 }, new int[] { 9, 1 }));
1208  1 assertTrue(
1209    MappingUtils.rangeContains(new int[]
1210    { 1, 10 }, new int[] { 10, 2 }));
1211  1 assertTrue(
1212    MappingUtils.rangeContains(new int[]
1213    { 1, 10 }, new int[] { 5, 5 }));
1214  1 assertFalse(
1215    MappingUtils.rangeContains(new int[]
1216    { 1, 10 }, new int[] { 11, 1 }));
1217  1 assertFalse(
1218    MappingUtils.rangeContains(new int[]
1219    { 1, 10 }, new int[] { 10, 0 }));
1220   
1221    /*
1222    * reverse range, forward query
1223    */
1224  1 assertTrue(
1225    MappingUtils.rangeContains(new int[]
1226    { 10, 1 }, new int[] { 1, 10 }));
1227  1 assertTrue(
1228    MappingUtils.rangeContains(new int[]
1229    { 10, 1 }, new int[] { 1, 9 }));
1230  1 assertTrue(
1231    MappingUtils.rangeContains(new int[]
1232    { 10, 1 }, new int[] { 2, 10 }));
1233  1 assertTrue(
1234    MappingUtils.rangeContains(new int[]
1235    { 10, 1 }, new int[] { 6, 6 }));
1236  1 assertFalse(
1237    MappingUtils.rangeContains(new int[]
1238    { 10, 1 }, new int[] { 6, 11 }));
1239  1 assertFalse(
1240    MappingUtils.rangeContains(new int[]
1241    { 10, 1 }, new int[] { 11, 20 }));
1242  1 assertFalse(
1243    MappingUtils.rangeContains(new int[]
1244    { 10, 1 }, new int[] { -3, -2 }));
1245   
1246    /*
1247    * both reverse
1248    */
1249  1 assertTrue(
1250    MappingUtils.rangeContains(new int[]
1251    { 10, 1 }, new int[] { 10, 1 }));
1252  1 assertTrue(
1253    MappingUtils.rangeContains(new int[]
1254    { 10, 1 }, new int[] { 9, 1 }));
1255  1 assertTrue(
1256    MappingUtils.rangeContains(new int[]
1257    { 10, 1 }, new int[] { 10, 2 }));
1258  1 assertTrue(
1259    MappingUtils.rangeContains(new int[]
1260    { 10, 1 }, new int[] { 3, 3 }));
1261  1 assertFalse(
1262    MappingUtils.rangeContains(new int[]
1263    { 10, 1 }, new int[] { 11, 1 }));
1264  1 assertFalse(
1265    MappingUtils.rangeContains(new int[]
1266    { 10, 1 }, new int[] { 10, 0 }));
1267  1 assertFalse(
1268    MappingUtils.rangeContains(new int[]
1269    { 10, 1 }, new int[] { 12, 11 }));
1270  1 assertFalse(
1271    MappingUtils.rangeContains(new int[]
1272    { 10, 1 }, new int[] { -5, -8 }));
1273   
1274    /*
1275    * bad arguments
1276    */
1277  1 assertFalse(
1278    MappingUtils.rangeContains(new int[]
1279    { 1, 10, 12 }, new int[] { 1, 10 }));
1280  1 assertFalse(
1281    MappingUtils.rangeContains(new int[]
1282    { 1, 10 }, new int[] { 1 }));
1283  1 assertFalse(MappingUtils.rangeContains(new int[] { 1, 10 }, null));
1284  1 assertFalse(MappingUtils.rangeContains(null, new int[] { 1, 10 }));
1285    }
1286   
 
1287  1 toggle @Test(groups = "Functional")
1288    public void testRemoveEndPositions()
1289    {
1290  1 List<int[]> ranges = new ArrayList<>();
1291   
1292    /*
1293    * case 1: truncate last range
1294    */
1295  1 ranges.add(new int[] { 1, 10 });
1296  1 ranges.add(new int[] { 20, 30 });
1297  1 MappingUtils.removeEndPositions(5, ranges);
1298  1 assertEquals(2, ranges.size());
1299  1 assertEquals(25, ranges.get(1)[1]);
1300   
1301    /*
1302    * case 2: remove last range
1303    */
1304  1 ranges.clear();
1305  1 ranges.add(new int[] { 1, 10 });
1306  1 ranges.add(new int[] { 20, 22 });
1307  1 MappingUtils.removeEndPositions(3, ranges);
1308  1 assertEquals(1, ranges.size());
1309  1 assertEquals(10, ranges.get(0)[1]);
1310   
1311    /*
1312    * case 3: truncate penultimate range
1313    */
1314  1 ranges.clear();
1315  1 ranges.add(new int[] { 1, 10 });
1316  1 ranges.add(new int[] { 20, 21 });
1317  1 MappingUtils.removeEndPositions(3, ranges);
1318  1 assertEquals(1, ranges.size());
1319  1 assertEquals(9, ranges.get(0)[1]);
1320   
1321    /*
1322    * case 4: remove last two ranges
1323    */
1324  1 ranges.clear();
1325  1 ranges.add(new int[] { 1, 10 });
1326  1 ranges.add(new int[] { 20, 20 });
1327  1 ranges.add(new int[] { 30, 30 });
1328  1 MappingUtils.removeEndPositions(3, ranges);
1329  1 assertEquals(1, ranges.size());
1330  1 assertEquals(9, ranges.get(0)[1]);
1331    }
1332   
 
1333  1 toggle @Test(groups = "Functional")
1334    public void testFindOverlap()
1335    {
1336  1 List<int[]> ranges = new ArrayList<>();
1337  1 ranges.add(new int[] { 4, 8 });
1338  1 ranges.add(new int[] { 10, 12 });
1339  1 ranges.add(new int[] { 16, 19 });
1340   
1341  1 int[] overlap = MappingUtils.findOverlap(ranges, 5, 13);
1342  1 assertArrayEquals(overlap, new int[] { 5, 12 });
1343  1 overlap = MappingUtils.findOverlap(ranges, -100, 100);
1344  1 assertArrayEquals(overlap, new int[] { 4, 19 });
1345  1 overlap = MappingUtils.findOverlap(ranges, 7, 17);
1346  1 assertArrayEquals(overlap, new int[] { 7, 17 });
1347  1 overlap = MappingUtils.findOverlap(ranges, 13, 15);
1348  1 assertNull(overlap);
1349    }
1350   
1351    /**
1352    * Test mapping a sequence group where sequences in and outside the group
1353    * share a dataset sequence (e.g. alternative CDS for the same gene)
1354    * <p>
1355    * This scenario doesn't arise after JAL-3763 changes, but test left as still
1356    * valid
1357    *
1358    * @throws IOException
1359    */
 
1360  1 toggle @Test(groups = { "Functional" })
1361    public void testMapSequenceGroup_sharedDataset() throws IOException
1362    {
1363    /*
1364    * Set up dna and protein Seq1/2/3 with mappings (held on the protein
1365    * viewport). CDS sequences share the same 'gene' dataset sequence.
1366    */
1367  1 SequenceI dna = new Sequence("dna", "aaatttgggcccaaatttgggccc");
1368  1 SequenceI cds1 = new Sequence("cds1/1-6", "aaattt");
1369  1 SequenceI cds2 = new Sequence("cds1/4-9", "tttggg");
1370  1 SequenceI cds3 = new Sequence("cds1/19-24", "gggccc");
1371   
1372  1 cds1.setDatasetSequence(dna);
1373  1 cds2.setDatasetSequence(dna);
1374  1 cds3.setDatasetSequence(dna);
1375   
1376  1 SequenceI pep1 = new Sequence("pep1", "KF");
1377  1 SequenceI pep2 = new Sequence("pep2", "FG");
1378  1 SequenceI pep3 = new Sequence("pep3", "GP");
1379  1 pep1.createDatasetSequence();
1380  1 pep2.createDatasetSequence();
1381  1 pep3.createDatasetSequence();
1382   
1383    /*
1384    * add mappings from coding positions of dna to respective peptides
1385    */
1386  1 AlignedCodonFrame acf = new AlignedCodonFrame();
1387  1 acf.addMap(dna, pep1,
1388    new MapList(new int[]
1389    { 1, 6 }, new int[] { 1, 2 }, 3, 1));
1390  1 acf.addMap(dna, pep2,
1391    new MapList(new int[]
1392    { 4, 9 }, new int[] { 1, 2 }, 3, 1));
1393  1 acf.addMap(dna, pep3,
1394    new MapList(new int[]
1395    { 19, 24 }, new int[] { 1, 2 }, 3, 1));
1396   
1397  1 List<AlignedCodonFrame> acfList = Arrays
1398    .asList(new AlignedCodonFrame[]
1399    { acf });
1400   
1401  1 AlignmentI cdna = new Alignment(new SequenceI[] { cds1, cds2, cds3 });
1402  1 AlignmentI protein = new Alignment(
1403    new SequenceI[]
1404    { pep1, pep2, pep3 });
1405  1 AlignViewportI cdnaView = new AlignViewport(cdna);
1406  1 AlignViewportI peptideView = new AlignViewport(protein);
1407  1 protein.setCodonFrames(acfList);
1408   
1409    /*
1410    * Select pep1 and pep3 in the protein alignment
1411    */
1412  1 SequenceGroup sg = new SequenceGroup();
1413  1 sg.setColourText(true);
1414  1 sg.setIdColour(Color.GREEN);
1415  1 sg.setOutlineColour(Color.LIGHT_GRAY);
1416  1 sg.addSequence(pep1, false);
1417  1 sg.addSequence(pep3, false);
1418  1 sg.setEndRes(protein.getWidth() - 1);
1419   
1420    /*
1421    * Verify the mapped sequence group in dna is cds1 and cds3
1422    */
1423  1 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
1424    peptideView, cdnaView);
1425  1 assertTrue(mappedGroup.getColourText());
1426  1 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
1427  1 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
1428  1 assertEquals(2, mappedGroup.getSequences().size());
1429  1 assertSame(cds1, mappedGroup.getSequences().get(0));
1430  1 assertSame(cds3, mappedGroup.getSequences().get(1));
1431    // columns 1-6 selected (0-5 base zero)
1432  1 assertEquals(0, mappedGroup.getStartRes());
1433  1 assertEquals(5, mappedGroup.getEndRes());
1434   
1435    /*
1436    * Select mapping sequence group from dna to protein
1437    */
1438  1 sg.clear();
1439  1 sg.addSequence(cds2, false);
1440  1 sg.addSequence(cds1, false);
1441  1 sg.setStartRes(0);
1442  1 sg.setEndRes(cdna.getWidth() - 1);
1443  1 mappedGroup = MappingUtils.mapSequenceGroup(sg, cdnaView, peptideView);
1444  1 assertTrue(mappedGroup.getColourText());
1445  1 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
1446  1 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
1447  1 assertEquals(2, mappedGroup.getSequences().size());
1448  1 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
1449  1 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
1450  1 assertEquals(0, mappedGroup.getStartRes());
1451  1 assertEquals(1, mappedGroup.getEndRes()); // two columns
1452    }
1453    }