JAL-1497 check to see if tree structure is ready for display, and show a 'tree loadin...
[jalview.git] / src / jalview / gui / Jalview2XML.java
index 8872be0..3bca941 100644 (file)
@@ -1,19 +1,20 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
- * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
- *
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
+ * Copyright (C) 2014 The Jalview Authors
+ * 
  * This file is part of Jalview.
- *
+ * 
  * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
+ * modify it under the terms of the GNU General Public License 
  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
  * PURPOSE.  See the GNU General Public License for more details.
- *
+ * 
  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 package jalview.gui;
 
@@ -38,9 +39,9 @@ import jalview.schemabinding.version2.*;
 import jalview.schemes.*;
 import jalview.util.Platform;
 import jalview.util.jarInputStreamProvider;
-import jalview.ws.jws2.AAConsClient;
+import jalview.viewmodel.AlignmentViewport;
 import jalview.ws.jws2.Jws2Discoverer;
-import jalview.ws.jws2.dm.AAConsSettings;
+import jalview.ws.jws2.dm.AAConSettings;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.params.ArgumentI;
 import jalview.ws.params.AutoCalcSetting;
@@ -48,11 +49,11 @@ import jalview.ws.params.WsParamSetI;
 
 /**
  * Write out the current jalview desktop state as a Jalview XML stream.
- *
+ * 
  * Note: the vamsas objects referred to here are primitive versions of the
  * VAMSAS project schema elements - they are not the same and most likely never
  * will be :)
- *
+ * 
  * @author $author$
  * @version $Revision: 1.134 $
  */
@@ -60,7 +61,7 @@ public class Jalview2XML
 {
   /**
    * create/return unique hash string for sq
-   *
+   * 
    * @param sq
    * @return new or existing unique string for sq
    */
@@ -266,7 +267,7 @@ public class Jalview2XML
 
   /**
    * Writes a jalview project archive to the given Jar output stream.
-   *
+   * 
    * @param jout
    */
   public void SaveState(JarOutputStream jout)
@@ -278,6 +279,8 @@ public class Jalview2XML
       return;
     }
 
+    Hashtable<String,AlignFrame> dsses = new Hashtable<String,AlignFrame>();
+
     try
     {
 
@@ -332,6 +335,7 @@ public class Jalview2XML
           }
 
           int ap, apSize = af.alignPanels.size();
+
           for (ap = 0; ap < apSize; ap++)
           {
             AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
@@ -343,9 +347,19 @@ public class Jalview2XML
             }
 
             SaveState(apanel, fileName, jout);
+
+            String dssid = getDatasetIdRef(af.getViewport().getAlignment().getDataset());
+            if (!dsses.containsKey(dssid))
+            {
+              dsses.put(dssid, af);
+            }
+
           }
         }
       }
+
+      writeDatasetFor(dsses, ""+jout.hashCode()+" "+uniqueSetSuffix, jout);
+      
       try
       {
         jout.flush();
@@ -375,6 +389,7 @@ public class Jalview2XML
       int ap, apSize = af.alignPanels.size();
       FileOutputStream fos = new FileOutputStream(jarFile);
       JarOutputStream jout = new JarOutputStream(fos);
+      Hashtable<String,AlignFrame> dsses = new Hashtable<String,AlignFrame>();
       for (ap = 0; ap < apSize; ap++)
       {
         AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
@@ -385,8 +400,13 @@ public class Jalview2XML
           jfileName = jfileName + ".xml";
         }
         SaveState(apanel, jfileName, jout);
+        String dssid = getDatasetIdRef(af.getViewport().getAlignment().getDataset());
+        if (!dsses.containsKey(dssid))
+        {
+          dsses.put(dssid, af);
+        }
       }
-
+      writeDatasetFor(dsses, fileName, jout);
       try
       {
         jout.flush();
@@ -404,10 +424,26 @@ public class Jalview2XML
     }
   }
 
