88f3fdd72189bae594614cfe2d0e73f18b996120
[jalview.git] / test / jalview / io / Jalview2xmlTests.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
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.
11  *  
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.
16  * 
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.
20  */
21 package jalview.io;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertNotNull;
26 import static org.testng.AssertJUnit.assertSame;
27 import static org.testng.AssertJUnit.assertTrue;
28
29 import jalview.api.AlignViewportI;
30 import jalview.api.AlignmentViewPanel;
31 import jalview.api.ViewStyleI;
32 import jalview.datamodel.AlignmentAnnotation;
33 import jalview.datamodel.AlignmentI;
34 import jalview.datamodel.HiddenSequences;
35 import jalview.datamodel.PDBEntry;
36 import jalview.datamodel.PDBEntry.Type;
37 import jalview.datamodel.SequenceCollectionI;
38 import jalview.datamodel.SequenceGroup;
39 import jalview.datamodel.SequenceI;
40 import jalview.gui.AlignFrame;
41 import jalview.gui.AlignmentPanel;
42 import jalview.gui.Desktop;
43 import jalview.gui.Jalview2XML;
44 import jalview.gui.JvOptionPane;
45 import jalview.schemes.AnnotationColourGradient;
46 import jalview.schemes.ColourSchemeI;
47 import jalview.schemes.ColourSchemeProperty;
48 import jalview.schemes.TCoffeeColourScheme;
49 import jalview.structure.StructureImportSettings;
50 import jalview.viewmodel.AlignmentViewport;
51
52 import java.io.File;
53 import java.util.ArrayList;
54 import java.util.HashMap;
55 import java.util.List;
56 import java.util.Map;
57
58 import org.testng.Assert;
59 import org.testng.AssertJUnit;
60 import org.testng.annotations.BeforeClass;
61 import org.testng.annotations.Test;
62
63 @Test(singleThreaded = true)
64 public class Jalview2xmlTests extends Jalview2xmlBase
65 {
66
67   @Override
68   @BeforeClass(alwaysRun = true)
69   public void setUpJvOptionPane()
70   {
71     JvOptionPane.setInteractiveMode(false);
72     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
73   }
74
75   @Test(groups = { "Functional" })
76   public void testRNAStructureRecovery() throws Exception
77   {
78     String inFile = "examples/RF00031_folded.stk";
79     String tfile = File.createTempFile("JalviewTest", ".jvp")
80             .getAbsolutePath();
81     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
82             inFile, DataSourceType.FILE);
83     assertTrue("Didn't read input file " + inFile, af != null);
84     int olddsann = countDsAnn(af.getViewport());
85     assertTrue("Didn't find any dataset annotations", olddsann > 0);
86     af.rnahelicesColour_actionPerformed();
87     assertTrue(
88             "Couldn't apply RNA helices colourscheme",
89             af.getViewport().getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);
90     assertTrue("Failed to store as a project.",
91             af.saveAlignment(tfile, FileFormat.Jalview));
92     af.closeMenuItem_actionPerformed(true);
93     af = null;
94     af = new FileLoader().LoadFileWaitTillLoaded(tfile, DataSourceType.FILE);
95     assertTrue("Failed to import new project", af != null);
96     int newdsann = countDsAnn(af.getViewport());
97     assertTrue(
98             "Differing numbers of dataset sequence annotation\nOriginally "
99                     + olddsann + " and now " + newdsann,
100             olddsann == newdsann);
101     System.out
102             .println("Read in same number of annotations as originally present ("
103                     + olddsann + ")");
104     assertTrue(
105             "RNA helices colourscheme was not applied on import.",
106             af.getViewport().getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);
107   }
108
109   @Test(groups = { "Functional" })
110   public void testTCoffeeScores() throws Exception
111   {
112     String inFile = "examples/uniref50.fa", inAnnot = "examples/uniref50.score_ascii";
113     String tfile = File.createTempFile("JalviewTest", ".jvp")
114             .getAbsolutePath();
115     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
116             inFile, DataSourceType.FILE);
117     assertNotNull("Didn't read input file " + inFile, af);
118     af.loadJalviewDataFile(inAnnot, DataSourceType.FILE, null, null);
119     assertSame("Didn't set T-coffee colourscheme", af.getViewport()
120             .getGlobalColourScheme().getClass(), TCoffeeColourScheme.class);
121     assertNotNull("Recognise T-Coffee score from string",
122             ColourSchemeProperty.getColour(af.getViewport()
123                     .getAlignment(), ColourSchemeProperty.getColourName(af
124                     .getViewport().getGlobalColourScheme())));
125
126     assertTrue("Failed to store as a project.",
127             af.saveAlignment(tfile, FileFormat.Jalview));
128     af.closeMenuItem_actionPerformed(true);
129     af = null;
130     af = new FileLoader().LoadFileWaitTillLoaded(tfile,
131             DataSourceType.FILE);
132     assertNotNull("Failed to import new project", af);
133     assertSame("Didn't set T-coffee colourscheme for imported project.", af
134             .getViewport().getGlobalColourScheme().getClass(),
135             TCoffeeColourScheme.class);
136     System.out
137             .println("T-Coffee score shading successfully recovered from project.");
138   }
139
140   @Test(groups = { "Functional" })
141   public void testColourByAnnotScores() throws Exception
142   {
143     String inFile = "examples/uniref50.fa", inAnnot = "examples/testdata/uniref50_iupred.jva";
144     String tfile = File.createTempFile("JalviewTest", ".jvp")
145             .getAbsolutePath();
146     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(inFile, DataSourceType.FILE);
147     assertNotNull("Didn't read input file " + inFile, af);
148     af.loadJalviewDataFile(inAnnot, DataSourceType.FILE, null, null);
149     AlignmentAnnotation[] aa = af.getViewport().getAlignment()
150             .getSequenceAt(0).getAnnotation("IUPredWS (Short)");
151     assertTrue(
152             "Didn't find any IUPred annotation to use to shade alignment.",
153             aa != null && aa.length > 0);
154     AnnotationColourGradient cs = new AnnotationColourGradient(aa[0], null,
155             AnnotationColourGradient.ABOVE_THRESHOLD);
156     AnnotationColourGradient gcs = new AnnotationColourGradient(aa[0],
157             null, AnnotationColourGradient.BELOW_THRESHOLD);
158     cs.setSeqAssociated(true);
159     gcs.setSeqAssociated(true);
160     af.changeColour(cs);
161     SequenceGroup sg = new SequenceGroup();
162     sg.setStartRes(57);
163     sg.setEndRes(92);
164     sg.cs = gcs;
165     af.getViewport().getAlignment().addGroup(sg);
166     sg.addSequence(af.getViewport().getAlignment().getSequenceAt(1), false);
167     sg.addSequence(af.getViewport().getAlignment().getSequenceAt(2), true);
168     af.alignPanel.alignmentChanged();
169     assertTrue("Failed to store as a project.",
170             af.saveAlignment(tfile, FileFormat.Jalview));
171     af.closeMenuItem_actionPerformed(true);
172     af = null;
173     af = new FileLoader().LoadFileWaitTillLoaded(tfile, DataSourceType.FILE);
174     assertTrue("Failed to import new project", af != null);
175
176     // check for group and alignment colourschemes
177
178     ColourSchemeI _rcs = af.getViewport().getGlobalColourScheme();
179     ColourSchemeI _rgcs = af.getViewport().getAlignment().getGroups()
180             .get(0).cs;
181     assertNotNull("Didn't recover global colourscheme", _rcs);
182     assertTrue("Didn't recover annotation colour global scheme",
183             _rcs instanceof AnnotationColourGradient);
184     AnnotationColourGradient __rcs = (AnnotationColourGradient) _rcs;
185     assertTrue("Annotation colourscheme wasn't sequence associated",
186             __rcs.isSeqAssociated());
187
188     boolean diffseqcols = false, diffgseqcols = false;
189     SequenceI[] sqs = af.getViewport().getAlignment().getSequencesArray();
190     for (int p = 0, pSize = af.getViewport().getAlignment().getWidth(); p < pSize
191             && (!diffseqcols || !diffgseqcols); p++)
192     {
193       if (_rcs.findColour(sqs[0].getCharAt(p), p, sqs[0]) != _rcs
194               .findColour(sqs[5].getCharAt(p), p, sqs[5]))
195       {
196         diffseqcols = true;
197       }
198     }
199     assertTrue("Got Different sequence colours", diffseqcols);
200     System.out
201             .println("Per sequence colourscheme (Background) successfully applied and recovered.");
202
203     assertNotNull("Didn't recover group colourscheme", _rgcs);
204     assertTrue("Didn't recover annotation colour group colourscheme",
205             _rgcs instanceof AnnotationColourGradient);
206     __rcs = (AnnotationColourGradient) _rgcs;
207     assertTrue("Group Annotation colourscheme wasn't sequence associated",
208             __rcs.isSeqAssociated());
209
210     for (int p = 0, pSize = af.getViewport().getAlignment().getWidth(); p < pSize
211             && (!diffseqcols || !diffgseqcols); p++)
212     {
213       if (_rgcs.findColour(sqs[1].getCharAt(p), p, sqs[1]) != _rgcs
214               .findColour(sqs[2].getCharAt(p), p, sqs[2]))
215       {
216         diffgseqcols = true;
217       }
218     }
219     assertTrue("Got Different group sequence colours", diffgseqcols);
220     System.out
221             .println("Per sequence (Group) colourscheme successfully applied and recovered.");
222   }
223
224   @Test(groups = { "Functional" })
225   public void gatherViewsHere() throws Exception
226   {
227     int origCount = Desktop.getAlignFrames() == null ? 0 : Desktop
228             .getAlignFrames().length;
229     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
230             "examples/exampleFile_2_7.jar", DataSourceType.FILE);
231     assertNotNull("Didn't read in the example file correctly.", af);
232     assertTrue("Didn't gather the views in the example file.",
233             Desktop.getAlignFrames().length == 1 + origCount);
234
235   }
236
237   @Test(groups = { "Functional" })
238   public void viewRefPdbAnnotation() throws Exception
239   {
240     StructureImportSettings.setProcessSecondaryStructure(true);
241     StructureImportSettings.setVisibleChainAnnotation(true);
242     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
243             "examples/exampleFile_2_7.jar", DataSourceType.FILE);
244     assertNotNull("Didn't read in the example file correctly.", af);
245     AlignmentViewPanel sps = null;
246     for (AlignmentViewPanel ap : af.alignPanel.alignFrame.getAlignPanels())
247     {
248       if ("Spinach Feredoxin Structure".equals(ap.getViewName()))
249       {
250         sps = ap;
251         break;
252       }
253     }
254     assertNotNull("Couldn't find the structure view", sps);
255     AlignmentAnnotation refan = null;
256     for (AlignmentAnnotation ra : sps.getAlignment()
257             .getAlignmentAnnotation())
258     {
259       if (ra.graph != 0)
260       {
261         refan = ra;
262         break;
263       }
264     }
265     assertNotNull("Annotation secondary structure not found.", refan);
266     SequenceI sq = sps.getAlignment().findName("1A70|");
267     assertNotNull("Couldn't find 1a70 null chain", sq);
268     // compare the manually added temperature factor annotation
269     // to the track automatically transferred from the pdb structure on load
270     assertNotNull("1a70 has no annotation", sq.getDatasetSequence()
271             .getAnnotation());
272     for (AlignmentAnnotation ala : sq.getDatasetSequence().getAnnotation())
273     {
274       AlignmentAnnotation alaa;
275       sq.addAlignmentAnnotation(alaa = new AlignmentAnnotation(ala));
276       alaa.adjustForAlignment();
277       if (ala.graph == refan.graph)
278       {
279         for (int p = 0; p < ala.annotations.length; p++)
280         {
281           sq.findPosition(p);
282           try
283           {
284             assertTrue(
285                     "Mismatch at alignment position " + p,
286                     (alaa.annotations[p] == null && refan.annotations[p] == null)
287                             || alaa.annotations[p].value == refan.annotations[p].value);
288           } catch (NullPointerException q)
289           {
290             Assert.fail("Mismatch of alignment annotations at position "
291                     + p + " Ref seq ann: " + refan.annotations[p]
292                     + " alignment " + alaa.annotations[p]);
293           }
294         }
295       }
296     }
297
298   }
299
300   @Test(groups = { "Functional" })
301   public void testCopyViewSettings() throws Exception
302   {
303     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
304             "examples/exampleFile_2_7.jar", DataSourceType.FILE);
305     assertNotNull("Didn't read in the example file correctly.", af);
306     AlignmentViewPanel sps = null, groups = null;
307     for (AlignmentViewPanel ap : af.alignPanel.alignFrame.getAlignPanels())
308     {
309       if ("Spinach Feredoxin Structure".equals(ap.getViewName()))
310       {
311         sps = ap;
312       }
313       if (ap.getViewName().contains("MAFFT"))
314       {
315         groups = ap;
316       }
317     }
318     assertNotNull("Couldn't find the structure view", sps);
319     assertNotNull("Couldn't find the MAFFT view", groups);
320
321     ViewStyleI structureStyle = sps.getAlignViewport().getViewStyle();
322     ViewStyleI groupStyle = groups.getAlignViewport().getViewStyle();
323     AssertJUnit.assertFalse(structureStyle.sameStyle(groupStyle));
324
325     groups.getAlignViewport().setViewStyle(structureStyle);
326     AssertJUnit.assertFalse(groupStyle.sameStyle(groups.getAlignViewport()
327             .getViewStyle()));
328     Assert.assertTrue(structureStyle.sameStyle(groups.getAlignViewport()
329             .getViewStyle()));
330
331   }
332
333   /**
334    * test store and recovery of expanded views
335    * 
336    * @throws Exception
337    */
338   @Test(groups = { "Functional" }, enabled = true)
339   public void testStoreAndRecoverExpandedviews() throws Exception
340   {
341     Desktop.instance.closeAll_actionPerformed(null);
342
343     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
344             "examples/exampleFile_2_7.jar", DataSourceType.FILE);
345     Assert.assertEquals(Desktop.getAlignFrames().length, 1);
346     String afid = af.getViewport().getSequenceSetId();
347
348     // check FileLoader returned a reference to the one alignFrame that is
349     // actually on the Desktop
350     assertTrue(
351             "Jalview2XML.loadAlignFrame() didn't return correct AlignFrame reference for multiple view window",
352             af == Desktop.getAlignFrameFor(af.getViewport()));
353
354     Desktop.explodeViews(af);
355
356     int oldviews = Desktop.getAlignFrames().length;
357     Assert.assertEquals(Desktop.getAlignFrames().length,
358             Desktop.getAlignmentPanels(afid).length);
359     File tfile = File.createTempFile("testStoreAndRecoverExpanded", ".jvp");
360     try
361     {
362       new Jalview2XML(false).saveState(tfile);
363     } catch (Error e)
364     {
365       Assert.fail("Didn't save the expanded view state", e);
366     } catch (Exception e)
367     {
368       Assert.fail("Didn't save the expanded view state", e);
369     }
370     Desktop.instance.closeAll_actionPerformed(null);
371     if (Desktop.getAlignFrames() != null)
372     {
373       Assert.assertEquals(Desktop.getAlignFrames().length, 0);
374     }
375     af = new FileLoader().LoadFileWaitTillLoaded(
376             tfile.getAbsolutePath(), DataSourceType.FILE);
377     Assert.assertNotNull(af);
378     Assert.assertEquals(
379             Desktop.getAlignFrames().length,
380             Desktop.getAlignmentPanels(af.getViewport().getSequenceSetId()).length);
381     Assert.assertEquals(
382             oldviews,
383             Desktop.getAlignmentPanels(af.getViewport().getSequenceSetId()).length);
384   }
385
386   /**
387    * Test save and reload of a project with a different representative sequence
388    * in each view.
389    * 
390    * @throws Exception
391    */
392   @Test(groups = { "Functional" })
393   public void testStoreAndRecoverReferenceSeqSettings() throws Exception
394   {
395     Desktop.instance.closeAll_actionPerformed(null);
396     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
397             "examples/exampleFile_2_7.jar", DataSourceType.FILE);
398     assertNotNull("Didn't read in the example file correctly.", af);
399     String afid = af.getViewport().getSequenceSetId();
400
401     // remember reference sequence for each panel
402     Map<String, SequenceI> refseqs = new HashMap<String, SequenceI>();
403
404     /*
405      * mark sequence 2, 3, 4.. in panels 1, 2, 3...
406      * as reference sequence for itself and the preceding sequence
407      */
408     int n = 1;
409     for (AlignmentViewPanel ap : Desktop.getAlignmentPanels(afid))
410     {
411       AlignViewportI av = ap.getAlignViewport();
412       AlignmentI alignment = ap.getAlignment();
413       int repIndex = n % alignment.getHeight();
414       SequenceI rep = alignment.getSequenceAt(repIndex);
415       refseqs.put(ap.getViewName(), rep);
416
417       // code from mark/unmark sequence as reference in jalview.gui.PopupMenu
418       // todo refactor this to an alignment view controller
419       av.setDisplayReferenceSeq(true);
420       av.setColourByReferenceSeq(true);
421       av.getAlignment().setSeqrep(rep);
422
423       n++;
424     }
425     File tfile = File.createTempFile("testStoreAndRecoverReferenceSeq",
426             ".jvp");
427     try
428     {
429       new Jalview2XML(false).saveState(tfile);
430     } catch (Throwable e)
431     {
432       Assert.fail("Didn't save the expanded view state", e);
433     }
434     Desktop.instance.closeAll_actionPerformed(null);
435     if (Desktop.getAlignFrames() != null)
436     {
437       Assert.assertEquals(Desktop.getAlignFrames().length, 0);
438     }
439
440     af = new FileLoader().LoadFileWaitTillLoaded(
441             tfile.getAbsolutePath(), DataSourceType.FILE);
442     afid = af.getViewport().getSequenceSetId();
443
444     for (AlignmentViewPanel ap : Desktop.getAlignmentPanels(afid))
445     {
446       // check representative
447       AlignmentI alignment = ap.getAlignment();
448       SequenceI rep = alignment.getSeqrep();
449       Assert.assertNotNull(rep,
450               "Couldn't restore sequence representative from project");
451       // can't use a strong equals here, because by definition, the sequence IDs
452       // will be different.
453       // could set vamsas session save/restore flag to preserve IDs across
454       // load/saves.
455       Assert.assertEquals(refseqs.get(ap.getViewName()).toString(),
456               rep.toString(),
457               "Representative wasn't the same when recovered.");
458       Assert.assertTrue(ap.getAlignViewport().isDisplayReferenceSeq(),
459               "Display reference sequence view setting not set.");
460       Assert.assertTrue(ap.getAlignViewport().isColourByReferenceSeq(),
461               "Colour By Reference Seq view setting not set.");
462     }
463   }
464
465   @Test(groups = { "Functional" })
466   public void testIsVersionStringLaterThan()
467   {
468     /*
469      * No version / development / test / autobuild is leniently assumed to be
470      * compatible
471      */
472     assertTrue(Jalview2XML.isVersionStringLaterThan(null, null));
473     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3", null));
474     assertTrue(Jalview2XML.isVersionStringLaterThan(null, "2.8.3"));
475     assertTrue(Jalview2XML.isVersionStringLaterThan(null,
476             "Development Build"));
477     assertTrue(Jalview2XML.isVersionStringLaterThan(null,
478             "DEVELOPMENT BUILD"));
479     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3",
480             "Development Build"));
481     assertTrue(Jalview2XML.isVersionStringLaterThan(null, "Test"));
482     assertTrue(Jalview2XML.isVersionStringLaterThan(null, "TEST"));
483     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3", "Test"));
484     assertTrue(Jalview2XML
485             .isVersionStringLaterThan(null, "Automated Build"));
486     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3",
487             "Automated Build"));
488     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3",
489             "AUTOMATED BUILD"));
490
491     /*
492      * same version returns true i.e. compatible
493      */
494     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8", "2.8"));
495     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3", "2.8.3"));
496     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3b1", "2.8.3b1"));
497     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3B1", "2.8.3b1"));
498     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3b1", "2.8.3B1"));
499
500     /*
501      * later version returns true
502      */
503     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3", "2.8.4"));
504     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3", "2.9"));
505     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3", "2.9.2"));
506     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8", "2.8.3"));
507     assertTrue(Jalview2XML.isVersionStringLaterThan("2.8.3", "2.8.3b1"));
508
509     /*
510      * earlier version returns false
511      */
512     assertFalse(Jalview2XML.isVersionStringLaterThan("2.8.3", "2.8"));
513     assertFalse(Jalview2XML.isVersionStringLaterThan("2.8.4", "2.8.3"));
514     assertFalse(Jalview2XML.isVersionStringLaterThan("2.8.3b1", "2.8.3"));
515     assertFalse(Jalview2XML.isVersionStringLaterThan("2.8.3", "2.8.2b1"));
516     assertFalse(Jalview2XML.isVersionStringLaterThan("2.8.0b2", "2.8.0b1"));
517   }
518
519   /**
520    * Test save and reload of a project with a different sequence group (and
521    * representative sequence) in each view.
522    * 
523    * @throws Exception
524    */
525   @Test(groups = { "Functional" })
526   public void testStoreAndRecoverGroupRepSeqs() throws Exception
527   {
528     Desktop.instance.closeAll_actionPerformed(null);
529     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
530             "examples/uniref50.fa", DataSourceType.FILE);
531     assertNotNull("Didn't read in the example file correctly.", af);
532     String afid = af.getViewport().getSequenceSetId();
533     // make a second view of the alignment
534     af.newView_actionPerformed(null);
535
536     /*
537      * remember representative and hidden sequences marked 
538      * on each panel
539      */
540     Map<String, SequenceI> repSeqs = new HashMap<String, SequenceI>();
541     Map<String, List<String>> hiddenSeqNames = new HashMap<String, List<String>>();
542
543     /*
544      * mark sequence 2, 3, 4.. in panels 1, 2, 3...
545      * as reference sequence for itself and the preceding sequence
546      */
547     int n = 1;
548     for (AlignmentViewPanel ap : Desktop.getAlignmentPanels(afid))
549     {
550       AlignViewportI av = ap.getAlignViewport();
551       AlignmentI alignment = ap.getAlignment();
552       int repIndex = n % alignment.getHeight();
553       // ensure at least one preceding sequence i.e. index >= 1
554       repIndex = Math.max(repIndex, 1);
555       SequenceI repSeq = alignment.getSequenceAt(repIndex);
556       repSeqs.put(ap.getViewName(), repSeq);
557       List<String> hiddenNames = new ArrayList<String>();
558       hiddenSeqNames.put(ap.getViewName(), hiddenNames);
559
560       /*
561        * have rep sequence represent itself and the one before it
562        * this hides the group (except for the rep seq)
563        */
564       SequenceGroup sg = new SequenceGroup();
565       sg.addSequence(repSeq, false);
566       SequenceI precedingSeq = alignment.getSequenceAt(repIndex - 1);
567       sg.addSequence(precedingSeq, false);
568       sg.setSeqrep(repSeq);
569       assertTrue(sg.getSequences().contains(repSeq));
570       assertTrue(sg.getSequences().contains(precedingSeq));
571       av.setSelectionGroup(sg);
572       assertSame(repSeq, sg.getSeqrep());
573
574       /*
575        * represent group with sequence adds to a map of hidden rep sequences
576        * (it does not create a group on the alignment) 
577        */
578       ((AlignmentViewport) av).hideSequences(repSeq, true);
579       assertSame(repSeq, sg.getSeqrep());
580       assertTrue(sg.getSequences().contains(repSeq));
581       assertTrue(sg.getSequences().contains(precedingSeq));
582       assertTrue("alignment has groups", alignment.getGroups().isEmpty());
583       Map<SequenceI, SequenceCollectionI> hiddenRepSeqsMap = av
584               .getHiddenRepSequences();
585       assertNotNull(hiddenRepSeqsMap);
586       assertEquals(1, hiddenRepSeqsMap.size());
587       assertSame(sg, hiddenRepSeqsMap.get(repSeq));
588       assertTrue(alignment.getHiddenSequences().isHidden(precedingSeq));
589       assertFalse(alignment.getHiddenSequences().isHidden(repSeq));
590       hiddenNames.add(precedingSeq.getName());
591
592       n++;
593     }
594     File tfile = File
595             .createTempFile("testStoreAndRecoverGroupReps", ".jvp");
596     try
597     {
598       new Jalview2XML(false).saveState(tfile);
599     } catch (Throwable e)
600     {
601       Assert.fail("Didn't save the expanded view state", e);
602     }
603     Desktop.instance.closeAll_actionPerformed(null);
604     if (Desktop.getAlignFrames() != null)
605     {
606       Assert.assertEquals(Desktop.getAlignFrames().length, 0);
607     }
608   
609     af = new FileLoader().LoadFileWaitTillLoaded(
610             tfile.getAbsolutePath(), DataSourceType.FILE);
611     afid = af.getViewport().getSequenceSetId();
612
613     for (AlignmentViewPanel ap : Desktop.getAlignmentPanels(afid))
614     {
615       String viewName = ap.getViewName();
616       AlignViewportI av = ap.getAlignViewport();
617       AlignmentI alignment = ap.getAlignment();
618       List<SequenceGroup> groups = alignment.getGroups();
619       assertNotNull(groups);
620       assertTrue("Alignment has groups", groups.isEmpty());
621       Map<SequenceI, SequenceCollectionI> hiddenRepSeqsMap = av
622               .getHiddenRepSequences();
623       assertNotNull("No hidden represented sequences", hiddenRepSeqsMap);
624       assertEquals(1, hiddenRepSeqsMap.size());
625       assertEquals(repSeqs.get(viewName).getDisplayId(true),
626               hiddenRepSeqsMap.keySet().iterator().next()
627                       .getDisplayId(true));
628
629       /*
630        * verify hidden sequences in restored panel
631        */
632       List<String> hidden = hiddenSeqNames.get(ap.getViewName());
633       HiddenSequences hs = alignment.getHiddenSequences();
634       assertEquals(
635               "wrong number of restored hidden sequences in "
636                       + ap.getViewName(), hidden.size(), hs.getSize());
637     }
638   }
639
640   /**
641    * Test save and reload of PDBEntry in Jalview project
642    * 
643    * @throws Exception
644    */
645   @Test(groups = { "Functional" })
646   public void testStoreAndRecoverPDBEntry() throws Exception
647   {
648     Desktop.instance.closeAll_actionPerformed(null);
649     String exampleFile = "examples/3W5V.pdb";
650     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(exampleFile,
651             DataSourceType.FILE);
652     assertNotNull("Didn't read in the example file correctly.", af);
653     String afid = af.getViewport().getSequenceSetId();
654
655     AlignmentPanel[] alignPanels = Desktop.getAlignmentPanels(afid);
656     System.out.println();
657     AlignmentViewPanel ap = alignPanels[0];
658     String tfileBase = new File(".").getAbsolutePath().replace(".", "");
659     String testFile = tfileBase + exampleFile;
660     AlignmentI alignment = ap.getAlignment();
661     System.out.println("blah");
662     SequenceI[] seqs = alignment.getSequencesArray();
663     Assert.assertNotNull(seqs[0]);
664     Assert.assertNotNull(seqs[1]);
665     Assert.assertNotNull(seqs[2]);
666     Assert.assertNotNull(seqs[3]);
667     Assert.assertNotNull(seqs[0].getDatasetSequence());
668     Assert.assertNotNull(seqs[1].getDatasetSequence());
669     Assert.assertNotNull(seqs[2].getDatasetSequence());
670     Assert.assertNotNull(seqs[3].getDatasetSequence());
671     PDBEntry[] pdbEntries = new PDBEntry[4];
672     pdbEntries[0] = new PDBEntry("3W5V", "A", Type.PDB, testFile);
673     pdbEntries[1] = new PDBEntry("3W5V", "B", Type.PDB, testFile);
674     pdbEntries[2] = new PDBEntry("3W5V", "C", Type.PDB, testFile);
675     pdbEntries[3] = new PDBEntry("3W5V", "D", Type.PDB, testFile);
676     Assert.assertEquals(seqs[0].getDatasetSequence().getAllPDBEntries()
677             .get(0), pdbEntries[0]);
678     Assert.assertEquals(seqs[1].getDatasetSequence().getAllPDBEntries()
679             .get(0), pdbEntries[1]);
680     Assert.assertEquals(seqs[2].getDatasetSequence().getAllPDBEntries()
681             .get(0), pdbEntries[2]);
682     Assert.assertEquals(seqs[3].getDatasetSequence().getAllPDBEntries()
683             .get(0), pdbEntries[3]);
684
685     File tfile = File.createTempFile("testStoreAndRecoverPDBEntry", ".jvp");
686     try
687     {
688       new Jalview2XML(false).saveState(tfile);
689     } catch (Throwable e)
690     {
691       Assert.fail("Didn't save the state", e);
692     }
693     Desktop.instance.closeAll_actionPerformed(null);
694     if (Desktop.getAlignFrames() != null)
695     {
696       Assert.assertEquals(Desktop.getAlignFrames().length, 0);
697     }
698
699     AlignFrame restoredFrame = new FileLoader().LoadFileWaitTillLoaded(
700             tfile.getAbsolutePath(), DataSourceType.FILE);
701     String rfid = restoredFrame.getViewport().getSequenceSetId();
702     AlignmentPanel[] rAlignPanels = Desktop.getAlignmentPanels(rfid);
703     AlignmentViewPanel rap = rAlignPanels[0];
704     AlignmentI rAlignment = rap.getAlignment();
705     System.out.println("blah");
706     SequenceI[] rseqs = rAlignment.getSequencesArray();
707     Assert.assertNotNull(rseqs[0]);
708     Assert.assertNotNull(rseqs[1]);
709     Assert.assertNotNull(rseqs[2]);
710     Assert.assertNotNull(rseqs[3]);
711     Assert.assertNotNull(rseqs[0].getDatasetSequence());
712     Assert.assertNotNull(rseqs[1].getDatasetSequence());
713     Assert.assertNotNull(rseqs[2].getDatasetSequence());
714     Assert.assertNotNull(rseqs[3].getDatasetSequence());
715
716     // The Asserts below are expected to fail until the PDB chainCode is
717     // recoverable from a Jalview projects
718     for (int chain = 0; chain < 4; chain++)
719     {
720       PDBEntry recov = rseqs[chain].getDatasetSequence().getAllPDBEntries()
721               .get(0);
722       PDBEntry expected = pdbEntries[chain];
723       Assert.assertEquals(recov.getId(), expected.getId(),
724               "Mismatch PDB ID");
725       Assert.assertEquals(recov.getChainCode(), expected.getChainCode(),
726               "Mismatch PDB ID");
727       Assert.assertEquals(recov.getType(), expected.getType(),
728               "Mismatch PDBEntry 'Type'");
729       Assert.assertNotNull(recov.getFile(),
730               "Recovered PDBEntry should have a non-null file entry");
731     }
732   }
733 }