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.AppletFormatAdapter;
43 import jalview.io.FormatAdapter;
45 import java.awt.Color;
46 import java.io.IOException;
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.List;
51 import org.testng.annotations.Test;
53 public class MappingUtilsTest
55 private AlignViewportI dnaView;
57 private AlignViewportI proteinView;
60 * Simple test of mapping with no intron involved.
62 @Test(groups = { "Functional" })
63 public void testBuildSearchResults()
65 final Sequence seq1 = new Sequence("Seq1/5-10", "C-G-TA-GC");
66 seq1.createDatasetSequence();
68 final Sequence aseq1 = new Sequence("Seq1/12-13", "-P-R");
69 aseq1.createDatasetSequence();
72 * Map dna bases 5-10 to protein residues 12-13
74 AlignedCodonFrame acf = new AlignedCodonFrame();
75 MapList map = new MapList(new int[] { 5, 10 }, new int[] { 12, 13 }, 3,
77 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
78 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
82 * Check protein residue 12 maps to codon 5-7, 13 to codon 8-10
84 SearchResults sr = MappingUtils.buildSearchResults(aseq1, 12, acfList);
85 assertEquals(1, sr.getResults().size());
86 Match m = sr.getResults().get(0);
87 assertEquals(seq1.getDatasetSequence(), m.getSequence());
88 assertEquals(5, m.getStart());
89 assertEquals(7, m.getEnd());
90 sr = MappingUtils.buildSearchResults(aseq1, 13, acfList);
91 assertEquals(1, sr.getResults().size());
92 m = sr.getResults().get(0);
93 assertEquals(seq1.getDatasetSequence(), m.getSequence());
94 assertEquals(8, m.getStart());
95 assertEquals(10, m.getEnd());
98 * Check inverse mappings, from codons 5-7, 8-10 to protein 12, 13
100 for (int i = 5; i < 11; i++)
102 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
103 assertEquals(1, sr.getResults().size());
104 m = sr.getResults().get(0);
105 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
106 int residue = i > 7 ? 13 : 12;
107 assertEquals(residue, m.getStart());
108 assertEquals(residue, m.getEnd());
113 * Simple test of mapping with introns involved.
115 @Test(groups = { "Functional" })
116 public void testBuildSearchResults_withIntron()
118 final Sequence seq1 = new Sequence("Seq1/5-17", "c-G-tAGa-GcAgCtt");
119 seq1.createDatasetSequence();
121 final Sequence aseq1 = new Sequence("Seq1/8-9", "-E-D");
122 aseq1.createDatasetSequence();
125 * Map dna bases [6, 8, 9], [11, 13, 115] to protein residues 8 and 9
127 AlignedCodonFrame acf = new AlignedCodonFrame();
128 MapList map = new MapList(new int[] { 6, 6, 8, 9, 11, 11, 13, 13, 15,
129 15 }, new int[] { 8, 9 }, 3, 1);
130 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
131 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
135 * Check protein residue 8 maps to [6, 8, 9]
137 SearchResults sr = MappingUtils.buildSearchResults(aseq1, 8, acfList);
138 assertEquals(2, sr.getResults().size());
139 Match m = sr.getResults().get(0);
140 assertEquals(seq1.getDatasetSequence(), m.getSequence());
141 assertEquals(6, m.getStart());
142 assertEquals(6, m.getEnd());
143 m = sr.getResults().get(1);
144 assertEquals(seq1.getDatasetSequence(), m.getSequence());
145 assertEquals(8, m.getStart());
146 assertEquals(9, m.getEnd());
149 * Check protein residue 9 maps to [11, 13, 15]
151 sr = MappingUtils.buildSearchResults(aseq1, 9, acfList);
152 assertEquals(3, sr.getResults().size());
153 m = sr.getResults().get(0);
154 assertEquals(seq1.getDatasetSequence(), m.getSequence());
155 assertEquals(11, m.getStart());
156 assertEquals(11, m.getEnd());
157 m = sr.getResults().get(1);
158 assertEquals(seq1.getDatasetSequence(), m.getSequence());
159 assertEquals(13, m.getStart());
160 assertEquals(13, m.getEnd());
161 m = sr.getResults().get(2);
162 assertEquals(seq1.getDatasetSequence(), m.getSequence());
163 assertEquals(15, m.getStart());
164 assertEquals(15, m.getEnd());
167 * Check inverse mappings, from codons to protein
169 for (int i = 5; i < 18; i++)
171 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
172 int residue = (i == 6 || i == 8 || i == 9) ? 8 : (i == 11 || i == 13
176 assertEquals(0, sr.getResults().size());
179 assertEquals(1, sr.getResults().size());
180 m = sr.getResults().get(0);
181 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
182 assertEquals(residue, m.getStart());
183 assertEquals(residue, m.getEnd());
188 * Test mapping a sequence group made of entire sequences.
190 * @throws IOException
192 @Test(groups = { "Functional" })
193 public void testMapSequenceGroup_sequences() throws IOException
196 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
199 AlignmentI cdna = loadAlignment(">Seq1\nACG\n>Seq2\nTGA\n>Seq3\nTAC\n",
201 cdna.setDataset(null);
202 AlignmentI protein = loadAlignment(">Seq1\nK\n>Seq2\nL\n>Seq3\nQ\n",
204 protein.setDataset(null);
205 AlignedCodonFrame acf = new AlignedCodonFrame();
206 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 1 }, 3, 1);
207 for (int seq = 0; seq < 3; seq++)
209 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(), protein
210 .getSequenceAt(seq).getDatasetSequence(), map);
212 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
215 AlignViewportI dnaView = new AlignViewport(cdna);
216 AlignViewportI proteinView = new AlignViewport(protein);
217 protein.setCodonFrames(acfList);
220 * Select Seq1 and Seq3 in the protein (startRes=endRes=0)
222 SequenceGroup sg = new SequenceGroup();
223 sg.setColourText(true);
224 sg.setIdColour(Color.GREEN);
225 sg.setOutlineColour(Color.LIGHT_GRAY);
226 sg.addSequence(protein.getSequenceAt(0), false);
227 sg.addSequence(protein.getSequenceAt(2), false);
230 * Verify the mapped sequence group in dna
232 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
233 proteinView, dnaView);
234 assertTrue(mappedGroup.getColourText());
235 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
236 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
237 assertEquals(2, mappedGroup.getSequences().size());
238 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
239 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(1));
240 assertEquals(0, mappedGroup.getStartRes());
241 assertEquals(2, mappedGroup.getEndRes());
244 * Verify mapping sequence group from dna to protein
247 sg.addSequence(cdna.getSequenceAt(1), false);
248 sg.addSequence(cdna.getSequenceAt(0), false);
251 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
252 assertTrue(mappedGroup.getColourText());
253 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
254 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
255 assertEquals(2, mappedGroup.getSequences().size());
256 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
257 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
258 assertEquals(0, mappedGroup.getStartRes());
259 assertEquals(0, mappedGroup.getEndRes());
263 * Helper method to load an alignment and ensure dataset sequences are set up.
269 * @throws IOException
271 protected AlignmentI loadAlignment(final String data, String format)
274 AlignmentI a = new FormatAdapter().readFile(data,
275 AppletFormatAdapter.PASTE, format);
281 * Test mapping a column selection in protein to its dna equivalent
283 * @throws IOException
285 @Test(groups = { "Functional" })
286 public void testMapColumnSelection_proteinToDna() throws IOException
288 setupMappedAlignments();
290 ColumnSelection colsel = new ColumnSelection();
293 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
294 * in dna respectively, overall 0-4
296 colsel.addElement(0);
297 ColumnSelection cs = MappingUtils.mapColumnSelection(colsel,
298 proteinView, dnaView);
299 assertEquals("[0, 1, 2, 3, 4]", cs.getSelected().toString());
302 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
305 colsel.addElement(1);
306 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
307 assertEquals("[0, 1, 2, 3]", cs.getSelected().toString());
310 * Column 2 in protein picks up gaps only - no mapping
313 colsel.addElement(2);
314 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
315 assertEquals("[]", cs.getSelected().toString());
318 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
319 * 6-9, 6-10, 5-8 respectively, overall to 5-10
322 colsel.addElement(3);
323 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
324 assertEquals("[5, 6, 7, 8, 9, 10]", cs.getSelected().toString());
327 * Combine selection of columns 1 and 3 to get a discontiguous mapped
331 colsel.addElement(1);
332 colsel.addElement(3);
333 cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
334 assertEquals("[0, 1, 2, 3, 5, 6, 7, 8, 9, 10]", cs.getSelected()
339 * Set up mappings for tests from 3 dna to 3 protein sequences. Sequences have
340 * offset start positions for a more general test case.
342 * @throws IOException
344 protected void setupMappedAlignments() throws IOException
347 * Map (upper-case = coding):
348 * Seq1/10-18 AC-GctGtC-T to Seq1/40 -K-P
349 * Seq2/20-27 Tc-GA-G-T-T to Seq2/20-27 L--Q
350 * Seq3/30-38 TtTT-AaCGg- to Seq3/60-61\nG--S
352 AlignmentI cdna = loadAlignment(">Seq1/10-18\nAC-GctGtC-T\n"
353 + ">Seq2/20-27\nTc-GA-G-T-Tc\n" + ">Seq3/30-38\nTtTT-AaCGg-\n",
355 cdna.setDataset(null);
356 AlignmentI protein = loadAlignment(
357 ">Seq1/40-41\n-K-P\n>Seq2/50-51\nL--Q\n>Seq3/60-61\nG--S\n",
359 protein.setDataset(null);
361 // map first dna to first protein seq
362 AlignedCodonFrame acf = new AlignedCodonFrame();
363 MapList map = new MapList(new int[] { 10, 12, 15, 15, 17, 18 },
364 new int[] { 40, 41 }, 3, 1);
365 acf.addMap(cdna.getSequenceAt(0).getDatasetSequence(), protein
366 .getSequenceAt(0).getDatasetSequence(), map);
368 // map second dna to second protein seq
369 map = new MapList(new int[] { 20, 20, 22, 23, 24, 26 }, new int[] { 50,
371 acf.addMap(cdna.getSequenceAt(1).getDatasetSequence(), protein
372 .getSequenceAt(1).getDatasetSequence(), map);
374 // map third dna to third protein seq
375 map = new MapList(new int[] { 30, 30, 32, 34, 36, 37 }, new int[] { 60,
377 acf.addMap(cdna.getSequenceAt(2).getDatasetSequence(), protein
378 .getSequenceAt(2).getDatasetSequence(), map);
379 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
382 dnaView = new AlignViewport(cdna);
383 proteinView = new AlignViewport(protein);
384 protein.setCodonFrames(acfList);
388 * Test mapping a column selection in dna to its protein equivalent
390 * @throws IOException
392 @Test(groups = { "Functional" })
393 public void testMapColumnSelection_dnaToProtein() throws IOException
395 setupMappedAlignments();
397 ColumnSelection colsel = new ColumnSelection();
400 * Column 0 in dna picks up first bases which map to residue 1, columns 0-1
403 colsel.addElement(0);
404 ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, dnaView,
406 assertEquals("[0, 1]", cs.getSelected().toString());
409 * Columns 3-5 in dna map to the first residues in protein Seq1, Seq2, and
410 * the first two in Seq3. Overall to columns 0, 1, 3 (col2 is all gaps).
412 colsel.addElement(3);
413 colsel.addElement(4);
414 colsel.addElement(5);
415 cs = MappingUtils.mapColumnSelection(colsel, dnaView, proteinView);
416 assertEquals("[0, 1, 3]", cs.getSelected().toString());
419 @Test(groups = { "Functional" })
420 public void testMapColumnSelection_null() throws IOException
422 setupMappedAlignments();
423 ColumnSelection cs = MappingUtils.mapColumnSelection(null, dnaView,
425 assertTrue("mapped selection not empty", cs.getSelected().isEmpty());
429 * Tests for the method that converts a series of [start, end] ranges to
432 @Test(groups = { "Functional" })
433 public void testFlattenRanges()
435 assertEquals("[1, 2, 3, 4]",
436 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 4 })));
439 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 2, 3,
443 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 1, 2,
446 "[1, 2, 3, 4, 7, 8, 9, 12]",
447 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 4, 7,
449 // trailing unpaired start position is ignored:
451 "[1, 2, 3, 4, 7, 8, 9, 12]",
452 Arrays.toString(MappingUtils.flattenRanges(new int[] { 1, 4, 7,
457 * Test mapping a sequence group made of entire columns.
459 * @throws IOException
461 @Test(groups = { "Functional" })
462 public void testMapSequenceGroup_columns() throws IOException
465 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
468 AlignmentI cdna = loadAlignment(
469 ">Seq1\nACGGCA\n>Seq2\nTGACAG\n>Seq3\nTACGTA\n", "FASTA");
470 cdna.setDataset(null);
471 AlignmentI protein = loadAlignment(">Seq1\nKA\n>Seq2\nLQ\n>Seq3\nQV\n",
473 protein.setDataset(null);
474 AlignedCodonFrame acf = new AlignedCodonFrame();
475 MapList map = new MapList(new int[] { 1, 6 }, new int[] { 1, 2 }, 3, 1);
476 for (int seq = 0; seq < 3; seq++)
478 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(), protein
479 .getSequenceAt(seq).getDatasetSequence(), map);
481 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
484 AlignViewportI dnaView = new AlignViewport(cdna);
485 AlignViewportI proteinView = new AlignViewport(protein);
486 protein.setCodonFrames(acfList);
489 * Select all sequences, column 2 in the protein
491 SequenceGroup sg = new SequenceGroup();
492 sg.setColourText(true);
493 sg.setIdColour(Color.GREEN);
494 sg.setOutlineColour(Color.LIGHT_GRAY);
495 sg.addSequence(protein.getSequenceAt(0), false);
496 sg.addSequence(protein.getSequenceAt(1), false);
497 sg.addSequence(protein.getSequenceAt(2), false);
502 * Verify the mapped sequence group in dna
504 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
505 proteinView, dnaView);
506 assertTrue(mappedGroup.getColourText());
507 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
508 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
509 assertEquals(3, mappedGroup.getSequences().size());
510 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
511 assertSame(cdna.getSequenceAt(1), mappedGroup.getSequences().get(1));
512 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(2));
513 assertEquals(3, mappedGroup.getStartRes());
514 assertEquals(5, mappedGroup.getEndRes());
517 * Verify mapping sequence group from dna to protein
520 sg.addSequence(cdna.getSequenceAt(0), false);
521 sg.addSequence(cdna.getSequenceAt(1), false);
522 sg.addSequence(cdna.getSequenceAt(2), false);
523 // select columns 2 and 3 in DNA which span protein columns 0 and 1
526 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
527 assertTrue(mappedGroup.getColourText());
528 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
529 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
530 assertEquals(3, mappedGroup.getSequences().size());
531 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(0));
532 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(1));
533 assertSame(protein.getSequenceAt(2), mappedGroup.getSequences().get(2));
534 assertEquals(0, mappedGroup.getStartRes());
535 assertEquals(1, mappedGroup.getEndRes());
539 * Test mapping a sequence group made of a sequences/columns region.
541 * @throws IOException
543 @Test(groups = { "Functional" })
544 public void testMapSequenceGroup_region() throws IOException
547 * Set up gapped dna and protein Seq1/2/3 with mappings (held on the protein
550 AlignmentI cdna = loadAlignment(
551 ">Seq1\nA-CG-GC--AT-CA\n>Seq2\n-TG-AC-AG-T-AT\n>Seq3\n-T--ACG-TAAT-G\n",
553 cdna.setDataset(null);
554 AlignmentI protein = loadAlignment(
555 ">Seq1\n-KA-S\n>Seq2\n--L-QY\n>Seq3\nQ-V-M\n", "FASTA");
556 protein.setDataset(null);
557 AlignedCodonFrame acf = new AlignedCodonFrame();
558 MapList map = new MapList(new int[] { 1, 9 }, new int[] { 1, 3 }, 3, 1);
559 for (int seq = 0; seq < 3; seq++)
561 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(), protein
562 .getSequenceAt(seq).getDatasetSequence(), map);
564 List<AlignedCodonFrame> acfList = Arrays.asList(new AlignedCodonFrame[]
567 AlignViewportI dnaView = new AlignViewport(cdna);
568 AlignViewportI proteinView = new AlignViewport(protein);
569 protein.setCodonFrames(acfList);
572 * Select Seq1 and Seq2 in the protein, column 1 (K/-). Expect mapped
573 * sequence group to cover Seq1, columns 0-3 (ACG). Because the selection
574 * only includes a gap in Seq2 there is no mappable selection region in the
577 SequenceGroup sg = new SequenceGroup();
578 sg.setColourText(true);
579 sg.setIdColour(Color.GREEN);
580 sg.setOutlineColour(Color.LIGHT_GRAY);
581 sg.addSequence(protein.getSequenceAt(0), false);
582 sg.addSequence(protein.getSequenceAt(1), false);
587 * Verify the mapped sequence group in dna
589 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
590 proteinView, dnaView);
591 assertTrue(mappedGroup.getColourText());
592 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
593 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
594 assertEquals(1, mappedGroup.getSequences().size());
595 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
596 // Seq2 in protein has a gap in column 1 - ignored
597 // Seq1 has K which should map to columns 0-3 in Seq1
598 assertEquals(0, mappedGroup.getStartRes());
599 assertEquals(3, mappedGroup.getEndRes());
602 * Now select cols 2-4 in protein. These cover Seq1:AS Seq2:LQ Seq3:VM which
603 * extend over DNA columns 3-12, 1-7, 6-13 respectively, or 1-13 overall.
607 mappedGroup = MappingUtils.mapSequenceGroup(sg, proteinView, dnaView);
608 assertEquals(1, mappedGroup.getStartRes());
609 assertEquals(13, mappedGroup.getEndRes());
612 * Verify mapping sequence group from dna to protein
615 sg.addSequence(cdna.getSequenceAt(0), false);
617 // select columns 4,5 - includes Seq1:codon2 (A) only
620 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
621 assertEquals(2, mappedGroup.getStartRes());
622 assertEquals(2, mappedGroup.getEndRes());
624 // add Seq2 to dna selection cols 4-5 include codons 1 and 2 (LQ)
625 sg.addSequence(cdna.getSequenceAt(1), false);
626 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
627 assertEquals(2, mappedGroup.getStartRes());
628 assertEquals(4, mappedGroup.getEndRes());
630 // add Seq3 to dna selection cols 4-5 include codon 1 (Q)
631 sg.addSequence(cdna.getSequenceAt(2), false);
632 mappedGroup = MappingUtils.mapSequenceGroup(sg, dnaView, proteinView);
633 assertEquals(0, mappedGroup.getStartRes());
634 assertEquals(4, mappedGroup.getEndRes());
637 @Test(groups = { "Functional" })
638 public void testFindMappingsForSequence()
640 SequenceI seq1 = new Sequence("Seq1", "ABC");
641 SequenceI seq2 = new Sequence("Seq2", "ABC");
642 SequenceI seq3 = new Sequence("Seq3", "ABC");
643 SequenceI seq4 = new Sequence("Seq4", "ABC");
644 seq1.createDatasetSequence();
645 seq2.createDatasetSequence();
646 seq3.createDatasetSequence();
647 seq4.createDatasetSequence();
650 * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1
652 AlignedCodonFrame acf1 = new AlignedCodonFrame();
653 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
654 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
655 AlignedCodonFrame acf2 = new AlignedCodonFrame();
656 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
657 AlignedCodonFrame acf3 = new AlignedCodonFrame();
658 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
660 List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
666 * Seq1 has three mappings
668 List<AlignedCodonFrame> result = MappingUtils.findMappingsForSequence(
670 assertEquals(3, result.size());
671 assertTrue(result.contains(acf1));
672 assertTrue(result.contains(acf2));
673 assertTrue(result.contains(acf3));
676 * Seq2 has two mappings
678 result = MappingUtils.findMappingsForSequence(seq2, mappings);
679 assertEquals(2, result.size());
680 assertTrue(result.contains(acf1));
681 assertTrue(result.contains(acf2));
684 * Seq3 has one mapping
686 result = MappingUtils.findMappingsForSequence(seq3, mappings);
687 assertEquals(1, result.size());
688 assertTrue(result.contains(acf3));
691 * Seq4 has no mappings
693 result = MappingUtils.findMappingsForSequence(seq4, mappings);
694 assertEquals(0, result.size());
696 result = MappingUtils.findMappingsForSequence(null, mappings);
697 assertEquals(0, result.size());
699 result = MappingUtils.findMappingsForSequence(seq1, null);
700 assertEquals(0, result.size());
702 result = MappingUtils.findMappingsForSequence(null, null);
703 assertEquals(0, result.size());
706 @Test(groups = { "Functional" })
707 public void testMapEditCommand()
709 SequenceI dna = new Sequence("Seq1", "---ACG---GCATCA", 8, 16);
710 SequenceI protein = new Sequence("Seq2", "-T-AS", 5, 7);
711 dna.createDatasetSequence();
712 protein.createDatasetSequence();
713 AlignedCodonFrame acf = new AlignedCodonFrame();
714 MapList map = new MapList(new int[] { 8, 16 }, new int[] { 5, 7 }, 3, 1);
715 acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
716 List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
719 AlignmentI prot = new Alignment(new SequenceI[] { protein });
720 prot.setCodonFrames(mappings);
721 AlignmentI nuc = new Alignment(new SequenceI[] { dna });
724 * construct and perform the edit command to turn "-T-AS" in to "-T-A--S"
725 * i.e. insert two gaps at column 4
727 EditCommand ec = new EditCommand();
728 final Edit edit = ec.new Edit(Action.INSERT_GAP,
729 new SequenceI[] { protein }, 4, 2, '-');
730 ec.appendEdit(edit, prot, true, null);
733 * the mapped edit command should be to insert 6 gaps before base 4 in the
734 * nucleotide sequence, which corresponds to aligned column 12 in the dna
736 EditCommand mappedEdit = MappingUtils.mapEditCommand(ec, false, nuc,
738 assertEquals(1, mappedEdit.getEdits().size());
739 Edit e = mappedEdit.getEdits().get(0);
740 assertEquals(1, e.getSequences().length);
741 assertEquals(dna, e.getSequences()[0]);
742 assertEquals(12, e.getPosition());
743 assertEquals(6, e.getNumber());
747 * Tests for the method that converts a series of [start, end] ranges to
748 * single positions, where the mapping is to a reverse strand i.e. start is
749 * greater than end point mapped to
751 @Test(groups = { "Functional" })
752 public void testFlattenRanges_reverseStrand()
754 assertEquals("[4, 3, 2, 1]",
755 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 1 })));
758 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 3, 2,
762 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 4, 3,
765 "[12, 9, 8, 7, 4, 3, 2, 1]",
766 Arrays.toString(MappingUtils.flattenRanges(new int[] { 12, 12,
768 // forwards and backwards anyone?
770 "[4, 5, 6, 3, 2, 1]",
771 Arrays.toString(MappingUtils.flattenRanges(new int[] { 4, 6, 3,
773 // backwards and forwards
775 "[3, 2, 1, 4, 5, 6]",
776 Arrays.toString(MappingUtils.flattenRanges(new int[] { 3, 1, 4,
778 // trailing unpaired start position is ignored:
780 "[12, 9, 8, 7, 4, 3, 2]",
781 Arrays.toString(MappingUtils.flattenRanges(new int[] { 12, 12,
786 * Test mapping a column selection including hidden columns
788 * @throws IOException
790 @Test(groups = { "Functional" })
791 public void testMapColumnSelection_hiddenColumns() throws IOException
793 setupMappedAlignments();
795 ColumnSelection proteinSelection = new ColumnSelection();
798 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
799 * in dna respectively, overall 0-4
801 proteinSelection.hideColumns(0);
802 ColumnSelection dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
803 proteinView, dnaView);
804 assertEquals("[]", dnaSelection.getSelected().toString());
805 List<int[]> hidden = dnaSelection.getHiddenColumns();
806 assertEquals(1, hidden.size());
807 assertEquals("[0, 4]", Arrays.toString(hidden.get(0)));
810 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
812 proteinSelection.revealAllHiddenColumns();
813 // the unhidden columns are now marked selected!
814 assertEquals("[0]", proteinSelection.getSelected().toString());
815 // deselect these or hideColumns will be expanded to include 0
816 proteinSelection.clear();
817 proteinSelection.hideColumns(1);
818 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection, proteinView, dnaView);
819 hidden = dnaSelection.getHiddenColumns();
820 assertEquals(1, hidden.size());
821 assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
824 * Column 2 in protein picks up gaps only - no mapping
826 proteinSelection.revealAllHiddenColumns();
827 proteinSelection.clear();
828 proteinSelection.hideColumns(2);
829 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection, proteinView, dnaView);
830 assertTrue(dnaSelection.getHiddenColumns().isEmpty());
833 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
834 * 6-9, 6-10, 5-8 respectively, overall to 5-10
836 proteinSelection.revealAllHiddenColumns();
837 proteinSelection.clear();
838 proteinSelection.hideColumns(3); // 5-10 hidden in dna
839 proteinSelection.addElement(1); // 0-3 selected in dna
840 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection, proteinView, dnaView);
841 assertEquals("[0, 1, 2, 3]", dnaSelection.getSelected().toString());
842 hidden = dnaSelection.getHiddenColumns();
843 assertEquals(1, hidden.size());
844 assertEquals("[5, 10]", Arrays.toString(hidden.get(0)));
847 * Combine hiding columns 1 and 3 to get discontiguous hidden columns
849 proteinSelection.revealAllHiddenColumns();
850 proteinSelection.clear();
851 proteinSelection.hideColumns(1);
852 proteinSelection.hideColumns(3);
853 dnaSelection = MappingUtils.mapColumnSelection(proteinSelection, proteinView, dnaView);
854 hidden = dnaSelection.getHiddenColumns();
855 assertEquals(2, hidden.size());
856 assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
857 assertEquals("[5, 10]", Arrays.toString(hidden.get(1)));
860 @Test(groups = { "Functional" })
861 public void testGetLength()
863 assertEquals(0, MappingUtils.getLength(null));
866 * [start, end] ranges
868 List<int[]> ranges = new ArrayList<int[]>();
869 assertEquals(0, MappingUtils.getLength(ranges));
870 ranges.add(new int[] { 1, 1 });
871 assertEquals(1, MappingUtils.getLength(ranges));
872 ranges.add(new int[] { 2, 10 });
873 assertEquals(10, MappingUtils.getLength(ranges));
874 ranges.add(new int[] { 20, 10 });
875 assertEquals(21, MappingUtils.getLength(ranges));
878 * [start, end, start, end...] ranges
881 ranges.add(new int[] { 1, 5, 8, 4 });
882 ranges.add(new int[] { 8, 2 });
883 ranges.add(new int[] { 12, 12 });
884 assertEquals(18, MappingUtils.getLength(ranges));
887 @Test(groups = { "Functional" })
888 public void testContains()
890 assertFalse(MappingUtils.contains(null, 1));
891 List<int[]> ranges = new ArrayList<int[]>();
892 assertFalse(MappingUtils.contains(ranges, 1));
894 ranges.add(new int[] { 1, 4 });
895 ranges.add(new int[] { 6, 6 });
896 ranges.add(new int[] { 8, 10 });
897 ranges.add(new int[] { 30, 20 });
898 ranges.add(new int[] { -16, -44 });
900 assertFalse(MappingUtils.contains(ranges, 0));
901 assertTrue(MappingUtils.contains(ranges, 1));
902 assertTrue(MappingUtils.contains(ranges, 2));
903 assertTrue(MappingUtils.contains(ranges, 3));
904 assertTrue(MappingUtils.contains(ranges, 4));
905 assertFalse(MappingUtils.contains(ranges, 5));
907 assertTrue(MappingUtils.contains(ranges, 6));
908 assertFalse(MappingUtils.contains(ranges, 7));
910 assertTrue(MappingUtils.contains(ranges, 8));
911 assertTrue(MappingUtils.contains(ranges, 9));
912 assertTrue(MappingUtils.contains(ranges, 10));
914 assertFalse(MappingUtils.contains(ranges, 31));
915 assertTrue(MappingUtils.contains(ranges, 30));
916 assertTrue(MappingUtils.contains(ranges, 29));
917 assertTrue(MappingUtils.contains(ranges, 20));
918 assertFalse(MappingUtils.contains(ranges, 19));
920 assertFalse(MappingUtils.contains(ranges, -15));
921 assertTrue(MappingUtils.contains(ranges, -16));
922 assertTrue(MappingUtils.contains(ranges, -44));
923 assertFalse(MappingUtils.contains(ranges, -45));
927 * Test the method that drops positions from the start of a mapped range
929 @Test(groups = "Functional")
930 public void testRemoveStartPositions()
932 int[] ranges = new int[] { 1, 10 };
933 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
934 assertEquals("[1, 10]", Arrays.toString(adjusted));
936 adjusted = MappingUtils.removeStartPositions(1, ranges);
937 assertEquals("[2, 10]", Arrays.toString(adjusted));
938 assertEquals("[1, 10]", Arrays.toString(ranges));
941 adjusted = MappingUtils.removeStartPositions(1, ranges);
942 assertEquals("[3, 10]", Arrays.toString(adjusted));
943 assertEquals("[2, 10]", Arrays.toString(ranges));
945 ranges = new int[] { 2, 3, 10, 12 };
946 adjusted = MappingUtils.removeStartPositions(1, ranges);
947 assertEquals("[3, 3, 10, 12]", Arrays.toString(adjusted));
948 assertEquals("[2, 3, 10, 12]", Arrays.toString(ranges));
950 ranges = new int[] { 2, 2, 8, 12 };
951 adjusted = MappingUtils.removeStartPositions(1, ranges);
952 assertEquals("[8, 12]", Arrays.toString(adjusted));
953 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
955 ranges = new int[] { 2, 2, 8, 12 };
956 adjusted = MappingUtils.removeStartPositions(2, ranges);
957 assertEquals("[9, 12]", Arrays.toString(adjusted));
958 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
960 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
961 adjusted = MappingUtils.removeStartPositions(1, ranges);
962 assertEquals("[4, 4, 9, 12]", Arrays.toString(adjusted));
963 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
965 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
966 adjusted = MappingUtils.removeStartPositions(2, ranges);
967 assertEquals("[9, 12]", Arrays.toString(adjusted));
968 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
970 ranges = new int[] { 2, 3, 9, 12 };
971 adjusted = MappingUtils.removeStartPositions(3, ranges);
972 assertEquals("[10, 12]", Arrays.toString(adjusted));
973 assertEquals("[2, 3, 9, 12]", Arrays.toString(ranges));
977 * Test the method that drops positions from the start of a mapped range, on
980 @Test(groups = "Functional")
981 public void testRemoveStartPositions_reverseStrand()
983 int[] ranges = new int[] { 10, 1 };
984 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
985 assertEquals("[10, 1]", Arrays.toString(adjusted));
986 assertEquals("[10, 1]", Arrays.toString(ranges));
989 adjusted = MappingUtils.removeStartPositions(1, ranges);
990 assertEquals("[9, 1]", Arrays.toString(adjusted));
991 assertEquals("[10, 1]", Arrays.toString(ranges));
994 adjusted = MappingUtils.removeStartPositions(1, ranges);
995 assertEquals("[8, 1]", Arrays.toString(adjusted));
996 assertEquals("[9, 1]", Arrays.toString(ranges));
998 ranges = new int[] { 12, 11, 9, 6 };
999 adjusted = MappingUtils.removeStartPositions(1, ranges);
1000 assertEquals("[11, 11, 9, 6]", Arrays.toString(adjusted));
1001 assertEquals("[12, 11, 9, 6]", Arrays.toString(ranges));
1003 ranges = new int[] { 12, 12, 8, 4 };
1004 adjusted = MappingUtils.removeStartPositions(1, ranges);
1005 assertEquals("[8, 4]", Arrays.toString(adjusted));
1006 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1008 ranges = new int[] { 12, 12, 8, 4 };
1009 adjusted = MappingUtils.removeStartPositions(2, ranges);
1010 assertEquals("[7, 4]", Arrays.toString(adjusted));
1011 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1013 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1014 adjusted = MappingUtils.removeStartPositions(1, ranges);
1015 assertEquals("[10, 10, 8, 4]", Arrays.toString(adjusted));
1016 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1018 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1019 adjusted = MappingUtils.removeStartPositions(2, ranges);
1020 assertEquals("[8, 4]", Arrays.toString(adjusted));
1021 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1023 ranges = new int[] { 12, 11, 8, 4 };
1024 adjusted = MappingUtils.removeStartPositions(3, ranges);
1025 assertEquals("[7, 4]", Arrays.toString(adjusted));
1026 assertEquals("[12, 11, 8, 4]", Arrays.toString(ranges));