+  private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
+          String fileName, JarOutputStream jout)
+  {
+
+    for (String dssids:dsses.keySet())
+    {
+      AlignFrame _af = dsses.get(dssids);
+      String jfileName = fileName + " Dataset for "+ _af.getTitle();
+      if (!jfileName.endsWith(".xml"))
+      {
+        jfileName = jfileName + ".xml";
+      }
+      SaveState(_af.alignPanel, jfileName, true, jout);
+    }
+  }
+
   /**
    * create a JalviewModel from an algnment view and marshall it to a
    * JarOutputStream
-   *
+   * 
    * @param ap
    *          panel to create jalview model for
    * @param fileName
@@ -420,6 +456,26 @@ public class Jalview2XML
   public JalviewModel SaveState(AlignmentPanel ap, String fileName,
           JarOutputStream jout)
   {
+    return SaveState(ap, fileName, false,jout);
+  }
+  /**
+  * create a JalviewModel from an algnment view and marshall it to a
+  * JarOutputStream
+  * 
+  * @param ap
+  *          panel to create jalview model for
+  * @param fileName
+  *          name of alignment panel written to output stream
+  * @param storeDS
+  *          when true, only write the dataset for the alignment, not the data associated with the view.
+  * @param jout
+  *          jar output stream
+  * @param out
+  *          jar entry name
+  */
+  public JalviewModel SaveState(AlignmentPanel ap, String fileName, boolean storeDS,
+          JarOutputStream jout)
+  {
     initSeqRefs();
     Vector jmolViewIds = new Vector(); //
     Vector userColours = new Vector();
@@ -430,7 +486,7 @@ public class Jalview2XML
     object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
 
     object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
-    object.setVersion(jalview.bin.Cache.getProperty("VERSION"));
+    object.setVersion(jalview.bin.Cache.getDefault("VERSION","Development Build"));
 
     jalview.datamodel.AlignmentI jal = av.getAlignment();
 
@@ -449,6 +505,11 @@ public class Jalview2XML
     {
       // dataset id is the dataset's hashcode
       vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
+      if (storeDS)
+      {
+        // switch jal and the dataset
+        jal = jal.getDataset();
+      }
     }
     if (jal.getProperties() != null)
     {
@@ -464,14 +525,15 @@ public class Jalview2XML
     }
 
     JSeq jseq;
-    Set<String> calcIdSet=new HashSet<String>();
+    Set<String> calcIdSet = new HashSet<String>();
 
     // SAVE SEQUENCES
     String id = "";
-    jalview.datamodel.SequenceI jds;
+    jalview.datamodel.SequenceI jds,jdatasq;
     for (int i = 0; i < jal.getHeight(); i++)
     {
       jds = jal.getSequenceAt(i);
+      jdatasq=jds.getDatasetSequence() == null ? jds : jds.getDatasetSequence();
       id = seqHash(jds);
 
       if (seqRefIds.get(id) != null)
@@ -503,29 +565,34 @@ public class Jalview2XML
       jseq.setColour(av.getSequenceColour(jds).getRGB());
 
       jseq.setId(id); // jseq id should be a string not a number
-
-      if (av.hasHiddenRows())
+      if (!storeDS)
       {
-        jseq.setHidden(av.getAlignment().getHiddenSequences().isHidden(jds));
-
-        if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
+        // Store any sequences this sequence represents
+        if (av.hasHiddenRows())
         {
-          jalview.datamodel.SequenceI[] reps = av.getRepresentedSequences(
-                  jal.getSequenceAt(i)).getSequencesInOrder(jal);
+          jseq.setHidden(av.getAlignment().getHiddenSequences()
+                  .isHidden(jds));
 
-          for (int h = 0; h < reps.length; h++)
+          if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
           {
-            if (reps[h] != jal.getSequenceAt(i))
+            jalview.datamodel.SequenceI[] reps = av
+                    .getRepresentedSequences(jal.getSequenceAt(i))
+                    .getSequencesInOrder(jal);
+
+            for (int h = 0; h < reps.length; h++)
             {
-              jseq.addHiddenSequences(jal.findIndex(reps[h]));
+              if (reps[h] != jal.getSequenceAt(i))
+              {
+                jseq.addHiddenSequences(jal.findIndex(reps[h]));
+              }
             }
           }
         }
       }
 
-      if (jds.getDatasetSequence().getSequenceFeatures() != null)
+      if (jdatasq.getSequenceFeatures() != null)
       {
-        jalview.datamodel.SequenceFeature[] sf = jds.getDatasetSequence()
+        jalview.datamodel.SequenceFeature[] sf = jdatasq
                 .getSequenceFeatures();
         int index = 0;
         while (index < sf.length)
@@ -567,9 +634,9 @@ public class Jalview2XML
         }
       }
 
-      if (jds.getDatasetSequence().getPDBId() != null)
+      if (jdatasq.getPDBId() != null)
       {
-        Enumeration en = jds.getDatasetSequence().getPDBId().elements();
+        Enumeration en = jdatasq.getPDBId().elements();
         while (en.hasMoreElements())
         {
           Pdbids pdb = new Pdbids();
@@ -578,7 +645,10 @@ public class Jalview2XML
 
           pdb.setId(entry.getId());
           pdb.setType(entry.getType());
-
+          //
+          // store any JMol views associated with this seqeunce
+          // this section copes with duplicate entries in the project, so a
+          // dataset only view *should* be coped with sensibly
           AppJmol jmol;
           // This must have been loaded, is it still visible?
           JInternalFrame[] frames = Desktop.desktop.getAllFrames();
@@ -645,6 +715,7 @@ public class Jalview2XML
                     }
                     pdb.addStructureState(state);
                   }
+
                 }
               }
             }
@@ -713,7 +784,7 @@ public class Jalview2XML
       jms.addJSeq(jseq);
     }
 
-    if (av.hasHiddenRows())
+    if (!storeDS && av.hasHiddenRows())
     {
       jal = av.getAlignment();
     }
@@ -757,7 +828,7 @@ public class Jalview2XML
 
     // SAVE TREES
     // /////////////////////////////////
