From: tcofoegbu Date: Tue, 28 Jun 2016 14:28:28 +0000 (+0100) Subject: Merge branch 'develop' of https://source.jalview.org/git/jalview into develop X-Git-Tag: Release_2_10_0~154 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=ac8d1df7e4ad0cb6a2e0119b132440c3f439d17c;hp=37bc56d23032f26c0da11b0532902d1f629a2080;p=jalview.git Merge branch 'develop' of https://source.jalview.org/git/jalview into develop --- diff --git a/src/jalview/appletgui/APopupMenu.java b/src/jalview/appletgui/APopupMenu.java index 748954a..948c8e5 100644 --- a/src/jalview/appletgui/APopupMenu.java +++ b/src/jalview/appletgui/APopupMenu.java @@ -537,6 +537,7 @@ public class APopupMenu extends java.awt.PopupMenu implements MenuItem item = new MenuItem(label); item.addActionListener(new java.awt.event.ActionListener() { + @Override public void actionPerformed(ActionEvent e) { ap.alignFrame.showURL(url, target); @@ -545,6 +546,7 @@ public class APopupMenu extends java.awt.PopupMenu implements linkMenu.add(item); } + @Override public void itemStateChanged(ItemEvent evt) { if (evt.getSource() == abovePIDColour) @@ -569,6 +571,7 @@ public class APopupMenu extends java.awt.PopupMenu implements } } + @Override public void actionPerformed(ActionEvent evt) { Object source = evt.getSource(); @@ -1299,35 +1302,7 @@ public class APopupMenu extends java.awt.PopupMenu implements void hideSequences(boolean representGroup) { - SequenceGroup sg = ap.av.getSelectionGroup(); - if (sg == null || sg.getSize() < 1) - { - ap.av.hideSequence(new SequenceI[] { seq }); - return; - } - - ap.av.setSelectionGroup(null); - - if (representGroup) - { - ap.av.hideRepSequences(seq, sg); - - return; - } - - int gsize = sg.getSize(); - SequenceI[] hseqs; - - hseqs = new SequenceI[gsize]; - - int index = 0; - for (int i = 0; i < gsize; i++) - { - hseqs[index++] = sg.getSequenceAt(i); - } - - ap.av.hideSequence(hseqs); - ap.av.sendSelection(); + ap.av.hideSequences(seq, representGroup); } /** diff --git a/src/jalview/datamodel/HiddenSequences.java b/src/jalview/datamodel/HiddenSequences.java index db4c858..8ca3c5a 100755 --- a/src/jalview/datamodel/HiddenSequences.java +++ b/src/jalview/datamodel/HiddenSequences.java @@ -33,11 +33,21 @@ public class HiddenSequences AlignmentI alignment; + /** + * Constructor given a reference to an alignment (with no hidden sequences) + * + * @param al + */ public HiddenSequences(AlignmentI al) { alignment = al; } + /** + * Answers the number of hidden sequences + * + * @return + */ public int getSize() { if (hiddenSequences == null) @@ -45,9 +55,9 @@ public class HiddenSequences return 0; } int count = 0; - for (int i = 0; i < hiddenSequences.length; i++) + for (SequenceI seq : hiddenSequences) { - if (hiddenSequences[i] != null) + if (seq != null) { count++; } @@ -56,15 +66,23 @@ public class HiddenSequences return count; } + /** + * Answers the length of the longest hidden sequence + * + * @return + */ public int getWidth() { + if (hiddenSequences == null) + { + return 0; + } int width = 0; - for (int i = 0; i < hiddenSequences.length; i++) + for (SequenceI seq : hiddenSequences) { - if (hiddenSequences[i] != null - && hiddenSequences[i].getLength() > width) + if (seq != null && seq.getLength() > width) { - width = hiddenSequences[i].getLength(); + width = seq.getLength(); } } @@ -72,7 +90,7 @@ public class HiddenSequences } /** - * Call this method if sequences are removed from the main alignment + * Call this method after a sequence is removed from the main alignment */ public void adjustHeightSequenceDeleted(int seqIndex) { @@ -108,8 +126,7 @@ public class HiddenSequences } /** - * Call this method if sequences are added to or removed from the main - * alignment + * Call this method after a sequence is added to the main alignment */ public void adjustHeightSequenceAdded() { @@ -125,6 +142,11 @@ public class HiddenSequences hiddenSequences = tmp; } + /** + * Mark the specified sequence as hidden + * + * @param sequence + */ public void hideSequence(SequenceI sequence) { if (hiddenSequences == null) @@ -163,6 +185,17 @@ public class HiddenSequences return revealedSeqs; } + /** + * Reveals (unhides) consecutive hidden sequences just above the given + * alignment index. The revealed sequences are selected (including their + * visible representative sequence if there was one and 'reveal' is being + * performed on it). + * + * @param alignmentIndex + * @param hiddenRepSequences + * a map of representative sequences to the sequences they represent + * @return + */ public List showSequence(int alignmentIndex, Map hiddenRepSequences) { @@ -203,20 +236,22 @@ public class HiddenSequences + " has been deleted whilst hidden"); } } - } } - return revealedSeqs; } public SequenceI getHiddenSequence(int alignmentIndex) { - return hiddenSequences[alignmentIndex]; + return hiddenSequences == null ? null : hiddenSequences[alignmentIndex]; } public int findIndexWithoutHiddenSeqs(int alignmentIndex) { + if (hiddenSequences == null) + { + return alignmentIndex; + } int index = 0; int hiddenSeqs = 0; if (hiddenSequences.length <= alignmentIndex) @@ -232,13 +267,16 @@ public class HiddenSequences } index++; } - ; return (alignmentIndex - hiddenSeqs); } public int adjustForHiddenSeqs(int alignmentIndex) { + if (hiddenSequences == null) + { + return alignmentIndex; + } int index = 0; int hSize = hiddenSequences.length; while (index <= alignmentIndex && index < hSize) @@ -262,20 +300,28 @@ public class HiddenSequences */ public AlignmentI getFullAlignment() { - int isize = hiddenSequences.length; - SequenceI[] seq = new Sequence[isize]; - - int index = 0; - for (int i = 0; i < hiddenSequences.length; i++) + SequenceI[] seq; + if (hiddenSequences == null) { - if (hiddenSequences[i] != null) - { - seq[i] = hiddenSequences[i]; - } - else + seq = alignment.getSequencesArray(); + } + else + { + int isize = hiddenSequences.length; + seq = new Sequence[isize]; + + int index = 0; + for (int i = 0; i < hiddenSequences.length; i++) { - seq[i] = alignment.getSequenceAt(index); - index++; + if (hiddenSequences[i] != null) + { + seq[i] = hiddenSequences[i]; + } + else + { + seq[i] = alignment.getSequenceAt(index); + index++; + } } } Alignment fAlignmt = new Alignment(seq); diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index eeb4214..01e60d4 100644 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -680,9 +680,8 @@ public class Jalview2XML Set calcIdSet = new HashSet(); // SAVE SEQUENCES - for (int i = 0; i < rjal.getHeight(); i++) + for (final SequenceI jds : rjal.getSequences()) { - final SequenceI jds = rjal.getSequenceAt(i); final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds : jds.getDatasetSequence(); String id = seqHash(jds); @@ -725,15 +724,15 @@ public class Jalview2XML jseq.setHidden(av.getAlignment().getHiddenSequences() .isHidden(jds)); - if (av.isHiddenRepSequence(rjal.getSequenceAt(i))) + if (av.isHiddenRepSequence(jds)) { jalview.datamodel.SequenceI[] reps = av - .getRepresentedSequences(rjal.getSequenceAt(i)) + .getRepresentedSequences(jds) .getSequencesInOrder(rjal); for (int h = 0; h < reps.length; h++) { - if (reps[h] != rjal.getSequenceAt(i)) + if (reps[h] != jds) { jseq.addHiddenSequences(rjal.findIndex(reps[h])); } @@ -743,7 +742,7 @@ public class Jalview2XML // mark sequence as reference - if it is the reference for this view if (jal.hasSeqrep()) { - jseq.setViewreference(rjal.getSequenceAt(i) == jal.getSeqrep()); + jseq.setViewreference(jds == jal.getSeqrep()); } } diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index e64d43f..497f3ba 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -2270,28 +2270,7 @@ public class PopupMenu extends JPopupMenu void hideSequences(boolean representGroup) { - SequenceGroup sg = ap.av.getSelectionGroup(); - if (sg == null || sg.getSize() < 1) - { - ap.av.hideSequence(new SequenceI[] { sequence }); - return; - } - - ap.av.setSelectionGroup(null); - - if (representGroup) - { - ap.av.hideRepSequences(sequence, sg); - - return; - } - - int gsize = sg.getSize(); - SequenceI[] hseqs = sg.getSequences().toArray(new SequenceI[gsize]); - - ap.av.hideSequence(hseqs); - // refresh(); TODO: ? needed ? - ap.av.sendSelection(); + ap.av.hideSequences(sequence, representGroup); } public void copy_actionPerformed() diff --git a/src/jalview/viewmodel/AlignmentViewport.java b/src/jalview/viewmodel/AlignmentViewport.java index 91ee3c1..eab4aa5 100644 --- a/src/jalview/viewmodel/AlignmentViewport.java +++ b/src/jalview/viewmodel/AlignmentViewport.java @@ -1413,6 +1413,39 @@ public abstract class AlignmentViewport implements AlignViewportI, } /** + * Hides the specified sequence, or the sequences it represents + * + * @param sequence + * the sequence to hide, or keep as representative + * @param representGroup + * if true, hide the current selection group except for the + * representative sequence + */ + public void hideSequences(SequenceI sequence, boolean representGroup) + { + if (selectionGroup == null || selectionGroup.getSize() < 1) + { + hideSequence(new SequenceI[] { sequence }); + return; + } + + if (representGroup) + { + hideRepSequences(sequence, selectionGroup); + setSelectionGroup(null); + return; + } + + int gsize = selectionGroup.getSize(); + SequenceI[] hseqs = selectionGroup.getSequences().toArray( + new SequenceI[gsize]); + + hideSequence(hseqs); + setSelectionGroup(null); + sendSelection(); + } + + /** * Set visibility for any annotations for the given sequence. * * @param sequenceI diff --git a/test/jalview/datamodel/HiddenSequencesTest.java b/test/jalview/datamodel/HiddenSequencesTest.java new file mode 100644 index 0000000..8b50a8b --- /dev/null +++ b/test/jalview/datamodel/HiddenSequencesTest.java @@ -0,0 +1,378 @@ +package jalview.datamodel; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNotSame; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertSame; +import static org.testng.AssertJUnit.assertTrue; +import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals; + +import jalview.gui.AlignViewport; + +import java.util.List; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +@Test(singleThreaded = true) +public class HiddenSequencesTest +{ + static int SEQ_COUNT = 10; + + SequenceI[] seqs; + + /** + * Set up an alignment of 10 sequences + */ + @BeforeTest(alwaysRun = true) + public void setUp() + { + seqs = new SequenceI[SEQ_COUNT]; + for (int i = 0; i < SEQ_COUNT; i++) + { + // sequence lengths are 1, 2, ... 10 + seqs[i] = new Sequence("Seq" + i, "abcdefghijk".substring(0, i + 1)); + } + } + + /** + * Test the method that converts sequence alignment index to what it would be + * if all sequences were unhidden + */ + @Test(groups = "Functional") + public void testAdjustForHiddenSeqs() + { + AlignmentI al = new Alignment(seqs); + HiddenSequences hs = al.getHiddenSequences(); + for (int i = 0; i < SEQ_COUNT; i++) + { + assertEquals(i, hs.adjustForHiddenSeqs(i)); + } + + // hide seq1 and seq5 and seq6 + hs.hideSequence(seqs[1]); + hs.hideSequence(seqs[5]); + hs.hideSequence(seqs[6]); + + /* + * alignment is now seq0/2/3/4/7/8/9 + */ + assertEquals(7, al.getHeight()); + assertEquals(0, hs.adjustForHiddenSeqs(0)); + assertEquals(2, hs.adjustForHiddenSeqs(1)); + assertEquals(3, hs.adjustForHiddenSeqs(2)); + assertEquals(4, hs.adjustForHiddenSeqs(3)); + assertEquals(7, hs.adjustForHiddenSeqs(4)); + assertEquals(8, hs.adjustForHiddenSeqs(5)); + assertEquals(9, hs.adjustForHiddenSeqs(6)); + } + + /** + * Test the method that increments the internal array size if a sequence is + * added to the alignment (ugh this should not be exposed to the light of day) + */ + @Test(groups = "Functional") + public void testAdjustHeightSequenceAdded() + { + AlignmentI al = new Alignment(seqs); + assertEquals(SEQ_COUNT, al.getHeight()); + + HiddenSequences hs = al.getHiddenSequences(); + // initially does nothing + hs.adjustHeightSequenceAdded(); + assertNull(hs.hiddenSequences); + + // hide one sequence + hs.hideSequence(seqs[3]); + assertEquals(1, hs.getSize()); + assertEquals(SEQ_COUNT - 1, al.getHeight()); + assertEquals(SEQ_COUNT, hs.hiddenSequences.length); + + /* + * add a sequence to the alignment + * - the safe way to call hs.adjustHeightSequenceAdded! + * (implementation depends on alignment height having + * been already updated for the added sequence) + */ + al.addSequence(new Sequence("a", "b")); + assertEquals(1, hs.getSize()); + assertEquals(SEQ_COUNT, al.getHeight()); + assertEquals(SEQ_COUNT + 1, hs.hiddenSequences.length); + } + + /** + * Test the method that decrements the internal array size if a sequence is + * deleted from the alignment (ugh this should not be exposed to the light of + * day) + */ + @Test(groups = "Functional") + public void testAdjustHeightSequenceDeleted() + { + AlignmentI al = new Alignment(seqs); + assertEquals(SEQ_COUNT, al.getHeight()); + + HiddenSequences hs = al.getHiddenSequences(); + // initially does nothing + hs.adjustHeightSequenceAdded(); + assertNull(hs.hiddenSequences); + + // hide two sequences + hs.hideSequence(seqs[3]); + hs.hideSequence(seqs[5]); + assertEquals(2, hs.getSize()); + assertTrue(hs.isHidden(seqs[3])); + assertTrue(hs.isHidden(seqs[5])); + assertEquals(SEQ_COUNT - 2, al.getHeight()); + assertEquals(SEQ_COUNT, hs.hiddenSequences.length); + + /* + * delete a visible sequence from the alignment + * - the safe way to call hs.adjustHeightSequenceDeleted! + * (implementation depends on alignment height having + * been already updated for the removed sequence) + */ + al.deleteSequence(seqs[2]); + assertEquals(2, hs.getSize()); + // the visible alignment is unchanged: + assertEquals(SEQ_COUNT - 3, al.getHeight()); + // sequences array size has decremented: + assertEquals(SEQ_COUNT - 1, hs.hiddenSequences.length); + } + + /** + * Test the method that converts a 'full alignment' sequence index into the + * equivalent in the alignment with sequences hidden + */ + @Test(groups = "Functional") + public void testFindIndexWithoutHiddenSeqs() + { + AlignmentI al = new Alignment(seqs); + HiddenSequences hs = al.getHiddenSequences(); + for (int i = 0; i < SEQ_COUNT; i++) + { + assertEquals(i, hs.findIndexWithoutHiddenSeqs(i)); + } + + // hide seq1 and seq5 and seq6 + hs.hideSequence(seqs[1]); + hs.hideSequence(seqs[5]); + hs.hideSequence(seqs[6]); + + /* + * alignment is now seq0/2/3/4/7/8/9 + */ + assertEquals(7, al.getHeight()); + assertEquals(0, hs.findIndexWithoutHiddenSeqs(0)); + assertEquals(0, hs.findIndexWithoutHiddenSeqs(1)); + assertEquals(1, hs.findIndexWithoutHiddenSeqs(2)); + assertEquals(2, hs.findIndexWithoutHiddenSeqs(3)); + assertEquals(3, hs.findIndexWithoutHiddenSeqs(4)); + assertEquals(3, hs.findIndexWithoutHiddenSeqs(5)); + assertEquals(3, hs.findIndexWithoutHiddenSeqs(6)); + assertEquals(4, hs.findIndexWithoutHiddenSeqs(7)); + assertEquals(5, hs.findIndexWithoutHiddenSeqs(8)); + assertEquals(6, hs.findIndexWithoutHiddenSeqs(9)); + } + + /** + * Test the method that reconstructs (sort of) the full alignment including + * hidden sequences + */ + @Test(groups = "Functional") + public void testGetFullAlignment() + { + AlignmentI al = new Alignment(seqs); + assertArrayEquals(seqs, al.getSequencesArray()); + al.setProperty("a", "b"); + al.addAnnotation(new AlignmentAnnotation("ann", "label", 12f)); + al.setSeqrep(seqs[4]); + SequenceGroup sg = new SequenceGroup(); + sg.addSequence(seqs[8], false); + al.addGroup(sg); + ((Alignment) al).hasRNAStructure = true; + + HiddenSequences hs = al.getHiddenSequences(); + AlignmentI al2 = hs.getFullAlignment(); + // new alignment but with original sequences + assertNotSame(al, al2); + assertArrayEquals(al.getSequencesArray(), al2.getSequencesArray()); + + hs.hideSequence(seqs[4]); + hs.hideSequence(seqs[9]); + al2 = hs.getFullAlignment(); + assertNotSame(al, al2); + assertArrayEquals(seqs, al2.getSequencesArray()); + assertNotNull(al2.getProperties()); + assertSame(al.getProperties(), al2.getProperties()); + assertNotNull(al2.getAlignmentAnnotation()); + assertSame(al.getAlignmentAnnotation(), al2.getAlignmentAnnotation()); + assertSame(seqs[4], al2.getSeqrep()); + assertNotNull(al2.getGroups()); + assertSame(al.getGroups(), al2.getGroups()); + assertTrue(al2.hasRNAStructure()); + } + + /** + * Test the method that returns the hidden sequence at a given index in the + * full alignment + * + * @return either the sequence (if hidden) or null (if not hidden) + */ + @Test(groups = "Functional") + public void testGetHiddenSequence() + { + AlignmentI al = new Alignment(seqs); + HiddenSequences hs = al.getHiddenSequences(); + assertNull(hs.getHiddenSequence(0)); + hs.hideSequence(seqs[3]); + assertSame(seqs[3], hs.getHiddenSequence(3)); + assertNull(hs.getHiddenSequence(2)); + assertNull(hs.getHiddenSequence(4)); + } + + @Test(groups = "Functional") + public void testGetSize() + { + } + + @Test(groups = "Functional") + public void testGetWidth() + { + AlignmentI al = new Alignment(seqs); + HiddenSequences hs = al.getHiddenSequences(); + assertEquals(0, hs.getWidth()); + hs.hideSequence(seqs[6]); + hs.hideSequence(seqs[8]); + assertEquals(9, hs.getWidth()); + } + + /** + * Test the method that adds a sequence to the hidden sequences and deletes it + * from the alignment, and its converse + */ + @Test(groups = "Functional") + public void testHideShowSequence() + { + AlignmentI al = new Alignment(seqs); + assertTrue(al.getSequences().contains(seqs[1])); + HiddenSequences hs = al.getHiddenSequences(); + assertEquals(0, hs.getSize()); + assertEquals(10, al.getHeight()); + + /* + * hide the second sequence in the alignment + */ + hs.hideSequence(seqs[1]); + assertFalse(hs.isHidden(seqs[0])); + assertTrue(hs.isHidden(seqs[1])); + assertFalse(al.getSequences().contains(seqs[1])); + assertEquals(1, hs.getSize()); + assertEquals(9, al.getHeight()); + assertSame(seqs[2], al.getSequenceAt(1)); + + /* + * hide what is now the second sequence in the alignment + */ + hs.hideSequence(seqs[2]); + assertFalse(hs.isHidden(seqs[0])); + assertTrue(hs.isHidden(seqs[1])); + assertTrue(hs.isHidden(seqs[2])); + assertFalse(al.getSequences().contains(seqs[1])); + assertFalse(al.getSequences().contains(seqs[2])); + assertEquals(2, hs.getSize()); + assertEquals(8, al.getHeight()); + + /* + * perform 'reveal' on what is now the second sequence in the alignment + * this should unhide the two sequences that precede it + */ + List revealed = hs.showSequence(1, null); + assertEquals(2, revealed.size()); + assertTrue(revealed.contains(seqs[1])); + assertTrue(revealed.contains(seqs[2])); + assertEquals(0, hs.getSize()); + assertEquals(10, al.getHeight()); + } + + @Test(groups = "Functional") + public void testIsHidden() + { + AlignmentI al = new Alignment(seqs); + HiddenSequences hs = al.getHiddenSequences(); + hs.hideSequence(seqs[7]); + hs.hideSequence(seqs[4]); + assertTrue(hs.isHidden(seqs[4])); + assertFalse(hs.isHidden(seqs[5])); + assertFalse(hs.isHidden(seqs[6])); + assertTrue(hs.isHidden(seqs[7])); + assertFalse(hs.isHidden(null)); + assertFalse(hs.isHidden(new Sequence("", ""))); + } + + /** + * Test hiding and unhiding a group with a representative sequence. The + * representative should be left visible when the group is hidden, and + * included in the selected group when it is unhidden. + */ + @Test(groups = "Functional") + public void testHideShowSequence_withHiddenRepSequence() + { + AlignmentI al = new Alignment(seqs); + + /* + * represent seqs 2-4 with seq3 + * this hides seq2 and seq4 but not seq3 + */ + AlignViewport av = new AlignViewport(al); + SequenceGroup sg = new SequenceGroup(); + sg.addSequence(seqs[1], false); + sg.addSequence(seqs[2], false); + sg.addSequence(seqs[3], false); + av.setSelectionGroup(sg); + + /* + * hiding group with reference sequence is done via AlignViewport + */ + av.hideSequences(seqs[2], true); + HiddenSequences hs = al.getHiddenSequences(); + assertEquals(2, hs.getSize()); + assertTrue(hs.isHidden(seqs[1])); + assertFalse(hs.isHidden(seqs[2])); + assertTrue(hs.isHidden(seqs[3])); + + /* + * should now be no sequences selected in the alignment + */ + assertNull(av.getSelectionGroup()); + + /* + * visible alignment is now seq0/2/4/5/6/7/8/9 + * 'reveal sequences' at the representative sequence (index = 1) + * this should unhide the one above i.e. seq1 + * and return a selection list including seq2 + * + * note have to call via AlignViewport to get the expected + * resulting sequence selection + */ + av.showSequence(1); + + /* + * only seq3 is now hidden + */ + assertEquals(1, hs.getSize()); + assertTrue(hs.isHidden(seqs[3])); + assertEquals(SEQ_COUNT - 1, al.getHeight()); + sg = av.getSelectionGroup(); + + /* + * unhidden and representative sequence selected + * (this behaviour may change! JAL-2133) + */ + assertEquals(2, sg.getSize()); + assertTrue(sg.getSequences().contains(seqs[1])); + assertTrue(sg.getSequences().contains(seqs[2])); + assertFalse(sg.getSequences().contains(seqs[3])); + } +} diff --git a/test/jalview/io/Jalview2xmlTests.java b/test/jalview/io/Jalview2xmlTests.java index 00d4ee0..a77e10a 100644 --- a/test/jalview/io/Jalview2xmlTests.java +++ b/test/jalview/io/Jalview2xmlTests.java @@ -20,13 +20,17 @@ */ package jalview.io; +import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertTrue; +import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; import jalview.api.ViewStyleI; import jalview.bin.Cache; import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.HiddenSequences; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; @@ -34,9 +38,12 @@ import jalview.gui.Desktop; import jalview.gui.Jalview2XML; import jalview.schemes.AnnotationColourGradient; import jalview.schemes.ColourSchemeI; +import jalview.viewmodel.AlignmentViewport; import java.io.File; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.testng.Assert; @@ -66,10 +73,9 @@ public class Jalview2xmlTests public static void tearDownAfterClass() throws Exception { jalview.gui.Desktop.instance.closeAll_actionPerformed(null); - } - public int countDsAnn(jalview.viewmodel.AlignmentViewport avp) + int countDsAnn(jalview.viewmodel.AlignmentViewport avp) { int numdsann = 0; for (SequenceI sq : avp.getAlignment().getDataset().getSequences()) @@ -361,7 +367,7 @@ public class Jalview2xmlTests * * @throws Exception */ - @Test(groups = { "Functional" }, enabled = false) + @Test(groups = { "Functional" }, enabled = true) public void testStoreAndRecoverExpandedviews() throws Exception { AlignFrame af = new jalview.io.FileLoader().LoadFileWaitTillLoaded( @@ -417,7 +423,8 @@ public class Jalview2xmlTests } /** - * based on above test store and recovery of expanded views. + * Test save and reload of a project with a different representative sequence + * in each view. * * @throws Exception */ @@ -425,36 +432,69 @@ public class Jalview2xmlTests public void testStoreAndRecoverReferenceSeqSettings() throws Exception { Desktop.instance.closeAll_actionPerformed(null); - String afid = ""; - { - AlignFrame af = new jalview.io.FileLoader().LoadFileWaitTillLoaded( - "examples/exampleFile_2_7.jar", FormatAdapter.FILE); - assertTrue("Didn't read in the example file correctly.", af != null); - afid = af.getViewport().getSequenceSetId(); - } - Map refs = new HashMap(); + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded( + "examples/exampleFile_2_7.jar", FormatAdapter.FILE); + assertTrue("Didn't read in the example file correctly.", af != null); + String afid = af.getViewport().getSequenceSetId(); + + /* + * remember representative and hidden sequences marked + * on each panel + */ + Map refseqs = new HashMap(); + Map> hiddenSeqNames = new HashMap>(); + + /* + * mark sequence 2, 3, 4.. in panels 1, 2, 3... + * as reference sequence for itself and the preceding sequence + */ int n = 1; for (AlignmentViewPanel ap : Desktop.getAlignmentPanels(afid)) { - // mark representative - SequenceI rep = ap.getAlignment().getSequenceAt( - n++ % ap.getAlignment().getHeight()); - refs.put(ap.getViewName(), rep); + AlignViewportI av = ap.getAlignViewport(); + AlignmentI alignment = ap.getAlignment(); + int repIndex = n % alignment.getHeight(); + SequenceI rep = alignment.getSequenceAt(repIndex); + refseqs.put(ap.getViewName(), rep); + List hiddenNames = new ArrayList(); + hiddenSeqNames.put(ap.getViewName(), hiddenNames); + + /* + * hide rep sequence and the one before it + */ + SequenceI seqToHide = alignment.getSequenceAt(repIndex); + SequenceGroup sg = new SequenceGroup(); + sg.addSequence(seqToHide, false); + SequenceI precedingSeq = alignment.getSequenceAt(repIndex - 1); + sg.addSequence(precedingSeq, false); + av.setSelectionGroup(sg); + ((AlignmentViewport) av).hideSequences(seqToHide, true); + + /* + * record names of hidden sequences + */ + HiddenSequences hs = alignment.getHiddenSequences(); + for (SequenceI seq : hs.hiddenSequences) + { + if (seq != null) + { + hiddenNames.add(seq.getName()); + } + } // code from mark/unmark sequence as reference in jalview.gui.PopupMenu - // todo refactor the to an alignment view controller - ap.getAlignViewport().setDisplayReferenceSeq(true); - ap.getAlignViewport().setColourByReferenceSeq(true); - ap.getAlignViewport().getAlignment().setSeqrep(rep); + // todo refactor this to an alignment view controller + av.setDisplayReferenceSeq(true); + av.setColourByReferenceSeq(true); + av.getAlignment().setSeqrep(rep); + + n++; } File tfile = File.createTempFile("testStoreAndRecoverReferenceSeq", ".jvp"); try { new Jalview2XML(false).saveState(tfile); - } catch (Error e) - { - Assert.fail("Didn't save the expanded view state", e); - } catch (Exception e) + } catch (Throwable e) { Assert.fail("Didn't save the expanded view state", e); } @@ -463,28 +503,39 @@ public class Jalview2xmlTests { Assert.assertEquals(Desktop.getAlignFrames().length, 0); } - { - AlignFrame af = new jalview.io.FileLoader().LoadFileWaitTillLoaded( + + af = new FileLoader().LoadFileWaitTillLoaded( tfile.getAbsolutePath(), FormatAdapter.FILE); - afid = af.getViewport().getSequenceSetId(); - } + afid = af.getViewport().getSequenceSetId(); + for (AlignmentViewPanel ap : Desktop.getAlignmentPanels(afid)) { // check representative - SequenceI rep = ap.getAlignment().getSeqrep(); + AlignmentI alignment = ap.getAlignment(); + SequenceI rep = alignment.getSeqrep(); Assert.assertNotNull(rep, "Couldn't restore sequence representative from project"); // can't use a strong equals here, because by definition, the sequence IDs // will be different. // could set vamsas session save/restore flag to preserve IDs across // load/saves. - Assert.assertEquals(refs.get(ap.getViewName()).toString(), + Assert.assertEquals(refseqs.get(ap.getViewName()).toString(), rep.toString(), "Representative wasn't the same when recovered."); Assert.assertTrue(ap.getAlignViewport().isDisplayReferenceSeq(), "Display reference sequence view setting not set."); Assert.assertTrue(ap.getAlignViewport().isColourByReferenceSeq(), "Colour By Reference Seq view setting not set."); + + /* + * verify hidden sequences in restored panel + */ + List hidden = hiddenSeqNames.get(ap.getViewName()); + HiddenSequences hs = alignment.getHiddenSequences(); + assertEquals( + "wrong number of restored hidden sequences in " + + ap.getViewName(), + hidden.size(), hs.getSize()); } }