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.assertNull;
26 import static org.testng.AssertJUnit.assertSame;
27 import static org.testng.AssertJUnit.assertTrue;
28 import static org.testng.AssertJUnit.fail;
29 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
31 import java.awt.Color;
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Iterator;
36 import java.util.List;
38 import org.testng.annotations.BeforeClass;
39 import org.testng.annotations.Test;
41 import jalview.api.AlignViewportI;
42 import jalview.bin.Cache;
43 import jalview.commands.EditCommand;
44 import jalview.commands.EditCommand.Action;
45 import jalview.commands.EditCommand.Edit;
46 import jalview.datamodel.AlignedCodonFrame;
47 import jalview.datamodel.Alignment;
48 import jalview.datamodel.AlignmentI;
49 import jalview.datamodel.ColumnSelection;
50 import jalview.datamodel.HiddenColumns;
51 import jalview.datamodel.SearchResultMatchI;
52 import jalview.datamodel.SearchResultsI;
53 import jalview.datamodel.Sequence;
54 import jalview.datamodel.SequenceGroup;
55 import jalview.datamodel.SequenceI;
56 import jalview.gui.AlignViewport;
57 import jalview.gui.JvOptionPane;
58 import jalview.io.DataSourceType;
59 import jalview.io.FileFormat;
60 import jalview.io.FileFormatI;
61 import jalview.io.FormatAdapter;
63 public class MappingUtilsTest
65 @BeforeClass(alwaysRun = true)
71 @BeforeClass(alwaysRun = true)
72 public void setUpJvOptionPane()
74 JvOptionPane.setInteractiveMode(false);
75 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
78 private AlignViewportI dnaView;
80 private AlignViewportI proteinView;
83 * Simple test of mapping with no intron involved.
85 @Test(groups = { "Functional" })
86 public void testBuildSearchResults()
88 final Sequence seq1 = new Sequence("Seq1/5-10", "C-G-TA-GC");
89 seq1.createDatasetSequence();
91 final Sequence aseq1 = new Sequence("Seq1/12-13", "-P-R");
92 aseq1.createDatasetSequence();
95 * Map dna bases 5-10 to protein residues 12-13
97 AlignedCodonFrame acf = new AlignedCodonFrame();
98 MapList map = new MapList(new int[] { 5, 10 }, new int[] { 12, 13 }, 3,
100 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
101 List<AlignedCodonFrame> acfList = Arrays
102 .asList(new AlignedCodonFrame[]
106 * Check protein residue 12 maps to codon 5-7, 13 to codon 8-10
108 SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 12, acfList);
109 assertEquals(1, sr.getResults().size());
110 SearchResultMatchI m = sr.getResults().get(0);
111 assertEquals(seq1.getDatasetSequence(), m.getSequence());
112 assertEquals(5, m.getStart());
113 assertEquals(7, m.getEnd());
114 sr = MappingUtils.buildSearchResults(aseq1, 13, acfList);
115 assertEquals(1, sr.getResults().size());
116 m = sr.getResults().get(0);
117 assertEquals(seq1.getDatasetSequence(), m.getSequence());
118 assertEquals(8, m.getStart());
119 assertEquals(10, m.getEnd());
122 * Check inverse mappings, from codons 5-7, 8-10 to protein 12, 13
124 for (int i = 5; i < 11; i++)
126 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
127 assertEquals(1, sr.getResults().size());
128 m = sr.getResults().get(0);
129 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
130 int residue = i > 7 ? 13 : 12;
131 assertEquals(residue, m.getStart());
132 assertEquals(residue, m.getEnd());
137 * Simple test of mapping with introns involved.
139 @Test(groups = { "Functional" })
140 public void testBuildSearchResults_withIntron()
142 final Sequence seq1 = new Sequence("Seq1/5-17", "c-G-tAGa-GcAgCtt");
143 seq1.createDatasetSequence();
145 final Sequence aseq1 = new Sequence("Seq1/8-9", "-E-D");
146 aseq1.createDatasetSequence();
149 * Map dna bases [6, 8, 9], [11, 13, 115] to protein residues 8 and 9
151 AlignedCodonFrame acf = new AlignedCodonFrame();
152 MapList map = new MapList(
154 { 6, 6, 8, 9, 11, 11, 13, 13, 15, 15 }, new int[] { 8, 9 }, 3,
156 acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
157 List<AlignedCodonFrame> acfList = Arrays
158 .asList(new AlignedCodonFrame[]
162 * Check protein residue 8 maps to [6, 8, 9]
164 SearchResultsI sr = MappingUtils.buildSearchResults(aseq1, 8, acfList);
165 assertEquals(2, sr.getResults().size());
166 SearchResultMatchI m = sr.getResults().get(0);
167 assertEquals(seq1.getDatasetSequence(), m.getSequence());
168 assertEquals(6, m.getStart());
169 assertEquals(6, m.getEnd());
170 m = sr.getResults().get(1);
171 assertEquals(seq1.getDatasetSequence(), m.getSequence());
172 assertEquals(8, m.getStart());
173 assertEquals(9, m.getEnd());
176 * Check protein residue 9 maps to [11, 13, 15]
178 sr = MappingUtils.buildSearchResults(aseq1, 9, acfList);
179 assertEquals(3, sr.getResults().size());
180 m = sr.getResults().get(0);
181 assertEquals(seq1.getDatasetSequence(), m.getSequence());
182 assertEquals(11, m.getStart());
183 assertEquals(11, m.getEnd());
184 m = sr.getResults().get(1);
185 assertEquals(seq1.getDatasetSequence(), m.getSequence());
186 assertEquals(13, m.getStart());
187 assertEquals(13, m.getEnd());
188 m = sr.getResults().get(2);
189 assertEquals(seq1.getDatasetSequence(), m.getSequence());
190 assertEquals(15, m.getStart());
191 assertEquals(15, m.getEnd());
194 * Check inverse mappings, from codons to protein
196 for (int i = 5; i < 18; i++)
198 sr = MappingUtils.buildSearchResults(seq1, i, acfList);
199 int residue = (i == 6 || i == 8 || i == 9) ? 8
200 : (i == 11 || i == 13 || i == 15 ? 9 : 0);
203 assertEquals(0, sr.getResults().size());
206 assertEquals(1, sr.getResults().size());
207 m = sr.getResults().get(0);
208 assertEquals(aseq1.getDatasetSequence(), m.getSequence());
209 assertEquals(residue, m.getStart());
210 assertEquals(residue, m.getEnd());
215 * Test mapping a sequence group made of entire sequences.
217 * @throws IOException
219 @Test(groups = { "Functional" })
220 public void testMapSequenceGroup_sequences() throws IOException
223 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
226 AlignmentI cdna = loadAlignment(">Seq1\nACG\n>Seq2\nTGA\n>Seq3\nTAC\n",
228 cdna.setDataset(null);
229 AlignmentI protein = loadAlignment(">Seq1\nK\n>Seq2\nL\n>Seq3\nQ\n",
231 protein.setDataset(null);
232 AlignedCodonFrame acf = new AlignedCodonFrame();
233 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 1 }, 3, 1);
234 for (int seq = 0; seq < 3; seq++)
236 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(),
237 protein.getSequenceAt(seq).getDatasetSequence(), map);
239 List<AlignedCodonFrame> acfList = Arrays
240 .asList(new AlignedCodonFrame[]
243 AlignViewportI theDnaView = new AlignViewport(cdna);
244 AlignViewportI theProteinView = new AlignViewport(protein);
245 protein.setCodonFrames(acfList);
248 * Select Seq1 and Seq3 in the protein
250 SequenceGroup sg = new SequenceGroup();
251 sg.setColourText(true);
252 sg.setIdColour(Color.GREEN);
253 sg.setOutlineColour(Color.LIGHT_GRAY);
254 sg.addSequence(protein.getSequenceAt(0), false);
255 sg.addSequence(protein.getSequenceAt(2), false);
256 sg.setEndRes(protein.getWidth() - 1);
259 * Verify the mapped sequence group in dna
261 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
262 theProteinView, theDnaView);
263 assertTrue(mappedGroup.getColourText());
264 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
265 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
266 assertEquals(2, mappedGroup.getSequences().size());
267 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
268 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(1));
269 assertEquals(0, mappedGroup.getStartRes());
270 assertEquals(2, mappedGroup.getEndRes()); // 3 columns (1 codon)
273 * Verify mapping sequence group from dna to protein
276 sg.addSequence(cdna.getSequenceAt(1), false);
277 sg.addSequence(cdna.getSequenceAt(0), false);
280 mappedGroup = MappingUtils.mapSequenceGroup(sg, theDnaView,
282 assertTrue(mappedGroup.getColourText());
283 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
284 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
285 assertEquals(2, mappedGroup.getSequences().size());
286 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
287 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
288 assertEquals(0, mappedGroup.getStartRes());
289 assertEquals(0, mappedGroup.getEndRes());
293 * Helper method to load an alignment and ensure dataset sequences are set up.
299 * @throws IOException
301 protected AlignmentI loadAlignment(final String data, FileFormatI format)
304 AlignmentI a = new FormatAdapter().readFile(data, DataSourceType.PASTE,
311 * Test mapping a column selection in protein to its dna equivalent
313 * @throws IOException
315 @Test(groups = { "Functional" })
316 public void testMapColumnSelection_proteinToDna() throws IOException
318 setupMappedAlignments();
320 ColumnSelection colsel = new ColumnSelection();
321 HiddenColumns hidden = new HiddenColumns();
324 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
325 * in dna respectively, overall 0-4
327 colsel.addElement(0);
328 ColumnSelection cs = new ColumnSelection();
329 HiddenColumns hs = new HiddenColumns();
330 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
332 assertEquals("[0, 1, 2, 3, 4]", cs.getSelected().toString());
335 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
339 colsel.addElement(1);
340 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
342 assertEquals("[0, 1, 2, 3]", cs.getSelected().toString());
345 * Column 2 in protein picks up gaps only - no mapping
349 colsel.addElement(2);
350 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
352 assertEquals("[]", cs.getSelected().toString());
355 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
356 * 6-9, 6-10, 5-8 respectively, overall to 5-10
360 colsel.addElement(3);
361 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
363 assertEquals("[5, 6, 7, 8, 9, 10]", cs.getSelected().toString());
366 * Combine selection of columns 1 and 3 to get a discontiguous mapped
371 colsel.addElement(1);
372 colsel.addElement(3);
373 MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
375 assertEquals("[0, 1, 2, 3, 5, 6, 7, 8, 9, 10]",
376 cs.getSelected().toString());
380 * Set up mappings for tests from 3 dna to 3 protein sequences. Sequences have
381 * offset start positions for a more general test case.
383 * @throws IOException
385 protected void setupMappedAlignments() throws IOException
388 * Map (upper-case = coding):
389 * Seq1/10-18 AC-GctGtC-T to Seq1/40 -K-P
390 * Seq2/20-27 Tc-GA-G-T-T to Seq2/20-27 L--Q
391 * Seq3/30-38 TtTT-AaCGg- to Seq3/60-61\nG--S
393 AlignmentI cdna = loadAlignment(">Seq1/10-18\nAC-GctGtC-T\n"
394 + ">Seq2/20-27\nTc-GA-G-T-Tc\n" + ">Seq3/30-38\nTtTT-AaCGg-\n",
396 cdna.setDataset(null);
397 AlignmentI protein = loadAlignment(
398 ">Seq1/40-41\n-K-P\n>Seq2/50-51\nL--Q\n>Seq3/60-61\nG--S\n",
400 protein.setDataset(null);
402 // map first dna to first protein seq
403 AlignedCodonFrame acf = new AlignedCodonFrame();
404 MapList map = new MapList(new int[] { 10, 12, 15, 15, 17, 18 },
407 acf.addMap(cdna.getSequenceAt(0).getDatasetSequence(),
408 protein.getSequenceAt(0).getDatasetSequence(), map);
410 // map second dna to second protein seq
411 map = new MapList(new int[] { 20, 20, 22, 23, 24, 26 },
414 acf.addMap(cdna.getSequenceAt(1).getDatasetSequence(),
415 protein.getSequenceAt(1).getDatasetSequence(), map);
417 // map third dna to third protein seq
418 map = new MapList(new int[] { 30, 30, 32, 34, 36, 37 },
421 acf.addMap(cdna.getSequenceAt(2).getDatasetSequence(),
422 protein.getSequenceAt(2).getDatasetSequence(), map);
423 List<AlignedCodonFrame> acfList = Arrays
424 .asList(new AlignedCodonFrame[]
427 dnaView = new AlignViewport(cdna);
428 proteinView = new AlignViewport(protein);
429 protein.setCodonFrames(acfList);
433 * Test mapping a column selection in dna to its protein equivalent
435 * @throws IOException
437 @Test(groups = { "Functional" })
438 public void testMapColumnSelection_dnaToProtein() throws IOException
440 setupMappedAlignments();
442 ColumnSelection colsel = new ColumnSelection();
443 HiddenColumns hidden = new HiddenColumns();
446 * Column 0 in dna picks up first bases which map to residue 1, columns 0-1
449 ColumnSelection cs = new ColumnSelection();
450 HiddenColumns hs = new HiddenColumns();
451 colsel.addElement(0);
452 MappingUtils.mapColumnSelection(colsel, hidden, dnaView, proteinView,
454 assertEquals("[0, 1]", cs.getSelected().toString());
457 * Columns 3-5 in dna map to the first residues in protein Seq1, Seq2, and
458 * the first two in Seq3. Overall to columns 0, 1, 3 (col2 is all gaps).
460 colsel.addElement(3);
461 colsel.addElement(4);
462 colsel.addElement(5);
464 MappingUtils.mapColumnSelection(colsel, hidden, dnaView, proteinView,
466 assertEquals("[0, 1, 3]", cs.getSelected().toString());
469 @Test(groups = { "Functional" })
470 public void testMapColumnSelection_null() throws IOException
472 setupMappedAlignments();
473 ColumnSelection cs = new ColumnSelection();
474 HiddenColumns hs = new HiddenColumns();
475 MappingUtils.mapColumnSelection(null, null, dnaView, proteinView, cs,
477 assertTrue("mapped selection not empty", cs.getSelected().isEmpty());
481 * Tests for the method that converts a series of [start, end] ranges to
484 @Test(groups = { "Functional" })
485 public void testFlattenRanges()
487 assertEquals("[1, 2, 3, 4]",
488 Arrays.toString(MappingUtils.flattenRanges(new int[]
490 assertEquals("[1, 2, 3, 4]",
491 Arrays.toString(MappingUtils.flattenRanges(new int[]
493 assertEquals("[1, 2, 3, 4]",
494 Arrays.toString(MappingUtils.flattenRanges(new int[]
495 { 1, 1, 2, 2, 3, 3, 4, 4 })));
496 assertEquals("[1, 2, 3, 4, 7, 8, 9, 12]",
497 Arrays.toString(MappingUtils.flattenRanges(new int[]
498 { 1, 4, 7, 9, 12, 12 })));
499 // trailing unpaired start position is ignored:
500 assertEquals("[1, 2, 3, 4, 7, 8, 9, 12]",
501 Arrays.toString(MappingUtils.flattenRanges(new int[]
502 { 1, 4, 7, 9, 12, 12, 15 })));
506 * Test mapping a sequence group made of entire columns.
508 * @throws IOException
510 @Test(groups = { "Functional" })
511 public void testMapSequenceGroup_columns() throws IOException
514 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
517 AlignmentI cdna = loadAlignment(
518 ">Seq1\nACGGCA\n>Seq2\nTGACAG\n>Seq3\nTACGTA\n",
520 cdna.setDataset(null);
521 AlignmentI protein = loadAlignment(">Seq1\nKA\n>Seq2\nLQ\n>Seq3\nQV\n",
523 protein.setDataset(null);
524 AlignedCodonFrame acf = new AlignedCodonFrame();
525 MapList map = new MapList(new int[] { 1, 6 }, new int[] { 1, 2 }, 3, 1);
526 for (int seq = 0; seq < 3; seq++)
528 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(),
529 protein.getSequenceAt(seq).getDatasetSequence(), map);
531 List<AlignedCodonFrame> acfList = Arrays
532 .asList(new AlignedCodonFrame[]
535 AlignViewportI theDnaView = new AlignViewport(cdna);
536 AlignViewportI theProteinView = new AlignViewport(protein);
537 protein.setCodonFrames(acfList);
540 * Select all sequences, column 2 in the protein
542 SequenceGroup sg = new SequenceGroup();
543 sg.setColourText(true);
544 sg.setIdColour(Color.GREEN);
545 sg.setOutlineColour(Color.LIGHT_GRAY);
546 sg.addSequence(protein.getSequenceAt(0), false);
547 sg.addSequence(protein.getSequenceAt(1), false);
548 sg.addSequence(protein.getSequenceAt(2), false);
553 * Verify the mapped sequence group in dna
555 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
556 theProteinView, theDnaView);
557 assertTrue(mappedGroup.getColourText());
558 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
559 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
560 assertEquals(3, mappedGroup.getSequences().size());
561 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
562 assertSame(cdna.getSequenceAt(1), mappedGroup.getSequences().get(1));
563 assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(2));
564 assertEquals(3, mappedGroup.getStartRes());
565 assertEquals(5, mappedGroup.getEndRes());
568 * Verify mapping sequence group from dna to protein
571 sg.addSequence(cdna.getSequenceAt(0), false);
572 sg.addSequence(cdna.getSequenceAt(1), false);
573 sg.addSequence(cdna.getSequenceAt(2), false);
574 // select columns 2 and 3 in DNA which span protein columns 0 and 1
577 mappedGroup = MappingUtils.mapSequenceGroup(sg, theDnaView,
579 assertTrue(mappedGroup.getColourText());
580 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
581 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
582 assertEquals(3, mappedGroup.getSequences().size());
583 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(0));
584 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(1));
585 assertSame(protein.getSequenceAt(2), mappedGroup.getSequences().get(2));
586 assertEquals(0, mappedGroup.getStartRes());
587 assertEquals(1, mappedGroup.getEndRes());
591 * Test mapping a sequence group made of a sequences/columns region.
593 * @throws IOException
595 @Test(groups = { "Functional" })
596 public void testMapSequenceGroup_region() throws IOException
599 * Set up gapped dna and protein Seq1/2/3 with mappings (held on the protein
602 AlignmentI cdna = loadAlignment(
603 ">Cds11\nA-CG-GC--AT-CA\n>Cds2\n-TG-AC-AG-T-AT\n>Cds3\n-T--ACG-TAAT-G\n",
605 cdna.setDataset(null);
606 AlignmentI protein = loadAlignment(
607 ">Pep1\n-KA-S\n>Pep2\n--L-QY\n>Pep3\nQ-V-M\n",
609 protein.setDataset(null);
610 AlignedCodonFrame acf = new AlignedCodonFrame();
611 MapList map = new MapList(new int[] { 1, 9 }, new int[] { 1, 3 }, 3, 1);
612 for (int seq = 0; seq < 3; seq++)
614 acf.addMap(cdna.getSequenceAt(seq).getDatasetSequence(),
615 protein.getSequenceAt(seq).getDatasetSequence(), map);
617 List<AlignedCodonFrame> acfList = Arrays
618 .asList(new AlignedCodonFrame[]
621 AlignViewportI theDnaView = new AlignViewport(cdna);
622 AlignViewportI theProteinView = new AlignViewport(protein);
623 protein.setCodonFrames(acfList);
626 * Select Pep1 and Pep2 in the protein, column 1 (K/-). Expect mapped
627 * sequence group to cover Cds1, columns 0-3 (ACG). Although the selection
628 * only includes a gap in Cds2, mapped Cds2 is included with 'no columns'
630 SequenceGroup sg = new SequenceGroup();
631 sg.setColourText(true);
632 sg.setIdColour(Color.GREEN);
633 sg.setOutlineColour(Color.LIGHT_GRAY);
634 sg.addSequence(protein.getSequenceAt(0), false);
635 sg.addSequence(protein.getSequenceAt(1), false);
640 * Verify the mapped sequence group in dna
642 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
643 theProteinView, theDnaView);
644 assertTrue(mappedGroup.getColourText());
645 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
646 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
647 assertEquals(2, mappedGroup.getSequences().size());
648 assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
649 assertSame(cdna.getSequenceAt(1), mappedGroup.getSequences().get(1));
650 // Pep2 in protein has a gap in column 1 - doesn't map to any column
651 // Pep1 has K which should map to columns 0-3 in Cds1
652 assertEquals(0, mappedGroup.getStartRes());
653 assertEquals(3, mappedGroup.getEndRes());
656 * Now select cols 2-4 in protein. These cover Seq1:AS Seq2:LQ Seq3:VM which
657 * extend over DNA columns 3-12, 1-7, 6-13 respectively, or 1-13 overall.
661 mappedGroup = MappingUtils.mapSequenceGroup(sg, theProteinView,
663 assertEquals(1, mappedGroup.getStartRes());
664 assertEquals(13, mappedGroup.getEndRes());
667 * Verify mapping sequence group from dna to protein
670 sg.addSequence(cdna.getSequenceAt(0), false);
672 // select columns 4,5 - includes Seq1:codon2 (A) only
675 mappedGroup = MappingUtils.mapSequenceGroup(sg, theDnaView,
677 assertEquals(2, mappedGroup.getStartRes());
678 assertEquals(2, mappedGroup.getEndRes());
680 // add Seq2 to dna selection cols 4-5 include codons 1 and 2 (LQ)
681 sg.addSequence(cdna.getSequenceAt(1), false);
682 mappedGroup = MappingUtils.mapSequenceGroup(sg, theDnaView,
684 assertEquals(2, mappedGroup.getStartRes());
685 assertEquals(4, mappedGroup.getEndRes());
687 // add Seq3 to dna selection cols 4-5 include codon 1 (Q)
688 sg.addSequence(cdna.getSequenceAt(2), false);
689 mappedGroup = MappingUtils.mapSequenceGroup(sg, theDnaView,
691 assertEquals(0, mappedGroup.getStartRes());
692 assertEquals(4, mappedGroup.getEndRes());
695 @Test(groups = { "Functional" })
696 public void testFindMappingsForSequence()
698 SequenceI seq1 = new Sequence("Seq1", "ABC");
699 SequenceI seq2 = new Sequence("Seq2", "ABC");
700 SequenceI seq3 = new Sequence("Seq3", "ABC");
701 SequenceI seq4 = new Sequence("Seq4", "ABC");
702 seq1.createDatasetSequence();
703 seq2.createDatasetSequence();
704 seq3.createDatasetSequence();
705 seq4.createDatasetSequence();
708 * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1
710 AlignedCodonFrame acf1 = new AlignedCodonFrame();
711 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
712 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
713 AlignedCodonFrame acf2 = new AlignedCodonFrame();
714 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
715 AlignedCodonFrame acf3 = new AlignedCodonFrame();
716 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
718 List<AlignedCodonFrame> mappings = new ArrayList<>();
724 * Seq1 has three mappings
726 List<AlignedCodonFrame> result = MappingUtils
727 .findMappingsForSequence(seq1, mappings);
728 assertEquals(3, result.size());
729 assertTrue(result.contains(acf1));
730 assertTrue(result.contains(acf2));
731 assertTrue(result.contains(acf3));
734 * Seq2 has two mappings
736 result = MappingUtils.findMappingsForSequence(seq2, mappings);
737 assertEquals(2, result.size());
738 assertTrue(result.contains(acf1));
739 assertTrue(result.contains(acf2));
742 * Seq3 has one mapping
744 result = MappingUtils.findMappingsForSequence(seq3, mappings);
745 assertEquals(1, result.size());
746 assertTrue(result.contains(acf3));
749 * Seq4 has no mappings
751 result = MappingUtils.findMappingsForSequence(seq4, mappings);
752 assertEquals(0, result.size());
754 result = MappingUtils.findMappingsForSequence(null, mappings);
755 assertEquals(0, result.size());
757 result = MappingUtils.findMappingsForSequence(seq1, null);
758 assertEquals(0, result.size());
760 result = MappingUtils.findMappingsForSequence(null, null);
761 assertEquals(0, result.size());
765 * just like the one above, but this time, we provide a set of sequences to
766 * subselect the mapping search
768 @Test(groups = { "Functional" })
769 public void testFindMappingsForSequenceAndOthers()
771 SequenceI seq1 = new Sequence("Seq1", "ABC");
772 SequenceI seq2 = new Sequence("Seq2", "ABC");
773 SequenceI seq3 = new Sequence("Seq3", "ABC");
774 SequenceI seq4 = new Sequence("Seq4", "ABC");
775 seq1.createDatasetSequence();
776 seq2.createDatasetSequence();
777 seq3.createDatasetSequence();
778 seq4.createDatasetSequence();
781 * Create mappings from seq1 to seq2, seq2 to seq1, seq3 to seq1, seq3 to seq4
783 AlignedCodonFrame acf1 = new AlignedCodonFrame();
784 MapList map = new MapList(new int[] { 1, 3 }, new int[] { 1, 3 }, 1, 1);
785 acf1.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map);
786 AlignedCodonFrame acf2 = new AlignedCodonFrame();
787 acf2.addMap(seq2.getDatasetSequence(), seq1.getDatasetSequence(), map);
788 AlignedCodonFrame acf3 = new AlignedCodonFrame();
789 acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
790 AlignedCodonFrame acf4 = new AlignedCodonFrame();
791 acf4.addMap(seq3.getDatasetSequence(), seq4.getDatasetSequence(), map);
793 List<AlignedCodonFrame> mappings = new ArrayList<>();
802 List<AlignedCodonFrame> result = MappingUtils
803 .findMappingsForSequenceAndOthers(null, mappings,
804 Arrays.asList(new SequenceI[]
806 assertTrue(result.isEmpty());
808 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, null,
809 Arrays.asList(new SequenceI[]
811 assertTrue(result.isEmpty());
814 * Seq1 has three mappings, but filter argument will only accept
817 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, mappings,
818 Arrays.asList(new SequenceI[]
819 { seq1, seq2, seq1.getDatasetSequence() }));
820 assertEquals(2, result.size());
821 assertTrue(result.contains(acf1));
822 assertTrue(result.contains(acf2));
823 assertFalse("Did not expect to find mapping acf3 - subselect failed",
824 result.contains(acf3));
826 "Did not expect to find mapping acf4 - doesn't involve sequence",
827 result.contains(acf4));
830 * and verify the no filter case
832 result = MappingUtils.findMappingsForSequenceAndOthers(seq1, mappings,
834 assertEquals(3, result.size());
835 assertTrue(result.contains(acf1));
836 assertTrue(result.contains(acf2));
837 assertTrue(result.contains(acf3));
840 @Test(groups = { "Functional" })
841 public void testMapEditCommand()
843 SequenceI dna = new Sequence("Seq1", "---ACG---GCATCA", 8, 16);
844 SequenceI protein = new Sequence("Seq2", "-T-AS", 5, 7);
845 dna.createDatasetSequence();
846 protein.createDatasetSequence();
847 AlignedCodonFrame acf = new AlignedCodonFrame();
848 MapList map = new MapList(new int[] { 8, 16 }, new int[] { 5, 7 }, 3,
850 acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
851 List<AlignedCodonFrame> mappings = new ArrayList<>();
854 AlignmentI prot = new Alignment(new SequenceI[] { protein });
855 prot.setCodonFrames(mappings);
856 AlignmentI nuc = new Alignment(new SequenceI[] { dna });
859 * construct and perform the edit command to turn "-T-AS" in to "-T-A--S"
860 * i.e. insert two gaps at column 4
862 EditCommand ec = new EditCommand();
863 final Edit edit = ec.new Edit(Action.INSERT_GAP,
865 { protein }, 4, 2, '-');
866 ec.appendEdit(edit, prot, true, null);
869 * the mapped edit command should be to insert 6 gaps before base 4 in the
870 * nucleotide sequence, which corresponds to aligned column 12 in the dna
872 EditCommand mappedEdit = MappingUtils.mapEditCommand(ec, false, nuc,
874 assertEquals(1, mappedEdit.getEdits().size());
875 Edit e = mappedEdit.getEdits().get(0);
876 assertEquals(1, e.getSequences().length);
877 assertEquals(dna, e.getSequences()[0]);
878 assertEquals(12, e.getPosition());
879 assertEquals(6, e.getNumber());
883 * Tests for the method that converts a series of [start, end] ranges to
884 * single positions, where the mapping is to a reverse strand i.e. start is
885 * greater than end point mapped to
887 @Test(groups = { "Functional" })
888 public void testFlattenRanges_reverseStrand()
890 assertEquals("[4, 3, 2, 1]",
891 Arrays.toString(MappingUtils.flattenRanges(new int[]
893 assertEquals("[4, 3, 2, 1]",
894 Arrays.toString(MappingUtils.flattenRanges(new int[]
896 assertEquals("[4, 3, 2, 1]",
897 Arrays.toString(MappingUtils.flattenRanges(new int[]
898 { 4, 4, 3, 3, 2, 2, 1, 1 })));
899 assertEquals("[12, 9, 8, 7, 4, 3, 2, 1]",
900 Arrays.toString(MappingUtils.flattenRanges(new int[]
901 { 12, 12, 9, 7, 4, 1 })));
902 // forwards and backwards anyone?
903 assertEquals("[4, 5, 6, 3, 2, 1]",
904 Arrays.toString(MappingUtils.flattenRanges(new int[]
906 // backwards and forwards
907 assertEquals("[3, 2, 1, 4, 5, 6]",
908 Arrays.toString(MappingUtils.flattenRanges(new int[]
910 // trailing unpaired start position is ignored:
911 assertEquals("[12, 9, 8, 7, 4, 3, 2]",
912 Arrays.toString(MappingUtils.flattenRanges(new int[]
913 { 12, 12, 9, 7, 4, 2, 1 })));
917 * Test mapping a column selection including hidden columns
919 * @throws IOException
921 @Test(groups = { "Functional" })
922 public void testMapColumnSelection_hiddenColumns() throws IOException
924 setupMappedAlignments();
926 ColumnSelection proteinSelection = new ColumnSelection();
927 HiddenColumns hiddenCols = new HiddenColumns();
930 * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
931 * in dna respectively, overall 0-4
933 proteinSelection.hideSelectedColumns(0, hiddenCols);
934 ColumnSelection dnaSelection = new ColumnSelection();
935 HiddenColumns dnaHidden = new HiddenColumns();
936 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
937 proteinView, dnaView, dnaSelection, dnaHidden);
938 assertEquals("[]", dnaSelection.getSelected().toString());
939 Iterator<int[]> regions = dnaHidden.iterator();
940 assertEquals(1, dnaHidden.getNumberOfRegions());
941 assertEquals("[0, 4]", Arrays.toString(regions.next()));
944 * Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
946 dnaSelection = new ColumnSelection();
947 dnaHidden = new HiddenColumns();
948 hiddenCols.revealAllHiddenColumns(proteinSelection);
949 // the unhidden columns are now marked selected!
950 assertEquals("[0]", proteinSelection.getSelected().toString());
951 // deselect these or hideColumns will be expanded to include 0
952 proteinSelection.clear();
953 proteinSelection.hideSelectedColumns(1, hiddenCols);
954 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
955 proteinView, dnaView, dnaSelection, dnaHidden);
956 regions = dnaHidden.iterator();
957 assertEquals(1, dnaHidden.getNumberOfRegions());
958 assertEquals("[0, 3]", Arrays.toString(regions.next()));
961 * Column 2 in protein picks up gaps only - no mapping
963 dnaSelection = new ColumnSelection();
964 dnaHidden = new HiddenColumns();
965 hiddenCols.revealAllHiddenColumns(proteinSelection);
966 proteinSelection.clear();
967 proteinSelection.hideSelectedColumns(2, hiddenCols);
968 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
969 proteinView, dnaView, dnaSelection, dnaHidden);
970 assertEquals(0, dnaHidden.getNumberOfRegions());
973 * Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
974 * 6-9, 6-10, 5-8 respectively, overall to 5-10
976 dnaSelection = new ColumnSelection();
977 dnaHidden = new HiddenColumns();
978 hiddenCols.revealAllHiddenColumns(proteinSelection);
979 proteinSelection.clear();
980 proteinSelection.hideSelectedColumns(3, hiddenCols); // 5-10 hidden in dna
981 proteinSelection.addElement(1); // 0-3 selected in dna
982 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
983 proteinView, dnaView, dnaSelection, dnaHidden);
984 assertEquals("[0, 1, 2, 3]", dnaSelection.getSelected().toString());
985 regions = dnaHidden.iterator();
986 assertEquals(1, dnaHidden.getNumberOfRegions());
987 assertEquals("[5, 10]", Arrays.toString(regions.next()));
990 * Combine hiding columns 1 and 3 to get discontiguous hidden columns
992 dnaSelection = new ColumnSelection();
993 dnaHidden = new HiddenColumns();
994 hiddenCols.revealAllHiddenColumns(proteinSelection);
995 proteinSelection.clear();
996 proteinSelection.hideSelectedColumns(1, hiddenCols);
997 proteinSelection.hideSelectedColumns(3, hiddenCols);
998 MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
999 proteinView, dnaView, dnaSelection, dnaHidden);
1000 regions = dnaHidden.iterator();
1001 assertEquals(2, dnaHidden.getNumberOfRegions());
1002 assertEquals("[0, 3]", Arrays.toString(regions.next()));
1003 assertEquals("[5, 10]", Arrays.toString(regions.next()));
1006 @Test(groups = { "Functional" })
1007 public void testGetLength()
1009 assertEquals(0, MappingUtils.getLength(null));
1012 * [start, end] ranges
1014 List<int[]> ranges = new ArrayList<>();
1015 assertEquals(0, MappingUtils.getLength(ranges));
1016 ranges.add(new int[] { 1, 1 });
1017 assertEquals(1, MappingUtils.getLength(ranges));
1018 ranges.add(new int[] { 2, 10 });
1019 assertEquals(10, MappingUtils.getLength(ranges));
1020 ranges.add(new int[] { 20, 10 });
1021 assertEquals(21, MappingUtils.getLength(ranges));
1024 * [start, end, start, end...] ranges
1027 ranges.add(new int[] { 1, 5, 8, 4 });
1028 ranges.add(new int[] { 8, 2 });
1029 ranges.add(new int[] { 12, 12 });
1030 assertEquals(18, MappingUtils.getLength(ranges));
1033 @Test(groups = { "Functional" })
1034 public void testContains()
1036 assertFalse(MappingUtils.contains(null, 1));
1037 List<int[]> ranges = new ArrayList<>();
1038 assertFalse(MappingUtils.contains(ranges, 1));
1040 ranges.add(new int[] { 1, 4 });
1041 ranges.add(new int[] { 6, 6 });
1042 ranges.add(new int[] { 8, 10 });
1043 ranges.add(new int[] { 30, 20 });
1044 ranges.add(new int[] { -16, -44 });
1046 assertFalse(MappingUtils.contains(ranges, 0));
1047 assertTrue(MappingUtils.contains(ranges, 1));
1048 assertTrue(MappingUtils.contains(ranges, 2));
1049 assertTrue(MappingUtils.contains(ranges, 3));
1050 assertTrue(MappingUtils.contains(ranges, 4));
1051 assertFalse(MappingUtils.contains(ranges, 5));
1053 assertTrue(MappingUtils.contains(ranges, 6));
1054 assertFalse(MappingUtils.contains(ranges, 7));
1056 assertTrue(MappingUtils.contains(ranges, 8));
1057 assertTrue(MappingUtils.contains(ranges, 9));
1058 assertTrue(MappingUtils.contains(ranges, 10));
1060 assertFalse(MappingUtils.contains(ranges, 31));
1061 assertTrue(MappingUtils.contains(ranges, 30));
1062 assertTrue(MappingUtils.contains(ranges, 29));
1063 assertTrue(MappingUtils.contains(ranges, 20));
1064 assertFalse(MappingUtils.contains(ranges, 19));
1066 assertFalse(MappingUtils.contains(ranges, -15));
1067 assertTrue(MappingUtils.contains(ranges, -16));
1068 assertTrue(MappingUtils.contains(ranges, -44));
1069 assertFalse(MappingUtils.contains(ranges, -45));
1073 * Test the method that drops positions from the start of a mapped range
1075 @Test(groups = "Functional")
1076 public void testRemoveStartPositions()
1078 int[] ranges = new int[] { 1, 10 };
1079 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
1080 assertEquals("[1, 10]", Arrays.toString(adjusted));
1082 adjusted = MappingUtils.removeStartPositions(1, ranges);
1083 assertEquals("[2, 10]", Arrays.toString(adjusted));
1084 assertEquals("[1, 10]", Arrays.toString(ranges));
1087 adjusted = MappingUtils.removeStartPositions(1, ranges);
1088 assertEquals("[3, 10]", Arrays.toString(adjusted));
1089 assertEquals("[2, 10]", Arrays.toString(ranges));
1091 ranges = new int[] { 2, 3, 10, 12 };
1092 adjusted = MappingUtils.removeStartPositions(1, ranges);
1093 assertEquals("[3, 3, 10, 12]", Arrays.toString(adjusted));
1094 assertEquals("[2, 3, 10, 12]", Arrays.toString(ranges));
1096 ranges = new int[] { 2, 2, 8, 12 };
1097 adjusted = MappingUtils.removeStartPositions(1, ranges);
1098 assertEquals("[8, 12]", Arrays.toString(adjusted));
1099 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
1101 ranges = new int[] { 2, 2, 8, 12 };
1102 adjusted = MappingUtils.removeStartPositions(2, ranges);
1103 assertEquals("[9, 12]", Arrays.toString(adjusted));
1104 assertEquals("[2, 2, 8, 12]", Arrays.toString(ranges));
1106 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
1107 adjusted = MappingUtils.removeStartPositions(1, ranges);
1108 assertEquals("[4, 4, 9, 12]", Arrays.toString(adjusted));
1109 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
1111 ranges = new int[] { 2, 2, 4, 4, 9, 12 };
1112 adjusted = MappingUtils.removeStartPositions(2, ranges);
1113 assertEquals("[9, 12]", Arrays.toString(adjusted));
1114 assertEquals("[2, 2, 4, 4, 9, 12]", Arrays.toString(ranges));
1116 ranges = new int[] { 2, 3, 9, 12 };
1117 adjusted = MappingUtils.removeStartPositions(3, ranges);
1118 assertEquals("[10, 12]", Arrays.toString(adjusted));
1119 assertEquals("[2, 3, 9, 12]", Arrays.toString(ranges));
1123 * Test the method that drops positions from the start of a mapped range, on
1124 * the reverse strand
1126 @Test(groups = "Functional")
1127 public void testRemoveStartPositions_reverseStrand()
1129 int[] ranges = new int[] { 10, 1 };
1130 int[] adjusted = MappingUtils.removeStartPositions(0, ranges);
1131 assertEquals("[10, 1]", Arrays.toString(adjusted));
1132 assertEquals("[10, 1]", Arrays.toString(ranges));
1135 adjusted = MappingUtils.removeStartPositions(1, ranges);
1136 assertEquals("[9, 1]", Arrays.toString(adjusted));
1137 assertEquals("[10, 1]", Arrays.toString(ranges));
1140 adjusted = MappingUtils.removeStartPositions(1, ranges);
1141 assertEquals("[8, 1]", Arrays.toString(adjusted));
1142 assertEquals("[9, 1]", Arrays.toString(ranges));
1144 ranges = new int[] { 12, 11, 9, 6 };
1145 adjusted = MappingUtils.removeStartPositions(1, ranges);
1146 assertEquals("[11, 11, 9, 6]", Arrays.toString(adjusted));
1147 assertEquals("[12, 11, 9, 6]", Arrays.toString(ranges));
1149 ranges = new int[] { 12, 12, 8, 4 };
1150 adjusted = MappingUtils.removeStartPositions(1, ranges);
1151 assertEquals("[8, 4]", Arrays.toString(adjusted));
1152 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1154 ranges = new int[] { 12, 12, 8, 4 };
1155 adjusted = MappingUtils.removeStartPositions(2, ranges);
1156 assertEquals("[7, 4]", Arrays.toString(adjusted));
1157 assertEquals("[12, 12, 8, 4]", Arrays.toString(ranges));
1159 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1160 adjusted = MappingUtils.removeStartPositions(1, ranges);
1161 assertEquals("[10, 10, 8, 4]", Arrays.toString(adjusted));
1162 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1164 ranges = new int[] { 12, 12, 10, 10, 8, 4 };
1165 adjusted = MappingUtils.removeStartPositions(2, ranges);
1166 assertEquals("[8, 4]", Arrays.toString(adjusted));
1167 assertEquals("[12, 12, 10, 10, 8, 4]", Arrays.toString(ranges));
1169 ranges = new int[] { 12, 11, 8, 4 };
1170 adjusted = MappingUtils.removeStartPositions(3, ranges);
1171 assertEquals("[7, 4]", Arrays.toString(adjusted));
1172 assertEquals("[12, 11, 8, 4]", Arrays.toString(ranges));
1175 @Test(groups = { "Functional" })
1176 public void testRangeContains()
1179 * both forward ranges
1182 MappingUtils.rangeContains(new int[]
1183 { 1, 10 }, new int[] { 1, 10 }));
1185 MappingUtils.rangeContains(new int[]
1186 { 1, 10 }, new int[] { 2, 10 }));
1188 MappingUtils.rangeContains(new int[]
1189 { 1, 10 }, new int[] { 1, 9 }));
1191 MappingUtils.rangeContains(new int[]
1192 { 1, 10 }, new int[] { 4, 5 }));
1194 MappingUtils.rangeContains(new int[]
1195 { 1, 10 }, new int[] { 0, 9 }));
1197 MappingUtils.rangeContains(new int[]
1198 { 1, 10 }, new int[] { -10, -9 }));
1200 MappingUtils.rangeContains(new int[]
1201 { 1, 10 }, new int[] { 1, 11 }));
1203 MappingUtils.rangeContains(new int[]
1204 { 1, 10 }, new int[] { 11, 12 }));
1207 * forward range, reverse query
1210 MappingUtils.rangeContains(new int[]
1211 { 1, 10 }, new int[] { 10, 1 }));
1213 MappingUtils.rangeContains(new int[]
1214 { 1, 10 }, new int[] { 9, 1 }));
1216 MappingUtils.rangeContains(new int[]
1217 { 1, 10 }, new int[] { 10, 2 }));
1219 MappingUtils.rangeContains(new int[]
1220 { 1, 10 }, new int[] { 5, 5 }));
1222 MappingUtils.rangeContains(new int[]
1223 { 1, 10 }, new int[] { 11, 1 }));
1225 MappingUtils.rangeContains(new int[]
1226 { 1, 10 }, new int[] { 10, 0 }));
1229 * reverse range, forward query
1232 MappingUtils.rangeContains(new int[]
1233 { 10, 1 }, new int[] { 1, 10 }));
1235 MappingUtils.rangeContains(new int[]
1236 { 10, 1 }, new int[] { 1, 9 }));
1238 MappingUtils.rangeContains(new int[]
1239 { 10, 1 }, new int[] { 2, 10 }));
1241 MappingUtils.rangeContains(new int[]
1242 { 10, 1 }, new int[] { 6, 6 }));
1244 MappingUtils.rangeContains(new int[]
1245 { 10, 1 }, new int[] { 6, 11 }));
1247 MappingUtils.rangeContains(new int[]
1248 { 10, 1 }, new int[] { 11, 20 }));
1250 MappingUtils.rangeContains(new int[]
1251 { 10, 1 }, new int[] { -3, -2 }));
1257 MappingUtils.rangeContains(new int[]
1258 { 10, 1 }, new int[] { 10, 1 }));
1260 MappingUtils.rangeContains(new int[]
1261 { 10, 1 }, new int[] { 9, 1 }));
1263 MappingUtils.rangeContains(new int[]
1264 { 10, 1 }, new int[] { 10, 2 }));
1266 MappingUtils.rangeContains(new int[]
1267 { 10, 1 }, new int[] { 3, 3 }));
1269 MappingUtils.rangeContains(new int[]
1270 { 10, 1 }, new int[] { 11, 1 }));
1272 MappingUtils.rangeContains(new int[]
1273 { 10, 1 }, new int[] { 10, 0 }));
1275 MappingUtils.rangeContains(new int[]
1276 { 10, 1 }, new int[] { 12, 11 }));
1278 MappingUtils.rangeContains(new int[]
1279 { 10, 1 }, new int[] { -5, -8 }));
1285 MappingUtils.rangeContains(new int[]
1286 { 1, 10, 12 }, new int[] { 1, 10 }));
1288 MappingUtils.rangeContains(new int[]
1289 { 1, 10 }, new int[] { 1 }));
1290 assertFalse(MappingUtils.rangeContains(new int[] { 1, 10 }, null));
1291 assertFalse(MappingUtils.rangeContains(null, new int[] { 1, 10 }));
1294 @Test(groups = "Functional")
1295 public void testRemoveEndPositions()
1297 List<int[]> ranges = new ArrayList<>();
1300 * case 1: truncate last range
1302 ranges.add(new int[] { 1, 10 });
1303 ranges.add(new int[] { 20, 30 });
1304 MappingUtils.removeEndPositions(5, ranges);
1305 assertEquals(2, ranges.size());
1306 assertEquals(25, ranges.get(1)[1]);
1309 * case 2: remove last range
1312 ranges.add(new int[] { 1, 10 });
1313 ranges.add(new int[] { 20, 22 });
1314 MappingUtils.removeEndPositions(3, ranges);
1315 assertEquals(1, ranges.size());
1316 assertEquals(10, ranges.get(0)[1]);
1319 * case 3: truncate penultimate range
1322 ranges.add(new int[] { 1, 10 });
1323 ranges.add(new int[] { 20, 21 });
1324 MappingUtils.removeEndPositions(3, ranges);
1325 assertEquals(1, ranges.size());
1326 assertEquals(9, ranges.get(0)[1]);
1329 * case 4: remove last two ranges
1332 ranges.add(new int[] { 1, 10 });
1333 ranges.add(new int[] { 20, 20 });
1334 ranges.add(new int[] { 30, 30 });
1335 MappingUtils.removeEndPositions(3, ranges);
1336 assertEquals(1, ranges.size());
1337 assertEquals(9, ranges.get(0)[1]);
1340 @Test(groups = "Functional")
1341 public void testListToArray()
1343 List<int[]> ranges = new ArrayList<>();
1345 int[] result = MappingUtils.listToArray(ranges);
1346 assertEquals(result.length, 0);
1347 ranges.add(new int[] { 24, 12 });
1348 result = MappingUtils.listToArray(ranges);
1349 assertEquals(result.length, 2);
1350 assertEquals(result[0], 24);
1351 assertEquals(result[1], 12);
1352 ranges.add(new int[] { -7, 30 });
1353 result = MappingUtils.listToArray(ranges);
1354 assertEquals(result.length, 4);
1355 assertEquals(result[0], 24);
1356 assertEquals(result[1], 12);
1357 assertEquals(result[2], -7);
1358 assertEquals(result[3], 30);
1361 MappingUtils.listToArray(null);
1362 fail("Expected exception");
1363 } catch (NullPointerException e)
1370 * Test mapping a sequence group where sequences in and outside the group
1371 * share a dataset sequence (e.g. alternative CDS for the same gene)
1373 * This scenario doesn't arise after JAL-3763 changes, but test left as still
1376 * @throws IOException
1378 @Test(groups = { "Functional" })
1379 public void testMapSequenceGroup_sharedDataset() throws IOException
1382 * Set up dna and protein Seq1/2/3 with mappings (held on the protein
1383 * viewport). CDS sequences share the same 'gene' dataset sequence.
1385 SequenceI dna = new Sequence("dna", "aaatttgggcccaaatttgggccc");
1386 SequenceI cds1 = new Sequence("cds1/1-6", "aaattt");
1387 SequenceI cds2 = new Sequence("cds1/4-9", "tttggg");
1388 SequenceI cds3 = new Sequence("cds1/19-24", "gggccc");
1390 cds1.setDatasetSequence(dna);
1391 cds2.setDatasetSequence(dna);
1392 cds3.setDatasetSequence(dna);
1394 SequenceI pep1 = new Sequence("pep1", "KF");
1395 SequenceI pep2 = new Sequence("pep2", "FG");
1396 SequenceI pep3 = new Sequence("pep3", "GP");
1397 pep1.createDatasetSequence();
1398 pep2.createDatasetSequence();
1399 pep3.createDatasetSequence();
1402 * add mappings from coding positions of dna to respective peptides
1404 AlignedCodonFrame acf = new AlignedCodonFrame();
1405 acf.addMap(dna, pep1,
1406 new MapList(new int[]
1407 { 1, 6 }, new int[] { 1, 2 }, 3, 1));
1408 acf.addMap(dna, pep2,
1409 new MapList(new int[]
1410 { 4, 9 }, new int[] { 1, 2 }, 3, 1));
1411 acf.addMap(dna, pep3,
1412 new MapList(new int[]
1413 { 19, 24 }, new int[] { 1, 2 }, 3, 1));
1415 List<AlignedCodonFrame> acfList = Arrays
1416 .asList(new AlignedCodonFrame[]
1419 AlignmentI cdna = new Alignment(new SequenceI[] { cds1, cds2, cds3 });
1420 AlignmentI protein = new Alignment(
1422 { pep1, pep2, pep3 });
1423 AlignViewportI cdnaView = new AlignViewport(cdna);
1424 AlignViewportI peptideView = new AlignViewport(protein);
1425 protein.setCodonFrames(acfList);
1428 * Select pep1 and pep3 in the protein alignment
1430 SequenceGroup sg = new SequenceGroup();
1431 sg.setColourText(true);
1432 sg.setIdColour(Color.GREEN);
1433 sg.setOutlineColour(Color.LIGHT_GRAY);
1434 sg.addSequence(pep1, false);
1435 sg.addSequence(pep3, false);
1436 sg.setEndRes(protein.getWidth() - 1);
1439 * Verify the mapped sequence group in dna is cds1 and cds3
1441 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
1442 peptideView, cdnaView);
1443 assertTrue(mappedGroup.getColourText());
1444 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
1445 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
1446 assertEquals(2, mappedGroup.getSequences().size());
1447 assertSame(cds1, mappedGroup.getSequences().get(0));
1448 assertSame(cds3, mappedGroup.getSequences().get(1));
1449 // columns 1-6 selected (0-5 base zero)
1450 assertEquals(0, mappedGroup.getStartRes());
1451 assertEquals(5, mappedGroup.getEndRes());
1454 * Select mapping sequence group from dna to protein
1457 sg.addSequence(cds2, false);
1458 sg.addSequence(cds1, false);
1460 sg.setEndRes(cdna.getWidth() - 1);
1461 mappedGroup = MappingUtils.mapSequenceGroup(sg, cdnaView, peptideView);
1462 assertTrue(mappedGroup.getColourText());
1463 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
1464 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
1465 assertEquals(2, mappedGroup.getSequences().size());
1466 assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
1467 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
1468 assertEquals(0, mappedGroup.getStartRes());
1469 assertEquals(1, mappedGroup.getEndRes()); // two columns
1472 @Test(groups = "Functional")
1473 public void testFindOverlap()
1475 List<int[]> ranges = new ArrayList<>();
1476 ranges.add(new int[] { 4, 8 });
1477 ranges.add(new int[] { 10, 12 });
1478 ranges.add(new int[] { 16, 19 });
1480 int[] overlap = MappingUtils.findOverlap(ranges, 5, 13);
1481 assertArrayEquals(overlap, new int[] { 5, 12 });
1482 overlap = MappingUtils.findOverlap(ranges, -100, 100);
1483 assertArrayEquals(overlap, new int[] { 4, 19 });
1484 overlap = MappingUtils.findOverlap(ranges, 7, 17);
1485 assertArrayEquals(overlap, new int[] { 7, 17 });
1486 overlap = MappingUtils.findOverlap(ranges, 13, 15);
1487 assertNull(overlap);
1491 * Test mapping a sequence group including a sequence which maps to more than
1492 * one other sequence
1494 * @throws IOException
1496 @Test(groups = { "Functional" })
1497 public void testMapSequenceGroup_oneToMany() throws IOException
1500 * Uniprot:FER2_ARATH has cross-refs to 10 EMBLCDS sequences;
1501 * we'll just mimic 3 of them here (abbreviated)
1502 * From EMBLCDS|BAE98526 [ [1, 444] ] 3:1 to [ [1, 148] ] FER2_ARATH
1503 * From EMBLCDS|AAM91336 same
1504 * From EMBLCDS|AAM13033 same
1506 String coding = "atggcttccactgctctctca";
1507 AlignmentI cds = loadAlignment(">BAE98526\n" + coding + "\n>AAM91336\n"
1508 + coding + "\n>AAM13033\n" + coding + "\n",
1510 cds.setDataset(null);
1511 AlignmentI protein = loadAlignment(">FER2_ARATH\nMASTALS\n",
1513 protein.setDataset(null);
1514 AlignedCodonFrame acf = new AlignedCodonFrame();
1515 MapList map = new MapList(new int[] { 1, 21 }, new int[] { 1, 7 }, 3, 1);
1516 for (int seq = 0; seq < 3; seq++)
1518 acf.addMap(cds.getSequenceAt(seq).getDatasetSequence(),
1519 protein.getSequenceAt(0).getDatasetSequence(), map);
1521 List<AlignedCodonFrame> acfList = Arrays
1522 .asList(new AlignedCodonFrame[]
1525 AlignViewportI theDnaView = new AlignViewport(cds);
1526 AlignViewportI theProteinView = new AlignViewport(protein);
1527 protein.setCodonFrames(acfList);
1530 * Select FER2_ARATH in the protein
1532 SequenceGroup sg = new SequenceGroup();
1533 sg.setColourText(true);
1534 sg.setIdColour(Color.GREEN);
1535 sg.setOutlineColour(Color.LIGHT_GRAY);
1536 sg.addSequence(protein.getSequenceAt(0), false);
1537 sg.setEndRes(protein.getWidth() - 1);
1540 * Verify the mapped sequence group in dna
1542 SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
1543 theProteinView, theDnaView);
1544 assertTrue(mappedGroup.getColourText());
1545 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
1546 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
1547 assertEquals(3, mappedGroup.getSequences().size());
1548 assertSame(cds.getSequenceAt(0), mappedGroup.getSequences().get(0));
1549 assertSame(cds.getSequenceAt(1), mappedGroup.getSequences().get(1));
1550 assertSame(cds.getSequenceAt(2), mappedGroup.getSequences().get(2));
1551 assertEquals(0, mappedGroup.getStartRes());
1552 assertEquals(20, mappedGroup.getEndRes()); // 21 columns (7 codons)
1555 * Select 2 CDS, verify peptide is mapped
1558 sg.addSequence(cds.getSequenceAt(1), false);
1559 sg.addSequence(cds.getSequenceAt(0), false);
1562 mappedGroup = MappingUtils.mapSequenceGroup(sg, theDnaView,
1564 assertTrue(mappedGroup.getColourText());
1565 assertSame(sg.getIdColour(), mappedGroup.getIdColour());
1566 assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
1567 assertEquals(1, mappedGroup.getSequences().size());
1568 assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(0));
1569 assertEquals(0, mappedGroup.getStartRes());
1570 assertEquals(6, mappedGroup.getEndRes());