-    if (av.currentTree != null)
+    if (!storeDS && av.currentTree != null)
     {
       // FIND ANY ASSOCIATED TREES
       // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
@@ -804,139 +875,26 @@ public class Jalview2XML
      * store forward refs from an annotationRow to any groups
      */
     IdentityHashMap groupRefs = new IdentityHashMap();
-    if (jal.getAlignmentAnnotation() != null)
+    if (storeDS)
     {
-      jalview.datamodel.AlignmentAnnotation[] aa = jal
-              .getAlignmentAnnotation();
-
-      for (int i = 0; i < aa.length; i++)
-      {
-        Annotation an = new Annotation();
-
-        if (aa[i].annotationId != null)
+        for (SequenceI sq:jal.getSequences())
         {
-          annotationIds.put(aa[i].annotationId, aa[i]);
-        }
-
-        an.setId(aa[i].annotationId);
-
-        an.setVisible(aa[i].visible);
-
-        an.setDescription(aa[i].description);
-
-        if (aa[i].sequenceRef != null)
-        {
-          // TODO later annotation sequenceRef should be the XML ID of the
-          // sequence rather than its display name
-          an.setSequenceRef(aa[i].sequenceRef.getName());
-        }
-        if (aa[i].groupRef != null)
-        {
-          Object groupIdr = groupRefs.get(aa[i].groupRef);
-          if (groupIdr == null)
+       // Store annotation on dataset sequences only
+          jalview.datamodel.AlignmentAnnotation[] aa = sq.getAnnotation();
+          if (aa!=null && aa.length>0)
           {
-            // make a locally unique String
-            groupRefs.put(aa[i].groupRef,
-                    groupIdr = ("" + System.currentTimeMillis()
-                            + aa[i].groupRef.getName() + groupRefs.size()));
-          }
-          an.setGroupRef(groupIdr.toString());
-        }
-
-        // store all visualization attributes for annotation
-        an.setGraphHeight(aa[i].graphHeight);
-        an.setCentreColLabels(aa[i].centreColLabels);
-        an.setScaleColLabels(aa[i].scaleColLabel);
-        an.setShowAllColLabels(aa[i].showAllColLabels);
-        an.setBelowAlignment(aa[i].belowAlignment);
-
-        if (aa[i].graph > 0)
-        {
-          an.setGraph(true);
-          an.setGraphType(aa[i].graph);
-          an.setGraphGroup(aa[i].graphGroup);
-          if (aa[i].getThreshold() != null)
-          {
-            ThresholdLine line = new ThresholdLine();
-            line.setLabel(aa[i].getThreshold().label);
-            line.setValue(aa[i].getThreshold().value);
-            line.setColour(aa[i].getThreshold().colour.getRGB());
-            an.setThresholdLine(line);
-          }
-        }
-        else
-        {
-          an.setGraph(false);
-        }
-
-        an.setLabel(aa[i].label);
-
-        if (aa[i] == av.getAlignmentQualityAnnot()
-                || aa[i] == av.getAlignmentConservationAnnotation()
-                || aa[i] == av.getAlignmentConsensusAnnotation()
-                || aa[i].autoCalculated)
-        {
-          // new way of indicating autocalculated annotation -
-          an.setAutoCalculated(aa[i].autoCalculated);
-        }
-        if (aa[i].hasScore())
-        {
-          an.setScore(aa[i].getScore());
-        }
-
-        if (aa[i].getCalcId() != null)
-        {
-          calcIdSet.add(aa[i].getCalcId());
-          an.setCalcId(aa[i].getCalcId());
-        }
-
-        AnnotationElement ae;
-        if (aa[i].annotations != null)
-        {
-          an.setScoreOnly(false);
-          for (int a = 0; a < aa[i].annotations.length; a++)
-          {
-            if ((aa[i] == null) || (aa[i].annotations[a] == null))
-            {
-              continue;
-            }
-
-            ae = new AnnotationElement();
-            if (aa[i].annotations[a].description != null)
-              ae.setDescription(aa[i].annotations[a].description);
-            if (aa[i].annotations[a].displayCharacter != null)
-              ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
-
-            if (!Float.isNaN(aa[i].annotations[a].value))
-              ae.setValue(aa[i].annotations[a].value);
-
-            ae.setPosition(a);
-            if (aa[i].annotations[a].secondaryStructure != ' '
-                    && aa[i].annotations[a].secondaryStructure != '\0')
-              ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
-                      + "");
-
-            if (aa[i].annotations[a].colour != null
-                    && aa[i].annotations[a].colour != java.awt.Color.black)
-            {
-              ae.setColour(aa[i].annotations[a].colour.getRGB());
-            }
-
-            an.addAnnotationElement(ae);
-            if (aa[i].autoCalculated)
-            {
-              // only write one non-null entry into the annotation row -
-              // sufficient to get the visualization attributes necessary to
-              // display data
-              continue;
-            }
+            storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
+                    vamsasSet);
           }
         }
-        else
-        {
-          an.setScoreOnly(true);
-        }
-        vamsasSet.addAnnotation(an);
+    } else {
+      if (jal.getAlignmentAnnotation() != null)
+      {
+        // Store the annotation shown on the alignment.
+        jalview.datamodel.AlignmentAnnotation[] aa = jal
+                .getAlignmentAnnotation();
+        storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
+                vamsasSet);
       }
     }
     // SAVE GROUPS
@@ -1004,6 +962,7 @@ public class Jalview2XML
         groups[i].setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
         groups[i].setShowConsensusHistogram(sg.isShowConsensusHistogram());
         groups[i].setShowSequenceLogo(sg.isShowSequenceLogo());
+        groups[i].setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
         for (int s = 0; s < sg.getSize(); s++)
         {
           jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
@@ -1014,250 +973,255 @@ public class Jalview2XML
 
       jms.setJGroup(groups);
     }
+    if (!storeDS)
+    {
+      // /////////SAVE VIEWPORT
+      Viewport view = new Viewport();
+      view.setTitle(ap.alignFrame.getTitle());
+      view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
+              av.getSequenceSetId()));
+      view.setId(av.getViewId());
+      view.setViewName(av.viewName);
+      view.setGatheredViews(av.gatherViewsHere);
+
+      if (ap.av.explodedPosition != null)
+      {
+        view.setXpos(av.explodedPosition.x);
+        view.setYpos(av.explodedPosition.y);
+        view.setWidth(av.explodedPosition.width);
+        view.setHeight(av.explodedPosition.height);
+      }
+      else
+      {
+        view.setXpos(ap.alignFrame.getBounds().x);
+        view.setYpos(ap.alignFrame.getBounds().y);
+        view.setWidth(ap.alignFrame.getBounds().width);
+        view.setHeight(ap.alignFrame.getBounds().height);
+      }
 
