2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertSame;
26 import static org.testng.AssertJUnit.assertTrue;
27 import static org.testng.AssertJUnit.fail;
29 import java.awt.Color;
30 import java.io.IOException;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Iterator;
34 import java.util.List;
36 import org.testng.annotations.BeforeClass;
37 import org.testng.annotations.Test;
39 import jalview.api.AlignViewportI;
40 import jalview.commands.EditCommand;
41 import jalview.commands.EditCommand.Action;
42 import jalview.commands.EditCommand.Edit;
43 import jalview.datamodel.AlignedCodonFrame;
44 import jalview.datamodel.Alignment;
45 import jalview.datamodel.AlignmentI;
46 import jalview.datamodel.ColumnSelection;
47 import jalview.datamodel.HiddenColumns;
48 import jalview.datamodel.SearchResultMatchI;
49 import jalview.datamodel.SearchResultsI;
50 import jalview.datamodel.Sequence;
51 import jalview.datamodel.SequenceGroup;
52 import jalview.datamodel.SequenceI;
53 import jalview.gui.AlignViewport;
54 import jalview.gui.JvOptionPane;
55 import jalview.io.DataSourceType;
56 import jalview.io.FileFormat;
57 import jalview.io.FileFormatI;
58 import jalview.io.FormatAdapter;
60 public class MappingUtilsTest
63 @BeforeClass(alwaysRun = true)
64 public void setUpJvOptionPane()
66 JvOptionPane.setInteractiveMode(false);
67 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
70 private AlignViewportI dnaView;
72 private AlignViewportI proteinView;
75 * Simple test of mapping with no intron involved.
77 @Test(groups = { "Functional" })
78 public void testBuildSearchResults()
80 final Sequence seq1 = new Sequence("Seq1/5-10", "C-G-TA-GC");
81 seq1.createDatasetSequence();
83 final Sequence aseq1 = new Sequence("Seq1/12-13", "-P-R");
84 aseq1.createDatasetSequence();
87 * Map dna bases 5-10 to protein residues 12-13
89 AlignedCodonFrame acf = new AlignedCodonFrame();
90 MapList map = new MapList(new int[] { 5, 10 }, new int[] { 12, 13 }, 3,
92 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
93 List<AlignedCodonFrame> acfList = Arrays
94 .asList(new AlignedCodonFrame[]
98 * Check protein residue 12 maps to codon 5-7, 13 to codon 8-10
100 SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 12, acfList);
101 assertEquals(1, sr.getResults().size());
102 SearchResultMatchI m = sr.getResults().get(0);
103 assertEquals(seq1.getDatasetSequence(), m.getSequence());
104 assertEquals(5, m.getStart());
105 assertEquals(7, m.getEnd());
106 sr = MappingUtils.buildSearchResults(aseq1, 13, acfList);
107 assertEquals(1, sr.getResults().size());
108 m = sr.getResults().get(0);
109 assertEquals(seq1.getDatasetSequence(), m.getSequence());
110 assertEquals(8, m.getStart());
111 assertEquals(10, m.getEnd());
114 * Check inverse mappings, from codons 5-7, 8-10 to protein 12, 13
116 for (int i = 5; i < 11; i++)
118 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
119 assertEquals(1, sr.getResults().size());
120 m = sr.getResults().get(0);
121 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
122 int residue = i > 7 ? 13 : 12;
123 assertEquals(residue, m.getStart());
124 assertEquals(residue, m.getEnd());
129 * Simple test of mapping with introns involved.
131 @Test(groups = { "Functional" })
132 public void testBuildSearchResults_withIntron()
134 final Sequence seq1 = new Sequence("Seq1/5-17", "c-G-tAGa-GcAgCtt");
135 seq1.createDatasetSequence();
137 final Sequence aseq1 = new Sequence("Seq1/8-9", "-E-D");
138 aseq1.createDatasetSequence();
141 * Map dna bases [6, 8, 9], [11, 13, 115] to protein residues 8 and 9
143 AlignedCodonFrame acf = new AlignedCodonFrame();
144 MapList map = new MapList(
146 { 6, 6, 8, 9, 11, 11, 13, 13, 15, 15 }, new int[] { 8, 9 }, 3,
148 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
149 List<AlignedCodonFrame> acfList = Arrays
150 .asList(new AlignedCodonFrame[]
154 * Check protein residue 8 maps to [6, 8, 9]
156 SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 8, acfList);
157 assertEquals(2, sr.getResults().size());
158 SearchResultMatchI m = sr.getResults().get(0);
159 assertEquals(seq1.getDatasetSequence(), m.getSequence());
160 assertEquals(6, m.getStart());
161 assertEquals(6, m.getEnd());
162 m = sr.getResults().get(1);
163 assertEquals(seq1.getDatasetSequence(), m.getSequence());
164 assertEquals(8, m.getStart());
165 assertEquals(9, m.getEnd());
168 * Check protein residue 9 maps to [11, 13, 15]
170 sr = MappingUtils.buildSearchResults(aseq1, 9, acfList);
171 assertEquals(3, sr.getResults().size());
172 m = sr.getResults().get(0);
173 assertEquals(seq1.getDatasetSequence(), m.getSequence());
174 assertEquals(11, m.getStart());
175 assertEquals(11, m.getEnd());
176 m = sr.getResults().get(1);
177 assertEquals(seq1.getDatasetSequence(), m.getSequence());
178 assertEquals(13, m.getStart());
179 assertEquals(13, m.getEnd());
180 m = sr.getResults().get(2);
181 assertEquals(seq1.getDatasetSequence(), m.getSequence());
182 assertEquals(15, m.getStart());
183 assertEquals(15, m.getEnd());
186 * Check inverse mappings, from codons to protein
188 for (int i = 5; i < 18; i++)
190 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
191 int residue = (i == 6 || i == 8 || i == 9) ? 8
192 : (i == 11 || i == 13 || i == 15 ? 9 : 0);
195 assertEquals(0, sr.getResults().size());
198 assertEquals(1, sr.getResults().size());
199 m = sr.getResults().get(0);
200 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
201 assertEquals(residue, m.getStart());
202 assertEquals(residue, m.getEnd());
207 * Test mapping a sequence group made of entire sequences.
209 * @throws IOException
211 @Test(groups = { "Functional" })
212 public void testMapSequenceGroup_sequences() throws IOException
215 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
218 AlignmentI cdna = loadAlignment(">Seq1\nACG\n>Seq2\nTGA\n>Seq3\nTAC\n",
220 cdna.setDataset(null);
221 AlignmentI protein = loadAlignment(">Seq1\nK\n>Seq2\nL\n>Seq3\nQ\n",
223 protein.setDataset(null);
224 AlignedCodonFrame acf = new AlignedCodonFrame();
225 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 1 }, 3, 1);
226 for (int seq = 0; seq < 3; seq++)
228 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(),
229 protein.getSequenceAt(seq).getDatasetSequence(), map);
231 List<AlignedCodonFrame> acfList = Arrays
232 .asList(new AlignedCodonFrame[]
235 AlignViewportI dnaView = new AlignViewport(cdna);
236 AlignViewportI proteinView = new AlignViewport(protein);
237 protein.setCodonFrames(acfList);
240 * Select Seq1 and Seq3 in the protein
242 SequenceGroup sg = new SequenceGroup();
243 sg.setColourText(true);
244 sg.setIdColour(Color.GREEN);
245 sg.setOutlineColour(Color.LIGHT_GRAY);
246 sg.addSequence(protein.getSequenceAt(0), false);
247 sg.addSequence(protein.getSequenceAt(2), false);
248 sg.setEndRes(protein.getWidth() - 1);
251 * Verify the mapped sequence group in dna
253 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
254 proteinView, dnaView);
255 assertTrue(mappedGroup.getColourText());
256 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
257 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
258 assertEquals(2, mappedGroup.getSequences().size());
259 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
260 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(1));
261 assertEquals(0, mappedGroup.getStartRes());
262 assertEquals(2, mappedGroup.getEndRes()); // 3 columns (1 codon)
265 * Verify mapping sequence group from dna to protein
268 sg.addSequence(cdna.getSequenceAt(1), false);
269 sg.addSequence(cdna.getSequenceAt(0), false);
272 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
273 assertTrue(mappedGroup.getColourText());
274 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
275 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
276 assertEquals(2, mappedGroup.getSequences().size());
277 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
278 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
279 assertEquals(0, mappedGroup.getStartRes());
280 assertEquals(0, mappedGroup.getEndRes());
284 * Helper method to load an alignment and ensure dataset sequences are set up.
290 * @throws IOException
292 protected AlignmentI loadAlignment(final String data, FileFormatI format)
295 AlignmentI a = new FormatAdapter().readFile(data, DataSourceType.PASTE,
302 * Test mapping a column selection in protein to its dna equivalent
304 * @throws IOException
306 @Test(groups = { "Functional" })
307 public void testMapColumnSelection_proteinToDna() throws IOException
309 setupMappedAlignments();
311 ColumnSelection colsel = new ColumnSelection();
312 HiddenColumns hidden = new HiddenColumns();
315 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
316 * in dna respectively, overall 0-4
318 colsel.addElement(0);
319 ColumnSelection cs = new ColumnSelection();
320 HiddenColumns hs = new HiddenColumns();
321 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
323 assertEquals("[0, 1, 2, 3, 4]", cs.getSelected().toString());
326 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
330 colsel.addElement(1);
331 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
333 assertEquals("[0, 1, 2, 3]", cs.getSelected().toString());
336 * Column 2 in protein picks up gaps only - no mapping
340 colsel.addElement(2);
341 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
343 assertEquals("[]", cs.getSelected().toString());
346 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
347 * 6-9, 6-10, 5-8 respectively, overall to 5-10
351 colsel.addElement(3);
352 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
354 assertEquals("[5, 6, 7, 8, 9, 10]", cs.getSelected().toString());
357 * Combine selection of columns 1 and 3 to get a discontiguous mapped
362 colsel.addElement(1);
363 colsel.addElement(3);
364 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
366 assertEquals("[0, 1, 2, 3, 5, 6, 7, 8, 9, 10]",
367 cs.getSelected().toString());
371 * Set up mappings for tests from 3 dna to 3 protein sequences. Sequences have
372 * offset start positions for a more general test case.
374 * @throws IOException
376 protected void setupMappedAlignments() throws IOException
379 * Map (upper-case = coding):
380 * Seq1/10-18 AC-GctGtC-T to Seq1/40 -K-P
381 * Seq2/20-27 Tc-GA-G-T-T to Seq2/20-27 L--Q
382 * Seq3/30-38 TtTT-AaCGg- to Seq3/60-61\nG--S
384 AlignmentI cdna = loadAlignment(">Seq1/10-18\nAC-GctGtC-T\n"
385 + ">Seq2/20-27\nTc-GA-G-T-Tc\n" + ">Seq3/30-38\nTtTT-AaCGg-\n",
387 cdna.setDataset(null);
388 AlignmentI protein = loadAlignment(
389 ">Seq1/40-41\n-K-P\n>Seq2/50-51\nL--Q\n>Seq3/60-61\nG--S\n",
391 protein.setDataset(null);
393 // map first dna to first protein seq
394 AlignedCodonFrame acf = new AlignedCodonFrame();
395 MapList map = new MapList(new int[] { 10, 12, 15, 15, 17, 18 },
398 acf.addMap(cdna.getSequenceAt(0).getDatasetSequence(),
399 protein.getSequenceAt(0).getDatasetSequence(), map);
401 // map second dna to second protein seq
402 map = new MapList(new int[] { 20, 20, 22, 23, 24, 26 },
405 acf.addMap(cdna.getSequenceAt(1).getDatasetSequence(),
406 protein.getSequenceAt(1).getDatasetSequence(), map);
408 // map third dna to third protein seq
409 map = new MapList(new int[] { 30, 30, 32, 34, 36, 37 },
412 acf.addMap(cdna.getSequenceAt(2).getDatasetSequence(),
413 protein.getSequenceAt(2).getDatasetSequence(), map);
414 List<AlignedCodonFrame> acfList = Arrays
415 .asList(new AlignedCodonFrame[]
418 dnaView = new AlignViewport(cdna);
419 proteinView = new AlignViewport(protein);
420 protein.setCodonFrames(acfList);
424 * Test mapping a column selection in dna to its protein equivalent
426 * @throws IOException
428 @Test(groups = { "Functional" })
429 public void testMapColumnSelection_dnaToProtein() throws IOException
431 setupMappedAlignments();
433 ColumnSelection colsel = new ColumnSelection();
434 HiddenColumns hidden = new HiddenColumns();
437 * Column 0 in dna picks up first bases which map to residue 1, columns 0-1
440 ColumnSelection cs = new ColumnSelection();
441 HiddenColumns hs = new HiddenColumns();
442 colsel.addElement(0);
443 MappingUtils.mapColumnSelection(colsel, hidden, dnaView, proteinView,
445 assertEquals("[0, 1]", cs.getSelected().toString());
448 * Columns 3-5 in dna map to the first residues in protein Seq1, Seq2, and
449 * the first two in Seq3. Overall to columns 0, 1, 3 (col2 is all gaps).
451 colsel.addElement(3);
452 colsel.addElement(4);
453 colsel.addElement(5);
455 MappingUtils.mapColumnSelection(colsel, hidden, dnaView, proteinView,
457 assertEquals("[0, 1, 3]", cs.getSelected().toString());
460 @Test(groups = { "Functional" })
461 public void testMapColumnSelection_null() throws IOException
463 setupMappedAlignments();
464 ColumnSelection cs = new ColumnSelection();
465 HiddenColumns hs = new HiddenColumns();
466 MappingUtils.mapColumnSelection(null, null, dnaView, proteinView, cs,
468 assertTrue("mapped selection not empty", cs.getSelected().isEmpty());
472 * Tests for the method that converts a series of [start, end] ranges to
475 @Test(groups = { "Functional" })
476 public void testFlattenRanges()
478 assertEquals("[1, 2, 3, 4]",
479 Arrays.toString(MappingUtils.flattenRanges(new int[]
481 assertEquals("[1, 2, 3, 4]",
482 Arrays.toString(MappingUtils.flattenRanges(new int[]
484 assertEquals("[1, 2, 3, 4]",
485 Arrays.toString(MappingUtils.flattenRanges(new int[]
486 { 1, 1, 2, 2, 3, 3, 4, 4 })));
487 assertEquals("[1, 2, 3, 4, 7, 8, 9, 12]",
488 Arrays.toString(MappingUtils.flattenRanges(new int[]
489 { 1, 4, 7, 9, 12, 12 })));
490 // trailing unpaired start position is ignored:
491 assertEquals("[1, 2, 3, 4, 7, 8, 9, 12]",
492 Arrays.toString(MappingUtils.flattenRanges(new int[]
493 { 1, 4, 7, 9, 12, 12, 15 })));
497 * Test mapping a sequence group made of entire columns.
499 * @throws IOException
501 @Test(groups = { "Functional" })
502 public void testMapSequenceGroup_columns() throws IOException
505 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
508 AlignmentI cdna = loadAlignment(
509 ">Seq1\nACGGCA\n>Seq2\nTGACAG\n>Seq3\nTACGTA\n",
511 cdna.setDataset(null);
512 AlignmentI protein = loadAlignment(">Seq1\nKA\n>Seq2\nLQ\n>Seq3\nQV\n",
514 protein.setDataset(null);
515 AlignedCodonFrame acf = new AlignedCodonFrame();
516 MapList map = new MapList(new int[] { 1, 6 }, new int[] { 1, 2 }, 3, 1);
517 for (int seq = 0; seq < 3; seq++)
519 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(),
520 protein.getSequenceAt(seq).getDatasetSequence(), map);
522 List<AlignedCodonFrame> acfList = Arrays
523 .asList(new AlignedCodonFrame[]
526 AlignViewportI dnaView = new AlignViewport(cdna);
527 AlignViewportI proteinView = new AlignViewport(protein);
528 protein.setCodonFrames(acfList);
531 * Select all sequences, column 2 in the protein
533 SequenceGroup sg = new SequenceGroup();
534 sg.setColourText(true);
535 sg.setIdColour(Color.GREEN);
536 sg.setOutlineColour(Color.LIGHT_GRAY);
537 sg.addSequence(protein.getSequenceAt(0), false);
538 sg.addSequence(protein.getSequenceAt(1), false);
539 sg.addSequence(protein.getSequenceAt(2), false);
544 * Verify the mapped sequence group in dna
546 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
547 proteinView, dnaView);
548 assertTrue(mappedGroup.getColourText());
549 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
550 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
551 assertEquals(3, mappedGroup.getSequences().size());
552 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
553 assertSame(cdna.getSequenceAt(1), mappedGroup.getSequences().get(1));
554 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(2));
555 assertEquals(3, mappedGroup.getStartRes());
556 assertEquals(5, mappedGroup.getEndRes());
559 * Verify mapping sequence group from dna to protein
562 sg.addSequence(cdna.getSequenceAt(0), false);
563 sg.addSequence(cdna.getSequenceAt(1), false);
564 sg.addSequence(cdna.getSequenceAt(2), false);
565 // select columns 2 and 3 in DNA which span protein columns 0 and 1
568 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
569 assertTrue(mappedGroup.getColourText());
570 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
571 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
572 assertEquals(3, mappedGroup.getSequences().size());
573 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(0));
574 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(1));
575 assertSame(protein.getSequenceAt(2), mappedGroup.getSequences().get(2));
576 assertEquals(0, mappedGroup.getStartRes());
577 assertEquals(1, mappedGroup.getEndRes());
581 * Test mapping a sequence group made of a sequences/columns region.
583 * @throws IOException
585 @Test(groups = { "Functional" })
586 public void testMapSequenceGroup_region() throws IOException
589 * Set up gapped dna and protein Seq1/2/3 with mappings (held on the protein
592 AlignmentI cdna = loadAlignment(
593 ">Seq1\nA-CG-GC--AT-CA\n>Seq2\n-TG-AC-AG-T-AT\n>Seq3\n-T--ACG-TAAT-G\n",
595 cdna.setDataset(null);
596 AlignmentI protein = loadAlignment(
597 ">Seq1\n-KA-S\n>Seq2\n--L-QY\n>Seq3\nQ-V-M\n",
599 protein.setDataset(null);
600 AlignedCodonFrame acf = new AlignedCodonFrame();
601 MapList map = new MapList(new int[] { 1, 9 }, new int[] { 1, 3 }, 3, 1);
602 for (int seq = 0; seq < 3; seq++)
604 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(),
605 protein.getSequenceAt(seq).getDatasetSequence(), map);
607 List<AlignedCodonFrame> acfList = Arrays
608 .asList(new AlignedCodonFrame[]
611 AlignViewportI dnaView = new AlignViewport(cdna);
612 AlignViewportI proteinView = new AlignViewport(protein);
613 protein.setCodonFrames(acfList);
616 * Select Seq1 and Seq2 in the protein, column 1 (K/-). Expect mapped
617 * sequence group to cover Seq1, columns 0-3 (ACG). Because the selection
618 * only includes a gap in Seq2 there is no mappable selection region in the
621 SequenceGroup sg = new SequenceGroup();
622 sg.setColourText(true);
623 sg.setIdColour(Color.GREEN);
624 sg.setOutlineColour(Color.LIGHT_GRAY);
625 sg.addSequence(protein.getSequenceAt(0), false);
626 sg.addSequence(protein.getSequenceAt(1), false);
631 * Verify the mapped sequence group in dna
633 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
634 proteinView, dnaView);
635 assertTrue(mappedGroup.getColourText());
636 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
637 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
638 assertEquals(1, mappedGroup.getSequences().size());
639 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
640 // Seq2 in protein has a gap in column 1 - ignored
641 // Seq1 has K which should map to columns 0-3 in Seq1
642 assertEquals(0, mappedGroup.getStartRes());
643 assertEquals(3, mappedGroup.getEndRes());
646 * Now select cols 2-4 in protein. These cover Seq1:AS Seq2:LQ Seq3:VM which
647 * extend over DNA columns 3-12, 1-7, 6-13 respectively, or 1-13 overall.
651 mappedGroup = MappingUtils.mapSequenceGroup(sg, proteinView, dnaView);
652 assertEquals(1, mappedGroup.getStartRes());
653 assertEquals(13, mappedGroup.getEndRes());
656 * Verify mapping sequence group from dna to protein
659 sg.addSequence(cdna.getSequenceAt(0), false);
661 // select columns 4,5 - includes Seq1:codon2 (A) only
664 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
665 assertEquals(2, mappedGroup.getStartRes());
666 assertEquals(2, mappedGroup.getEndRes());
668 // add Seq2 to dna selection cols 4-5 include codons 1 and 2 (LQ)
669 sg.addSequence(cdna.getSequenceAt(1), false);
670 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
671 assertEquals(2, mappedGroup.getStartRes());
672 assertEquals(4, mappedGroup.getEndRes());
674 // add Seq3 to dna selection cols 4-5 include codon 1 (Q)
675 sg.addSequence(cdna.getSequenceAt(2), false);
676 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
677 assertEquals(0, mappedGroup.getStartRes());
678 assertEquals(4, mappedGroup.getEndRes());
681 @Test(groups = { "Functional" })
682 public void testFindMappingsForSequence()
684 SequenceI seq1 = new Sequence("Seq1", "ABC");
685 SequenceI seq2 = new Sequence("Seq2", "ABC");
686 SequenceI seq3 = new Sequence("Seq3", "ABC");
687 SequenceI seq4 = new Sequence("Seq4", "ABC");
688 seq1.createDatasetSequence();
689 seq2.createDatasetSequence();
690 seq3.createDatasetSequence();
691 seq4.createDatasetSequence();
694 * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1
696 AlignedCodonFrame acf1 = new AlignedCodonFrame();
697 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
698 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
699 AlignedCodonFrame acf2 = new AlignedCodonFrame();
700 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
701 AlignedCodonFrame acf3 = new AlignedCodonFrame();
702 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
704 List<AlignedCodonFrame> mappings = new ArrayList<>();
710 * Seq1 has three mappings
712 List<AlignedCodonFrame> result = MappingUtils
713 .findMappingsForSequence(seq1, mappings);
714 assertEquals(3, result.size());
715 assertTrue(result.contains(acf1));
716 assertTrue(result.contains(acf2));
717 assertTrue(result.contains(acf3));
720 * Seq2 has two mappings
722 result = MappingUtils.findMappingsForSequence(seq2, mappings);
723 assertEquals(2, result.size());
724 assertTrue(result.contains(acf1));
725 assertTrue(result.contains(acf2));
728 * Seq3 has one mapping
730 result = MappingUtils.findMappingsForSequence(seq3, mappings);
731 assertEquals(1, result.size());
732 assertTrue(result.contains(acf3));
735 * Seq4 has no mappings
737 result = MappingUtils.findMappingsForSequence(seq4, mappings);
738 assertEquals(0, result.size());
740 result = MappingUtils.findMappingsForSequence(null, mappings);
741 assertEquals(0, result.size());
743 result = MappingUtils.findMappingsForSequence(seq1, null);
744 assertEquals(0, result.size());
746 result = MappingUtils.findMappingsForSequence(null, null);
747 assertEquals(0, result.size());
751 * just like the one above, but this time, we provide a set of sequences to
752 * subselect the mapping search
754 @Test(groups = { "Functional" })
755 public void testFindMappingsForSequenceAndOthers()
757 SequenceI seq1 = new Sequence("Seq1", "ABC");
758 SequenceI seq2 = new Sequence("Seq2", "ABC");
759 SequenceI seq3 = new Sequence("Seq3", "ABC");
760 SequenceI seq4 = new Sequence("Seq4", "ABC");
761 seq1.createDatasetSequence();
762 seq2.createDatasetSequence();
763 seq3.createDatasetSequence();
764 seq4.createDatasetSequence();
767 * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1, seq3 to seq4
769 AlignedCodonFrame acf1 = new AlignedCodonFrame();
770 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
771 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
772 AlignedCodonFrame acf2 = new AlignedCodonFrame();
773 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
774 AlignedCodonFrame acf3 = new AlignedCodonFrame();
775 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
776 AlignedCodonFrame acf4 = new AlignedCodonFrame();
777 acf4.addMap(seq3.getDatasetSequence(), seq4.getDatasetSequence(), map);
779 List<AlignedCodonFrame> mappings = new ArrayList<>();
788 List<AlignedCodonFrame> result = MappingUtils
789 .findMappingsForSequenceAndOthers(null, mappings,
790 Arrays.asList(new SequenceI[]
792 assertTrue(result.isEmpty());
794 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, null,
795 Arrays.asList(new SequenceI[]
797 assertTrue(result.isEmpty());
800 * Seq1 has three mappings, but filter argument will only accept
803 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, mappings,
804 Arrays.asList(new SequenceI[]
805 { seq1, seq2, seq1.getDatasetSequence() }));
806 assertEquals(2, result.size());
807 assertTrue(result.contains(acf1));
808 assertTrue(result.contains(acf2));
809 assertFalse("Did not expect to find mapping acf3 - subselect failed",
810 result.contains(acf3));
812 "Did not expect to find mapping acf4 - doesn't involve sequence",
813 result.contains(acf4));
816 * and verify the no filter case
818 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, mappings,
820 assertEquals(3, result.size());
821 assertTrue(result.contains(acf1));
822 assertTrue(result.contains(acf2));
823 assertTrue(result.contains(acf3));
826 @Test(groups = { "Functional" })
827 public void testMapEditCommand()
829 SequenceI dna = new Sequence("Seq1", "---ACG---GCATCA", 8, 16);
830 SequenceI protein = new Sequence("Seq2", "-T-AS", 5, 7);
831 dna.createDatasetSequence();
832 protein.createDatasetSequence();
833 AlignedCodonFrame acf = new AlignedCodonFrame();
834 MapList map = new MapList(new int[] { 8, 16 }, new int[] { 5, 7 }, 3,
836 acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
837 List<AlignedCodonFrame> mappings = new ArrayList<>();
840 AlignmentI prot = new Alignment(new SequenceI[] { protein });
841 prot.setCodonFrames(mappings);
842 AlignmentI nuc = new Alignment(new SequenceI[] { dna });
845 * construct and perform the edit command to turn "-T-AS" in to "-T-A--S"
846 * i.e. insert two gaps at column 4
848 EditCommand ec = new EditCommand();
849 final Edit edit = ec.new Edit(Action.INSERT_GAP,
851 { protein }, 4, 2, '-');
852 ec.appendEdit(edit, prot, true, null);
855 * the mapped edit command should be to insert 6 gaps before base 4 in the
856 * nucleotide sequence, which corresponds to aligned column 12 in the dna
858 EditCommand mappedEdit = MappingUtils.mapEditCommand(ec, false, nuc,
860 assertEquals(1, mappedEdit.getEdits().size());
861 Edit e = mappedEdit.getEdits().get(0);
862 assertEquals(1, e.getSequences().length);
863 assertEquals(dna, e.getSequences()[0]);
864 assertEquals(12, e.getPosition());
865 assertEquals(6, e.getNumber());
869 * Tests for the method that converts a series of [start, end] ranges to
870 * single positions, where the mapping is to a reverse strand i.e. start is
871 * greater than end point mapped to
873 @Test(groups = { "Functional" })
874 public void testFlattenRanges_reverseStrand()
876 assertEquals("[4, 3, 2, 1]",
877 Arrays.toString(MappingUtils.flattenRanges(new int[]
879 assertEquals("[4, 3, 2, 1]",
880 Arrays.toString(MappingUtils.flattenRanges(new int[]
882 assertEquals("[4, 3, 2, 1]",
883 Arrays.toString(MappingUtils.flattenRanges(new int[]
884 { 4, 4, 3, 3, 2, 2, 1, 1 })));
885 assertEquals("[12, 9, 8, 7, 4, 3, 2, 1]",
886 Arrays.toString(MappingUtils.flattenRanges(new int[]
887 { 12, 12, 9, 7, 4, 1 })));
888 // forwards and backwards anyone?
889 assertEquals("[4, 5, 6, 3, 2, 1]",
890 Arrays.toString(MappingUtils.flattenRanges(new int[]
892 // backwards and forwards
893 assertEquals("[3, 2, 1, 4, 5, 6]",
894 Arrays.toString(MappingUtils.flattenRanges(new int[]
896 // trailing unpaired start position is ignored:
897 assertEquals("[12, 9, 8, 7, 4, 3, 2]",
898 Arrays.toString(MappingUtils.flattenRanges(new int[]
899 { 12, 12, 9, 7, 4, 2, 1 })));
903 * Test mapping a column selection including hidden columns
905 * @throws IOException
907 @Test(groups = { "Functional" })
908 public void testMapColumnSelection_hiddenColumns() throws IOException
910 setupMappedAlignments();
912 ColumnSelection proteinSelection = new ColumnSelection();
913 HiddenColumns hiddenCols = new HiddenColumns();
916 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
917 * in dna respectively, overall 0-4
919 proteinSelection.hideSelectedColumns(0, hiddenCols);
920 ColumnSelection dnaSelection = new ColumnSelection();
921 HiddenColumns dnaHidden = new HiddenColumns();
922 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
923 proteinView, dnaView, dnaSelection, dnaHidden);
924 assertEquals("[]", dnaSelection.getSelected().toString());
925 Iterator<int[]> regions = dnaHidden.iterator();
926 assertEquals(1, dnaHidden.getNumberOfRegions());
927 assertEquals("[0, 4]", Arrays.toString(regions.next()));
930 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
932 dnaSelection = new ColumnSelection();
933 dnaHidden = new HiddenColumns();
934 hiddenCols.revealAllHiddenColumns(proteinSelection);
935 // the unhidden columns are now marked selected!
936 assertEquals("[0]", proteinSelection.getSelected().toString());
937 // deselect these or hideColumns will be expanded to include 0
938 proteinSelection.clear();
939 proteinSelection.hideSelectedColumns(1, hiddenCols);
940 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
941 proteinView, dnaView, dnaSelection, dnaHidden);
942 regions = dnaHidden.iterator();
943 assertEquals(1, dnaHidden.getNumberOfRegions());
944 assertEquals("[0, 3]", Arrays.toString(regions.next()));
947 * Column 2 in protein picks up gaps only - no mapping
949 dnaSelection = new ColumnSelection();
950 dnaHidden = new HiddenColumns();
951 hiddenCols.revealAllHiddenColumns(proteinSelection);
952 proteinSelection.clear();
953 proteinSelection.hideSelectedColumns(2, hiddenCols);
954 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
955 proteinView, dnaView, dnaSelection, dnaHidden);
956 assertEquals(0, dnaHidden.getNumberOfRegions());
959 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
960 * 6-9, 6-10, 5-8 respectively, overall to 5-10
962 dnaSelection = new ColumnSelection();
963 dnaHidden = new HiddenColumns();
964 hiddenCols.revealAllHiddenColumns(proteinSelection);
965 proteinSelection.clear();
966 proteinSelection.hideSelectedColumns(3, hiddenCols); // 5-10 hidden in dna
967 proteinSelection.addElement(1); // 0-3 selected in dna
968 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
969 proteinView, dnaView, dnaSelection, dnaHidden);
970 assertEquals("[0, 1, 2, 3]", dnaSelection.getSelected().toString());
971 regions = dnaHidden.iterator();
972 assertEquals(1, dnaHidden.getNumberOfRegions());
973 assertEquals("[5, 10]", Arrays.toString(regions.next()));
976 * Combine hiding columns 1 and 3 to get discontiguous hidden columns
978 dnaSelection = new ColumnSelection();
979 dnaHidden = new HiddenColumns();
980 hiddenCols.revealAllHiddenColumns(proteinSelection);
981 proteinSelection.clear();
982 proteinSelection.hideSelectedColumns(1, hiddenCols);
983 proteinSelection.hideSelectedColumns(3, hiddenCols);
984 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
985 proteinView, dnaView, dnaSelection, dnaHidden);
986 regions = dnaHidden.iterator();
987 assertEquals(2, dnaHidden.getNumberOfRegions());
988 assertEquals("[0, 3]", Arrays.toString(regions.next()));
989 assertEquals("[5, 10]", Arrays.toString(regions.next()));
992 @Test(groups = { "Functional" })
993 public void testGetLength()
995 assertEquals(0, MappingUtils.getLength(null));
998 * [start, end] ranges
1000 List<int[]> ranges = new ArrayList<>();
1001 assertEquals(0, MappingUtils.getLength(ranges));
1002 ranges.add(new int[] { 1, 1 });
1003 assertEquals(1, MappingUtils.getLength(ranges));
1004 ranges.add(new int[] { 2, 10 });
1005 assertEquals(10, MappingUtils.getLength(ranges));
1006 ranges.add(new int[] { 20, 10 });
1007 assertEquals(21, MappingUtils.getLength(ranges));
1010 * [start, end, start, end...] ranges
1013 ranges.add(new int[] { 1, 5, 8, 4 });
1014 ranges.add(new int[] { 8, 2 });
1015 ranges.add(new int[] { 12, 12 });
1016 assertEquals(18, MappingUtils.getLength(ranges));
1019 @Test(groups = { "Functional" })
1020 public void testContains()
1022 assertFalse(MappingUtils.contains(null, 1));
1023 List<int[]> ranges = new ArrayList<>();
1024 assertFalse(MappingUtils.contains(ranges, 1));
1026 ranges.add(new int[] { 1, 4 });
1027 ranges.add(new int[] { 6, 6 });
1028 ranges.add(new int[] { 8, 10 });
1029 ranges.add(new int[] { 30, 20 });
1030 ranges.add(new int[] { -16, -44 });
1032 assertFalse(MappingUtils.contains(ranges, 0));
1033 assertTrue(MappingUtils.contains(ranges, 1));
1034 assertTrue(MappingUtils.contains(ranges, 2));
1035 assertTrue(MappingUtils.contains(ranges, 3));
1036 assertTrue(MappingUtils.contains(ranges, 4));
1037 assertFalse(MappingUtils.contains(ranges, 5));
1039 assertTrue(MappingUtils.contains(ranges, 6));
1040 assertFalse(MappingUtils.contains(ranges, 7));
1042 assertTrue(MappingUtils.contains(ranges, 8));
1043 assertTrue(MappingUtils.contains(ranges, 9));
1044 assertTrue(MappingUtils.contains(ranges, 10));
1046 assertFalse(MappingUtils.contains(ranges, 31));
1047 assertTrue(MappingUtils.contains(ranges, 30));
1048 assertTrue(MappingUtils.contains(ranges, 29));
1049 assertTrue(MappingUtils.contains(ranges, 20));
1050 assertFalse(MappingUtils.contains(ranges, 19));
1052 assertFalse(MappingUtils.contains(ranges, -15));
1053 assertTrue(MappingUtils.contains(ranges, -16));
1054 assertTrue(MappingUtils.contains(ranges, -44));
1055 assertFalse(MappingUtils.contains(ranges, -45));
1059 * Test the method that drops positions from the start of a mapped range
1061 @Test(groups = "Functional")
1062 public void testRemoveStartPositions()
1064 int[] ranges = new int[] { 1, 10 };
1065 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
1066 assertEquals("[1, 10]", Arrays.toString(adjusted));
1068 adjusted = MappingUtils.removeStartPositions(1, ranges);
1069 assertEquals("[2, 10]", Arrays.toString(adjusted));
1070 assertEquals("[1, 10]", Arrays.toString(ranges));
1073 adjusted = MappingUtils.removeStartPositions(1, ranges);
1074 assertEquals("[3, 10]", Arrays.toString(adjusted));
1075 assertEquals("[2, 10]", Arrays.toString(ranges));
1077 ranges = new int[] { 2, 3, 10, 12 };
1078 adjusted = MappingUtils.removeStartPositions(1, ranges);
1079 assertEquals("[3, 3, 10, 12]", Arrays.toString(adjusted));
1080 assertEquals("[2, 3, 10, 12]", Arrays.toString(ranges));
1082 ranges = new int[] { 2, 2, 8, 12 };
1083 adjusted = MappingUtils.removeStartPositions(1, ranges);
1084 assertEquals("[8, 12]", Arrays.toString(adjusted));
1085 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
1087 ranges = new int[] { 2, 2, 8, 12 };
1088 adjusted = MappingUtils.removeStartPositions(2, ranges);
1089 assertEquals("[9, 12]", Arrays.toString(adjusted));
1090 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
1092 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
1093 adjusted = MappingUtils.removeStartPositions(1, ranges);
1094 assertEquals("[4, 4, 9, 12]", Arrays.toString(adjusted));
1095 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
1097 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
1098 adjusted = MappingUtils.removeStartPositions(2, ranges);
1099 assertEquals("[9, 12]", Arrays.toString(adjusted));
1100 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
1102 ranges = new int[] { 2, 3, 9, 12 };
1103 adjusted = MappingUtils.removeStartPositions(3, ranges);
1104 assertEquals("[10, 12]", Arrays.toString(adjusted));
1105 assertEquals("[2, 3, 9, 12]", Arrays.toString(ranges));
1109 * Test the method that drops positions from the start of a mapped range, on
1110 * the reverse strand
1112 @Test(groups = "Functional")
1113 public void testRemoveStartPositions_reverseStrand()
1115 int[] ranges = new int[] { 10, 1 };
1116 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
1117 assertEquals("[10, 1]", Arrays.toString(adjusted));
1118 assertEquals("[10, 1]", Arrays.toString(ranges));
1121 adjusted = MappingUtils.removeStartPositions(1, ranges);
1122 assertEquals("[9, 1]", Arrays.toString(adjusted));
1123 assertEquals("[10, 1]", Arrays.toString(ranges));
1126 adjusted = MappingUtils.removeStartPositions(1, ranges);
1127 assertEquals("[8, 1]", Arrays.toString(adjusted));
1128 assertEquals("[9, 1]", Arrays.toString(ranges));
1130 ranges = new int[] { 12, 11, 9, 6 };
1131 adjusted = MappingUtils.removeStartPositions(1, ranges);
1132 assertEquals("[11, 11, 9, 6]", Arrays.toString(adjusted));
1133 assertEquals("[12, 11, 9, 6]", Arrays.toString(ranges));
1135 ranges = new int[] { 12, 12, 8, 4 };
1136 adjusted = MappingUtils.removeStartPositions(1, ranges);
1137 assertEquals("[8, 4]", Arrays.toString(adjusted));
1138 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1140 ranges = new int[] { 12, 12, 8, 4 };
1141 adjusted = MappingUtils.removeStartPositions(2, ranges);
1142 assertEquals("[7, 4]", Arrays.toString(adjusted));
1143 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1145 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1146 adjusted = MappingUtils.removeStartPositions(1, ranges);
1147 assertEquals("[10, 10, 8, 4]", Arrays.toString(adjusted));
1148 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1150 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1151 adjusted = MappingUtils.removeStartPositions(2, ranges);
1152 assertEquals("[8, 4]", Arrays.toString(adjusted));
1153 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1155 ranges = new int[] { 12, 11, 8, 4 };
1156 adjusted = MappingUtils.removeStartPositions(3, ranges);
1157 assertEquals("[7, 4]", Arrays.toString(adjusted));
1158 assertEquals("[12, 11, 8, 4]", Arrays.toString(ranges));
1161 @Test(groups = { "Functional" })
1162 public void testRangeContains()
1165 * both forward ranges
1168 MappingUtils.rangeContains(new int[]
1169 { 1, 10 }, new int[] { 1, 10 }));
1171 MappingUtils.rangeContains(new int[]
1172 { 1, 10 }, new int[] { 2, 10 }));
1174 MappingUtils.rangeContains(new int[]
1175 { 1, 10 }, new int[] { 1, 9 }));
1177 MappingUtils.rangeContains(new int[]
1178 { 1, 10 }, new int[] { 4, 5 }));
1180 MappingUtils.rangeContains(new int[]
1181 { 1, 10 }, new int[] { 0, 9 }));
1183 MappingUtils.rangeContains(new int[]
1184 { 1, 10 }, new int[] { -10, -9 }));
1186 MappingUtils.rangeContains(new int[]
1187 { 1, 10 }, new int[] { 1, 11 }));
1189 MappingUtils.rangeContains(new int[]
1190 { 1, 10 }, new int[] { 11, 12 }));
1193 * forward range, reverse query
1196 MappingUtils.rangeContains(new int[]
1197 { 1, 10 }, new int[] { 10, 1 }));
1199 MappingUtils.rangeContains(new int[]
1200 { 1, 10 }, new int[] { 9, 1 }));
1202 MappingUtils.rangeContains(new int[]
1203 { 1, 10 }, new int[] { 10, 2 }));
1205 MappingUtils.rangeContains(new int[]
1206 { 1, 10 }, new int[] { 5, 5 }));
1208 MappingUtils.rangeContains(new int[]
1209 { 1, 10 }, new int[] { 11, 1 }));
1211 MappingUtils.rangeContains(new int[]
1212 { 1, 10 }, new int[] { 10, 0 }));
1215 * reverse range, forward query
1218 MappingUtils.rangeContains(new int[]
1219 { 10, 1 }, new int[] { 1, 10 }));
1221 MappingUtils.rangeContains(new int[]
1222 { 10, 1 }, new int[] { 1, 9 }));
1224 MappingUtils.rangeContains(new int[]
1225 { 10, 1 }, new int[] { 2, 10 }));
1227 MappingUtils.rangeContains(new int[]
1228 { 10, 1 }, new int[] { 6, 6 }));
1230 MappingUtils.rangeContains(new int[]
1231 { 10, 1 }, new int[] { 6, 11 }));
1233 MappingUtils.rangeContains(new int[]
1234 { 10, 1 }, new int[] { 11, 20 }));
1236 MappingUtils.rangeContains(new int[]
1237 { 10, 1 }, new int[] { -3, -2 }));
1243 MappingUtils.rangeContains(new int[]
1244 { 10, 1 }, new int[] { 10, 1 }));
1246 MappingUtils.rangeContains(new int[]
1247 { 10, 1 }, new int[] { 9, 1 }));
1249 MappingUtils.rangeContains(new int[]
1250 { 10, 1 }, new int[] { 10, 2 }));
1252 MappingUtils.rangeContains(new int[]
1253 { 10, 1 }, new int[] { 3, 3 }));
1255 MappingUtils.rangeContains(new int[]
1256 { 10, 1 }, new int[] { 11, 1 }));
1258 MappingUtils.rangeContains(new int[]
1259 { 10, 1 }, new int[] { 10, 0 }));
1261 MappingUtils.rangeContains(new int[]
1262 { 10, 1 }, new int[] { 12, 11 }));
1264 MappingUtils.rangeContains(new int[]
1265 { 10, 1 }, new int[] { -5, -8 }));
1271 MappingUtils.rangeContains(new int[]
1272 { 1, 10, 12 }, new int[] { 1, 10 }));
1274 MappingUtils.rangeContains(new int[]
1275 { 1, 10 }, new int[] { 1 }));
1276 assertFalse(MappingUtils.rangeContains(new int[] { 1, 10 }, null));
1277 assertFalse(MappingUtils.rangeContains(null, new int[] { 1, 10 }));
1280 @Test(groups = "Functional")
1281 public void testRemoveEndPositions()
1283 List<int[]> ranges = new ArrayList<>();
1286 * case 1: truncate last range
1288 ranges.add(new int[] { 1, 10 });
1289 ranges.add(new int[] { 20, 30 });
1290 MappingUtils.removeEndPositions(5, ranges);
1291 assertEquals(2, ranges.size());
1292 assertEquals(25, ranges.get(1)[1]);
1295 * case 2: remove last range
1298 ranges.add(new int[] { 1, 10 });
1299 ranges.add(new int[] { 20, 22 });
1300 MappingUtils.removeEndPositions(3, ranges);
1301 assertEquals(1, ranges.size());
1302 assertEquals(10, ranges.get(0)[1]);
1305 * case 3: truncate penultimate range
1308 ranges.add(new int[] { 1, 10 });
1309 ranges.add(new int[] { 20, 21 });
1310 MappingUtils.removeEndPositions(3, ranges);
1311 assertEquals(1, ranges.size());
1312 assertEquals(9, ranges.get(0)[1]);
1315 * case 4: remove last two ranges
1318 ranges.add(new int[] { 1, 10 });
1319 ranges.add(new int[] { 20, 20 });
1320 ranges.add(new int[] { 30, 30 });
1321 MappingUtils.removeEndPositions(3, ranges);
1322 assertEquals(1, ranges.size());
1323 assertEquals(9, ranges.get(0)[1]);
1326 @Test(groups = "Functional")
1327 public void testListToArray()
1329 List<int[]> ranges = new ArrayList<>();
1331 int[] result = MappingUtils.listToArray(ranges);
1332 assertEquals(result.length, 0);
1333 ranges.add(new int[] {24, 12});
1334 result = MappingUtils.listToArray(ranges);
1335 assertEquals(result.length, 2);
1336 assertEquals(result[0], 24);
1337 assertEquals(result[1], 12);
1338 ranges.add(new int[] {-7, 30});
1339 result = MappingUtils.listToArray(ranges);
1340 assertEquals(result.length, 4);
1341 assertEquals(result[0], 24);
1342 assertEquals(result[1], 12);
1343 assertEquals(result[2], -7);
1344 assertEquals(result[3], 30);
1347 MappingUtils.listToArray(null);
1348 fail("Expected exception");
1349 } catch (NullPointerException e)
1356 * Test mapping a sequence group where sequences in and outside the group
1357 * share a dataset sequence (e.g. alternative CDS for the same gene)
1359 * @throws IOException
1361 @Test(groups = { "Functional" })
1362 public void testMapSequenceGroup_sharedDataset() throws IOException
1365 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
1366 * viewport). CDS sequences share the same 'gene' dataset sequence.
1368 SequenceI dna = new Sequence("dna", "aaatttgggcccaaatttgggccc");
1369 SequenceI cds1 = new Sequence("cds1/1-6", "aaattt");
1370 SequenceI cds2 = new Sequence("cds1/4-9", "tttggg");
1371 SequenceI cds3 = new Sequence("cds1/19-24", "gggccc");
1373 cds1.setDatasetSequence(dna);
1374 cds2.setDatasetSequence(dna);
1375 cds3.setDatasetSequence(dna);
1377 SequenceI pep1 = new Sequence("pep1", "KF");
1378 SequenceI pep2 = new Sequence("pep2", "FG");
1379 SequenceI pep3 = new Sequence("pep3", "GP");
1382 * add mappings from coding positions of dna to respective peptides
1384 AlignedCodonFrame acf = new AlignedCodonFrame();
1385 acf.addMap(dna, pep1,
1386 new MapList(new int[]
1387 { 1, 6 }, new int[] { 1, 2 }, 3, 1));
1388 acf.addMap(dna, pep2,
1389 new MapList(new int[]
1390 { 4, 9 }, new int[] { 1, 2 }, 3, 1));
1391 acf.addMap(dna, pep3,
1392 new MapList(new int[]
1393 { 19, 24 }, new int[] { 1, 2 }, 3, 1));
1395 List<AlignedCodonFrame> acfList = Arrays
1396 .asList(new AlignedCodonFrame[]
1399 AlignmentI cdna = new Alignment(new SequenceI[] { cds1, cds2, cds3 });
1400 AlignmentI protein = new Alignment(
1402 { pep1, pep2, pep3 });
1403 AlignViewportI cdnaView = new AlignViewport(cdna);
1404 AlignViewportI proteinView = new AlignViewport(protein);
1405 protein.setCodonFrames(acfList);
1408 * Select pep1 and pep3 in the protein alignment
1410 SequenceGroup sg = new SequenceGroup();
1411 sg.setColourText(true);
1412 sg.setIdColour(Color.GREEN);
1413 sg.setOutlineColour(Color.LIGHT_GRAY);
1414 sg.addSequence(pep1, false);
1415 sg.addSequence(pep3, false);
1416 sg.setEndRes(protein.getWidth() - 1);
1419 * Verify the mapped sequence group in dna is cds1 and cds3
1421 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
1422 proteinView, cdnaView);
1423 assertTrue(mappedGroup.getColourText());
1424 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
1425 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
1426 assertEquals(2, mappedGroup.getSequences().size());
1427 assertSame(cds1, mappedGroup.getSequences().get(0));
1428 assertSame(cds3, mappedGroup.getSequences().get(1));
1429 // columns 1-6 selected (0-5 base zero)
1430 assertEquals(0, mappedGroup.getStartRes());
1431 assertEquals(5, mappedGroup.getEndRes());
1434 * Select mapping sequence group from dna to protein
1437 sg.addSequence(cds2, false);
1438 sg.addSequence(cds1, false);
1440 sg.setEndRes(cdna.getWidth() - 1);
1441 mappedGroup = MappingUtils.mapSequenceGroup(sg, cdnaView, proteinView);
1442 assertTrue(mappedGroup.getColourText());
1443 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
1444 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
1445 assertEquals(2, mappedGroup.getSequences().size());
1446 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
1447 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
1448 assertEquals(0, mappedGroup.getStartRes());
1449 assertEquals(1, mappedGroup.getEndRes()); // two columns