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.SearchResults;
37 import jalview.datamodel.SearchResults.Match;
38 import jalview.datamodel.Sequence;
39 import jalview.datamodel.SequenceGroup;
40 import jalview.datamodel.SequenceI;
41 import jalview.gui.AlignViewport;
42 import jalview.io.DataSourceType;
43 import jalview.io.FileFormat;
44 import jalview.io.FileFormatI;
45 import jalview.io.FormatAdapter;
47 import java.awt.Color;
48 import java.io.IOException;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.List;
53 import org.testng.annotations.Test;
55 public class MappingUtilsTest
57 private AlignViewportI dnaView;
59 private AlignViewportI proteinView;
62 * Simple test of mapping with no intron involved.
64 @Test(groups = { "Functional" })
65 public void testBuildSearchResults()
67 final Sequence seq1 = new Sequence("Seq1/5-10", "C-G-TA-GC");
68 seq1.createDatasetSequence();
70 final Sequence aseq1 = new Sequence("Seq1/12-13", "-P-R");
71 aseq1.createDatasetSequence();
74 * Map dna bases 5-10 to protein residues 12-13
76 AlignedCodonFrame acf = new AlignedCodonFrame();
77 MapList map = new MapList(new int[] { 5, 10 }, new int[] { 12, 13 }, 3,
79 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
80 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
84 * Check protein residue 12 maps to codon 5-7, 13 to codon 8-10
86 SearchResults sr = MappingUtils.buildSearchResults(aseq1, 12, acfList);
87 assertEquals(1, sr.getResults().size());
88 Match m = sr.getResults().get(0);
89 assertEquals(seq1.getDatasetSequence(), m.getSequence());
90 assertEquals(5, m.getStart());
91 assertEquals(7, m.getEnd());
92 sr = MappingUtils.buildSearchResults(aseq1, 13, acfList);
93 assertEquals(1, sr.getResults().size());
94 m = sr.getResults().get(0);
95 assertEquals(seq1.getDatasetSequence(), m.getSequence());
96 assertEquals(8, m.getStart());
97 assertEquals(10, m.getEnd());
100 * Check inverse mappings, from codons 5-7, 8-10 to protein 12, 13
102 for (int i = 5; i < 11; i++)
104 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
105 assertEquals(1, sr.getResults().size());
106 m = sr.getResults().get(0);
107 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
108 int residue = i > 7 ? 13 : 12;
109 assertEquals(residue, m.getStart());
110 assertEquals(residue, m.getEnd());
115 * Simple test of mapping with introns involved.
117 @Test(groups = { "Functional" })
118 public void testBuildSearchResults_withIntron()
120 final Sequence seq1 = new Sequence("Seq1/5-17", "c-G-tAGa-GcAgCtt");
121 seq1.createDatasetSequence();
123 final Sequence aseq1 = new Sequence("Seq1/8-9", "-E-D");
124 aseq1.createDatasetSequence();
127 * Map dna bases [6, 8, 9], [11, 13, 115] to protein residues 8 and 9
129 AlignedCodonFrame acf = new AlignedCodonFrame();
130 MapList map = new MapList(new int[] { 6, 6, 8, 9, 11, 11, 13, 13, 15,
131 15 }, new int[] { 8, 9 }, 3, 1);
132 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
133 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
137 * Check protein residue 8 maps to [6, 8, 9]
139 SearchResults sr = MappingUtils.buildSearchResults(aseq1, 8, acfList);
140 assertEquals(2, sr.getResults().size());
141 Match m = sr.getResults().get(0);
142 assertEquals(seq1.getDatasetSequence(), m.getSequence());
143 assertEquals(6, m.getStart());
144 assertEquals(6, m.getEnd());
145 m = sr.getResults().get(1);
146 assertEquals(seq1.getDatasetSequence(), m.getSequence());
147 assertEquals(8, m.getStart());
148 assertEquals(9, m.getEnd());
151 * Check protein residue 9 maps to [11, 13, 15]
153 sr = MappingUtils.buildSearchResults(aseq1, 9, acfList);
154 assertEquals(3, sr.getResults().size());
155 m = sr.getResults().get(0);
156 assertEquals(seq1.getDatasetSequence(), m.getSequence());
157 assertEquals(11, m.getStart());
158 assertEquals(11, m.getEnd());
159 m = sr.getResults().get(1);
160 assertEquals(seq1.getDatasetSequence(), m.getSequence());
161 assertEquals(13, m.getStart());
162 assertEquals(13, m.getEnd());
163 m = sr.getResults().get(2);
164 assertEquals(seq1.getDatasetSequence(), m.getSequence());
165 assertEquals(15, m.getStart());
166 assertEquals(15, m.getEnd());
169 * Check inverse mappings, from codons to protein
171 for (int i = 5; i < 18; i++)
173 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
174 int residue = (i == 6 || i == 8 || i == 9) ? 8 : (i == 11 || i == 13
178 assertEquals(0, sr.getResults().size());
181 assertEquals(1, sr.getResults().size());
182 m = sr.getResults().get(0);
183 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
184 assertEquals(residue, m.getStart());
185 assertEquals(residue, m.getEnd());
190 * Test mapping a sequence group made of entire sequences.
192 * @throws IOException
194 @Test(groups = { "Functional" })
195 public void testMapSequenceGroup_sequences() throws IOException
198 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
201 AlignmentI cdna = loadAlignment(">Seq1\nACG\n>Seq2\nTGA\n>Seq3\nTAC\n",
203 cdna.setDataset(null);
204 AlignmentI protein = loadAlignment(">Seq1\nK\n>Seq2\nL\n>Seq3\nQ\n",
206 protein.setDataset(null);
207 AlignedCodonFrame acf = new AlignedCodonFrame();
208 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 1 }, 3, 1);
209 for (int seq = 0; seq < 3; seq++)
211 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(), protein
212 .getSequenceAt(seq).getDatasetSequence(), map);
214 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
217 AlignViewportI dnaView = new AlignViewport(cdna);
218 AlignViewportI proteinView = new AlignViewport(protein);
219 protein.setCodonFrames(acfList);
222 * Select Seq1 and Seq3 in the protein (startRes=endRes=0)
224 SequenceGroup sg = new SequenceGroup();
225 sg.setColourText(true);
226 sg.setIdColour(Color.GREEN);
227 sg.setOutlineColour(Color.LIGHT_GRAY);
228 sg.addSequence(protein.getSequenceAt(0), false);
229 sg.addSequence(protein.getSequenceAt(2), false);
232 * Verify the mapped sequence group in dna
234 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
235 proteinView, dnaView);
236 assertTrue(mappedGroup.getColourText());
237 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
238 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
239 assertEquals(2, mappedGroup.getSequences().size());
240 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
241 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(1));
242 assertEquals(0, mappedGroup.getStartRes());
243 assertEquals(2, mappedGroup.getEndRes());
246 * Verify mapping sequence group from dna to protein
249 sg.addSequence(cdna.getSequenceAt(1), false);
250 sg.addSequence(cdna.getSequenceAt(0), false);
253 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
254 assertTrue(mappedGroup.getColourText());
255 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
256 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
257 assertEquals(2, mappedGroup.getSequences().size());
258 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
259 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
260 assertEquals(0, mappedGroup.getStartRes());
261 assertEquals(0, mappedGroup.getEndRes());
265 * Helper method to load an alignment and ensure dataset sequences are set up.
271 * @throws IOException
273 protected AlignmentI loadAlignment(final String data, FileFormatI format)
276 AlignmentI a = new FormatAdapter().readFile(data,
277 DataSourceType.PASTE, format);
283 * Test mapping a column selection in protein to its dna equivalent
285 * @throws IOException
287 @Test(groups = { "Functional" })
288 public void testMapColumnSelection_proteinToDna() throws IOException
290 setupMappedAlignments();
292 ColumnSelection colsel = new ColumnSelection();
295 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
296 * in dna respectively, overall 0-4
298 colsel.addElement(0);
299 ColumnSelection cs = MappingUtils.mapColumnSelection(colsel,
300 proteinView, dnaView);
301 assertEquals("[0, 1, 2, 3, 4]", cs.getSelected().toString());
304 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
307 colsel.addElement(1);
308 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
309 assertEquals("[0, 1, 2, 3]", cs.getSelected().toString());
312 * Column 2 in protein picks up gaps only - no mapping
315 colsel.addElement(2);
316 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
317 assertEquals("[]", cs.getSelected().toString());
320 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
321 * 6-9, 6-10, 5-8 respectively, overall to 5-10
324 colsel.addElement(3);
325 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
326 assertEquals("[5, 6, 7, 8, 9, 10]", cs.getSelected().toString());
329 * Combine selection of columns 1 and 3 to get a discontiguous mapped
333 colsel.addElement(1);
334 colsel.addElement(3);
335 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
336 assertEquals("[0, 1, 2, 3, 5, 6, 7, 8, 9, 10]", cs.getSelected()
341 * Set up mappings for tests from 3 dna to 3 protein sequences. Sequences have
342 * offset start positions for a more general test case.
344 * @throws IOException
346 protected void setupMappedAlignments() throws IOException
349 * Map (upper-case = coding):
350 * Seq1/10-18 AC-GctGtC-T to Seq1/40 -K-P
351 * Seq2/20-27 Tc-GA-G-T-T to Seq2/20-27 L--Q
352 * Seq3/30-38 TtTT-AaCGg- to Seq3/60-61\nG--S
354 AlignmentI cdna = loadAlignment(">Seq1/10-18\nAC-GctGtC-T\n"
355 + ">Seq2/20-27\nTc-GA-G-T-Tc\n" + ">Seq3/30-38\nTtTT-AaCGg-\n",
357 cdna.setDataset(null);
358 AlignmentI protein = loadAlignment(
359 ">Seq1/40-41\n-K-P\n>Seq2/50-51\nL--Q\n>Seq3/60-61\nG--S\n",
361 protein.setDataset(null);
363 // map first dna to first protein seq
364 AlignedCodonFrame acf = new AlignedCodonFrame();
365 MapList map = new MapList(new int[] { 10, 12, 15, 15, 17, 18 },
366 new int[] { 40, 41 }, 3, 1);
367 acf.addMap(cdna.getSequenceAt(0).getDatasetSequence(), protein
368 .getSequenceAt(0).getDatasetSequence(), map);
370 // map second dna to second protein seq
371 map = new MapList(new int[] { 20, 20, 22, 23, 24, 26 }, new int[] { 50,
373 acf.addMap(cdna.getSequenceAt(1).getDatasetSequence(), protein
374 .getSequenceAt(1).getDatasetSequence(), map);
376 // map third dna to third protein seq
377 map = new MapList(new int[] { 30, 30, 32, 34, 36, 37 }, new int[] { 60,
379 acf.addMap(cdna.getSequenceAt(2).getDatasetSequence(), protein
380 .getSequenceAt(2).getDatasetSequence(), map);
381 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
384 dnaView = new AlignViewport(cdna);
385 proteinView = new AlignViewport(protein);
386 protein.setCodonFrames(acfList);
390 * Test mapping a column selection in dna to its protein equivalent
392 * @throws IOException
394 @Test(groups = { "Functional" })
395 public void testMapColumnSelection_dnaToProtein() throws IOException
397 setupMappedAlignments();
399 ColumnSelection colsel = new ColumnSelection();
402 * Column 0 in dna picks up first bases which map to residue 1, columns 0-1
405 colsel.addElement(0);
406 ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, dnaView,
408 assertEquals("[0, 1]", cs.getSelected().toString());
411 * Columns 3-5 in dna map to the first residues in protein Seq1, Seq2, and
412 * the first two in Seq3. Overall to columns 0, 1, 3 (col2 is all gaps).
414 colsel.addElement(3);
415 colsel.addElement(4);
416 colsel.addElement(5);
417 cs = MappingUtils.mapColumnSelection(colsel, dnaView, proteinView);
418 assertEquals("[0, 1, 3]", cs.getSelected().toString());
421 @Test(groups = { "Functional" })
422 public void testMapColumnSelection_null() throws IOException
424 setupMappedAlignments();
425 ColumnSelection cs = MappingUtils.mapColumnSelection(null, dnaView,
427 assertTrue("mapped selection not empty", cs.getSelected().isEmpty());
431 * Tests for the method that converts a series of [start, end] ranges to
434 @Test(groups = { "Functional" })
435 public void testFlattenRanges()
437 assertEquals("[1, 2, 3, 4]",
438 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 4 })));
441 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 2, 3,
445 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 1, 2,
448 "[1, 2, 3, 4, 7, 8, 9, 12]",
449 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 4, 7,
451 // trailing unpaired start position is ignored:
453 "[1, 2, 3, 4, 7, 8, 9, 12]",
454 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 4, 7,
459 * Test mapping a sequence group made of entire columns.
461 * @throws IOException
463 @Test(groups = { "Functional" })
464 public void testMapSequenceGroup_columns() throws IOException
467 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
470 AlignmentI cdna = loadAlignment(
471 ">Seq1\nACGGCA\n>Seq2\nTGACAG\n>Seq3\nTACGTA\n",
473 cdna.setDataset(null);
474 AlignmentI protein = loadAlignment(">Seq1\nKA\n>Seq2\nLQ\n>Seq3\nQV\n",
476 protein.setDataset(null);
477 AlignedCodonFrame acf = new AlignedCodonFrame();
478 MapList map = new MapList(new int[] { 1, 6 }, new int[] { 1, 2 }, 3, 1);
479 for (int seq = 0; seq < 3; seq++)
481 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(), protein
482 .getSequenceAt(seq).getDatasetSequence(), map);
484 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
487 AlignViewportI dnaView = new AlignViewport(cdna);
488 AlignViewportI proteinView = new AlignViewport(protein);
489 protein.setCodonFrames(acfList);
492 * Select all sequences, column 2 in the protein
494 SequenceGroup sg = new SequenceGroup();
495 sg.setColourText(true);
496 sg.setIdColour(Color.GREEN);
497 sg.setOutlineColour(Color.LIGHT_GRAY);
498 sg.addSequence(protein.getSequenceAt(0), false);
499 sg.addSequence(protein.getSequenceAt(1), false);
500 sg.addSequence(protein.getSequenceAt(2), false);
505 * Verify the mapped sequence group in dna
507 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
508 proteinView, dnaView);
509 assertTrue(mappedGroup.getColourText());
510 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
511 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
512 assertEquals(3, mappedGroup.getSequences().size());
513 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
514 assertSame(cdna.getSequenceAt(1), mappedGroup.getSequences().get(1));
515 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(2));
516 assertEquals(3, mappedGroup.getStartRes());
517 assertEquals(5, mappedGroup.getEndRes());
520 * Verify mapping sequence group from dna to protein
523 sg.addSequence(cdna.getSequenceAt(0), false);
524 sg.addSequence(cdna.getSequenceAt(1), false);
525 sg.addSequence(cdna.getSequenceAt(2), false);
526 // select columns 2 and 3 in DNA which span protein columns 0 and 1
529 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
530 assertTrue(mappedGroup.getColourText());
531 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
532 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
533 assertEquals(3, mappedGroup.getSequences().size());
534 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(0));
535 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(1));
536 assertSame(protein.getSequenceAt(2), mappedGroup.getSequences().get(2));
537 assertEquals(0, mappedGroup.getStartRes());
538 assertEquals(1, mappedGroup.getEndRes());
542 * Test mapping a sequence group made of a sequences/columns region.
544 * @throws IOException
546 @Test(groups = { "Functional" })
547 public void testMapSequenceGroup_region() throws IOException
550 * Set up gapped dna and protein Seq1/2/3 with mappings (held on the protein
553 AlignmentI cdna = loadAlignment(
554 ">Seq1\nA-CG-GC--AT-CA\n>Seq2\n-TG-AC-AG-T-AT\n>Seq3\n-T--ACG-TAAT-G\n",
556 cdna.setDataset(null);
557 AlignmentI protein = loadAlignment(
558 ">Seq1\n-KA-S\n>Seq2\n--L-QY\n>Seq3\nQ-V-M\n", FileFormat.Fasta);
559 protein.setDataset(null);
560 AlignedCodonFrame acf = new AlignedCodonFrame();
561 MapList map = new MapList(new int[] { 1, 9 }, new int[] { 1, 3 }, 3, 1);
562 for (int seq = 0; seq < 3; seq++)
564 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(), protein
565 .getSequenceAt(seq).getDatasetSequence(), map);
567 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
570 AlignViewportI dnaView = new AlignViewport(cdna);
571 AlignViewportI proteinView = new AlignViewport(protein);
572 protein.setCodonFrames(acfList);
575 * Select Seq1 and Seq2 in the protein, column 1 (K/-). Expect mapped
576 * sequence group to cover Seq1, columns 0-3 (ACG). Because the selection
577 * only includes a gap in Seq2 there is no mappable selection region in the
580 SequenceGroup sg = new SequenceGroup();
581 sg.setColourText(true);
582 sg.setIdColour(Color.GREEN);
583 sg.setOutlineColour(Color.LIGHT_GRAY);
584 sg.addSequence(protein.getSequenceAt(0), false);
585 sg.addSequence(protein.getSequenceAt(1), false);
590 * Verify the mapped sequence group in dna
592 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
593 proteinView, dnaView);
594 assertTrue(mappedGroup.getColourText());
595 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
596 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
597 assertEquals(1, mappedGroup.getSequences().size());
598 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
599 // Seq2 in protein has a gap in column 1 - ignored
600 // Seq1 has K which should map to columns 0-3 in Seq1
601 assertEquals(0, mappedGroup.getStartRes());
602 assertEquals(3, mappedGroup.getEndRes());
605 * Now select cols 2-4 in protein. These cover Seq1:AS Seq2:LQ Seq3:VM which
606 * extend over DNA columns 3-12, 1-7, 6-13 respectively, or 1-13 overall.
610 mappedGroup = MappingUtils.mapSequenceGroup(sg, proteinView, dnaView);
611 assertEquals(1, mappedGroup.getStartRes());
612 assertEquals(13, mappedGroup.getEndRes());
615 * Verify mapping sequence group from dna to protein
618 sg.addSequence(cdna.getSequenceAt(0), false);
620 // select columns 4,5 - includes Seq1:codon2 (A) only
623 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
624 assertEquals(2, mappedGroup.getStartRes());
625 assertEquals(2, mappedGroup.getEndRes());
627 // add Seq2 to dna selection cols 4-5 include codons 1 and 2 (LQ)
628 sg.addSequence(cdna.getSequenceAt(1), false);
629 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
630 assertEquals(2, mappedGroup.getStartRes());
631 assertEquals(4, mappedGroup.getEndRes());
633 // add Seq3 to dna selection cols 4-5 include codon 1 (Q)
634 sg.addSequence(cdna.getSequenceAt(2), false);
635 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
636 assertEquals(0, mappedGroup.getStartRes());
637 assertEquals(4, mappedGroup.getEndRes());
640 @Test(groups = { "Functional" })
641 public void testFindMappingsForSequence()
643 SequenceI seq1 = new Sequence("Seq1", "ABC");
644 SequenceI seq2 = new Sequence("Seq2", "ABC");
645 SequenceI seq3 = new Sequence("Seq3", "ABC");
646 SequenceI seq4 = new Sequence("Seq4", "ABC");
647 seq1.createDatasetSequence();
648 seq2.createDatasetSequence();
649 seq3.createDatasetSequence();
650 seq4.createDatasetSequence();
653 * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1
655 AlignedCodonFrame acf1 = new AlignedCodonFrame();
656 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
657 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
658 AlignedCodonFrame acf2 = new AlignedCodonFrame();
659 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
660 AlignedCodonFrame acf3 = new AlignedCodonFrame();
661 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
663 List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
669 * Seq1 has three mappings
671 List<AlignedCodonFrame> result = MappingUtils.findMappingsForSequence(
673 assertEquals(3, result.size());
674 assertTrue(result.contains(acf1));
675 assertTrue(result.contains(acf2));
676 assertTrue(result.contains(acf3));
679 * Seq2 has two mappings
681 result = MappingUtils.findMappingsForSequence(seq2, mappings);
682 assertEquals(2, result.size());
683 assertTrue(result.contains(acf1));
684 assertTrue(result.contains(acf2));
687 * Seq3 has one mapping
689 result = MappingUtils.findMappingsForSequence(seq3, mappings);
690 assertEquals(1, result.size());
691 assertTrue(result.contains(acf3));
694 * Seq4 has no mappings
696 result = MappingUtils.findMappingsForSequence(seq4, mappings);
697 assertEquals(0, result.size());
699 result = MappingUtils.findMappingsForSequence(null, mappings);
700 assertEquals(0, result.size());
702 result = MappingUtils.findMappingsForSequence(seq1, null);
703 assertEquals(0, result.size());
705 result = MappingUtils.findMappingsForSequence(null, null);
706 assertEquals(0, result.size());
709 @Test(groups = { "Functional" })
710 public void testMapEditCommand()
712 SequenceI dna = new Sequence("Seq1", "---ACG---GCATCA", 8, 16);
713 SequenceI protein = new Sequence("Seq2", "-T-AS", 5, 7);
714 dna.createDatasetSequence();
715 protein.createDatasetSequence();
716 AlignedCodonFrame acf = new AlignedCodonFrame();
717 MapList map = new MapList(new int[] { 8, 16 }, new int[] { 5, 7 }, 3, 1);
718 acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
719 List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
722 AlignmentI prot = new Alignment(new SequenceI[] { protein });
723 prot.setCodonFrames(mappings);
724 AlignmentI nuc = new Alignment(new SequenceI[] { dna });
727 * construct and perform the edit command to turn "-T-AS" in to "-T-A--S"
728 * i.e. insert two gaps at column 4
730 EditCommand ec = new EditCommand();
731 final Edit edit = ec.new Edit(Action.INSERT_GAP,
732 new SequenceI[] { protein }, 4, 2, '-');
733 ec.appendEdit(edit, prot, true, null);
736 * the mapped edit command should be to insert 6 gaps before base 4 in the
737 * nucleotide sequence, which corresponds to aligned column 12 in the dna
739 EditCommand mappedEdit = MappingUtils.mapEditCommand(ec, false, nuc,
741 assertEquals(1, mappedEdit.getEdits().size());
742 Edit e = mappedEdit.getEdits().get(0);
743 assertEquals(1, e.getSequences().length);
744 assertEquals(dna, e.getSequences()[0]);
745 assertEquals(12, e.getPosition());
746 assertEquals(6, e.getNumber());
750 * Tests for the method that converts a series of [start, end] ranges to
751 * single positions, where the mapping is to a reverse strand i.e. start is
752 * greater than end point mapped to
754 @Test(groups = { "Functional" })
755 public void testFlattenRanges_reverseStrand()
757 assertEquals("[4, 3, 2, 1]",
758 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 1 })));
761 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 3, 2,
765 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 4, 3,
768 "[12, 9, 8, 7, 4, 3, 2, 1]",
769 Arrays.toString(MappingUtils.flattenRanges(new int[] { 12, 12,
771 // forwards and backwards anyone?
773 "[4, 5, 6, 3, 2, 1]",
774 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 6, 3,
776 // backwards and forwards
778 "[3, 2, 1, 4, 5, 6]",
779 Arrays.toString(MappingUtils.flattenRanges(new int[] { 3, 1, 4,
781 // trailing unpaired start position is ignored:
783 "[12, 9, 8, 7, 4, 3, 2]",
784 Arrays.toString(MappingUtils.flattenRanges(new int[] { 12, 12,
789 * Test mapping a column selection including hidden columns
791 * @throws IOException
793 @Test(groups = { "Functional" })
794 public void testMapColumnSelection_hiddenColumns() throws IOException
796 setupMappedAlignments();
798 ColumnSelection proteinSelection = new ColumnSelection();
801 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
802 * in dna respectively, overall 0-4
804 proteinSelection.hideColumns(0);
805 ColumnSelection dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
806 proteinView, dnaView);
807 assertEquals("[]", dnaSelection.getSelected().toString());
808 List<int[]> hidden = dnaSelection.getHiddenColumns();
809 assertEquals(1, hidden.size());
810 assertEquals("[0, 4]", Arrays.toString(hidden.get(0)));
813 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
815 proteinSelection.revealAllHiddenColumns();
816 // the unhidden columns are now marked selected!
817 assertEquals("[0]", proteinSelection.getSelected().toString());
818 // deselect these or hideColumns will be expanded to include 0
819 proteinSelection.clear();
820 proteinSelection.hideColumns(1);
821 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection, proteinView, dnaView);
822 hidden = dnaSelection.getHiddenColumns();
823 assertEquals(1, hidden.size());
824 assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
827 * Column 2 in protein picks up gaps only - no mapping
829 proteinSelection.revealAllHiddenColumns();
830 proteinSelection.clear();
831 proteinSelection.hideColumns(2);
832 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection, proteinView, dnaView);
833 assertTrue(dnaSelection.getHiddenColumns().isEmpty());
836 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
837 * 6-9, 6-10, 5-8 respectively, overall to 5-10
839 proteinSelection.revealAllHiddenColumns();
840 proteinSelection.clear();
841 proteinSelection.hideColumns(3); // 5-10 hidden in dna
842 proteinSelection.addElement(1); // 0-3 selected in dna
843 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection, proteinView, dnaView);
844 assertEquals("[0, 1, 2, 3]", dnaSelection.getSelected().toString());
845 hidden = dnaSelection.getHiddenColumns();
846 assertEquals(1, hidden.size());
847 assertEquals("[5, 10]", Arrays.toString(hidden.get(0)));
850 * Combine hiding columns 1 and 3 to get discontiguous hidden columns
852 proteinSelection.revealAllHiddenColumns();
853 proteinSelection.clear();
854 proteinSelection.hideColumns(1);
855 proteinSelection.hideColumns(3);
856 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection, proteinView, dnaView);
857 hidden = dnaSelection.getHiddenColumns();
858 assertEquals(2, hidden.size());
859 assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
860 assertEquals("[5, 10]", Arrays.toString(hidden.get(1)));
863 @Test(groups = { "Functional" })
864 public void testGetLength()
866 assertEquals(0, MappingUtils.getLength(null));
869 * [start, end] ranges
871 List<int[]> ranges = new ArrayList<int[]>();
872 assertEquals(0, MappingUtils.getLength(ranges));
873 ranges.add(new int[] { 1, 1 });
874 assertEquals(1, MappingUtils.getLength(ranges));
875 ranges.add(new int[] { 2, 10 });
876 assertEquals(10, MappingUtils.getLength(ranges));
877 ranges.add(new int[] { 20, 10 });
878 assertEquals(21, MappingUtils.getLength(ranges));
881 * [start, end, start, end...] ranges
884 ranges.add(new int[] { 1, 5, 8, 4 });
885 ranges.add(new int[] { 8, 2 });
886 ranges.add(new int[] { 12, 12 });
887 assertEquals(18, MappingUtils.getLength(ranges));
890 @Test(groups = { "Functional" })
891 public void testContains()
893 assertFalse(MappingUtils.contains(null, 1));
894 List<int[]> ranges = new ArrayList<int[]>();
895 assertFalse(MappingUtils.contains(ranges, 1));
897 ranges.add(new int[] { 1, 4 });
898 ranges.add(new int[] { 6, 6 });
899 ranges.add(new int[] { 8, 10 });
900 ranges.add(new int[] { 30, 20 });
901 ranges.add(new int[] { -16, -44 });
903 assertFalse(MappingUtils.contains(ranges, 0));
904 assertTrue(MappingUtils.contains(ranges, 1));
905 assertTrue(MappingUtils.contains(ranges, 2));
906 assertTrue(MappingUtils.contains(ranges, 3));
907 assertTrue(MappingUtils.contains(ranges, 4));
908 assertFalse(MappingUtils.contains(ranges, 5));
910 assertTrue(MappingUtils.contains(ranges, 6));
911 assertFalse(MappingUtils.contains(ranges, 7));
913 assertTrue(MappingUtils.contains(ranges, 8));
914 assertTrue(MappingUtils.contains(ranges, 9));
915 assertTrue(MappingUtils.contains(ranges, 10));
917 assertFalse(MappingUtils.contains(ranges, 31));
918 assertTrue(MappingUtils.contains(ranges, 30));
919 assertTrue(MappingUtils.contains(ranges, 29));
920 assertTrue(MappingUtils.contains(ranges, 20));
921 assertFalse(MappingUtils.contains(ranges, 19));
923 assertFalse(MappingUtils.contains(ranges, -15));
924 assertTrue(MappingUtils.contains(ranges, -16));
925 assertTrue(MappingUtils.contains(ranges, -44));
926 assertFalse(MappingUtils.contains(ranges, -45));
930 * Test the method that drops positions from the start of a mapped range
932 @Test(groups = "Functional")
933 public void testRemoveStartPositions()
935 int[] ranges = new int[] { 1, 10 };
936 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
937 assertEquals("[1, 10]", Arrays.toString(adjusted));
939 adjusted = MappingUtils.removeStartPositions(1, ranges);
940 assertEquals("[2, 10]", Arrays.toString(adjusted));
941 assertEquals("[1, 10]", Arrays.toString(ranges));
944 adjusted = MappingUtils.removeStartPositions(1, ranges);
945 assertEquals("[3, 10]", Arrays.toString(adjusted));
946 assertEquals("[2, 10]", Arrays.toString(ranges));
948 ranges = new int[] { 2, 3, 10, 12 };
949 adjusted = MappingUtils.removeStartPositions(1, ranges);
950 assertEquals("[3, 3, 10, 12]", Arrays.toString(adjusted));
951 assertEquals("[2, 3, 10, 12]", Arrays.toString(ranges));
953 ranges = new int[] { 2, 2, 8, 12 };
954 adjusted = MappingUtils.removeStartPositions(1, ranges);
955 assertEquals("[8, 12]", Arrays.toString(adjusted));
956 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
958 ranges = new int[] { 2, 2, 8, 12 };
959 adjusted = MappingUtils.removeStartPositions(2, ranges);
960 assertEquals("[9, 12]", Arrays.toString(adjusted));
961 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
963 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
964 adjusted = MappingUtils.removeStartPositions(1, ranges);
965 assertEquals("[4, 4, 9, 12]", Arrays.toString(adjusted));
966 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
968 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
969 adjusted = MappingUtils.removeStartPositions(2, ranges);
970 assertEquals("[9, 12]", Arrays.toString(adjusted));
971 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
973 ranges = new int[] { 2, 3, 9, 12 };
974 adjusted = MappingUtils.removeStartPositions(3, ranges);
975 assertEquals("[10, 12]", Arrays.toString(adjusted));
976 assertEquals("[2, 3, 9, 12]", Arrays.toString(ranges));
980 * Test the method that drops positions from the start of a mapped range, on
983 @Test(groups = "Functional")
984 public void testRemoveStartPositions_reverseStrand()
986 int[] ranges = new int[] { 10, 1 };
987 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
988 assertEquals("[10, 1]", Arrays.toString(adjusted));
989 assertEquals("[10, 1]", Arrays.toString(ranges));
992 adjusted = MappingUtils.removeStartPositions(1, ranges);
993 assertEquals("[9, 1]", Arrays.toString(adjusted));
994 assertEquals("[10, 1]", Arrays.toString(ranges));
997 adjusted = MappingUtils.removeStartPositions(1, ranges);
998 assertEquals("[8, 1]", Arrays.toString(adjusted));
999 assertEquals("[9, 1]", Arrays.toString(ranges));
1001 ranges = new int[] { 12, 11, 9, 6 };
1002 adjusted = MappingUtils.removeStartPositions(1, ranges);
1003 assertEquals("[11, 11, 9, 6]", Arrays.toString(adjusted));
1004 assertEquals("[12, 11, 9, 6]", Arrays.toString(ranges));
1006 ranges = new int[] { 12, 12, 8, 4 };
1007 adjusted = MappingUtils.removeStartPositions(1, ranges);
1008 assertEquals("[8, 4]", Arrays.toString(adjusted));
1009 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1011 ranges = new int[] { 12, 12, 8, 4 };
1012 adjusted = MappingUtils.removeStartPositions(2, ranges);
1013 assertEquals("[7, 4]", Arrays.toString(adjusted));
1014 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1016 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1017 adjusted = MappingUtils.removeStartPositions(1, ranges);
1018 assertEquals("[10, 10, 8, 4]", Arrays.toString(adjusted));
1019 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1021 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1022 adjusted = MappingUtils.removeStartPositions(2, ranges);
1023 assertEquals("[8, 4]", Arrays.toString(adjusted));
1024 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1026 ranges = new int[] { 12, 11, 8, 4 };
1027 adjusted = MappingUtils.removeStartPositions(3, ranges);
1028 assertEquals("[7, 4]", Arrays.toString(adjusted));
1029 assertEquals("[12, 11, 8, 4]", Arrays.toString(ranges));