-    // /////////SAVE VIEWPORT
-    Viewport view = new Viewport();
-    view.setTitle(ap.alignFrame.getTitle());
-    view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
-            av.getSequenceSetId()));
-    view.setId(av.getViewId());
-    view.setViewName(av.viewName);
-    view.setGatheredViews(av.gatherViewsHere);
-
-    if (ap.av.explodedPosition != null)
-    {
-      view.setXpos(av.explodedPosition.x);
-      view.setYpos(av.explodedPosition.y);
-      view.setWidth(av.explodedPosition.width);
-      view.setHeight(av.explodedPosition.height);
-    }
-    else
-    {
-      view.setXpos(ap.alignFrame.getBounds().x);
-      view.setYpos(ap.alignFrame.getBounds().y);
-      view.setWidth(ap.alignFrame.getBounds().width);
-      view.setHeight(ap.alignFrame.getBounds().height);
-    }
-
-    view.setStartRes(av.startRes);
-    view.setStartSeq(av.startSeq);
-
-    if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
-    {
-      view.setBgColour(SetUserColourScheme(av.getGlobalColourScheme(),
-              userColours, jms));
-    }
-    else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
-    {
-      jalview.schemes.AnnotationColourGradient acg = (jalview.schemes.AnnotationColourGradient) av
-              .getGlobalColourScheme();
+      view.setStartRes(av.startRes);
+      view.setStartSeq(av.startSeq);
 
-      AnnotationColours ac = new AnnotationColours();
-      ac.setAboveThreshold(acg.getAboveThreshold());
-      ac.setThreshold(acg.getAnnotationThreshold());
-      ac.setAnnotation(acg.getAnnotation());
-      if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
+      if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
       {
-        ac.setColourScheme(SetUserColourScheme(acg.getBaseColour(),
+        view.setBgColour(SetUserColourScheme(av.getGlobalColourScheme(),
                 userColours, jms));
       }
+      else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
+      {
+        jalview.schemes.AnnotationColourGradient acg = (jalview.schemes.AnnotationColourGradient) av
+                .getGlobalColourScheme();
+
+        AnnotationColours ac = new AnnotationColours();
+        ac.setAboveThreshold(acg.getAboveThreshold());
+        ac.setThreshold(acg.getAnnotationThreshold());
+        ac.setAnnotation(acg.getAnnotation());
+        if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
+        {
+          ac.setColourScheme(SetUserColourScheme(acg.getBaseColour(),
+                  userColours, jms));
+        }
+        else
+        {
+          ac.setColourScheme(ColourSchemeProperty.getColourName(acg
+                  .getBaseColour()));
+        }
+
+        ac.setMaxColour(acg.getMaxColour().getRGB());
+        ac.setMinColour(acg.getMinColour().getRGB());
+        ac.setPerSequence(acg.isSeqAssociated());
+        ac.setPredefinedColours(acg.isPredefinedColours());
+        view.setAnnotationColours(ac);
+        view.setBgColour("AnnotationColourGradient");
+      }
       else
       {
-        ac.setColourScheme(ColourSchemeProperty.getColourName(acg
-                .getBaseColour()));
+        view.setBgColour(ColourSchemeProperty.getColourName(av
+                .getGlobalColourScheme()));
       }
 
-      ac.setMaxColour(acg.getMaxColour().getRGB());
-      ac.setMinColour(acg.getMinColour().getRGB());
-      view.setAnnotationColours(ac);
-      view.setBgColour("AnnotationColourGradient");
-    }
-    else
-    {
-      view.setBgColour(ColourSchemeProperty.getColourName(av
-              .getGlobalColourScheme()));
-    }
-
-    ColourSchemeI cs = av.getGlobalColourScheme();
+      ColourSchemeI cs = av.getGlobalColourScheme();
 
-    if (cs != null)
-    {
-      if (cs.conservationApplied())
+      if (cs != null)
       {
-        view.setConsThreshold(cs.getConservationInc());
-        if (cs instanceof jalview.schemes.UserColourScheme)
+        if (cs.conservationApplied())
         {
-          view.setBgColour(SetUserColourScheme(cs, userColours, jms));
+          view.setConsThreshold(cs.getConservationInc());
+          if (cs instanceof jalview.schemes.UserColourScheme)
+          {
+            view.setBgColour(SetUserColourScheme(cs, userColours, jms));
+          }
         }
-      }
 
-      if (cs instanceof ResidueColourScheme)
-      {
-        view.setPidThreshold(cs.getThreshold());
+        if (cs instanceof ResidueColourScheme)
+        {
+          view.setPidThreshold(cs.getThreshold());
+        }
       }
-    }
 
-    view.setConservationSelected(av.getConservationSelected());
-    view.setPidSelected(av.getAbovePIDThreshold());
-    view.setFontName(av.font.getName());
-    view.setFontSize(av.font.getSize());
-    view.setFontStyle(av.font.getStyle());
-    view.setRenderGaps(av.renderGaps);
-    view.setShowAnnotation(av.getShowAnnotation());
-    view.setShowBoxes(av.getShowBoxes());
-    view.setShowColourText(av.getColourText());
-    view.setShowFullId(av.getShowJVSuffix());
-    view.setRightAlignIds(av.rightAlignIds);
-    view.setShowSequenceFeatures(av.showSequenceFeatures);
-    view.setShowText(av.getShowText());
-    view.setShowUnconserved(av.getShowUnconserved());
-    view.setWrapAlignment(av.getWrapAlignment());
-    view.setTextCol1(av.textColour.getRGB());
-    view.setTextCol2(av.textColour2.getRGB());
-    view.setTextColThreshold(av.thresholdTextColour);
-    view.setShowConsensusHistogram(av.isShowConsensusHistogram());
-    view.setShowSequenceLogo(av.isShowSequenceLogo());
-    view.setShowGroupConsensus(av.isShowGroupConsensus());
-    view.setShowGroupConservation(av.isShowGroupConservation());
-    view.setShowNPfeatureTooltip(av.isShowNpFeats());
-    view.setShowDbRefTooltip(av.isShowDbRefs());
-    view.setFollowHighlight(av.followHighlight);
-    view.setFollowSelection(av.followSelection);
-    view.setIgnoreGapsinConsensus(av.getIgnoreGapsConsensus());
-    if (av.featuresDisplayed != null)
-    {
-      jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
+      view.setConservationSelected(av.getConservationSelected());
+      view.setPidSelected(av.getAbovePIDThreshold());
+      view.setFontName(av.font.getName());
+      view.setFontSize(av.font.getSize());
+      view.setFontStyle(av.font.getStyle());
+      view.setRenderGaps(av.renderGaps);
+      view.setShowAnnotation(av.getShowAnnotation());
+      view.setShowBoxes(av.getShowBoxes());
+      view.setShowColourText(av.getColourText());
+      view.setShowFullId(av.getShowJVSuffix());
+      view.setRightAlignIds(av.rightAlignIds);
+      view.setShowSequenceFeatures(av.showSequenceFeatures);
+      view.setShowText(av.getShowText());
+      view.setShowUnconserved(av.getShowUnconserved());
+      view.setWrapAlignment(av.getWrapAlignment());
+      view.setTextCol1(av.textColour.getRGB());
+      view.setTextCol2(av.textColour2.getRGB());
+      view.setTextColThreshold(av.thresholdTextColour);
+      view.setShowConsensusHistogram(av.isShowConsensusHistogram());
+      view.setShowSequenceLogo(av.isShowSequenceLogo());
+      view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
+      view.setShowGroupConsensus(av.isShowGroupConsensus());
+      view.setShowGroupConservation(av.isShowGroupConservation());
+      view.setShowNPfeatureTooltip(av.isShowNpFeats());
+      view.setShowDbRefTooltip(av.isShowDbRefs());
+      view.setFollowHighlight(av.followHighlight);
+      view.setFollowSelection(av.followSelection);
+      view.setIgnoreGapsinConsensus(av.getIgnoreGapsConsensus());
+      if (av.featuresDisplayed != null)
+      {
+        jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
 
-      String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
+        String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
 
-      Vector settingsAdded = new Vector();
-      Object gstyle = null;
-      GraduatedColor gcol = null;
-      if (renderOrder != null)
-      {
-        for (int ro = 0; ro < renderOrder.length; ro++)
+        Vector settingsAdded = new Vector();
+        Object gstyle = null;
+        GraduatedColor gcol = null;
+        if (renderOrder != null)
         {
-          gstyle = ap.seqPanel.seqCanvas.getFeatureRenderer()
-                  .getFeatureStyle(renderOrder[ro]);
-          Setting setting = new Setting();
-          setting.setType(renderOrder[ro]);
-          if (gstyle instanceof GraduatedColor)
-          {
-            gcol = (GraduatedColor) gstyle;
-            setting.setColour(gcol.getMaxColor().getRGB());
-            setting.setMincolour(gcol.getMinColor().getRGB());
-            setting.setMin(gcol.getMin());
-            setting.setMax(gcol.getMax());
-            setting.setColourByLabel(gcol.isColourByLabel());
-            setting.setAutoScale(gcol.isAutoScale());
-            setting.setThreshold(gcol.getThresh());
-            setting.setThreshstate(gcol.getThreshType());
+          for (int ro = 0; ro < renderOrder.length; ro++)
+          {
+            gstyle = ap.seqPanel.seqCanvas.getFeatureRenderer()
+                    .getFeatureStyle(renderOrder[ro]);
+            Setting setting = new Setting();
+            setting.setType(renderOrder[ro]);
+            if (gstyle instanceof GraduatedColor)
+            {
+              gcol = (GraduatedColor) gstyle;
+              setting.setColour(gcol.getMaxColor().getRGB());
+              setting.setMincolour(gcol.getMinColor().getRGB());
+              setting.setMin(gcol.getMin());
+              setting.setMax(gcol.getMax());
+              setting.setColourByLabel(gcol.isColourByLabel());
+              setting.setAutoScale(gcol.isAutoScale());
+              setting.setThreshold(gcol.getThresh());
+              setting.setThreshstate(gcol.getThreshType());
+            }
+            else
+            {
+              setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
+                      .getColour(renderOrder[ro]).getRGB());
+            }
+
+            setting.setDisplay(av.featuresDisplayed
+                    .containsKey(renderOrder[ro]));
+            float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
+                    .getOrder(renderOrder[ro]);
+            if (rorder > -1)
+            {
+              setting.setOrder(rorder);
+            }
+            fs.addSetting(setting);
+            settingsAdded.addElement(renderOrder[ro]);
           }
-          else
+        }
+
+        // Make sure we save none displayed feature settings
+        Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
+                .keySet().iterator();
+        while (en.hasNext())
+        {
+          String key = en.next().toString();
+          if (settingsAdded.contains(key))
           {
-            setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
-                    .getColour(renderOrder[ro]).getRGB());
+            continue;
           }
 
-          setting.setDisplay(av.featuresDisplayed
-                  .containsKey(renderOrder[ro]));
+          Setting setting = new Setting();
+          setting.setType(key);
+          setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
+                  .getColour(key).getRGB());
+
+          setting.setDisplay(false);
           float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
-                  .getOrder(renderOrder[ro]);
+                  .getOrder(key);
           if (rorder > -1)
           {
             setting.setOrder(rorder);
           }
           fs.addSetting(setting);
-          settingsAdded.addElement(renderOrder[ro]);
+          settingsAdded.addElement(key);
         }
-      }
-
-      // Make sure we save none displayed feature settings
-      Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
-              .keySet().iterator();
-      while (en.hasNext())
-      {
-        String key = en.next().toString();
-        if (settingsAdded.contains(key))
+        en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups
+                .keySet().iterator();
+        Vector groupsAdded = new Vector();
+        while (en.hasNext())
         {
-          continue;
+          String grp = en.next().toString();
+          if (groupsAdded.contains(grp))
+          {
+            continue;
+          }
+          Group g = new Group();
+          g.setName(grp);
+          g.setDisplay(((Boolean) ap.seqPanel.seqCanvas
+                  .getFeatureRenderer().featureGroups.get(grp))
+                  .booleanValue());
+          fs.addGroup(g);
+          groupsAdded.addElement(grp);
         }
+        jms.setFeatureSettings(fs);
 
-        Setting setting = new Setting();
-        setting.setType(key);
-        setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
-                .getColour(key).getRGB());
-
-        setting.setDisplay(false);
-        float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer().getOrder(
-                key);
-        if (rorder > -1)
-        {
-          setting.setOrder(rorder);
-        }
-        fs.addSetting(setting);
-        settingsAdded.addElement(key);
       }
-      en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups
-              .keySet().iterator();
-      Vector groupsAdded = new Vector();
-      while (en.hasNext())
+
+      if (av.hasHiddenColumns())
       {
-        String grp = en.next().toString();
-        if (groupsAdded.contains(grp))
+        if (av.getColumnSelection() == null
+                || av.getColumnSelection().getHiddenColumns() == null)
         {
-          continue;
+          warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
         }
-        Group g = new Group();
-        g.setName(grp);
-        g.setDisplay(((Boolean) ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups
-                .get(grp)).booleanValue());
-        fs.addGroup(g);
-        groupsAdded.addElement(grp);
-      }
-      jms.setFeatureSettings(fs);
-
-    }
-
-    if (av.hasHiddenColumns())
-    {
-      if (av.getColumnSelection() == null
-              || av.getColumnSelection().getHiddenColumns() == null)
-      {
-        warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
-      }
-      else
-      {
-        for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
-                .size(); c++)
+        else
         {
-          int[] region = (int[]) av.getColumnSelection().getHiddenColumns()
-                  .elementAt(c);
-          HiddenColumns hc = new HiddenColumns();
-          hc.setStart(region[0]);
-          hc.setEnd(region[1]);
-          view.addHiddenColumns(hc);
+          for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
+                  .size(); c++)
+          {
+            int[] region = (int[]) av.getColumnSelection()
+                    .getHiddenColumns().elementAt(c);
+            HiddenColumns hc = new HiddenColumns();
+            hc.setStart(region[0]);
+            hc.setEnd(region[1]);
+            view.addHiddenColumns(hc);
+          }
         }
       }
