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;
28 import jalview.api.AlignViewportI;
29 import jalview.commands.EditCommand;
30 import jalview.commands.EditCommand.Action;
31 import jalview.commands.EditCommand.Edit;
32 import jalview.datamodel.AlignedCodonFrame;
33 import jalview.datamodel.Alignment;
34 import jalview.datamodel.AlignmentI;
35 import jalview.datamodel.ColumnSelection;
36 import jalview.datamodel.SearchResultMatchI;
37 import jalview.datamodel.SearchResultsI;
38 import jalview.datamodel.Sequence;
39 import jalview.datamodel.SequenceGroup;
40 import jalview.datamodel.SequenceI;
41 import jalview.gui.AlignViewport;
42 import jalview.gui.JvOptionPane;
43 import jalview.io.AppletFormatAdapter;
44 import jalview.io.FormatAdapter;
46 import java.awt.Color;
47 import java.io.IOException;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.List;
52 import org.testng.annotations.BeforeClass;
53 import org.testng.annotations.Test;
55 public class MappingUtilsTest
58 @BeforeClass(alwaysRun = true)
59 public void setUpJvOptionPane()
61 JvOptionPane.setInteractiveMode(false);
62 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
65 private AlignViewportI dnaView;
67 private AlignViewportI proteinView;
70 * Simple test of mapping with no intron involved.
72 @Test(groups = { "Functional" })
73 public void testBuildSearchResults()
75 final Sequence seq1 = new Sequence("Seq1/5-10", "C-G-TA-GC");
76 seq1.createDatasetSequence();
78 final Sequence aseq1 = new Sequence("Seq1/12-13", "-P-R");
79 aseq1.createDatasetSequence();
82 * Map dna bases 5-10 to protein residues 12-13
84 AlignedCodonFrame acf = new AlignedCodonFrame();
85 MapList map = new MapList(new int[] { 5, 10 }, new int[] { 12, 13 }, 3,
87 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
88 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
92 * Check protein residue 12 maps to codon 5-7, 13 to codon 8-10
94 SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 12, acfList);
95 assertEquals(1, sr.getResults().size());
96 SearchResultMatchI m = sr.getResults().get(0);
97 assertEquals(seq1.getDatasetSequence(), m.getSequence());
98 assertEquals(5, m.getStart());
99 assertEquals(7, m.getEnd());
100 sr = MappingUtils.buildSearchResults(aseq1, 13, acfList);
101 assertEquals(1, sr.getResults().size());
102 m = sr.getResults().get(0);
103 assertEquals(seq1.getDatasetSequence(), m.getSequence());
104 assertEquals(8, m.getStart());
105 assertEquals(10, m.getEnd());
108 * Check inverse mappings, from codons 5-7, 8-10 to protein 12, 13
110 for (int i = 5; i < 11; i++)
112 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
113 assertEquals(1, sr.getResults().size());
114 m = sr.getResults().get(0);
115 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
116 int residue = i > 7 ? 13 : 12;
117 assertEquals(residue, m.getStart());
118 assertEquals(residue, m.getEnd());
123 * Simple test of mapping with introns involved.
125 @Test(groups = { "Functional" })
126 public void testBuildSearchResults_withIntron()
128 final Sequence seq1 = new Sequence("Seq1/5-17", "c-G-tAGa-GcAgCtt");
129 seq1.createDatasetSequence();
131 final Sequence aseq1 = new Sequence("Seq1/8-9", "-E-D");
132 aseq1.createDatasetSequence();
135 * Map dna bases [6, 8, 9], [11, 13, 115] to protein residues 8 and 9
137 AlignedCodonFrame acf = new AlignedCodonFrame();
138 MapList map = new MapList(new int[] { 6, 6, 8, 9, 11, 11, 13, 13, 15,
139 15 }, new int[] { 8, 9 }, 3, 1);
140 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
141 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
145 * Check protein residue 8 maps to [6, 8, 9]
147 SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 8, acfList);
148 assertEquals(2, sr.getResults().size());
149 SearchResultMatchI m = sr.getResults().get(0);
150 assertEquals(seq1.getDatasetSequence(), m.getSequence());
151 assertEquals(6, m.getStart());
152 assertEquals(6, m.getEnd());
153 m = sr.getResults().get(1);
154 assertEquals(seq1.getDatasetSequence(), m.getSequence());
155 assertEquals(8, m.getStart());
156 assertEquals(9, m.getEnd());
159 * Check protein residue 9 maps to [11, 13, 15]
161 sr = MappingUtils.buildSearchResults(aseq1, 9, acfList);
162 assertEquals(3, sr.getResults().size());
163 m = sr.getResults().get(0);
164 assertEquals(seq1.getDatasetSequence(), m.getSequence());
165 assertEquals(11, m.getStart());
166 assertEquals(11, m.getEnd());
167 m = sr.getResults().get(1);
168 assertEquals(seq1.getDatasetSequence(), m.getSequence());
169 assertEquals(13, m.getStart());
170 assertEquals(13, m.getEnd());
171 m = sr.getResults().get(2);
172 assertEquals(seq1.getDatasetSequence(), m.getSequence());
173 assertEquals(15, m.getStart());
174 assertEquals(15, m.getEnd());
177 * Check inverse mappings, from codons to protein
179 for (int i = 5; i < 18; i++)
181 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
182 int residue = (i == 6 || i == 8 || i == 9) ? 8 : (i == 11 || i == 13
186 assertEquals(0, sr.getResults().size());
189 assertEquals(1, sr.getResults().size());
190 m = sr.getResults().get(0);
191 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
192 assertEquals(residue, m.getStart());
193 assertEquals(residue, m.getEnd());
198 * Test mapping a sequence group made of entire sequences.
200 * @throws IOException
202 @Test(groups = { "Functional" })
203 public void testMapSequenceGroup_sequences() throws IOException
206 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
209 AlignmentI cdna = loadAlignment(">Seq1\nACG\n>Seq2\nTGA\n>Seq3\nTAC\n",
211 cdna.setDataset(null);
212 AlignmentI protein = loadAlignment(">Seq1\nK\n>Seq2\nL\n>Seq3\nQ\n",
214 protein.setDataset(null);
215 AlignedCodonFrame acf = new AlignedCodonFrame();
216 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 1 }, 3, 1);
217 for (int seq = 0; seq < 3; seq++)
219 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(), protein
220 .getSequenceAt(seq).getDatasetSequence(), map);
222 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
225 AlignViewportI dnaView = new AlignViewport(cdna);
226 AlignViewportI proteinView = new AlignViewport(protein);
227 protein.setCodonFrames(acfList);
230 * Select Seq1 and Seq3 in the protein (startRes=endRes=0)
232 SequenceGroup sg = new SequenceGroup();
233 sg.setColourText(true);
234 sg.setIdColour(Color.GREEN);
235 sg.setOutlineColour(Color.LIGHT_GRAY);
236 sg.addSequence(protein.getSequenceAt(0), false);
237 sg.addSequence(protein.getSequenceAt(2), false);
240 * Verify the mapped sequence group in dna
242 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
243 proteinView, dnaView);
244 assertTrue(mappedGroup.getColourText());
245 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
246 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
247 assertEquals(2, mappedGroup.getSequences().size());
248 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
249 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(1));
250 assertEquals(0, mappedGroup.getStartRes());
251 assertEquals(2, mappedGroup.getEndRes());
254 * Verify mapping sequence group from dna to protein
257 sg.addSequence(cdna.getSequenceAt(1), false);
258 sg.addSequence(cdna.getSequenceAt(0), false);
261 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
262 assertTrue(mappedGroup.getColourText());
263 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
264 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
265 assertEquals(2, mappedGroup.getSequences().size());
266 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
267 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
268 assertEquals(0, mappedGroup.getStartRes());
269 assertEquals(0, mappedGroup.getEndRes());
273 * Helper method to load an alignment and ensure dataset sequences are set up.
279 * @throws IOException
281 protected AlignmentI loadAlignment(final String data, String format)
284 AlignmentI a = new FormatAdapter().readFile(data,
285 AppletFormatAdapter.PASTE, format);
291 * Test mapping a column selection in protein to its dna equivalent
293 * @throws IOException
295 @Test(groups = { "Functional" })
296 public void testMapColumnSelection_proteinToDna() throws IOException
298 setupMappedAlignments();
300 ColumnSelection colsel = new ColumnSelection();
303 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
304 * in dna respectively, overall 0-4
306 colsel.addElement(0);
307 ColumnSelection cs = MappingUtils.mapColumnSelection(colsel,
308 proteinView, dnaView);
309 assertEquals("[0, 1, 2, 3, 4]", cs.getSelected().toString());
312 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
315 colsel.addElement(1);
316 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
317 assertEquals("[0, 1, 2, 3]", cs.getSelected().toString());
320 * Column 2 in protein picks up gaps only - no mapping
323 colsel.addElement(2);
324 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
325 assertEquals("[]", cs.getSelected().toString());
328 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
329 * 6-9, 6-10, 5-8 respectively, overall to 5-10
332 colsel.addElement(3);
333 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
334 assertEquals("[5, 6, 7, 8, 9, 10]", cs.getSelected().toString());
337 * Combine selection of columns 1 and 3 to get a discontiguous mapped
341 colsel.addElement(1);
342 colsel.addElement(3);
343 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
344 assertEquals("[0, 1, 2, 3, 5, 6, 7, 8, 9, 10]", cs.getSelected()
349 * Set up mappings for tests from 3 dna to 3 protein sequences. Sequences have
350 * offset start positions for a more general test case.
352 * @throws IOException
354 protected void setupMappedAlignments() throws IOException
357 * Map (upper-case = coding):
358 * Seq1/10-18 AC-GctGtC-T to Seq1/40 -K-P
359 * Seq2/20-27 Tc-GA-G-T-T to Seq2/20-27 L--Q
360 * Seq3/30-38 TtTT-AaCGg- to Seq3/60-61\nG--S
362 AlignmentI cdna = loadAlignment(">Seq1/10-18\nAC-GctGtC-T\n"
363 + ">Seq2/20-27\nTc-GA-G-T-Tc\n" + ">Seq3/30-38\nTtTT-AaCGg-\n",
365 cdna.setDataset(null);
366 AlignmentI protein = loadAlignment(
367 ">Seq1/40-41\n-K-P\n>Seq2/50-51\nL--Q\n>Seq3/60-61\nG--S\n",
369 protein.setDataset(null);
371 // map first dna to first protein seq
372 AlignedCodonFrame acf = new AlignedCodonFrame();
373 MapList map = new MapList(new int[] { 10, 12, 15, 15, 17, 18 },
374 new int[] { 40, 41 }, 3, 1);
375 acf.addMap(cdna.getSequenceAt(0).getDatasetSequence(), protein
376 .getSequenceAt(0).getDatasetSequence(), map);
378 // map second dna to second protein seq
379 map = new MapList(new int[] { 20, 20, 22, 23, 24, 26 }, new int[] { 50,
381 acf.addMap(cdna.getSequenceAt(1).getDatasetSequence(), protein
382 .getSequenceAt(1).getDatasetSequence(), map);
384 // map third dna to third protein seq
385 map = new MapList(new int[] { 30, 30, 32, 34, 36, 37 }, new int[] { 60,
387 acf.addMap(cdna.getSequenceAt(2).getDatasetSequence(), protein
388 .getSequenceAt(2).getDatasetSequence(), map);
389 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
392 dnaView = new AlignViewport(cdna);
393 proteinView = new AlignViewport(protein);
394 protein.setCodonFrames(acfList);
398 * Test mapping a column selection in dna to its protein equivalent
400 * @throws IOException
402 @Test(groups = { "Functional" })
403 public void testMapColumnSelection_dnaToProtein() throws IOException
405 setupMappedAlignments();
407 ColumnSelection colsel = new ColumnSelection();
410 * Column 0 in dna picks up first bases which map to residue 1, columns 0-1
413 colsel.addElement(0);
414 ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, dnaView,
416 assertEquals("[0, 1]", cs.getSelected().toString());
419 * Columns 3-5 in dna map to the first residues in protein Seq1, Seq2, and
420 * the first two in Seq3. Overall to columns 0, 1, 3 (col2 is all gaps).
422 colsel.addElement(3);
423 colsel.addElement(4);
424 colsel.addElement(5);
425 cs = MappingUtils.mapColumnSelection(colsel, dnaView, proteinView);
426 assertEquals("[0, 1, 3]", cs.getSelected().toString());
429 @Test(groups = { "Functional" })
430 public void testMapColumnSelection_null() throws IOException
432 setupMappedAlignments();
433 ColumnSelection cs = MappingUtils.mapColumnSelection(null, dnaView,
435 assertTrue("mapped selection not empty", cs.getSelected().isEmpty());
439 * Tests for the method that converts a series of [start, end] ranges to
442 @Test(groups = { "Functional" })
443 public void testFlattenRanges()
445 assertEquals("[1, 2, 3, 4]",
446 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 4 })));
449 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 2, 3,
453 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 1, 2,
456 "[1, 2, 3, 4, 7, 8, 9, 12]",
457 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 4, 7,
459 // trailing unpaired start position is ignored:
461 "[1, 2, 3, 4, 7, 8, 9, 12]",
462 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 4, 7,
467 * Test mapping a sequence group made of entire columns.
469 * @throws IOException
471 @Test(groups = { "Functional" })
472 public void testMapSequenceGroup_columns() throws IOException
475 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
478 AlignmentI cdna = loadAlignment(
479 ">Seq1\nACGGCA\n>Seq2\nTGACAG\n>Seq3\nTACGTA\n", "FASTA");
480 cdna.setDataset(null);
481 AlignmentI protein = loadAlignment(">Seq1\nKA\n>Seq2\nLQ\n>Seq3\nQV\n",
483 protein.setDataset(null);
484 AlignedCodonFrame acf = new AlignedCodonFrame();
485 MapList map = new MapList(new int[] { 1, 6 }, new int[] { 1, 2 }, 3, 1);
486 for (int seq = 0; seq < 3; seq++)
488 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(), protein
489 .getSequenceAt(seq).getDatasetSequence(), map);
491 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
494 AlignViewportI dnaView = new AlignViewport(cdna);
495 AlignViewportI proteinView = new AlignViewport(protein);
496 protein.setCodonFrames(acfList);
499 * Select all sequences, column 2 in the protein
501 SequenceGroup sg = new SequenceGroup();
502 sg.setColourText(true);
503 sg.setIdColour(Color.GREEN);
504 sg.setOutlineColour(Color.LIGHT_GRAY);
505 sg.addSequence(protein.getSequenceAt(0), false);
506 sg.addSequence(protein.getSequenceAt(1), false);
507 sg.addSequence(protein.getSequenceAt(2), false);
512 * Verify the mapped sequence group in dna
514 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
515 proteinView, dnaView);
516 assertTrue(mappedGroup.getColourText());
517 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
518 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
519 assertEquals(3, mappedGroup.getSequences().size());
520 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
521 assertSame(cdna.getSequenceAt(1), mappedGroup.getSequences().get(1));
522 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(2));
523 assertEquals(3, mappedGroup.getStartRes());
524 assertEquals(5, mappedGroup.getEndRes());
527 * Verify mapping sequence group from dna to protein
530 sg.addSequence(cdna.getSequenceAt(0), false);
531 sg.addSequence(cdna.getSequenceAt(1), false);
532 sg.addSequence(cdna.getSequenceAt(2), false);
533 // select columns 2 and 3 in DNA which span protein columns 0 and 1
536 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
537 assertTrue(mappedGroup.getColourText());
538 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
539 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
540 assertEquals(3, mappedGroup.getSequences().size());
541 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(0));
542 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(1));
543 assertSame(protein.getSequenceAt(2), mappedGroup.getSequences().get(2));
544 assertEquals(0, mappedGroup.getStartRes());
545 assertEquals(1, mappedGroup.getEndRes());
549 * Test mapping a sequence group made of a sequences/columns region.
551 * @throws IOException
553 @Test(groups = { "Functional" })
554 public void testMapSequenceGroup_region() throws IOException
557 * Set up gapped dna and protein Seq1/2/3 with mappings (held on the protein
560 AlignmentI cdna = loadAlignment(
561 ">Seq1\nA-CG-GC--AT-CA\n>Seq2\n-TG-AC-AG-T-AT\n>Seq3\n-T--ACG-TAAT-G\n",
563 cdna.setDataset(null);
564 AlignmentI protein = loadAlignment(
565 ">Seq1\n-KA-S\n>Seq2\n--L-QY\n>Seq3\nQ-V-M\n", "FASTA");
566 protein.setDataset(null);
567 AlignedCodonFrame acf = new AlignedCodonFrame();
568 MapList map = new MapList(new int[] { 1, 9 }, new int[] { 1, 3 }, 3, 1);
569 for (int seq = 0; seq < 3; seq++)
571 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(), protein
572 .getSequenceAt(seq).getDatasetSequence(), map);
574 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
577 AlignViewportI dnaView = new AlignViewport(cdna);
578 AlignViewportI proteinView = new AlignViewport(protein);
579 protein.setCodonFrames(acfList);
582 * Select Seq1 and Seq2 in the protein, column 1 (K/-). Expect mapped
583 * sequence group to cover Seq1, columns 0-3 (ACG). Because the selection
584 * only includes a gap in Seq2 there is no mappable selection region in the
587 SequenceGroup sg = new SequenceGroup();
588 sg.setColourText(true);
589 sg.setIdColour(Color.GREEN);
590 sg.setOutlineColour(Color.LIGHT_GRAY);
591 sg.addSequence(protein.getSequenceAt(0), false);
592 sg.addSequence(protein.getSequenceAt(1), false);
597 * Verify the mapped sequence group in dna
599 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
600 proteinView, dnaView);
601 assertTrue(mappedGroup.getColourText());
602 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
603 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
604 assertEquals(1, mappedGroup.getSequences().size());
605 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
606 // Seq2 in protein has a gap in column 1 - ignored
607 // Seq1 has K which should map to columns 0-3 in Seq1
608 assertEquals(0, mappedGroup.getStartRes());
609 assertEquals(3, mappedGroup.getEndRes());
612 * Now select cols 2-4 in protein. These cover Seq1:AS Seq2:LQ Seq3:VM which
613 * extend over DNA columns 3-12, 1-7, 6-13 respectively, or 1-13 overall.
617 mappedGroup = MappingUtils.mapSequenceGroup(sg, proteinView, dnaView);
618 assertEquals(1, mappedGroup.getStartRes());
619 assertEquals(13, mappedGroup.getEndRes());
622 * Verify mapping sequence group from dna to protein
625 sg.addSequence(cdna.getSequenceAt(0), false);
627 // select columns 4,5 - includes Seq1:codon2 (A) only
630 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
631 assertEquals(2, mappedGroup.getStartRes());
632 assertEquals(2, mappedGroup.getEndRes());
634 // add Seq2 to dna selection cols 4-5 include codons 1 and 2 (LQ)
635 sg.addSequence(cdna.getSequenceAt(1), false);
636 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
637 assertEquals(2, mappedGroup.getStartRes());
638 assertEquals(4, mappedGroup.getEndRes());
640 // add Seq3 to dna selection cols 4-5 include codon 1 (Q)
641 sg.addSequence(cdna.getSequenceAt(2), false);
642 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
643 assertEquals(0, mappedGroup.getStartRes());
644 assertEquals(4, mappedGroup.getEndRes());
647 @Test(groups = { "Functional" })
648 public void testFindMappingsForSequence()
650 SequenceI seq1 = new Sequence("Seq1", "ABC");
651 SequenceI seq2 = new Sequence("Seq2", "ABC");
652 SequenceI seq3 = new Sequence("Seq3", "ABC");
653 SequenceI seq4 = new Sequence("Seq4", "ABC");
654 seq1.createDatasetSequence();
655 seq2.createDatasetSequence();
656 seq3.createDatasetSequence();
657 seq4.createDatasetSequence();
660 * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1
662 AlignedCodonFrame acf1 = new AlignedCodonFrame();
663 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
664 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
665 AlignedCodonFrame acf2 = new AlignedCodonFrame();
666 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
667 AlignedCodonFrame acf3 = new AlignedCodonFrame();
668 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
670 List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
676 * Seq1 has three mappings
678 List<AlignedCodonFrame> result = MappingUtils.findMappingsForSequence(
680 assertEquals(3, result.size());
681 assertTrue(result.contains(acf1));
682 assertTrue(result.contains(acf2));
683 assertTrue(result.contains(acf3));
686 * Seq2 has two mappings
688 result = MappingUtils.findMappingsForSequence(seq2, mappings);
689 assertEquals(2, result.size());
690 assertTrue(result.contains(acf1));
691 assertTrue(result.contains(acf2));
694 * Seq3 has one mapping
696 result = MappingUtils.findMappingsForSequence(seq3, mappings);
697 assertEquals(1, result.size());
698 assertTrue(result.contains(acf3));
701 * Seq4 has no mappings
703 result = MappingUtils.findMappingsForSequence(seq4, mappings);
704 assertEquals(0, result.size());
706 result = MappingUtils.findMappingsForSequence(null, mappings);
707 assertEquals(0, result.size());
709 result = MappingUtils.findMappingsForSequence(seq1, null);
710 assertEquals(0, result.size());
712 result = MappingUtils.findMappingsForSequence(null, null);
713 assertEquals(0, result.size());
717 * just like the one above, but this time, we provide a set of sequences to
718 * subselect the mapping search
720 @Test(groups = { "Functional" })
721 public void testFindMappingsForSequenceAndOthers()
723 SequenceI seq1 = new Sequence("Seq1", "ABC");
724 SequenceI seq2 = new Sequence("Seq2", "ABC");
725 SequenceI seq3 = new Sequence("Seq3", "ABC");
726 SequenceI seq4 = new Sequence("Seq4", "ABC");
727 seq1.createDatasetSequence();
728 seq2.createDatasetSequence();
729 seq3.createDatasetSequence();
730 seq4.createDatasetSequence();
733 * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1, seq3 to seq4
735 AlignedCodonFrame acf1 = new AlignedCodonFrame();
736 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
737 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
738 AlignedCodonFrame acf2 = new AlignedCodonFrame();
739 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
740 AlignedCodonFrame acf3 = new AlignedCodonFrame();
741 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
742 AlignedCodonFrame acf4 = new AlignedCodonFrame();
743 acf4.addMap(seq3.getDatasetSequence(), seq4.getDatasetSequence(), map);
745 List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
754 List<AlignedCodonFrame> result = MappingUtils
755 .findMappingsForSequenceAndOthers(null, mappings,
756 Arrays.asList(new SequenceI[] { seq1, seq2 }));
757 assertTrue(result.isEmpty());
759 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, null,
760 Arrays.asList(new SequenceI[] { seq1, seq2 }));
761 assertTrue(result.isEmpty());
764 * Seq1 has three mappings, but filter argument will only accept
767 result = MappingUtils.findMappingsForSequenceAndOthers(
770 Arrays.asList(new SequenceI[] { seq1, seq2,
771 seq1.getDatasetSequence() }));
772 assertEquals(2, result.size());
773 assertTrue(result.contains(acf1));
774 assertTrue(result.contains(acf2));
775 assertFalse("Did not expect to find mapping acf3 - subselect failed",
776 result.contains(acf3));
778 "Did not expect to find mapping acf4 - doesn't involve sequence",
779 result.contains(acf4));
782 * and verify the no filter case
784 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, mappings,
786 assertEquals(3, result.size());
787 assertTrue(result.contains(acf1));
788 assertTrue(result.contains(acf2));
789 assertTrue(result.contains(acf3));
792 @Test(groups = { "Functional" })
793 public void testMapEditCommand()
795 SequenceI dna = new Sequence("Seq1", "---ACG---GCATCA", 8, 16);
796 SequenceI protein = new Sequence("Seq2", "-T-AS", 5, 7);
797 dna.createDatasetSequence();
798 protein.createDatasetSequence();
799 AlignedCodonFrame acf = new AlignedCodonFrame();
800 MapList map = new MapList(new int[] { 8, 16 }, new int[] { 5, 7 }, 3, 1);
801 acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
802 List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
805 AlignmentI prot = new Alignment(new SequenceI[] { protein });
806 prot.setCodonFrames(mappings);
807 AlignmentI nuc = new Alignment(new SequenceI[] { dna });
810 * construct and perform the edit command to turn "-T-AS" in to "-T-A--S"
811 * i.e. insert two gaps at column 4
813 EditCommand ec = new EditCommand();
814 final Edit edit = ec.new Edit(Action.INSERT_GAP,
815 new SequenceI[] { protein }, 4, 2, '-');
816 ec.appendEdit(edit, prot, true, null);
819 * the mapped edit command should be to insert 6 gaps before base 4 in the
820 * nucleotide sequence, which corresponds to aligned column 12 in the dna
822 EditCommand mappedEdit = MappingUtils.mapEditCommand(ec, false, nuc,
824 assertEquals(1, mappedEdit.getEdits().size());
825 Edit e = mappedEdit.getEdits().get(0);
826 assertEquals(1, e.getSequences().length);
827 assertEquals(dna, e.getSequences()[0]);
828 assertEquals(12, e.getPosition());
829 assertEquals(6, e.getNumber());
833 * Tests for the method that converts a series of [start, end] ranges to
834 * single positions, where the mapping is to a reverse strand i.e. start is
835 * greater than end point mapped to
837 @Test(groups = { "Functional" })
838 public void testFlattenRanges_reverseStrand()
840 assertEquals("[4, 3, 2, 1]",
841 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 1 })));
844 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 3, 2,
848 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 4, 3,
851 "[12, 9, 8, 7, 4, 3, 2, 1]",
852 Arrays.toString(MappingUtils.flattenRanges(new int[] { 12, 12,
854 // forwards and backwards anyone?
856 "[4, 5, 6, 3, 2, 1]",
857 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 6, 3,
859 // backwards and forwards
861 "[3, 2, 1, 4, 5, 6]",
862 Arrays.toString(MappingUtils.flattenRanges(new int[] { 3, 1, 4,
864 // trailing unpaired start position is ignored:
866 "[12, 9, 8, 7, 4, 3, 2]",
867 Arrays.toString(MappingUtils.flattenRanges(new int[] { 12, 12,
872 * Test mapping a column selection including hidden columns
874 * @throws IOException
876 @Test(groups = { "Functional" })
877 public void testMapColumnSelection_hiddenColumns() throws IOException
879 setupMappedAlignments();
881 ColumnSelection proteinSelection = new ColumnSelection();
884 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
885 * in dna respectively, overall 0-4
887 proteinSelection.hideColumns(0);
888 ColumnSelection dnaSelection = MappingUtils.mapColumnSelection(
889 proteinSelection, proteinView, dnaView);
890 assertEquals("[]", dnaSelection.getSelected().toString());
891 List<int[]> hidden = dnaSelection.getHiddenColumns();
892 assertEquals(1, hidden.size());
893 assertEquals("[0, 4]", Arrays.toString(hidden.get(0)));
896 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
898 proteinSelection.revealAllHiddenColumns();
899 // the unhidden columns are now marked selected!
900 assertEquals("[0]", proteinSelection.getSelected().toString());
901 // deselect these or hideColumns will be expanded to include 0
902 proteinSelection.clear();
903 proteinSelection.hideColumns(1);
904 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
905 proteinView, dnaView);
906 hidden = dnaSelection.getHiddenColumns();
907 assertEquals(1, hidden.size());
908 assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
911 * Column 2 in protein picks up gaps only - no mapping
913 proteinSelection.revealAllHiddenColumns();
914 proteinSelection.clear();
915 proteinSelection.hideColumns(2);
916 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
917 proteinView, dnaView);
918 assertTrue(dnaSelection.getHiddenColumns().isEmpty());
921 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
922 * 6-9, 6-10, 5-8 respectively, overall to 5-10
924 proteinSelection.revealAllHiddenColumns();
925 proteinSelection.clear();
926 proteinSelection.hideColumns(3); // 5-10 hidden in dna
927 proteinSelection.addElement(1); // 0-3 selected in dna
928 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
929 proteinView, dnaView);
930 assertEquals("[0, 1, 2, 3]", dnaSelection.getSelected().toString());
931 hidden = dnaSelection.getHiddenColumns();
932 assertEquals(1, hidden.size());
933 assertEquals("[5, 10]", Arrays.toString(hidden.get(0)));
936 * Combine hiding columns 1 and 3 to get discontiguous hidden columns
938 proteinSelection.revealAllHiddenColumns();
939 proteinSelection.clear();
940 proteinSelection.hideColumns(1);
941 proteinSelection.hideColumns(3);
942 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
943 proteinView, dnaView);
944 hidden = dnaSelection.getHiddenColumns();
945 assertEquals(2, hidden.size());
946 assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
947 assertEquals("[5, 10]", Arrays.toString(hidden.get(1)));
950 @Test(groups = { "Functional" })
951 public void testGetLength()
953 assertEquals(0, MappingUtils.getLength(null));
956 * [start, end] ranges
958 List<int[]> ranges = new ArrayList<int[]>();
959 assertEquals(0, MappingUtils.getLength(ranges));
960 ranges.add(new int[] { 1, 1 });
961 assertEquals(1, MappingUtils.getLength(ranges));
962 ranges.add(new int[] { 2, 10 });
963 assertEquals(10, MappingUtils.getLength(ranges));
964 ranges.add(new int[] { 20, 10 });
965 assertEquals(21, MappingUtils.getLength(ranges));
968 * [start, end, start, end...] ranges
971 ranges.add(new int[] { 1, 5, 8, 4 });
972 ranges.add(new int[] { 8, 2 });
973 ranges.add(new int[] { 12, 12 });
974 assertEquals(18, MappingUtils.getLength(ranges));
977 @Test(groups = { "Functional" })
978 public void testContains()
980 assertFalse(MappingUtils.contains(null, 1));
981 List<int[]> ranges = new ArrayList<int[]>();
982 assertFalse(MappingUtils.contains(ranges, 1));
984 ranges.add(new int[] { 1, 4 });
985 ranges.add(new int[] { 6, 6 });
986 ranges.add(new int[] { 8, 10 });
987 ranges.add(new int[] { 30, 20 });
988 ranges.add(new int[] { -16, -44 });
990 assertFalse(MappingUtils.contains(ranges, 0));
991 assertTrue(MappingUtils.contains(ranges, 1));
992 assertTrue(MappingUtils.contains(ranges, 2));
993 assertTrue(MappingUtils.contains(ranges, 3));
994 assertTrue(MappingUtils.contains(ranges, 4));
995 assertFalse(MappingUtils.contains(ranges, 5));
997 assertTrue(MappingUtils.contains(ranges, 6));
998 assertFalse(MappingUtils.contains(ranges, 7));
1000 assertTrue(MappingUtils.contains(ranges, 8));
1001 assertTrue(MappingUtils.contains(ranges, 9));
1002 assertTrue(MappingUtils.contains(ranges, 10));
1004 assertFalse(MappingUtils.contains(ranges, 31));
1005 assertTrue(MappingUtils.contains(ranges, 30));
1006 assertTrue(MappingUtils.contains(ranges, 29));
1007 assertTrue(MappingUtils.contains(ranges, 20));
1008 assertFalse(MappingUtils.contains(ranges, 19));
1010 assertFalse(MappingUtils.contains(ranges, -15));
1011 assertTrue(MappingUtils.contains(ranges, -16));
1012 assertTrue(MappingUtils.contains(ranges, -44));
1013 assertFalse(MappingUtils.contains(ranges, -45));
1017 * Test the method that drops positions from the start of a mapped range
1019 @Test(groups = "Functional")
1020 public void testRemoveStartPositions()
1022 int[] ranges = new int[] { 1, 10 };
1023 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
1024 assertEquals("[1, 10]", Arrays.toString(adjusted));
1026 adjusted = MappingUtils.removeStartPositions(1, ranges);
1027 assertEquals("[2, 10]", Arrays.toString(adjusted));
1028 assertEquals("[1, 10]", Arrays.toString(ranges));
1031 adjusted = MappingUtils.removeStartPositions(1, ranges);
1032 assertEquals("[3, 10]", Arrays.toString(adjusted));
1033 assertEquals("[2, 10]", Arrays.toString(ranges));
1035 ranges = new int[] { 2, 3, 10, 12 };
1036 adjusted = MappingUtils.removeStartPositions(1, ranges);
1037 assertEquals("[3, 3, 10, 12]", Arrays.toString(adjusted));
1038 assertEquals("[2, 3, 10, 12]", Arrays.toString(ranges));
1040 ranges = new int[] { 2, 2, 8, 12 };
1041 adjusted = MappingUtils.removeStartPositions(1, ranges);
1042 assertEquals("[8, 12]", Arrays.toString(adjusted));
1043 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
1045 ranges = new int[] { 2, 2, 8, 12 };
1046 adjusted = MappingUtils.removeStartPositions(2, ranges);
1047 assertEquals("[9, 12]", Arrays.toString(adjusted));
1048 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
1050 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
1051 adjusted = MappingUtils.removeStartPositions(1, ranges);
1052 assertEquals("[4, 4, 9, 12]", Arrays.toString(adjusted));
1053 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
1055 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
1056 adjusted = MappingUtils.removeStartPositions(2, ranges);
1057 assertEquals("[9, 12]", Arrays.toString(adjusted));
1058 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
1060 ranges = new int[] { 2, 3, 9, 12 };
1061 adjusted = MappingUtils.removeStartPositions(3, ranges);
1062 assertEquals("[10, 12]", Arrays.toString(adjusted));
1063 assertEquals("[2, 3, 9, 12]", Arrays.toString(ranges));
1067 * Test the method that drops positions from the start of a mapped range, on
1068 * the reverse strand
1070 @Test(groups = "Functional")
1071 public void testRemoveStartPositions_reverseStrand()
1073 int[] ranges = new int[] { 10, 1 };
1074 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
1075 assertEquals("[10, 1]", Arrays.toString(adjusted));
1076 assertEquals("[10, 1]", Arrays.toString(ranges));
1079 adjusted = MappingUtils.removeStartPositions(1, ranges);
1080 assertEquals("[9, 1]", Arrays.toString(adjusted));
1081 assertEquals("[10, 1]", Arrays.toString(ranges));
1084 adjusted = MappingUtils.removeStartPositions(1, ranges);
1085 assertEquals("[8, 1]", Arrays.toString(adjusted));
1086 assertEquals("[9, 1]", Arrays.toString(ranges));
1088 ranges = new int[] { 12, 11, 9, 6 };
1089 adjusted = MappingUtils.removeStartPositions(1, ranges);
1090 assertEquals("[11, 11, 9, 6]", Arrays.toString(adjusted));
1091 assertEquals("[12, 11, 9, 6]", Arrays.toString(ranges));
1093 ranges = new int[] { 12, 12, 8, 4 };
1094 adjusted = MappingUtils.removeStartPositions(1, ranges);
1095 assertEquals("[8, 4]", Arrays.toString(adjusted));
1096 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1098 ranges = new int[] { 12, 12, 8, 4 };
1099 adjusted = MappingUtils.removeStartPositions(2, ranges);
1100 assertEquals("[7, 4]", Arrays.toString(adjusted));
1101 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1103 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1104 adjusted = MappingUtils.removeStartPositions(1, ranges);
1105 assertEquals("[10, 10, 8, 4]", Arrays.toString(adjusted));
1106 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1108 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1109 adjusted = MappingUtils.removeStartPositions(2, ranges);
1110 assertEquals("[8, 4]", Arrays.toString(adjusted));
1111 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1113 ranges = new int[] { 12, 11, 8, 4 };
1114 adjusted = MappingUtils.removeStartPositions(3, ranges);
1115 assertEquals("[7, 4]", Arrays.toString(adjusted));
1116 assertEquals("[12, 11, 8, 4]", Arrays.toString(ranges));