-    }
-    if (calcIdSet.size() > 0)
-    {
-      for (String calcId : calcIdSet)
+      if (calcIdSet.size() > 0)
       {
-        if (calcId.trim().length() > 0)
+        for (String calcId : calcIdSet)
         {
-          CalcIdParam cidp = createCalcIdParam(calcId, av);
-          // Some calcIds have no parameters.
-          if (cidp != null)
+          if (calcId.trim().length() > 0)
           {
-            view.addCalcIdParam(cidp);
+            CalcIdParam cidp = createCalcIdParam(calcId, av);
+            // Some calcIds have no parameters.
+            if (cidp != null)
+            {
+              view.addCalcIdParam(cidp);
+            }
           }
         }
       }
-    }
-
-    jms.addViewport(view);
 
+      jms.addViewport(view);
+    }
     object.setJalviewModelSequence(jms);
     object.getVamsasModel().addSequenceSet(vamsasSet);
 
@@ -1286,6 +1250,145 @@ public class Jalview2XML
     return object;
   }
 
+  private void storeAlignmentAnnotation(AlignmentAnnotation[] aa, IdentityHashMap groupRefs, AlignmentViewport av, Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
+  {
+
+    for (int i = 0; i < aa.length; i++)
+    {
+      Annotation an = new Annotation();
+
+      if (aa[i].annotationId != null)
+      {
+        annotationIds.put(aa[i].annotationId, aa[i]);
+      }
+
+      an.setId(aa[i].annotationId);
+
+      an.setVisible(aa[i].visible);
+
+      an.setDescription(aa[i].description);
+
+      if (aa[i].sequenceRef != null)
+      {
+        // TODO later annotation sequenceRef should be the XML ID of the
+        // sequence rather than its display name
+        an.setSequenceRef(aa[i].sequenceRef.getName());
+      }
+      if (aa[i].groupRef != null)
+      {
+        Object groupIdr = groupRefs.get(aa[i].groupRef);
+        if (groupIdr == null)
+        {
+          // make a locally unique String
+          groupRefs.put(aa[i].groupRef,
+                  groupIdr = ("" + System.currentTimeMillis()
+                          + aa[i].groupRef.getName() + groupRefs.size()));
+        }
+        an.setGroupRef(groupIdr.toString());
+      }
+
+      // store all visualization attributes for annotation
+      an.setGraphHeight(aa[i].graphHeight);
+      an.setCentreColLabels(aa[i].centreColLabels);
+      an.setScaleColLabels(aa[i].scaleColLabel);
+      an.setShowAllColLabels(aa[i].showAllColLabels);
+      an.setBelowAlignment(aa[i].belowAlignment);
+
+      if (aa[i].graph > 0)
+      {
+        an.setGraph(true);
+        an.setGraphType(aa[i].graph);
+        an.setGraphGroup(aa[i].graphGroup);
+        if (aa[i].getThreshold() != null)
+        {
+          ThresholdLine line = new ThresholdLine();
+          line.setLabel(aa[i].getThreshold().label);
+          line.setValue(aa[i].getThreshold().value);
+          line.setColour(aa[i].getThreshold().colour.getRGB());
+          an.setThresholdLine(line);
+        }
+      }
+      else
+      {
+        an.setGraph(false);
+      }
+
+      an.setLabel(aa[i].label);
+
+      if (aa[i] == av.getAlignmentQualityAnnot()
+              || aa[i] == av.getAlignmentConservationAnnotation()
+              || aa[i] == av.getAlignmentConsensusAnnotation()
+              || aa[i].autoCalculated)
+      {
+        // new way of indicating autocalculated annotation -
+        an.setAutoCalculated(aa[i].autoCalculated);
+      }
+      if (aa[i].hasScore())
+      {
+        an.setScore(aa[i].getScore());
+      }
+
+      if (aa[i].getCalcId() != null)
+      {
+        calcIdSet.add(aa[i].getCalcId());
+        an.setCalcId(aa[i].getCalcId());
+      }
+
+      AnnotationElement ae;
+      if (aa[i].annotations != null)
+      {
+        an.setScoreOnly(false);
+        for (int a = 0; a < aa[i].annotations.length; a++)
+        {
+          if ((aa[i] == null) || (aa[i].annotations[a] == null))
+          {
+            continue;
+          }
+
+          ae = new AnnotationElement();
+          if (aa[i].annotations[a].description != null)
+            ae.setDescription(aa[i].annotations[a].description);
+          if (aa[i].annotations[a].displayCharacter != null)
+            ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
+
+          if (!Float.isNaN(aa[i].annotations[a].value))
+            ae.setValue(aa[i].annotations[a].value);
+
+          ae.setPosition(a);
+          if (aa[i].annotations[a].secondaryStructure != ' '
+                  && aa[i].annotations[a].secondaryStructure != '\0')
+            ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
+                    + "");
+
+          if (aa[i].annotations[a].colour != null
+                  && aa[i].annotations[a].colour != java.awt.Color.black)
+          {
+            ae.setColour(aa[i].annotations[a].colour.getRGB());
+          }
+
+          an.addAnnotationElement(ae);
+          if (aa[i].autoCalculated)
+          {
+            // only write one non-null entry into the annotation row -
+            // sufficient to get the visualization attributes necessary to
+            // display data
+            continue;
+          }
+        }
+      }
+      else
+      {
+        an.setScoreOnly(true);
+      }
+      if (!storeDS || (storeDS && !aa[i].autoCalculated))
+      {
+        // skip autocalculated annotation - these are only provided for alignments
+        vamsasSet.addAnnotation(an);
+      }
+    }
+    
+  }
+
   private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
   {
     AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
@@ -1354,7 +1457,7 @@ public class Jalview2XML
                   .getPreset(calcIdParam.getName());
           if (parmSet != null)
           {
-            // TODO : check we have a good match with settings in AACons -
+            // TODO : check we have a good match with settings in AACon -
             // otherwise we'll need to create a new preset
           }
         }
@@ -1363,7 +1466,7 @@ public class Jalview2XML
           argList = parmSet.getArguments();
           parmSet = null;
         }
-        AAConsSettings settings = new AAConsSettings(
+        AAConSettings settings = new AAConSettings(
                 calcIdParam.isAutoUpdate(), service, parmSet, argList);
         av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
                 calcIdParam.isNeedsUpdate());
@@ -1668,6 +1771,8 @@ public class Jalview2XML
 
     try
     {
+      // create list to store references for any new Jmol viewers created
+      newStructureViewers=new Vector<AppJmol>();
       // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
       // Workaround is to make sure caller implements the JarInputStreamProvider
       // interface
@@ -1675,11 +1780,27 @@ public class Jalview2XML
 
       jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
       af = LoadJalviewAlign(jprovider);
+      
     } catch (MalformedURLException e)
     {
       errorMessage = "Invalid URL format for '" + file + "'";
       reportErrors();
     }
+    finally {
+      try
+      {
+        SwingUtilities.invokeAndWait(new Runnable()
+        {
+          public void run()
+          {
+            setLoadingFinishedForNewStructureViewers();
+          };
+        });
+      } catch (Exception x)
+      {
+
+      }
+    }
     return af;
   }
 
@@ -1751,7 +1872,7 @@ public class Jalview2XML
       frefedSequence = new Vector();
     }
 
-    jalview.gui.AlignFrame af = null;
+    jalview.gui.AlignFrame af= null,_af = null;
     Hashtable gatherToThisFrame = new Hashtable();
     final String file = jprovider.getFilename();
     try
@@ -1778,10 +1899,15 @@ public class Jalview2XML
           object = (JalviewModel) unmar.unmarshal(in);
           if (true) // !skipViewport(object))
           {
-            af = LoadFromObject(object, file, true, jprovider);
-            if (af.viewport.gatherViewsHere)
+            _af = LoadFromObject(object, file, true, jprovider);
+            if (object.getJalviewModelSequence().getViewportCount() > 0)
             {
-              gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
+              af = _af;
+              if (object.getJalviewModelSequence().getViewportCount() > 1
+                      && af.viewport.gatherViewsHere)
+              {
+                gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
+              }
             }
           }
           entryCount++;
@@ -2004,7 +2130,8 @@ public class Jalview2XML
 
     JalviewModelSequence jms = object.getJalviewModelSequence();
 
-    Viewport view = jms.getViewport(0);
+    Viewport view = (jms.getViewportCount()>0) ? jms.getViewport(0) : null;
+    
     // ////////////////////////////////
     // LOAD SEQUENCES
 
@@ -2267,16 +2394,19 @@ public class Jalview2XML
         // Construct new annotation from model.
         AnnotationElement[] ae = an[i].getAnnotationElement();
         jalview.datamodel.Annotation[] anot = null;
-
+        java.awt.Color firstColour = null;
+        int anpos;
         if (!an[i].getScoreOnly())
         {
           anot = new jalview.datamodel.Annotation[al.getWidth()];
           for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
           {
-            if (ae[aa].getPosition() >= anot.length)
+            anpos = ae[aa].getPosition();
+
+            if (anpos >= anot.length)
               continue;
 
-            anot[ae[aa].getPosition()] = new jalview.datamodel.Annotation(
+            anot[anpos] = new jalview.datamodel.Annotation(
 
             ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
                     (ae[aa].getSecondaryStructure() == null || ae[aa]
@@ -2292,8 +2422,11 @@ public class Jalview2XML
             // {
             // anot[ae[aa].getPosition()].displayCharacter = "";
             // }
-            anot[ae[aa].getPosition()].colour = new java.awt.Color(
-                    ae[aa].getColour());
+            anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
+            if (firstColour == null)
+            {
+              firstColour = anot[anpos].colour;
+            }
           }
         }
         jalview.datamodel.AlignmentAnnotation jaa = null;
@@ -2309,7 +2442,7 @@ public class Jalview2XML
                   an[i].getGraphType());
 
           jaa.graphGroup = an[i].getGraphGroup();
-
+          jaa._linecolour = firstColour;
           if (an[i].getThresholdLine() != null)
           {
             jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
@@ -2329,6 +2462,7 @@ public class Jalview2XML
         {
           jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
                   an[i].getDescription(), anot);
+          jaa._linecolour = firstColour;
         }
         // register new annotation
         if (an[i].getId() != null)
@@ -2472,6 +2606,10 @@ public class Jalview2XML
         {
           sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
         }
+        if (groups[i].hasNormaliseSequenceLogo())
+        {
+          sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
+        }
         if (groups[i].hasIgnoreGapsinConsensus())
         {
           sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
@@ -2518,7 +2656,11 @@ public class Jalview2XML
 
       }
     }
-
+    if (view==null)
+    {
+      // only dataset in this model, so just return.
+      return null;
+    }
     // ///////////////////////////////
     // LOAD VIEWPORT
 
@@ -2956,6 +3098,7 @@ public class Jalview2XML
                       sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
                               useinJmolsuperpos, usetoColourbyseq,
                               jmolColouring, fileloc, rect, vid);
+                      addNewStructureViewer(sview);
                     } catch (OutOfMemoryError ex)
                     {
                       new OOMWarning("restoring structure view for PDB id "
@@ -3025,6 +3168,27 @@ public class Jalview2XML
     // and finally return.
     return af;
   }
+  Vector<AppJmol> newStructureViewers=null;
+  protected void addNewStructureViewer(AppJmol sview)
+  {
+    if (newStructureViewers!=null)
+    {
+      sview.jmb.setFinishedLoadingFromArchive(false);
+      newStructureViewers.add(sview);
+    }
+  }
+  protected void setLoadingFinishedForNewStructureViewers()
+  {
+    if (newStructureViewers!=null)
+    {
+      for (AppJmol sview:newStructureViewers)
+      {
+        sview.jmb.setFinishedLoadingFromArchive(true);
+      }
+      newStructureViewers.clear();
+      newStructureViewers=null;
+    }
+  }
 
   AlignFrame loadViewport(String file, JSeq[] JSEQ, Vector hiddenSeqs,
           Alignment al, JalviewModelSequence jms, Viewport view,
@@ -3186,7 +3350,14 @@ public class Jalview2XML
                                 .getAnnotationColours().getColourScheme()),
                         view.getAnnotationColours().getAboveThreshold());
               }
-
+              if (view.getAnnotationColours().hasPerSequence())
+              {
+                ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
+              }
+              if (view.getAnnotationColours().hasPredefinedColours())
+              {
+                ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
+              }
               // Also use these settings for all the groups
               if (al.getGroups() != null)
               {
@@ -3216,6 +3387,17 @@ public class Jalview2XML
                             .getAlignment().getAlignmentAnnotation()[i],
                             sg.cs, view.getAnnotationColours()
                                     .getAboveThreshold());
+                    if (cs instanceof AnnotationColourGradient) 
+                    {
+                      if (view.getAnnotationColours().hasPerSequence())
+                      { 
+                        ((AnnotationColourGradient)cs).setSeqAssociated(view.getAnnotationColours().isPerSequence());
+                      }
+                      if (view.getAnnotationColours().hasPredefinedColours())
+                      {
+                        ((AnnotationColourGradient)cs).setPredefinedColours(view.getAnnotationColours().isPredefinedColours());
+                      }
+                    }
                   }
 
                 }
@@ -3289,6 +3471,10 @@ public class Jalview2XML
     {
       af.viewport.setShowSequenceLogo(false);
     }
+    if (view.hasNormaliseSequenceLogo())
+    {
+      af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
+    }
     if (view.hasShowDbRefTooltip())
     {
       af.viewport.setShowDbRefs(view.getShowDbRefTooltip());
@@ -3409,8 +3595,9 @@ public class Jalview2XML
     // TODO: we don't need to do this if the viewport is aready visible.
     Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
             view.getHeight());
-    af.alignPanel.updateAnnotation(false); // recompute any autoannotation
+    af.alignPanel.updateAnnotation(false, true); // recompute any autoannotation
     reorderAutoannotation(af, al, autoAlan);
+    af.alignPanel.alignmentChanged();
     return af;
   }
 
@@ -3517,7 +3704,7 @@ public class Jalview2XML
 
   /**
    * TODO remove this method
-   *
+   * 
    * @param view
    * @return AlignFrame bound to sequenceSetId from view, if one exists. private
    *         AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
@@ -3528,7 +3715,7 @@ public class Jalview2XML
 
   /**
    * Check if the Jalview view contained in object should be skipped or not.
-   *
+   * 
    * @param object
    * @return true if view's sequenceSetId is a key in skipList
    */
@@ -3601,7 +3788,7 @@ public class Jalview2XML
   }
 
   /**
-   *
+   * 
    * @param vamsasSeq
    *          sequence definition to create/merge dataset sequence for
    * @param ds
@@ -3659,6 +3846,20 @@ public class Jalview2XML
         if (sq != dsq)
         { // make this dataset sequence sq's dataset sequence
           sq.setDatasetSequence(dsq);
+          // and update the current dataset alignment
+          if (ds==null) {
+            if (dseqs!=null) {
+              if (!dseqs.contains(dsq))
+              {
+                dseqs.add(dsq);
+              }
+            } else {
+              if (ds.findIndex(dsq)<0)
+              {
+                ds.addSequence(dsq);
+              }
+            }
+          }
         }
       }
     }
@@ -3685,11 +3886,11 @@ public class Jalview2XML
            * sb.append(newres.substring(newres.length() - sq.getEnd() -
            * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
            */
-          dsq.setSequence(sb.toString());
+          dsq.setSequence(newres);
         }
         // TODO: merges will never happen if we 'know' we have the real dataset
         // sequence - this should be detected when id==dssid
-        System.err.println("DEBUG Notice:  Merged dataset sequence"); // ("
+        System.err.println("DEBUG Notice:  Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
         // + (pre ? "prepended" : "") + " "
         // + (post ? "appended" : ""));
       }
@@ -3725,7 +3926,7 @@ public class Jalview2XML
 
   /**
    * make a new dataset ID for this jalview dataset alignment
-   *
+   * 
    * @param dataset
    * @return
    */
@@ -3912,7 +4113,7 @@ public class Jalview2XML
 
   /*
    * (non-Javadoc)
-   *
+   * 
    * @see java.lang.Object#finalize()
    */
   @Override
@@ -3990,13 +4191,13 @@ public class Jalview2XML
    * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
    * object goes out of scope. - also populates the datasetIds hashtable with
    * alignment objects containing dataset sequences
-   *
+   * 
    * @param vobj2jv
    *          Map from ID strings to jalview datamodel
    * @param jv2vobj
    *          Map from jalview datamodel to ID strings
-   *
-   *
+   * 
+   * 
    */
   public void setObjectMappingTables(Hashtable vobj2jv,
           IdentityHashMap jv2vobj)
@@ -4068,7 +4269,7 @@ public class Jalview2XML
    * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
    * objects created from the project archive. If string is null (default for
    * construction) then suffix will be set automatically.
-   *
+   * 
    * @param string
    */
   public void setUniqueSetSuffix(String string)
@@ -4080,7 +4281,7 @@ public class Jalview2XML
   /**
    * uses skipList2 as the skipList for skipping views on sequence sets
    * associated with keys in the skipList
-   *
+   * 
    * @param skipList2
    */
   public void setSkipList(Hashtable skipList2)